Skip to content

Commit bb066fe

Browse files
committed
add integration tests
1 parent 6460eb5 commit bb066fe

File tree

6 files changed

+158
-19
lines changed

6 files changed

+158
-19
lines changed

lint.js

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -83,24 +83,28 @@ const command = async (specFile, cmd) => {
8383
buildLoaderOptions(jsonSchema, verbose),
8484
);
8585

86-
validator.validate(spec, buildValidatorOptions(skip, verbose), (err, _options) => {
87-
const { context, warnings } = _options || err.options;
88-
if (err && err.options.valid === false) {
89-
console.error(colors.red + 'Specification schema is invalid.' + colors.reset);
90-
console.error(formatSchemaError(err, context));
91-
process.exit(1);
92-
}
93-
94-
if (warnings.length) {
95-
console.error(colors.red + 'Specification contains lint errors: ' + warnings.length + colors.reset);
96-
console.warn(formatLintResults(warnings))
97-
process.exit(1);
98-
}
99-
100-
if (!cmd.quiet) {
101-
console.log(colors.green + 'Specification is valid, with 0 lint errors' + colors.reset)
102-
}
103-
process.exit(0);
86+
return new Promise((resolve, reject) => {
87+
validator.validate(spec, buildValidatorOptions(skip, verbose), (err, _options) => {
88+
const { context, warnings, valid } = _options || err.options;
89+
90+
if (err && valid === false) {
91+
console.error(colors.red + 'Specification schema is invalid.' + colors.reset);
92+
console.error(formatSchemaError(err, context));
93+
return reject();
94+
}
95+
96+
if (warnings.length) {
97+
console.error(colors.red + 'Specification contains lint errors: ' + warnings.length + colors.reset);
98+
console.warn(formatLintResults(warnings))
99+
return reject();
100+
}
101+
102+
if (!cmd.quiet) {
103+
console.log(colors.green + 'Specification is valid, with 0 lint errors' + colors.reset)
104+
}
105+
106+
return resolve();
107+
});
104108
});
105109
};
106110

speccy.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,11 @@ program
2828
.option('-s, --skip [ruleName]', 'provide multiple rules to skip', collect, [])
2929
.option('-j, --json-schema', 'treat $ref like JSON Schema and convert to OpenAPI Schema Objects (default: false)')
3030
.option('-v, --verbose', 'increase verbosity')
31-
.action(lint.command);
31+
.action((specFile, cmd) => {
32+
lint.command(specFile, cmd)
33+
.then( () => { process.exit(0) } )
34+
.catch( () => { process.exit(1) } );
35+
});
3236

3337
program
3438
.command('resolve <file-or-url>')
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
openapi: 3.0.0
3+
info:
4+
contact:
5+
namex: Derp
6+
7+
version: 1.0.0
8+
title: Swagger 2.0 Without Scheme
9+
paths: {}
10+
tags:
11+
- name: Gym
12+
- name: Pokemon
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
openapi: 3.0.0
3+
info:
4+
version: 1.0.0
5+
title: Swagger 2.0 Without Scheme
6+
paths: {}
7+
tags:
8+
- name: Gym
9+
- name: Pokemon
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
openapi: 3.0.0
2+
servers:
3+
- url: 'http://petstore.swagger.io/v2'
4+
info:
5+
description: >-
6+
This is a sample server Petstore server. You can find out more about
7+
Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net,
8+
#swagger](http://swagger.io/irc/). For this sample, you can use the api key
9+
`special-key` to test the authorization filters.
10+
version: 1.0.0
11+
title: Swagger Petstore
12+
termsOfService: 'http://swagger.io/terms/'
13+
contact:
14+
15+
license:
16+
name: Apache 2.0
17+
url: 'http://www.apache.org/licenses/LICENSE-2.0.html'
18+
paths:
19+
/pet:
20+
post:
21+
tags:
22+
- pet
23+
summary: Add a new pet to the store
24+
description: ''
25+
operationId: addPet
26+
responses:
27+
'405':
28+
description: Invalid input
29+
security:
30+
- petstore_auth:
31+
- 'write:pets'
32+
- 'read:pets'
33+
requestBody:
34+
$ref: '#/components/requestBodies/Pet'

test/integration/lint.test.js

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
'use strict';
2+
3+
const lint = require('../../lint.js');
4+
5+
const commandConfig = {
6+
quiet: false,
7+
rules: [],
8+
skip: []
9+
};
10+
11+
beforeEach(() => {
12+
jest.resetAllMocks();
13+
});
14+
15+
describe('Lint command', () => {
16+
describe('properly handles scheme validation', () => {
17+
test('succesfully validates a valid spec', () => {
18+
expect.assertions(4);
19+
const logSpy = jest.spyOn(console, 'log');
20+
const warnSpy = jest.spyOn(console, 'warn');
21+
const errorSpy = jest.spyOn(console, 'error');
22+
23+
return lint.command('./test/fixtures/loader/openapi.yaml', commandConfig).then(() => {
24+
expect(logSpy).toBeCalledTimes(1);
25+
expect(logSpy.mock.calls[0][0]).toEqual('\x1b[32mSpecification is valid, with 0 lint errors\x1b[0m');
26+
expect(warnSpy).toBeCalledTimes(0);
27+
expect(errorSpy).toBeCalledTimes(0);
28+
});
29+
});
30+
31+
test('displays a validation error on invalid key', () => {
32+
expect.assertions(4);
33+
const logSpy = jest.spyOn(console, 'log');
34+
const warnSpy = jest.spyOn(console, 'warn');
35+
const errorSpy = jest.spyOn(console, 'error');
36+
37+
return lint.command('./test/fixtures/integration/invalid-key.yaml', commandConfig).catch(() => {
38+
expect(logSpy).toBeCalledTimes(0);
39+
expect(warnSpy).toBeCalledTimes(0);
40+
expect(errorSpy).toBeCalledTimes(2);
41+
expect(errorSpy).toHaveBeenCalledWith('\x1b[31mSpecification schema is invalid.\x1b[0m');
42+
});
43+
});
44+
45+
test('displays a validation error on missing reference', () => {
46+
expect.assertions(4);
47+
const logSpy = jest.spyOn(console, 'log');
48+
const warnSpy = jest.spyOn(console, 'warn');
49+
const errorSpy = jest.spyOn(console, 'error');
50+
51+
return lint.command('./test/fixtures/integration/missing-ref.yaml', commandConfig).catch(() => {
52+
expect(logSpy).toBeCalledTimes(0);
53+
expect(warnSpy).toBeCalledTimes(0);
54+
expect(errorSpy).toBeCalledTimes(2);
55+
expect(errorSpy).toHaveBeenCalledWith('\x1b[31mSpecification schema is invalid.\x1b[0m');
56+
});
57+
});
58+
});
59+
60+
describe('properly handles linter warnings', () => {
61+
test('displays a linting error on missing contact field', () => {
62+
expect.assertions(5);
63+
const logSpy = jest.spyOn(console, 'log');
64+
const warnSpy = jest.spyOn(console, 'warn');
65+
const errorSpy = jest.spyOn(console, 'error');
66+
67+
return lint.command('./test/fixtures/integration/missing-contact.yaml', commandConfig).catch(() => {
68+
expect(logSpy).toBeCalledTimes(0);
69+
expect(warnSpy).toBeCalledTimes(1);
70+
expect(errorSpy).toBeCalledTimes(1);
71+
expect(errorSpy.mock.calls[0][0]).toEqual('\x1b[31mSpecification contains lint errors: 1\x1b[0m');
72+
expect(warnSpy.mock.calls[0][0]).toContain('info-contact');
73+
});
74+
});
75+
});
76+
});

0 commit comments

Comments
 (0)