@eggjs/supertest
Version:
SuperAgent driven library for testing HTTP servers
326 lines • 23.6 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Test = void 0;
const node_util_1 = require("node:util");
const node_http_1 = require("node:http");
const node_tls_1 = require("node:tls");
const node_assert_1 = require("node:assert");
const superagent_1 = require("superagent");
const AssertError_js_1 = require("./error/AssertError.js");
class Test extends superagent_1.Request {
app;
_server;
_asserts = [];
/**
* Initialize a new `Test` with the given `app`,
* request `method` and `path`.
*/
constructor(app, method, path) {
super(method.toUpperCase(), path);
this.redirects(0);
this.buffer();
this.app = app;
this.url = typeof app === 'string'
? app + path
: this.serverAddress(app, path);
}
/**
* Returns a URL, extracted from a server.
*
* @return {String} URL address
* @private
*/
serverAddress(app, path) {
const addr = app.address();
if (!addr) {
this._server = app.listen(0);
}
const port = app.address().port;
const protocol = (app instanceof node_tls_1.Server || this._server instanceof node_tls_1.Server) ? 'https' : 'http';
return `${protocol}://127.0.0.1:${port}${path}`;
}
/**
* Expectations:
*
* ```js
* .expect(200)
* .expect(200, fn)
* .expect(200, body)
* .expect('Some body')
* .expect('Some body', fn)
* .expect(['json array body', { key: 'val' }])
* .expect('Content-Type', 'application/json')
* .expect('Content-Type', 'application/json', fn)
* .expect(fn)
* .expect([200, 404])
* ```
*
* @return {Test} The current Test instance for chaining.
*/
expect(a, b, c) {
// callback
if (typeof a === 'function') {
// .expect(fn)
this._asserts.push(wrapAssertFn(a));
return this;
}
if (typeof b === 'function') {
// .expect('Some body', fn)
this.end(b);
}
if (typeof c === 'function') {
// .expect('Content-Type', 'application/json', fn)
this.end(c);
}
// status
if (typeof a === 'number') {
this._asserts.push(wrapAssertFn(this._assertStatus.bind(this, a)));
// body
if (typeof b !== 'function' && arguments.length > 1) {
// .expect(200, 'body')
// .expect(200, null)
// .expect(200, 9999999)
this._asserts.push(wrapAssertFn(this._assertBody.bind(this, b)));
}
return this;
}
// multiple statuses
if (Array.isArray(a) && a.length > 0 && a.every(val => typeof val === 'number')) {
// .expect([200, 300])
this._asserts.push(wrapAssertFn(this._assertStatusArray.bind(this, a)));
return this;
}
// header field
if (typeof b === 'string' || typeof b === 'number' || b instanceof RegExp) {
// .expect('Content-Type', 'application/json')
// .expect('Content-Type', /json/)
this._asserts.push(wrapAssertFn(this._assertHeader.bind(this, { name: String(a), value: b })));
return this;
}
// body
// .expect('body')
// .expect(['json array body', { key: 'val' }])
// .expect(/foo/)
this._asserts.push(wrapAssertFn(this._assertBody.bind(this, a)));
return this;
}
/**
* UnExpectations:
*
* .unexpectHeader('Content-Type')
* .unexpectHeader('Content-Type', fn)
*/
unexpectHeader(name, fn) {
if (typeof fn === 'function') {
this.end(fn);
}
// header
if (typeof name === 'string') {
this._asserts.push(this._unexpectHeader.bind(this, name));
}
return this;
}
/**
* Expectations:
*
* .expectHeader('Content-Type')
* .expectHeader('Content-Type', fn)
*/
expectHeader(name, fn) {
if (typeof fn === 'function') {
this.end(fn);
}
// header
if (typeof name === 'string') {
this._asserts.push(this._expectHeader.bind(this, name));
}
return this;
}
_unexpectHeader(name, res) {
const actual = res.headers[name.toLowerCase()];
if (actual) {
return new AssertError_js_1.AssertError('unexpected "' + name + '" header field, got "' + actual + '"', name, actual);
}
}
_expectHeader(name, res) {
const actual = res.headers[name.toLowerCase()];
if (!actual) {
return new AssertError_js_1.AssertError('expected "' + name + '" header field', name, actual);
}
}
/**
* Defer invoking superagent's `.end()` until
* the server is listening.
*/
end(fn) {
const server = this._server;
super.end((err, res) => {
const localAssert = () => {
this.assert(err, res, fn);
};
if (server && '_handle' in server && server._handle) {
return server.close(localAssert);
}
localAssert();
});
return this;
}
/**
* Perform assertions and invoke `fn(err, res)`.
*/
assert(resError, res, fn) {
let errorObj;
// check for unexpected network errors or server not running/reachable errors
// when there is no response and superagent sends back a System Error
// do not check further for other asserts, if any, in such case
// https://nodejs.org/api/errors.html#errors_common_system_errors
const sysErrors = {
ECONNREFUSED: 'Connection refused',
ECONNRESET: 'Connection reset by peer',
EPIPE: 'Broken pipe',
ETIMEDOUT: 'Operation timed out',
};
if (!res && resError) {
if (resError instanceof Error
&& resError.syscall === 'connect'
&& resError.code
&& sysErrors[resError.code]) {
errorObj = new Error(resError.code + ': ' + sysErrors[resError.code]);
}
else {
errorObj = resError;
}
}
// asserts
for (let i = 0; i < this._asserts.length && !errorObj; i += 1) {
errorObj = this._assertFunction(this._asserts[i], res);
}
// set unexpected superagent error if no other error has occurred.
if (!errorObj && resError instanceof Error && (!res || resError.status !== res.status)) {
errorObj = resError;
}
fn.call(this, errorObj || null, res);
}
/**
* Perform assertions on a response body and return an Error upon failure.
*/
_assertBody(body, res) {
const isRegexp = body instanceof RegExp;
// parsed
if (typeof body === 'object' && !isRegexp) {
try {
(0, node_assert_1.deepStrictEqual)(body, res.body);
}
catch (err) {
const a = (0, node_util_1.inspect)(body);
const b = (0, node_util_1.inspect)(res.body);
return new AssertError_js_1.AssertError('expected ' + a + ' response body, got ' + b, body, res.body, { cause: err });
}
}
else if (body !== res.text) {
// string
const a = (0, node_util_1.inspect)(body);
const b = (0, node_util_1.inspect)(res.text);
// regexp
if (isRegexp) {
if (!body.test(res.text)) {
return new AssertError_js_1.AssertError('expected body ' + b + ' to match ' + body, body, res.body);
}
}
else {
return new AssertError_js_1.AssertError('expected ' + a + ' response body, got ' + b, body, res.body);
}
}
}
/**
* Perform assertions on a response header and return an Error upon failure.
*/
_assertHeader(header, res) {
const field = header.name;
const actual = res.header[field.toLowerCase()];
const fieldExpected = header.value;
if (typeof actual === 'undefined') {
return new AssertError_js_1.AssertError('expected "' + field + '" header field', header, actual);
}
// This check handles header values that may be a String or single element Array
if ((Array.isArray(actual) && actual.toString() === fieldExpected)
|| fieldExpected === actual) {
return;
}
if (fieldExpected instanceof RegExp) {
if (!fieldExpected.test(actual)) {
return new AssertError_js_1.AssertError('expected "' + field + '" matching '
+ fieldExpected + ', got "' + actual + '"', header, actual);
}
}
else {
return new AssertError_js_1.AssertError('expected "' + field + '" of "' + fieldExpected + '", got "' + actual + '"', header, actual);
}
}
/**
* Perform assertions on the response status and return an Error upon failure.
*/
_assertStatus(status, res) {
if (res.status !== status) {
const a = node_http_1.STATUS_CODES[status];
const b = node_http_1.STATUS_CODES[res.status];
return new AssertError_js_1.AssertError('expected ' + status + ' "' + a + '", got ' + res.status + ' "' + b + '"', status, res.status);
}
}
/**
* Perform assertions on the response status and return an Error upon failure.
*/
_assertStatusArray(statusArray, res) {
if (!statusArray.includes(res.status)) {
const b = node_http_1.STATUS_CODES[res.status];
const expectedList = statusArray.join(', ');
return new AssertError_js_1.AssertError('expected one of "' + expectedList + '", got ' + res.status + ' "' + b + '"', statusArray, res.status);
}
}
/**
* Performs an assertion by calling a function and return an Error upon failure.
*/
_assertFunction(fn, res) {
let err;
try {
err = fn(res);
}
catch (e) {
err = e;
}
if (err instanceof Error) {
return err;
}
}
}
exports.Test = Test;
/**
* Wraps an assert function into another.
* The wrapper function edit the stack trace of any assertion error, prepending a more useful stack to it.
*
* @param {Function} assertFn
* @return {Function} wrapped assert function
*/
function wrapAssertFn(assertFn) {
const savedStack = new Error().stack.split('\n').slice(3);
return (res) => {
let badStack;
let err;
try {
err = assertFn(res);
}
catch (e) {
err = e;
}
if (err instanceof Error && err.stack) {
badStack = err.stack.replace(err.message, '').split('\n').slice(1);
err.stack = [err.toString()]
.concat(savedStack)
.concat('----')
.concat(badStack)
.join('\n');
}
return err;
};
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHlDQUFvQztBQUNwQyx5Q0FBeUM7QUFDekMsdUNBQWlEO0FBRWpELDZDQUE4QztBQUM5QywyQ0FBb0Q7QUFDcEQsMkRBQXFEO0FBWXJELE1BQWEsSUFBSyxTQUFRLG9CQUFPO0lBQy9CLEdBQUcsQ0FBa0I7SUFDckIsT0FBTyxDQUFTO0lBQ2hCLFFBQVEsR0FBcUIsRUFBRSxDQUFDO0lBRWhDOzs7T0FHRztJQUNILFlBQVksR0FBb0IsRUFBRSxNQUFjLEVBQUUsSUFBWTtRQUM1RCxLQUFLLENBQUMsTUFBTSxDQUFDLFdBQVcsRUFBRSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBRWxDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDbEIsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQ2QsSUFBSSxDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUM7UUFDZixJQUFJLENBQUMsR0FBRyxHQUFHLE9BQU8sR0FBRyxLQUFLLFFBQVE7WUFDaEMsQ0FBQyxDQUFDLEdBQUcsR0FBRyxJQUFJO1lBQ1osQ0FBQyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ3BDLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNPLGFBQWEsQ0FBQyxHQUFXLEVBQUUsSUFBWTtRQUMvQyxNQUFNLElBQUksR0FBRyxHQUFHLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDM0IsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ1YsSUFBSSxDQUFDLE9BQU8sR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQy9CLENBQUM7UUFDRCxNQUFNLElBQUksR0FBSSxHQUFHLENBQUMsT0FBTyxFQUFrQixDQUFDLElBQUksQ0FBQztRQUNqRCxNQUFNLFFBQVEsR0FBRyxDQUFD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