Skip to content

Commit 6395f18

Browse files
committed
fix: infinite recursion + change behaviour to match SMV
1 parent a54f891 commit 6395f18

File tree

8 files changed

+108
-18
lines changed

8 files changed

+108
-18
lines changed

src/__tests__/fixtures/example-petstore-1/results.json

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,45 @@
9898
},
9999
"type": "error"
100100
},
101+
{
102+
"code": "request.accept.unknown",
103+
"message": "Request Accept header is defined but the spec does not specify any mime-types to produce",
104+
"mockDetails": {
105+
"interactionDescription": "a request to create a pet with invalid body",
106+
"interactionState": "[none]",
107+
"location": "[root].interactions[1].request.headers.accept",
108+
"value": "application/json"
109+
},
110+
"specDetails": {
111+
"location": "[root].paths./pet.post",
112+
"pathMethod": "post",
113+
"pathName": "/pet",
114+
"value": {
115+
"tags": [
116+
"pet"
117+
],
118+
"summary": "Add a new pet to the store",
119+
"operationId": "addPet",
120+
"responses": {
121+
"405": {
122+
"description": "Invalid input"
123+
}
124+
},
125+
"security": [
126+
{
127+
"petstore_auth": [
128+
"write:pets",
129+
"read:pets"
130+
]
131+
}
132+
],
133+
"requestBody": {
134+
"$ref": "#/components/requestBodies/Pet"
135+
}
136+
}
137+
},
138+
"type": "warning"
139+
},
101140
{
102141
"code": "response.content-type.unknown",
103142
"message": "Response Content-Type header is defined but the spec does not specify any mime-types to produce",

src/__tests__/fixtures/example-petstore-2/results.json

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,45 @@
9898
},
9999
"type": "error"
100100
},
101+
{
102+
"code": "request.accept.unknown",
103+
"message": "Request Accept header is defined but the spec does not specify any mime-types to produce",
104+
"mockDetails": {
105+
"interactionDescription": "a request to create a pet with invalid body",
106+
"interactionState": "[none]",
107+
"location": "[root].interactions[1].request.headers.accept",
108+
"value": "application/json"
109+
},
110+
"specDetails": {
111+
"location": "[root].paths./pet.post",
112+
"pathMethod": "post",
113+
"pathName": "/pet",
114+
"value": {
115+
"tags": [
116+
"pet"
117+
],
118+
"summary": "Add a new pet to the store",
119+
"operationId": "addPet",
120+
"responses": {
121+
"405": {
122+
"description": "Invalid input"
123+
}
124+
},
125+
"security": [
126+
{
127+
"petstore_auth": [
128+
"write:pets",
129+
"read:pets"
130+
]
131+
}
132+
],
133+
"requestBody": {
134+
"$ref": "#/components/requestBodies/Pet"
135+
}
136+
}
137+
},
138+
"type": "warning"
139+
},
101140
{
102141
"code": "response.content-type.unknown",
103142
"message": "Response Content-Type header is defined but the spec does not specify any mime-types to produce",

src/__tests__/fixtures/response-body-swagger2/results.json

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
},
1919
{
2020
"code": "response.body.incompatible",
21-
"message": "Response body is incompatible with the response body schema in the spec file: must have required property 'age'",
21+
"message": "Response body is incompatible with the response body schema in the spec file: must NOT have additional properties - detail",
2222
"mockDetails": {
2323
"interactionDescription": "should error with invalid response",
2424
"interactionState": "[none]",
@@ -29,13 +29,10 @@
2929
}
3030
},
3131
"specDetails": {
32-
"location": "[root].paths./animal.get.responses.200.content.application/json.schema.definitions.Animal.required",
32+
"location": "[root].paths./animal.get.responses.200.content.application/json.schema.definitions.Animal.additionalProperties",
3333
"pathMethod": "get",
3434
"pathName": "/animal",
35-
"value": [
36-
"name",
37-
"age"
38-
]
35+
"value": false
3936
},
4037
"type": "error"
4138
}

