|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 |
- import {IncomingHttpHeaders, IncomingMessage, OutgoingHttpHeaders, request, RequestOptions} from 'http';
- import {Method} from '../src/backend/common';
- import {DataSource} from '../src/backend/data-source';
-
- interface ClientParams {
- method: Method;
- path: string;
- headers?: IncomingHttpHeaders;
- body?: unknown;
- }
-
- type ResponseBody = Buffer | string | object;
-
- export interface TestClient {
- (params: ClientParams): Promise<[IncomingMessage, ResponseBody?]>;
- acceptMediaType(mediaType: string): this;
- acceptLanguage(language: string): this;
- acceptCharset(charset: string): this;
- contentType(mediaType: string): this;
- contentCharset(charset: string): this;
- }
-
- export const createTestClient = (options: Omit<RequestOptions, 'method' | 'path'>): TestClient => {
- const additionalHeaders: OutgoingHttpHeaders = {};
- const client = (params: ClientParams) => new Promise<[IncomingMessage, ResponseBody?]>((resolve, reject) => {
- const {
- ...etcAdditionalHeaders
- } = additionalHeaders;
-
- const headers: OutgoingHttpHeaders = {
- ...(options.headers ?? {}),
- ...etcAdditionalHeaders,
- };
-
- let contentTypeHeader: string | undefined;
- if (typeof params.body !== 'undefined') {
- contentTypeHeader = headers['content-type'] = params.headers?.['content-type'] ?? 'application/json';
- }
-
- const req = request({
- ...options,
- method: params.method,
- path: params.path,
- headers,
- });
-
- req.on('response', (res) => {
- res.on('error', (err) => {
- reject(err);
- });
-
- let resBuffer: Buffer | undefined;
- res.on('data', (c) => {
- resBuffer = (
- typeof resBuffer === 'undefined'
- ? Buffer.from(c)
- : Buffer.concat([resBuffer, c])
- );
- });
-
- res.on('close', () => {
- const acceptHeader = Array.isArray(headers['accept']) ? headers['accept'].join('; ') : headers['accept'];
- const contentTypeBase = acceptHeader ?? 'application/octet-stream';
- const [type, subtype] = contentTypeBase.split('/');
- const allSubtypes = subtype.split('+');
- if (typeof resBuffer !== 'undefined') {
- if (allSubtypes.includes('json')) {
- const acceptCharset = (
- Array.isArray(headers['accept-charset'])
- ? headers['accept-charset'].join('; ')
- : headers['accept-charset']
- ) as BufferEncoding | undefined;
- resolve([res, JSON.parse(resBuffer.toString(acceptCharset ?? 'utf-8'))]);
- return;
- }
-
- if (type === 'text') {
- const acceptCharset = (
- Array.isArray(headers['accept-charset'])
- ? headers['accept-charset'].join('; ')
- : headers['accept-charset']
- ) as BufferEncoding | undefined;
- resolve([res, resBuffer.toString(acceptCharset ?? 'utf-8')]);
- return;
- }
-
- resolve([res, resBuffer]);
- return;
- }
-
- resolve([res]);
- });
- });
-
- req.on('error', (err) => {
- reject(err);
- })
-
- if (typeof params.body !== 'undefined') {
- const theContentTypeHeader = Array.isArray(contentTypeHeader) ? contentTypeHeader.join('; ') : contentTypeHeader?.toString();
- const contentTypeAll = theContentTypeHeader ?? 'application/octet-stream';
- const [contentTypeBase, ...contentTypeParams] = contentTypeAll.split(';').map((s) => s.replace(/\s+/g, '').trim());
- const charsetParam = contentTypeParams.find((s) => s.startsWith('charset='));
- const charset = charsetParam?.split('=')?.[1] as BufferEncoding | undefined;
- const [, subtype] = contentTypeBase.split('/');
- const allSubtypes = subtype.split('+');
- req.write(
- allSubtypes.includes('json')
- ? JSON.stringify(params.body)
- : Buffer.from(params.body?.toString() ?? '', contentTypeBase === 'text' ? charset : undefined)
- );
- }
-
- req.end();
- });
-
- client.acceptMediaType = function acceptMediaType(mediaType: string) {
- additionalHeaders['accept'] = mediaType;
- return this;
- };
-
- client.acceptLanguage = function acceptLanguage(language: string) {
- additionalHeaders['accept-language'] = language;
- return this;
- };
-
- client.acceptCharset = function acceptCharset(charset: string) {
- additionalHeaders['accept-charset'] = charset;
- return this;
- };
-
- client.contentType = function contentType(mediaType: string) {
- additionalHeaders['content-type'] = mediaType;
- return this;
- };
-
- client.contentCharset = function contentCharset(charset: string) {
- additionalHeaders['content-type'] = `${additionalHeaders['content-type']}; charset="${charset}"`;
- return this;
- };
-
- return client;
- };
-
- export class DummyError extends Error {}
-
- export class DummyDataSource implements DataSource {
- private resource?: { dataSource?: unknown };
-
- create(): Promise<never> {
- throw new DummyError();
- }
-
- delete(): Promise<never> {
- throw new DummyError();
- }
-
- emplace(): Promise<never> {
- throw new DummyError();
- }
-
- getById(): Promise<never> {
- throw new DummyError();
- }
-
- newId(): Promise<never> {
- throw new DummyError();
- }
-
- getMultiple(): Promise<never> {
- throw new DummyError();
- }
-
- getSingle(): Promise<never> {
- throw new DummyError();
- }
-
- getTotalCount(): Promise<never> {
- throw new DummyError();
- }
-
- async initialize(): Promise<void> {}
-
- patch(): Promise<never> {
- throw new DummyError();
- }
-
- prepareResource(rr: unknown) {
- this.resource = rr as unknown as { dataSource: DummyDataSource };
- this.resource.dataSource = this;
- }
- }
|