Skip to content

Commit

Permalink
fix: improve error source detection (#685)
Browse files Browse the repository at this point in the history
* fix: consume graph data in doesBelongToSourceDoc

* fix: write detection from scratch

* refactor: flatten parsedMap structure

* fix: normalize source

* chore: bump @stoplight/json and use utils

* build: rollup config
  • Loading branch information
P0lip committed Dec 10, 2019
1 parent 93b173e commit 4d14fa0
Show file tree
Hide file tree
Showing 17 changed files with 492 additions and 133 deletions.
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -59,7 +59,7 @@
"test": "jest --silent"
},
"dependencies": {
"@stoplight/json": "^3.3.0",
"@stoplight/json": "^3.4.0",
"@stoplight/json-ref-readers": "^1.1.1",
"@stoplight/json-ref-resolver": "^3.0.1",
"@stoplight/path": "^1.3.0",
Expand Down
7 changes: 6 additions & 1 deletion rollup.config.js
Expand Up @@ -28,7 +28,12 @@ module.exports = functions.map(fn => ({
include: ['dist/**/*.{ts,tsx}'],
}),
resolve(),
commonjs(),
commonjs({
namedExports: {
'node_modules/lodash/lodash.js': ['isObject', 'trimStart'],
'node_modules/@stoplight/types/dist/index.js': ['DiagnosticSeverity'],
},
}),
terser(),
],
output: {
Expand Down
44 changes: 44 additions & 0 deletions src/__tests__/__fixtures__/gh-658/URIError.yaml
@@ -0,0 +1,44 @@
%YAML 1.2
---
openapi: 3.0.0

info:
title: Hey Mum! I'm on GitHub!
description: Resource definition.
version: 1.0.0

servers:
- url: https://boom.com

paths:
"/test":
get:
summary: Dummy endpoint.
description: Cf. summary
responses:
"200":
description: All is good.
content:
application/json:
schema:
type: string
"400":
description: Bad Request.
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
"500":
description: No Bueno.
content:
application/json:
schema:
$ref: "./lib.yaml#/components/schemas/Error"
components:
schemas:
Error:
$ref: "#/components/schemas/Baz"
Baz:
$ref: ./lib.yaml#/components/schemas/Error
Foo:
type: string
24 changes: 24 additions & 0 deletions src/__tests__/__fixtures__/gh-658/lib.yaml
@@ -0,0 +1,24 @@
%YAML 1.2
---
openapi: 3.0.0

info:
title: Library
description: Collection of reusable standard definitions.
version: 2.0.0
paths: {}
components:
schemas:
Error:
type: object
properties:
error:
type: string
maxLength: 1
error_description:
type: string
maxLength: 1
status_code:
type: string
test:
$ref: ./URIError.yaml#/components/schemas/Foo
223 changes: 218 additions & 5 deletions src/__tests__/spectral.jest.test.ts
Expand Up @@ -97,14 +97,15 @@ describe('Spectral', () => {
);
});

test('reports issues for correct files with correct ranges and paths', async () => {
test('should report issues for correct files with correct ranges and paths', async () => {
const documentUri = path.join(__dirname, './__fixtures__/document-with-external-refs.oas2.json');
const spectral = new Spectral({ resolver: httpAndFileResolver });
await spectral.loadRuleset('spectral:oas');
spectral.registerFormat('oas2', isOpenApiv2);
const parsed = {
parsed: parseWithPointers(fs.readFileSync(documentUri, 'utf8')),
getLocationForJsonPath,
source: documentUri,
};

const results = await spectral.run(parsed, {
Expand All @@ -128,7 +129,7 @@ describe('Spectral', () => {
line: 16,
},
},
source: undefined,
source: documentUri,
}),
expect.objectContaining({
code: 'oas2-schema',
Expand Down Expand Up @@ -158,7 +159,7 @@ describe('Spectral', () => {
line: 10,
},
},
source: undefined,
source: documentUri,
}),
expect.objectContaining({
code: 'info-contact',
Expand All @@ -173,7 +174,7 @@ describe('Spectral', () => {
line: 2,
},
},
source: undefined,
source: documentUri,
}),
expect.objectContaining({
code: 'operation-description',
Expand All @@ -188,9 +189,221 @@ describe('Spectral', () => {
line: 11,
},
},
source: undefined,
source: documentUri,
}),
]),
);
});

