Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"mockDetails": {
"interactionDescription": "should error on unknown request accept",
"interactionState": "[none]",
"location": "[root].interactions[1].request.headers.accept",
"location": "[root].interactions[2].request.headers.accept",
"value": "application/xxx"
},
"specDetails": {
Expand All @@ -29,7 +29,7 @@
"mockDetails": {
"interactionDescription": "should error on incompatible request accept",
"interactionState": "[none]",
"location": "[root].interactions[2].request.headers.accept",
"location": "[root].interactions[3].request.headers.accept",
"value": "application/xxx"
},
"specDetails": {
Expand Down
15 changes: 15 additions & 0 deletions src/__tests__/fixtures/response-content-negotiation/oas.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,18 @@ paths:
content:
application/aaa: {}
application/bbb: {}
/with-encoding:
get:
responses:
"200":
description: OK
content:
"application/aaa; utf-8":
schema:
type: object
required:
- name
properties:
name:
type: number

22 changes: 19 additions & 3 deletions src/__tests__/fixtures/response-content-negotiation/pact.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
"interactions": [
{
"description": "should pass on successful response content negotiation",
"providerState": "",
"request": {
"method": "GET",
"path": "/with-content",
Expand All @@ -19,9 +18,27 @@
}
}
},
{
"description": "should pass on successful response content negotiation, with encoding",
"request": {
"method": "GET",
"path": "/with-encoding",
"headers": {
"accept": "application/aaa"
}
},
"response": {
"status": 200,
"headers": {
"Content-Type": "application/aaa"
},
"body": {
"name": "name"
}
}
},
{
"description": "should error on unknown request accept",
"providerState": "",
"request": {
"method": "GET",
"path": "/no-content",
Expand All @@ -35,7 +52,6 @@
},
{
"description": "should error on incompatible request accept",
"providerState": "",
"request": {
"method": "GET",
"path": "/with-content",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"mockDetails": {
"interactionDescription": "should error on unknown request accept",
"interactionState": "[none]",
"location": "[root].interactions[1].request.headers.accept",
"location": "[root].interactions[2].request.headers.accept",
"value": "application/xxx"
},
"specDetails": {
Expand All @@ -29,7 +29,7 @@
"mockDetails": {
"interactionDescription": "should error on incompatible request accept",
"interactionState": "[none]",
"location": "[root].interactions[2].request.headers.accept",
"location": "[root].interactions[3].request.headers.accept",
"value": "application/xxx"
},
"specDetails": {
Expand Down
21 changes: 12 additions & 9 deletions src/compare/requestBody.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { minimumSchema, transformRequestSchema } from "../transform/index";
import { isValidRequest } from "../utils/interaction";
import { dereferenceOas, splitPath } from "../utils/schema";
import { getValidateFunction } from "../utils/validation";
import { findMatchingType } from "./utils/content";
import { findMatchingType, getByContentType } from "./utils/content";

const parseBody = (body: unknown, contentType: string) => {
if (
Expand Down Expand Up @@ -56,14 +56,17 @@ export function* compareReqBody(
Object.keys(
dereferenceOas(operation.requestBody || {}, oas)?.content || {},
);
const contentType =
findMatchingType(
requestHeaders.get("content-type") || DEFAULT_CONTENT_TYPE,
availableRequestContentTypes,
) || DEFAULT_CONTENT_TYPE;

const requestContentType = requestHeaders.get("content-type") || "";
const contentType = requestContentType
? findMatchingType(requestContentType, availableRequestContentTypes) ||
requestContentType
: DEFAULT_CONTENT_TYPE;
const schema: SchemaObject | undefined =
dereferenceOas(operation.requestBody || {}, oas)?.content?.[contentType]
?.schema ||
getByContentType(
dereferenceOas(operation.requestBody || {}, oas)?.content,
contentType,
)?.schema ||
dereferenceOas(
(operation.parameters || []).find(
(p: OpenAPIV2.ParameterObject) => p.in === "body",
Expand All @@ -72,7 +75,7 @@ export function* compareReqBody(
)?.schema;

if (schema && canValidate(contentType) && isValidRequest(interaction)) {
const value = parseBody(body, contentType);
const value = parseBody(body, requestContentType);
const schemaId = `[root].paths.${path}.${method}.requestBody.content.${contentType}`;
const validate = getValidateFunction(ajv, schemaId, () =>
transformRequestSchema(minimumSchema(schema, oas)),
Expand Down
6 changes: 1 addition & 5 deletions src/compare/requestHeader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,7 @@ export function* compareReqHeader(
const requestContentType: string =
requestHeaders.get("content-type")?.split(";")[0] || "";

if (
requestContentType &&
!availableRequestContentType.length &&
isValidRequest(interaction)
) {
if (requestContentType && !availableRequestContentType.length) {
yield {
code: "request.content-type.unknown",
message:
Expand Down
5 changes: 3 additions & 2 deletions src/compare/responseBody.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
import { minimumSchema, transformResponseSchema } from "../transform/index";
import { dereferenceOas, splitPath } from "../utils/schema";
import { getValidateFunction } from "../utils/validation";
import { findMatchingType } from "./utils/content";
import { findMatchingType, getByContentType } from "./utils/content";

const canValidate = (contentType = ""): boolean => {
return !!findMatchingType(contentType, ["application/json"]);
Expand Down Expand Up @@ -74,7 +74,8 @@ export function* compareResBody(
const dereferencedResponse = dereferenceOas(response, oas);
const schema: SchemaObject | undefined =
(dereferencedResponse as OpenAPIV2.ResponseObject)?.schema ||
dereferencedResponse.content?.[contentType]?.schema;
getByContentType(dereferencedResponse.content || {}, contentType)?.schema;

const value = body;

if (!statusResponse) {
Expand Down
5 changes: 5 additions & 0 deletions src/compare/utils/content.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@ export function findMatchingType(
return undefined;
}

export const getByContentType = (object = {}, contentType: string) => {
const key = findMatchingType(contentType, Object.keys(object));
return object[key];
};

export const standardHttpRequestHeaders = [
"accept",
"accept-charset",
Expand Down