Files
3dverse-testtask/vendor/deno.land/x/oak@v12.1.0/testing.ts
T

180 lines
4.5 KiB
TypeScript

// Copyright 2018-2022 the oak authors. All rights reserved. MIT license.
// deno-lint-ignore-file no-explicit-any
/**
* A collection of utility APIs which can make testing of an oak application
* easier.
*
* @module
*/
import type { Application, State } from "./application.ts";
import { accepts, createHttpError, SecureCookieMap } from "./deps.ts";
import type { RouteParams, RouterContext } from "./router.ts";
import type { ErrorStatus } from "./types.d.ts";
import { Request } from "./request.ts";
import { Response } from "./response.ts";
/** Creates a mock of `Application`. */
export function createMockApp<
S extends Record<string | number | symbol, any> = Record<string, any>,
>(
state = {} as S,
): Application<S> {
const app = {
state,
use() {
return app;
},
[Symbol.for("Deno.customInspect")]() {
return "MockApplication {}";
},
[Symbol.for("nodejs.util.inspect.custom")](
depth: number,
options: any,
inspect: (value: unknown, options?: unknown) => string,
) {
if (depth < 0) {
return options.stylize(`[MockApplication]`, "special");
}
const newOptions = Object.assign({}, options, {
depth: options.depth === null ? null : options.depth - 1,
});
return `${options.stylize("MockApplication", "special")} ${
inspect({}, newOptions)
}`;
},
} as any;
return app;
}
/** Options that can be set in a mock context. */
export interface MockContextOptions<
R extends string,
P extends RouteParams<R> = RouteParams<R>,
S extends State = Record<string, any>,
> {
app?: Application<S>;
ip?: string;
method?: string;
params?: P;
path?: string;
state?: S;
headers?: [string, string][];
}
/** Allows external parties to modify the context state. */
export const mockContextState = {
/** Adjusts the return value of the `acceptedEncodings` in the context's
* `request` object. */
encodingsAccepted: "identity",
};
/** Create a mock of `Context` or `RouterContext`. */
export function createMockContext<
R extends string,
P extends RouteParams<R> = RouteParams<R>,
S extends State = Record<string, any>,
>(
{
ip = "127.0.0.1",
method = "GET",
params,
path = "/",
state,
app = createMockApp(state),
headers: requestHeaders,
}: MockContextOptions<R> = {},
) {
function createMockRequest(): Request {
const headers = new Headers(requestHeaders);
return {
accepts(...types: string[]) {
if (!headers.has("Accept")) {
return;
}
if (types.length) {
return accepts({ headers }, ...types);
}
return accepts({ headers });
},
acceptsEncodings() {
return mockContextState.encodingsAccepted;
},
headers,
ip,
method,
path,
search: undefined,
searchParams: new URLSearchParams(),
url: new URL(path, "http://localhost/"),
} as any;
}
const request = createMockRequest();
const response = new Response(request);
const cookies = new SecureCookieMap(request, { response });
return ({
app,
params,
request,
cookies,
response,
state: Object.assign({}, app.state),
assert(
condition: any,
errorStatus: ErrorStatus = 500,
message?: string,
props?: Record<string, unknown>,
): asserts condition {
if (condition) {
return;
}
const err = createHttpError(errorStatus, message);
if (props) {
Object.assign(err, props);
}
throw err;
},
throw(
errorStatus: ErrorStatus,
message?: string,
props?: Record<string, unknown>,
): never {
const err = createHttpError(errorStatus, message);
if (props) {
Object.assign(err, props);
}
throw err;
},
[Symbol.for("Deno.customInspect")]() {
return `MockContext {}`;
},
[Symbol.for("nodejs.util.inspect.custom")](
depth: number,
options: any,
inspect: (value: unknown, options?: unknown) => string,
) {
if (depth < 0) {
return options.stylize(`[MockContext]`, "special");
}
const newOptions = Object.assign({}, options, {
depth: options.depth === null ? null : options.depth - 1,
});
return `${options.stylize("MockContext", "special")} ${
inspect({}, newOptions)
}`;
},
} as unknown) as RouterContext<R, P, S>;
}
/** Creates a mock `next()` function which can be used when calling
* middleware. */
export function createMockNext() {
return async function next() {};
}