src/__tests__/fixtures/response-body/baseline.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
"code": "response.body.unknown",
4141
"message": "No matching schema found for response body",
4242
"mockDetails": {
43-
"interactionDescription": "should error with unknown respos body",
43+
"interactionDescription": "should error with unknown response body",
4444
"interactionState": "[none]",
4545
"location": "[root].interactions[6].response.body",
4646
"value": {
@@ -62,7 +62,7 @@
6262
"code": "response.content-type.unknown",
6363
"message": "Response Content-Type header is defined but the spec does not specify any mime-types to produce",
6464
"mockDetails": {
65-
"interactionDescription": "should error with unknown respos body",
65+
"interactionDescription": "should error with unknown response body",
6666
"interactionState": "[none]",
6767
"location": "[root].interactions[6].response.headers.Content-Type",
6868
"value": "application/json"

src/__tests__/fixtures/response-body/pact.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@
125125
}
126126
},
127127
{
128-
"description": "should error with unknown respos body",
128+
"description": "should error with unknown response body",
129129
"request": {
130130
"method": "GET",
131131
"path": "/no-response-schema"

src/__tests__/fixtures/response-body/results.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
"code": "response.content-type.unknown",
4141
"message": "Response Content-Type header is defined but the spec does not specify any mime-types to produce",
4242
"mockDetails": {
43-
"interactionDescription": "should error with unknown respos body",
43+
"interactionDescription": "should error with unknown response body",
4444
"interactionState": "[none]",
4545
"location": "[root].interactions[6].response.headers.content-type",
4646
"value": "application/json"
@@ -64,7 +64,7 @@
6464
"code": "response.body.unknown",
6565
"message": "No matching schema found for response body",
6666
"mockDetails": {
67-
"interactionDescription": "should error with unknown respos body",
67+
"interactionDescription": "should error with unknown response body",
6868
"interactionState": "[none]",
6969
"location": "[root].interactions[6].response.body",
7070
"value": {

src/compare/requestHeader.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,17 @@ export function* compareReqHeader(
3232
Object.keys(
3333
dereferenceOas(operation.requestBody || {}, oas)?.content || {},
3434
);
35+
const allAvailableResponseContentTypes =
36+
operation.produces ||
37+
Object.entries(operation.responses).reduce(
38+
(acc: string[], [_status, response]) => {
39+
return [
40+
...acc,
41+
...Object.keys(dereferenceOas(response || {}, oas)?.content || {}),
42+
];
43+
},
44+
[],
45+
);
3546
const availableResponseContentType =
3647
operation.produces ||
3748
Object.keys(
@@ -49,11 +60,7 @@ export function* compareReqHeader(
4960
const requestAccept: string =
5061
requestHeaders.get("accept")?.split(";")[0] || "";
5162

52-
if (
53-
requestAccept &&
54-
!availableResponseContentType.length &&
55-
isValidRequest(interaction)
56-
) {
63+
if (requestAccept && !allAvailableResponseContentTypes.length) {
5764
yield {
5865
code: "request.accept.unknown",
5966
message:

src/utils/schema.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,16 +43,24 @@ export const traverse = (
4343
const _traverseWithDereferencing = (
4444
schema: SchemaObject,
4545
oas: OpenAPIV3.Document,
46+
visited: string[],
4647
visitor: (schema: SchemaObject) => void,
4748
) => {
4849
if (typeof schema === "boolean" || schema === undefined) {
4950
return;
5051
}
5152

53+
if (visited.includes(schema.$ref)) {
54+
return;
55+
}
56+
57+
if (schema.$ref) {
58+
visited.push(schema.$ref);
59+
}
5260
const dereferencedSchema = dereferenceOas(schema, oas);
5361

5462
const traverseSubSchema = (item: SchemaObject) =>
55-
_traverseWithDereferencing(item, oas, visitor);
63+
_traverseWithDereferencing(item, oas, visited, visitor);
5664

5765
each(dereferencedSchema.allOf, traverseSubSchema);
5866
each(dereferencedSchema.oneOf, traverseSubSchema);
@@ -69,5 +77,5 @@ export const traverseWithDereferencing = (
6977
schema: SchemaObject,
7078
visitor: (schema: SchemaObject) => void,
7179
) => {
72-
_traverseWithDereferencing(schema, schema as OpenAPIV3.Document, visitor);
80+
_traverseWithDereferencing(schema, schema as OpenAPIV3.Document, [], visitor);
7381
};

0 commit comments

Comments
 (0)