supertest-fetch
Advanced tools
Comparing version 1.5.0 to 2.0.0
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
var __generator = (this && this.__generator) || function (thisArg, body) { | ||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | ||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | ||
function verb(n) { return function (v) { return step([n, v]); }; } | ||
function step(op) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
if (y = 0, t) op = [op[0] & 2, t.value]; | ||
switch (op[0]) { | ||
case 0: case 1: t = op; break; | ||
case 4: _.label++; return { value: op[1], done: false }; | ||
case 5: _.label++; y = op[1]; op = [0]; continue; | ||
case 7: op = _.ops.pop(); _.trys.pop(); continue; | ||
default: | ||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | ||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | ||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | ||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | ||
if (t[2]) _.ops.pop(); | ||
_.trys.pop(); continue; | ||
} | ||
op = body.call(thisArg, _); | ||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | ||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | ||
} | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
@@ -43,40 +7,19 @@ return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
exports.HeaderAssertion = exports.BodyAssertion = exports.StatusAssertion = void 0; | ||
var assert_1 = __importDefault(require("assert")); | ||
var MAX_SHORT_BODY_LENGTH = 80; | ||
function getBody(response, context) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var _a; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: | ||
if (!(context.body === undefined)) return [3 /*break*/, 2]; | ||
_a = context; | ||
return [4 /*yield*/, response.text()]; | ||
case 1: | ||
_a.body = _b.sent(); | ||
_b.label = 2; | ||
case 2: return [2 /*return*/, context.body]; | ||
} | ||
}); | ||
}); | ||
const node_assert_1 = __importDefault(require("node:assert")); | ||
const MAX_SHORT_BODY_LENGTH = 80; | ||
async function getBody(response, context) { | ||
if (context.body === undefined) { | ||
context.body = await response.text(); | ||
} | ||
return context.body; | ||
} | ||
function getShortBody(response, context) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var body, firstLine; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, getBody(response, context)]; | ||
case 1: | ||
body = _a.sent(); | ||
firstLine = body.split('\n')[0]; | ||
if (firstLine.length > MAX_SHORT_BODY_LENGTH) { | ||
return [2 /*return*/, firstLine.slice(0, MAX_SHORT_BODY_LENGTH) + '...']; | ||
} | ||
else { | ||
return [2 /*return*/, firstLine]; | ||
} | ||
return [2 /*return*/]; | ||
} | ||
}); | ||
}); | ||
async function getShortBody(response, context) { | ||
const body = await getBody(response, context); | ||
const firstLine = body.split('\n')[0]; | ||
if (firstLine.length > MAX_SHORT_BODY_LENGTH) { | ||
return firstLine.slice(0, MAX_SHORT_BODY_LENGTH) + '...'; | ||
} | ||
else { | ||
return firstLine; | ||
} | ||
} | ||
@@ -91,157 +34,127 @@ // throw new assert.AssertionError({ | ||
// }); | ||
var StatusAssertion = /** @class */ (function () { | ||
function StatusAssertion(status, statusText) { | ||
this.type = 'status'; | ||
class StatusAssertion { | ||
type = 'status'; | ||
_code; | ||
_text; | ||
constructor(status, statusText) { | ||
this._code = status; | ||
this._text = statusText; | ||
} | ||
StatusAssertion.prototype.canAdd = function (expected) { | ||
return !('status' in expected) || expected.status === this._code; | ||
}; | ||
StatusAssertion.prototype.execute = function (actual, expected, response, context) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var body, _a, err_1, _b, contentType; | ||
return __generator(this, function (_c) { | ||
switch (_c.label) { | ||
case 0: | ||
expected.status = | ||
typeof this._text === 'string' ? this._code + " - " + this._text : "" + this._code; | ||
actual.status = | ||
typeof this._text === 'string' | ||
? response.status + " - " + response.statusText | ||
: "" + response.status; | ||
if (!(expected.status !== actual.status)) return [3 /*break*/, 7]; | ||
body = void 0; | ||
_c.label = 1; | ||
case 1: | ||
_c.trys.push([1, 3, , 4]); | ||
_a = " (body was: "; | ||
return [4 /*yield*/, getShortBody(response, context)]; | ||
case 2: | ||
body = _a + (_c.sent()) + ")"; | ||
return [3 /*break*/, 4]; | ||
case 3: | ||
err_1 = _c.sent(); | ||
body = ''; | ||
return [3 /*break*/, 4]; | ||
case 4: | ||
if (!!('body' in actual)) return [3 /*break*/, 6]; | ||
_b = actual; | ||
return [4 /*yield*/, getBody(response, context)]; | ||
case 5: | ||
_b.body = _c.sent(); | ||
contentType = response.headers.get('content-type') || ''; | ||
if (contentType.toLowerCase().includes('json')) { | ||
try { | ||
actual.body = JSON.parse(actual.body); | ||
} | ||
catch (_d) { | ||
// Ignore | ||
} | ||
} | ||
_c.label = 6; | ||
case 6: return [2 /*return*/, "have status code " + expected.status + " but was " + actual.status + body]; | ||
case 7: return [2 /*return*/, undefined]; | ||
canAdd(expected) { | ||
return expected && !('status' in expected) || expected.status === this._status_to_string(this._code, this._text); | ||
} | ||
async execute(actual, expected, response, context) { | ||
expected.status = this._status_to_string(this._code, this._text); | ||
actual.status = this._status_to_string(response.status, response.statusText); | ||
if (expected.status !== actual.status) { | ||
let body; | ||
try { | ||
body = ` (body was: ${await getShortBody(response, context)})`; | ||
} | ||
catch (err) { | ||
body = ''; | ||
} | ||
if (!('body' in actual)) { | ||
const body = await getBody(response, context); | ||
actual.body = body; | ||
const contentType = response.headers.get('content-type') || ''; | ||
if (contentType.toLowerCase().includes('json')) { | ||
try { | ||
actual.body = JSON.parse(body); | ||
} | ||
catch { | ||
// Ignore | ||
} | ||
} | ||
}); | ||
}); | ||
}; | ||
return StatusAssertion; | ||
}()); | ||
} | ||
return `have status code ${expected.status} but was ${actual.status}${body}`; | ||
} | ||
return undefined; | ||
} | ||
_status_to_string(status, statusText) { | ||
return typeof this._text === 'string' ? `${status} - ${statusText || ''}` : `${status}`; | ||
} | ||
} | ||
exports.StatusAssertion = StatusAssertion; | ||
var BodyAssertion = /** @class */ (function () { | ||
function BodyAssertion(expected) { | ||
this.type = 'body'; | ||
class BodyAssertion { | ||
type = 'body'; | ||
_expectedBody; | ||
constructor(expected) { | ||
this._expectedBody = expected; | ||
} | ||
BodyAssertion.prototype.canAdd = function (expected) { | ||
canAdd(expected) { | ||
return !('body' in expected) || expected.body === this._expectedBody; | ||
}; | ||
BodyAssertion.prototype.execute = function (actual, expected, response, context) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var message, _a, regex, _b, textBody; | ||
return __generator(this, function (_c) { | ||
switch (_c.label) { | ||
case 0: | ||
if (!(typeof this._expectedBody === 'string')) return [3 /*break*/, 2]; | ||
expected.body = this._expectedBody; | ||
_a = actual; | ||
return [4 /*yield*/, getBody(response, context)]; | ||
case 1: | ||
_a.body = _c.sent(); | ||
if (expected.body !== actual.body) { | ||
message = "have expected body"; | ||
} | ||
return [3 /*break*/, 7]; | ||
case 2: | ||
if (!(this._expectedBody instanceof RegExp)) return [3 /*break*/, 4]; | ||
regex = this._expectedBody; | ||
_b = actual; | ||
return [4 /*yield*/, getBody(response, context)]; | ||
case 3: | ||
_b.body = _c.sent(); | ||
expected.body = !!regex.exec(actual.body) | ||
? actual.body | ||
: "a body with a value that matches " + regex; | ||
if (!!regex.exec(actual.body)) { | ||
expected.body = actual.body; | ||
} | ||
else { | ||
expected.body = "a body with a value that matches " + regex; | ||
message = "have a body with a value that matches " + regex; | ||
} | ||
return [3 /*break*/, 7]; | ||
case 4: | ||
if (!(this._expectedBody && typeof this._expectedBody === 'object')) return [3 /*break*/, 6]; | ||
expected.body = this._expectedBody; | ||
return [4 /*yield*/, getBody(response, context)]; | ||
case 5: | ||
textBody = _c.sent(); | ||
try { | ||
actual.body = JSON.parse(textBody); | ||
try { | ||
assert_1.default.deepStrictEqual(expected.body, actual.body); | ||
} | ||
catch (err) { | ||
message = "have expected JSON body"; | ||
} | ||
} | ||
catch (err) { | ||
actual.body = textBody; | ||
message = "have JSON body but body could not be parsed: " + err.toString(); | ||
} | ||
return [3 /*break*/, 7]; | ||
case 6: | ||
// Expect no body. | ||
actual.headers = actual.headers || {}; | ||
expected.headers = expected.headers || {}; | ||
actual.headers['content-length'] = response.headers.get('content-length'); | ||
expected.headers['content-length'] = null; | ||
actual.headers['transfer-encoding'] = response.headers.get('transfer-encoding'); | ||
expected.headers['transfer-encoding'] = null; | ||
if (actual.headers['content-length'] || actual.headers['transfer-encoding']) { | ||
message = "have no body"; | ||
} | ||
_c.label = 7; | ||
case 7: return [2 /*return*/, message]; | ||
} | ||
async execute(actual, expected, response, context) { | ||
let message; | ||
if (typeof this._expectedBody === 'string') { | ||
expected.body = this._expectedBody; | ||
actual.body = await getBody(response, context); | ||
if (expected.body !== actual.body) { | ||
message = `have expected body`; | ||
} | ||
} | ||
else if (this._expectedBody instanceof RegExp) { | ||
const regex = this._expectedBody; | ||
const body = await getBody(response, context); | ||
actual.body = body; | ||
expected.body = regex.exec(body) | ||
? actual.body | ||
: `a body with a value that matches ${regex}`; | ||
if (regex.exec(body)) { | ||
expected.body = actual.body; | ||
} | ||
else { | ||
expected.body = `a body with a value that matches ${regex}`; | ||
message = `have a body with a value that matches ${regex}`; | ||
} | ||
} | ||
else if (this._expectedBody && typeof this._expectedBody === 'object') { | ||
expected.body = this._expectedBody; | ||
const textBody = await getBody(response, context); | ||
try { | ||
actual.body = JSON.parse(textBody); | ||
try { | ||
node_assert_1.default.deepStrictEqual(expected.body, actual.body); | ||
} | ||
}); | ||
}); | ||
}; | ||
return BodyAssertion; | ||
}()); | ||
catch (err) { | ||
message = `have expected JSON body`; | ||
} | ||
} | ||
catch (err) { | ||
actual.body = textBody; | ||
message = `have JSON body but body could not be parsed: ${err.toString()}`; | ||
} | ||
} | ||
else { | ||
// Expect no body. | ||
actual.headers = actual.headers || {}; | ||
expected.headers = expected.headers || {}; | ||
actual.headers['content-length'] = response.headers.get('content-length'); | ||
expected.headers['content-length'] = null; | ||
actual.headers['transfer-encoding'] = response.headers.get('transfer-encoding'); | ||
expected.headers['transfer-encoding'] = null; | ||
if (actual.headers['content-length'] || actual.headers['transfer-encoding']) { | ||
message = `have no body`; | ||
} | ||
} | ||
return message; | ||
} | ||
} | ||
exports.BodyAssertion = BodyAssertion; | ||
var HeaderAssertion = /** @class */ (function () { | ||
function HeaderAssertion(name, value) { | ||
this.type = 'header'; | ||
class HeaderAssertion { | ||
type = 'header'; | ||
_name; | ||
_value; | ||
constructor(name, value) { | ||
this._name = name; | ||
this._value = value; | ||
} | ||
HeaderAssertion.prototype.canAdd = function () { | ||
canAdd() { | ||
return true; | ||
}; | ||
HeaderAssertion.prototype.execute = function (actual, expected, response) { | ||
} | ||
execute(actual, expected, response) { | ||
actual.headers = actual.headers || {}; | ||
expected.headers = expected.headers || {}; | ||
var result; | ||
let result; | ||
if (this._value === undefined || this._value === null) { | ||
@@ -251,8 +164,8 @@ expected.headers[this._name] = null; | ||
if (expected.headers[this._name] !== actual.headers[this._name]) { | ||
result = "have no header " + this._name + " but has \"" + actual.headers[this._name] + "\""; | ||
result = `have no header ${this._name} but has "${actual.headers[this._name]}"`; | ||
} | ||
} | ||
else if (typeof this._value === 'object' && 'exec' in this._value) { | ||
var regex = this._value; | ||
var headerValue = response.headers.get(this._name); | ||
const regex = this._value; | ||
const headerValue = response.headers.get(this._name); | ||
actual.headers[this._name] = headerValue; | ||
@@ -263,4 +176,4 @@ if (headerValue && !!regex.exec(headerValue)) { | ||
else { | ||
expected.headers[this._name] = "a header that matches " + regex; | ||
result = "a header " + this._name + " which matches " + regex; | ||
expected.headers[this._name] = `a header that matches ${regex}`; | ||
result = `a header ${this._name} which matches ${regex}`; | ||
} | ||
@@ -272,3 +185,3 @@ } | ||
if (expected.headers[this._name] !== actual.headers[this._name]) { | ||
result = "have correct header " + this._name + "\""; | ||
result = `have correct header ${this._name}"`; | ||
} | ||
@@ -280,13 +193,12 @@ } | ||
if (expected.headers[this._name] !== actual.headers[this._name]) { | ||
result = "have correct header " + this._name + "\""; | ||
result = `have correct header ${this._name}"`; | ||
} | ||
} | ||
else { | ||
throw new Error("expectHeader expects a string or array of strings"); | ||
throw new Error(`expectHeader expects a string or array of strings`); | ||
} | ||
return result; | ||
}; | ||
return HeaderAssertion; | ||
}()); | ||
} | ||
} | ||
exports.HeaderAssertion = HeaderAssertion; | ||
//# sourceMappingURL=Assertions.js.map |
@@ -6,12 +6,12 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.makeFetch = exports.fetch = exports.Test = exports.Response = exports.Request = exports.Headers = exports.Body = void 0; | ||
var http_1 = require("http"); | ||
var Server_1 = __importDefault(require("./Server")); | ||
var Test_1 = __importDefault(require("./Test")); | ||
exports.Test = void 0; | ||
exports.default = fetch; | ||
exports.fetch = fetch; | ||
exports.default = fetch; | ||
exports.fetch = fetch; | ||
exports.makeFetch = makeFetch; | ||
const node_http_1 = require("node:http"); | ||
const Server_1 = __importDefault(require("./Server")); | ||
const Test_1 = __importDefault(require("./Test")); | ||
exports.Test = Test_1.default; | ||
var node_fetch_1 = require("node-fetch"); | ||
Object.defineProperty(exports, "Body", { enumerable: true, get: function () { return node_fetch_1.Body; } }); | ||
Object.defineProperty(exports, "Headers", { enumerable: true, get: function () { return node_fetch_1.Headers; } }); | ||
Object.defineProperty(exports, "Request", { enumerable: true, get: function () { return node_fetch_1.Request; } }); | ||
Object.defineProperty(exports, "Response", { enumerable: true, get: function () { return node_fetch_1.Response; } }); | ||
/** | ||
@@ -36,7 +36,5 @@ * Fetch a resource from a server, returns a Test. | ||
} | ||
var pServer = Server_1.default.create(server); | ||
const pServer = Server_1.default.create(server); | ||
return new Test_1.default(pServer, url, init); | ||
} | ||
exports.default = fetch; | ||
exports.fetch = fetch; | ||
/** | ||
@@ -53,5 +51,3 @@ * Creates a `fetch` function for a server. | ||
// if we were given an express app | ||
var server = target && target.route | ||
? (0, http_1.createServer)(target) | ||
: target; | ||
const server = target && 'route' in target ? (0, node_http_1.createServer)(target) : target; | ||
if (!server || !server.listen || !server.address || !server.close) { | ||
@@ -61,7 +57,6 @@ throw new Error('Expected server'); | ||
return function fetch(url, init) { | ||
var pServer = Server_1.default.create(server); | ||
const pServer = Server_1.default.create(server); | ||
return new Test_1.default(pServer, url, init); | ||
}; | ||
} | ||
exports.makeFetch = makeFetch; | ||
//# sourceMappingURL=index.js.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var Server = /** @class */ (function () { | ||
function Server(server, address, started) { | ||
this._startedServer = false; | ||
const node_tls_1 = require("node:tls"); | ||
class Server { | ||
_server; | ||
_startedServer = false; | ||
url; | ||
constructor(server, address, started) { | ||
this._server = server; | ||
this._startedServer = started; | ||
// Check if server is an instance of tls.Server. | ||
var https = 'getTicketKeys' in server; | ||
this.url = (https ? 'https' : 'http') + "://localhost:" + address.port; | ||
const https = server instanceof node_tls_1.Server; | ||
this.url = `${https ? 'https' : 'http'}://localhost:${address.port}`; | ||
} | ||
Server.create = function (server) { | ||
return new Promise(function (resolve, reject) { | ||
var address = server.address(); | ||
static create(server) { | ||
return new Promise((resolve, reject) => { | ||
const address = server.address(); | ||
if (typeof address === 'string') { | ||
throw new Error("Can't use a server listening on a UNIX domain socket: " + address); | ||
throw new Error(`Can't use a server listening on a UNIX domain socket: ${address}`); | ||
} | ||
@@ -21,4 +23,4 @@ if (address !== null) { | ||
} | ||
var errHandler = function (err) { | ||
if (err.code === 'EADDRINUSE') { | ||
const errHandler = (err) => { | ||
if (err && typeof err === 'object' && 'code' in err && err.code === 'EADDRINUSE') { | ||
reject(new Error('Address in use')); | ||
@@ -29,5 +31,5 @@ } | ||
server.once('error', errHandler); | ||
server.once('listening', function () { | ||
server.once('listening', () => { | ||
server.removeListener('error', errHandler); | ||
var address = server.address(); | ||
const address = server.address(); | ||
resolve(new Server(server, address, true)); | ||
@@ -37,11 +39,10 @@ }); | ||
}); | ||
}; | ||
Server.prototype.close = function () { | ||
} | ||
close() { | ||
if (this._startedServer) { | ||
this._server.close(); | ||
} | ||
}; | ||
return Server; | ||
}()); | ||
} | ||
} | ||
exports.default = Server; | ||
//# sourceMappingURL=Server.js.map |
211
lib/Test.js
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
var __generator = (this && this.__generator) || function (thisArg, body) { | ||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | ||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | ||
function verb(n) { return function (v) { return step([n, v]); }; } | ||
function step(op) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
if (y = 0, t) op = [op[0] & 2, t.value]; | ||
switch (op[0]) { | ||
case 0: case 1: t = op; break; | ||
case 4: _.label++; return { value: op[1], done: false }; | ||
case 5: _.label++; y = op[1]; op = [0]; continue; | ||
case 7: op = _.ops.pop(); _.trys.pop(); continue; | ||
default: | ||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | ||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | ||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | ||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | ||
if (t[2]) _.ops.pop(); | ||
_.trys.pop(); continue; | ||
} | ||
op = body.call(thisArg, _); | ||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | ||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | ||
} | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
@@ -61,28 +6,30 @@ return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var assert_1 = __importDefault(require("assert")); | ||
var nodeFetch = __importStar(require("node-fetch")); | ||
var Assertions_1 = require("./Assertions"); | ||
var Test = /** @class */ (function () { | ||
function Test(pServer, url, init) { | ||
this._assertions = []; | ||
const node_assert_1 = __importDefault(require("node:assert")); | ||
const Assertions_1 = require("./Assertions"); | ||
class Test { | ||
_pServer; | ||
_description; | ||
_result; | ||
_assertions = []; | ||
constructor(pServer, url, init) { | ||
this._pServer = pServer; | ||
if (typeof url === 'string') { | ||
var method = ((init && init.method) || 'get').toUpperCase(); | ||
this._description = method + " " + url; | ||
const method = ((init && init.method) || 'get').toUpperCase(); | ||
this._description = `${method} ${url}`; | ||
} | ||
else { | ||
var method = (url.method || (init && init.method) || 'get').toUpperCase(); | ||
this._description = method + " " + url; | ||
const method = (url.method || (init && init.method) || 'get').toUpperCase(); | ||
this._description = `${method} ${url}`; | ||
} | ||
this._result = this._fetchPriv(url, init); | ||
} | ||
Test.prototype._fetchPriv = function (url, init) { | ||
return this._pServer.then(function (server) { | ||
var result; | ||
_fetchPriv(url, init) { | ||
return this._pServer.then((server) => { | ||
let result; | ||
if (typeof url === 'string') { | ||
var requestUrl = server.url + url; | ||
result = nodeFetch.default(requestUrl, init); | ||
const requestUrl = server.url + url; | ||
result = fetch(requestUrl, init); | ||
} | ||
else { | ||
var request = new nodeFetch.Request(server.url + url.url, { | ||
const request = new Request(server.url + url.url, { | ||
method: url.method, | ||
@@ -92,13 +39,9 @@ headers: url.headers, | ||
redirect: url.redirect, | ||
timeout: url.timeout, | ||
compress: url.compress, | ||
size: url.size, | ||
follow: url.follow, | ||
}); | ||
result = nodeFetch.default(request, init); | ||
result = fetch(request, init); | ||
} | ||
return result; | ||
}); | ||
}; | ||
Test.prototype.expect = function (a, b) { | ||
} | ||
expect(a, b) { | ||
if (typeof a === 'number') { | ||
@@ -111,2 +54,5 @@ this.expectStatus(a); | ||
else if (typeof a === 'string' && arguments.length === 2) { | ||
if (!isHeaderValue(b)) { | ||
throw new Error(`Invalid header value: ${b}`); | ||
} | ||
this.expectHeader(a, b); | ||
@@ -118,3 +64,3 @@ } | ||
return this; | ||
}; | ||
} | ||
/** | ||
@@ -126,6 +72,6 @@ * Verify the status code (and optionally the status text) of a response. | ||
*/ | ||
Test.prototype.expectStatus = function (statusCode, statusText) { | ||
expectStatus(statusCode, statusText) { | ||
this._assertions.push(new Assertions_1.StatusAssertion(statusCode, statusText)); | ||
return this; | ||
}; | ||
} | ||
/** | ||
@@ -139,6 +85,6 @@ * Verify the body of a response. | ||
*/ | ||
Test.prototype.expectBody = function (expectedBody) { | ||
expectBody(expectedBody) { | ||
this._assertions.push(new Assertions_1.BodyAssertion(expectedBody)); | ||
return this; | ||
}; | ||
} | ||
/** | ||
@@ -151,44 +97,25 @@ * Verifies a header exists and has the specified value. | ||
*/ | ||
Test.prototype.expectHeader = function (name, value) { | ||
expectHeader(name, value) { | ||
this._assertions.push(new Assertions_1.HeaderAssertion(name, value)); | ||
return this; | ||
}; | ||
Test.prototype.end = function () { | ||
var _this = this; | ||
var expected = {}; | ||
var actual = {}; | ||
var context = {}; | ||
return this._result.then(function (response) { return __awaiter(_this, void 0, void 0, function () { | ||
var server, message, _i, _a, assertion, assertionMessage; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: return [4 /*yield*/, this._pServer]; | ||
case 1: | ||
server = _b.sent(); | ||
server.close(); | ||
_i = 0, _a = this._assertions; | ||
_b.label = 2; | ||
case 2: | ||
if (!(_i < _a.length)) return [3 /*break*/, 5]; | ||
assertion = _a[_i]; | ||
return [4 /*yield*/, assertion.execute(actual, expected, response, context)]; | ||
case 3: | ||
assertionMessage = _b.sent(); | ||
message = message || assertionMessage; | ||
_b.label = 4; | ||
case 4: | ||
_i++; | ||
return [3 /*break*/, 2]; | ||
case 5: | ||
assert_1.default.deepStrictEqual(actual, expected, message ? this._should(message) : undefined); | ||
return [2 /*return*/, response]; | ||
} | ||
}); | ||
}); }, function (err) { | ||
return _this._pServer.then(function (server) { | ||
server.close(); | ||
throw err; | ||
}); | ||
}); | ||
}; | ||
} | ||
end() { | ||
const expected = {}; | ||
const actual = {}; | ||
const context = {}; | ||
return this._result.then(async (response) => { | ||
const server = await this._pServer; | ||
server.close(); | ||
let message; | ||
for (const assertion of this._assertions) { | ||
const assertionMessage = await assertion.execute(actual, expected, response, context); | ||
message = message || assertionMessage; | ||
} | ||
node_assert_1.default.deepStrictEqual(actual, expected, message ? this._should(message) : undefined); | ||
return response; | ||
}, (err) => this._pServer.then((server) => { | ||
server.close(); | ||
throw err; | ||
})); | ||
} | ||
/** | ||
@@ -198,28 +125,24 @@ * Tests are 'thennable', so you can treat them like a Promise and get back | ||
*/ | ||
Test.prototype.then = function (onfulfilled, onrejected) { | ||
then(onfulfilled, onrejected) { | ||
return this.end().then(onfulfilled, onrejected); | ||
}; | ||
Test.prototype._should = function (message) { | ||
return "Request \"" + this._description + "\" should " + message; | ||
}; | ||
} | ||
_should(message) { | ||
return `Request "${this._description}" should ${message}`; | ||
} | ||
/** | ||
* Returns the JSON contents of the response. | ||
*/ | ||
Test.prototype.json = function () { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var response; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, this.end()]; | ||
case 1: | ||
response = _a.sent(); | ||
return [4 /*yield*/, response.json()]; | ||
case 2: return [2 /*return*/, _a.sent()]; | ||
} | ||
}); | ||
}); | ||
}; | ||
return Test; | ||
}()); | ||
async json() { | ||
const response = await this.end(); | ||
return await response.json(); | ||
} | ||
} | ||
exports.default = Test; | ||
function isHeaderValue(v) { | ||
return (v === null || | ||
typeof v === 'string' || | ||
(Array.isArray(v) && v.every((s) => typeof s === 'string')) || | ||
typeof v === 'number' || | ||
v instanceof RegExp); | ||
} | ||
//# sourceMappingURL=Test.js.map |
{ | ||
"name": "supertest-fetch", | ||
"version": "1.5.0", | ||
"version": "2.0.0", | ||
"description": "Supertest with WHATWG fetch like interface.", | ||
"main": "lib/index.js", | ||
"types": "types/index.d.ts", | ||
"engines": { | ||
"node": ">=18.0.0" | ||
}, | ||
"type": "commonjs", | ||
"files": [ | ||
@@ -16,7 +20,5 @@ "lib/**/*", | ||
"clean": "rm -rf dist coverage", | ||
"test:unittest": "tsc -p test && nyc mocha 'test/**/*.@(ts|js)'", | ||
"test:unittest": "tsc -p test && c8 mocha 'test/**/*.@(ts|js)'", | ||
"precommit:unittest": "tsc -p test && mocha --reporter progress 'test/**/*.@(ts|js)'", | ||
"lint": "npm run lint:source && npm run lint:tests", | ||
"lint:source": "tslint -c tslint.json -t stylish 'src/**/*.ts'", | ||
"lint:tests": "tslint -c test/tslint.json -t stylish 'test/**/*.ts'", | ||
"lint": "eslint src test", | ||
"prepare": "husky install && npm run build", | ||
@@ -27,7 +29,8 @@ "prepublishOnly": "npm run build && npm test", | ||
"lint-staged": { | ||
"src/**/*.ts": [ | ||
"tslint -c tslint.json -t stylish" | ||
"**/*.@(ts|tsx)}": [ | ||
"prettier --write", | ||
"eslint" | ||
], | ||
"test/**/*.ts": [ | ||
"tslint -c test/tslint.json -t stylish" | ||
"**/*.@(js|cjs|mjs|jsx)}": [ | ||
"prettier --write" | ||
] | ||
@@ -52,28 +55,26 @@ }, | ||
"devDependencies": { | ||
"@types/chai": "^4.1.7", | ||
"@types/chai-as-promised": "^7.1.0", | ||
"@types/mocha": "^9.0.0", | ||
"@types/node": "^16.0.0", | ||
"@types/pem": "^1.9.6", | ||
"chai": "^4.2.0", | ||
"chai-as-promised": "^7.1.1", | ||
"coveralls": "^3.0.2", | ||
"express": "^4.16.4", | ||
"husky": "^7.0.0", | ||
"lint-staged": "^11.0.0", | ||
"mocha": "^9.1.1", | ||
"nyc": "^15.0.0", | ||
"pem": "^1.14.4", | ||
"prettier": "^2.0.1", | ||
"pretty-quick": "^3.0.0", | ||
"semantic-release": "^18.0.0", | ||
"ts-node": "^10.0.0", | ||
"tslint": "^6.0.0", | ||
"typescript": "^4.0.2" | ||
}, | ||
"dependencies": { | ||
"@types/express": "^4.17.7", | ||
"@types/node-fetch": "^2.3.1", | ||
"node-fetch": "^2.3.0" | ||
"@eslint/js": "^9.5.0", | ||
"@types/chai": "^4.3.8", | ||
"@types/chai-as-promised": "^7.1.6", | ||
"@types/express": "^4.17.19", | ||
"@types/mocha": "^10.0.2", | ||
"@types/node": "^20.14.9", | ||
"@types/pem": "^1.14.2", | ||
"c8": "^10.1.2", | ||
"chai": "^4.4.1", | ||
"chai-as-promised": "^7.1.2", | ||
"coveralls": "^3.1.1", | ||
"eslint": "^8.57.0", | ||
"eslint-plugin-import": "^2.29.1", | ||
"express": "^4.18.2", | ||
"husky": "^9.0.11", | ||
"lint-staged": "^15.2.7", | ||
"mocha": "^10.5.2", | ||
"pem": "^1.14.8", | ||
"prettier": "^3.3.2", | ||
"semantic-release": "^24.0.0", | ||
"ts-node": "^10.9.1", | ||
"typescript": "^5.2.2", | ||
"typescript-eslint": "^7.14.1" | ||
} | ||
} |
@@ -8,3 +8,3 @@ # supertest-fetch | ||
A typescript friendly alternative to Supertest, backed by node-fetch | ||
A typescript friendly alternative to Supertest. Backed by native node fetch implementation so it requires node 18+ version. | ||
@@ -14,7 +14,6 @@ ## What is it? | ||
This is a library heavily influenced by Visionmedia's excellent | ||
[supertest](https://github.com/visionmedia/supertest) library. The advantages | ||
[supertest](https://github.com/visionmedia/supertest) library, but with a [WHATWG Fetch](https://github.github.io/fetch)-like interface. The advantages | ||
of this library are: | ||
- Uses [node-fetch](https://github.com/bitinn/node-fetch) to give you a | ||
[WHATWG Fetch](https://github.github.io/fetch)-like interface. | ||
- Uses native node [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) implementation (support since node v18.0.0). | ||
- Should be instantly familiar to anyone who has used supertest. | ||
@@ -75,5 +74,5 @@ - First class support for promises. | ||
If the `server` passed in is not already listening, each call to `fetch()` will call `listen()` on the server, and close it after each fetch. This will assign a random free port to the server, so you don't need to worry about listening on a well-known port for your tests to work. | ||
If the `server` passed in is not already listening, each call to `fetch()` will call `listen()` on the server, and close it after each request. This will assign a random free port to the server, so you don't need to worry about listening on a well-known port for your tests to work. | ||
If the `server` passed in is an instance of tls.Server, then the returned `fetch` instance will use HTTPS to connect to the server instead of HTTP. Note that it's up to you to appropriately configure the server, supplying a certificate and key, and if you're using a self-signed certificate you'll need to pass an "agent" to the call to `fetch`. See [this example](https://github.com/jwalton/node-supertest-fetch/blob/master/test/https.ts) for details. | ||
If the `server` passed in is an instance of tls.Server, then the returned `fetch` instance will use HTTPS to connect to the server instead of HTTP. Note that it's up to you to appropriately configure the server, supplying a certificate and key, and if you're using a self-signed certificate you'll need to pass an "agent" to the call to `fetch`. See [this example](https://github.com/jwalton/node-supertest-fetch/blob/master/test/httpsTest.ts) for details. | ||
@@ -80,0 +79,0 @@ ### .expectStatus(statusCode[, statusText]) |
@@ -1,2 +0,7 @@ | ||
import * as fetch from 'node-fetch'; | ||
export type HeaderValue = string | string[] | number | RegExp | null; | ||
export interface Results { | ||
status?: string; | ||
body?: string | object; | ||
headers?: Record<string, string | string[] | number | null>; | ||
} | ||
export interface AssertionContext { | ||
@@ -7,4 +12,4 @@ body?: string; | ||
type: string; | ||
canAdd(expected: any): boolean; | ||
execute(actual: any, expected: any, response: fetch.Response, context: AssertionContext): Promise<string | undefined> | string | undefined; | ||
canAdd(expected: Results): boolean; | ||
execute(actual: Results, expected: Results, response: Response, context: AssertionContext): Promise<string | undefined> | string | undefined; | ||
} | ||
@@ -16,4 +21,5 @@ export declare class StatusAssertion implements Assertion { | ||
constructor(status: number, statusText?: string); | ||
canAdd(expected: any): boolean; | ||
execute(actual: any, expected: any, response: fetch.Response, context: AssertionContext): Promise<string | undefined>; | ||
canAdd(expected: Results): boolean; | ||
execute(actual: Results, expected: Results, response: Response, context: AssertionContext): Promise<string | undefined>; | ||
private _status_to_string; | ||
} | ||
@@ -23,5 +29,5 @@ export declare class BodyAssertion implements Assertion { | ||
private _expectedBody; | ||
constructor(expected: any); | ||
canAdd(expected: any): boolean; | ||
execute(actual: any, expected: any, response: fetch.Response, context: AssertionContext): Promise<string | undefined>; | ||
constructor(expected: unknown); | ||
canAdd(expected: Results): boolean; | ||
execute(actual: Results, expected: Results, response: Response, context: AssertionContext): Promise<string | undefined>; | ||
} | ||
@@ -32,5 +38,5 @@ export declare class HeaderAssertion implements Assertion { | ||
private _value; | ||
constructor(name: string, value: string | string[] | number | undefined | RegExp | null); | ||
constructor(name: string, value: HeaderValue); | ||
canAdd(): boolean; | ||
execute(actual: any, expected: any, response: fetch.Response): string | undefined; | ||
execute(actual: Results, expected: Results, response: Response): string | undefined; | ||
} |
@@ -1,9 +0,8 @@ | ||
/// <reference types="node" /> | ||
import { Express } from 'express'; | ||
import { Server as httpServer } from 'http'; | ||
import * as nodeFetch from 'node-fetch'; | ||
import { Server as HttpServer, RequestListener } from 'node:http'; | ||
import Test from './Test'; | ||
export { Body, BodyInit, Headers, HeadersInit as HeaderInit, HeadersInit, Request, RequestCache, RequestContext, RequestCredentials, RequestInfo, RequestInit, RequestMode, RequestRedirect, Response, ResponseInit, ResponseType, } from 'node-fetch'; | ||
export { Test }; | ||
export { fetch }; | ||
export interface IExpressLike extends RequestListener { | ||
route<T extends string>(prefix: T): unknown; | ||
} | ||
/** | ||
@@ -21,4 +20,4 @@ * Fetch a resource from a server, returns a Test. | ||
*/ | ||
export default function fetch(server: httpServer, url: string | nodeFetch.Request, init?: nodeFetch.RequestInit): Test; | ||
export declare type FetchFunction = (url: string | nodeFetch.Request, init?: nodeFetch.RequestInit | undefined) => Test; | ||
export default function fetch(server: HttpServer, url: string | Request, init?: RequestInit): Test; | ||
export type FetchFunction = (url: string | Request, init?: RequestInit | undefined) => Test; | ||
/** | ||
@@ -33,2 +32,2 @@ * Creates a `fetch` function for a server. | ||
*/ | ||
export declare function makeFetch(target: httpServer | Express): FetchFunction; | ||
export declare function makeFetch(target: HttpServer | IExpressLike): FetchFunction; |
@@ -1,3 +0,2 @@ | ||
/// <reference types="node" /> | ||
import * as http from 'http'; | ||
import { Server as HttpServer } from 'node:http'; | ||
export default class Server { | ||
@@ -8,4 +7,4 @@ private readonly _server; | ||
private constructor(); | ||
static create(server: http.Server): Promise<Server>; | ||
static create(server: HttpServer): Promise<Server>; | ||
close(): void; | ||
} |
@@ -1,5 +0,4 @@ | ||
import * as fetch from 'node-fetch'; | ||
import * as nodeFetch from 'node-fetch'; | ||
import Server from './Server'; | ||
export default class Test implements PromiseLike<fetch.Response> { | ||
import { HeaderValue } from './Assertions'; | ||
export default class Test implements PromiseLike<Response> { | ||
private _pServer; | ||
@@ -9,3 +8,3 @@ private _description; | ||
private _assertions; | ||
constructor(pServer: Promise<Server>, url: string | nodeFetch.Request, init?: nodeFetch.RequestInit); | ||
constructor(pServer: Promise<Server>, url: string | Request, init?: RequestInit); | ||
private _fetchPriv; | ||
@@ -18,3 +17,3 @@ /** | ||
*/ | ||
expect(statusCode: number, body?: any): this; | ||
expect(statusCode: number, body?: unknown): this; | ||
/** | ||
@@ -26,3 +25,3 @@ * Verify a header exists. This is an alias for `expectHeader()`. | ||
*/ | ||
expect(header: string, value: string | string[] | number | RegExp): this; | ||
expect(header: string, value: HeaderValue): this; | ||
/** | ||
@@ -35,3 +34,3 @@ * Verify body exists. This is an alias for `expectBody()`. | ||
*/ | ||
expect(body: any): this; | ||
expect(body: unknown): this; | ||
/** | ||
@@ -52,3 +51,3 @@ * Verify the status code (and optionally the status text) of a response. | ||
*/ | ||
expectBody(expectedBody: any): this; | ||
expectBody(expectedBody: unknown): this; | ||
/** | ||
@@ -61,4 +60,4 @@ * Verifies a header exists and has the specified value. | ||
*/ | ||
expectHeader(name: string, value: string | string[] | number | undefined | RegExp | null): this; | ||
end(): Promise<fetch.Response>; | ||
expectHeader(name: string, value: HeaderValue): this; | ||
end(): Promise<Response>; | ||
/** | ||
@@ -68,3 +67,3 @@ * Tests are 'thennable', so you can treat them like a Promise and get back | ||
*/ | ||
then(onfulfilled?: (res: fetch.Response) => any, onrejected?: (err: Error) => any): Promise<any>; | ||
then<TResult1 = Response, TResult2 = never>(onfulfilled?: ((value: Response) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | undefined | null): PromiseLike<TResult1 | TResult2>; | ||
private _should; | ||
@@ -71,0 +70,0 @@ /** |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
0
42695
23
582
120
7
- Removed@types/express@^4.17.7
- Removed@types/node-fetch@^2.3.1
- Removednode-fetch@^2.3.0
- Removed@types/body-parser@1.19.5(transitive)
- Removed@types/connect@3.4.38(transitive)
- Removed@types/express@4.17.21(transitive)
- Removed@types/express-serve-static-core@4.19.6(transitive)
- Removed@types/http-errors@2.0.4(transitive)
- Removed@types/mime@1.3.5(transitive)
- Removed@types/node@22.10.2(transitive)
- Removed@types/node-fetch@2.6.12(transitive)
- Removed@types/qs@6.9.17(transitive)
- Removed@types/range-parser@1.2.7(transitive)
- Removed@types/send@0.17.4(transitive)
- Removed@types/serve-static@1.15.7(transitive)
- Removedasynckit@0.4.0(transitive)
- Removedcombined-stream@1.0.8(transitive)
- Removeddelayed-stream@1.0.0(transitive)
- Removedform-data@4.0.1(transitive)
- Removedmime-db@1.52.0(transitive)
- Removedmime-types@2.1.35(transitive)
- Removednode-fetch@2.7.0(transitive)
- Removedtr46@0.0.3(transitive)
- Removedundici-types@6.20.0(transitive)
- Removedwebidl-conversions@3.0.1(transitive)
- Removedwhatwg-url@5.0.0(transitive)