test('should recognize the source of remote $refs', async () => {
const s = new Spectral({ resolver: httpAndFileResolver });
const documentUri = path.join(__dirname, './__fixtures__/gh-658/URIError.yaml');

s.setRules({
'schema-strings-maxLength': {
severity: DiagnosticSeverity.Warning,
recommended: true,
message: "String typed properties MUST be further described using 'maxLength'. Error: {{error}}",
given: "$..[?(@.type === 'string')]",
then: {
field: 'maxLength',
function: 'truthy',
},
},
});

const results = await s.run(fs.readFileSync(documentUri, 'utf8'), { resolve: { documentUri } });

return expect(results).toEqual([
expect.objectContaining({
path: ['paths', '/test', 'get', 'responses', '200', 'content', 'application/json', 'schema'],
source: expect.stringContaining('/src/__tests__/__fixtures__/gh-658/URIError.yaml'),
range: {
end: {
character: 28,
line: 23,
},
start: {
character: 21,
line: 22,
},
},
}),

expect.objectContaining({
path: [
'paths',
'/test',
'get',
'responses',
'400',
'content',
'application/json',
'schema',
'properties',
'status_code',
],
source: expect.stringContaining('/src/__tests__/__fixtures__/gh-658/lib.yaml'),
range: {
end: {
character: 22,
line: 21,
},
start: {
character: 20,
line: 20,
},
},
}),
expect.objectContaining({
path: [
'paths',
'/test',
'get',
'responses',
'400',
'content',
'application/json',
'schema',
'properties',
'test',
],
source: expect.stringContaining('/src/__tests__/__fixtures__/gh-658/URIError.yaml'),
range: {
end: {
character: 18,
line: 43,
},
start: {
character: 8,
line: 42,
},
},
}),

expect.objectContaining({
path: [
'paths',
'/test',
'get',
'responses',
'500',
'content',
'application/json',
'schema',
'properties',
'status_code',
],
source: expect.stringContaining('/src/__tests__/__fixtures__/gh-658/lib.yaml'),
range: {
end: {
character: 22,
line: 21,
},
start: {
character: 20,
line: 20,
},
},
}),
expect.objectContaining({
path: [
'paths',
'/test',
'get',
'responses',
'500',
'content',
'application/json',
'schema',
'properties',
'test',
],
source: expect.stringContaining('/src/__tests__/__fixtures__/gh-658/URIError.yaml'),
range: {
end: {
character: 18,
line: 43,
},
start: {
character: 8,
line: 42,
},
},
}),

expect.objectContaining({
path: ['components', 'schemas', 'Foo'],
source: expect.stringContaining('/src/__tests__/__fixtures__/gh-658/URIError.yaml'),
range: {
end: {
character: 18,
line: 43,
},
start: {
character: 8,
line: 42,
},
},
}),

expect.objectContaining({
path: ['components', 'schemas', 'Error', 'properties', 'status_code'],
source: expect.stringContaining('/src/__tests__/__fixtures__/gh-658/lib.yaml'),
range: {
end: {
character: 22,
line: 21,
},
start: {
character: 20,
line: 20,
},
},
}),
expect.objectContaining({
path: ['components', 'schemas', 'Error', 'properties', 'test'],
source: expect.stringContaining('/src/__tests__/__fixtures__/gh-658/URIError.yaml'),
range: {
end: {
character: 18,
line: 43,
},
start: {
character: 8,
line: 42,
},
},
}),

expect.objectContaining({
path: ['components', 'schemas', 'Baz', 'properties', 'status_code'],
source: expect.stringContaining('/src/__tests__/__fixtures__/gh-658/lib.yaml'),
range: {
end: {
character: 22,
line: 21,
},
start: {
character: 20,
line: 20,
},
},
}),
expect.objectContaining({
path: ['components', 'schemas', 'Baz', 'properties', 'test'],
source: expect.stringContaining('/src/__tests__/__fixtures__/gh-658/URIError.yaml'),
range: {
end: {
character: 18,
line: 43,
},
start: {
character: 8,
line: 42,
},
},
}),
]);
});
});
2 changes: 1 addition & 1 deletion src/__tests__/spectral.test.ts
Expand Up @@ -250,7 +250,7 @@ describe('spectral', () => {
},
});

return expect(s.run(parsedResult)).resolves.toEqual([
return expect(s.run(parsedResult, { resolve: { documentUri: source } })).resolves.toEqual([
{
code: 'pagination-responses-have-x-next-token',
message: 'All collection endpoints have the X-Next-Token parameter in responses',
Expand Down

0 comments on commit 4d14fa0

Please sign in to comment.