From d19a375ec97b776fbf247fa6afb493a0cd189fd5 Mon Sep 17 00:00:00 2001 From: Shubh Bapna Date: Wed, 8 Mar 2023 14:30:16 -0500 Subject: [PATCH 1/4] added ability to mock requests which match certain headers --- .../response/abstract-response-mocker.ts | 27 ++++++++++++++----- .../abstract-response-mocker.types.ts | 6 ++++- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/src/endpoint-mocker/response/abstract-response-mocker.ts b/src/endpoint-mocker/response/abstract-response-mocker.ts index 6ece21a..6ee4246 100644 --- a/src/endpoint-mocker/response/abstract-response-mocker.ts +++ b/src/endpoint-mocker/response/abstract-response-mocker.ts @@ -1,14 +1,16 @@ import nock, { DataMatcherMap } from "nock"; -import { Response } from "@mg/endpoint-mocker/response/abstract-response-mocker.types"; +import { Header, Response } from "@mg/endpoint-mocker/response/abstract-response-mocker.types"; export abstract class ResponseMocker { - private interceptor: nock.Interceptor; private scope: nock.Scope; private responses: Response[]; + private headers: Header; private path: string | RegExp; private query?: DataMatcherMap; private requestBody?: DataMatcherMap; private method: string; + private baseUrl: string; + private allowUnmocked: boolean; constructor( baseUrl: string, @@ -18,13 +20,23 @@ export abstract class ResponseMocker { requestBody?: DataMatcherMap, allowUnmocked = false ) { + this.baseUrl = baseUrl; + this.allowUnmocked = allowUnmocked; this.scope = nock(baseUrl, { allowUnmocked }); this.responses = []; + this.headers = {} this.path = path; this.query = query; this.requestBody = requestBody; this.method = method; - this.interceptor = this.createInterceptor(); + } + + matchReqHeaders(headers: Header) { + this.headers = {...this.headers, ...headers} + if (Object.keys(this.headers).length > 0) { + this.scope = nock(this.baseUrl, { allowUnmocked: this.allowUnmocked, reqheaders: this.headers }) + } + return this; } setResponse(responses: Response | Response[]) { @@ -37,20 +49,21 @@ export abstract class ResponseMocker { } reply(response?: Response) { + let interceptor = this.createInterceptor(); if (response) { - this.scope = this.interceptor + this.scope = interceptor .times(response.repeat ?? 1) .reply(response.status, response.data as nock.Body, response.headers); - this.interceptor = this.createInterceptor(); } else { this.responses.forEach(res => { - this.scope = this.interceptor + this.scope = interceptor .times(res.repeat ?? 1) .reply(res.status, res.data as nock.Body, res.headers); - this.interceptor = this.createInterceptor(); + interceptor = this.createInterceptor() }); this.responses = []; } + this.headers = {} return this; } diff --git a/src/endpoint-mocker/response/abstract-response-mocker.types.ts b/src/endpoint-mocker/response/abstract-response-mocker.types.ts index 4b3356b..58fdd7e 100644 --- a/src/endpoint-mocker/response/abstract-response-mocker.types.ts +++ b/src/endpoint-mocker/response/abstract-response-mocker.types.ts @@ -1,4 +1,4 @@ -import { ReplyHeaders } from "nock"; +import { ReplyHeaders, RequestHeaderMatcher } from "nock"; export type Response = { status: S; @@ -6,3 +6,7 @@ export type Response = { headers?: ReplyHeaders repeat?: number }; + +export type Header = { + [key: string]: RequestHeaderMatcher +} From 7a109344cb71868e5349f4413025fa70fc61c1e1 Mon Sep 17 00:00:00 2001 From: Shubh Bapna Date: Wed, 8 Mar 2023 14:30:32 -0500 Subject: [PATCH 2/4] added test cases --- test/moctokit/request-response-mocker.test.ts | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/test/moctokit/request-response-mocker.test.ts b/test/moctokit/request-response-mocker.test.ts index efd501b..c160867 100644 --- a/test/moctokit/request-response-mocker.test.ts +++ b/test/moctokit/request-response-mocker.test.ts @@ -180,6 +180,38 @@ describe.each(["get", "post", "delete", "put", "patch"])( expect(status).toBe(200); expect(data).toStrictEqual({ msg: "hello world" }); }); + + test("mock headers", async () => { + const requestMocker = new MoctokitRequestMocker(url, { + path: "/query/{param1}/query", + method: method as EndpointMethod, + parameters: { + path: ["param1"], + query: ["query1", "query2", "query3"], + body: [], + }, + }); + + requestMocker + .request({ + param1: "hello" + } as any) + .matchReqHeaders({ + "authorization": /bearer */, + }) + .reply({ status: 200, data: { msg: "hello world" } } as never); + + const { status, data } = await instance({ + method, + url: "/query/hello/query?query1=hello", + headers: { + authorization: "bearer some_token", + "custom-header": "value" + }, + }); + expect(status).toBe(200); + expect(data).toStrictEqual({ msg: "hello world" }); + }) test("setResponse: singular response", async () => { const requestMocker = new MoctokitRequestMocker(url, { From 74d908829ce1f5d6fa104235f9a374f5e0d79b8f Mon Sep 17 00:00:00 2001 From: Shubh Bapna Date: Wed, 8 Mar 2023 14:34:53 -0500 Subject: [PATCH 3/4] bump version, update readme --- README.md | 14 ++++++++++++-- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 4bc0999..66a051d 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Using this library along with [kiegroup/act-js](https://github.com/kiegroup/act- - [Initialization options](#initialization-options) - [Mock an api](#mock-an-api) - [Mock the entire endpoint](#mock-the-entire-endpoint) - - [Mock an endpoint for specific parameter(s)](#mock-an-endpoint-for-specific-parameters) + - [Mock an endpoint for specific parameter(s) and header(s)](#mock-an-endpoint-for-specific-parameters-and-headers) - [Replying with a response](#replying-with-a-response) - [Reply once](#reply-once) - [Reply N times](#reply-n-times) @@ -81,7 +81,7 @@ moctokit.rest.projects .reply({ status: 200, data: { owner_url: "whatever url" } }); ``` -#### Mock an endpoint for specific parameter(s) +#### Mock an endpoint for specific parameter(s) and header(s) You can mock an endpoint for certain paramters. So only if the call to the api has parameters which match the values you defined it will be get the mocked response. @@ -96,6 +96,16 @@ const moctokit = new Moctokit(); moctokit.rest.projects .createForRepo({ owner: "kie", repo: /d.+/, name: "project" }) .reply({ status: 200, data: { owner_url: "whatever url" } }); + +/** + * Mocks the same api as above but only for requests which match the same parameters as above as well contains the following 2 request headers: + * 1. "custom-header" with value as "value" + * 2. "test-header" with value as any number + */ +moctokit.rest.projects + .createForRepo({ owner: "kie", repo: /d.+/, name: "project" }) + .matchReqHeaders({"custom-header": "value", "test-header": /\d+/}) + .reply({ status: 200, data: { owner_url: "whatever url" } }); ``` ### Replying with a response diff --git a/package-lock.json b/package-lock.json index d7c26c6..8a2b789 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@kie/mock-github", - "version": "1.0.2", + "version": "1.0.3", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@kie/mock-github", - "version": "1.0.2", + "version": "1.0.3", "license": "SEE LICENSE IN LICENSE", "dependencies": { "@octokit/openapi-types-ghec": "^14.0.0", diff --git a/package.json b/package.json index 74bf5e5..36edb77 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@kie/mock-github", - "version": "1.0.2", + "version": "1.0.3", "description": "A bunch of tools to configure and create a local github environment to test your github actions in without having to clutter your github with test repositories, actions or hitting github api rate limits.", "main": "build/src/index.js", "types": "build/src/index.d.ts", From 43e3ae96741c403c972c76a13ca0cc01d2ab1357 Mon Sep 17 00:00:00 2001 From: Shubh Bapna Date: Wed, 8 Mar 2023 14:47:50 -0500 Subject: [PATCH 4/4] lint --- .../response/abstract-response-mocker.ts | 10 +++++----- test/moctokit/request-response-mocker.test.ts | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/endpoint-mocker/response/abstract-response-mocker.ts b/src/endpoint-mocker/response/abstract-response-mocker.ts index 6ee4246..ee19f98 100644 --- a/src/endpoint-mocker/response/abstract-response-mocker.ts +++ b/src/endpoint-mocker/response/abstract-response-mocker.ts @@ -24,7 +24,7 @@ export abstract class ResponseMocker { this.allowUnmocked = allowUnmocked; this.scope = nock(baseUrl, { allowUnmocked }); this.responses = []; - this.headers = {} + this.headers = {}; this.path = path; this.query = query; this.requestBody = requestBody; @@ -32,9 +32,9 @@ export abstract class ResponseMocker { } matchReqHeaders(headers: Header) { - this.headers = {...this.headers, ...headers} + this.headers = {...this.headers, ...headers}; if (Object.keys(this.headers).length > 0) { - this.scope = nock(this.baseUrl, { allowUnmocked: this.allowUnmocked, reqheaders: this.headers }) + this.scope = nock(this.baseUrl, { allowUnmocked: this.allowUnmocked, reqheaders: this.headers }); } return this; } @@ -59,11 +59,11 @@ export abstract class ResponseMocker { this.scope = interceptor .times(res.repeat ?? 1) .reply(res.status, res.data as nock.Body, res.headers); - interceptor = this.createInterceptor() + interceptor = this.createInterceptor(); }); this.responses = []; } - this.headers = {} + this.headers = {}; return this; } diff --git a/test/moctokit/request-response-mocker.test.ts b/test/moctokit/request-response-mocker.test.ts index c160867..3d10f87 100644 --- a/test/moctokit/request-response-mocker.test.ts +++ b/test/moctokit/request-response-mocker.test.ts @@ -211,7 +211,7 @@ describe.each(["get", "post", "delete", "put", "patch"])( }); expect(status).toBe(200); expect(data).toStrictEqual({ msg: "hello world" }); - }) + }); test("setResponse: singular response", async () => { const requestMocker = new MoctokitRequestMocker(url, {