Skip to content

Commit

Permalink
feat: add types to support typescript projects
Browse files Browse the repository at this point in the history
  • Loading branch information
rimesime committed Apr 27, 2024
1 parent fe2f1b5 commit 17c6275
Show file tree
Hide file tree
Showing 10 changed files with 247 additions and 21 deletions.
8 changes: 2 additions & 6 deletions README.md
Expand Up @@ -37,17 +37,13 @@ With npm:
$ npm install --save-dev jest-matcher-http
```

Add this package to your `jest.config.js`:
Add this setting to your `jest.config.js`:
```
setupFilesAfterEnv: ['jest-matcher-http'],
```

Alternatively, if you need fine-grained control, load specific matchers in your test file:
```javascript
const { toReturnHttpCode } = require('jest-matcher-http');
There's an example typescript project here: [integration_tests/tsProject/](integration_tests/tsProject/). This is used for integration testing this lib to ensure typescript compatibility.

expect.extend({ toReturnHttpCode });
```

# Usage

Expand Down
26 changes: 26 additions & 0 deletions integration_tests/tsProject.int.test.js
@@ -0,0 +1,26 @@
'use strict';

const { exec } = require('child_process');

describe('typescript project', () => {
// eslint-disable-next-line jest/no-done-callback
it('should successfully run jest tests of typescript project', (done) => {
const cmd = 'cd integration_tests/tsProject && npx jest my.successful.test.ts';
exec(cmd, (error) => {
expect(error).toBeNull();
done();
});
});

// eslint-disable-next-line jest/no-done-callback
it('should let jest tests fail if tests failing', (done) => {
const cmd = 'cd integration_tests/tsProject && npx jest my.failing.test.ts';
exec(cmd, (error) => {
expect(error?.code).toBe(1);
expect(error?.message).toStrictEqual(
expect.stringContaining('expected http status code 200 to equal 500'),
);
done();
});
});
});
10 changes: 10 additions & 0 deletions integration_tests/tsProject/jest.config.js
@@ -0,0 +1,10 @@
'use strict';

module.exports = {
preset: 'ts-jest',
// For real projects, use:
// setupFilesAfterEnv: ['jest-matcher-http'],
// Since this is a integration test project, living in the main
// package, we have to import the main package with a relative path.
setupFilesAfterEnv: ['../../'],
};
24 changes: 24 additions & 0 deletions integration_tests/tsProject/my.failing.test.ts
@@ -0,0 +1,24 @@
// For real projects, use:
// import 'jest-matcher-http';
// Since this is a integration test project, living in the main
// package, we have to import the main package with a relative path.
import '../../';

import axios, { AxiosInstance, AxiosResponse } from 'axios';

const { runAgainstServer } = require('../localServer.int.helper');

describe('matchers', () => {
let request: AxiosInstance;
let response: AxiosResponse;

test('should always fail', async () => {
await runAgainstServer(async (url: string) => {
request = axios.create({ baseURL: url });
response = await request.get('/get-json');
});

expect(response).toReturnHttpCode(500);
expect(response).toReturnHttpHeader('non-existing', 'Header');
});
});
24 changes: 24 additions & 0 deletions integration_tests/tsProject/my.successful.test.ts
@@ -0,0 +1,24 @@
// For real projects, use:
// import 'jest-matcher-http';
// Since this is a integration test project, living in the main
// package, we have to import the main package with a relative path.
import '../../';

import axios, { AxiosInstance, AxiosResponse } from 'axios';

const { runAgainstServer } = require('../localServer.int.helper');

describe('matchers', () => {
let request: AxiosInstance;
let response: AxiosResponse;

test('should be able to use http matchers', async () => {
await runAgainstServer(async (url: string) => {
request = axios.create({ baseURL: url });
response = await request.get('/get-json');
});

expect(response).toReturnHttpCode(200);
expect(response).toReturnHttpHeader('some', 'Header');
});
});
7 changes: 4 additions & 3 deletions jest.unit.config.js
Expand Up @@ -177,9 +177,10 @@ module.exports = {

// An array of regexp pattern strings that are matched against all test paths,
// matched tests are skipped
// testPathIgnorePatterns: [
// "/node_modules/"
// ],
testPathIgnorePatterns: [
'/node_modules/',
'.ts$',
],

// The regexp pattern or array of patterns that Jest uses to detect test files
// testRegex: [],
Expand Down
131 changes: 126 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion package.json
Expand Up @@ -6,6 +6,7 @@
"engines": {
"node": "16.x || 18.x || 20.x"
},
"types": "./types/index.d.ts",
"scripts": {
"lint": "eslint .",
"test": "jest --coverage --config jest.unit.config.js",
Expand Down Expand Up @@ -38,6 +39,7 @@
]
},
"devDependencies": {
"@types/jest": "^29.5.12",
"axios": "^1.3.4",
"eslint": "^8.36.0",
"eslint-config-airbnb-base": "^15.0.0",
Expand All @@ -50,7 +52,9 @@
"pre-commit": "^1.2.2",
"semantic-release": "^23.0.7",
"signal-promise": "^1.0.3",
"superagent": "^8.0.9"
"superagent": "^8.0.9",
"ts-jest": "^29.1.2",
"typescript": "^5.4.4"
},
"dependencies": {
"@jest/globals": "^29.5.0"
Expand Down
22 changes: 16 additions & 6 deletions src/matchers.js
@@ -1,10 +1,20 @@
'use strict';

/**
* @typedef {object} GenericResponse
* @property {{ [key: string]: any }} headers - The headers of the response.
* @property {object} [data] - The data of the response.
* @property {string} [text] - The text of the response.
* @property {object} [body] - The body of the response.
* @property {number} [status] - The status of the response.
* @property {number} [statusCode] - The status of the response.
*/

/**
* Extract the result from the response.
*
* @param {object} response - The response of the request.
* @returns {object} The result. Empty string if no result found.
* @param {GenericResponse} response - The response of the request.
* @returns {object | string} The result. Empty string if no result found.
*/
function extractResult(response) {
if (response.data) {
Expand All @@ -26,9 +36,9 @@ function extractResult(response) {
* Expect a http request to return given http status code.
* Log response body and headers otherwise.
*
* @param {object} response - The response of the request.
* @param {GenericResponse} response - The response of the request.
* @param {number} expectedHttpStatusCode - The expected http status code.
* @returns {{message: Function, pass: boolean}} The expect result according to jest.
* @returns {{ pass: boolean, message: () => string }} The expect result according to jest.
* @see {@link https://jestjs.io/docs/expect#expectextendmatchers}
*/
function toReturnHttpCode(response, expectedHttpStatusCode) {
Expand All @@ -51,10 +61,10 @@ function toReturnHttpCode(response, expectedHttpStatusCode) {
* Expect a http request to return the given http header.
* Log response body and headers otherwise.
*
* @param {object} response - The response of the request.
* @param {GenericResponse} response - The response of the request.
* @param {string} headerField - The expected http header field.
* @param {string} headerValue - The expected http header value.
* @returns {{message: Function, pass: boolean}} The expect result according to jest.
* @returns {{ pass: boolean, message: () => string }} The expect result according to jest.
* @see {@link https://jestjs.io/docs/expect#expectextendmatchers}
*/
function toReturnHttpHeader(response, headerField, headerValue) {
Expand Down
10 changes: 10 additions & 0 deletions types/index.d.ts
@@ -0,0 +1,10 @@
export {};

declare global {
namespace jest {
interface Matchers<R> {
toReturnHttpCode(status: number): R;
toReturnHttpHeader(headerField: string, headerValue: string): R;
}
}
}

0 comments on commit 17c6275

Please sign in to comment.