Skip to content

Commit 000df40

Browse files
authored
Merge pull request #1620 from shockey/master
Always use resolved API definition in semantic validation
2 parents 50e7719 + 4bdcf8f commit 000df40

File tree

12 files changed

+80
-49
lines changed

12 files changed

+80
-49
lines changed

src/plugins/validate-semantic/index.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,8 @@ export default function SemanticValidatorsPlugin({getSystem}) {
2727
spec: {
2828
selectors: {
2929
jsonAsJS: createSelector(
30-
state => state.get("resolvedSpec"),
31-
state => state.get("json"),
32-
(a,b) => (a || b).toJS()
30+
state => state.get("resolved"),
31+
(spec) => spec ? spec.toJS() : null
3332
),
3433
definitions: createSelector(
3534
state => state.getIn(["json", "definitions"]),

src/plugins/validate-semantic/selectors.js

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -84,15 +84,15 @@ export const isResponseSchema = (state, node) => (sys) => {
8484
}
8585

8686
export const allSchemas = () => (system) => {
87-
const schemaSources = [
88-
"allParameterSchemas",
89-
"allResponseSchemas",
90-
"allDefinitions",
91-
"allHeaders",
92-
"allSubSchemas",
93-
]
87+
const { validateSelectors } = system
9488

95-
const selectors = schemaSources.map(name => system.validateSelectors[name]())
89+
const selectors = [
90+
validateSelectors.allParameterSchemas(),
91+
validateSelectors.allResponseSchemas(),
92+
validateSelectors.allDefinitions(),
93+
validateSelectors.allHeaders(),
94+
validateSelectors.allSubSchemas(),
95+
]
9696

9797
return Promise.all(selectors)
9898
.then((schemasAr) => {

src/plugins/validate-semantic/validators/operations.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,19 @@ export const validateOperationHasUniqueId = () => sys => {
66
return nodes.reduce((acc, node) => {
77
const value = node.node
88

9-
if(value.operationId) {
10-
if(seen.indexOf(value.operationId) > -1) {
9+
// Swagger-Client messes with `value.operationId`, but puts the inital
10+
// value in `__originalOperationId` when it resolves, so we use that.
11+
const id = value.__originalOperationId
12+
13+
if(id) {
14+
if(seen.indexOf(id) > -1) {
1115
acc.push({
1216
level: "error",
1317
message: "Operations must have unique operationIds.",
1418
path: [...node.path, "operationId"]
1519
})
1620
}
17-
seen.push(value.operationId)
21+
seen.push(id)
1822
}
1923
return acc
2024
}, [])

src/plugins/validate-semantic/validators/refs.js

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
1+
import get from "lodash/get"
2+
13
export const validateRefHasNoSiblings = () => system => {
2-
return system.validateSelectors
3-
.all$refs()
4-
.then(nodes => {
4+
return Promise.all([
5+
system.validateSelectors.all$refArtifacts(),
6+
]).then(([nodes]) => {
7+
const immSpecJson = system.specSelectors.specJson()
8+
const specJson = immSpecJson.toJS ? immSpecJson.toJS() : {}
9+
510
return nodes.reduce((acc, node) => {
6-
const parentValue = node.notRoot ? node.parent.node : null
7-
const parentKeys = Object.keys(parentValue) || []
11+
const unresolvedValue = get(specJson, node.parent.path) || {}
12+
const unresolvedKeys = Object.keys(unresolvedValue) || []
813

9-
parentKeys.forEach(k => {
10-
if(k !== "$ref") {
14+
15+
unresolvedKeys.forEach(k => {
16+
if(k !== "$ref" && unresolvedKeys.indexOf("$ref") > -1) {
1117
acc.push({
1218
message: `Sibling values are not allowed alongside $refs`,
1319
path: [...node.path.slice(0, -1), k],
@@ -26,7 +32,12 @@ export const validateUnusedDefinitions = () => (system) => {
2632
system.validateSelectors.all$refs(),
2733
system.validateSelectors.all$refArtifacts()
2834
]).then(([refs, refArtifacts]) => {
29-
const references = (refs || refArtifacts || []).map(node => node.node)
35+
const references = (
36+
(refs.length ? refs : null)
37+
|| (refArtifacts.length ? refArtifacts : null)
38+
|| []
39+
).map(node => node.node)
40+
3041
const errors = []
3142

3243
system.specSelectors.definitions()
File renamed without changes.
File renamed without changes.
File renamed without changes.

test/plugins/validate/paths.js renamed to test/plugins/validate-semantic/paths.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,28 @@ describe("validation plugin - semantic - paths", function(){
2424
return expectNoErrors(spec)
2525
})
2626

27+
it("should not return problems for a valid path-level definiton/declaration pair using a $ref", function(){
28+
const spec = {
29+
paths: {
30+
"/CoolPath/{id}": {
31+
parameters: [
32+
{ $ref: "#/parameters/id" }
33+
]
34+
}
35+
},
36+
parameters: {
37+
id: {
38+
name: "id",
39+
in: "path",
40+
description: "An id",
41+
required: true
42+
}
43+
}
44+
}
45+
46+
return expectNoErrors(spec)
47+
})
48+
2749
it("should not return problems for a valid operation-level definiton/declaration pair", function(){
2850
const spec = {
2951
paths: {

test/plugins/validate/refs.js renamed to test/plugins/validate-semantic/refs.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,13 @@ describe("validation plugin - semantic - refs", function() {
1010
paths: {
1111
"/CoolPath": {
1212
schema: {
13-
$ref: "#/definition/abc",
13+
$ref: "#/definitions/abc",
1414
description: "My very cool schema"
1515
}
1616
}
17+
},
18+
definitions: {
19+
abc: {}
1720
}
1821
}
1922

test/plugins/validate/schema.js renamed to test/plugins/validate-semantic/schema.js

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -545,30 +545,34 @@ describe("validation plugin - semantic - schema", function() {
545545
// Given
546546
const spec = {
547547
paths: {
548-
$ref: "#/definitions/asdf"
549-
},
550-
"definitions": {
551-
"asdf": {
552-
type: "object",
553-
properties: {
554-
slug: {
555-
type: "string",
556-
pattern: "^[-a-zA-Z0-9_]+\\Z"
548+
"/": {
549+
get: {
550+
responses: {
551+
"200": {
552+
schema: {
553+
type: "object",
554+
properties: {
555+
slug: {
556+
type: "string",
557+
pattern: "^[-a-zA-Z0-9_]+\\Z"
558+
}
559+
}
560+
}
561+
}
557562
}
558563
}
559564
}
560-
}
565+
},
561566
}
562567

563568
// When
564569
return validateHelper(spec)
565570
.then(system => {
566-
567571
// Then
568572
expect(system.errSelectors.allErrors().count()).toEqual(1)
569573
const firstError = system.errSelectors.allErrors().first().toJS()
570574
expect(firstError.message).toEqual(`"\\Z" anchors are not allowed in regular expression patterns`)
571-
expect(firstError.path).toEqual(["definitions", "asdf", "properties", "slug", "pattern"])
575+
expect(firstError.path).toEqual(["paths", "/", "get", "responses", "200", "schema", "properties", "slug", "pattern"])
572576
})
573577

574578
})

0 commit comments

Comments
 (0)