UNPKG

@opra/testing

Version:

Opra testing package

81 lines (80 loc) 2.86 kB
import { createServer, IncomingMessage, Server, ServerResponse, } from 'node:http'; import * as path from 'node:path'; import { FetchBackend, HttpResponse } from '@opra/client'; import { ApiExpect } from './api-expect/api-expect.js'; /** * Test specific implementation of {@link FetchBackend} for API testing. * * @class TestBackend */ export class TestBackend extends FetchBackend { _server; /** * Creates a new instance of TestBackend. * * @param app The server or request listener to test. * @param options Configuration options. */ constructor(app, options) { super(options?.basePath ? path.posix.join('http://tempuri.org', options.basePath) : 'http://tempuri.org', options); this._server = app instanceof Server ? app : createServer(app); } /** * Sends the actual HTTP request by starting the server if necessary. * * @param req The request to send. * @returns A promise that resolves to the response. * @protected */ send(req) { return new Promise((resolve, reject) => { const url = new URL(req.url); // Set protocol to HTTP url.protocol = 'http'; // Apply original host to request header if (url.host !== 'opra.test' && req.headers.get('host') == null) req.headers.set('host', url.host); new Promise(subResolve => { if (this._server.listening) subResolve(); else this._server.listen(0, '127.0.0.1', () => subResolve()); }) .then(() => { const address = this._server.address(); url.host = '127.0.0.1'; url.port = address.port.toString(); return fetch(url.toString(), req); }) .then(res => { if (!this._server.listening) return resolve(res); this._server.once('close', () => resolve(res)); this._server.close(); this._server.unref(); }) .then() .catch(error => { if (!this._server.listening) return reject(error); this._server.once('close', () => reject(error)); this._server.close(); this._server.unref(); }); }); } /** * Creates a {@link HttpResponse} instance with an added `expect` property. * * @param init The response initiator parameters. * @returns A new HttpResponse instance with ApiExpect. * @protected */ createResponse(init) { const response = new HttpResponse(init); response.expect = new ApiExpect(response); return response; } }