@opra/testing
Version:
Opra testing package
81 lines (80 loc) • 2.86 kB
JavaScript
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;
}
}