Skip to content

Enable TypeScript strict mode #254

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Oct 16, 2021
1 change: 1 addition & 0 deletions .eslintrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ env:

extends:
- eslint:recommended
- airbnb-base
- airbnb-typescript/base
- plugin:@typescript-eslint/recommended
# - plugin:@typescript-eslint/recommended-requiring-type-checking
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"swagger": "2.0",
"info": {
"description": "Has various paths with responses to use in testing",
"title": "Example OpenApi 3 spec",
"version": "0.1.0"
},
"paths": {
"/endpointPath": {
"get": {
"parameters": [],
"responses": {
"204": {
"$ref": "#/responses/NonExistentResponse"
}
}
}
}
},
"x-components": {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
openapi: 3.0.0
info:
title: Example OpenApi 3 spec
description: Has various paths with responses to use in testing
version: 0.1.0
paths:
/endpointPath:
get:
responses:
204:
$ref: '#/components/responses/NonExistentResponse'
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"swagger": "2.0",
"info": {
"description": "Has various paths with responses to use in testing",
"title": "Example OpenApi 3 spec",
"version": "0.1.0"
},
"paths": {
"/unused": {
"get": {
"parameters": [],
"responses": {
"204": {
"description": "No response body"
}
}
}
}
},
"x-components": {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
openapi: 3.0.0
info:
title: Example OpenApi 3 spec
description: Has various paths with responses to use in testing
version: 0.1.0
paths:
/unused:
get:
responses:
204:
description: No response body
15 changes: 10 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
"node": ">=10.0.0"
},
"scripts": {
"postinstall": "patch-package",
"patch-packages": "yarn patch-package openapi-response-validator",
"clean": "yarn workspaces run clean && rimraf packages/.nyc_output && rimraf packages/coverage",
"format": "prettier --write . --ignore-path .prettierignore",
"lint": "yarn workspaces run lint",
Expand All @@ -20,20 +22,23 @@
},
"devDependencies": {
"@types/express": "^4.17.13",
"@typescript-eslint/eslint-plugin": "^4.17.0",
"@typescript-eslint/parser": "^4.16.1",
"@typescript-eslint/eslint-plugin": "^4.33.0",
"@typescript-eslint/parser": "^4.33.0",
"eslint": "^7.11.0",
"eslint-config-airbnb-typescript": "^12.3.1",
"eslint-config-airbnb-base": "^14.2.1",
"eslint-config-airbnb-typescript": "^14.0.1",
"eslint-config-prettier": "^6.12.0",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-jest": "^24.1.0",
"eslint-plugin-mocha": "^8.0.0",
"express": "^4.17.1",
"husky": "^4.3.0",
"lerna": "^4.0.0",
"prettier": "^2.1.2",
"patch-package": "^6.4.7",
"postinstall-postinstall": "^2.1.0",
"prettier": "^2.4.1",
"rimraf": "^3.0.2",
"typescript": "^4.2.3"
"typescript": "^4.4.3"
},
"husky": {
"hooks": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,21 @@ export default function (

Assertion.addProperty('satisfyApiSpec', function () {
const actualResponse = makeResponse(this._obj); // eslint-disable-line no-underscore-dangle

const validationError = openApiSpec.validateResponse(actualResponse);
const predicate = !validationError;
const pass = !validationError;
this.assert(
predicate,
getExpectedResToSatisfyApiSpecMsg(
actualResponse,
openApiSpec,
validationError,
),
getExpectedResNotToSatisfyApiSpecMsg(
actualResponse,
openApiSpec,
validationError,
),
pass,
pass
? ''
: getExpectedResToSatisfyApiSpecMsg(
actualResponse,
openApiSpec,
validationError,
),
pass
? getExpectedResNotToSatisfyApiSpecMsg(actualResponse, openApiSpec)
: '',
null,
);
});
Expand All @@ -40,10 +41,7 @@ function getExpectedResToSatisfyApiSpecMsg(
actualResponse: ActualResponse,
openApiSpec: OpenApiSpec,
validationError: ValidationError,
): string | null {
if (!validationError) {
return null;
}
): string {
const hint = 'expected res to satisfy API spec';

const { status, req } = actualResponse;
Expand Down Expand Up @@ -120,9 +118,9 @@ function getExpectedResToSatisfyApiSpecMsg(
}

if (validationError.code === ErrorCode.StatusNotFound) {
const expectedResponseOperation = openApiSpec.findExpectedResponseOperation(
req,
);
const expectedResponseOperation =
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
openApiSpec.findExpectedResponseOperation(req)!;
const expectedResponseStatuses = Object.keys(
expectedResponseOperation.responses,
).join(', ');
Expand Down Expand Up @@ -150,12 +148,7 @@ function getExpectedResToSatisfyApiSpecMsg(
function getExpectedResNotToSatisfyApiSpecMsg(
actualResponse: ActualResponse,
openApiSpec: OpenApiSpec,
validationError: ValidationError,
): string | null {
if (validationError) {
return null;
}

): string {
const { status, req } = actualResponse;
const responseDefinition = openApiSpec.findExpectedResponse(actualResponse);
const endpoint = `${req.method} ${openApiSpec.findOpenApiPathMatchingRequest(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,17 @@ export default function (
}

const validationError = openApiSpec.validateObject(actualObject, schema);
const predicate = !validationError;
const pass = !validationError;
this.assert(
predicate,
getExpectReceivedToSatisfySchemaInApiSpecMsg(
actualObject,
schemaName,
schema,
validationError,
),
pass,
pass
? ''
: getExpectReceivedToSatisfySchemaInApiSpecMsg(
actualObject,
schemaName,
schema,
validationError,
),
getExpectReceivedNotToSatisfySchemaInApiSpecMsg(
actualObject,
schemaName,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import chai from 'chai';
import path from 'path';

import { joinWithNewLines } from '../../../../../commonTestResources/utils';
import chaiResponseValidator from '../../..';

const openApiSpecsDir = path.resolve(
'../../commonTestResources/exampleOpenApiFiles/valid/noResponseComponents',
);
const openApiSpecs = [
{
openApiVersion: 2,
pathToApiSpec: path.join(openApiSpecsDir, 'openapi2WithNoResponses.json'),
},
{
openApiVersion: 3,
pathToApiSpec: path.join(openApiSpecsDir, 'openapi3WithNoComponents.yml'),
},
];

const { expect } = chai;

openApiSpecs.forEach((spec) => {
const { openApiVersion, pathToApiSpec } = spec;

describe(`expect(res).to.satisfyApiSpec (using an OpenAPI ${openApiVersion} spec with no response component definitions)`, () => {
const res = {
status: 204,
req: {
method: 'GET',
path: '/endpointPath',
},
};

before(() => {
chai.use(chaiResponseValidator(pathToApiSpec));
});

it('fails', () => {
const assertion = () => expect(res).to.satisfyApiSpec;
expect(assertion).to.throw(
joinWithNewLines(
"expected res to satisfy a '204' response defined for endpoint 'GET /endpointPath' in your API spec",
"res had status '204', but your API spec has no '204' response defined for endpoint 'GET /endpointPath'",
),
);
});

it('passes when using .not', () => {
expect(res).not.to.satisfyApiSpec;
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -453,8 +453,7 @@ describe('Using OpenAPI 3 specs that define servers differently', () => {
status: 200,
req: {
method: 'GET',
path:
'/defaultValueOfFirstVariableInPath/defaultValueOfSecondVariableInPath/endpointPath',
path: '/defaultValueOfFirstVariableInPath/defaultValueOfSecondVariableInPath/endpointPath',
},
body: 'valid body (string)',
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import chai from 'chai';
import path from 'path';

import chaiResponseValidator from '../../..';

const openApiSpecsDir = path.resolve(
'../../commonTestResources/exampleOpenApiFiles/valid/satisfySchemaInApiSpec/noSchemaComponents',
);
const openApiSpecs = [
{
openApiVersion: 2,
pathToApiSpec: path.join(openApiSpecsDir, 'openapi2WithNoDefinitions.json'),
},
{
openApiVersion: 3,
pathToApiSpec: path.join(openApiSpecsDir, 'openapi3WithNoComponents.yml'),
},
];

const { expect, AssertionError } = chai;

openApiSpecs.forEach((spec) => {
const { openApiVersion, pathToApiSpec } = spec;

describe(`expect(obj).to.satisfySchemaInApiSpec(schemaName) (using an OpenAPI ${openApiVersion} spec with no schema definitions)`, () => {
const obj = 'foo';

before(() => {
chai.use(chaiResponseValidator(pathToApiSpec));
});

it('fails', () => {
const assertion = () =>
expect(obj).to.satisfySchemaInApiSpec('NonExistentSchema');
expect(assertion).to.throw(
AssertionError,
'The argument to satisfySchemaInApiSpec must match a schema in your API spec',
);
});

it('fails when using .not', () => {
const assertion = () =>
expect(obj).to.not.satisfySchemaInApiSpec('NonExistentSchema');
expect(assertion).to.throw(
AssertionError,
'The argument to satisfySchemaInApiSpec must match a schema in your API spec',
);
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { RECEIVED_COLOR as red } from 'jest-matcher-utils';
import path from 'path';

import { joinWithNewLines } from '../../../../../commonTestResources/utils';
import jestOpenAPI from '../../..';

const openApiSpecsDir = path.resolve(
'../../commonTestResources/exampleOpenApiFiles/valid/noResponseComponents',
);
const openApiSpecs = [
{
openApiVersion: 2,
pathToApiSpec: path.join(openApiSpecsDir, 'openapi2WithNoResponses.json'),
},
{
openApiVersion: 3,
pathToApiSpec: path.join(openApiSpecsDir, 'openapi3WithNoComponents.yml'),
},
];

openApiSpecs.forEach((spec) => {
const { openApiVersion, pathToApiSpec } = spec;

describe(`expect(res).toSatisfyApiSpec() (using an OpenAPI ${openApiVersion} spec with no response component definitions)`, () => {
const res = {
status: 204,
req: {
method: 'GET',
path: '/endpointPath',
},
};

beforeAll(() => {
jestOpenAPI(pathToApiSpec);
});

it('fails', () => {
const assertion = () => expect(res).toSatisfyApiSpec();
expect(assertion).toThrow(
// prettier-ignore
joinWithNewLines(
`expected ${red('received')} to satisfy a '204' response defined for endpoint 'GET /endpointPath' in your API spec`,
`${red('received')} had status ${red('204')}, but your API spec has no ${red('204')} response defined for endpoint 'GET /endpointPath'`,
),
);
});

it('passes when using .not', () => {
expect(res).not.toSatisfyApiSpec();
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -468,8 +468,7 @@ describe('Using OpenAPI 3 specs that define servers differently', () => {
status: 200,
req: {
method: 'GET',
path:
'/defaultValueOfFirstVariableInPath/defaultValueOfSecondVariableInPath/endpointPath',
path: '/defaultValueOfFirstVariableInPath/defaultValueOfSecondVariableInPath/endpointPath',
},
body: 'valid body (string)',
};
Expand Down
Loading