Skip to content

Commit 66e241b

Browse files
authored
fix(cli): JUnit formatter respects fail-severity (#1375)
* fix(cli): list format choices * fix(cli): junit respects fail-severity
1 parent 28ecf19 commit 66e241b

37 files changed

+113
-51
lines changed

docs/guides/2-cli.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,14 @@ Other options include:
2424
--version Show version number [boolean]
2525
--help Show help [boolean]
2626
--encoding, -e text encoding to use [string] [default: "utf8"]
27-
--format, -f formatter to use for outputting results [string] [default: "stylish"]
27+
--format, -f formatter to use for outputting results
28+
[string] [choices: "json", "stylish", "junit", "html", "text", "teamcity"] [default: "stylish"]
2829
--output, -o output to a file instead of stdout [string]
2930
--resolver path to custom json-ref-resolver instance [string]
3031
--ruleset, -r path/URL to a ruleset file [string]
3132
--skip-rule, -s ignore certain rules if they are causing trouble [string]
3233
--fail-severity, -F results of this level or above will trigger a failure exit code
33-
[string] [choices: "error", "warn", "info", "hint"] [default: "warn"]
34+
[string] [choices: "error", "warn", "info", "hint"] [default: "error"]
3435
--display-only-failures, -D only output results equal to or greater than --fail-severity
3536
[boolean] [default: false]
3637
--ignore-unknown-format do not warn about unmatched formats [boolean] [default: false]

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,10 @@
4343
"inline-version": "node ./scripts/inline-version.js",
4444
"prelint": "tsc --noEmit",
4545
"lint.fix": "yarn lint.prettier --write && yarn lint.eslint --fix",
46-
"lint.eslint":" eslint --cache --cache-location .cache/ --ext=.js,.ts src test-harness",
46+
"lint.eslint": "eslint --cache --cache-location .cache/ --ext=.js,.ts src test-harness",
4747
"lint.prettier": "prettier --ignore-path .eslintignore --check {src,test-harness}/**/*.{json,yaml} docs/**/*.md README.md",
4848
"lint": "yarn lint.prettier && yarn lint.eslint",
49-
"copy.html-templates": "copyfiles -u 1 \"./src/formatters/html/*.html\" \"./dist/\"",
49+
"copy.html-templates": "copyfiles -u 1 \"./src/cli/formatters/html/*.html\" \"./dist/\"",
5050
"postbuild.functions": "copyfiles -u 1 \"dist/rulesets/{oas,asyncapi}/functions/*.js\" ./",
5151
"postbuild": "yarn build.functions && yarn generate-assets",
5252
"prebuild": "yarn build.clean && copyfiles -u 1 \"src/rulesets/{oas,asyncapi}/**/*.json\" dist && copyfiles -u 1 \"src/rulesets/{oas,asyncapi}/**/*.json\" ./ && yarn copy.html-templates",

src/cli/commands/__tests__/lint.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as yargs from 'yargs';
22

3-
import { DiagnosticSeverity } from '@stoplight/types/dist';
3+
import { DiagnosticSeverity } from '@stoplight/types';
44
import { IRuleResult } from '../../../types';
55
import { lint } from '../../services/linter';
66
import { formatOutput, writeOutput } from '../../services/output';
@@ -150,7 +150,7 @@ describe('lint', () => {
150150
// needed by Node 8 (different ticking?) - can be simplified once we drop support for version 8
151151
await new Promise(resolve => {
152152
setImmediate(() => {
153-
expect(formatOutput).toBeCalledWith(results, format);
153+
expect(formatOutput).toBeCalledWith(results, format, { failSeverity: DiagnosticSeverity.Error });
154154
resolve();
155155
});
156156
});

src/cli/commands/lint.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ const lintCommand: CommandModule = {
6262
format: {
6363
alias: 'f',
6464
description: 'formatter to use for outputting results',
65-
options: formatOptions,
65+
choices: formatOptions,
6666
default: OutputFormat.STYLISH,
6767
type: 'string',
6868
},
@@ -161,7 +161,7 @@ const lintCommand: CommandModule = {
161161
} else if (!config.quiet) {
162162
console.log(`No results with a severity of '${failSeverity}' or higher found!`);
163163
}
164-
const formattedOutput = formatOutput(results, format);
164+
const formattedOutput = formatOutput(results, format, { failSeverity: getDiagnosticSeverity(failSeverity) });
165165
return writeOutput(formattedOutput, output);
166166
})
167167
.catch(fail);

src/formatters/__tests__/html.test.ts renamed to src/cli/formatters/__tests__/html.test.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1+
import { DiagnosticSeverity } from '@stoplight/types';
12
import { HTMLElement, parse } from 'node-html-parser';
2-
import { sortResults } from '../../utils';
3+
import { sortResults } from '../../../utils';
34
import { html } from '../html';
45

56
const mixedErrors = sortResults(require('./__fixtures__/mixed-errors.json'));
67

78
describe('HTML formatter', () => {
89
test('should display proper severity levels', () => {
9-
const result = parse(html(mixedErrors)) as HTMLElement;
10+
const result = parse(html(mixedErrors, { failSeverity: DiagnosticSeverity.Error })) as HTMLElement;
1011
const table = result.querySelector('table tbody');
1112
expect(table.innerHTML.trim()).toEqual(`<tr class="bg-error" data-group="f-0">
1213
<th colspan="4">

src/formatters/__tests__/json.test.ts renamed to src/cli/formatters/__tests__/json.test.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import { IRuleResult } from '../../types';
2-
import { sortResults } from '../../utils';
1+
import { DiagnosticSeverity } from '@stoplight/types';
2+
import { IRuleResult } from '../../../types';
3+
import { sortResults } from '../../../utils';
34
import { json } from '../json';
45

56
const results: IRuleResult[] = sortResults([
@@ -41,7 +42,7 @@ const results: IRuleResult[] = sortResults([
4142

4243
describe('JSON formatter', () => {
4344
test('should include ranges', () => {
44-
expect(JSON.parse(json(results))).toEqual([
45+
expect(JSON.parse(json(results, { failSeverity: DiagnosticSeverity.Error }))).toEqual([
4546
expect.objectContaining({
4647
range: {
4748
start: {
@@ -70,7 +71,7 @@ describe('JSON formatter', () => {
7071
});
7172

7273
test('should include message', () => {
73-
expect(JSON.parse(json(results))).toEqual([
74+
expect(JSON.parse(json(results, { failSeverity: DiagnosticSeverity.Error }))).toEqual([
7475
expect.objectContaining({
7576
message: 'paths./pets.get.description is not truthy',
7677
}),

src/formatters/__tests__/junit.test.ts renamed to src/cli/formatters/__tests__/junit.test.ts

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Parser } from 'xml2js';
2-
import { sortResults } from '../../utils';
2+
import { sortResults } from '../../../utils';
33
import { junit } from '../junit';
4+
import { DiagnosticSeverity } from '@stoplight/types';
45

56
const oas3SchemaErrors = sortResults(require('./__fixtures__/oas3-schema-errors.json'));
67
const mixedErrors = sortResults(require('./__fixtures__/mixed-errors.json'));
@@ -14,7 +15,7 @@ describe('JUnit formatter', () => {
1415
});
1516

1617
test('should produce valid report', async () => {
17-
const result = await parse(junit(oas3SchemaErrors));
18+
const result = await parse(junit(oas3SchemaErrors, { failSeverity: DiagnosticSeverity.Error }));
1819
expect(result).toEqual({
1920
testsuites: {
2021
testsuite: [
@@ -83,8 +84,8 @@ describe('JUnit formatter', () => {
8384
});
8485
});
8586

86-
test('should filter out non-error validation results', async () => {
87-
const result = await parse(junit(mixedErrors));
87+
test('given failSeverity set to error, should filter out non-error validation results', async () => {
88+
const result = await parse(junit(mixedErrors, { failSeverity: DiagnosticSeverity.Error }));
8889
expect(result).toEqual({
8990
testsuites: {
9091
testsuite: [
@@ -119,4 +120,57 @@ describe('JUnit formatter', () => {
119120
},
120121
});
121122
});
123+
124+
test('given failSeverity set to other value than error, should filter treat all validation results matching the severity as errors', async () => {
125+
const result = await parse(junit(mixedErrors, { failSeverity: DiagnosticSeverity.Warning }));
126+
expect(result).toEqual({
127+
testsuites: {
128+
testsuite: [
129+
{
130+
$: {
131+
errors: '0',
132+
failures: '2',
133+
name: '/home/Stoplight/spectral/src/__tests__/__fixtures__/petstore.oas3.json',
134+
package: 'org.spectral',
135+
tests: '2',
136+
time: '0',
137+
},
138+
testcase: [
139+
{
140+
$: {
141+
classname: '/home/Stoplight/spectral/src/__tests__/__fixtures__/petstore.oas3',
142+
name: 'org.spectral.info-description',
143+
time: '0',
144+
},
145+
failure: [
146+
{
147+
$: {
148+
message: 'OpenAPI object info `description` must be present and non-empty string.',
149+
},
150+
_:
151+
'line 3, col 10, OpenAPI object info `description` must be present and non-empty string. (info-description) at path #/info',
152+
},
153+
],
154+
},
155+
{
156+
$: {
157+
classname: '/home/Stoplight/spectral/src/__tests__/__fixtures__/petstore.oas3',
158+
name: 'org.spectral.info-matches-stoplight',
159+
time: '0',
160+
},
161+
failure: [
162+
{
163+
$: {
164+
message: 'Info must contain Stoplight',
165+
},
166+
_: 'line 5, col 14, Info must contain Stoplight (info-matches-stoplight) at path #/info/title',
167+
},
168+
],
169+
},
170+
],
171+
},
172+
],
173+
},
174+
});
175+
});
122176
});

0 commit comments

Comments
 (0)