This commit is contained in:
2026-03-03 15:23:00 +00:00
parent 5e3726de39
commit 8e223bfbec
3689 changed files with 955330 additions and 1011 deletions

21
node_modules/node-mocks-http/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,21 @@
This project is bound by the MIT License (MIT)
Copyright (c) 2012-2014, Howard Abrams and other collaborators
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

295
node_modules/node-mocks-http/README.md generated vendored Normal file
View File

@@ -0,0 +1,295 @@
[![Logo](https://user-images.githubusercontent.com/895071/227720269-37e34019-eba0-4768-80ab-1a4dad043043.png)](https://github.com/eugef/node-mocks-http)
---
[![NPM version][npm-badge]][npm-url]
Mock 'http' objects for testing [Express][express-url], [Next.js][nextjs-url] and [Koa][koa-url] routing functions,
but could be used for testing any [Node.js][node-url] web server applications that have code that requires mockups of the `request` and `response` objects.
## Installation
This project is available as a
[NPM package][npm-url].
```bash
$ npm install node-mocks-http --save-dev
$ npm install @types/node @types/express --save-dev # when using TypeScript
```
or
```bash
$ yarn add node-mocks-http --dev
$ yarn add @types/node @types/express --dev # when using TypeScript
```
After installing the package include the following in your test files:
```js
const httpMocks = require('node-mocks-http');
```
## Usage
Suppose you have the following Express route:
```js
app.get('/user/:id', routeHandler);
```
And you have created a function to handle that route's call:
```js
const routeHandler = function( request, response ) { ... };
```
You can easily test the `routeHandler` function with some code like
this using the testing framework of your choice:
```js
exports['routeHandler - Simple testing'] = function (test) {
const request = httpMocks.createRequest({
method: 'GET',
url: '/user/42',
params: {
id: 42
}
});
const response = httpMocks.createResponse();
routeHandler(request, response);
const data = response._getJSONData(); // short-hand for JSON.parse( response._getData() );
test.equal('Bob Dog', data.name);
test.equal(42, data.age);
test.equal('bob@dog.com', data.email);
test.equal(200, response.statusCode);
test.ok(response._isEndCalled());
test.ok(response._isJSON());
test.ok(response._isUTF8());
test.done();
};
```
### TypeScript typings
The typings for TypeScript are bundled with this project. In particular, the `.createRequest()`, `.createResponse()` and `.createMocks()` methods are typed and are generic. Unless specified explicitly, they will be return an Express-based request/response object:
```ts
it('should handle expressjs requests', () => {
const mockExpressRequest = httpMocks.createRequest({
method: 'GET',
url: '/user/42',
params: {
id: 42
}
});
const mockExpressResponse = httpMocks.createResponse();
routeHandler(request, response);
const data = response._getJSONData();
test.equal('Bob Dog', data.name);
test.equal(42, data.age);
test.equal('bob@dog.com', data.email);
test.equal(200, response.statusCode);
test.ok(response._isEndCalled());
test.ok(response._isJSON());
test.ok(response._isUTF8());
test.done();
});
```
The expected type parameter in the mock request and response expects any type that extends the NodeJS
`http.IncomingRequest` interface or Fetch API `Request` class. This means you can also mock requests
coming from other frameworks too. An example for NextJS request will look like this:
```ts
it('should handle nextjs requests', () => {
const mockExpressRequest = httpMocks.createRequest<NextApiRequest>({
method: 'GET',
url: '/user/42',
params: {
id: 42
}
});
const mockExpressResponse = httpMocks.createResponse<NextApiResponse>();
// ... the rest of the test as above.
});
```
It is also possible to mock requests from the NextJS new AppRouter:
```ts
it('should handle nextjs app reouter requests', () => {
const mockExpressRequest = httpMocks.createRequest<NextRequest>({
method: 'GET',
url: '/user/42',
params: {
id: 42
}
});
const mockExpressResponse = httpMocks.createResponse<NextResponse>();
// ... the rest of the test as above.
});
```
## API
### .createRequest()
```
httpMocks.createRequest(options)
```
Where options is an object hash with any of the following values:
| option | description | default value |
| --------------- | -------------------------------- | ------------- |
| `method` | request HTTP method | 'GET' |
| `url` | request URL | '' |
| `originalUrl` | request original URL | `url` |
| `baseUrl` | request base URL | `url` |
| `path` | request path | '' |
| `params` | object hash with params | {} |
| `session` | object hash with session values | `undefined` |
| `cookies` | object hash with request cookies | {} |
| `socket` | object hash with request socket | {} |
| `signedCookies` | object hash with signed cookies | `undefined` |
| `headers` | object hash with request headers | {} |
| `body` | object hash with body | {} |
| `query` | object hash with query values | {} |
| `files` | object hash with values | {} |
The object returned from this function also supports the [Express request](http://expressjs.com/en/4x/api.html#req) functions ([`.accepts()`](http://expressjs.com/en/4x/api.html#req.accepts), [`.is()`](http://expressjs.com/en/4x/api.html#req.is), [`.get()`](http://expressjs.com/en/4x/api.html#req.get), [`.range()`](http://expressjs.com/en/4x/api.html#req.range), etc.). Please send a PR for any missing functions.
### .createResponse()
```js
httpMocks.createResponse(options);
```
Where options is an object hash with any of the following values:
| option | description | default value |
| ---------------- | ----------------------------------------------- | -------------------- |
| `locals` | object that contains `response` local variables | `{}` |
| `eventEmitter` | event emitter used by `response` object | `mockEventEmitter` |
| `writableStream` | writable stream used by `response` object | `mockWritableStream` |
| `req` | Request object being responded to | null |
> NOTE: The out-of-the-box mock event emitter included with `node-mocks-http` is
> not a functional event emitter and as such does not actually emit events. If you
> wish to test your event handlers you will need to bring your own event emitter.
> Here's an example:
```js
const httpMocks = require('node-mocks-http');
const res = httpMocks.createResponse({
eventEmitter: require('events').EventEmitter
});
// ...
it('should do something', function(done) {
res.on('end', function() {
assert.equal(...);
done();
});
});
// ...
```
> This is an example to send request body and trigger it's 'data' and 'end' events:
```js
const httpMocks = require('node-mocks-http');
const req = httpMocks.createRequest();
const res = httpMocks.createResponse({
eventEmitter: require('events').EventEmitter
});
// ...
it('should do something', function (done) {
res.on('end', function () {
expect(response._getData()).to.equal('data sent in request');
done();
});
route(req, res);
req.send('data sent in request');
});
function route(req, res) {
let data = [];
req.on('data', (chunk) => {
data.push(chunk);
});
req.on('end', () => {
data = Buffer.concat(data);
res.write(data);
res.end();
});
}
// ...
```
### .createMocks()
```js
httpMocks.createMocks(reqOptions, resOptions);
```
Merges `createRequest` and `createResponse`. Passes given options object to each
constructor. Returns an object with properties `req` and `res`.
## Design Decisions
We wanted some simple mocks without a large framework.
We also wanted the mocks to act like the original framework being
mocked, but allow for setting of values before calling and inspecting
of values after calling.
## For Developers
We are looking for more volunteers to bring value to this project,
including the creation of more objects from the
[HTTP module][node-http-module-url].
This project doesn't address all features that must be
mocked, but it is a good start. Feel free to send pull requests,
and a member of the team will be timely in merging them.
If you wish to contribute please read our [Contributing Guidelines](CONTRIBUTING.md).
## Release Notes
Most releases fix bugs with our mocks or add features similar to the
actual `Request` and `Response` objects offered by Node.js and extended
by Express.
See the [Release History](HISTORY.md) for details.
[release-notes]: https://github.com/eugef/node-mocks-http/releases
## License
Licensed under [MIT](LICENSE).
[npm-badge]: https://badge.fury.io/js/node-mocks-http.png
[npm-url]: https://www.npmjs.com/package/node-mocks-http
[express-url]: https://expressjs.com
[nextjs-url]: https://nextjs.org
[koa-url]: https://koajs.com
[node-url]: http://www.nodejs.org
[node-http-module-url]: http://nodejs.org/docs/latest/api/http.html

View File

@@ -0,0 +1,104 @@
const methods = require('methods');
const deprecate = require('depd')('express');
const app = {};
const trustProxyDefaultSymbol = '@@symbol:trust_proxy_default';
app.init = function init() {
this.cache = {};
this.settings = {};
this.engines = {};
this.defaultConfiguration();
};
app.defaultConfiguration = function defaultConfiguration() {
this.enable('x-powered-by');
this.set('etag', 'weak');
const env = process.env.NODE_ENV || 'development';
this.set('env', env);
this.set('query parser', 'extended');
this.set('subdomain offset', 2);
this.set('trust proxy', false);
Object.defineProperty(this.settings, trustProxyDefaultSymbol, {
configurable: true,
value: true
});
this.locals = Object.create(null);
this.mountpath = '/';
this.locals.settings = this.settings;
this.set('jsonp callback name', 'callback');
if (env === 'production') {
this.enable('view cache');
}
Object.defineProperty(this, 'router', {
get() {
throw new Error(
"'app.router' is deprecated!\nPlease see the 3.x to 4.x migration guide for details on how to update your app."
);
}
});
};
app.lazyrouter = () => {};
app.handle = () => {};
app.route = () => {};
app.render = () => {};
app.listen = () => {};
app.use = function use() {
return this;
};
app.engine = function engine() {
return this;
};
app.param = function param() {
return this;
};
app.set = function set(setting, val) {
if (arguments.length === 1) {
return this.settings[setting];
}
this.settings[setting] = val;
return this;
};
app.path = function path() {
return '';
};
app.enabled = function enabled(setting) {
return !!this.set(setting);
};
app.disabled = function disabled(setting) {
return !this.set(setting);
};
app.enable = function enable(setting) {
return this.set(setting, true);
};
app.disable = function disable(setting) {
return this.set(setting, false);
};
methods.forEach((method) => {
app[method] = function httpMethod() {
return this;
};
});
app.all = function all() {
return this;
};
app.del = deprecate.function(app.delete, 'app.del: Use app.delete instead');
module.exports = app;

View File

@@ -0,0 +1,35 @@
const { EventEmitter } = require('events');
const mixin = require('merge-descriptors');
const application = require('./mock-application');
const request = require('./mock-request');
const response = require('../mockResponse');
const expressResponse = {
createResponse: response.createResponse
};
function createApplication() {
const app = function () {};
mixin(app, EventEmitter.prototype, false);
mixin(app, application, false);
app.request = {
__proto__: request,
app
};
app.response = {
__proto__: expressResponse.createResponse(),
app
};
app.init();
return app;
}
module.exports = createApplication;
module.exports.application = application;
module.exports.request = request;
module.exports.response = expressResponse;

View File

@@ -0,0 +1,170 @@
const accepts = require('accepts');
const typeis = require('type-is');
const parseRange = require('range-parser');
const parse = require('parseurl');
const { isIP } = require('net');
const fresh = require('fresh');
const http = require('http');
const defineGetter = require('./utils/define-getter');
const req = {
__proto__: http.IncomingMessage.prototype
};
req.header = function header(name) {
const headerName = name.toLowerCase();
switch (headerName) {
case 'referer':
case 'referrer':
return this.headers.referrer || this.headers.referer;
default:
return this.headers[headerName];
}
};
req.get = req.header;
req.accepts = function acceptTypes(...args) {
const accept = accepts(this);
return accept.types(...args);
};
req.acceptsEncodings = function acceptsEncodings(...args) {
const accept = accepts(this);
return accept.encodings(...args);
};
req.acceptsEncoding = req.acceptsEncodings;
req.acceptsCharsets = function acceptsCharsets(...args) {
const accept = accepts(this);
return accept.charsets(...args);
};
req.acceptsCharset = req.acceptsCharsets;
req.acceptsLanguages = function acceptsLanguages(...args) {
const accept = accepts(this);
return accept.languages(...args);
};
req.acceptsLanguage = req.acceptsLanguages;
req.range = function getRange(size) {
const range = this.get('Range');
if (!range) {
return undefined;
}
return parseRange(size, range);
};
req.param = function param(name, defaultValue) {
const params = this.params || {};
const body = this.body || {};
const query = this.query || {};
if (params[name] !== null && {}.hasOwnProperty.call(params, name)) {
return params[name];
}
if (body[name] !== null) {
return body[name];
}
if (query[name] !== null) {
return query[name];
}
return defaultValue;
};
req.is = function is(...args) {
let types = args;
if (Array.isArray(args[0])) {
types = args[0];
}
return typeis(this, types);
};
defineGetter(req, 'protocol', function protocol() {
let { proto } = this.options;
proto = this.get('X-Forwarded-Proto') || proto;
return proto.split(/\s*,\s*/)[0];
});
defineGetter(req, 'secure', function secure() {
return this.protocol === 'https';
});
defineGetter(req, 'ip', function ip() {
return this.options.ip || '127.0.0.1';
});
defineGetter(req, 'ips', function ips() {
return [this.ip];
});
defineGetter(req, 'subdomains', function subdomains() {
const { hostname } = this;
if (!hostname) {
return [];
}
const offset = this.app.get('subdomain offset');
const domains = !isIP(hostname) ? hostname.split('.').reverse() : [hostname];
return domains.slice(offset);
});
defineGetter(req, 'path', function path() {
return parse(this).pathname;
});
defineGetter(req, 'hostname', function hostname() {
let host = this.get('X-Forwarded-Host');
if (!host) {
host = this.get('Host');
}
if (!host) {
return undefined;
}
const offset = host[0] === '[' ? host.indexOf(']') + 1 : 0;
const index = host.indexOf(':', offset);
return index < 0 ? host.substring(0, index) : host;
});
defineGetter(req, 'host', function host() {
return this.hostname;
});
defineGetter(req, 'fresh', function isFresh() {
const { method } = this;
const { statusCode } = this.res;
if (method !== 'GET' && method !== 'HEAD') {
return false;
}
if ((statusCode >= 200 && statusCode < 300) || statusCode === 304) {
return fresh(this.headers, this.res._headers || {});
}
return false;
});
defineGetter(req, 'stale', function stale() {
return !this.fresh;
});
defineGetter(req, 'xhr', function xhr() {
const val = this.get('X-Requested-With') || '';
return val.toLowerCase() === 'xmlhttprequest';
});
module.exports = req;

View File

@@ -0,0 +1,9 @@
function defineGetter(obj, name, getter) {
Object.defineProperty(obj, name, {
configurable: true,
enumerable: true,
get: getter
});
}
module.exports = defineGetter;

137
node_modules/node-mocks-http/lib/headers.js generated vendored Normal file
View File

@@ -0,0 +1,137 @@
/**
* This file implements the Web API Headers interface
* (https://developer.mozilla.org/en-US/docs/Web/API/Headers)
* while maintaining compatibility with Express.js style header access.
*/
const utils = require('./utils');
const REFERER_HEADER_NAMES = ['referer', 'referrer'];
/**
* Get a header value from the headers object.
* Because headers can be set in multiple ways, their names can be uppercased and lowercased.
*
* @param {Object} headers
* @param {string} name
* @returns
*/
function getHeaderValue(headers, name) {
const lowerName = name.toLowerCase();
return headers[
Object.keys(headers).find((key) => {
const lowerKey = key.toLowerCase();
return (
lowerKey === lowerName ||
(REFERER_HEADER_NAMES.includes(lowerKey) && REFERER_HEADER_NAMES.includes(lowerName))
);
})
];
}
/**
* Creates a Headers object that implements both Express.js style access
* and the Web API Headers interface
*
* @param {Object} headers - Initial headers object
* @returns {HeaderWebAPI} - A proxy that implements the HeaderWebAPI interface
*/
function createHeaders(headers = {}) {
return new Proxy(utils.convertKeysToLowerCase(headers), {
get(target, prop) {
// Handle Headers interface methods
switch (prop) {
case 'get':
return (name) => getHeaderValue(target, name);
case 'getAll':
return (name) => {
const value = getHeaderValue(target, name);
if (!value) {
return [];
}
return Array.isArray(value) ? value : [value];
};
case 'has':
return (name) => getHeaderValue(target, name) !== undefined;
case 'set':
return (name, value) => {
// eslint-disable-next-line no-param-reassign
target[name.toLowerCase()] = value;
};
case 'append':
return (name, value) => {
const lowerName = name.toLowerCase();
if (lowerName in target) {
const existingValue = target[lowerName];
if (Array.isArray(existingValue)) {
existingValue.push(value);
} else {
// eslint-disable-next-line no-param-reassign
target[lowerName] = [existingValue, value];
}
} else {
// eslint-disable-next-line no-param-reassign
target[lowerName] = value;
}
};
case 'delete':
return (name) => {
// eslint-disable-next-line no-param-reassign
delete target[name.toLowerCase()];
};
case 'forEach':
return (callback, thisArg) => {
Object.entries(target).forEach(([key, value]) => {
callback.call(thisArg, value, key, target);
});
};
case 'entries':
return () => Object.entries(target)[Symbol.iterator]();
case 'keys':
return () => Object.keys(target)[Symbol.iterator]();
case 'values':
return () => Object.values(target)[Symbol.iterator]();
case Symbol.iterator:
return (
target[Symbol.iterator] ||
function* iterator() {
yield* Object.entries(target);
}
);
default:
return typeof prop === 'string' ? getHeaderValue(target, prop) : target[prop];
}
},
set(target, prop, value) {
if (typeof prop === 'string') {
// eslint-disable-next-line no-param-reassign
target[prop.toLowerCase()] = value;
return true;
}
return false;
},
has(target, prop) {
if (typeof prop === 'string') {
return prop.toLowerCase() in target;
}
return prop in target;
},
deleteProperty(target, prop) {
if (typeof prop === 'string') {
// eslint-disable-next-line no-param-reassign
delete target[prop.toLowerCase()];
return true;
}
// eslint-disable-next-line no-param-reassign
return delete target[prop];
},
ownKeys(target) {
return Object.keys(target);
},
getOwnPropertyDescriptor(target, prop) {
return Object.getOwnPropertyDescriptor(target, prop);
}
});
}
module.exports = { createHeaders, getHeaderValue };

200
node_modules/node-mocks-http/lib/http-mock.d.ts generated vendored Normal file
View File

@@ -0,0 +1,200 @@
import { Request, Response, CookieOptions } from 'express';
import { IncomingMessage, OutgoingMessage } from 'http';
export type RequestType = IncomingMessage | globalThis.Request;
export type ResponseType = OutgoingMessage | globalThis.Response;
export type RequestMethod = 'CONNECT' | 'DELETE' | 'GET' | 'HEAD' | 'OPTIONS' | 'PATCH' | 'POST' | 'PUT' | 'TRACE';
export interface Params {
[key: string]: any;
}
export interface Session {
[key: string]: any;
}
export interface Cookies {
[key: string]: string;
}
export interface Headers {
// Standard HTTP headers
accept?: string;
'accept-language'?: string;
'accept-patch'?: string;
'accept-ranges'?: string;
'access-control-allow-credentials'?: string;
'access-control-allow-headers'?: string;
'access-control-allow-methods'?: string;
'access-control-allow-origin'?: string;
'access-control-expose-headers'?: string;
'access-control-max-age'?: string;
age?: string;
allow?: string;
'alt-svc'?: string;
authorization?: string;
'cache-control'?: string;
connection?: string;
'content-disposition'?: string;
'content-encoding'?: string;
'content-language'?: string;
'content-length'?: string;
'content-location'?: string;
'content-range'?: string;
'content-type'?: string;
cookie?: string;
date?: string;
expect?: string;
expires?: string;
forwarded?: string;
from?: string;
host?: string;
'if-match'?: string;
'if-modified-since'?: string;
'if-none-match'?: string;
'if-unmodified-since'?: string;
'last-modified'?: string;
location?: string;
pragma?: string;
'proxy-authenticate'?: string;
'proxy-authorization'?: string;
'public-key-pins'?: string;
range?: string;
referer?: string;
'retry-after'?: string;
'set-cookie'?: string[];
'strict-transport-security'?: string;
tk?: string;
trailer?: string;
'transfer-encoding'?: string;
upgrade?: string;
'user-agent'?: string;
vary?: string;
via?: string;
warning?: string;
'www-authenticate'?: string;
// Support for arbitrary headers
[header: string]: string | string[] | undefined;
}
/**
* HeaderWebAPI interface combines the existing Headers type with
* standard Web API Headers interface methods for better compatibility
* with browser environments.
*/
export interface HeaderWebAPI {
// Include all the header properties
[header: string]: any; // 'any' to accommodate both header values and methods
// Web API Headers methods
append(name: string, value: string): void;
delete(name: string): void;
get(name: string): string | null;
has(name: string): boolean;
set(name: string, value: string): void;
forEach(callbackfn: (value: string, key: string, parent: HeaderWebAPI) => void, thisArg?: any): void;
// Iterator methods
entries(): IterableIterator<[string, string]>;
keys(): IterableIterator<string>;
values(): IterableIterator<string>;
[Symbol.iterator](): IterableIterator<[string, string]>;
}
export interface Query {
[key: string]: any;
}
export interface Files {
[key: string]: string;
}
export interface Body {
[key: string]: any;
}
export interface RequestOptions {
method?: RequestMethod;
url?: string;
originalUrl?: string;
baseUrl?: string;
path?: string;
params?: Params;
session?: Session;
cookies?: Cookies;
signedCookies?: Cookies;
headers?: Headers;
body?: Body;
query?: Query;
files?: Files;
ip?: string;
// Support custom properties appended on Request objects.
[key: string]: any;
}
export type MockRequest<T extends RequestType> = T & {
_setParameter: (key: string, value?: string) => void;
_setSessionVariable: (variable: string, value?: string) => void;
_setCookiesVariable: (variable: string, value?: string) => void;
_setSignedCookiesVariable: (variable: string, value?: string) => void;
_setHeadersCookiesVariable: (variable: string, value: string) => void;
_setFilesCookiesVariable: (variable: string, value?: string) => void;
_setMethod: (method?: string) => void;
_setURL: (value?: string) => void;
_setOriginalUrl: (value?: string) => void;
_setBody: (body?: Body) => void;
_addBody: (key: string, value?: any) => void;
headers: HeaderWebAPI;
// Support custom properties appended on Request objects.
[key: string]: any;
};
export interface ResponseOptions {
eventEmitter?: any;
writableStream?: any;
req?: any;
locals?: any;
}
export type ResponseCookie = {
value: any;
options: CookieOptions;
};
export type MockResponse<T extends ResponseType> = T & {
_isEndCalled: () => boolean;
_getHeaders: () => HeaderWebAPI;
_getData: () => any;
_getJSONData: () => any;
_getBuffer: () => Buffer;
_getLocals: () => any;
_getStatusCode: () => number;
_getStatusMessage: () => string;
_isJSON: () => boolean;
_isUTF8: () => boolean;
_isDataLengthValid: () => boolean;
_getRedirectUrl: () => string;
_getRenderData: () => any;
_getRenderView: () => string;
cookies: { [name: string]: ResponseCookie };
};
export function createRequest<T extends RequestType = Request>(options?: RequestOptions): MockRequest<T>;
export function createResponse<T extends ResponseType = Response>(options?: ResponseOptions): MockResponse<T>;
export interface Mocks<T1 extends RequestType, T2 extends ResponseType> {
req: MockRequest<T1>;
res: MockResponse<T2>;
}
export function createMocks<T1 extends RequestType = Request, T2 extends ResponseType = Response>(
reqOptions?: RequestOptions,
resOptions?: ResponseOptions
): Mocks<T1, T2>;

32
node_modules/node-mocks-http/lib/http-mock.js generated vendored Normal file
View File

@@ -0,0 +1,32 @@
/**
* Module: http-mock
*
* The interface for this entire module that just exposes the exported
* functions from the other libraries.
*/
const request = require('./mockRequest');
const response = require('./mockResponse');
const express = require('./express/mock-express');
/**
* Creates linked req and res objects. Enables using methods that require both
* objects to interact, for example res.format.
*
* @param {Object} reqOpts Options for req creation, see
* @mockRequest.createRequest
* @param {Object} resOpts Options for res creation, see
* @mockResponse.createResponse
* @return {Object} Object with both mocks: { req, res }
*/
const createRequestResponse = function (reqOpts, resOpts) {
const req = request.createRequest(reqOpts);
const res = response.createResponse({ ...resOpts, req });
return { req, res };
};
exports.createRequest = request.createRequest;
exports.createResponse = response.createResponse;
exports.createMocks = createRequestResponse;
exports.express = express;

19
node_modules/node-mocks-http/lib/mockEventEmitter.js generated vendored Normal file
View File

@@ -0,0 +1,19 @@
/*
* http://nodejs.org/api/events.html
*/
function EventEmitter() {}
EventEmitter.prototype.addListener = () => {};
EventEmitter.prototype.on = () => {};
EventEmitter.prototype.once = () => {};
EventEmitter.prototype.removeListener = () => {};
EventEmitter.prototype.removeAllListeners = () => {};
// EventEmitter.prototype.removeAllListeners = function([event])
EventEmitter.prototype.setMaxListeners = () => {};
EventEmitter.prototype.listeners = () => {};
EventEmitter.prototype.emit = () => {};
EventEmitter.prototype.prependListener = () => {};
// EventEmitter.prototype.emit = function(event, [arg1], [arg2], [...]){}
module.exports = EventEmitter;

650
node_modules/node-mocks-http/lib/mockRequest.js generated vendored Normal file
View File

@@ -0,0 +1,650 @@
/**
* File: mockRequest
*
* This file implements node.js's implementation of a 'request' object.
* This is actually closer to what Express offers the user, in that the
* body is really a parsed object of values.
*
* @author Howard Abrams <howard.abrams@gmail.com>
*/
/**
* Function: createRequest
*
* Creates a new mock 'request' instance. All values are reset to the
* defaults.
*
* Parameters:
*
* options - An object of named parameters.
*
* Options:
*
* method - The method value, see <mockRequest._setMethod>
* url - The url value, see <mockRequest._setURL>
* originalUrl - The originalUrl value, see <mockRequest._setOriginalUrl>
* baseUrl - The baseUrl value, see <mockRequest._setBaseUrl>
* params - The parameters, see <mockRequest._setParam>
* body - The body values, , see <mockRequest._setBody>
*/
const url = require('url');
const typeis = require('type-is');
const accepts = require('accepts');
const parseRange = require('range-parser');
let { EventEmitter } = require('events');
const querystring = require('querystring');
const { createHeaders, getHeaderValue } = require('./headers');
const standardRequestOptions = [
'method',
'url',
'originalUrl',
'baseUrl',
'path',
'params',
'session',
'cookies',
'headers',
'body',
'query',
'files'
];
function createRequest(options = {}) {
if (options.eventEmitter) {
EventEmitter = options.eventEmitter;
}
// create mockRequest
const mockRequest = Object.create(EventEmitter.prototype);
EventEmitter.call(mockRequest);
mockRequest.method = options.method ? options.method : 'GET';
mockRequest.url = options.url || options.path || '';
mockRequest.originalUrl = options.originalUrl || mockRequest.url;
mockRequest.baseUrl = options.baseUrl || mockRequest.url;
mockRequest.path = options.path || (options.url ? url.parse(options.url).pathname : '');
mockRequest.params = options.params ? options.params : {};
if (options.session) {
mockRequest.session = options.session;
}
mockRequest.cookies = options.cookies ? options.cookies : {};
if (options.signedCookies) {
mockRequest.signedCookies = options.signedCookies;
}
// Create headers using the Headers.js module
mockRequest.headers = createHeaders(options.headers);
mockRequest.body = options.body ? options.body : {};
mockRequest.query = options.query ? options.query : {};
mockRequest.files = options.files ? options.files : {};
mockRequest.socket = options.socket ? options.socket : {};
mockRequest.ip = options.ip || '127.0.0.1';
mockRequest.ips = [mockRequest.ip];
mockRequest.destroy = () => {};
// parse query string from url to object
if (Object.keys(mockRequest.query).length === 0) {
mockRequest.query = querystring.parse(mockRequest.url.split('?')[1]);
if (!mockRequest.query.hasOwnProperty) {
Object.defineProperty(mockRequest.query, 'hasOwnProperty', {
enumerable: false,
value: Object.hasOwnProperty.bind(mockRequest.query)
});
}
}
// attach any other provided objects into the request for more advanced testing
for (const n in options) {
if (standardRequestOptions.indexOf(n) === -1) {
mockRequest[n] = options[n];
}
}
/**
* Return request header.
*
* The `Referrer` header field is special-cased,
* both `Referrer` and `Referer` are interchangeable.
*
* Examples:
*
* mockRequest.get('Content-Type');
* // => "text/plain"
*
* mockRequest.get('content-type');
* // => "text/plain"
*
* mockRequest.get('Something');
* // => undefined
*
* Aliased as `mockRequest.header()`.
*
* @param {String} name
* @return {String}
* @api public
*/
mockRequest.getHeader = function getHeader(name) {
return getHeaderValue(mockRequest.headers, name);
};
mockRequest.header = mockRequest.getHeader;
mockRequest.get = mockRequest.getHeader;
/**
* Function: is
*
* Checks for matching content types in the content-type header.
* Requires a request body, identified by transfer-encoding or content-length headers
*
* Examples:
*
* mockRequest.headers['content-type'] = 'text/html';
* mockRequest.headers['transfer-encoding'] = 'chunked';
* mockRequest.headers['content-length'] = '100';
*
* mockRequest.is('html');
* // => "html"
*
* mockRequest.is('json');
* // => false
*
* mockRequest.is(['json', 'html', 'text']);
* // => "html"
*
* @param {String|String[]} types content type or array of types to match
* @return {String|false|null} Matching content type as string, false if no match, null if request has no body.
* @api public
*/
mockRequest.is = function isContentType(...args) {
let types = args;
if (Array.isArray(args[0])) {
types = args[0];
}
return typeis(mockRequest, types);
};
/**
* Function: accepts
*
* Checks for matching content types in the Accept header.
*
* Examples:
*
* mockRequest.headers['accept'] = 'application/json'
*
* mockRequest.accepts('json');
* // => 'json'
*
* mockRequest.accepts('html');
* // => false
*
* mockRequest.accepts(['html', 'json']);
* // => 'json'
*
* @param {String|String[]} types Mime type(s) to check against
* @return {String|false} Matching type or false if no match.
*/
mockRequest.accepts = function acceptsTypes(types) {
const Accepts = accepts(mockRequest);
return Accepts.type(types);
};
/**
* Check if the given `encoding`s are accepted.
*
* @param {String} ...encoding
* @return {String|Array}
* @public
*/
mockRequest.acceptsEncodings = function acceptsEncodings(...args) {
let encodings = args;
if (Array.isArray(args[0])) {
encodings = args[0];
}
const accept = accepts(mockRequest);
return accept.encodings(encodings);
};
/**
* Check if the given `charset`s are acceptable,
* otherwise you should respond with 406 "Not Acceptable".
*
* @param {String} ...charset
* @return {String|Array}
* @public
*/
mockRequest.acceptsCharsets = function acceptsCharsets(...args) {
let charsets = args;
if (Array.isArray(args[0])) {
charsets = args[0];
}
const accept = accepts(mockRequest);
return accept.charsets(charsets);
};
/**
* Check if the given `lang`s are acceptable,
* otherwise you should respond with 406 "Not Acceptable".
*
* @param {String} ...lang
* @return {String|Array}
* @public
*/
mockRequest.acceptsLanguages = function acceptsLanguages(...args) {
let languages = args;
if (Array.isArray(args[0])) {
languages = args[0];
}
const accept = accepts(mockRequest);
return accept.languages(languages);
};
/**
* Function: range
*
* Parse Range header field, capping to the given `size`.
*
* Unspecified ranges such as "0-" require knowledge of your resource length. In
* the case of a byte range this is of course the total number of bytes. If the
* Range header field is not given `undefined` is returned, `-1` when unsatisfiable,
* and `-2` when syntactically invalid.
*
* When ranges are returned, the array has a "type" property which is the type of
* range that is required (most commonly, "bytes"). Each array element is an object
* with a "start" and "end" property for the portion of the range.
*
* The "combine" option can be set to `true` and overlapping & adjacent ranges
* will be combined into a single range.
*
* NOTE: remember that ranges are inclusive, so for example "Range: users=0-3"
* should respond with 4 users when available, not 3.
*
* @param {number} size
* @param {object} [opts]
* @param {boolean} [opts.combine=false]
* @return {false|number|array}
* @public
*/
mockRequest.range = function isRange(size, opts) {
const range = mockRequest.get('Range');
if (!range) {
return undefined;
}
return parseRange(size, range, opts);
};
/**
* Function: param
*
* Return the value of param name when present.
* Lookup is performed in the following order:
* - req.params
* - req.body
* - req.query
*/
mockRequest.param = function param(parameterName, defaultValue) {
if ({}.hasOwnProperty.call(mockRequest.params, parameterName)) {
return mockRequest.params[parameterName];
}
if ({}.hasOwnProperty.call(mockRequest.body, parameterName)) {
return mockRequest.body[parameterName];
}
if ({}.hasOwnProperty.call(mockRequest.query, parameterName)) {
return mockRequest.query[parameterName];
}
return defaultValue;
};
/**
* Function: _setParameter
*
* Set parameters that the client can then get using the 'params'
* key.
*
* Parameters:
*
* key - The key. For instance, 'bob' would be accessed: request.params.bob
* value - The value to return when accessed.
*/
mockRequest._setParameter = function _setParameter(key, value) {
mockRequest.params[key] = value;
};
/**
* Sets a variable that is stored in the session.
*
* @param variable The variable to store in the session
* @param value The value associated with the variable
*/
mockRequest._setSessionVariable = function _setSessionVariable(variable, value) {
if (typeof mockRequest.session !== 'object') {
mockRequest.session = {};
}
mockRequest.session[variable] = value;
};
/**
* Sets a variable that is stored in the cookies.
*
* @param variable The variable to store in the cookies
* @param value The value associated with the variable
*/
mockRequest._setCookiesVariable = function _setCookiesVariable(variable, value) {
mockRequest.cookies[variable] = value;
};
/**
* Sets a variable that is stored in the signed cookies.
*
* @param variable The variable to store in the signed cookies
* @param value The value associated with the variable
*/
mockRequest._setSignedCookiesVariable = function _setSignedCookiesVariable(variable, value) {
if (typeof mockRequest.signedCookies !== 'object') {
mockRequest.signedCookies = {};
}
mockRequest.signedCookies[variable] = value;
};
/**
* Sets a variable that is stored in the headers.
*
* @param variable The variable to store in the headers
* @param value The value associated with the variable
*/
mockRequest._setHeadersVariable = function _setHeadersVariable(variable, value) {
mockRequest.headers[variable] = value;
};
/**
* Sets a variable that is stored in the files.
*
* @param variable The variable to store in the files
* @param value The value associated with the variable
*/
mockRequest._setFilesVariable = function _setFilesVariable(variable, value) {
mockRequest.files[variable] = value;
};
/**
* Function: _setMethod
*
* Sets the HTTP method that the client gets when the called the 'method'
* property. This defaults to 'GET' if it is not set.
*
* Parameters:
*
* method - The HTTP method, e.g. GET, POST, PUT, DELETE, etc.
*
* Note: We don't validate the string. We just return it.
*/
mockRequest._setMethod = function _setMethod(method) {
mockRequest.method = method;
};
/**
* Function: _setURL
*
* Sets the URL value that the client gets when the called the 'url'
* property.
*
* Parameters:
*
* value - The request path, e.g. /my-route/452
*
* Note: We don't validate the string. We just return it. Typically, these
* do not include hostname, port or that part of the URL.
*/
mockRequest._setURL = function _setURL(value) {
mockRequest.url = value;
};
/**
* Function: _setBaseUrl
*
* Sets the URL value that the client gets when the called the 'baseUrl'
* property.
*
* Parameters:
*
* value - The request base path, e.g. /my-route
*
* Note: We don't validate the string. We just return it. Typically, these
* do not include hostname, port or that part of the URL.
*/
mockRequest._setBaseUrl = function _setBaseUrl(value) {
mockRequest.baseUrl = value;
};
/**
* Function: _setOriginalUrl
*
* Sets the URL value that the client gets when the called the 'originalUrl'
* property.
*
* Parameters:
*
* value - The request path, e.g. /my-route/452
*
* Note: We don't validate the string. We just return it. Typically, these
* do not include hostname, port or that part of the URL.
*/
mockRequest._setOriginalUrl = function _setOriginalUrl(value) {
mockRequest.originalUrl = value;
};
/**
* Function: _setBody
*
* Sets the body that the client gets when the called the 'body'
* parameter. This defaults to 'GET' if it is not set.
*
* Parameters:
*
* body - An object representing the body.
*
* If you expect the 'body' to come from a form, this typically means that
* it would be a flat object of properties and values, as in:
*
* > { name: 'Howard Abrams',
* > age: 522
* > }
*
* If the client is expecting a JSON object through a REST interface, then
* this object could be anything.
*/
mockRequest._setBody = function _setBody(body) {
mockRequest.body = body;
};
/**
* Function: _addBody
*
* Adds another body parameter the client gets when calling the 'body'
* parameter with another property value, e.g. the name of a form element
* that was passed in.
*
* Parameters:
*
* key - The key. For instance, 'bob' would be accessed: request.params.bob
* value - The value to return when accessed.
*/
mockRequest._addBody = function _addBody(key, value) {
mockRequest.body[key] = value;
};
/**
* Function: send
*
* Write data to the request stream which will trigger request's 'data', and 'end' event
*
* Parameters:
*
* data - string, array, object, number, buffer
*/
mockRequest.send = function send(data) {
if (Buffer.isBuffer(data)) {
this.emit('data', data);
} else if (typeof data === 'object' || typeof data === 'number') {
this.emit('data', Buffer.from(JSON.stringify(data)));
} else if (typeof data === 'string') {
this.emit('data', Buffer.from(data));
}
this.emit('end');
};
/**
* Function: hostname
*
* If Hostname is not set explicitly, then derive it from the Host header without port information
*
*/
if (!mockRequest.hostname) {
mockRequest.hostname = (function getHostname() {
if (!mockRequest.headers.host) {
return '';
}
const hostname = mockRequest.headers.host.split(':')[0].split('.');
return hostname.join('.');
})();
}
/**
* Function: subdomains
*
* Subdomains are the dot-separated parts of the host before the main domain of the app.
*
*/
mockRequest.subdomains = (function getSubdomains() {
if (!mockRequest.headers.host) {
return [];
}
const offset = 2;
const subdomains = mockRequest.headers.host.split('.').reverse();
return subdomains.slice(offset);
})();
/**
* Function: asyncIterator
*
* Buffers data, error, end, and close events and yields them in order.
* Unlike stream.Readable, this async iterator implementation will not exit
* early on error or close.
*/
mockRequest[Symbol.asyncIterator] = async function* asyncIterator() {
let ended = false;
let closed = false;
let error = null;
const chunks = [];
let resolvePromise = null;
const promiseExecutor = (resolve) => {
resolvePromise = resolve;
};
const promiseResolver = () => {
if (resolvePromise) {
resolvePromise();
resolvePromise = null;
}
};
const dataEventHandler = (chunk) => {
if (ended || closed || error) {
return;
}
chunks.push(chunk);
promiseResolver();
};
const endEventHandler = () => {
if (ended || closed || error) {
return;
}
ended = true;
promiseResolver();
};
const closeEventHandler = () => {
if (closed || error) {
return;
}
closed = true;
promiseResolver();
};
const errorEventHandler = (err) => {
if (closed || error) {
return;
}
error = err;
promiseResolver();
};
mockRequest.on('data', dataEventHandler);
mockRequest.on('end', endEventHandler);
mockRequest.on('close', closeEventHandler);
mockRequest.on('error', errorEventHandler);
// Emit custom event after entering the loop.
setTimeout(() => {
this.emit('async_iterator');
});
try {
for (;;) {
// eslint-disable-next-line no-await-in-loop
await new Promise(promiseExecutor);
let i = 0;
for (;;) {
if (error) {
throw error;
}
if (closed) {
return;
}
const hasChunks = i < chunks.length;
if (!hasChunks) {
if (ended) {
// End signaled. Bail.
return;
}
// Wait for next push.
break;
}
const chunk = chunks[i];
chunks[i] = undefined;
i += 1;
yield chunk;
}
chunks.length = 0;
}
} finally {
chunks.length = 0;
error = null;
mockRequest.off('data', dataEventHandler);
mockRequest.off('end', endEventHandler);
mockRequest.off('close', closeEventHandler);
mockRequest.off('error', errorEventHandler);
}
};
return mockRequest;
}
module.exports.createRequest = createRequest;

959
node_modules/node-mocks-http/lib/mockResponse.js generated vendored Normal file
View File

@@ -0,0 +1,959 @@
/**
* File: mockResponse
*
* This file implements node.js's implementation of a 'response' object.
* Like all good mocks, the response file that can be called and used in
* place of a real HTTP response object.
*
* @author Howard Abrams <howard.abrams@gmail.com>
*/
/**
* Function: createResponse
*
* Creates a new mock 'response' instance. All values are reset to the
* defaults.
*
* Parameters:
*
* options - An object of named parameters.
*
* Options:
*
* encoding - The default encoding for the response
*/
const mime = require('mime');
const path = require('path');
const contentDisposition = require('content-disposition');
let WritableStream = require('./mockWritableStream');
let EventEmitter = require('./mockEventEmitter');
const http = require('./node/http');
const utils = require('./utils');
const TypedArray = Object.getPrototypeOf(Uint8Array);
function createResponse(options = {}) {
let _endCalled = false;
let _data = '';
let _buffer = Buffer.alloc(0);
const _chunks = [];
let _size = 0;
let _encoding = options.encoding;
let _redirectUrl = '';
let _renderView = '';
let _renderData = {};
if (options.writableStream) {
WritableStream = options.writableStream;
}
if (options.eventEmitter) {
EventEmitter = options.eventEmitter;
}
const writableStream = new WritableStream();
const mockRequest = options.req;
// create mockResponse
const mockResponse = Object.create(EventEmitter.prototype);
EventEmitter.call(mockResponse);
mockResponse._headers = {};
mockResponse.cookies = {};
mockResponse.finished = false;
mockResponse.writableEnded = false;
mockResponse.writableFinished = false;
mockResponse.headersSent = false;
mockResponse.statusCode = 200;
mockResponse.statusMessage = 'OK';
// http://expressjs.com/en/api.html#res.locals
mockResponse.locals = options.locals || {};
mockResponse.cookie = function cookie(name, value, opt) {
mockResponse.cookies[name] = {
value,
options: opt
};
return this;
};
mockResponse.clearCookie = function clearCookie(name, opt) {
const opts = opt || {};
opts.expires = new Date(1);
opts.path = '/';
return this.cookie(name, '', opts);
};
mockResponse.status = function status(code) {
mockResponse.statusCode = code;
return this;
};
/**
* Function: writeHead
*
* The 'writeHead' function from node's HTTP API.
*
* Parameters:
*
* statusCode - A number to send as a the HTTP status
* headers - An object of properties that will be used for
* the HTTP headers.
*/
mockResponse.writeHead = function writeHead(statusCode, statusMessage, headers) {
if (_endCalled) {
throw new Error('The end() method has already been called.');
}
if (mockResponse.headersSent) {
// Node docs: "This method must only be called once on a message"
// but it doesn't error if you do call it after first chunk of body is sent
// so we shouldn't throw here either (although it's a bug in the code).
// We return without updating since in real life it's just possible the double call didn't
// completely corrupt the response (for example not using chunked encoding due to HTTP/1.0 client)
// and in this case the client will see the _original_ headers.
return this;
}
mockResponse.statusCode = statusCode;
// resolve statusMessage and headers as optional
if (Object.prototype.toString.call(statusMessage) === '[object Object]') {
// eslint-disable-next-line no-param-reassign
headers = statusMessage;
// eslint-disable-next-line no-param-reassign
statusMessage = null;
}
if (statusMessage) {
mockResponse.statusMessage = statusMessage;
}
// The headers specified earlier (been set with `mockResponse.setHeader`)
// should not be overwritten but be merged with the headers
// passed into `mockResponse.writeHead`.
if (headers) {
Object.assign(mockResponse._headers, utils.convertKeysToLowerCase(headers));
}
this.headersSent = true;
return this;
};
/**
* The 'send' function from restify's Response API that returns data
* to the client. Can be called multiple times.
*
* @see http://mcavage.me/node-restify/#response-api
*
* @param data The data to return. Must be a string.
*/
mockResponse.send = function send(a, b, c) {
const _formatData = (data) => {
if (typeof data === 'object') {
if (data.statusCode) {
mockResponse.statusCode = data.statusCode;
} else if (data.httpCode) {
mockResponse.statusCode = data.httpCode;
}
if (data.body) {
_data = data.body;
} else {
_data = data;
}
} else {
_data += data ?? '';
}
};
switch (arguments.length) {
case 1:
if (typeof a === 'number') {
mockResponse.statusCode = a;
} else {
_formatData(a);
}
break;
case 2:
if (typeof a === 'number') {
_formatData(b);
mockResponse.statusCode = a;
} else if (typeof b === 'number') {
_formatData(a);
mockResponse.statusCode = b;
console.warn('WARNING: Called send() with deprecated parameter order');
} else {
_formatData(a);
_encoding = b;
}
break;
case 3:
_formatData(a);
mockResponse._headers = utils.convertKeysToLowerCase(b);
mockResponse.statusCode = c;
console.warn('WARNING: Called send() with deprecated three parameters');
break;
default:
break;
}
mockResponse.headersSent = true;
mockResponse.emit('send');
mockResponse.end();
return mockResponse;
};
/**
* Send given HTTP status code.
*
* Sets the response status to `statusCode` and the body of the
* response to the standard description from node's http.STATUS_CODES
* or the statusCode number if no description.
*
* Examples:
*
* mockResponse.sendStatus(200);
*
* @param {number} statusCode
* @api public
*/
mockResponse.sendStatus = function sendStatus(statusCode) {
const body = http.STATUS_CODES[statusCode] || String(statusCode);
mockResponse.statusCode = statusCode;
mockResponse.type('txt');
return mockResponse.send(body);
};
/**
* Function: json
*
* The 'json' function from node's HTTP API that returns JSON
* data to the client.
*
* Parameters:
*
* a - Either a statusCode or string containing JSON payload
* b - Either a statusCode or string containing JSON payload
*
* If not specified, the statusCode defaults to 200.
* Second parameter is optional.
*/
mockResponse.json = function json(a, b) {
mockResponse.setHeader('Content-Type', 'application/json');
if (typeof a !== 'undefined') {
if (typeof a === 'number' && typeof b !== 'undefined') {
mockResponse.statusCode = a;
mockResponse.write(JSON.stringify(b), 'utf8');
} else if (typeof b !== 'undefined' && typeof b === 'number') {
mockResponse.statusCode = b;
mockResponse.write(JSON.stringify(a), 'utf8');
} else {
mockResponse.write(JSON.stringify(a), 'utf8');
}
}
mockResponse.emit('send');
mockResponse.end();
return mockResponse;
};
/**
* Function: jsonp
*
* The 'jsonp' function from node's HTTP API that returns JSON
* data to the client.
*
* Parameters:
*
* a - Either a statusCode or string containing JSON payload
* b - Either a statusCode or string containing JSON payload
*
* If not specified, the statusCode defaults to 200.
* Second parameter is optional.
*/
mockResponse.jsonp = function jsonp(a, b) {
mockResponse.setHeader('Content-Type', 'text/javascript');
if (typeof a !== 'undefined') {
if (typeof a === 'number' && typeof b !== 'undefined') {
mockResponse.statusCode = a;
_data += JSON.stringify(b);
} else if (typeof b !== 'undefined' && typeof b === 'number') {
mockResponse.statusCode = b;
_data += JSON.stringify(a);
} else {
_data += JSON.stringify(a);
}
}
mockResponse.emit('send');
mockResponse.end();
return mockResponse;
};
/**
* Set "Content-Type" response header with `type` through `mime.lookup()`
* when it does not contain "/", or set the Content-Type to `type` otherwise.
*
* Examples:
*
* res.type('.html');
* res.type('html');
* res.type('json');
* res.type('application/json');
* res.type('png');
*
* @param {String} type
* @return {ServerResponse} for chaining
* @api public
*/
mockResponse.contentType = function contentType(type) {
return mockResponse.set('Content-Type', type.indexOf('/') >= 0 ? type : mime.lookup(type));
};
mockResponse.type = mockResponse.contentType;
/**
* Set 'Location' response header.
*
* @see http://expressjs.com/en/api.html#res.location
*
* @param {String} location The location to set in the header.
* @return {ServerResponse} For chaining
*/
mockResponse.location = function setLocation(location) {
return mockResponse.set('Location', location);
};
/**
* Function: write
*
* This function has the same behavior as the 'send' function.
*
* Parameters:
*
* data - The data to return. Must be a string. Appended to
* previous calls to data.
* encoding - Optional encoding value.
*/
mockResponse.write = function write(data, encoding) {
mockResponse.headersSent = true;
if (data instanceof Buffer) {
_chunks.push(data);
_size += data.length;
} else if (data instanceof TypedArray) {
_data += new TextDecoder(encoding).decode(data);
} else {
_data += data;
}
if (encoding) {
_encoding = encoding;
}
};
/**
* Function: getEndArguments
*
* Utility function that parses and names parameters for the various
* mockResponse.end() signatures. Reference:
* https://nodejs.org/api/http.html#http_response_end_data_encoding_callback
*
*/
function getEndArguments(args) {
let data;
let encoding;
let callback;
if (args[0]) {
if (typeof args[0] === 'function') {
callback = args[0];
} else {
data = args[0];
}
}
if (args[1]) {
const type = typeof args[1];
if (type === 'function') {
callback = args[1];
} else if (type === 'string' || args[1] instanceof String) {
encoding = args[1];
}
}
if (args[2] && typeof args[2] === 'function') {
callback = args[2];
}
return { data, encoding, callback };
}
/**
* Function: end
*
* The 'end' function from node's HTTP API that finishes
* the connection request. This must be called.
*
* Signature: response.end([data[, encoding]][, callback])
*
* Parameters:
*
* data - Optional data to return. Must be a string or Buffer instance.
* Appended to previous calls to <send>.
* encoding - Optional encoding value.
* callback - Optional callback function, called once the logic has run
*
*/
mockResponse.end = function end(...endArgs) {
if (_endCalled) {
// Do not emit this event twice.
return;
}
mockResponse.finished = true;
mockResponse.writableEnded = true;
mockResponse.headersSent = true;
_endCalled = true;
const args = getEndArguments(endArgs);
if (args.data) {
if (args.data instanceof Buffer) {
_chunks.push(args.data);
_size += args.data.length;
} else if (args.data instanceof TypedArray) {
_data += new TextDecoder(args.encoding).decode(args.data);
} else {
_data += args.data;
}
}
if (_chunks.length) {
switch (_chunks.length) {
case 1:
_buffer = _chunks[0];
break;
default:
_buffer = Buffer.alloc(_size);
for (let i = 0, pos = 0, l = _chunks.length; i < l; i++) {
const chunk = _chunks[i];
chunk.copy(_buffer, pos);
pos += chunk.length;
}
break;
}
}
if (args.encoding) {
_encoding = args.encoding;
}
mockResponse.emit('end');
mockResponse.writableFinished = true; // Reference: https://nodejs.org/docs/latest-v12.x/api/http.html#http_request_writablefinished
mockResponse.emit('finish');
if (args.callback) {
args.callback();
}
};
/**
* Function: vary
*
* Adds the field/s to the Vary response header
*
* Examples:
*
* res.vary('A-B-Test');
* res.vary(['A-B-Test', 'Known-User']);
*/
mockResponse.vary = function vary(fields) {
const header = mockResponse.getHeader('Vary') || '';
let values = header.length ? header.split(', ') : [];
const uniqueFields = (Array.isArray(fields) ? fields : [fields]).filter((field) => {
const regex = new RegExp(field, 'i');
const matches = values.filter((value) => value.match(regex));
return !matches.length;
});
values = values.concat(uniqueFields);
return mockResponse.setHeader('Vary', values.join(', '));
};
/**
* Set _Content-Disposition_ header to _attachment_ with optional `filename`.
*
* Example:
*
* res.attachment('download.csv')
*
* @param {String} filename
* @return {ServerResponse}
* @api public
*/
mockResponse.attachment = function attachment(filename) {
if (filename) {
mockResponse.type(path.extname(filename));
}
mockResponse.set('Content-Disposition', contentDisposition(filename));
return this;
};
/**
* Append additional header `field` with value `val`.
*
* Example:
*
* res.append('Link', ['<http://localhost/>', '<http://localhost:3000/>']);
* res.append('Set-Cookie', 'foo=bar; Path=/; HttpOnly');
* res.append('Warning', '199 Miscellaneous warning');
*
* @param {String} field
* @param {String|Array} val
* @return {ServerResponse} for chaining
* @api public
*/
mockResponse.append = function append(field, val) {
const prev = mockResponse.get(field);
let value = val;
if (prev) {
// concat the new and prev vals
value = Array.isArray(prev) ? prev.concat(val) : [prev].concat(val);
}
return mockResponse.set(field, value);
};
/**
* Set header `field` to `val`, or pass
* an object of header fields.
*
* Examples:
*
* res.set('Foo', ['bar', 'baz']);
* res.set('Accept', 'application/json');
* res.set({ Accept: 'text/plain', 'X-API-Key': 'tobi' });
*
* Aliased as `mockResponse.header()`.
*
* @param {String|Object|Array} field
* @param {String} val
* @return {ServerResponse} for chaining
* @api public
*/
mockResponse.header = function header(field, val) {
if (arguments.length === 2) {
let value;
if (Array.isArray(val)) {
value = val.map(String);
} else {
value = String(val);
}
mockResponse.setHeader(field, value);
} else if (typeof field === 'string') {
return mockResponse.getHeader(field);
} else {
for (const key in field) {
if ({}.hasOwnProperty.call(field, key)) {
mockResponse.setHeader(key, field[key]);
}
}
}
return mockResponse;
};
mockResponse.set = mockResponse.header;
/**
* Function: getHeaders
*
* Returns a shallow copy of the current outgoing headers.
*/
mockResponse.getHeaders = function getHeaders() {
return JSON.parse(JSON.stringify(mockResponse._headers));
};
/**
* Function: getHeader
* Function: get
*
* Returns a particular header by name.
*/
mockResponse.getHeader = function getHeader(name) {
return mockResponse._headers[name.toLowerCase()];
};
mockResponse.get = mockResponse.getHeader;
/**
* Function: getHeaderNames
*
* Returns an array containing the unique names of the current outgoing headers.
*/
mockResponse.getHeaderNames = function getHeaderNames() {
return Object.keys(mockResponse._headers); // names are already stored in lowercase
};
/**
* Function: hasHeader
*
* Returns `true` if the header identified by `name` is currently set.
*/
mockResponse.hasHeader = function hasHeader(name) {
return name.toLowerCase() in mockResponse._headers;
};
/**
* Function: setHeader
* Function: set
*
* Set a particular header by name.
*/
mockResponse.setHeader = function setHeader(name, value) {
mockResponse._headers[name.toLowerCase()] = value;
return this;
};
/**
* Function: appendHeader
*
* Append a header by name. If a header already exists, the new value is appended to the existing header.
*/
mockResponse.appendHeader = function appendHeader(name, value) {
mockResponse.append(name, value);
return this;
};
/**
* Function: removeHeader
*
* Removes an HTTP header by name.
*/
mockResponse.removeHeader = function removeHeader(name) {
delete mockResponse._headers[name.toLowerCase()];
};
/**
* Function: setEncoding
*
* Sets the encoding for the data. Generally 'utf8'.
*
* Parameters:
*
* encoding - The string representing the encoding value.
*/
mockResponse.setEncoding = function setEncoding(encoding) {
_encoding = encoding;
};
mockResponse.getEncoding = function getEncoding() {
return _encoding;
};
/**
* Function: redirect
*
* Redirect to a url with response code
*/
mockResponse.redirect = function redirect(a, b) {
switch (arguments.length) {
case 1:
mockResponse.statusCode = 302;
_redirectUrl = a;
break;
case 2:
if (typeof a === 'number') {
mockResponse.statusCode = a;
_redirectUrl = b;
}
break;
default:
break;
}
mockResponse.end();
};
/**
* Function: render
*
* Render a view with a callback responding with the
* rendered string.
*/
mockResponse.render = function render(a, b, c) {
_renderView = a;
let data = b;
let done = c;
// support callback function as second arg
if (typeof b === 'function') {
done = b;
data = {};
}
switch (arguments.length) {
case 2:
case 3:
_renderData = data;
break;
default:
break;
}
if (typeof done === 'function') {
done(null, '');
} else {
mockResponse.emit('render');
mockResponse.end();
}
};
/**
* Chooses the correct response function from the given supported types.
* This method requires that the mockResponse object be initialized with a
* mockRequest object reference, otherwise it will throw. @see createMocks.
*
* @param {Object} supported Object with formats to handler functions.
* @return {Object} Whatever handler function returns.
*/
mockResponse.format = function format(supported = {}) {
const types = Object.keys(supported);
if (types.length === 0) {
return mockResponse.sendStatus(406);
}
if (!mockRequest) {
throw new Error(
'Request object unavailable. Use createMocks or pass in a request object in createResponse to use format.'
);
}
const accepted = mockRequest.accepts(types);
if (accepted) {
return supported[accepted]();
}
if (supported.default) {
return supported.default();
}
return mockResponse.sendStatus(406);
};
// WritableStream.writable is not a function
// mockResponse.writable = function() {
// return writableStream.writable.apply(this, arguments);
// };
// mockResponse.end = function(){
// return writableStream.end.apply(this, arguments);
// };
mockResponse.destroy = function destroy(...args) {
return writableStream.destroy.apply(this, args);
};
mockResponse.destroySoon = function destroySoon(...args) {
return writableStream.destroySoon.apply(this, args);
};
// This mock object stores some state as well
// as some test-analysis functions:
/**
* Function: _isEndCalled
*
* Since the <end> function must be called, this function
* returns true if it has been called. False otherwise.
*/
mockResponse._isEndCalled = function _isEndCalled() {
return _endCalled;
};
/**
* Function: _getHeaders
*
* Returns all the headers that were set. This may be an
* empty object, but probably will have "Content-Type" set.
*/
mockResponse._getHeaders = function _getHeaders() {
return mockResponse._headers;
};
/**
* Function: _getLocals
*
* Returns all the locals that were set.
*/
mockResponse._getLocals = function _getLocals() {
return mockResponse.locals;
};
/**
* Function: _getData
*
* The data sent to the user.
*/
mockResponse._getData = function _getData() {
return _data;
};
/**
* Function: _getJSONData
*
* The data sent to the user as JSON.
*/
mockResponse._getJSONData = function _getJSONData() {
return JSON.parse(_data);
};
/**
* Function: _getBuffer
*
* The buffer containing data to be sent to the user.
* Non-empty if Buffers were given in calls to write() and end()
*/
mockResponse._getBuffer = function _getBuffer() {
return _buffer;
};
/**
* Function: _getChunks
*
* The buffer containing data to be sent to the user.
* Non-empty if Buffers were given in calls to write() and end()
*/
mockResponse._getChunks = function _getChunks() {
return _chunks;
};
/**
* Function: _getStatusCode
*
* The status code that was sent to the user.
*/
mockResponse._getStatusCode = function _getStatusCode() {
return mockResponse.statusCode;
};
/**
* Function: _getStatusMessage
*
* The status message that was sent to the user.
*/
mockResponse._getStatusMessage = function _getStatusMessage() {
return mockResponse.statusMessage;
};
/**
* Function: _isJSON
*
* Returns true if the data sent was defined as JSON.
* It doesn't validate the data that was sent.
*/
mockResponse._isJSON = function _isJSON() {
return mockResponse.getHeader('Content-Type') === 'application/json';
};
/**
* Function: _isUTF8
*
* If the encoding was set, and it was set to UTF-8, then
* this function return true. False otherwise.
*
* Returns:
*
* False if the encoding wasn't set and wasn't set to "utf8".
*/
mockResponse._isUTF8 = function _isUTF8() {
if (!_encoding) {
return false;
}
return _encoding === 'utf8';
};
/**
* Function: _isDataLengthValid
*
* If the Content-Length header was set, this will only
* return true if the length is actually the length of the
* data that was set.
*
* Returns:
*
* True if the "Content-Length" header was not
* set. Otherwise, it compares it.
*/
mockResponse._isDataLengthValid = function _isDataLengthValid() {
if (mockResponse.getHeader('Content-Length')) {
return mockResponse.getHeader('Content-Length').toString() === _data.length.toString();
}
return true;
};
/**
* Function: _getRedirectUrl
*
* Return redirect url of redirect method
*
* Returns:
*
* Redirect url
*/
mockResponse._getRedirectUrl = function _getRedirectUrl() {
return _redirectUrl;
};
/**
* Function: _getRenderView
*
* Return render view of render method
*
* Returns:
*
* render view
*/
mockResponse._getRenderView = function _getRenderView() {
return _renderView;
};
/**
* Function: _getRenderData
*
* Return render data of render method
*
* Returns:
*
* render data
*/
mockResponse._getRenderData = function _getRenderData() {
return _renderData;
};
return mockResponse;
}
module.exports.createResponse = createResponse;

23
node_modules/node-mocks-http/lib/mockWritableStream.js generated vendored Normal file
View File

@@ -0,0 +1,23 @@
/*
* http://nodejs.org/api/stream.html#stream_writable_stream
*/
function WritableStream() {}
Object.defineProperty(WritableStream, 'writable', {
configurable: true,
enumerable: true,
get() {
return true;
}
});
// WritableStream.prototype.write = function(string, [encoding], [fd]){}
// WritableStream.prototype.write = function(buffer){}
WritableStream.prototype.end = () => {};
// WritableStream.prototype.end = function(string, encoding){}
// WritableStream.prototype.end = function(buffer){}
WritableStream.prototype.destroy = () => {};
WritableStream.prototype.destroySoon = () => {};
module.exports = WritableStream;

121
node_modules/node-mocks-http/lib/node/_http_incoming.js generated vendored Normal file
View File

@@ -0,0 +1,121 @@
const util = require('util');
const Stream = require('stream');
function readStart() {}
exports.readStart = readStart;
function readStop() {}
exports.readStop = readStop;
function IncomingMessage() {
Stream.Readable.call(this);
this.httpVersionMajor = null;
this.httpVersionMinor = null;
this.httpVersion = null;
this.complete = false;
this.headers = {};
this.rawHeaders = [];
this.trailers = {};
this.rawTrailers = [];
this.readable = true;
this._pendings = [];
this._pendingIndex = 0;
this.upgrade = null;
this.url = '';
this.method = null;
this.statusCode = null;
this.statusMessage = null;
this._consuming = false;
this._dumped = false;
}
util.inherits(IncomingMessage, Stream.Readable);
exports.IncomingMessage = IncomingMessage;
IncomingMessage.prototype.read = () => {};
IncomingMessage.prototype._read = () => {};
IncomingMessage.prototype.destroy = () => {};
IncomingMessage.prototype.setTimeout = function setTimeout(msecs, callback) {
if (callback) {
setTimeout(callback, msecs);
}
};
IncomingMessage.prototype._addHeaderLines = function _addHeaderLines(headers, n) {
if (headers && headers.length) {
let raw;
let dest;
if (this.complete) {
raw = this.rawTrailers;
dest = this.trailers;
} else {
raw = this.rawHeaders;
dest = this.headers;
}
for (let i = 0; i < n; i += 2) {
const k = headers[i];
const v = headers[i + 1];
raw.push(k);
raw.push(v);
this._addHeaderLine(k, v, dest);
}
}
};
IncomingMessage.prototype._addHeaderLine = function _addHeaderLine(field, value, dest) {
const fieldName = field.toLowerCase();
switch (fieldName) {
// Array headers:
case 'set-cookie':
if (!util.isUndefined(dest[fieldName])) {
// eslint-disable-next-line no-param-reassign
dest[fieldName].push(value);
} else {
// eslint-disable-next-line no-param-reassign
dest[fieldName] = [value];
}
break;
case 'content-type':
case 'content-length':
case 'user-agent':
case 'referer':
case 'host':
case 'authorization':
case 'proxy-authorization':
case 'if-modified-since':
case 'if-unmodified-since':
case 'from':
case 'location':
case 'max-forwards':
if (util.isUndefined(dest[fieldName])) {
// eslint-disable-next-line no-param-reassign
dest[fieldName] = value;
}
break;
default:
if (!util.isUndefined(dest[fieldName])) {
// eslint-disable-next-line no-param-reassign
dest[fieldName] += `, ${value}`;
} else {
// eslint-disable-next-line no-param-reassign
dest[fieldName] = value;
}
}
};
IncomingMessage.prototype._dump = function _dump() {
if (!this._dumped) {
this._dumped = true;
}
};

59
node_modules/node-mocks-http/lib/node/_http_server.js generated vendored Normal file
View File

@@ -0,0 +1,59 @@
exports.STATUS_CODES = {
100: 'Continue',
101: 'Switching Protocols',
102: 'Processing',
200: 'OK',
201: 'Created',
202: 'Accepted',
203: 'Non-Authoritative Information',
204: 'No Content',
205: 'Reset Content',
206: 'Partial Content',
207: 'Multi-Status',
300: 'Multiple Choices',
301: 'Moved Permanently',
302: 'Moved Temporarily',
303: 'See Other',
304: 'Not Modified',
305: 'Use Proxy',
307: 'Temporary Redirect',
308: 'Permanent Redirect',
400: 'Bad Request',
401: 'Unauthorized',
402: 'Payment Required',
403: 'Forbidden',
404: 'Not Found',
405: 'Method Not Allowed',
406: 'Not Acceptable',
407: 'Proxy Authentication Required',
408: 'Request Time-out',
409: 'Conflict',
410: 'Gone',
411: 'Length Required',
412: 'Precondition Failed',
413: 'Request Entity Too Large',
414: 'Request-URI Too Large',
415: 'Unsupported Media Type',
416: 'Requested Range Not Satisfiable',
417: 'Expectation Failed',
418: "I'm a teapot",
422: 'Unprocessable Entity',
423: 'Locked',
424: 'Failed Dependency',
425: 'Unordered Collection',
426: 'Upgrade Required',
428: 'Precondition Required',
429: 'Too Many Requests',
431: 'Request Header Fields Too Large',
500: 'Internal Server Error',
501: 'Not Implemented',
502: 'Bad Gateway',
503: 'Service Unavailable',
504: 'Gateway Time-out',
505: 'HTTP Version Not Supported',
506: 'Variant Also Negotiates',
507: 'Insufficient Storage',
509: 'Bandwidth Limit Exceeded',
510: 'Not Extended',
511: 'Network Authentication Required'
};

5
node_modules/node-mocks-http/lib/node/http.js generated vendored Normal file
View File

@@ -0,0 +1,5 @@
const server = require('./_http_server');
exports.IncomingMessage = require('./_http_incoming').IncomingMessage;
exports.STATUS_CODES = server.STATUS_CODES;

9
node_modules/node-mocks-http/lib/utils.js generated vendored Normal file
View File

@@ -0,0 +1,9 @@
module.exports.convertKeysToLowerCase = (map) => {
const newMap = {};
for (const key in map) {
if ({}.hasOwnProperty.call(map, key)) {
newMap[key.toLowerCase()] = map[key];
}
}
return newMap;
};

107
node_modules/node-mocks-http/package.json generated vendored Normal file
View File

@@ -0,0 +1,107 @@
{
"author": "Howard Abrams <howard.abrams@gmail.com> (http://www.github.com/howardabrams)",
"name": "node-mocks-http",
"description": "Mock 'http' objects for testing Express, Next.js and Koa routing functions",
"version": "1.17.2",
"homepage": "https://github.com/eugef/node-mocks-http",
"bugs": {
"url": "https://github.com/eugef/node-mocks-http/issues"
},
"contributors": [
{
"name": "Howard Abrams",
"email": "howard.abrams@gmail.com",
"url": "https://github.com/howardabrams"
},
{
"name": "Johnny Estilles",
"email": "johnny.estilles@agentia.asia",
"url": "https://github.com/JohnnyEstilles"
},
{
"name": "Eugene Fidelin",
"email": "eugene.fidelin@gmail.com",
"url": "https://github.com/eugef"
}
],
"license": "MIT",
"keywords": [
"mock",
"stub",
"dummy",
"nodejs",
"js",
"testing",
"test",
"http",
"http mock"
],
"repository": {
"type": "git",
"url": "git://github.com/eugef/node-mocks-http.git"
},
"main": "./lib/http-mock.js",
"types": "./lib/http-mock.d.ts",
"engines": {
"node": ">=14"
},
"dependencies": {
"accepts": "^1.3.7",
"content-disposition": "^0.5.3",
"depd": "^1.1.0",
"fresh": "^0.5.2",
"merge-descriptors": "^1.0.1",
"methods": "^1.1.2",
"mime": "^1.3.4",
"parseurl": "^1.3.3",
"range-parser": "^1.2.0",
"type-is": "^1.6.18"
},
"peerDependencies": {
"@types/express": "^4.17.21 || ^5.0.0",
"@types/node": "*"
},
"peerDependenciesMeta": {
"@types/express": {
"optional": true
},
"@types/node": {
"optional": true
}
},
"devDependencies": {
"@types/chai": "^4.3.11",
"@types/mocha": "^10.0.6",
"@typescript-eslint/eslint-plugin": "^6.17.0",
"@typescript-eslint/parser": "^6.17.0",
"chai": "^4.2.0",
"eslint": "^8.56.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-import": "^2.29.1",
"husky": "^8.0.3",
"mocha": "^10.2.0",
"nyc": "^15.1.0",
"prettier": "^3.1.1",
"sinon": "^17.0.1",
"sinon-chai": "^3.5.0",
"ts-node": "^10.9.1",
"tsd": "^0.29.0",
"typescript": "^5.3.2"
},
"scripts": {
"test": "mocha",
"coverage": "nyc --reporter=html --reporter=lcov --reporter=text-summary mocha",
"format": "prettier --write --list-different .",
"lint": "eslint --fix .",
"check": "npm run check:format && npm run check:lint && npm run check:types",
"check:format": "prettier --list-different .",
"check:lint": "eslint .",
"check:types": "tsd --files ./test/**/*.test-d.ts .",
"postversion": "npm publish && git push --follow-tags",
"prepare": "husky install"
},
"files": [
"lib"
]
}