Created
February 21, 2025 11:55
-
-
Save jrmmendes/8e561858d0861158f948364e77f5ced8 to your computer and use it in GitHub Desktop.
Nock inspired http mocker
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { HttpMockClientBuilder } from "./testing/http-mock-client-builder.ts"; | |
import { TestDataBuilder } from "./testing/test-data-builder.ts"; | |
const builder = new TestDataBuilder<{ id: string; name: string }>({ | |
id: () => "123", | |
name: () => "Mendes", | |
}); | |
const client = new HttpMockClientBuilder() | |
.get("/") | |
.headers({ authorization: "access-token" }) | |
.query({ personCode: 123 }) | |
.reply(200, builder.build()) | |
.build(); | |
try { | |
const response = await client.get({ | |
url: "/", | |
headers: { | |
authorization: "access-token", | |
}, | |
method: "GET", | |
params: { | |
personCode: 123, | |
}, | |
}); | |
console.log(response.data); | |
} catch (e) { | |
console.log('error', e); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { HttpMockClient } from "./http-mock-client.ts"; | |
import type { MockElement } from "./types.ts"; | |
export class HttpMockClientBuilder { | |
mocks: MockElement[] = []; | |
currentMock: Partial<MockElement> = {}; | |
headers(headers: Record<string, string>) { | |
this.currentMock.headers = headers; | |
return this; | |
} | |
query<T extends Record<string, unknown>>(params: T) { | |
this.currentMock.params = params; | |
return this; | |
} | |
method(name: string, url: string = "/") { | |
this.currentMock.url = url; | |
this.currentMock.method = name.toUpperCase(); | |
return this; | |
} | |
get(url?: string) { | |
return this.method("GET", url); | |
} | |
post(url?: string) { | |
return this.method("POST", url); | |
} | |
put(url?: string) { | |
return this.method("PUT", url); | |
} | |
patch(url?: string) { | |
return this.method("PATCH", url); | |
} | |
delete(url?: string) { | |
return this.method("DELETE", url); | |
} | |
reply<T extends object>(status: number, data?: T) { | |
this.currentMock.response = { status, data }; | |
this.saveCurrentMock(); | |
return this; | |
} | |
saveCurrentMock() { | |
if (!this.currentMock.response) { | |
throw Error("Invalid mock value"); | |
} | |
this.mocks.push(this.currentMock as MockElement); | |
this.currentMock = {}; | |
} | |
build(): HttpMockClient { | |
return new HttpMockClient(this.mocks); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import type { | |
HttpClientRequestParams, | |
HttpResponse, | |
MockElement, | |
} from "./types.ts"; | |
export class HttpMockClient { | |
mocks: MockElement[] = []; | |
constructor(mocks: MockElement[] = []) { | |
this.mocks = mocks; | |
} | |
validateStatus(code: number) { | |
return code >= 199 && code <= 499; | |
} | |
getMock<T>({ | |
method, | |
url, | |
params, | |
headers, | |
}: HttpClientRequestParams): HttpResponse<T> | void { | |
const mock = this.mocks.find( | |
(mock) => | |
mock.method === method && | |
mock.url === url && | |
Object.keys(mock.params).reduce( | |
(isParamsMatching, name) => | |
isParamsMatching && mock.params[name] === params?.[name], | |
true, | |
) && | |
Object.keys(mock.headers).reduce( | |
(isHeadersMatching, name) => | |
isHeadersMatching && mock.headers[name] === headers?.[name], | |
true, | |
), | |
); | |
if (mock) return mock.response as HttpResponse<T>; | |
} | |
request<T = unknown>({ | |
url, | |
params, | |
headers, | |
method, | |
}: HttpClientRequestParams): Promise<HttpResponse<T>> { | |
const mock = this.getMock<T>({ url, params, headers, method }) ?? { | |
status: 404, | |
}; | |
return this.validateStatus(mock.status) | |
? Promise.resolve(mock) | |
: Promise.reject(mock); | |
} | |
get<T = unknown>(params: HttpClientRequestParams): Promise<HttpResponse<T>> { | |
return this.request<T>({ ...params, method: "GET" }); | |
} | |
post<T = unknown>(params: HttpClientRequestParams): Promise<HttpResponse<T>> { | |
return this.request<T>({ ...params, method: "POST" }); | |
} | |
put<T = unknown>(params: HttpClientRequestParams): Promise<HttpResponse<T>> { | |
return this.request<T>({ ...params, method: "PUT" }); | |
} | |
patch<T = unknown>( | |
params: HttpClientRequestParams, | |
): Promise<HttpResponse<T>> { | |
return this.request<T>({ ...params, method: "PATCH" }); | |
} | |
delete<T = unknown>( | |
params: HttpClientRequestParams, | |
): Promise<HttpResponse<T>> { | |
return this.request<T>({ ...params, method: "DELETE" }); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export type HttpClientRequestParams = { | |
url: string; | |
method: string; | |
params?: Record<string | symbol, unknown>; | |
headers?: Record<string, string>; | |
}; | |
export type HttpResponse<T = unknown> = { | |
status: number; | |
data?: T; | |
}; | |
export type MockElement = { | |
method: string; | |
url: string; | |
params: Record<string, unknown>; | |
headers: Record<string, string>; | |
response: { | |
status: number; | |
data: unknown; | |
}; | |
}; | |
export type FactoryOrValue<T = unknown> = () => T | T; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment