diff --git a/.eslintrc b/.eslintrc index 7b4549f..6d387d6 100644 --- a/.eslintrc +++ b/.eslintrc @@ -3,6 +3,7 @@ "airbnb-base", "prettier" ], + "parser": "@typescript-eslint/parser", "rules": { "no-underscore-dangle": "off", "no-console": "off", @@ -11,6 +12,14 @@ "warn", "as-needed" ], + "prefer-destructuring": [ + "error", + { + "object": true, + "array": false + } + ], + "no-prototype-builtins": "warn", "no-restricted-syntax": [ "error", { @@ -26,11 +35,13 @@ "overrides": [ { "files": [ - "test/**/*.js" + "test/**/*.js", + "test/**/*.ts" ], "env": { "mocha": true } } - ] + ], + "root": true } \ No newline at end of file diff --git a/gulpfile.js b/gulpfile.js index 03954c2..a3cfa99 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -4,21 +4,17 @@ const istanbul = require('gulp-istanbul'); const files = { src: ['./lib/**/*.js'], - test: ['./test/**/*.spec.js', './*.js'], + test: ['./test/**/*.spec.js', './test/**/*.spec.ts'], testTs: ['./test/**/*.spec.ts'] }; -gulp.task('dot', () => gulp.src(files.test, { read: false }).pipe(mocha({ reporter: 'dot' }))); +gulp.task('dot', () => + gulp.src(files.test, { read: false }).pipe(mocha({ reporter: 'spec', require: 'ts-node/register' })) +); gulp.task('test', gulp.series('dot')); -gulp.task('test:ts', () => - gulp.src(files.testTs, { read: false }).pipe(mocha({ reporter: 'dot', require: 'ts-node/register' })) -); - gulp.task('spec', () => gulp.src(files.test, { read: false }).pipe(mocha({ reporter: 'spec' }))); -gulp.task('spec:ts', () => gulp.src(files.testTs, { read: false }).pipe(mocha({ reporter: 'spec' }))); - gulp.task('coverage', (done) => { gulp.src(files.src) .pipe(istanbul()) diff --git a/lib/express/mock-request.js b/lib/express/mock-request.js index a02e961..d200920 100644 --- a/lib/express/mock-request.js +++ b/lib/express/mock-request.js @@ -135,7 +135,7 @@ defineGetter(req, 'hostname', function hostname() { const offset = host[0] === '[' ? host.indexOf(']') + 1 : 0; const index = host.indexOf(':', offset); - return ~index ? host.substring(0, index) : host; + return index < 0 ? host.substring(0, index) : host; }); defineGetter(req, 'host', function host() { diff --git a/lib/mockRequest.js b/lib/mockRequest.js index 8243d24..428d819 100644 --- a/lib/mockRequest.js +++ b/lib/mockRequest.js @@ -365,8 +365,7 @@ function createRequest(options) { * @param value The value associated with the variable */ mockRequest._setHeadersVariable = function (variable, value) { - variable = variable.toLowerCase(); - mockRequest.headers[variable] = value; + mockRequest.headers[variable.toLowerCase()] = value; }; /** @@ -605,6 +604,7 @@ function createRequest(options) { try { for (;;) { + // eslint-disable-next-line no-await-in-loop await new Promise(promiseExecutor); let i = 0; for (;;) { diff --git a/lib/mockResponse.js b/lib/mockResponse.js index 525eb51..1b87d01 100644 --- a/lib/mockResponse.js +++ b/lib/mockResponse.js @@ -411,7 +411,7 @@ function createResponse(options) { * callback - Optional callback function, called once the logic has run * */ - mockResponse.end = function () { + mockResponse.end = function (...endArgs) { if (_endCalled) { // Do not emit this event twice. return; @@ -423,7 +423,7 @@ function createResponse(options) { _endCalled = true; - const args = getEndArguments(arguments); + const args = getEndArguments(endArgs); if (args.data) { if (args.data instanceof Buffer) { @@ -568,9 +568,10 @@ function createResponse(options) { } else if (typeof field === 'string') { return mockResponse.getHeader(field); } else { - // eslint-disable-line for (const key in field) { - mockResponse.setHeader(key, field[key]); + if ({}.hasOwnProperty.call(field, key)) { + mockResponse.setHeader(key, field[key]); + } } } return mockResponse; @@ -729,8 +730,7 @@ function createResponse(options) { if (!mockRequest) { throw new Error( - 'Request object unavailable. Use createMocks or pass in a ' + - 'request object in createResponse to use format.' + 'Request object unavailable. Use createMocks or pass in a request object in createResponse to use format.' ); } @@ -756,12 +756,12 @@ function createResponse(options) { // return writableStream.end.apply(this, arguments); // }; - mockResponse.destroy = function () { - return writableStream.destroy.apply(this, arguments); + mockResponse.destroy = function (...args) { + return writableStream.destroy.apply(this, args); }; - mockResponse.destroySoon = function () { - return writableStream.destroySoon.apply(this, arguments); + mockResponse.destroySoon = function (...args) { + return writableStream.destroySoon.apply(this, args); }; // This mock object stores some state as well diff --git a/package-lock.json b/package-lock.json index e3c8af1..4eaca7c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,6 +25,8 @@ "@types/express": "^4.17.17", "@types/mocha": "^10.0.6", "@types/node": "^14", + "@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", @@ -538,6 +540,12 @@ "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", "dev": true }, + "node_modules/@types/semver": { + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", + "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", + "dev": true + }, "node_modules/@types/serve-static": { "version": "1.15.1", "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.1.tgz", @@ -548,6 +556,322 @@ "@types/node": "*" } }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.17.0.tgz", + "integrity": "sha512-Vih/4xLXmY7V490dGwBQJTpIZxH4ZFH6eCVmQ4RFkB+wmaCTDAx4dtgoWwMNGKLkqRY1L6rPqzEbjorRnDo4rQ==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.17.0", + "@typescript-eslint/type-utils": "6.17.0", + "@typescript-eslint/utils": "6.17.0", + "@typescript-eslint/visitor-keys": "6.17.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.17.0.tgz", + "integrity": "sha512-C4bBaX2orvhK+LlwrY8oWGmSl4WolCfYm513gEccdWZj0CwGadbIADb0FtVEcI+WzUyjyoBj2JRP8g25E6IB8A==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "6.17.0", + "@typescript-eslint/types": "6.17.0", + "@typescript-eslint/typescript-estree": "6.17.0", + "@typescript-eslint/visitor-keys": "6.17.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.17.0.tgz", + "integrity": "sha512-RX7a8lwgOi7am0k17NUO0+ZmMOX4PpjLtLRgLmT1d3lBYdWH4ssBUbwdmc5pdRX8rXon8v9x8vaoOSpkHfcXGA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.17.0", + "@typescript-eslint/visitor-keys": "6.17.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.17.0.tgz", + "integrity": "sha512-hDXcWmnbtn4P2B37ka3nil3yi3VCQO2QEB9gBiHJmQp5wmyQWqnjA85+ZcE8c4FqnaB6lBwMrPkgd4aBYz3iNg==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "6.17.0", + "@typescript-eslint/utils": "6.17.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@typescript-eslint/types": { + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.17.0.tgz", + "integrity": "sha512-qRKs9tvc3a4RBcL/9PXtKSehI/q8wuU9xYJxe97WFxnzH8NWWtcW3ffNS+EWg8uPvIerhjsEZ+rHtDqOCiH57A==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.17.0.tgz", + "integrity": "sha512-gVQe+SLdNPfjlJn5VNGhlOhrXz4cajwFd5kAgWtZ9dCZf4XJf8xmgCTLIqec7aha3JwgLI2CK6GY1043FRxZwg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.17.0", + "@typescript-eslint/visitor-keys": "6.17.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.17.0.tgz", + "integrity": "sha512-LofsSPjN/ITNkzV47hxas2JCsNCEnGhVvocfyOcLzT9c/tSZE7SfhS/iWtzP1lKNOEfLhRTZz6xqI8N2RzweSQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.17.0", + "@typescript-eslint/types": "6.17.0", + "@typescript-eslint/typescript-estree": "6.17.0", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.17.0.tgz", + "integrity": "sha512-H6VwB/k3IuIeQOyYczyyKN8wH6ed8EwliaYHLxOIhyF0dYEIsN8+Bk3GE19qafeMKyZJJHP8+O1HiFhFLUNKSg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.17.0", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + } + }, "node_modules/@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", @@ -2291,7 +2615,7 @@ }, "node_modules/eslint-config-prettier": { "version": "9.1.0", - "resolved": "https://artifactory.corp.ebay.com/artifactory/api/npm/npm-corp/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", "dev": true, "bin": { @@ -8309,6 +8633,18 @@ "node": ">=8" } }, + "node_modules/ts-api-utils": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", + "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", + "dev": true, + "engines": { + "node": ">=16.13.0" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, "node_modules/ts-node": { "version": "10.9.1", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", @@ -9513,6 +9849,12 @@ "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", "dev": true }, + "@types/semver": { + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", + "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", + "dev": true + }, "@types/serve-static": { "version": "1.15.1", "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.1.tgz", @@ -9523,6 +9865,222 @@ "@types/node": "*" } }, + "@typescript-eslint/eslint-plugin": { + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.17.0.tgz", + "integrity": "sha512-Vih/4xLXmY7V490dGwBQJTpIZxH4ZFH6eCVmQ4RFkB+wmaCTDAx4dtgoWwMNGKLkqRY1L6rPqzEbjorRnDo4rQ==", + "dev": true, + "requires": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.17.0", + "@typescript-eslint/type-utils": "6.17.0", + "@typescript-eslint/utils": "6.17.0", + "@typescript-eslint/visitor-keys": "6.17.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@typescript-eslint/parser": { + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.17.0.tgz", + "integrity": "sha512-C4bBaX2orvhK+LlwrY8oWGmSl4WolCfYm513gEccdWZj0CwGadbIADb0FtVEcI+WzUyjyoBj2JRP8g25E6IB8A==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "6.17.0", + "@typescript-eslint/types": "6.17.0", + "@typescript-eslint/typescript-estree": "6.17.0", + "@typescript-eslint/visitor-keys": "6.17.0", + "debug": "^4.3.4" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "@typescript-eslint/scope-manager": { + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.17.0.tgz", + "integrity": "sha512-RX7a8lwgOi7am0k17NUO0+ZmMOX4PpjLtLRgLmT1d3lBYdWH4ssBUbwdmc5pdRX8rXon8v9x8vaoOSpkHfcXGA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.17.0", + "@typescript-eslint/visitor-keys": "6.17.0" + } + }, + "@typescript-eslint/type-utils": { + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.17.0.tgz", + "integrity": "sha512-hDXcWmnbtn4P2B37ka3nil3yi3VCQO2QEB9gBiHJmQp5wmyQWqnjA85+ZcE8c4FqnaB6lBwMrPkgd4aBYz3iNg==", + "dev": true, + "requires": { + "@typescript-eslint/typescript-estree": "6.17.0", + "@typescript-eslint/utils": "6.17.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "@typescript-eslint/types": { + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.17.0.tgz", + "integrity": "sha512-qRKs9tvc3a4RBcL/9PXtKSehI/q8wuU9xYJxe97WFxnzH8NWWtcW3ffNS+EWg8uPvIerhjsEZ+rHtDqOCiH57A==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.17.0.tgz", + "integrity": "sha512-gVQe+SLdNPfjlJn5VNGhlOhrXz4cajwFd5kAgWtZ9dCZf4XJf8xmgCTLIqec7aha3JwgLI2CK6GY1043FRxZwg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.17.0", + "@typescript-eslint/visitor-keys": "6.17.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@typescript-eslint/utils": { + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.17.0.tgz", + "integrity": "sha512-LofsSPjN/ITNkzV47hxas2JCsNCEnGhVvocfyOcLzT9c/tSZE7SfhS/iWtzP1lKNOEfLhRTZz6xqI8N2RzweSQ==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.17.0", + "@typescript-eslint/types": "6.17.0", + "@typescript-eslint/typescript-estree": "6.17.0", + "semver": "^7.5.4" + }, + "dependencies": { + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@typescript-eslint/visitor-keys": { + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.17.0.tgz", + "integrity": "sha512-H6VwB/k3IuIeQOyYczyyKN8wH6ed8EwliaYHLxOIhyF0dYEIsN8+Bk3GE19qafeMKyZJJHP8+O1HiFhFLUNKSg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.17.0", + "eslint-visitor-keys": "^3.4.1" + } + }, "@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", @@ -11135,7 +11693,7 @@ }, "eslint-config-prettier": { "version": "9.1.0", - "resolved": "https://artifactory.corp.ebay.com/artifactory/api/npm/npm-corp/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", "dev": true, "requires": {} @@ -15597,6 +16155,13 @@ "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", "dev": true }, + "ts-api-utils": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", + "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", + "dev": true, + "requires": {} + }, "ts-node": { "version": "10.9.1", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", diff --git a/package.json b/package.json index 6505276..e82a186 100644 --- a/package.json +++ b/package.json @@ -62,6 +62,8 @@ "@types/express": "^4.17.17", "@types/mocha": "^10.0.6", "@types/node": "^14", + "@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", @@ -81,11 +83,9 @@ "typescript": "^5.3.2" }, "scripts": { - "spec": "gulp spec", - "spec:ts": "gulp spec:ts", - "pretest": "prettier --check .", + "pretest": "npm run format", "test": "gulp test", - "test:ts": "gulp test:ts", + "coverage": "gulp coverage", "types": "tsd . --files ./test/**/*.test-d.ts", "format": "prettier --write --list-different .", "lint": "eslint --fix .", diff --git a/test/lib/http-mock.test-d.ts b/test/lib/http-mock.test-d.ts index fcfb4f6..8fea192 100644 --- a/test/lib/http-mock.test-d.ts +++ b/test/lib/http-mock.test-d.ts @@ -1,7 +1,7 @@ import { IncomingMessage as NodeRequest, OutgoingMessage as NodeResponse } from 'http'; import { expectAssignable, expectNotAssignable, expectNotType, expectType } from 'tsd'; -import { createMocks, createRequest, createResponse, MockRequest, MockResponse, Mocks } from '../../lib/http-mock'; import { Request as ExpressRequest, Response as ExpressResponse } from 'express'; +import { createMocks, createRequest, createResponse, MockRequest, MockResponse, Mocks } from '../../lib/http-mock'; expectType>(createRequest()); expectNotType>(createRequest()); diff --git a/test/lib/mockRequest.spec.js b/test/lib/mockRequest.spec.js deleted file mode 100644 index 44e822f..0000000 --- a/test/lib/mockRequest.spec.js +++ /dev/null @@ -1,1150 +0,0 @@ -const chai = require('chai'); - -const { expect } = chai; -const url = require('url'); -const querystring = require('querystring'); -const parseRange = require('range-parser'); -const eventEmitter = require('events').EventEmitter; - -const mockRequest = require('../../lib/mockRequest'); - -describe('mockRequest', () => { - it('should expose .createRequest()', () => { - expect(mockRequest.createRequest).to.be.a('function'); - }); - - describe('.createRequest()', () => { - let request; - - describe('without options', () => { - before(() => { - request = mockRequest.createRequest(); - }); - - it('should have event emitter prototype functions', () => { - expect(request.on).to.be.a('function'); - expect(request.once).to.be.a('function'); - expect(request.emit).to.be.a('function'); - }); - - it('should return an object', () => { - expect(request).to.be.an('object'); - }); - - it('should be an EventEmitter', () => { - expect(request).to.be.an.instanceof(eventEmitter); - }); - - it('should expose Express Request object methods', () => { - expect(request).to.have.property('get'); - expect(request.get).to.be.a('function'); - - expect(request).to.have.property('header'); - expect(request.header).to.be.a('function'); - - expect(request).to.have.property('param'); - expect(request.param).to.be.a('function'); - }); - - it('shoud initialize with default options', () => { - expect(request.method).to.equal('GET'); - expect(request.url).to.equal(''); - expect(request.originalUrl).to.equal(request.url); - expect(request.baseUrl).to.equal(request.url); - expect(request.path).to.equal(''); - expect(request.params).to.deep.equal({}); - expect(request.session).to.be.a('undefined'); - expect(request.cookies).to.deep.equal({}); - expect(request.signedCookies).to.be.a('undefined'); - expect(request.headers).to.deep.equal({}); - expect(request.body).to.deep.equal({}); - expect(request.query).to.deep.equal({}); - expect(request.files).to.deep.equal({}); - expect(request.ip).to.equal('127.0.0.1'); - expect(request.ips).to.deep.equal([request.ip]); - }); - }); - - describe('with options', () => { - afterEach(() => { - request = null; - }); - - it('should set .method to options.method', () => { - const options = { - method: 'POST' - }; - - request = mockRequest.createRequest(options); - expect(request.method).to.equal(options.method); - }); - - it('should set .url to options.url', () => { - const options = { - url: '/this/is/a/url' - }; - - request = mockRequest.createRequest(options); - expect(request.url).to.equal(options.url); - expect(request.originalUrl).to.equal(options.url); - expect(request.baseUrl).to.equal(options.url); - }); - - it('should set .url automatically', () => { - const options = { - path: '/this/is/a/path' - }; - - const expectedUrl = '/this/is/a/path'; - - request = mockRequest.createRequest(options); - expect(request.url).to.equal(expectedUrl); - }); - - it('should set .baseUrl to options.baseUrl', () => { - const options = { - baseUrl: '/this' - }; - - request = mockRequest.createRequest(options); - expect(request.baseUrl).to.equal(options.baseUrl); - }); - - it('should set .originalUrl to options.originalUrl', () => { - const options = { - originalUrl: '/this/is/a/url' - }; - - request = mockRequest.createRequest(options); - expect(request.originalUrl).to.equal(options.originalUrl); - }); - - it('should set .path to options.path', () => { - const options = { - path: '/this/is/a/path' - }; - - request = mockRequest.createRequest(options); - expect(request.path).to.equal(options.path); - }); - - it('should set .path to pathname of options.url', () => { - const options = { - url: '/this/is/a/url' - }; - - request = mockRequest.createRequest(options); - expect(request.path).to.equal(url.parse(options.url).pathname); - }); - - it('should set .params to options.params', () => { - const options = { - params: { - key1: 'value1', - key2: 'value2' - } - }; - - request = mockRequest.createRequest(options); - expect(request.params).to.deep.equal(options.params); - }); - - it('should set .session to options.session', () => { - const options = { - session: { - key1: 'value1', - key2: 'value2' - } - }; - - request = mockRequest.createRequest(options); - expect(request.session).to.deep.equal(options.session); - }); - - it('should set .cookies to options.cookies', () => { - const options = { - cookies: { - key1: 'value1', - key2: 'value2' - } - }; - - request = mockRequest.createRequest(options); - expect(request.cookies).to.deep.equal(options.cookies); - }); - - it('should set .signedCookies to options.signedCookies', () => { - const options = { - signedCookies: { - key1: 'value1', - key2: 'value2' - } - }; - - request = mockRequest.createRequest(options); - expect(request.signedCookies).to.deep.equal(options.signedCookies); - }); - - it('should set .headers to options.headers', () => { - const options = { - headers: { - key1: 'value1', - key2: 'value2' - } - }; - - request = mockRequest.createRequest(options); - expect(request.headers).to.deep.equal(options.headers); - }); - - it('should set .headers to options.headers and be accessible via get() and header() case-insensitively', () => { - const options = { - headers: { - KEY1: 'value1', - Key2: 'value2' - } - }; - - request = mockRequest.createRequest(options); - expect(request.header('KEY1')).to.equal('value1'); - expect(request.get('KEY1')).to.equal('value1'); - expect(request.getHeader('KEY1')).to.equal('value1'); - expect(request.header('KEY2')).to.equal('value2'); - expect(request.get('KEY2')).to.equal('value2'); - expect(request.getHeader('KEY2')).to.equal('value2'); - }); - - it('should set .body to options.body', () => { - const options = { - body: { - key1: 'value1', - key2: 'value2' - } - }; - - request = mockRequest.createRequest(options); - expect(request.body).to.deep.equal(options.body); - }); - - it('should set .query to options.query', () => { - const options = { - query: { - key1: 'value1', - key2: 'value2' - } - }; - - request = mockRequest.createRequest(options); - expect(request.query).to.deep.equal(options.query); - }); - - it('should set .files to options.files', () => { - const options = { - files: { - key1: 'value1', - key2: 'value2' - } - }; - - request = mockRequest.createRequest(options); - expect(request.files).to.deep.equal(options.files); - }); - - it('should set .query to url query params when options.query not set', () => { - const options = { - url: '/path/to/url?key1=value1&key2=value2' - }; - const parsedOptions = querystring.parse(options.url.split('?')[1]); - - request = mockRequest.createRequest(options); - expect(request.query).to.deep.equal(parsedOptions); - }); - - it('should accept and set non-standard options passed to it', () => { - const options = { - mySampleProp: 'la LA LA' - }; - - request = mockRequest.createRequest(options); - expect(request.mySampleProp).to.equal('la LA LA'); - }); - - it('should set .ip to options.ip', () => { - const options = { - ip: '192.168.1.1' - }; - - request = mockRequest.createRequest(options); - expect(request.ip).to.equal(options.ip); - }); - - it('should set .ips to [options.ip]', () => { - const options = { - ip: '192.168.1.1' - }; - - request = mockRequest.createRequest(options); - expect(request.ips).to.deep.equal([options.ip]); - }); - }); - }); - - describe('.get()/.header()', () => { - let request; - - afterEach(() => { - request = null; - }); - - it('should return header, when set', () => { - const options = { - headers: { - key: 'value' - } - }; - request = mockRequest.createRequest(options); - expect(request.get('key')).to.equal('value'); - expect(request.header('key')).to.equal('value'); - expect(request.getHeader('key')).to.equal('value'); - }); - - it('should return referer, when request as referrer', () => { - const options = { - headers: { - referer: 'value' - } - }; - - request = mockRequest.createRequest(options); - expect(request.get('referrer')).to.equal('value'); - expect(request.header('referrer')).to.equal('value'); - expect(request.getHeader('referrer')).to.equal('value'); - }); - - it('should return referrer, when request as referer', () => { - const options = { - headers: { - referrer: 'value' - } - }; - - request = mockRequest.createRequest(options); - expect(request.get('referer')).to.equal('value'); - expect(request.header('referer')).to.equal('value'); - expect(request.getHeader('referer')).to.equal('value'); - }); - - it('should not return header, when not set', () => { - request = mockRequest.createRequest(); - expect(request.get('key')).to.be.a('undefined'); - expect(request.header('key')).to.be.a('undefined'); - expect(request.getHeader('key')).to.be.a('undefined'); - }); - }); - - describe('.is()', () => { - let request; - - afterEach(() => { - request = null; - }); - - it('should return type, when found in content-type header', () => { - const options = { - headers: { - 'content-type': 'text/html', - 'transfer-encoding': 'chunked' - } - }; - - request = mockRequest.createRequest(options); - expect(request.is('html')).to.equal('html'); - }); - - it('should return first matching type, given array of types', () => { - const options = { - headers: { - 'content-type': 'text/html', - 'transfer-encoding': 'chunked' - } - }; - - request = mockRequest.createRequest(options); - expect(request.is(['json', 'html', 'text'])).to.equal('html'); - }); - - it('should return false when type not found', () => { - const options = { - headers: { - 'content-type': 'text/html', - 'transfer-encoding': 'chunked' - } - }; - - request = mockRequest.createRequest(options); - expect(request.is(['json'])).to.equal(false); - }); - }); - - describe('.accepts()', () => { - let request; - - beforeEach(() => { - request = mockRequest.createRequest({ headers: { accept: 'text/html' } }); - }); - - it('returns type if the same as Accept header', () => { - expect(request.accepts('text/html')).to.equal('text/html'); - expect(request.accepts('html')).to.equal('html'); - }); - - it('returns the first matching type of an array of types', () => { - expect(request.accepts(['json', 'html'])).to.equal('html'); - }); - - it('returns false when types dont match', () => { - expect(request.accepts(['json', 'xml'])).to.equal(false); - }); - }); - - describe('.acceptsEncodings()', () => { - let request; - - beforeEach(() => { - request = mockRequest.createRequest({ headers: { 'Accept-Encoding': 'gzip' } }); - }); - - it('returns type if the same as Accept-Encoding header', () => { - expect(request.acceptsEncodings('gzip')).to.equal('gzip'); - }); - - it('returns the first matching type of an array of types', () => { - expect(request.acceptsEncodings(['compress', 'gzip'])).to.equal('gzip'); - }); - - it('returns false when types dont match', () => { - expect(request.acceptsEncodings(['compress', 'deflate'])).to.equal(false); - }); - }); - - describe('.acceptsCharsets()', () => { - let request; - - beforeEach(() => { - request = mockRequest.createRequest({ headers: { 'Accept-Charset': 'utf-8' } }); - }); - - it('returns type if the same as Accept-Charset header', () => { - expect(request.acceptsCharsets('utf-8')).to.equal('utf-8'); - }); - - it('returns the first matching type of an array of types', () => { - expect(request.acceptsCharsets(['iso-8859-15', 'utf-8'])).to.equal('utf-8'); - }); - - it('returns false when types dont match', () => { - expect(request.acceptsCharsets(['iso-8859-15', 'us-ascii'])).to.equal(false); - }); - }); - - describe('.acceptsLanguages()', () => { - let request; - - beforeEach(() => { - request = mockRequest.createRequest({ headers: { 'Accept-Language': 'en-GB' } }); - }); - - it('returns type if the same as Accept-Language header', () => { - expect(request.acceptsLanguages('en-GB')).to.equal('en-GB'); - }); - - it('returns the first matching type of an array of types', () => { - expect(request.acceptsLanguages(['de-DE', 'en-GB'])).to.equal('en-GB'); - }); - - it('returns false when types dont match', () => { - expect(request.acceptsLanguages(['de-DE', 'fr-FR'])).to.equal(false); - }); - }); - - describe('.range()', () => { - let request; - - afterEach(() => { - request = null; - }); - - it('returns undefined if there is no Range header', () => { - request = mockRequest.createRequest(); - expect(request.range()).to.be.an('undefined'); - }); - - const tests = [ - { - // Unsatisfiable - header: 'bytes=90-100', - size: 10 - }, - { - // Malformed - header: 'by90-100', - size: 10 - }, - { - // Basic range - header: 'bytes=50-55', - size: 100 - }, - { - // Complex, without options - header: 'bytes=50-55,0-10,5-10,56-60', - size: 100 - }, - { - // With options - header: 'bytes=50-55,0-10,5-10,56-60', - size: 100, - options: { - combine: true - } - } - ]; - - tests.forEach((t) => { - it(`returns the result of range-parser if there is a Range header of ${t.header} using size: ${t.size}`, () => { - request = mockRequest.createRequest({ headers: { range: t.header } }); - expect(request.range(t.size, t.options)).to.deep.equal(parseRange(t.size, t.header, t.options)); - }); - }); - }); - - describe('.param()', () => { - let request; - - afterEach(() => { - request = null; - }); - - it('should return param, when found in params', () => { - const options = { - params: { - key: 'value' - } - }; - - request = mockRequest.createRequest(options); - expect(request.param('key')).to.equal('value'); - }); - - it('should return falsy param, when found in params', () => { - const options = { - params: { - key: 0 - } - }; - - request = mockRequest.createRequest(options); - expect(request.param('key')).to.equal(0); - }); - - it('should return param, when found in body', () => { - const options = { - body: { - key: 'value' - } - }; - - request = mockRequest.createRequest(options); - expect(request.param('key')).to.equal('value'); - }); - - it('should return falsy param, when found in body', () => { - const options = { - body: { - key: 0 - } - }; - - request = mockRequest.createRequest(options); - expect(request.param('key')).to.equal(0); - }); - - it('should return param, when found in query', () => { - const options = { - query: { - key: 'value' - } - }; - - request = mockRequest.createRequest(options); - expect(request.param('key')).to.equal('value'); - }); - - it('should return falsy param, when found in query', () => { - const options = { - query: { - key: 0 - } - }; - - request = mockRequest.createRequest(options); - expect(request.param('key')).to.equal(0); - }); - - it('should not return param, when not found in params/body/query', () => { - request = mockRequest.createRequest(); - expect(request.get('key')).to.be.a('undefined'); - expect(request.header('key')).to.be.a('undefined'); - }); - - it('should return defaultValue, when not found in params/body/query', () => { - request = mockRequest.createRequest(); - expect(request.get('key')).to.be.a('undefined'); - expect(request.param('key', 'defaultValue')).to.equal('defaultValue'); - }); - - it('should return undefined, when not found in params/body/query', () => { - request = mockRequest.createRequest(); - expect(request.get('key')).to.be.a('undefined'); - expect(request.param('key')).to.be.an('undefined'); - }); - }); - - describe('helper functions', () => { - let request; - - beforeEach(() => { - request = mockRequest.createRequest(); - }); - - afterEach(() => { - request = null; - }); - - describe('._setParameter()', () => { - it('should set param, when called with key and value', () => { - request._setParameter('key', 'value'); - expect(request.param('key')).to.equal('value'); - }); - - it('should unset param, when called with key and no value', () => { - request._setParameter('key', 'value'); - request._setParameter('key'); - expect(request.param('key')).to.be.a('undefined'); - }); - }); - - describe('._setSessionVariable()', () => { - it('should set session variable, when called with key and value', () => { - request._setSessionVariable('key', 'value'); - expect(request.session.key).to.equal('value'); - }); - - it('should unset session variable, when called with key and no value', () => { - request._setSessionVariable('key', 'value'); - request._setSessionVariable('key'); - expect(request.param('key')).to.be.a('undefined'); - }); - }); - - describe('._setCookiesVariable()', () => { - it('should set cookie, when called with key and value', () => { - request._setCookiesVariable('key', 'value'); - expect(request.cookies.key).to.equal('value'); - }); - - it('should unset cookie, when called with key and no value', () => { - request._setCookiesVariable('key', 'value'); - request._setCookiesVariable('key'); - expect(request.cookies.key).to.be.a('undefined'); - }); - }); - - describe('._setSignedCookiesVariable()', () => { - it('should set signed cookie, when called with key and value', () => { - request._setSignedCookiesVariable('key', 'value'); - expect(request.signedCookies.key).to.equal('value'); - }); - - it('should unset signed cookie, when called with key and no value', () => { - request._setSignedCookiesVariable('key', 'value'); - request._setSignedCookiesVariable('key'); - expect(request.signedCookies.key).to.be.a('undefined'); - }); - }); - - describe('._setHeadersVariable()', () => { - it('should set header, when called with key and value', () => { - request._setHeadersVariable('key', 'value'); - expect(request.get('key')).to.equal('value'); - expect(request.header('key')).to.equal('value'); - expect(request.getHeader('key')).to.equal('value'); - }); - - it('should throw an error, when called with missing arguments', () => { - expect(request._setHeadersVariable).to.throw(); - }); - }); - - describe('._setFilesVariable()', () => { - it('should set file, when called with key and value', () => { - request._setFilesVariable('key', 'value'); - expect(request.files.key).to.equal('value'); - }); - - it('should unset file, when called with key and no value', () => { - request._setFilesVariable('key', 'value'); - request._setFilesVariable('key'); - expect(request.files.key).to.be.a('undefined'); - }); - }); - - describe('._setMethod()', () => { - it('should set method, when called with value', () => { - const value = 'HEAD'; - request._setMethod(value); - expect(request.method).to.equal(value); - }); - - it('should unset method, when called with no arguments', () => { - request._setMethod(); - expect(request.method).to.be.a('undefined'); - }); - }); - - describe('._setURL()', () => { - it('should set url, when called with value', () => { - const value = '/path/to/url'; - request._setURL(value); - expect(request.url).to.equal(value); - }); - - it('should unset url, when called with no arguments', () => { - request._setURL(); - expect(request.url).to.be.a('undefined'); - }); - }); - - describe('._setBaseUrl()', () => { - it('should set baseUrl, when called with value', () => { - const value = '/path'; - request._setBaseUrl(value); - expect(request.baseUrl).to.equal(value); - }); - - it('should unset baseUrl, when called with no arguments', () => { - request._setBaseUrl(); - expect(request.baseUrl).to.be.a('undefined'); - }); - }); - - describe('._setOriginalUrl()', () => { - it('should set originalUrl, when called with value', () => { - const value = '/path/to/url'; - request._setOriginalUrl(value); - expect(request.originalUrl).to.equal(value); - }); - - it('should unset originalUrl, when called with no arguments', () => { - request._setOriginalUrl(); - expect(request.originalUrl).to.be.a('undefined'); - }); - }); - - describe('._setBody()', () => { - it('should set body, when called with value', () => { - const value = { - key1: 'value1', - key2: 'value2' - }; - request._setBody(value); - expect(request.body).to.deep.equal(value); - }); - - it('should unset body, when called with no arguments', () => { - request._setBody(); - expect(request.body).to.be.a('undefined'); - }); - }); - - describe('._addBody()', () => { - it('should add body variable, when called with key and value', () => { - request._addBody('key', 'value'); - expect(request.body.key).to.equal('value'); - }); - - it('should unset body variable, when called with key and no value', () => { - request._addBody('key', 'value'); - request._addBody('key'); - expect(request.body.key).to.be.a('undefined'); - }); - }); - - describe('.send()', () => { - it('should trigger data and end event when string is given', (done) => { - let data = []; - request.on('data', (chunk) => { - data.push(chunk); - }); - request.on('end', () => { - data = Buffer.concat(data).toString(); - expect(data).to.equal('test data'); - done(); - }); - request.send('test data'); - }); - - it('should trigger data and end event when object is given', (done) => { - let data = []; - const dataTosend = { key: 'value' }; - request.on('data', (chunk) => { - data.push(chunk); - }); - request.on('end', () => { - data = Buffer.concat(data).toString(); - expect(JSON.parse(data)).to.deep.equal(dataTosend); - done(); - }); - request.send(dataTosend); - }); - - it('should trigger data and end event when number is given', (done) => { - let data = []; - request.on('data', (chunk) => { - data.push(chunk); - }); - request.on('end', () => { - data = Buffer.concat(data).toString(); - expect(data).to.equal('35'); - done(); - }); - request.send(35); - }); - - it('should trigger data and end event when buffer is given', (done) => { - let data = []; - const bufferdata = Buffer.from('test data'); - request.on('data', (chunk) => { - data.push(chunk); - }); - request.on('end', () => { - data = Buffer.concat(data).toString(); - expect(data).to.equal('test data'); - done(); - }); - request.send(bufferdata); - }); - - it('should trigger data and end event when nothing is given', (done) => { - let data = []; - request.on('data', (chunk) => { - data.push(chunk); - }); - request.on('end', () => { - data = Buffer.concat(data).toString(); - expect(data).to.equal(''); - done(); - }); - request.send(); - }); - }); - - describe('.hostname', () => { - it("should return the host's main domain", () => { - const options = { - headers: { - host: 'tobi.ferrets.example.com:5000' - } - }; - request = mockRequest.createRequest(options); - expect(request.hostname).to.equal('tobi.ferrets.example.com'); - - options.headers.host = 'tobi.ferrets.example.com'; - request = mockRequest.createRequest(options); - expect(request.hostname).to.equal('tobi.ferrets.example.com'); - - options.headers.host = 'example.com'; - request = mockRequest.createRequest(options); - expect(request.hostname).to.equal('example.com'); - - options.headers.host = 'example.com:8443'; - request = mockRequest.createRequest(options); - expect(request.hostname).to.equal('example.com'); - - options.headers.host = 'localhost:3000'; - request = mockRequest.createRequest(options); - expect(request.hostname).to.equal('localhost'); - }); - - it('should return an empty string', () => { - const options = { - headers: { - key1: 'key1' - } - }; - request = mockRequest.createRequest(options); - expect(request.hostname).to.equal(''); - }); - - it('should return an predefined hostname', () => { - const options = { - hostname: 'predefined.host.com', - headers: { - host: 'other.host' - } - }; - request = mockRequest.createRequest(options); - expect(request.hostname).to.equal('predefined.host.com'); - }); - }); - - describe('.subdomains', () => { - it('should returns the host subdomains', () => { - const options = { - headers: { - host: 'tobi.ferrets.example.com' - } - }; - request = mockRequest.createRequest(options); - expect(request.subdomains).to.be.an('array').that.includes('ferrets'); - expect(request.subdomains).to.be.an('array').that.includes('tobi'); - }); - - it('should returns and empty array', () => { - const options = { - headers: { - key1: 'key1' - } - }; - request = mockRequest.createRequest(options); - expect(request.subdomains).to.be.an('array').to.have.lengthOf(0); - - options.headers.host = 'example.com'; - request = mockRequest.createRequest(options); - expect(request.subdomains).to.be.an('array').to.have.lengthOf(0); - }); - }); - }); - - describe('asyncIterator', () => { - async function collect(asyncIterable) { - const chunks = []; - for await (const chunk of asyncIterable) { - chunks.push(chunk); - } - return chunks; - } - - it('should iterate when sending data', async () => { - const request = mockRequest.createRequest(); - - const chunksPromise = collect(request); - request.send('test data'); - - const data = Buffer.concat(await chunksPromise).toString(); - expect(data).to.equal('test data'); - }); - - it('should iterate synchronous pushes', async () => { - const request = mockRequest.createRequest(); - - const chunksPromise = collect(request); - request.emit('data', Buffer.from('foo')); - request.emit('data', Buffer.from('bar')); - request.emit('data', Buffer.from('baz')); - request.emit('end'); - - const data = Buffer.concat(await chunksPromise).toString(); - expect(data).to.equal('foobarbaz'); - }); - - it('should ignore push after end', async () => { - const request = mockRequest.createRequest(); - - const chunksPromise = collect(request); - request.emit('data', Buffer.from('foo')); - request.emit('end'); - request.emit('data', Buffer.from('bar')); - - const data = Buffer.concat(await chunksPromise).toString(); - expect(data).to.equal('foo'); - }); - - it('should iterate asynchronous pushes', async () => { - const request = mockRequest.createRequest(); - - const chunksPromise = collect(request); - request.emit('data', Buffer.from('foo')); - await new Promise((r) => setTimeout(r)); - request.emit('data', Buffer.from('bar')); - await new Promise((r) => setTimeout(r)); - request.emit('data', Buffer.from('baz')); - await new Promise((r) => setTimeout(r)); - request.emit('end'); - - const data = Buffer.concat(await chunksPromise).toString(); - expect(data).to.equal('foobarbaz'); - }); - - it('should support asynchronous pushes while iterating', async () => { - const request = mockRequest.createRequest(); - - const chunksPromise = (async () => { - const extraPushes = ['3', '2', '1']; - const chunks = []; - for await (const chunk of request) { - chunks.push(chunk); - if (extraPushes.length > 0) { - request.emit('data', Buffer.from(extraPushes.pop())); - await new Promise((r) => setTimeout(r)); - } - } - return chunks; - })(); - - request.emit('data', Buffer.from('foo')); - await new Promise((r) => setTimeout(r)); - request.emit('data', Buffer.from('bar')); - await new Promise((r) => setTimeout(r)); - request.emit('data', Buffer.from('baz')); - await new Promise((r) => setTimeout(r)); - request.emit('end'); - - const data = Buffer.concat(await chunksPromise).toString(); - expect(data).to.equal('foo1bar2baz3'); - }); - - it('supports error', async () => { - const request = mockRequest.createRequest(); - - /** @type {AsyncIterator} */ - const iterator = request[Symbol.asyncIterator](); - const error = new Error('Test error'); - - const nextPromise = iterator.next(); - request.emit('error', error); - - try { - await nextPromise; - expect.fail(); - } catch (e) { - expect(e).to.equal(error); - } - }); - - it('supports throw', async () => { - const request = mockRequest.createRequest(); - - /** @type {AsyncIterator} */ - const iterator = request[Symbol.asyncIterator](); - const error = new Error('Test error'); - - const nextPromise = iterator.next(); - request.emit('data', Buffer.from('foo')); - await nextPromise; - - try { - await iterator.throw(error); - expect.fail(); - } catch (e) { - expect(e).to.equal(error); - } - }); - - it('first error wins', async () => { - const request = mockRequest.createRequest(); - - /** @type {AsyncIterator} */ - const iterator = request[Symbol.asyncIterator](); - const error1 = new Error('Test error 1'); - const error2 = new Error('Test error 2'); - - const nextPromise = iterator.next(); - request.emit('error', error1); - request.emit('error', error2); - - try { - await nextPromise; - expect.fail(); - } catch (e) { - expect(e).to.equal(error1); - } - }); - - it('supports return', async () => { - const request = mockRequest.createRequest(); - - /** @type {AsyncIterator} */ - const iterator = request[Symbol.asyncIterator](); - - const result = await iterator.return(); - expect(result.done).to.equal(true); - }); - - ['close', 'error'].forEach((event) => { - it(`discards buffer on ${event}`, async () => { - const request = mockRequest.createRequest(); - - const chunksPromise = (async () => { - const chunks = []; - try { - for await (const data of request) { - chunks.push(data); - } - } catch (e) { - // Ignore - } - return chunks; - })(); - - request.emit('data', Buffer.from('foo')); - await new Promise((r) => setTimeout(r)); - request.emit('data', Buffer.from('bar')); - request.emit(event, event === 'error' ? new Error('Test error') : undefined); - request.emit('data', Buffer.from('baz')); - - const data = Buffer.concat(await chunksPromise).toString(); - expect(data).to.equal('foo'); - }); - }); - - it('emits custom event after creation', async () => { - const request = mockRequest.createRequest(); - - request.on('async_iterator', () => { - request.emit('data', Buffer.from('foo')); - request.emit('data', Buffer.from('bar')); - request.emit('data', Buffer.from('baz')); - request.emit('end'); - }); - - const data = Buffer.concat(await collect(request)).toString(); - expect(data).to.equal('foobarbaz'); - }); - - if (typeof global.Request === 'function') { - it('can be fed to a Fetch API Request body', async () => { - const request = mockRequest.createRequest(); - - // eslint-disable-next-line no-undef - const webRequest = new Request('http://example.com', { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: request, - duplex: 'half' - }); - - request.on('async_iterator', () => { - request.emit('data', Buffer.from('{ "foo": "b')); - request.emit('data', Buffer.from('ar" }')); - request.emit('end'); - }); - - const webRequestJson = await webRequest.json(); - expect(webRequestJson).to.deep.equal({ foo: 'bar' }); - }); - } - }); -}); diff --git a/test/lib/mockRequest.spec.ts b/test/lib/mockRequest.spec.ts index c92261b..32b58b8 100644 --- a/test/lib/mockRequest.spec.ts +++ b/test/lib/mockRequest.spec.ts @@ -2,36 +2,36 @@ import { expect } from 'chai'; import * as url from 'url'; import * as querystring from 'querystring'; import parseRange from 'range-parser'; +import { EventEmitter } from 'events'; -import * as mockRequest from '../../lib/http-mock'; import { IncomingMessage } from 'http'; -import stream from 'stream'; +import * as mockRequest from '../../lib/http-mock'; -describe('mockRequest', function () { - it('should expose .createRequest()', function () { +describe('mockRequest', () => { + it('should expose .createRequest()', () => { expect(mockRequest.createRequest).to.be.a('function'); }); - describe('.createRequest()', function () { - describe('without options', function () { - it('should have event emitter prototype functions', function () { + describe('.createRequest()', () => { + describe('without options', () => { + it('should have event emitter prototype functions', () => { const request = mockRequest.createRequest(); expect(request.on).to.be.a('function'); expect(request.once).to.be.a('function'); expect(request.emit).to.be.a('function'); }); - it('should return an object', function () { + it('should return an object', () => { const request = mockRequest.createRequest(); expect(request).to.be.an('object'); }); - it('should be an EventEmitter', function () { + it('should be an EventEmitter', () => { const request = mockRequest.createRequest(); - expect(request).to.be.an.instanceof(require('events').EventEmitter); + expect(request).to.be.an.instanceof(EventEmitter); }); - it('should expose Express Request object methods', function () { + it('should expose Express Request object methods', () => { const request = mockRequest.createRequest(); expect(request).to.have.property('get'); expect(request.get).to.be.a('function'); @@ -43,7 +43,7 @@ describe('mockRequest', function () { expect(request.param).to.be.a('function'); }); - it('shoud initialize with default options', function () { + it('shoud initialize with default options', () => { const request = mockRequest.createRequest(); expect(request.method).to.equal('GET'); expect(request.url).to.equal(''); @@ -63,8 +63,8 @@ describe('mockRequest', function () { }); }); - describe('with options', function () { - it('should set .method to options.method', function () { + describe('with options', () => { + it('should set .method to options.method', () => { const options: mockRequest.RequestOptions = { method: 'POST' }; @@ -73,7 +73,7 @@ describe('mockRequest', function () { expect(request.method).to.equal(options.method); }); - it('should set .url to options.url', function () { + it('should set .url to options.url', () => { const options = { url: '/this/is/a/url' }; @@ -84,7 +84,7 @@ describe('mockRequest', function () { expect(request.baseUrl).to.equal(options.url); }); - it('should set .url automatically', function () { + it('should set .url automatically', () => { const options = { path: '/this/is/a/path' }; @@ -95,7 +95,7 @@ describe('mockRequest', function () { expect(request.url).to.equal(expectedUrl); }); - it('should set .baseUrl to options.baseUrl', function () { + it('should set .baseUrl to options.baseUrl', () => { const options = { baseUrl: '/this' }; @@ -104,7 +104,7 @@ describe('mockRequest', function () { expect(request.baseUrl).to.equal(options.baseUrl); }); - it('should set .originalUrl to options.originalUrl', function () { + it('should set .originalUrl to options.originalUrl', () => { const options = { originalUrl: '/this/is/a/url' }; @@ -113,7 +113,7 @@ describe('mockRequest', function () { expect(request.originalUrl).to.equal(options.originalUrl); }); - it('should set .path to options.path', function () { + it('should set .path to options.path', () => { const options = { path: '/this/is/a/path' }; @@ -122,7 +122,7 @@ describe('mockRequest', function () { expect(request.path).to.equal(options.path); }); - it('should set .path to pathname of options.url', function () { + it('should set .path to pathname of options.url', () => { const options = { url: '/this/is/a/url' }; @@ -131,7 +131,7 @@ describe('mockRequest', function () { expect(request.path).to.equal(url.parse(options.url).pathname); }); - it('should set .params to options.params', function () { + it('should set .params to options.params', () => { const options = { params: { key1: 'value1', @@ -143,7 +143,7 @@ describe('mockRequest', function () { expect(request.params).to.deep.equal(options.params); }); - it('should set .session to options.session', function () { + it('should set .session to options.session', () => { const options = { session: { key1: 'value1', @@ -155,7 +155,7 @@ describe('mockRequest', function () { expect(request.session).to.deep.equal(options.session); }); - it('should set .cookies to options.cookies', function () { + it('should set .cookies to options.cookies', () => { const options = { cookies: { key1: 'value1', @@ -167,7 +167,7 @@ describe('mockRequest', function () { expect(request.cookies).to.deep.equal(options.cookies); }); - it('should set .signedCookies to options.signedCookies', function () { + it('should set .signedCookies to options.signedCookies', () => { const options = { signedCookies: { key1: 'value1', @@ -179,7 +179,7 @@ describe('mockRequest', function () { expect(request.signedCookies).to.deep.equal(options.signedCookies); }); - it('should set .headers to options.headers', function () { + it('should set .headers to options.headers', () => { const options = { headers: { key1: 'value1', @@ -191,7 +191,7 @@ describe('mockRequest', function () { expect(request.headers).to.deep.equal(options.headers); }); - it('should set .headers to options.headers and be accessible via get() and header() case-insensitively', function () { + it('should set .headers to options.headers and be accessible via get() and header() case-insensitively', () => { const options = { headers: { KEY1: 'value1', @@ -208,7 +208,7 @@ describe('mockRequest', function () { expect(request.getHeader('KEY2')).to.equal('value2'); }); - it('should set .body to options.body', function () { + it('should set .body to options.body', () => { const options = { body: { key1: 'value1', @@ -220,7 +220,7 @@ describe('mockRequest', function () { expect(request.body).to.deep.equal(options.body); }); - it('should set .query to options.query', function () { + it('should set .query to options.query', () => { const options = { query: { key1: 'value1', @@ -232,7 +232,7 @@ describe('mockRequest', function () { expect(request.query).to.deep.equal(options.query); }); - it('should set .files to options.files', function () { + it('should set .files to options.files', () => { const options = { files: { key1: 'value1', @@ -244,7 +244,7 @@ describe('mockRequest', function () { expect(request.files).to.deep.equal(options.files); }); - it('should set .query to url query params when options.query not set', function () { + it('should set .query to url query params when options.query not set', () => { const options = { url: '/path/to/url?key1=value1&key2=value2' }; @@ -254,7 +254,7 @@ describe('mockRequest', function () { expect(request.query).to.deep.equal(parsedOptions); }); - it('should accept and set non-standard options passed to it', function () { + it('should accept and set non-standard options passed to it', () => { const options = { mySampleProp: 'la LA LA' }; @@ -263,7 +263,7 @@ describe('mockRequest', function () { expect(request.mySampleProp).to.equal('la LA LA'); }); - it('should set .ip to options.ip', function () { + it('should set .ip to options.ip', () => { const options = { ip: '192.168.1.1' }; @@ -272,7 +272,7 @@ describe('mockRequest', function () { expect(request.ip).to.equal(options.ip); }); - it('should set .ips to [options.ip]', function () { + it('should set .ips to [options.ip]', () => { const options = { ip: '192.168.1.1' }; @@ -283,14 +283,8 @@ describe('mockRequest', function () { }); }); - describe('.get()/.header()', function () { - let request; - - afterEach(function () { - const request = null; - }); - - it('should return header, when set', function () { + describe('.get()/.header()', () => { + it('should return header, when set', () => { const options = { headers: { key: 'value' @@ -302,7 +296,7 @@ describe('mockRequest', function () { expect(request.getHeader('key')).to.equal('value'); }); - it('should return referer, when request as referrer', function () { + it('should return referer, when request as referrer', () => { const options = { headers: { referer: 'value' @@ -315,7 +309,7 @@ describe('mockRequest', function () { expect(request.getHeader('referrer')).to.equal('value'); }); - it('should return referrer, when request as referer', function () { + it('should return referrer, when request as referer', () => { const options = { headers: { referrer: 'value' @@ -328,7 +322,7 @@ describe('mockRequest', function () { expect(request.getHeader('referer')).to.equal('value'); }); - it('should not return header, when not set', function () { + it('should not return header, when not set', () => { const request = mockRequest.createRequest(); expect(request.get('key')).to.be.a('undefined'); expect(request.header('key')).to.be.a('undefined'); @@ -336,14 +330,8 @@ describe('mockRequest', function () { }); }); - describe('.is()', function () { - let request; - - afterEach(function () { - const request = null; - }); - - it('should return type, when found in content-type header', function () { + describe('.is()', () => { + it('should return type, when found in content-type header', () => { const options = { headers: { 'content-type': 'text/html', @@ -355,7 +343,7 @@ describe('mockRequest', function () { expect(request.is('html')).to.equal('html'); }); - it('should return first matching type, given array of types', function () { + it('should return first matching type, given array of types', () => { const options = { headers: { 'content-type': 'text/html', @@ -367,7 +355,7 @@ describe('mockRequest', function () { expect(request.is(['json', 'html', 'text'])).to.equal('html'); }); - it('should return false when type not found', function () { + it('should return false when type not found', () => { const options = { headers: { 'content-type': 'text/html', @@ -380,80 +368,80 @@ describe('mockRequest', function () { }); }); - describe('.accepts()', function () { - it('returns type if the same as Accept header', function () { + describe('.accepts()', () => { + it('returns type if the same as Accept header', () => { const request = mockRequest.createRequest({ headers: { accept: 'text/html' } }); expect(request.accepts('text/html')).to.equal('text/html'); expect(request.accepts('html')).to.equal('html'); }); - it('returns the first matching type of an array of types', function () { + it('returns the first matching type of an array of types', () => { const request = mockRequest.createRequest({ headers: { accept: 'text/html' } }); expect(request.accepts(['json', 'html'])).to.equal('html'); }); - it('returns false when types dont match', function () { + it('returns false when types dont match', () => { const request = mockRequest.createRequest({ headers: { accept: 'text/html' } }); expect(request.accepts(['json', 'xml'])).to.equal(false); }); }); - describe('.acceptsEncodings()', function () { - it('returns type if the same as Accept-Encoding header', function () { + describe('.acceptsEncodings()', () => { + it('returns type if the same as Accept-Encoding header', () => { const request = mockRequest.createRequest({ headers: { 'Accept-Encoding': 'gzip' } }); expect(request.acceptsEncodings('gzip')).to.equal('gzip'); }); - it('returns the first matching type of an array of types', function () { + it('returns the first matching type of an array of types', () => { const request = mockRequest.createRequest({ headers: { 'Accept-Encoding': 'gzip' } }); expect(request.acceptsEncodings(['compress', 'gzip'])).to.equal('gzip'); }); - it('returns false when types dont match', function () { + it('returns false when types dont match', () => { const request = mockRequest.createRequest({ headers: { 'Accept-Encoding': 'gzip' } }); expect(request.acceptsEncodings(['compress', 'deflate'])).to.equal(false); }); }); - describe('.acceptsCharsets()', function () { + describe('.acceptsCharsets()', () => { let request: mockRequest.MockRequest; - beforeEach(function () { + beforeEach(() => { request = mockRequest.createRequest({ headers: { 'Accept-Charset': 'utf-8' } }); }); - it('returns type if the same as Accept-Charset header', function () { + it('returns type if the same as Accept-Charset header', () => { expect(request.acceptsCharsets('utf-8')).to.equal('utf-8'); }); - it('returns the first matching type of an array of types', function () { + it('returns the first matching type of an array of types', () => { expect(request.acceptsCharsets(['iso-8859-15', 'utf-8'])).to.equal('utf-8'); }); - it('returns false when types dont match', function () { + it('returns false when types dont match', () => { expect(request.acceptsCharsets(['iso-8859-15', 'us-ascii'])).to.equal(false); }); }); - describe('.acceptsLanguages()', function () { - it('returns type if the same as Accept-Language header', function () { + describe('.acceptsLanguages()', () => { + it('returns type if the same as Accept-Language header', () => { const request = mockRequest.createRequest({ headers: { 'Accept-Language': 'en-GB' } }); expect(request.acceptsLanguages('en-GB')).to.equal('en-GB'); }); - it('returns the first matching type of an array of types', function () { + it('returns the first matching type of an array of types', () => { const request = mockRequest.createRequest({ headers: { 'Accept-Language': 'en-GB' } }); expect(request.acceptsLanguages(['de-DE', 'en-GB'])).to.equal('en-GB'); }); - it('returns false when types dont match', function () { + it('returns false when types dont match', () => { const request = mockRequest.createRequest({ headers: { 'Accept-Language': 'en-GB' } }); expect(request.acceptsLanguages(['de-DE', 'fr-FR'])).to.equal(false); }); }); - describe('.range()', function () { - it('returns undefined if there is no Range header', function () { + describe('.range()', () => { + it('returns undefined if there is no Range header', () => { const request = mockRequest.createRequest(); expect(request.range(10)).to.be.an('undefined'); }); @@ -489,28 +477,16 @@ describe('mockRequest', function () { } ]; - tests.forEach(function (t) { - it( - 'returns the result of range-parser if there is a Range header of ' + - t.header + - ' using size: ' + - t.size, - function () { - const request = mockRequest.createRequest({ headers: { range: t.header } }); - expect(request.range(t.size, t.options)).to.deep.equal(parseRange(t.size, t.header, t.options)); - } - ); + tests.forEach((t) => { + it(`returns the result of range-parser if there is a Range header of ${t.header} using size: ${t.size}`, () => { + const request = mockRequest.createRequest({ headers: { range: t.header } }); + expect(request.range(t.size, t.options)).to.deep.equal(parseRange(t.size, t.header, t.options)); + }); }); }); - describe('.param()', function () { - let request; - - afterEach(function () { - const request = null; - }); - - it('should return param, when found in params', function () { + describe('.param()', () => { + it('should return param, when found in params', () => { const options = { params: { key: 'value' @@ -521,7 +497,7 @@ describe('mockRequest', function () { expect(request.param('key')).to.equal('value'); }); - it('should return falsy param, when found in params', function () { + it('should return falsy param, when found in params', () => { const options = { params: { key: 0 @@ -532,7 +508,7 @@ describe('mockRequest', function () { expect(request.param('key')).to.equal(0); }); - it('should return param, when found in body', function () { + it('should return param, when found in body', () => { const options = { body: { key: 'value' @@ -543,7 +519,7 @@ describe('mockRequest', function () { expect(request.param('key')).to.equal('value'); }); - it('should return falsy param, when found in body', function () { + it('should return falsy param, when found in body', () => { const options = { body: { key: 0 @@ -554,7 +530,7 @@ describe('mockRequest', function () { expect(request.param('key')).to.equal(0); }); - it('should return param, when found in query', function () { + it('should return param, when found in query', () => { const options = { query: { key: 'value' @@ -565,7 +541,7 @@ describe('mockRequest', function () { expect(request.param('key')).to.equal('value'); }); - it('should return falsy param, when found in query', function () { + it('should return falsy param, when found in query', () => { const options = { query: { key: 0 @@ -576,108 +552,88 @@ describe('mockRequest', function () { expect(request.param('key')).to.equal(0); }); - it('should not return param, when not found in params/body/query', function () { + it('should not return param, when not found in params/body/query', () => { const request = mockRequest.createRequest(); expect(request.get('key')).to.be.a('undefined'); expect(request.header('key')).to.be.a('undefined'); }); - it('should return defaultValue, when not found in params/body/query', function () { + it('should return defaultValue, when not found in params/body/query', () => { const request = mockRequest.createRequest(); expect(request.get('key')).to.be.a('undefined'); expect(request.param('key', 'defaultValue')).to.equal('defaultValue'); }); - it('should return undefined, when not found in params/body/query', function () { + it('should return undefined, when not found in params/body/query', () => { const request = mockRequest.createRequest(); expect(request.get('key')).to.be.a('undefined'); expect(request.param('key')).to.be.an('undefined'); }); }); - describe('helper functions', function () { - describe('._setParameter()', function () { - it('should set param, when called with key and value', function () { + describe('helper functions', () => { + describe('._setParameter()', () => { + it('should set param, when called with key and value', () => { const request = mockRequest.createRequest(); request._setParameter('key', 'value'); expect(request.param('key')).to.equal('value'); }); - it('should unset param, when called with key and no value', function () { + it('should unset param, when called with key and no value', () => { const request = mockRequest.createRequest(); request._setParameter('key', 'value'); request._setParameter('key'); expect(request.param('key')).to.be.a('undefined'); }); - - it('should throw an error, when called with no arguments', function () { - const request = mockRequest.createRequest(); - expect(request._setParameter).to.throw(); - }); }); - describe('._setSessionVariable()', function () { - it('should set session constiable, when called with key and value', function () { + describe('._setSessionVariable()', () => { + it('should set session constiable, when called with key and value', () => { const request = mockRequest.createRequest(); request._setSessionVariable('key', 'value'); expect(request.session.key).to.equal('value'); }); - it('should unset session constiable, when called with key and no value', function () { + it('should unset session constiable, when called with key and no value', () => { const request = mockRequest.createRequest(); request._setSessionVariable('key', 'value'); request._setSessionVariable('key'); expect(request.param('key')).to.be.a('undefined'); }); - - it('should throw an error, when called with no arguments', function () { - const request = mockRequest.createRequest(); - expect(request._setSessionVariable).to.throw(); - }); }); - describe('._setCookiesVariable()', function () { - it('should set cookie, when called with key and value', function () { + describe('._setCookiesVariable()', () => { + it('should set cookie, when called with key and value', () => { const request = mockRequest.createRequest(); request._setCookiesVariable('key', 'value'); expect(request.cookies.key).to.equal('value'); }); - it('should unset cookie, when called with key and no value', function () { + it('should unset cookie, when called with key and no value', () => { const request = mockRequest.createRequest(); request._setCookiesVariable('key', 'value'); request._setCookiesVariable('key'); expect(request.cookies.key).to.be.a('undefined'); }); - - it('should throw an error, when called with no arguments', function () { - const request = mockRequest.createRequest(); - expect(request._setCookiesVariable).to.throw(); - }); }); - describe('._setSignedCookiesVariable()', function () { - it('should set signed cookie, when called with key and value', function () { + describe('._setSignedCookiesVariable()', () => { + it('should set signed cookie, when called with key and value', () => { const request = mockRequest.createRequest(); request._setSignedCookiesVariable('key', 'value'); expect(request.signedCookies.key).to.equal('value'); }); - it('should unset signed cookie, when called with key and no value', function () { + it('should unset signed cookie, when called with key and no value', () => { const request = mockRequest.createRequest(); request._setSignedCookiesVariable('key', 'value'); request._setSignedCookiesVariable('key'); expect(request.signedCookies.key).to.be.a('undefined'); }); - - it('should throw an error, when called with no arguments', function () { - const request = mockRequest.createRequest(); - expect(request._setSignedCookiesVariable).to.throw(); - }); }); - describe('._setHeadersVariable()', function () { - it('should set header, when called with key and value', function () { + describe('._setHeadersVariable()', () => { + it('should set header, when called with key and value', () => { const request = mockRequest.createRequest(); request._setHeadersVariable('key', 'value'); expect(request.get('key')).to.equal('value'); @@ -685,95 +641,89 @@ describe('mockRequest', function () { expect(request.getHeader('key')).to.equal('value'); }); - it('should throw an error, when called with missing arguments', function () { + it('should throw an error, when called with missing arguments', () => { const request = mockRequest.createRequest(); expect(request._setHeadersVariable).to.throw(); - expect(request._setHeadersVariable.bind(null, 'key')).to.throw(); }); }); - describe('._setFilesVariable()', function () { - it('should set file, when called with key and value', function () { + describe('._setFilesVariable()', () => { + it('should set file, when called with key and value', () => { const request = mockRequest.createRequest(); request._setFilesVariable('key', 'value'); expect(request.files.key).to.equal('value'); }); - it('should unset file, when called with key and no value', function () { + it('should unset file, when called with key and no value', () => { const request = mockRequest.createRequest(); request._setFilesVariable('key', 'value'); request._setFilesVariable('key'); expect(request.files.key).to.be.a('undefined'); }); - - it('should throw an error, when called with no arguments', function () { - const request = mockRequest.createRequest(); - expect(request._setFilesVariable).to.throw(); - }); }); - describe('._setMethod()', function () { - it('should set method, when called with value', function () { + describe('._setMethod()', () => { + it('should set method, when called with value', () => { const request = mockRequest.createRequest(); const value = 'HEAD'; request._setMethod(value); expect(request.method).to.equal(value); }); - it('should unset method, when called with no arguments', function () { + it('should unset method, when called with no arguments', () => { const request = mockRequest.createRequest(); request._setMethod(); expect(request.method).to.be.a('undefined'); }); }); - describe('._setURL()', function () { - it('should set url, when called with value', function () { + describe('._setURL()', () => { + it('should set url, when called with value', () => { const request = mockRequest.createRequest(); const value = '/path/to/url'; request._setURL(value); expect(request.url).to.equal(value); }); - it('should unset url, when called with no arguments', function () { + it('should unset url, when called with no arguments', () => { const request = mockRequest.createRequest(); request._setURL(); expect(request.url).to.be.a('undefined'); }); }); - describe('._setBaseUrl()', function () { - it('should set baseUrl, when called with value', function () { + describe('._setBaseUrl()', () => { + it('should set baseUrl, when called with value', () => { const value = '/path'; const request = mockRequest.createRequest(); request._setBaseUrl(value); expect(request.baseUrl).to.equal(value); }); - it('should unset baseUrl, when called with no arguments', function () { + it('should unset baseUrl, when called with no arguments', () => { const request = mockRequest.createRequest(); request._setBaseUrl(); expect(request.baseUrl).to.be.a('undefined'); }); }); - describe('._setOriginalUrl()', function () { - it('should set originalUrl, when called with value', function () { + describe('._setOriginalUrl()', () => { + it('should set originalUrl, when called with value', () => { const value = '/path/to/url'; const request = mockRequest.createRequest(); request._setOriginalUrl(value); expect(request.originalUrl).to.equal(value); }); - it('should unset originalUrl, when called with no arguments', function () { + it('should unset originalUrl, when called with no arguments', () => { const request = mockRequest.createRequest(); request._setOriginalUrl(); expect(request.originalUrl).to.be.a('undefined'); }); }); - describe('._setBody()', function () { - it('should set body, when called with value', function () { + describe('._setBody()', () => { + it('should set body, when called with value', () => { const value = { key1: 'value1', key2: 'value2' @@ -783,41 +733,36 @@ describe('mockRequest', function () { expect(request.body).to.deep.equal(value); }); - it('should unset body, when called with no arguments', function () { + it('should unset body, when called with no arguments', () => { const request = mockRequest.createRequest(); request._setBody(); expect(request.body).to.be.a('undefined'); }); }); - describe('._addBody()', function () { - it('should add body constiable, when called with key and value', function () { + describe('._addBody()', () => { + it('should add body constiable, when called with key and value', () => { const request = mockRequest.createRequest(); request._addBody('key', 'value'); expect(request.body.key).to.equal('value'); }); - it('should unset body constiable, when called with key and no value', function () { + it('should unset body constiable, when called with key and no value', () => { const request = mockRequest.createRequest(); request._addBody('key', 'value'); request._addBody('key'); expect(request.body.key).to.be.a('undefined'); }); - - it('should throw an error, when called with no arguments', function () { - const request = mockRequest.createRequest(); - expect(request._addBody).to.throw(); - }); }); - describe('.send()', function () { - it('should trigger data and end event when string is given', function (done) { - const data = Array(); + describe('.send()', () => { + it('should trigger data and end event when string is given', (done) => { + const data = [] as string[]; const request = mockRequest.createRequest(); - request.on('data', function (chunk: any) { + request.on('data', (chunk: any) => { data.push(chunk); }); - request.on('end', function () { + request.on('end', () => { const result = data.join(''); expect(result).to.equal('test data'); done(); @@ -825,14 +770,14 @@ describe('mockRequest', function () { request.send('test data'); }); - it('should trigger data and end event when object is given', function (done) { - const data = Array(); + it('should trigger data and end event when object is given', (done) => { + const data = [] as string[]; const dataTosend = { key: 'value' }; const request = mockRequest.createRequest(); - request.on('data', function (chunk: any) { + request.on('data', (chunk: any) => { data.push(chunk); }); - request.on('end', function () { + request.on('end', () => { const result = data.join(''); expect(JSON.parse(result)).to.deep.equal(dataTosend); done(); @@ -840,13 +785,13 @@ describe('mockRequest', function () { request.send(dataTosend); }); - it('should trigger data and end event when number is given', function (done) { - const data = Array(); + it('should trigger data and end event when number is given', (done) => { + const data = [] as string[]; const request = mockRequest.createRequest(); - request.on('data', function (chunk: any) { + request.on('data', (chunk: any) => { data.push(chunk); }); - request.on('end', function () { + request.on('end', () => { const result = data.join(''); expect(result).to.equal('35'); done(); @@ -854,14 +799,14 @@ describe('mockRequest', function () { request.send(35); }); - it('should trigger data and end event when buffer is given', function (done) { - const data = Array(); + it('should trigger data and end event when buffer is given', (done) => { + const data = [] as string[]; const bufferdata = Buffer.from('test data'); const request = mockRequest.createRequest(); - request.on('data', function (chunk: any) { + request.on('data', (chunk: any) => { data.push(chunk); }); - request.on('end', function () { + request.on('end', () => { const result = data.join(''); expect(result).to.equal('test data'); done(); @@ -869,13 +814,13 @@ describe('mockRequest', function () { request.send(bufferdata); }); - it('should trigger data and end event when nothing is given', function (done) { - const data = Array(); + it('should trigger data and end event when nothing is given', (done) => { + const data = [] as string[]; const request = mockRequest.createRequest(); - request.on('data', function (chunk: any) { + request.on('data', (chunk: any) => { data.push(chunk); }); - request.on('end', function () { + request.on('end', () => { const result = data.join(''); expect(result).to.equal(''); done(); @@ -884,8 +829,8 @@ describe('mockRequest', function () { }); }); - describe('.hostname', function () { - it("should return the host's main domain", function () { + describe('.hostname', () => { + it("should return the host's main domain", () => { const options = { headers: { host: 'tobi.ferrets.example.com:5000' @@ -912,7 +857,7 @@ describe('mockRequest', function () { expect(request.hostname).to.equal('localhost'); }); - it('should return an empty string', function () { + it('should return an empty string', () => { const options = { headers: { key1: 'key1' @@ -922,7 +867,7 @@ describe('mockRequest', function () { expect(request.hostname).to.equal(''); }); - it('should return an predefined hostname', function () { + it('should return an predefined hostname', () => { const options = { hostname: 'predefined.host.com', headers: { @@ -934,8 +879,8 @@ describe('mockRequest', function () { }); }); - describe('.subdomains', function () { - it('should returns the host subdomains', function () { + describe('.subdomains', () => { + it('should returns the host subdomains', () => { const options = { headers: { host: 'tobi.ferrets.example.com' @@ -946,7 +891,7 @@ describe('mockRequest', function () { expect(request.subdomains).to.be.an('array').that.includes('tobi'); }); - it('should returns and empty array', function () { + it('should returns and empty array', () => { const options: mockRequest.RequestOptions = { headers: { key1: 'key1' @@ -964,16 +909,16 @@ describe('mockRequest', function () { }); }); - describe('asyncIterator', function () { + describe('asyncIterator', () => { async function collect(asyncIterable: any) { - const chunks = Array(); + const chunks = [] as string[]; for await (const chunk of asyncIterable) { chunks.push(chunk); } return chunks; } - it('should iterate when sending data', async function () { + it('should iterate when sending data', async () => { const request = mockRequest.createRequest(); const chunksPromise = collect(request); @@ -983,7 +928,7 @@ describe('mockRequest', function () { expect(data).to.equal('test data'); }); - it('should iterate synchronous pushes', async function () { + it('should iterate synchronous pushes', async () => { const request = mockRequest.createRequest(); const chunksPromise = collect(request); @@ -996,7 +941,7 @@ describe('mockRequest', function () { expect(data).to.equal('foobarbaz'); }); - it('should ignore push after end', async function () { + it('should ignore push after end', async () => { const request = mockRequest.createRequest(); const chunksPromise = collect(request); @@ -1008,52 +953,66 @@ describe('mockRequest', function () { expect(data).to.equal('foo'); }); - it('should iterate asynchronous pushes', async function () { + it('should iterate asynchronous pushes', async () => { const request = mockRequest.createRequest(); const chunksPromise = collect(request); request.emit('data', Buffer.from('foo')); - await new Promise((r) => setTimeout(r)); + await new Promise((r) => { + setTimeout(r); + }); request.emit('data', Buffer.from('bar')); - await new Promise((r) => setTimeout(r)); + await new Promise((r) => { + setTimeout(r); + }); request.emit('data', Buffer.from('baz')); - await new Promise((r) => setTimeout(r)); + await new Promise((r) => { + setTimeout(r); + }); request.emit('end'); const data = (await chunksPromise).join(''); expect(data).to.equal('foobarbaz'); }); - it('should support asynchronous pushes while iterating', async function () { + it('should support asynchronous pushes while iterating', async () => { const request = mockRequest.createRequest(); const chunksPromise = (async () => { const extraPushes = ['3', '2', '1']; - const chunks = Array(); + const chunks = [] as string[]; for await (const chunk of request) { chunks.push(chunk); if (extraPushes.length > 0) { const toCreate = extraPushes.pop()!; request.emit('data', Buffer.from(toCreate)); - await new Promise((r) => setTimeout(r)); + await new Promise((r) => { + setTimeout(r); + }); } } return chunks; })(); request.emit('data', Buffer.from('foo')); - await new Promise((r) => setTimeout(r)); + await new Promise((r) => { + setTimeout(r); + }); request.emit('data', Buffer.from('bar')); - await new Promise((r) => setTimeout(r)); + await new Promise((r) => { + setTimeout(r); + }); request.emit('data', Buffer.from('baz')); - await new Promise((r) => setTimeout(r)); + await new Promise((r) => { + setTimeout(r); + }); request.emit('end'); const data = (await chunksPromise).join(''); expect(data).to.equal('foo1bar2baz3'); }); - it('supports error', async function () { + it('supports error', async () => { const request = mockRequest.createRequest(); /** @type {AsyncIterator} */ @@ -1071,7 +1030,7 @@ describe('mockRequest', function () { } }); - it('supports throw', async function () { + it('supports throw', async () => { const request = mockRequest.createRequest(); /** @type {AsyncIterator} */ @@ -1087,11 +1046,10 @@ describe('mockRequest', function () { expect.fail(); } catch (e) { expect(e).to.equal(error); - return; } }); - it('first error wins', async function () { + it('first error wins', async () => { const request = mockRequest.createRequest(); /** @type {AsyncIterator} */ @@ -1111,7 +1069,7 @@ describe('mockRequest', function () { } }); - it('supports return', async function () { + it('supports return', async () => { const request = mockRequest.createRequest(); /** @type {AsyncIterator} */ @@ -1122,11 +1080,11 @@ describe('mockRequest', function () { }); ['close', 'error'].forEach((event) => { - it(`discards buffer on ${event}`, async function () { + it(`discards buffer on ${event}`, async () => { const request = mockRequest.createRequest(); const chunksPromise = (async () => { - const chunks = Array(); + const chunks = [] as string[]; try { for await (const data of request) { chunks.push(data); @@ -1138,7 +1096,9 @@ describe('mockRequest', function () { })(); request.emit('data', Buffer.from('foo')); - await new Promise((r) => setTimeout(r)); + await new Promise((r) => { + setTimeout(r); + }); request.emit('data', Buffer.from('bar')); request.emit(event, event === 'error' ? new Error('Test error') : undefined); request.emit('data', Buffer.from('baz')); @@ -1161,5 +1121,32 @@ describe('mockRequest', function () { const data = (await collect(request)).join(''); expect(data).to.equal('foobarbaz'); }); + + if (typeof global.Request === 'function') { + it('can be fed to a Fetch API Request body', async () => { + // TODO: what is the purpose of this test? + const request = mockRequest.createRequest(); + + const webRequest = new Request('http://example.com', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + // @ts-ignore:next-line + body: request, + // @ts-ignore:next-line + duplex: 'half' + }); + + request.on('async_iterator', () => { + request.emit('data', Buffer.from('{ "foo": "b')); + request.emit('data', Buffer.from('ar" }')); + request.emit('end'); + }); + + const webRequestJson = await webRequest.json(); + expect(webRequestJson).to.deep.equal({ foo: 'bar' }); + }); + } }); });