Skip to content

Commit 99be64f

Browse files
committed
Improve error messaging when path parameter is msising from operation
1 parent 512a01d commit 99be64f

File tree

2 files changed

+45
-16
lines changed

2 files changed

+45
-16
lines changed

src/plugins/validate/validators/paths.js

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,18 @@ export const validatePathParameterDeclarationHasMatchingDefiniton = () => system
1717
// don't validate empty param names... they're invalid anyway
1818
return
1919
}
20-
if(!checkForDefinition(paramName, pathItem)) {
20+
const res = checkForDefinition(paramName, pathItem)
21+
if(res.inOperation && res.missingFromOperations.length) {
22+
const missingStr = res.missingFromOperations
23+
.map(str => `"${str}"`)
24+
.join(", ")
25+
26+
acc.push({
27+
message: `Declared path parameter "${paramName}" needs to be defined within every operation in the path (missing in ${missingStr}), or moved to the path-level parameters object`,
28+
path: [...node.path],
29+
level: "error",
30+
})
31+
} else if(!res.found) {
2132
acc.push({
2233
message: `Declared path parameter "${paramName}" needs to be defined as a path parameter at either the path or operation level`,
2334
path: [...node.path],
@@ -97,31 +108,46 @@ function checkForDefinition(paramName, pathItem) {
97108
const pathItemParameters = pathItem.parameters
98109
const operationsInPathItem = (Object.keys(pathItem) || [])
99110
.filter(key => operationKeys.indexOf(key) > -1)
100-
.map(key => pathItem[key])
111+
.map(key => {
112+
const obj = pathItem[key]
113+
obj.method = key
114+
return obj
115+
})
101116

102-
let definitionFound = false
117+
const res = {
118+
found: false,
119+
inPath: false,
120+
inOperation: false,
121+
missingFromOperations: []
122+
}
103123

104124
// Look at the path parameters
105125
if(Array.isArray(pathItemParameters)) {
106126
pathItemParameters.forEach(param => {
107127
if(param.name === paramName && param.in === "path") {
108-
definitionFound = true
128+
res.found = true
129+
res.inPath = true
109130
}
110131
})
111132
}
112133

113-
// Next, look at the operation...
114-
// Mark as found if _every_ operation has a definition for the path param
115-
if(!definitionFound && operationsInPathItem.length) {
116-
definitionFound = operationsInPathItem
117-
.every(op => {
118-
if(!Array.isArray(op.parameters)) {
119-
return false
120-
}
121-
return op.parameters
134+
// Next, look at the operations...
135+
if(!res.found && operationsInPathItem.length) {
136+
operationsInPathItem
137+
.forEach(op => {
138+
const inThisOperation = (op.parameters || [])
122139
.some(param => param.name === paramName && param.in === "path")
140+
141+
if(inThisOperation) {
142+
res.found = true
143+
res.inOperation = true
144+
}
145+
146+
if(!inThisOperation) {
147+
res.missingFromOperations.push(op.method)
148+
}
123149
})
124150
}
125151

126-
return definitionFound
152+
return res
127153
}

test/plugins/validate/paths.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ describe("validation plugin - semantic - paths", function(){
5757
},
5858
post: {
5959
description: "the path parameter definition is missing here"
60+
},
61+
delete: {
62+
description: "the path parameter definition is missing here"
6063
}
6164
}
6265
}
@@ -67,12 +70,12 @@ describe("validation plugin - semantic - paths", function(){
6770
const allErrors = system.errSelectors.allErrors().toJS()
6871
const firstError = allErrors[0]
6972
expect(allErrors.length).toEqual(1)
70-
expect(firstError.message).toEqual( "Declared path parameter \"id\" needs to be defined as a path parameter at either the path or operation level")
73+
expect(firstError.message).toEqual( `Declared path parameter \"id\" needs to be defined within every operation in the path (missing in "post", "delete"), or moved to the path-level parameters object`)
7174
expect(firstError.path).toEqual(["paths", "/CoolPath/{id}"])
7275
})
7376
})
7477

75-
it("should return one problem when the definition is absent", function(){
78+
it("should return one problem when the definition is completely absent", function(){
7679
const spec = {
7780
paths: {
7881
"/CoolPath/{id}": {

0 commit comments

Comments
 (0)