mirror of
https://github.com/oven-sh/bun
synced 2026-02-04 07:58:54 +00:00
Compare commits
2 Commits
dylan/pyth
...
ci-regress
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
90d6a3f7bd | ||
|
|
a2df5195e0 |
@@ -7,7 +7,7 @@
|
||||
// - It cannot use Bun APIs, since it is run using Node.js.
|
||||
// - It does not import dependencies, so it's faster to start.
|
||||
|
||||
import { spawn, spawnSync } from "node:child_process";
|
||||
import { spawn as nodeSpawn, spawnSync as nodeSpawnSync } from "node:child_process";
|
||||
import { createHash } from "node:crypto";
|
||||
import {
|
||||
accessSync,
|
||||
@@ -59,6 +59,7 @@ const spawnTimeout = 5_000;
|
||||
const testTimeout = 3 * 60_000;
|
||||
const integrationTimeout = 5 * 60_000;
|
||||
const napiTimeout = 10 * 60_000;
|
||||
const vendorTimeout = 10_000;
|
||||
|
||||
function getNodeParallelTestTimeout(testPath) {
|
||||
if (testPath.includes("test-dns")) {
|
||||
@@ -137,6 +138,10 @@ const { values: options, positionals: filters } = parseArgs({
|
||||
type: "boolean",
|
||||
default: isBuildkite,
|
||||
},
|
||||
["update-regressions"]: {
|
||||
type: "boolean",
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -200,8 +205,14 @@ async function runTests() {
|
||||
*/
|
||||
const runTest = async (title, fn) => {
|
||||
const index = ++i;
|
||||
const isVendor = title.startsWith("vendor/");
|
||||
|
||||
let result, failure, flaky;
|
||||
/** @type {TestResult} */
|
||||
let result;
|
||||
/** @type {TestResult | undefined} */
|
||||
let failure;
|
||||
/** @type {boolean} */
|
||||
let flaky;
|
||||
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
||||
if (attempt > 1) {
|
||||
await new Promise(resolve => setTimeout(resolve, 5000 + Math.random() * 10_000));
|
||||
@@ -239,25 +250,95 @@ async function runTests() {
|
||||
}
|
||||
}
|
||||
|
||||
if (!failure) {
|
||||
/** @type {TestEntry[]} */
|
||||
const regressions = [];
|
||||
/** @type {TestEntry[]} */
|
||||
const regressionsFixed = [];
|
||||
if (isVendor) {
|
||||
const { tests, error, testPath } = result;
|
||||
if (error && !error.endsWith("failing")) {
|
||||
tests.push({ file: testPath, test: error, status: "fail" });
|
||||
}
|
||||
|
||||
const errors = tests.filter(({ status }) => status === "fail").map(({ file, test }) => `${file} > ${test}`);
|
||||
if (errors.length) {
|
||||
const knownErrors =
|
||||
vendorTests?.flatMap(({ testFailures }) => testFailures)?.filter(error => error.startsWith(testPath)) || [];
|
||||
|
||||
const regressedErrors = tests.filter(
|
||||
({ status, file, test }) => status === "fail" && !knownErrors.includes(`${file} > ${test}`),
|
||||
);
|
||||
for (const error of regressedErrors) {
|
||||
regressions.push(error);
|
||||
}
|
||||
|
||||
const fixedErrors = knownErrors.filter(error => !errors.includes(error));
|
||||
for (const error of fixedErrors) {
|
||||
const [file, ...labels] = error.split(" > ");
|
||||
regressionsFixed.push({
|
||||
file,
|
||||
test: labels.join(" > "),
|
||||
status: "pass",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (options["update-regressions"]) {
|
||||
const testFailures = regressions.map(({ file, test }) => `${file} > ${test}`);
|
||||
const vendorPath = join(cwd, "test", "vendor.json");
|
||||
/** @type {Vendor[]} */
|
||||
const vendorJson = JSON.parse(readFileSync(vendorPath, "utf-8"));
|
||||
const [, vendorName] = title.split("/");
|
||||
const vendorPackage = vendorJson.find(({ package: name }) => name === vendorName);
|
||||
if (vendorPackage) {
|
||||
const existingTestFailures = vendorPackage.testFailures || [];
|
||||
const updatedTestFailures = Array.from(
|
||||
new Set([...existingTestFailures.filter(error => !error.startsWith(title)), ...testFailures]),
|
||||
).sort();
|
||||
const vendorIndex = vendorJson.findIndex(({ package: name }) => name === vendorName);
|
||||
const vendorUpdatedPackage = {
|
||||
...vendorPackage,
|
||||
testFailures: updatedTestFailures?.length ? updatedTestFailures : undefined,
|
||||
};
|
||||
if (vendorIndex === -1) {
|
||||
vendorJson.push(vendorUpdatedPackage);
|
||||
} else {
|
||||
vendorJson[vendorIndex] = vendorUpdatedPackage;
|
||||
}
|
||||
writeFileSync(vendorPath, JSON.stringify(vendorJson, null, 2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isBuildkite && regressionsFixed.length) {
|
||||
const content = formatTestToMarkdown(
|
||||
{ ...result, tests: regressionsFixed, testPath: title },
|
||||
{ includeOk: true },
|
||||
);
|
||||
reportAnnotationToBuildKite({ context: "regressions", label: title, content, style: "info" });
|
||||
}
|
||||
|
||||
if (!failure || (isVendor && !regressions.length)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (isBuildkite) {
|
||||
// Group flaky tests together, regardless of the title
|
||||
const context = flaky ? "flaky" : title;
|
||||
const style = flaky || title.startsWith("vendor") ? "warning" : "error";
|
||||
const context = flaky && !isVendor ? "flaky" : title;
|
||||
const style = flaky || isVendor ? "warning" : "error";
|
||||
|
||||
if (title.startsWith("vendor")) {
|
||||
const content = formatTestToMarkdown({ ...failure, testPath: title });
|
||||
if (content) {
|
||||
reportAnnotationToBuildKite({ context, label: title, content, style });
|
||||
let content;
|
||||
if (isVendor) {
|
||||
if (regressions.length) {
|
||||
content = formatTestToMarkdown({ ...failure, tests: regressions, testPath: title });
|
||||
} else {
|
||||
content = formatTestToMarkdown({ ...failure, testPath: title });
|
||||
}
|
||||
} else {
|
||||
const content = formatTestToMarkdown(failure);
|
||||
if (content) {
|
||||
reportAnnotationToBuildKite({ context, label: title, content, style });
|
||||
}
|
||||
content = formatTestToMarkdown(failure);
|
||||
}
|
||||
|
||||
if (content) {
|
||||
reportAnnotationToBuildKite({ context, label: title, content, style });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -267,7 +348,7 @@ async function runTests() {
|
||||
const longMarkdown = formatTestToMarkdown(failure);
|
||||
appendFileSync(summaryPath, longMarkdown);
|
||||
}
|
||||
const shortMarkdown = formatTestToMarkdown(failure, true);
|
||||
const shortMarkdown = formatTestToMarkdown(failure, { concise: true });
|
||||
appendFileSync("comment.md", shortMarkdown);
|
||||
}
|
||||
|
||||
@@ -556,7 +637,7 @@ async function spawnSafe(options) {
|
||||
};
|
||||
await new Promise(resolve => {
|
||||
try {
|
||||
subprocess = spawn(command, args, {
|
||||
subprocess = nodeSpawn(command, args, {
|
||||
stdio: ["ignore", "pipe", "pipe"],
|
||||
timeout,
|
||||
cwd,
|
||||
@@ -667,6 +748,19 @@ async function spawnSafe(options) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {SpawnOptions} options
|
||||
* @returns {Promise<SpawnResult>}
|
||||
*/
|
||||
async function spawn(options) {
|
||||
const result = await spawnSafe(options);
|
||||
const { error, stdout } = result;
|
||||
if (error) {
|
||||
throw new Error(`Command failed: ${error}`, { cause: stdout });
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} execPath Path to bun binary
|
||||
* @param {SpawnOptions} options
|
||||
@@ -769,10 +863,11 @@ async function spawnBun(execPath, { args, cwd, timeout, env, stdout, stderr }) {
|
||||
* @returns {Promise<TestResult>}
|
||||
*/
|
||||
async function spawnBunTest(execPath, testPath, options = { cwd }) {
|
||||
const timeout = getTestTimeout(testPath);
|
||||
const isVendor = options.cwd?.includes("vendor");
|
||||
const timeout = isVendor ? vendorTimeout : getTestTimeout(testPath);
|
||||
const perTestTimeout = Math.ceil(timeout / 2);
|
||||
const absPath = join(options["cwd"], testPath);
|
||||
const isReallyTest = isTestStrict(testPath) || absPath.includes("vendor");
|
||||
const isReallyTest = isTestStrict(testPath) || isVendor;
|
||||
const args = options["args"] ?? [];
|
||||
|
||||
const testArgs = ["test", ...args, `--timeout=${perTestTimeout}`];
|
||||
@@ -1072,9 +1167,6 @@ function isHidden(path) {
|
||||
return /node_modules|node.js/.test(dirname(path)) || /^\./.test(basename(path));
|
||||
}
|
||||
|
||||
/** Files with these extensions are not treated as test cases */
|
||||
const IGNORED_EXTENSIONS = new Set([".md"]);
|
||||
|
||||
/**
|
||||
* @param {string} cwd
|
||||
* @returns {string[]}
|
||||
@@ -1084,9 +1176,8 @@ function getTests(cwd) {
|
||||
const dirname = join(cwd, path);
|
||||
for (const entry of readdirSync(dirname, { encoding: "utf-8", withFileTypes: true })) {
|
||||
const { name } = entry;
|
||||
const ext = name.slice(name.lastIndexOf("."));
|
||||
const filename = join(path, name);
|
||||
if (isHidden(filename) || IGNORED_EXTENSIONS.has(ext)) {
|
||||
if (isHidden(filename)) {
|
||||
continue;
|
||||
}
|
||||
if (entry.isFile() && isTest(filename)) {
|
||||
@@ -1105,10 +1196,9 @@ function getTests(cwd) {
|
||||
* @property {string} repository
|
||||
* @property {string} tag
|
||||
* @property {string} [packageManager]
|
||||
* @property {string} [testPath]
|
||||
* @property {string} [testRunner]
|
||||
* @property {string[]} [testExtensions]
|
||||
* @property {boolean | Record<string, boolean | string>} [skipTests]
|
||||
* @property {string[]} [testPatterns]
|
||||
* @property {string[]} [testFailures]
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -1117,6 +1207,7 @@ function getTests(cwd) {
|
||||
* @property {string} packageManager
|
||||
* @property {string} testRunner
|
||||
* @property {string[]} testPaths
|
||||
* @property {string[]} testFailures
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -1151,73 +1242,83 @@ async function getVendorTests(cwd) {
|
||||
|
||||
return Promise.all(
|
||||
relevantVendors.map(
|
||||
async ({ package: name, repository, tag, testPath, testExtensions, testRunner, packageManager, skipTests }) => {
|
||||
async ({ package: name, repository, tag, testPatterns, testFailures, testRunner, packageManager }) => {
|
||||
const vendorPath = join(cwd, "vendor", name);
|
||||
|
||||
if (!existsSync(vendorPath)) {
|
||||
await spawnSafe({
|
||||
await spawn({
|
||||
command: "git",
|
||||
args: ["clone", "--depth", "1", "--single-branch", repository, vendorPath],
|
||||
timeout: testTimeout,
|
||||
cwd,
|
||||
});
|
||||
}
|
||||
|
||||
await spawnSafe({
|
||||
command: "git",
|
||||
args: ["fetch", "--depth", "1", "origin", "tag", tag],
|
||||
timeout: testTimeout,
|
||||
cwd: vendorPath,
|
||||
});
|
||||
await spawn({
|
||||
command: "git",
|
||||
args: ["fetch", "--depth", "1", "origin", "tag", tag],
|
||||
timeout: testTimeout,
|
||||
cwd: vendorPath,
|
||||
});
|
||||
}
|
||||
|
||||
const packageJsonPath = join(vendorPath, "package.json");
|
||||
if (!existsSync(packageJsonPath)) {
|
||||
throw new Error(`Vendor '${name}' does not have a package.json: ${packageJsonPath}`);
|
||||
}
|
||||
|
||||
const testPathPrefix = testPath || "test";
|
||||
const testParentPath = join(vendorPath, testPathPrefix);
|
||||
if (!existsSync(testParentPath)) {
|
||||
throw new Error(`Vendor '${name}' does not have a test directory: ${testParentPath}`);
|
||||
}
|
||||
|
||||
const isTest = path => {
|
||||
if (!isJavaScriptTest(path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typeof skipTests === "boolean") {
|
||||
return !skipTests;
|
||||
}
|
||||
|
||||
if (typeof skipTests === "object") {
|
||||
for (const [glob, reason] of Object.entries(skipTests)) {
|
||||
const pattern = new RegExp(`^${glob.replace(/\*/g, ".*")}$`);
|
||||
if (pattern.test(path) && reason) {
|
||||
return false;
|
||||
}
|
||||
const testParentPaths = new Set();
|
||||
if (testPatterns?.length) {
|
||||
for (const pattern of testPatterns) {
|
||||
const endOfPath = pattern.lastIndexOf("/");
|
||||
const endOfGlob = pattern.lastIndexOf("*");
|
||||
if (endOfPath === -1 || endOfGlob < endOfPath) {
|
||||
continue;
|
||||
}
|
||||
const testPath = pattern.substring(0, endOfPath);
|
||||
if (existsSync(join(vendorPath, testPath))) {
|
||||
testParentPaths.add(testPath);
|
||||
}
|
||||
}
|
||||
} else if (existsSync(join(vendorPath, "test"))) {
|
||||
testParentPaths.add("test");
|
||||
}
|
||||
|
||||
return true;
|
||||
if (!testParentPaths.size) {
|
||||
throw new Error(
|
||||
`Could not find test directory for vendor '${name}' (hint: set 'testPatterns' in vendor.json)`,
|
||||
);
|
||||
}
|
||||
|
||||
const isMatch = (filename, glob) => {
|
||||
const pattern = new RegExp(`^${glob.replace(/\*/g, ".*")}$`);
|
||||
return pattern.test(filename);
|
||||
};
|
||||
|
||||
const testPaths = readdirSync(testParentPath, { encoding: "utf-8", recursive: true })
|
||||
.filter(filename =>
|
||||
testExtensions ? testExtensions.some(ext => filename.endsWith(`.${ext}`)) : isTest(filename),
|
||||
)
|
||||
.map(filename => join(testPathPrefix, filename))
|
||||
.filter(
|
||||
filename =>
|
||||
!filters?.length ||
|
||||
filters.some(filter => join(vendorPath, filename).replace(/\\/g, "/").includes(filter)),
|
||||
);
|
||||
const testPaths = Array.from(testParentPaths).flatMap(testParentPath =>
|
||||
readdirSync(join(vendorPath, testParentPath), { encoding: "utf-8", recursive: true })
|
||||
.filter(filename =>
|
||||
testPatterns?.length
|
||||
? testPatterns.some(pattern => isMatch(join(testParentPath, filename).replace(/\\/g, "/"), pattern))
|
||||
: isJavaScriptTest(filename),
|
||||
)
|
||||
.map(filename => join(testParentPath, filename))
|
||||
.filter(
|
||||
filename =>
|
||||
!filters?.length ||
|
||||
filters.some(filter => join(vendorPath, filename).replace(/\\/g, "/").includes(filter)),
|
||||
),
|
||||
);
|
||||
|
||||
if (!testPaths.length && !filters?.length) {
|
||||
throw new Error(`Could not find test files for vendor '${name}' (hint: set 'testPatterns' in vendor.json)`);
|
||||
}
|
||||
|
||||
return {
|
||||
cwd: vendorPath,
|
||||
packageManager: packageManager || "bun",
|
||||
testRunner: testRunner || "bun",
|
||||
testPaths,
|
||||
testFailures: testFailures || [],
|
||||
};
|
||||
},
|
||||
),
|
||||
@@ -1319,7 +1420,7 @@ function getExecPath(bunExe) {
|
||||
let execPath;
|
||||
let error;
|
||||
try {
|
||||
const { error, stdout } = spawnSync(bunExe, ["--print", "process.argv[0]"], {
|
||||
const { error, stdout } = nodeSpawnSync(bunExe, ["--print", "process.argv[0]"], {
|
||||
encoding: "utf-8",
|
||||
timeout: spawnTimeout,
|
||||
env: {
|
||||
@@ -1405,7 +1506,7 @@ async function getExecPathFromBuildKite(target, buildId) {
|
||||
*/
|
||||
function getRevision(execPath) {
|
||||
try {
|
||||
const { error, stdout } = spawnSync(execPath, ["--revision"], {
|
||||
const { error, stdout } = nodeSpawnSync(execPath, ["--revision"], {
|
||||
encoding: "utf-8",
|
||||
timeout: spawnTimeout,
|
||||
env: {
|
||||
@@ -1443,10 +1544,13 @@ function getTestLabel() {
|
||||
|
||||
/**
|
||||
* @param {TestResult | TestResult[]} result
|
||||
* @param {boolean} concise
|
||||
* @param {object} options
|
||||
* @param {boolean} options.concise
|
||||
* @param {boolean} options.includeOk
|
||||
* @returns {string}
|
||||
*/
|
||||
function formatTestToMarkdown(result, concise) {
|
||||
function formatTestToMarkdown(result, options = {}) {
|
||||
const { concise = false, includeOk = false } = options;
|
||||
const results = Array.isArray(result) ? result : [result];
|
||||
const buildLabel = getTestLabel();
|
||||
const buildUrl = getBuildUrl();
|
||||
@@ -1454,7 +1558,7 @@ function formatTestToMarkdown(result, concise) {
|
||||
|
||||
let markdown = "";
|
||||
for (const { testPath, ok, tests, error, stdoutPreview: stdout } of results) {
|
||||
if (ok || error === "SIGTERM") {
|
||||
if ((ok && !includeOk) || error === "SIGTERM") {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1486,6 +1590,8 @@ function formatTestToMarkdown(result, concise) {
|
||||
}
|
||||
if (error) {
|
||||
markdown += ` - ${error}`;
|
||||
} else if (ok) {
|
||||
markdown += ` - ok`;
|
||||
}
|
||||
if (platform) {
|
||||
markdown += ` on ${platform}`;
|
||||
@@ -1513,7 +1619,7 @@ function formatTestToMarkdown(result, concise) {
|
||||
* @param {string} glob
|
||||
*/
|
||||
function uploadArtifactsToBuildKite(glob) {
|
||||
spawn("buildkite-agent", ["artifact", "upload", glob], {
|
||||
nodeSpawnSync("buildkite-agent", ["artifact", "upload", glob], {
|
||||
stdio: ["ignore", "ignore", "ignore"],
|
||||
timeout: spawnTimeout,
|
||||
cwd,
|
||||
@@ -1538,7 +1644,7 @@ function listArtifactsFromBuildKite(glob, step) {
|
||||
if (step) {
|
||||
args.push("--step", step);
|
||||
}
|
||||
const { error, status, signal, stdout, stderr } = spawnSync("buildkite-agent", args, {
|
||||
const { error, status, signal, stdout, stderr } = nodeSpawnSync("buildkite-agent", args, {
|
||||
stdio: ["ignore", "ignore", "ignore"],
|
||||
encoding: "utf-8",
|
||||
timeout: spawnTimeout,
|
||||
@@ -2006,10 +2112,13 @@ export async function main() {
|
||||
// It also appears to hang on 1.1.1.1, which could explain this issue:
|
||||
// https://github.com/oven-sh/bun/issues/11136
|
||||
if (isWindows && isCI) {
|
||||
await spawn("pwsh", [
|
||||
"-Command",
|
||||
"Set-DnsClientServerAddress -InterfaceAlias 'Ethernet 4' -ServerAddresses ('8.8.8.8','8.8.4.4')",
|
||||
]);
|
||||
await spawn({
|
||||
command: "pwsh",
|
||||
args: [
|
||||
"-Command",
|
||||
"Set-DnsClientServerAddress -InterfaceAlias 'Ethernet 4' -ServerAddresses ('8.8.8.8','8.8.4.4')",
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
const results = await runTests();
|
||||
|
||||
1
test/js/third_party/express/README.md
vendored
1
test/js/third_party/express/README.md
vendored
@@ -1 +0,0 @@
|
||||
Test cases ported from [express](https://github.com/expressjs/express). MIT license.
|
||||
1108
test/js/third_party/express/app.router.test.ts
vendored
1108
test/js/third_party/express/app.router.test.ts
vendored
File diff suppressed because it is too large
Load Diff
745
test/js/third_party/express/express.json.test.ts
vendored
745
test/js/third_party/express/express.json.test.ts
vendored
@@ -1,745 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
var assert = require("node:assert");
|
||||
var AsyncLocalStorage = require("node:async_hooks").AsyncLocalStorage;
|
||||
|
||||
var express = require("express");
|
||||
var request = require("supertest");
|
||||
|
||||
describe("express.json()", function () {
|
||||
let app;
|
||||
|
||||
it("should parse JSON", function (done) {
|
||||
request(createApp())
|
||||
.post("/")
|
||||
.set("Content-Type", "application/json")
|
||||
.send('{"user":"tobi"}')
|
||||
.expect(200, '{"user":"tobi"}', done);
|
||||
});
|
||||
|
||||
it("should handle Content-Length: 0", function (done) {
|
||||
request(createApp())
|
||||
.post("/")
|
||||
.set("Content-Type", "application/json")
|
||||
.set("Content-Length", "0")
|
||||
.expect(200, "{}", done);
|
||||
});
|
||||
|
||||
it.todo("should handle empty message-body", function (done) {
|
||||
request(createApp())
|
||||
.post("/")
|
||||
.set("Content-Type", "application/json")
|
||||
.set("Transfer-Encoding", "chunked")
|
||||
.expect(200, "{}", done);
|
||||
});
|
||||
|
||||
it("should handle no message-body", function (done) {
|
||||
request(createApp())
|
||||
.post("/")
|
||||
.set("Content-Type", "application/json")
|
||||
.unset("Transfer-Encoding")
|
||||
.expect(200, "{}", done);
|
||||
});
|
||||
|
||||
// The old node error message modification in body parser is catching this
|
||||
it("should 400 when only whitespace", function (done) {
|
||||
request(createApp())
|
||||
.post("/")
|
||||
.set("Content-Type", "application/json")
|
||||
.send(" \n")
|
||||
.expect(400, "[entity.parse.failed] " + parseError(" \n"), done);
|
||||
});
|
||||
|
||||
it("should 400 when invalid content-length", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res, next) {
|
||||
req.headers["content-length"] = "20"; // bad length
|
||||
next();
|
||||
});
|
||||
|
||||
app.use(express.json());
|
||||
|
||||
app.post("/", function (req, res) {
|
||||
res.json(req.body);
|
||||
});
|
||||
|
||||
request(app)
|
||||
.post("/")
|
||||
.set("Content-Type", "application/json")
|
||||
.send('{"str":')
|
||||
.expect(400, /content length/, done);
|
||||
});
|
||||
|
||||
it("should handle duplicated middleware", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(express.json());
|
||||
app.use(express.json());
|
||||
|
||||
app.post("/", function (req, res) {
|
||||
res.json(req.body);
|
||||
});
|
||||
|
||||
request(app)
|
||||
.post("/")
|
||||
.set("Content-Type", "application/json")
|
||||
.send('{"user":"tobi"}')
|
||||
.expect(200, '{"user":"tobi"}', done);
|
||||
});
|
||||
|
||||
describe("when JSON is invalid", function () {
|
||||
let app;
|
||||
beforeAll(function () {
|
||||
app = createApp();
|
||||
});
|
||||
|
||||
it("should 400 for bad token", function (done) {
|
||||
request(app)
|
||||
.post("/")
|
||||
.set("Content-Type", "application/json")
|
||||
.send("{:")
|
||||
.expect(400, "[entity.parse.failed] " + parseError("{:"), done);
|
||||
});
|
||||
|
||||
it("should 400 for incomplete", function (done) {
|
||||
request(app)
|
||||
.post("/")
|
||||
.set("Content-Type", "application/json")
|
||||
.send('{"user"')
|
||||
.expect(400, "[entity.parse.failed] " + parseError('{"user"'), done);
|
||||
});
|
||||
|
||||
it("should include original body on error object", function (done) {
|
||||
request(app)
|
||||
.post("/")
|
||||
.set("Content-Type", "application/json")
|
||||
.set("X-Error-Property", "body")
|
||||
.send(' {"user"')
|
||||
.expect(400, ' {"user"', done);
|
||||
});
|
||||
});
|
||||
|
||||
describe("with limit option", function () {
|
||||
it("should 413 when over limit with Content-Length", function (done) {
|
||||
var buf = Buffer.alloc(1024, ".");
|
||||
request(createApp({ limit: "1kb" }))
|
||||
.post("/")
|
||||
.set("Content-Type", "application/json")
|
||||
.set("Content-Length", "1034")
|
||||
.send(JSON.stringify({ str: buf.toString() }))
|
||||
.expect(413, "[entity.too.large] request entity too large", done);
|
||||
});
|
||||
|
||||
it("should 413 when over limit with chunked encoding", function (done) {
|
||||
var app = createApp({ limit: "1kb" });
|
||||
var buf = Buffer.alloc(1024, ".");
|
||||
var test = request(app).post("/");
|
||||
test.set("Content-Type", "application/json");
|
||||
test.set("Transfer-Encoding", "chunked");
|
||||
test.write('{"str":');
|
||||
test.write('"' + buf.toString() + '"}');
|
||||
test.expect(413, done);
|
||||
});
|
||||
|
||||
it("should 413 when inflated body over limit", function (done) {
|
||||
var app = createApp({ limit: "1kb" });
|
||||
var test = request(app).post("/");
|
||||
test.set("Content-Encoding", "gzip");
|
||||
test.set("Content-Type", "application/json");
|
||||
test.write(Buffer.from("1f8b080000000000000aab562a2e2952b252d21b05a360148c58a0540b0066f7ce1e0a040000", "hex"));
|
||||
test.expect(413, done);
|
||||
});
|
||||
|
||||
it("should accept number of bytes", function (done) {
|
||||
var buf = Buffer.alloc(1024, ".");
|
||||
request(createApp({ limit: 1024 }))
|
||||
.post("/")
|
||||
.set("Content-Type", "application/json")
|
||||
.send(JSON.stringify({ str: buf.toString() }))
|
||||
.expect(413, done);
|
||||
});
|
||||
|
||||
it("should not change when options altered", function (done) {
|
||||
var buf = Buffer.alloc(1024, ".");
|
||||
var options = { limit: "1kb" };
|
||||
var app = createApp(options);
|
||||
|
||||
options.limit = "100kb";
|
||||
|
||||
request(app)
|
||||
.post("/")
|
||||
.set("Content-Type", "application/json")
|
||||
.send(JSON.stringify({ str: buf.toString() }))
|
||||
.expect(413, done);
|
||||
});
|
||||
|
||||
it("should not hang response", function (done) {
|
||||
var buf = Buffer.alloc(10240, ".");
|
||||
var app = createApp({ limit: "8kb" });
|
||||
var test = request(app).post("/");
|
||||
test.set("Content-Type", "application/json");
|
||||
test.write(buf);
|
||||
test.write(buf);
|
||||
test.write(buf);
|
||||
test.expect(413, done);
|
||||
});
|
||||
|
||||
it("should not error when inflating", function (done) {
|
||||
var app = createApp({ limit: "1kb" });
|
||||
var test = request(app).post("/");
|
||||
test.set("Content-Encoding", "gzip");
|
||||
test.set("Content-Type", "application/json");
|
||||
test.write(Buffer.from("1f8b080000000000000aab562a2e2952b252d21b05a360148c58a0540b0066f7ce1e0a0400", "hex"));
|
||||
test.expect(413, done);
|
||||
});
|
||||
});
|
||||
|
||||
describe("with inflate option", function () {
|
||||
describe("when false", function () {
|
||||
beforeAll(function () {
|
||||
app = createApp({ inflate: false });
|
||||
});
|
||||
|
||||
it.todo("should not accept content-encoding", function (done) {
|
||||
var test = request(app).post("/");
|
||||
test.set("Content-Encoding", "gzip");
|
||||
test.set("Content-Type", "application/json");
|
||||
test.write(Buffer.from("1f8b080000000000000bab56ca4bcc4d55b2527ab16e97522d00515be1cc0e000000", "hex"));
|
||||
test.expect(415, "[encoding.unsupported] content encoding unsupported", done);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when true", function () {
|
||||
beforeAll(function () {
|
||||
app = createApp({ inflate: true });
|
||||
});
|
||||
|
||||
it("should accept content-encoding", function (done) {
|
||||
var test = request(app).post("/");
|
||||
test.set("Content-Encoding", "gzip");
|
||||
test.set("Content-Type", "application/json");
|
||||
test.write(Buffer.from("1f8b080000000000000bab56ca4bcc4d55b2527ab16e97522d00515be1cc0e000000", "hex"));
|
||||
test.expect(200, '{"name":"论"}', done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("with strict option", function () {
|
||||
describe("when undefined", function () {
|
||||
beforeAll(function () {
|
||||
app = createApp();
|
||||
});
|
||||
|
||||
it("should 400 on primitives", function (done) {
|
||||
request(app)
|
||||
.post("/")
|
||||
.set("Content-Type", "application/json")
|
||||
.send("true")
|
||||
.expect(400, "[entity.parse.failed] " + parseError("#rue").replace(/#/g, "t"), done);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when false", function () {
|
||||
beforeAll(function () {
|
||||
app = createApp({ strict: false });
|
||||
});
|
||||
|
||||
it.todo("should parse primitives", function (done) {
|
||||
request(app).post("/").set("Content-Type", "application/json").send("true").expect(200, "true", done);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when true", function () {
|
||||
beforeAll(function () {
|
||||
app = createApp({ strict: true });
|
||||
});
|
||||
|
||||
it("should not parse primitives", function (done) {
|
||||
request(app)
|
||||
.post("/")
|
||||
.set("Content-Type", "application/json")
|
||||
.send("true")
|
||||
.expect(400, "[entity.parse.failed] " + parseError("#rue").replace(/#/g, "t"), done);
|
||||
});
|
||||
|
||||
it("should not parse primitives with leading whitespaces", function (done) {
|
||||
request(app)
|
||||
.post("/")
|
||||
.set("Content-Type", "application/json")
|
||||
.send(" true")
|
||||
.expect(400, "[entity.parse.failed] " + parseError(" #rue").replace(/#/g, "t"), done);
|
||||
});
|
||||
|
||||
it("should allow leading whitespaces in JSON", function (done) {
|
||||
request(app)
|
||||
.post("/")
|
||||
.set("Content-Type", "application/json")
|
||||
.send(' { "user": "tobi" }')
|
||||
.expect(200, '{"user":"tobi"}', done);
|
||||
});
|
||||
|
||||
it("should include correct message in stack trace", function (done) {
|
||||
request(app)
|
||||
.post("/")
|
||||
.set("Content-Type", "application/json")
|
||||
.set("X-Error-Property", "stack")
|
||||
.send("true")
|
||||
.expect(400)
|
||||
.expect(shouldContainInBody(parseError("#rue").replace(/#/g, "t")))
|
||||
.end(done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("with type option", function () {
|
||||
describe.skip('when "application/vnd.api+json"', function () {
|
||||
beforeAll(function () {
|
||||
app = createApp({ type: "application/vnd.api+json" });
|
||||
});
|
||||
|
||||
it("should parse JSON for custom type", function (done) {
|
||||
request(app)
|
||||
.post("/")
|
||||
.set("Content-Type", "application/vnd.api+json")
|
||||
.send('{"user":"tobi"}')
|
||||
.expect(200, '{"user":"tobi"}', done);
|
||||
});
|
||||
|
||||
it("should ignore standard type", function (done) {
|
||||
request(app).post("/").set("Content-Type", "application/json").send('{"user":"tobi"}').expect(200, "", done);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when ["application/json", "application/vnd.api+json"]', function () {
|
||||
beforeAll(function () {
|
||||
app = createApp({
|
||||
type: ["application/json", "application/vnd.api+json"],
|
||||
});
|
||||
});
|
||||
|
||||
it('should parse JSON for "application/json"', function (done) {
|
||||
request(app)
|
||||
.post("/")
|
||||
.set("Content-Type", "application/json")
|
||||
.send('{"user":"tobi"}')
|
||||
.expect(200, '{"user":"tobi"}', done);
|
||||
});
|
||||
|
||||
it.todo('should parse JSON for "application/vnd.api+json"', function (done) {
|
||||
request(app)
|
||||
.post("/")
|
||||
.set("Content-Type", "application/vnd.api+json")
|
||||
.send('{"user":"tobi"}')
|
||||
.expect(200, '{"user":"tobi"}', done);
|
||||
});
|
||||
|
||||
it.todo('should ignore "application/x-json"', function (done) {
|
||||
request(app).post("/").set("Content-Type", "application/x-json").send('{"user":"tobi"}').expect(200, "", done);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when a function", function () {
|
||||
it("should parse when truthy value returned", function (done) {
|
||||
var app = createApp({ type: accept });
|
||||
|
||||
function accept(req) {
|
||||
return req.headers["content-type"] === "application/vnd.api+json";
|
||||
}
|
||||
|
||||
request(app)
|
||||
.post("/")
|
||||
.set("Content-Type", "application/vnd.api+json")
|
||||
.send('{"user":"tobi"}')
|
||||
.expect(200, '{"user":"tobi"}', done);
|
||||
});
|
||||
|
||||
it("should work without content-type", function (done) {
|
||||
var app = createApp({ type: accept });
|
||||
|
||||
function accept(req) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var test = request(app).post("/");
|
||||
test.write('{"user":"tobi"}');
|
||||
test.expect(200, '{"user":"tobi"}', done);
|
||||
});
|
||||
|
||||
it("should not invoke without a body", function (done) {
|
||||
var app = createApp({ type: accept });
|
||||
|
||||
function accept(req) {
|
||||
throw new Error("oops!");
|
||||
}
|
||||
|
||||
request(app).get("/").expect(404, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("with verify option", function () {
|
||||
it("should assert value if function", function () {
|
||||
assert.throws(createApp.bind(null, { verify: "lol" }), /TypeError: option verify must be function/);
|
||||
});
|
||||
|
||||
it("should error from verify", function (done) {
|
||||
var app = createApp({
|
||||
verify: function (req, res, buf) {
|
||||
if (buf[0] === 0x5b) throw new Error("no arrays");
|
||||
},
|
||||
});
|
||||
|
||||
request(app)
|
||||
.post("/")
|
||||
.set("Content-Type", "application/json")
|
||||
.send('["tobi"]')
|
||||
.expect(403, "[entity.verify.failed] no arrays", done);
|
||||
});
|
||||
|
||||
it("should allow custom codes", function (done) {
|
||||
var app = createApp({
|
||||
verify: function (req, res, buf) {
|
||||
if (buf[0] !== 0x5b) return;
|
||||
var err = new Error("no arrays");
|
||||
err.status = 400;
|
||||
throw err;
|
||||
},
|
||||
});
|
||||
|
||||
request(app)
|
||||
.post("/")
|
||||
.set("Content-Type", "application/json")
|
||||
.send('["tobi"]')
|
||||
.expect(400, "[entity.verify.failed] no arrays", done);
|
||||
});
|
||||
|
||||
it("should allow custom type", function (done) {
|
||||
var app = createApp({
|
||||
verify: function (req, res, buf) {
|
||||
if (buf[0] !== 0x5b) return;
|
||||
var err = new Error("no arrays");
|
||||
err.type = "foo.bar";
|
||||
throw err;
|
||||
},
|
||||
});
|
||||
|
||||
request(app)
|
||||
.post("/")
|
||||
.set("Content-Type", "application/json")
|
||||
.send('["tobi"]')
|
||||
.expect(403, "[foo.bar] no arrays", done);
|
||||
});
|
||||
|
||||
it("should include original body on error object", function (done) {
|
||||
var app = createApp({
|
||||
verify: function (req, res, buf) {
|
||||
if (buf[0] === 0x5b) throw new Error("no arrays");
|
||||
},
|
||||
});
|
||||
|
||||
request(app)
|
||||
.post("/")
|
||||
.set("Content-Type", "application/json")
|
||||
.set("X-Error-Property", "body")
|
||||
.send('["tobi"]')
|
||||
.expect(403, '["tobi"]', done);
|
||||
});
|
||||
|
||||
it("should allow pass-through", function (done) {
|
||||
var app = createApp({
|
||||
verify: function (req, res, buf) {
|
||||
if (buf[0] === 0x5b) throw new Error("no arrays");
|
||||
},
|
||||
});
|
||||
|
||||
request(app)
|
||||
.post("/")
|
||||
.set("Content-Type", "application/json")
|
||||
.send('{"user":"tobi"}')
|
||||
.expect(200, '{"user":"tobi"}', done);
|
||||
});
|
||||
|
||||
it("should work with different charsets", function (done) {
|
||||
var app = createApp({
|
||||
verify: function (req, res, buf) {
|
||||
if (buf[0] === 0x5b) throw new Error("no arrays");
|
||||
},
|
||||
});
|
||||
|
||||
var test = request(app).post("/");
|
||||
test.set("Content-Type", "application/json; charset=utf-16");
|
||||
test.write(Buffer.from("feff007b0022006e0061006d00650022003a00228bba0022007d", "hex"));
|
||||
test.expect(200, '{"name":"论"}', done);
|
||||
});
|
||||
|
||||
it("should 415 on unknown charset prior to verify", function (done) {
|
||||
var app = createApp({
|
||||
verify: function (req, res, buf) {
|
||||
throw new Error("unexpected verify call");
|
||||
},
|
||||
});
|
||||
|
||||
var test = request(app).post("/");
|
||||
test.set("Content-Type", "application/json; charset=x-bogus");
|
||||
test.write(Buffer.from("00000000", "hex"));
|
||||
test.expect(415, '[charset.unsupported] unsupported charset "X-BOGUS"', done);
|
||||
});
|
||||
});
|
||||
|
||||
describe.todo("async local storage", function () {
|
||||
beforeAll(function () {
|
||||
var app = express();
|
||||
var store = { foo: "bar" };
|
||||
|
||||
app.use(function (req, res, next) {
|
||||
req.asyncLocalStorage = new AsyncLocalStorage();
|
||||
req.asyncLocalStorage.run(store, next);
|
||||
});
|
||||
|
||||
app.use(express.json());
|
||||
|
||||
app.use(function (req, res, next) {
|
||||
var local = req.asyncLocalStorage.getStore();
|
||||
|
||||
if (local) {
|
||||
res.setHeader("x-store-foo", String(local.foo));
|
||||
}
|
||||
|
||||
next();
|
||||
});
|
||||
|
||||
app.use(function (err, req, res, next) {
|
||||
var local = req.asyncLocalStorage.getStore();
|
||||
|
||||
if (local) {
|
||||
res.setHeader("x-store-foo", String(local.foo));
|
||||
}
|
||||
|
||||
res.status(err.status || 500);
|
||||
res.send("[" + err.type + "] " + err.message);
|
||||
});
|
||||
|
||||
app.post("/", function (req, res) {
|
||||
res.json(req.body);
|
||||
});
|
||||
|
||||
app = app;
|
||||
});
|
||||
|
||||
it("should presist store", function (done) {
|
||||
request(app)
|
||||
.post("/")
|
||||
.set("Content-Type", "application/json")
|
||||
.send('{"user":"tobi"}')
|
||||
.expect(200)
|
||||
.expect("x-store-foo", "bar")
|
||||
.expect('{"user":"tobi"}')
|
||||
.end(done);
|
||||
});
|
||||
|
||||
it("should persist store when unmatched content-type", function (done) {
|
||||
request(app)
|
||||
.post("/")
|
||||
.set("Content-Type", "application/fizzbuzz")
|
||||
.send("buzz")
|
||||
.expect(200)
|
||||
.expect("x-store-foo", "bar")
|
||||
.expect("")
|
||||
.end(done);
|
||||
});
|
||||
|
||||
it("should presist store when inflated", function (done) {
|
||||
var test = request(app).post("/");
|
||||
test.set("Content-Encoding", "gzip");
|
||||
test.set("Content-Type", "application/json");
|
||||
test.write(Buffer.from("1f8b080000000000000bab56ca4bcc4d55b2527ab16e97522d00515be1cc0e000000", "hex"));
|
||||
test.expect(200);
|
||||
test.expect("x-store-foo", "bar");
|
||||
test.expect('{"name":"论"}');
|
||||
test.end(done);
|
||||
});
|
||||
|
||||
it("should presist store when inflate error", function (done) {
|
||||
var test = request(app).post("/");
|
||||
test.set("Content-Encoding", "gzip");
|
||||
test.set("Content-Type", "application/json");
|
||||
test.write(Buffer.from("1f8b080000000000000bab56cc4d55b2527ab16e97522d00515be1cc0e000000", "hex"));
|
||||
test.expect(400);
|
||||
test.expect("x-store-foo", "bar");
|
||||
test.end(done);
|
||||
});
|
||||
|
||||
it("should presist store when parse error", function (done) {
|
||||
request(app)
|
||||
.post("/")
|
||||
.set("Content-Type", "application/json")
|
||||
.send('{"user":')
|
||||
.expect(400)
|
||||
.expect("x-store-foo", "bar")
|
||||
.end(done);
|
||||
});
|
||||
|
||||
it("should presist store when limit exceeded", function (done) {
|
||||
request(app)
|
||||
.post("/")
|
||||
.set("Content-Type", "application/json")
|
||||
.send('{"user":"' + Buffer.alloc(1024 * 100, ".").toString() + '"}')
|
||||
.expect(413)
|
||||
.expect("x-store-foo", "bar")
|
||||
.end(done);
|
||||
});
|
||||
});
|
||||
|
||||
describe("charset", function () {
|
||||
beforeAll(function () {
|
||||
app = createApp();
|
||||
});
|
||||
|
||||
it("should parse utf-8", function (done) {
|
||||
var test = request(app).post("/");
|
||||
test.set("Content-Type", "application/json; charset=utf-8");
|
||||
test.write(Buffer.from("7b226e616d65223a22e8aeba227d", "hex"));
|
||||
test.expect(200, '{"name":"论"}', done);
|
||||
});
|
||||
|
||||
it("should parse utf-16", function (done) {
|
||||
var test = request(app).post("/");
|
||||
test.set("Content-Type", "application/json; charset=utf-16");
|
||||
test.write(Buffer.from("feff007b0022006e0061006d00650022003a00228bba0022007d", "hex"));
|
||||
test.expect(200, '{"name":"论"}', done);
|
||||
});
|
||||
|
||||
it("should parse when content-length != char length", function (done) {
|
||||
var test = request(app).post("/");
|
||||
test.set("Content-Type", "application/json; charset=utf-8");
|
||||
test.set("Content-Length", "13");
|
||||
test.write(Buffer.from("7b2274657374223a22c3a5227d", "hex"));
|
||||
test.expect(200, '{"test":"å"}', done);
|
||||
});
|
||||
|
||||
it("should default to utf-8", function (done) {
|
||||
var test = request(app).post("/");
|
||||
test.set("Content-Type", "application/json");
|
||||
test.write(Buffer.from("7b226e616d65223a22e8aeba227d", "hex"));
|
||||
test.expect(200, '{"name":"论"}', done);
|
||||
});
|
||||
|
||||
it("should fail on unknown charset", function (done) {
|
||||
var test = request(app).post("/");
|
||||
test.set("Content-Type", "application/json; charset=koi8-r");
|
||||
test.write(Buffer.from("7b226e616d65223a22cec5d4227d", "hex"));
|
||||
test.expect(415, '[charset.unsupported] unsupported charset "KOI8-R"', done);
|
||||
});
|
||||
});
|
||||
|
||||
describe("encoding", function () {
|
||||
let app;
|
||||
beforeAll(function () {
|
||||
app = createApp({ limit: "1kb" });
|
||||
});
|
||||
|
||||
it("should parse without encoding", function (done) {
|
||||
var test = request(app).post("/");
|
||||
test.set("Content-Type", "application/json");
|
||||
test.write(Buffer.from("7b226e616d65223a22e8aeba227d", "hex"));
|
||||
test.expect(200, '{"name":"论"}', done);
|
||||
});
|
||||
|
||||
it("should support identity encoding", function (done) {
|
||||
var test = request(app).post("/");
|
||||
test.set("Content-Encoding", "identity");
|
||||
test.set("Content-Type", "application/json");
|
||||
test.write(Buffer.from("7b226e616d65223a22e8aeba227d", "hex"));
|
||||
test.expect(200, '{"name":"论"}', done);
|
||||
});
|
||||
|
||||
it("should support gzip encoding", function (done) {
|
||||
var test = request(app).post("/");
|
||||
test.set("Content-Encoding", "gzip");
|
||||
test.set("Content-Type", "application/json");
|
||||
test.write(Buffer.from("1f8b080000000000000bab56ca4bcc4d55b2527ab16e97522d00515be1cc0e000000", "hex"));
|
||||
test.expect(200, '{"name":"论"}', done);
|
||||
});
|
||||
|
||||
it("should support deflate encoding", function (done) {
|
||||
var test = request(app).post("/");
|
||||
test.set("Content-Encoding", "deflate");
|
||||
test.set("Content-Type", "application/json");
|
||||
test.write(Buffer.from("789cab56ca4bcc4d55b2527ab16e97522d00274505ac", "hex"));
|
||||
test.expect(200, '{"name":"论"}', done);
|
||||
});
|
||||
|
||||
it("should be case-insensitive", function (done) {
|
||||
var test = request(app).post("/");
|
||||
test.set("Content-Encoding", "GZIP");
|
||||
test.set("Content-Type", "application/json");
|
||||
test.write(Buffer.from("1f8b080000000000000bab56ca4bcc4d55b2527ab16e97522d00515be1cc0e000000", "hex"));
|
||||
test.expect(200, '{"name":"论"}', done);
|
||||
});
|
||||
|
||||
it("should 415 on unknown encoding", function (done) {
|
||||
var test = request(app).post("/");
|
||||
test.set("Content-Encoding", "nulls");
|
||||
test.set("Content-Type", "application/json");
|
||||
test.write(Buffer.from("000000000000", "hex"));
|
||||
test.expect(415, '[encoding.unsupported] unsupported content encoding "nulls"', done);
|
||||
});
|
||||
|
||||
it("should 400 on malformed encoding", function (done) {
|
||||
var test = request(app).post("/");
|
||||
test.set("Content-Encoding", "gzip");
|
||||
test.set("Content-Type", "application/json");
|
||||
test.write(Buffer.from("1f8b080000000000000bab56cc4d55b2527ab16e97522d00515be1cc0e000000", "hex"));
|
||||
test.expect(400, done);
|
||||
});
|
||||
|
||||
it("should 413 when inflated value exceeds limit", function (done) {
|
||||
// gzip'd data exceeds 1kb, but deflated below 1kb
|
||||
var test = request(app).post("/");
|
||||
test.set("Content-Encoding", "gzip");
|
||||
test.set("Content-Type", "application/json");
|
||||
test.write(Buffer.from("1f8b080000000000000bedc1010d000000c2a0f74f6d0f071400000000000000", "hex"));
|
||||
test.write(Buffer.from("0000000000000000000000000000000000000000000000000000000000000000", "hex"));
|
||||
test.write(Buffer.from("0000000000000000004f0625b3b71650c30000", "hex"));
|
||||
test.expect(413, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function createApp(options?) {
|
||||
var app = express();
|
||||
|
||||
app.use(express.json(options));
|
||||
|
||||
app.use(function (err, req, res, next) {
|
||||
// console.log(err)
|
||||
res.status(err.status || 500);
|
||||
res.send(
|
||||
String(
|
||||
req.headers["x-error-property"] ? err[req.headers["x-error-property"]] : "[" + err.type + "] " + err.message,
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
app.post("/", function (req, res) {
|
||||
res.json(req.body);
|
||||
});
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
function parseError(str) {
|
||||
try {
|
||||
JSON.parse(str);
|
||||
throw new SyntaxError("strict violation");
|
||||
} catch (e) {
|
||||
return e.message;
|
||||
}
|
||||
}
|
||||
|
||||
function shouldContainInBody(str) {
|
||||
return function (res) {
|
||||
assert.ok(res.text.indexOf(str) !== -1, "expected '" + res.text + "' to contain '" + str + "'");
|
||||
};
|
||||
}
|
||||
44
test/js/third_party/express/express.test.ts
vendored
44
test/js/third_party/express/express.test.ts
vendored
@@ -1,44 +0,0 @@
|
||||
// @ts-nocheck
|
||||
// can't use @types/express or @types/body-parser because they
|
||||
// depend on @types/node which conflicts with bun-types
|
||||
import { expect, test } from "bun:test";
|
||||
import express from "express";
|
||||
import { isIPv6 } from "node:net";
|
||||
// https://github.com/oven-sh/bun/issues/8926
|
||||
test("should respond with 404 when wrong method is used", async () => {
|
||||
const { promise: serve, resolve } = Promise.withResolvers();
|
||||
const app = express();
|
||||
app.use(express.json());
|
||||
|
||||
app.get("/api/hotels", (req, res) => {
|
||||
res.json({
|
||||
success: true,
|
||||
});
|
||||
});
|
||||
|
||||
const server = app.listen(0, (_, host, port) => {
|
||||
if (isIPv6(host)) {
|
||||
resolve(`http://[${host}]:${port}`);
|
||||
} else {
|
||||
resolve(`http://${host}:${port}`);
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
const url = await serve;
|
||||
const response = await fetch(`${url}/api/hotels`, {
|
||||
method: "POST",
|
||||
signal: AbortSignal.timeout(500),
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name: "Hotel 1",
|
||||
price: 100,
|
||||
}),
|
||||
});
|
||||
expect(response.status).toBe(404);
|
||||
} finally {
|
||||
server.close();
|
||||
}
|
||||
});
|
||||
531
test/js/third_party/express/express.text.test.ts
vendored
531
test/js/third_party/express/express.text.test.ts
vendored
@@ -1,531 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
var assert = require("node:assert");
|
||||
var AsyncLocalStorage = require("node:async_hooks").AsyncLocalStorage;
|
||||
|
||||
var express = require("express");
|
||||
var request = require("supertest");
|
||||
|
||||
describe("express.text()", function () {
|
||||
let app;
|
||||
|
||||
beforeAll(function () {
|
||||
app = createApp();
|
||||
});
|
||||
|
||||
it("should parse text/plain", function (done) {
|
||||
request(app).post("/").set("Content-Type", "text/plain").send("user is tobi").expect(200, '"user is tobi"', done);
|
||||
});
|
||||
|
||||
it("should 400 when invalid content-length", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res, next) {
|
||||
req.headers["content-length"] = "20"; // bad length
|
||||
next();
|
||||
});
|
||||
|
||||
app.use(express.text());
|
||||
|
||||
app.post("/", function (req, res) {
|
||||
res.json(req.body);
|
||||
});
|
||||
|
||||
request(app)
|
||||
.post("/")
|
||||
.set("Content-Type", "text/plain")
|
||||
.send("user")
|
||||
.expect(400, /content length/, done);
|
||||
});
|
||||
|
||||
it("should handle Content-Length: 0", function (done) {
|
||||
request(createApp({ limit: "1kb" }))
|
||||
.post("/")
|
||||
.set("Content-Type", "text/plain")
|
||||
.set("Content-Length", "0")
|
||||
.expect(200, '""', done);
|
||||
});
|
||||
|
||||
it.todo("should handle empty message-body", function (done) {
|
||||
request(createApp({ limit: "1kb" }))
|
||||
.post("/")
|
||||
.set("Content-Type", "text/plain")
|
||||
.set("Transfer-Encoding", "chunked")
|
||||
.send("")
|
||||
.expect(200, '""', done);
|
||||
});
|
||||
|
||||
it("should handle duplicated middleware", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(express.text());
|
||||
app.use(express.text());
|
||||
|
||||
app.post("/", function (req, res) {
|
||||
res.json(req.body);
|
||||
});
|
||||
|
||||
request(app).post("/").set("Content-Type", "text/plain").send("user is tobi").expect(200, '"user is tobi"', done);
|
||||
});
|
||||
|
||||
describe("with defaultCharset option", function () {
|
||||
it("should change default charset", function (done) {
|
||||
var server = createApp({ defaultCharset: "koi8-r" });
|
||||
var test = request(server).post("/");
|
||||
test.set("Content-Type", "text/plain");
|
||||
test.write(Buffer.from("6e616d6520697320cec5d4", "hex"));
|
||||
test.expect(200, '"name is нет"', done);
|
||||
});
|
||||
|
||||
it("should honor content-type charset", function (done) {
|
||||
var server = createApp({ defaultCharset: "koi8-r" });
|
||||
var test = request(server).post("/");
|
||||
test.set("Content-Type", "text/plain; charset=utf-8");
|
||||
test.write(Buffer.from("6e616d6520697320e8aeba", "hex"));
|
||||
test.expect(200, '"name is 论"', done);
|
||||
});
|
||||
});
|
||||
|
||||
describe("with limit option", function () {
|
||||
it("should 413 when over limit with Content-Length", function (done) {
|
||||
var buf = Buffer.alloc(1028, ".");
|
||||
request(createApp({ limit: "1kb" }))
|
||||
.post("/")
|
||||
.set("Content-Type", "text/plain")
|
||||
.set("Content-Length", "1028")
|
||||
.send(buf.toString())
|
||||
.expect(413, done);
|
||||
});
|
||||
|
||||
it.todo("should 413 when over limit with chunked encoding", function (done) {
|
||||
var app = createApp({ limit: "1kb" });
|
||||
var buf = Buffer.alloc(1028, ".");
|
||||
var test = request(app).post("/");
|
||||
test.set("Content-Type", "text/plain");
|
||||
test.set("Transfer-Encoding", "chunked");
|
||||
test.write(buf.toString());
|
||||
test.expect(413, done);
|
||||
});
|
||||
|
||||
it("should 413 when inflated body over limit", function (done) {
|
||||
var app = createApp({ limit: "1kb" });
|
||||
var test = request(app).post("/");
|
||||
test.set("Content-Encoding", "gzip");
|
||||
test.set("Content-Type", "text/plain");
|
||||
test.write(Buffer.from("1f8b080000000000000ad3d31b05a360148c64000087e5a14704040000", "hex"));
|
||||
test.expect(413, done);
|
||||
});
|
||||
|
||||
it("should accept number of bytes", function (done) {
|
||||
var buf = Buffer.alloc(1028, ".");
|
||||
request(createApp({ limit: 1024 }))
|
||||
.post("/")
|
||||
.set("Content-Type", "text/plain")
|
||||
.send(buf.toString())
|
||||
.expect(413, done);
|
||||
});
|
||||
|
||||
it("should not change when options altered", function (done) {
|
||||
var buf = Buffer.alloc(1028, ".");
|
||||
var options = { limit: "1kb" };
|
||||
var app = createApp(options);
|
||||
|
||||
options.limit = "100kb";
|
||||
|
||||
request(app).post("/").set("Content-Type", "text/plain").send(buf.toString()).expect(413, done);
|
||||
});
|
||||
|
||||
it("should not hang response", function (done) {
|
||||
var app = createApp({ limit: "8kb" });
|
||||
var buf = Buffer.alloc(10240, ".");
|
||||
var test = request(app).post("/");
|
||||
test.set("Content-Type", "text/plain");
|
||||
test.write(buf);
|
||||
test.write(buf);
|
||||
test.write(buf);
|
||||
test.expect(413, done);
|
||||
});
|
||||
|
||||
it("should not error when inflating", function (done) {
|
||||
var app = createApp({ limit: "1kb" });
|
||||
var test = request(app).post("/");
|
||||
test.set("Content-Encoding", "gzip");
|
||||
test.set("Content-Type", "text/plain");
|
||||
test.write(Buffer.from("1f8b080000000000000ad3d31b05a360148c64000087e5a1470404", "hex"));
|
||||
setTimeout(function () {
|
||||
test.expect(413, done);
|
||||
}, 100);
|
||||
});
|
||||
});
|
||||
|
||||
describe("with inflate option", function () {
|
||||
describe.todo("when false", function () {
|
||||
beforeAll(function () {
|
||||
app = createApp({ inflate: false });
|
||||
});
|
||||
|
||||
it("should not accept content-encoding", function (done) {
|
||||
var test = request(app).post("/");
|
||||
test.set("Content-Encoding", "gzip");
|
||||
test.set("Content-Type", "text/plain");
|
||||
test.write(Buffer.from("1f8b080000000000000bcb4bcc4d55c82c5678b16e170072b3e0200b000000", "hex"));
|
||||
test.expect(415, "[encoding.unsupported] content encoding unsupported", done);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when true", function () {
|
||||
beforeAll(function () {
|
||||
app = createApp({ inflate: true });
|
||||
});
|
||||
|
||||
it("should accept content-encoding", function (done) {
|
||||
var test = request(app).post("/");
|
||||
test.set("Content-Encoding", "gzip");
|
||||
test.set("Content-Type", "text/plain");
|
||||
test.write(Buffer.from("1f8b080000000000000bcb4bcc4d55c82c5678b16e170072b3e0200b000000", "hex"));
|
||||
test.expect(200, '"name is 论"', done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("with type option", function () {
|
||||
describe.todo('when "text/html"', function () {
|
||||
beforeAll(function () {
|
||||
app = createApp({ type: "text/html" });
|
||||
});
|
||||
|
||||
it("should parse for custom type", function (done) {
|
||||
request(app).post("/").set("Content-Type", "text/html").send("<b>tobi</b>").expect(200, '"<b>tobi</b>"', done);
|
||||
});
|
||||
|
||||
it("should ignore standard type", function (done) {
|
||||
request(app).post("/").set("Content-Type", "text/plain").send("user is tobi").expect(200, "", done);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when ["text/html", "text/plain"]', function () {
|
||||
beforeAll(function () {
|
||||
app = createApp({ type: ["text/html", "text/plain"] });
|
||||
});
|
||||
|
||||
it.todo('should parse "text/html"', function (done) {
|
||||
request(app).post("/").set("Content-Type", "text/html").send("<b>tobi</b>").expect(200, '"<b>tobi</b>"', done);
|
||||
});
|
||||
|
||||
it('should parse "text/plain"', function (done) {
|
||||
request(app).post("/").set("Content-Type", "text/plain").send("tobi").expect(200, '"tobi"', done);
|
||||
});
|
||||
|
||||
it.todo('should ignore "text/xml"', function (done) {
|
||||
request(app).post("/").set("Content-Type", "text/xml").send("<user>tobi</user>").expect(200, "", done);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when a function", function () {
|
||||
it("should parse when truthy value returned", function (done) {
|
||||
var app = createApp({ type: accept });
|
||||
|
||||
function accept(req) {
|
||||
return req.headers["content-type"] === "text/vnd.something";
|
||||
}
|
||||
|
||||
request(app)
|
||||
.post("/")
|
||||
.set("Content-Type", "text/vnd.something")
|
||||
.send("user is tobi")
|
||||
.expect(200, '"user is tobi"', done);
|
||||
});
|
||||
|
||||
it("should work without content-type", function (done) {
|
||||
var app = createApp({ type: accept });
|
||||
|
||||
function accept(req) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var test = request(app).post("/");
|
||||
test.write("user is tobi");
|
||||
test.expect(200, '"user is tobi"', done);
|
||||
});
|
||||
|
||||
it("should not invoke without a body", function (done) {
|
||||
var app = createApp({ type: accept });
|
||||
|
||||
function accept(req) {
|
||||
throw new Error("oops!");
|
||||
}
|
||||
|
||||
request(app).get("/").expect(404, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("with verify option", function () {
|
||||
it("should assert value is function", function () {
|
||||
assert.throws(createApp.bind(null, { verify: "lol" }), /TypeError: option verify must be function/);
|
||||
});
|
||||
|
||||
it("should error from verify", function (done) {
|
||||
var app = createApp({
|
||||
verify: function (req, res, buf) {
|
||||
if (buf[0] === 0x20) throw new Error("no leading space");
|
||||
},
|
||||
});
|
||||
|
||||
request(app)
|
||||
.post("/")
|
||||
.set("Content-Type", "text/plain")
|
||||
.send(" user is tobi")
|
||||
.expect(403, "[entity.verify.failed] no leading space", done);
|
||||
});
|
||||
|
||||
it("should allow custom codes", function (done) {
|
||||
var app = createApp({
|
||||
verify: function (req, res, buf) {
|
||||
if (buf[0] !== 0x20) return;
|
||||
var err = new Error("no leading space");
|
||||
err.status = 400;
|
||||
throw err;
|
||||
},
|
||||
});
|
||||
|
||||
request(app)
|
||||
.post("/")
|
||||
.set("Content-Type", "text/plain")
|
||||
.send(" user is tobi")
|
||||
.expect(400, "[entity.verify.failed] no leading space", done);
|
||||
});
|
||||
|
||||
it("should allow pass-through", function (done) {
|
||||
var app = createApp({
|
||||
verify: function (req, res, buf) {
|
||||
if (buf[0] === 0x20) throw new Error("no leading space");
|
||||
},
|
||||
});
|
||||
|
||||
request(app).post("/").set("Content-Type", "text/plain").send("user is tobi").expect(200, '"user is tobi"', done);
|
||||
});
|
||||
|
||||
it("should 415 on unknown charset prior to verify", function (done) {
|
||||
var app = createApp({
|
||||
verify: function (req, res, buf) {
|
||||
throw new Error("unexpected verify call");
|
||||
},
|
||||
});
|
||||
|
||||
var test = request(app).post("/");
|
||||
test.set("Content-Type", "text/plain; charset=x-bogus");
|
||||
test.write(Buffer.from("00000000", "hex"));
|
||||
test.expect(415, '[charset.unsupported] unsupported charset "X-BOGUS"', done);
|
||||
});
|
||||
});
|
||||
|
||||
describe.todo("async local storage", function () {
|
||||
beforeAll(function () {
|
||||
var app = express();
|
||||
var store = { foo: "bar" };
|
||||
|
||||
app.use(function (req, res, next) {
|
||||
req.asyncLocalStorage = new AsyncLocalStorage();
|
||||
req.asyncLocalStorage.run(store, next);
|
||||
});
|
||||
|
||||
app.use(express.text());
|
||||
|
||||
app.use(function (req, res, next) {
|
||||
var local = req.asyncLocalStorage.getStore();
|
||||
|
||||
if (local) {
|
||||
res.setHeader("x-store-foo", String(local.foo));
|
||||
}
|
||||
|
||||
next();
|
||||
});
|
||||
|
||||
app.use(function (err, req, res, next) {
|
||||
var local = req.asyncLocalStorage.getStore();
|
||||
|
||||
if (local) {
|
||||
res.setHeader("x-store-foo", String(local.foo));
|
||||
}
|
||||
|
||||
res.status(err.status || 500);
|
||||
res.send("[" + err.type + "] " + err.message);
|
||||
});
|
||||
|
||||
app.post("/", function (req, res) {
|
||||
res.json(req.body);
|
||||
});
|
||||
|
||||
app = app;
|
||||
});
|
||||
|
||||
it("should presist store", function (done) {
|
||||
request(app)
|
||||
.post("/")
|
||||
.set("Content-Type", "text/plain")
|
||||
.send("user is tobi")
|
||||
.expect(200)
|
||||
.expect("x-store-foo", "bar")
|
||||
.expect('"user is tobi"')
|
||||
.end(done);
|
||||
});
|
||||
|
||||
it("should presist store when unmatched content-type", function (done) {
|
||||
request(app)
|
||||
.post("/")
|
||||
.set("Content-Type", "application/fizzbuzz")
|
||||
.send("buzz")
|
||||
.expect(200)
|
||||
.expect("x-store-foo", "bar")
|
||||
.end(done);
|
||||
});
|
||||
|
||||
it("should presist store when inflated", function (done) {
|
||||
var test = request(app).post("/");
|
||||
test.set("Content-Encoding", "gzip");
|
||||
test.set("Content-Type", "text/plain");
|
||||
test.write(Buffer.from("1f8b080000000000000bcb4bcc4d55c82c5678b16e170072b3e0200b000000", "hex"));
|
||||
test.expect(200);
|
||||
test.expect("x-store-foo", "bar");
|
||||
test.expect('"name is 论"');
|
||||
test.end(done);
|
||||
});
|
||||
|
||||
it("should presist store when inflate error", function (done) {
|
||||
var test = request(app).post("/");
|
||||
test.set("Content-Encoding", "gzip");
|
||||
test.set("Content-Type", "text/plain");
|
||||
test.write(Buffer.from("1f8b080000000000000bcb4bcc4d55c82c5678b16e170072b3e0200b0000", "hex"));
|
||||
test.expect(400);
|
||||
test.expect("x-store-foo", "bar");
|
||||
test.end(done);
|
||||
});
|
||||
|
||||
it("should presist store when limit exceeded", function (done) {
|
||||
request(app)
|
||||
.post("/")
|
||||
.set("Content-Type", "text/plain")
|
||||
.send("user is " + Buffer.alloc(1024 * 100, ".").toString())
|
||||
.expect(413)
|
||||
.expect("x-store-foo", "bar")
|
||||
.end(done);
|
||||
});
|
||||
});
|
||||
|
||||
describe("charset", function () {
|
||||
beforeAll(function () {
|
||||
app = createApp();
|
||||
});
|
||||
|
||||
it("should parse utf-8", function (done) {
|
||||
var test = request(app).post("/");
|
||||
test.set("Content-Type", "text/plain; charset=utf-8");
|
||||
test.write(Buffer.from("6e616d6520697320e8aeba", "hex"));
|
||||
test.expect(200, '"name is 论"', done);
|
||||
});
|
||||
|
||||
it("should parse codepage charsets", function (done) {
|
||||
var test = request(app).post("/");
|
||||
test.set("Content-Type", "text/plain; charset=koi8-r");
|
||||
test.write(Buffer.from("6e616d6520697320cec5d4", "hex"));
|
||||
test.expect(200, '"name is нет"', done);
|
||||
});
|
||||
|
||||
it("should parse when content-length != char length", function (done) {
|
||||
var test = request(app).post("/");
|
||||
test.set("Content-Type", "text/plain; charset=utf-8");
|
||||
test.set("Content-Length", "11");
|
||||
test.write(Buffer.from("6e616d6520697320e8aeba", "hex"));
|
||||
test.expect(200, '"name is 论"', done);
|
||||
});
|
||||
|
||||
it("should default to utf-8", function (done) {
|
||||
var test = request(app).post("/");
|
||||
test.set("Content-Type", "text/plain");
|
||||
test.write(Buffer.from("6e616d6520697320e8aeba", "hex"));
|
||||
test.expect(200, '"name is 论"', done);
|
||||
});
|
||||
|
||||
it("should 415 on unknown charset", function (done) {
|
||||
var test = request(app).post("/");
|
||||
test.set("Content-Type", "text/plain; charset=x-bogus");
|
||||
test.write(Buffer.from("00000000", "hex"));
|
||||
test.expect(415, '[charset.unsupported] unsupported charset "X-BOGUS"', done);
|
||||
});
|
||||
});
|
||||
|
||||
describe("encoding", function () {
|
||||
beforeAll(function () {
|
||||
app = createApp({ limit: "10kb" });
|
||||
});
|
||||
|
||||
it("should parse without encoding", function (done) {
|
||||
var test = request(app).post("/");
|
||||
test.set("Content-Type", "text/plain");
|
||||
test.write(Buffer.from("6e616d6520697320e8aeba", "hex"));
|
||||
test.expect(200, '"name is 论"', done);
|
||||
});
|
||||
|
||||
it("should support identity encoding", function (done) {
|
||||
var test = request(app).post("/");
|
||||
test.set("Content-Encoding", "identity");
|
||||
test.set("Content-Type", "text/plain");
|
||||
test.write(Buffer.from("6e616d6520697320e8aeba", "hex"));
|
||||
test.expect(200, '"name is 论"', done);
|
||||
});
|
||||
|
||||
it("should support gzip encoding", function (done) {
|
||||
var test = request(app).post("/");
|
||||
test.set("Content-Encoding", "gzip");
|
||||
test.set("Content-Type", "text/plain");
|
||||
test.write(Buffer.from("1f8b080000000000000bcb4bcc4d55c82c5678b16e170072b3e0200b000000", "hex"));
|
||||
test.expect(200, '"name is 论"', done);
|
||||
});
|
||||
|
||||
it("should support deflate encoding", function (done) {
|
||||
var test = request(app).post("/");
|
||||
test.set("Content-Encoding", "deflate");
|
||||
test.set("Content-Type", "text/plain");
|
||||
test.write(Buffer.from("789ccb4bcc4d55c82c5678b16e17001a6f050e", "hex"));
|
||||
test.expect(200, '"name is 论"', done);
|
||||
});
|
||||
|
||||
it("should be case-insensitive", function (done) {
|
||||
var test = request(app).post("/");
|
||||
test.set("Content-Encoding", "GZIP");
|
||||
test.set("Content-Type", "text/plain");
|
||||
test.write(Buffer.from("1f8b080000000000000bcb4bcc4d55c82c5678b16e170072b3e0200b000000", "hex"));
|
||||
test.expect(200, '"name is 论"', done);
|
||||
});
|
||||
|
||||
it("should 415 on unknown encoding", function (done) {
|
||||
var test = request(app).post("/");
|
||||
test.set("Content-Encoding", "nulls");
|
||||
test.set("Content-Type", "text/plain");
|
||||
test.write(Buffer.from("000000000000", "hex"));
|
||||
test.expect(415, '[encoding.unsupported] unsupported content encoding "nulls"', done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function createApp(options) {
|
||||
var app = express();
|
||||
|
||||
app.use(express.text(options));
|
||||
|
||||
app.use(function (err, req, res, next) {
|
||||
res.status(err.status || 500);
|
||||
res.send(
|
||||
String(
|
||||
req.headers["x-error-property"] ? err[req.headers["x-error-property"]] : "[" + err.type + "] " + err.message,
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
app.post("/", function (req, res) {
|
||||
res.json(req.body);
|
||||
});
|
||||
|
||||
return app;
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
20%
|
||||
1
test/js/third_party/express/fixtures/.name
vendored
1
test/js/third_party/express/fixtures/.name
vendored
@@ -1 +0,0 @@
|
||||
tobi
|
||||
@@ -1 +0,0 @@
|
||||
<b>index</b>
|
||||
@@ -1 +0,0 @@
|
||||
<h1>blog post</h1>
|
||||
@@ -1 +0,0 @@
|
||||
tobi
|
||||
@@ -1 +0,0 @@
|
||||
123456789
|
||||
@@ -1 +0,0 @@
|
||||
<p>{{user.name}}</p>
|
||||
7
test/js/third_party/express/package.json
vendored
7
test/js/third_party/express/package.json
vendored
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"name": "express-test",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"express": "4.18.2"
|
||||
}
|
||||
}
|
||||
170
test/js/third_party/express/res.json.test.ts
vendored
170
test/js/third_party/express/res.json.test.ts
vendored
@@ -1,170 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
var express = require("express"),
|
||||
request = require("supertest"),
|
||||
assert = require("node:assert");
|
||||
|
||||
describe("res", function () {
|
||||
describe(".json(object)", function () {
|
||||
it("should not support jsonp callbacks", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.json({ foo: "bar" });
|
||||
});
|
||||
|
||||
request(app).get("/?callback=foo").expect('{"foo":"bar"}', done);
|
||||
});
|
||||
|
||||
it("should not override previous Content-Types", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.get("/", function (req, res) {
|
||||
res.type("application/vnd.example+json");
|
||||
res.json({ hello: "world" });
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get("/")
|
||||
.expect("Content-Type", "application/vnd.example+json; charset=utf-8")
|
||||
.expect(200, '{"hello":"world"}', done);
|
||||
});
|
||||
|
||||
describe("when given primitives", function () {
|
||||
it("should respond with json for null", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.json(null);
|
||||
});
|
||||
|
||||
request(app).get("/").expect("Content-Type", "application/json; charset=utf-8").expect(200, "null", done);
|
||||
});
|
||||
|
||||
it("should respond with json for Number", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.json(300);
|
||||
});
|
||||
|
||||
request(app).get("/").expect("Content-Type", "application/json; charset=utf-8").expect(200, "300", done);
|
||||
});
|
||||
|
||||
it("should respond with json for String", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.json("str");
|
||||
});
|
||||
|
||||
request(app).get("/").expect("Content-Type", "application/json; charset=utf-8").expect(200, '"str"', done);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when given an array", function () {
|
||||
it("should respond with json", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.json(["foo", "bar", "baz"]);
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get("/")
|
||||
.expect("Content-Type", "application/json; charset=utf-8")
|
||||
.expect(200, '["foo","bar","baz"]', done);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when given an object", function () {
|
||||
it("should respond with json", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.json({ name: "tobi" });
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get("/")
|
||||
.expect("Content-Type", "application/json; charset=utf-8")
|
||||
.expect(200, '{"name":"tobi"}', done);
|
||||
});
|
||||
});
|
||||
|
||||
describe('"json escape" setting', function () {
|
||||
it("should be undefined by default", function () {
|
||||
var app = express();
|
||||
assert.strictEqual(app.get("json escape"), undefined);
|
||||
});
|
||||
|
||||
it("should unicode escape HTML-sniffing characters", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.enable("json escape");
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.json({ "&": "<script>" });
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get("/")
|
||||
.expect("Content-Type", "application/json; charset=utf-8")
|
||||
.expect(200, '{"\\u0026":"\\u003cscript\\u003e"}', done);
|
||||
});
|
||||
|
||||
it("should not break undefined escape", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.enable("json escape");
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.json(undefined);
|
||||
});
|
||||
|
||||
request(app).get("/").expect("Content-Type", "application/json; charset=utf-8").expect(200, "", done);
|
||||
});
|
||||
});
|
||||
|
||||
describe('"json replacer" setting', function () {
|
||||
it("should be passed to JSON.stringify()", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.set("json replacer", function (key, val) {
|
||||
return key[0] === "_" ? undefined : val;
|
||||
});
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.json({ name: "tobi", _id: 12345 });
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get("/")
|
||||
.expect("Content-Type", "application/json; charset=utf-8")
|
||||
.expect(200, '{"name":"tobi"}', done);
|
||||
});
|
||||
});
|
||||
|
||||
describe('"json spaces" setting', function () {
|
||||
it("should be undefined by default", function () {
|
||||
var app = express();
|
||||
assert(undefined === app.get("json spaces"));
|
||||
});
|
||||
|
||||
it("should be passed to JSON.stringify()", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.set("json spaces", 2);
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.json({ name: "tobi", age: 2 });
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get("/")
|
||||
.expect("Content-Type", "application/json; charset=utf-8")
|
||||
.expect(200, '{\n "name": "tobi",\n "age": 2\n}', done);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
316
test/js/third_party/express/res.location.test.ts
vendored
316
test/js/third_party/express/res.location.test.ts
vendored
@@ -1,316 +0,0 @@
|
||||
'use strict'
|
||||
|
||||
var express = require('express')
|
||||
, request = require('supertest')
|
||||
, assert = require('node:assert')
|
||||
, url = require('node:url');
|
||||
|
||||
describe('res', function(){
|
||||
describe('.location(url)', function(){
|
||||
it('should set the header', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
res.location('http://google.com/').end();
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect('Location', 'http://google.com/')
|
||||
.expect(200, done)
|
||||
})
|
||||
|
||||
it('should preserve trailing slashes when not present', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
res.location('http://google.com').end();
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect('Location', 'http://google.com')
|
||||
.expect(200, done)
|
||||
})
|
||||
|
||||
it('should encode "url"', function (done) {
|
||||
var app = express()
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.location('https://google.com?q=\u2603 §10').end()
|
||||
})
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect('Location', 'https://google.com?q=%E2%98%83%20%C2%A710')
|
||||
.expect(200, done)
|
||||
})
|
||||
|
||||
it('should encode data uri1', function (done) {
|
||||
var app = express()
|
||||
app.use(function (req, res) {
|
||||
res.location('data:text/javascript,export default () => { }').end();
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect('Location', 'data:text/javascript,export%20default%20()%20=%3E%20%7B%20%7D')
|
||||
.expect(200, done)
|
||||
})
|
||||
|
||||
it('should encode data uri2', function (done) {
|
||||
var app = express()
|
||||
app.use(function (req, res) {
|
||||
res.location('data:text/javascript,export default () => { }').end();
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect('Location', 'data:text/javascript,export%20default%20()%20=%3E%20%7B%20%7D')
|
||||
.expect(200, done)
|
||||
})
|
||||
|
||||
it('should consistently handle non-string input: boolean', function (done) {
|
||||
var app = express()
|
||||
app.use(function (req, res) {
|
||||
res.location(true).end();
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect('Location', 'true')
|
||||
.expect(200, done)
|
||||
});
|
||||
|
||||
it('should consistently handle non-string inputs: object', function (done) {
|
||||
var app = express()
|
||||
app.use(function (req, res) {
|
||||
res.location({}).end();
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect('Location', '[object%20Object]')
|
||||
.expect(200, done)
|
||||
});
|
||||
|
||||
it.todo('should consistently handle non-string inputs: array', function (done) {
|
||||
var app = express()
|
||||
app.use(function (req, res) {
|
||||
res.location([]).end();
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect('Location', '')
|
||||
.expect(200, done)
|
||||
});
|
||||
|
||||
it.todo('should consistently handle empty string input', function (done) {
|
||||
var app = express()
|
||||
app.use(function (req, res) {
|
||||
res.location('').end();
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect('Location', '')
|
||||
.expect(200, done)
|
||||
});
|
||||
|
||||
|
||||
if (typeof URL !== 'undefined') {
|
||||
it('should accept an instance of URL', function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
res.location(new URL('http://google.com/')).end();
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect('Location', 'http://google.com/')
|
||||
.expect(200, done);
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
describe('location header encoding', function() {
|
||||
function createRedirectServerForDomain (domain) {
|
||||
var app = express();
|
||||
app.use(function (req, res) {
|
||||
var host = url.parse(req.query.q, false, true).host;
|
||||
// This is here to show a basic check one might do which
|
||||
// would pass but then the location header would still be bad
|
||||
if (host !== domain) {
|
||||
res.status(400).end('Bad host: ' + host + ' !== ' + domain);
|
||||
}
|
||||
res.location(req.query.q).end();
|
||||
});
|
||||
return app;
|
||||
}
|
||||
|
||||
function testRequestedRedirect (app, inputUrl, expected, expectedHost, done) {
|
||||
return request(app)
|
||||
// Encode uri because old supertest does not and is required
|
||||
// to test older node versions. New supertest doesn't re-encode
|
||||
// so this works in both.
|
||||
.get('/?q=' + encodeURIComponent(inputUrl))
|
||||
.expect('') // No body.
|
||||
.expect(200)
|
||||
.expect('Location', expected)
|
||||
.end(function (err, res) {
|
||||
if (err) {
|
||||
console.log('headers:', res.headers)
|
||||
console.error('error', res.error, err);
|
||||
return done(err, res);
|
||||
}
|
||||
|
||||
// Parse the hosts from the input URL and the Location header
|
||||
var inputHost = url.parse(inputUrl, false, true).host;
|
||||
var locationHost = url.parse(res.headers['location'], false, true).host;
|
||||
|
||||
assert.strictEqual(locationHost, expectedHost);
|
||||
|
||||
// Assert that the hosts are the same
|
||||
if (inputHost !== locationHost) {
|
||||
return done(new Error('Hosts do not match: ' + inputHost + " !== " + locationHost));
|
||||
}
|
||||
|
||||
return done(null, res);
|
||||
});
|
||||
}
|
||||
|
||||
it('should not touch already-encoded sequences in "url"', function (done) {
|
||||
var app = createRedirectServerForDomain('google.com');
|
||||
testRequestedRedirect(
|
||||
app,
|
||||
'https://google.com?q=%A710',
|
||||
'https://google.com?q=%A710',
|
||||
'google.com',
|
||||
done
|
||||
);
|
||||
});
|
||||
|
||||
it('should consistently handle relative urls', function (done) {
|
||||
var app = createRedirectServerForDomain(null);
|
||||
testRequestedRedirect(
|
||||
app,
|
||||
'/foo/bar',
|
||||
'/foo/bar',
|
||||
null,
|
||||
done
|
||||
);
|
||||
});
|
||||
|
||||
it.todo('should not encode urls in such a way that they can bypass redirect allow lists', function (done) {
|
||||
var app = createRedirectServerForDomain('google.com');
|
||||
testRequestedRedirect(
|
||||
app,
|
||||
'http://google.com\\@apple.com',
|
||||
'http://google.com\\@apple.com',
|
||||
'google.com',
|
||||
done
|
||||
);
|
||||
});
|
||||
|
||||
it.todo('should not be case sensitive', function (done) {
|
||||
var app = createRedirectServerForDomain('google.com');
|
||||
testRequestedRedirect(
|
||||
app,
|
||||
'HTTP://google.com\\@apple.com',
|
||||
'HTTP://google.com\\@apple.com',
|
||||
'google.com',
|
||||
done
|
||||
);
|
||||
});
|
||||
|
||||
it.todo('should work with https', function (done) {
|
||||
var app = createRedirectServerForDomain('google.com');
|
||||
testRequestedRedirect(
|
||||
app,
|
||||
'https://google.com\\@apple.com',
|
||||
'https://google.com\\@apple.com',
|
||||
'google.com',
|
||||
done
|
||||
);
|
||||
});
|
||||
|
||||
it.todo('should correctly encode schemaless paths', function (done) {
|
||||
var app = createRedirectServerForDomain('google.com');
|
||||
testRequestedRedirect(
|
||||
app,
|
||||
'//google.com\\@apple.com/',
|
||||
'//google.com\\@apple.com/',
|
||||
'google.com',
|
||||
done
|
||||
);
|
||||
});
|
||||
|
||||
it.todo('should keep backslashes in the path', function (done) {
|
||||
var app = createRedirectServerForDomain('google.com');
|
||||
testRequestedRedirect(
|
||||
app,
|
||||
'https://google.com/foo\\bar\\baz',
|
||||
'https://google.com/foo\\bar\\baz',
|
||||
'google.com',
|
||||
done
|
||||
);
|
||||
});
|
||||
|
||||
it.todo('should escape header splitting for old node versions', function (done) {
|
||||
var app = createRedirectServerForDomain('google.com');
|
||||
testRequestedRedirect(
|
||||
app,
|
||||
'http://google.com\\@apple.com/%0d%0afoo:%20bar',
|
||||
'http://google.com\\@apple.com/%0d%0afoo:%20bar',
|
||||
'google.com',
|
||||
done
|
||||
);
|
||||
});
|
||||
|
||||
it('should encode unicode correctly', function (done) {
|
||||
var app = createRedirectServerForDomain(null);
|
||||
testRequestedRedirect(
|
||||
app,
|
||||
'/%e2%98%83',
|
||||
'/%e2%98%83',
|
||||
null,
|
||||
done
|
||||
);
|
||||
});
|
||||
|
||||
it.todo('should encode unicode correctly even with a bad host', function (done) {
|
||||
var app = createRedirectServerForDomain('google.com');
|
||||
testRequestedRedirect(
|
||||
app,
|
||||
'http://google.com\\@apple.com/%e2%98%83',
|
||||
'http://google.com\\@apple.com/%e2%98%83',
|
||||
'google.com',
|
||||
done
|
||||
);
|
||||
});
|
||||
|
||||
it('should work correctly despite using deprecated url.parse', function (done) {
|
||||
var app = createRedirectServerForDomain('google.com');
|
||||
testRequestedRedirect(
|
||||
app,
|
||||
'https://google.com\'.bb.com/1.html',
|
||||
'https://google.com\'.bb.com/1.html',
|
||||
'google.com',
|
||||
done
|
||||
);
|
||||
});
|
||||
|
||||
it.todo('should encode file uri path', function (done) {
|
||||
var app = createRedirectServerForDomain('');
|
||||
testRequestedRedirect(
|
||||
app,
|
||||
'file:///etc\\passwd',
|
||||
'file:///etc\\passwd',
|
||||
'',
|
||||
done
|
||||
);
|
||||
});
|
||||
});
|
||||
})
|
||||
214
test/js/third_party/express/res.redirect.test.ts
vendored
214
test/js/third_party/express/res.redirect.test.ts
vendored
@@ -1,214 +0,0 @@
|
||||
'use strict'
|
||||
|
||||
var express = require('express');
|
||||
var request = require('supertest');
|
||||
var utils = require('./support/utils');
|
||||
|
||||
describe('res', function(){
|
||||
describe('.redirect(url)', function(){
|
||||
it('should default to a 302 redirect', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
res.redirect('http://google.com');
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect('location', 'http://google.com')
|
||||
.expect(302, done)
|
||||
})
|
||||
|
||||
it('should encode "url"', function (done) {
|
||||
var app = express()
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.redirect('https://google.com?q=\u2603 §10')
|
||||
})
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect('Location', 'https://google.com?q=%E2%98%83%20%C2%A710')
|
||||
.expect(302, done)
|
||||
})
|
||||
|
||||
it('should not touch already-encoded sequences in "url"', function (done) {
|
||||
var app = express()
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.redirect('https://google.com?q=%A710')
|
||||
})
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect('Location', 'https://google.com?q=%A710')
|
||||
.expect(302, done)
|
||||
})
|
||||
})
|
||||
|
||||
describe('.redirect(status, url)', function(){
|
||||
it('should set the response status', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
res.redirect(303, 'http://google.com');
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect('Location', 'http://google.com')
|
||||
.expect(303, done)
|
||||
})
|
||||
})
|
||||
|
||||
describe('when the request method is HEAD', function(){
|
||||
it('should ignore the body', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
res.redirect('http://google.com');
|
||||
});
|
||||
|
||||
request(app)
|
||||
.head('/')
|
||||
.expect(302)
|
||||
.expect('Location', 'http://google.com')
|
||||
.expect(utils.shouldNotHaveBody())
|
||||
.end(done)
|
||||
})
|
||||
})
|
||||
|
||||
describe('when accepting html', function(){
|
||||
it.todo('should respond with html', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
res.redirect('http://google.com');
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.set('Accept', 'text/html')
|
||||
.expect('Content-Type', /html/)
|
||||
.expect('Location', 'http://google.com')
|
||||
.expect(302, '<p>Found. Redirecting to http://google.com</p>', done)
|
||||
})
|
||||
|
||||
it.todo('should escape the url', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
res.redirect('<la\'me>');
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.set('Host', 'http://example.com')
|
||||
.set('Accept', 'text/html')
|
||||
.expect('Content-Type', /html/)
|
||||
.expect('Location', '%3Cla\'me%3E')
|
||||
.expect(302, '<p>Found. Redirecting to %3Cla'me%3E</p>', done)
|
||||
})
|
||||
|
||||
it.todo('should not render evil javascript links in anchor href (prevent XSS)', function(done){
|
||||
var app = express();
|
||||
var xss = 'javascript:eval(document.body.innerHTML=`<p>XSS</p>`);';
|
||||
var encodedXss = 'javascript:eval(document.body.innerHTML=%60%3Cp%3EXSS%3C/p%3E%60);';
|
||||
|
||||
app.use(function(req, res){
|
||||
res.redirect(xss);
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.set('Host', 'http://example.com')
|
||||
.set('Accept', 'text/html')
|
||||
.expect('Content-Type', /html/)
|
||||
.expect('Location', encodedXss)
|
||||
.expect(302, '<p>Found. Redirecting to ' + encodedXss +'</p>', done);
|
||||
});
|
||||
|
||||
it.todo('should include the redirect type', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
res.redirect(301, 'http://google.com');
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.set('Accept', 'text/html')
|
||||
.expect('Content-Type', /html/)
|
||||
.expect('Location', 'http://google.com')
|
||||
.expect(301, '<p>Moved Permanently. Redirecting to http://google.com</p>', done);
|
||||
})
|
||||
})
|
||||
|
||||
describe('when accepting text', function(){
|
||||
it('should respond with text', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
res.redirect('http://google.com');
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.set('Accept', 'text/plain, */*')
|
||||
.expect('Content-Type', /plain/)
|
||||
.expect('Location', 'http://google.com')
|
||||
.expect(302, 'Found. Redirecting to http://google.com', done)
|
||||
})
|
||||
|
||||
it('should encode the url', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
res.redirect('http://example.com/?param=<script>alert("hax");</script>');
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.set('Host', 'http://example.com')
|
||||
.set('Accept', 'text/plain, */*')
|
||||
.expect('Content-Type', /plain/)
|
||||
.expect('Location', 'http://example.com/?param=%3Cscript%3Ealert(%22hax%22);%3C/script%3E')
|
||||
.expect(302, 'Found. Redirecting to http://example.com/?param=%3Cscript%3Ealert(%22hax%22);%3C/script%3E', done)
|
||||
})
|
||||
|
||||
it('should include the redirect type', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
res.redirect(301, 'http://google.com');
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.set('Accept', 'text/plain, */*')
|
||||
.expect('Content-Type', /plain/)
|
||||
.expect('Location', 'http://google.com')
|
||||
.expect(301, 'Moved Permanently. Redirecting to http://google.com', done);
|
||||
})
|
||||
})
|
||||
|
||||
describe('when accepting neither text or html', function(){
|
||||
it('should respond with an empty body', function(done){
|
||||
var app = express();
|
||||
|
||||
app.use(function(req, res){
|
||||
res.redirect('http://google.com');
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.set('Accept', 'application/octet-stream')
|
||||
.expect(302)
|
||||
.expect('location', 'http://google.com')
|
||||
.expect('content-length', '0')
|
||||
.expect(utils.shouldNotHaveHeader('Content-Type'))
|
||||
.expect(utils.shouldNotHaveBody())
|
||||
.end(done)
|
||||
})
|
||||
})
|
||||
})
|
||||
475
test/js/third_party/express/res.send.test.ts
vendored
475
test/js/third_party/express/res.send.test.ts
vendored
@@ -1,475 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
var assert = require("node:assert");
|
||||
var express = require("express");
|
||||
var request = require("supertest");
|
||||
var utils = require("./support/utils");
|
||||
|
||||
var shouldSkipQuery = require("./support/utils").shouldSkipQuery;
|
||||
var methods = utils.methods;
|
||||
|
||||
describe("res", function () {
|
||||
describe(".send()", function () {
|
||||
it('should set body to ""', function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.send();
|
||||
});
|
||||
|
||||
request(app).get("/").expect(200, "", done);
|
||||
});
|
||||
});
|
||||
|
||||
describe(".send(null)", function () {
|
||||
it('should set body to ""', function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.send(null);
|
||||
});
|
||||
|
||||
request(app).get("/").expect("Content-Length", "0").expect(200, "", done);
|
||||
});
|
||||
});
|
||||
|
||||
describe(".send(undefined)", function () {
|
||||
it('should set body to ""', function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.send(undefined);
|
||||
});
|
||||
|
||||
request(app).get("/").expect(200, "", done);
|
||||
});
|
||||
});
|
||||
|
||||
describe(".send(Number)", function () {
|
||||
it.todo("should send as application/json", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.send(1000);
|
||||
});
|
||||
|
||||
request(app).get("/").expect("Content-Type", "application/json; charset=utf-8").expect(200, "1000", done);
|
||||
});
|
||||
});
|
||||
|
||||
describe(".send(String)", function () {
|
||||
it("should send as html", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.send("<p>hey</p>");
|
||||
});
|
||||
|
||||
request(app).get("/").expect("Content-Type", "text/html; charset=utf-8").expect(200, "<p>hey</p>", done);
|
||||
});
|
||||
|
||||
it("should set ETag", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
var str = Array(1000).join("-");
|
||||
res.send(str);
|
||||
});
|
||||
|
||||
request(app).get("/").expect("ETag", 'W/"3e7-qPnkJ3CVdVhFJQvUBfF10TmVA7g"').expect(200, done);
|
||||
});
|
||||
|
||||
it("should not override Content-Type", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.set("Content-Type", "text/plain").send("hey");
|
||||
});
|
||||
|
||||
request(app).get("/").expect("Content-Type", "text/plain; charset=utf-8").expect(200, "hey", done);
|
||||
});
|
||||
|
||||
it("should override charset in Content-Type", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.set("Content-Type", "text/plain; charset=iso-8859-1").send("hey");
|
||||
});
|
||||
|
||||
request(app).get("/").expect("Content-Type", "text/plain; charset=utf-8").expect(200, "hey", done);
|
||||
});
|
||||
|
||||
it("should keep charset in Content-Type for Buffers", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.set("Content-Type", "text/plain; charset=iso-8859-1").send(Buffer.from("hi"));
|
||||
});
|
||||
|
||||
request(app).get("/").expect("Content-Type", "text/plain; charset=iso-8859-1").expect(200, "hi", done);
|
||||
});
|
||||
});
|
||||
|
||||
describe(".send(Buffer)", function () {
|
||||
it("should send as octet-stream", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.send(Buffer.from("hello"));
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get("/")
|
||||
.expect(200)
|
||||
.expect("Content-Type", "application/octet-stream")
|
||||
.expect(utils.shouldHaveBody(Buffer.from("hello")))
|
||||
.end(done);
|
||||
});
|
||||
|
||||
it("should set ETag", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.send(Buffer.alloc(999, "-"));
|
||||
});
|
||||
|
||||
request(app).get("/").expect("ETag", 'W/"3e7-qPnkJ3CVdVhFJQvUBfF10TmVA7g"').expect(200, done);
|
||||
});
|
||||
|
||||
it("should not override Content-Type", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.set("Content-Type", "text/plain").send(Buffer.from("hey"));
|
||||
});
|
||||
|
||||
request(app).get("/").expect("Content-Type", "text/plain; charset=utf-8").expect(200, "hey", done);
|
||||
});
|
||||
|
||||
it.todo("should accept Uint8Array", function (done) {
|
||||
var app = express();
|
||||
app.use(function (req, res) {
|
||||
const encodedHey = new TextEncoder().encode("hey");
|
||||
res.set("Content-Type", "text/plain").send(encodedHey);
|
||||
});
|
||||
|
||||
request(app).get("/").expect("Content-Type", "text/plain; charset=utf-8").expect(200, "hey", done);
|
||||
});
|
||||
|
||||
it("should not override ETag", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.type("text/plain").set("ETag", '"foo"').send(Buffer.from("hey"));
|
||||
});
|
||||
|
||||
request(app).get("/").expect("ETag", '"foo"').expect(200, "hey", done);
|
||||
});
|
||||
});
|
||||
|
||||
describe(".send(Object)", function () {
|
||||
it("should send as application/json", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.send({ name: "tobi" });
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get("/")
|
||||
.expect("Content-Type", "application/json; charset=utf-8")
|
||||
.expect(200, '{"name":"tobi"}', done);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when the request method is HEAD", function () {
|
||||
it("should ignore the body", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.send("yay");
|
||||
});
|
||||
|
||||
request(app).head("/").expect(200).expect(utils.shouldNotHaveBody()).end(done);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when .statusCode is 204", function () {
|
||||
it.todo("should strip Content-* fields, Transfer-Encoding field, and body", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.status(204).set("Transfer-Encoding", "chunked").send("foo");
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get("/")
|
||||
.expect(utils.shouldNotHaveHeader("Content-Type"))
|
||||
.expect(utils.shouldNotHaveHeader("Content-Length"))
|
||||
.expect(utils.shouldNotHaveHeader("Transfer-Encoding"))
|
||||
.expect(204, "", done);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when .statusCode is 205", function () {
|
||||
it("should strip Transfer-Encoding field and body, set Content-Length", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.status(205).set("Transfer-Encoding", "chunked").send("foo");
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get("/")
|
||||
.expect(utils.shouldNotHaveHeader("Transfer-Encoding"))
|
||||
.expect("Content-Length", "0")
|
||||
.expect(205, "", done);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when .statusCode is 304", function () {
|
||||
it.todo("should strip Content-* fields, Transfer-Encoding field, and body", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.status(304).set("Transfer-Encoding", "chunked").send("foo");
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get("/")
|
||||
.expect(utils.shouldNotHaveHeader("Content-Type"))
|
||||
.expect(utils.shouldNotHaveHeader("Content-Length"))
|
||||
.expect(utils.shouldNotHaveHeader("Transfer-Encoding"))
|
||||
.expect(304, "", done);
|
||||
});
|
||||
});
|
||||
|
||||
it("should always check regardless of length", function (done) {
|
||||
var app = express();
|
||||
var etag = '"asdf"';
|
||||
|
||||
app.use(function (req, res, next) {
|
||||
res.set("ETag", etag);
|
||||
res.send("hey");
|
||||
});
|
||||
|
||||
request(app).get("/").set("If-None-Match", etag).expect(304, done);
|
||||
});
|
||||
|
||||
it("should respond with 304 Not Modified when fresh", function (done) {
|
||||
var app = express();
|
||||
var etag = '"asdf"';
|
||||
|
||||
app.use(function (req, res) {
|
||||
var str = Array(1000).join("-");
|
||||
res.set("ETag", etag);
|
||||
res.send(str);
|
||||
});
|
||||
|
||||
request(app).get("/").set("If-None-Match", etag).expect(304, done);
|
||||
});
|
||||
|
||||
it("should not perform freshness check unless 2xx or 304", function (done) {
|
||||
var app = express();
|
||||
var etag = '"asdf"';
|
||||
|
||||
app.use(function (req, res, next) {
|
||||
res.status(500);
|
||||
res.set("ETag", etag);
|
||||
res.send("hey");
|
||||
});
|
||||
|
||||
request(app).get("/").set("If-None-Match", etag).expect("hey").expect(500, done);
|
||||
});
|
||||
|
||||
it("should not support jsonp callbacks", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.send({ foo: "bar" });
|
||||
});
|
||||
|
||||
request(app).get("/?callback=foo").expect('{"foo":"bar"}', done);
|
||||
});
|
||||
|
||||
it("should be chainable", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
assert.equal(res.send("hey"), res);
|
||||
});
|
||||
|
||||
request(app).get("/").expect(200, "hey", done);
|
||||
});
|
||||
|
||||
describe('"etag" setting', function () {
|
||||
describe("when enabled", function () {
|
||||
it("should send ETag", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.send("kajdslfkasdf");
|
||||
});
|
||||
|
||||
app.enable("etag");
|
||||
|
||||
request(app).get("/").expect("ETag", 'W/"c-IgR/L5SF7CJQff4wxKGF/vfPuZ0"').expect(200, done);
|
||||
});
|
||||
|
||||
methods.forEach(function (method) {
|
||||
if (method === "connect") return;
|
||||
|
||||
it("should send ETag in response to " + method.toUpperCase() + " request", function (done) {
|
||||
if (method === "query" && shouldSkipQuery(process.versions.node)) {
|
||||
this.skip();
|
||||
}
|
||||
var app = express();
|
||||
|
||||
app[method]("/", function (req, res) {
|
||||
res.send("kajdslfkasdf");
|
||||
});
|
||||
|
||||
request(app)[method]("/").expect("ETag", 'W/"c-IgR/L5SF7CJQff4wxKGF/vfPuZ0"').expect(200, done);
|
||||
});
|
||||
});
|
||||
|
||||
it("should send ETag for empty string response", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.send("");
|
||||
});
|
||||
|
||||
app.enable("etag");
|
||||
|
||||
request(app).get("/").expect("ETag", 'W/"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk"').expect(200, done);
|
||||
});
|
||||
|
||||
it("should send ETag for long response", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
var str = Array(1000).join("-");
|
||||
res.send(str);
|
||||
});
|
||||
|
||||
app.enable("etag");
|
||||
|
||||
request(app).get("/").expect("ETag", 'W/"3e7-qPnkJ3CVdVhFJQvUBfF10TmVA7g"').expect(200, done);
|
||||
});
|
||||
|
||||
it("should not override ETag when manually set", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.set("etag", '"asdf"');
|
||||
res.send("hello!");
|
||||
});
|
||||
|
||||
app.enable("etag");
|
||||
|
||||
request(app).get("/").expect("ETag", '"asdf"').expect(200, done);
|
||||
});
|
||||
|
||||
it("should not send ETag for res.send()", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.send();
|
||||
});
|
||||
|
||||
app.enable("etag");
|
||||
|
||||
request(app).get("/").expect(utils.shouldNotHaveHeader("ETag")).expect(200, done);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when disabled", function () {
|
||||
it("should send no ETag", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
var str = Array(1000).join("-");
|
||||
res.send(str);
|
||||
});
|
||||
|
||||
app.disable("etag");
|
||||
|
||||
request(app).get("/").expect(utils.shouldNotHaveHeader("ETag")).expect(200, done);
|
||||
});
|
||||
|
||||
it("should send ETag when manually set", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.disable("etag");
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.set("etag", '"asdf"');
|
||||
res.send("hello!");
|
||||
});
|
||||
|
||||
request(app).get("/").expect("ETag", '"asdf"').expect(200, done);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when "strong"', function () {
|
||||
it("should send strong ETag", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.set("etag", "strong");
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.send("hello, world!");
|
||||
});
|
||||
|
||||
request(app).get("/").expect("ETag", '"d-HwnTDHB9U/PRbFMN1z1wps51lqk"').expect(200, done);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when "weak"', function () {
|
||||
it("should send weak ETag", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.set("etag", "weak");
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.send("hello, world!");
|
||||
});
|
||||
|
||||
request(app).get("/").expect("ETag", 'W/"d-HwnTDHB9U/PRbFMN1z1wps51lqk"').expect(200, done);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when a function", function () {
|
||||
it("should send custom ETag", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.set("etag", function (body, encoding) {
|
||||
var chunk = !Buffer.isBuffer(body) ? Buffer.from(body, encoding) : body;
|
||||
assert.strictEqual(chunk.toString(), "hello, world!");
|
||||
return '"custom"';
|
||||
});
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.send("hello, world!");
|
||||
});
|
||||
|
||||
request(app).get("/").expect("ETag", '"custom"').expect(200, done);
|
||||
});
|
||||
|
||||
it("should not send falsy ETag", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.set("etag", function (body, encoding) {
|
||||
return undefined;
|
||||
});
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.send("hello, world!");
|
||||
});
|
||||
|
||||
request(app).get("/").expect(utils.shouldNotHaveHeader("ETag")).expect(200, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
774
test/js/third_party/express/res.sendFile.test.ts
vendored
774
test/js/third_party/express/res.sendFile.test.ts
vendored
@@ -1,774 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
var after = require("./support/after");
|
||||
var assert = require("node:assert");
|
||||
var AsyncLocalStorage = require("node:async_hooks").AsyncLocalStorage;
|
||||
|
||||
var express = require("express"),
|
||||
request = require("supertest");
|
||||
// var onFinished = require("on-finished");
|
||||
var path = require("node:path");
|
||||
var fixtures = path.join(__dirname, "fixtures");
|
||||
var utils = require("./support/utils");
|
||||
|
||||
describe("res", function () {
|
||||
describe(".sendFile(path)", function () {
|
||||
it("should error missing path", function (done) {
|
||||
var app = createApp();
|
||||
|
||||
request(app)
|
||||
.get("/")
|
||||
.expect(500, /path.*required/, done);
|
||||
});
|
||||
|
||||
it("should error for non-string path", function (done) {
|
||||
var app = createApp(42);
|
||||
|
||||
request(app)
|
||||
.get("/")
|
||||
.expect(500, /TypeError: path must be a string to res.sendFile/, done);
|
||||
});
|
||||
|
||||
it("should error for non-absolute path", function (done) {
|
||||
var app = createApp("name.txt");
|
||||
|
||||
request(app)
|
||||
.get("/")
|
||||
.expect(500, /TypeError: path must be absolute/, done);
|
||||
});
|
||||
|
||||
it.todo("should transfer a file", function (done) {
|
||||
var app = createApp(path.resolve(fixtures, "name.txt"));
|
||||
|
||||
request(app).get("/").expect(200, "tobi", done);
|
||||
});
|
||||
|
||||
it("should transfer a file with special characters in string", function (done) {
|
||||
var app = createApp(path.resolve(fixtures, "% of dogs.txt"));
|
||||
|
||||
request(app).get("/").expect(200, "20%", done);
|
||||
});
|
||||
|
||||
it.todo("should include ETag", function (done) {
|
||||
var app = createApp(path.resolve(fixtures, "name.txt"));
|
||||
|
||||
request(app)
|
||||
.get("/")
|
||||
.expect("ETag", /^(?:W\/)?"[^"]+"$/)
|
||||
.expect(200, "tobi", done);
|
||||
});
|
||||
|
||||
it.todo("should 304 when ETag matches", function (done) {
|
||||
var app = createApp(path.resolve(fixtures, "name.txt"));
|
||||
|
||||
request(app)
|
||||
.get("/")
|
||||
.expect("ETag", /^(?:W\/)?"[^"]+"$/)
|
||||
.expect(200, "tobi", function (err, res) {
|
||||
if (err) return done(err);
|
||||
var etag = res.headers.etag;
|
||||
request(app).get("/").set("If-None-Match", etag).expect(304, done);
|
||||
});
|
||||
});
|
||||
|
||||
it.todo("should disable the ETag function if requested", function (done) {
|
||||
var app = createApp(path.resolve(fixtures, "name.txt")).disable("etag");
|
||||
|
||||
request(app).get("/").expect(handleHeaders).expect(200, done);
|
||||
|
||||
function handleHeaders(res) {
|
||||
assert(res.headers.etag === undefined);
|
||||
}
|
||||
});
|
||||
|
||||
it("should 404 for directory", function (done) {
|
||||
var app = createApp(path.resolve(fixtures, "blog"));
|
||||
|
||||
request(app).get("/").expect(404, done);
|
||||
});
|
||||
|
||||
it("should 404 when not found", function (done) {
|
||||
var app = createApp(path.resolve(fixtures, "does-no-exist"));
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.statusCode = 200;
|
||||
res.send("no!");
|
||||
});
|
||||
|
||||
request(app).get("/").expect(404, done);
|
||||
});
|
||||
|
||||
it("should send cache-control by default", function (done) {
|
||||
var app = createApp(path.resolve(__dirname, "fixtures/name.txt"));
|
||||
|
||||
request(app).get("/").expect("Cache-Control", "public, max-age=0").expect(200, done);
|
||||
});
|
||||
|
||||
it("should not serve dotfiles by default", function (done) {
|
||||
var app = createApp(path.resolve(__dirname, "fixtures/.name"));
|
||||
|
||||
request(app).get("/").expect(404, done);
|
||||
});
|
||||
|
||||
it("should not override manual content-types", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.contentType("application/x-bogus");
|
||||
res.sendFile(path.resolve(fixtures, "name.txt"));
|
||||
});
|
||||
|
||||
request(app).get("/").expect("Content-Type", "application/x-bogus").end(done);
|
||||
});
|
||||
|
||||
it.todo("should not error if the client aborts", function (done) {
|
||||
var app = express();
|
||||
var cb = after(2, done);
|
||||
var error = null;
|
||||
|
||||
app.use(function (req, res) {
|
||||
setImmediate(function () {
|
||||
res.sendFile(path.resolve(fixtures, "name.txt"));
|
||||
setTimeout(function () {
|
||||
cb(error);
|
||||
}, 10);
|
||||
});
|
||||
test.req.abort();
|
||||
});
|
||||
|
||||
app.use(function (err, req, res, next) {
|
||||
error = err;
|
||||
next(err);
|
||||
});
|
||||
|
||||
var server = app.listen();
|
||||
var test = request(server).get("/");
|
||||
test.end(function (err) {
|
||||
assert.ok(err);
|
||||
server.close(cb);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe(".sendFile(path, fn)", function () {
|
||||
it("should invoke the callback when complete", function (done) {
|
||||
var cb = after(2, done);
|
||||
var app = createApp(path.resolve(fixtures, "name.txt"), cb);
|
||||
|
||||
request(app).get("/").expect(200, cb);
|
||||
});
|
||||
|
||||
it.todo("should invoke the callback when client aborts", function (done) {
|
||||
var cb = after(2, done);
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
setImmediate(function () {
|
||||
res.sendFile(path.resolve(fixtures, "name.txt"), function (err) {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(err.code, "ECONNABORTED");
|
||||
cb();
|
||||
});
|
||||
});
|
||||
test.req.abort();
|
||||
});
|
||||
|
||||
var server = app.listen();
|
||||
var test = request(server).get("/");
|
||||
test.end(function (err) {
|
||||
assert.ok(err);
|
||||
server.close(cb);
|
||||
});
|
||||
});
|
||||
|
||||
// TODO: refactor to not use onFinished
|
||||
// it("should invoke the callback when client already aborted", function (done) {
|
||||
// var cb = after(2, done);
|
||||
// var app = express();
|
||||
|
||||
// app.use(function (req, res) {
|
||||
// onFinished(res, function () {
|
||||
// res.sendFile(path.resolve(fixtures, "name.txt"), function (err) {
|
||||
// assert.ok(err);
|
||||
// assert.strictEqual(err.code, "ECONNABORTED");
|
||||
// cb();
|
||||
// });
|
||||
// });
|
||||
// test.req.abort();
|
||||
// });
|
||||
|
||||
// var server = app.listen();
|
||||
// var test = request(server).get("/");
|
||||
// test.end(function (err) {
|
||||
// assert.ok(err);
|
||||
// server.close(cb);
|
||||
// });
|
||||
// });
|
||||
|
||||
it("should invoke the callback without error when HEAD", function (done) {
|
||||
var app = express();
|
||||
var cb = after(2, done);
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.sendFile(path.resolve(fixtures, "name.txt"), cb);
|
||||
});
|
||||
|
||||
request(app).head("/").expect(200, cb);
|
||||
});
|
||||
|
||||
it.todo("should invoke the callback without error when 304", function (done) {
|
||||
var app = express();
|
||||
var cb = after(3, done);
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.sendFile(path.resolve(fixtures, "name.txt"), cb);
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get("/")
|
||||
.expect("ETag", /^(?:W\/)?"[^"]+"$/)
|
||||
.expect(200, "tobi", function (err, res) {
|
||||
if (err) return cb(err);
|
||||
var etag = res.headers.etag;
|
||||
request(app).get("/").set("If-None-Match", etag).expect(304, cb);
|
||||
});
|
||||
});
|
||||
|
||||
it("should invoke the callback on 404", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.sendFile(path.resolve(fixtures, "does-not-exist"), function (err) {
|
||||
res.send(err ? "got " + err.status + " error" : "no error");
|
||||
});
|
||||
});
|
||||
|
||||
request(app).get("/").expect(200, "got 404 error", done);
|
||||
});
|
||||
|
||||
describe.todo("async local storage", function () {
|
||||
it("should presist store", function (done) {
|
||||
var app = express();
|
||||
var cb = after(2, done);
|
||||
var store = { foo: "bar" };
|
||||
|
||||
app.use(function (req, res, next) {
|
||||
req.asyncLocalStorage = new AsyncLocalStorage();
|
||||
req.asyncLocalStorage.run(store, next);
|
||||
});
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.sendFile(path.resolve(fixtures, "name.txt"), function (err) {
|
||||
if (err) return cb(err);
|
||||
|
||||
var local = req.asyncLocalStorage.getStore();
|
||||
|
||||
assert.strictEqual(local.foo, "bar");
|
||||
cb();
|
||||
});
|
||||
});
|
||||
|
||||
request(app).get("/").expect("Content-Type", "text/plain; charset=utf-8").expect(200, "tobi", cb);
|
||||
});
|
||||
|
||||
it("should presist store on error", function (done) {
|
||||
var app = express();
|
||||
var store = { foo: "bar" };
|
||||
|
||||
app.use(function (req, res, next) {
|
||||
req.asyncLocalStorage = new AsyncLocalStorage();
|
||||
req.asyncLocalStorage.run(store, next);
|
||||
});
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.sendFile(path.resolve(fixtures, "does-not-exist"), function (err) {
|
||||
var local = req.asyncLocalStorage.getStore();
|
||||
|
||||
if (local) {
|
||||
res.setHeader("x-store-foo", String(local.foo));
|
||||
}
|
||||
|
||||
res.send(err ? "got " + err.status + " error" : "no error");
|
||||
});
|
||||
});
|
||||
|
||||
request(app).get("/").expect(200).expect("x-store-foo", "bar").expect("got 404 error").end(done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe(".sendFile(path, options)", function () {
|
||||
it("should pass options to send module", function (done) {
|
||||
request(createApp(path.resolve(fixtures, "name.txt"), { start: 0, end: 1 }))
|
||||
.get("/")
|
||||
.expect(200, "to", done);
|
||||
});
|
||||
|
||||
describe('with "acceptRanges" option', function () {
|
||||
describe("when true", function () {
|
||||
it("should advertise byte range accepted", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.sendFile(path.resolve(fixtures, "nums.txt"), {
|
||||
acceptRanges: true,
|
||||
});
|
||||
});
|
||||
|
||||
request(app).get("/").expect(200).expect("Accept-Ranges", "bytes").expect("123456789").end(done);
|
||||
});
|
||||
|
||||
it("should respond to range request", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.sendFile(path.resolve(fixtures, "nums.txt"), {
|
||||
acceptRanges: true,
|
||||
});
|
||||
});
|
||||
|
||||
request(app).get("/").set("Range", "bytes=0-4").expect(206, "12345", done);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when false", function () {
|
||||
it("should not advertise accept-ranges", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.sendFile(path.resolve(fixtures, "nums.txt"), {
|
||||
acceptRanges: false,
|
||||
});
|
||||
});
|
||||
|
||||
request(app).get("/").expect(200).expect(utils.shouldNotHaveHeader("Accept-Ranges")).end(done);
|
||||
});
|
||||
|
||||
it("should not honor range requests", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.sendFile(path.resolve(fixtures, "nums.txt"), {
|
||||
acceptRanges: false,
|
||||
});
|
||||
});
|
||||
|
||||
request(app).get("/").set("Range", "bytes=0-4").expect(200, "123456789", done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('with "cacheControl" option', function () {
|
||||
describe("when true", function () {
|
||||
it("should send cache-control header", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.sendFile(path.resolve(fixtures, "user.html"), {
|
||||
cacheControl: true,
|
||||
});
|
||||
});
|
||||
|
||||
request(app).get("/").expect(200).expect("Cache-Control", "public, max-age=0").end(done);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when false", function () {
|
||||
it("should not send cache-control header", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.sendFile(path.resolve(fixtures, "user.html"), {
|
||||
cacheControl: false,
|
||||
});
|
||||
});
|
||||
|
||||
request(app).get("/").expect(200).expect(utils.shouldNotHaveHeader("Cache-Control")).end(done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('with "dotfiles" option', function () {
|
||||
describe('when "allow"', function () {
|
||||
it("should allow dotfiles", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.sendFile(path.resolve(fixtures, ".name"), {
|
||||
dotfiles: "allow",
|
||||
});
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get("/")
|
||||
.expect(200)
|
||||
.expect(utils.shouldHaveBody(Buffer.from("tobi")))
|
||||
.end(done);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when "deny"', function () {
|
||||
it("should deny dotfiles", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.sendFile(path.resolve(fixtures, ".name"), {
|
||||
dotfiles: "deny",
|
||||
});
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get("/")
|
||||
.expect(403)
|
||||
.expect(/Forbidden/)
|
||||
.end(done);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when "ignore"', function () {
|
||||
it("should ignore dotfiles", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.sendFile(path.resolve(fixtures, ".name"), {
|
||||
dotfiles: "ignore",
|
||||
});
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get("/")
|
||||
.expect(404)
|
||||
.expect(/Not Found/)
|
||||
.end(done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('with "headers" option', function () {
|
||||
it("should set headers on response", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.sendFile(path.resolve(fixtures, "user.html"), {
|
||||
headers: {
|
||||
"X-Foo": "Bar",
|
||||
"X-Bar": "Foo",
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
request(app).get("/").expect(200).expect("X-Foo", "Bar").expect("X-Bar", "Foo").end(done);
|
||||
});
|
||||
|
||||
it("should use last header when duplicated", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.sendFile(path.resolve(fixtures, "user.html"), {
|
||||
headers: {
|
||||
"X-Foo": "Bar",
|
||||
"x-foo": "bar",
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
request(app).get("/").expect(200).expect("X-Foo", "bar").end(done);
|
||||
});
|
||||
|
||||
it("should override Content-Type", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.sendFile(path.resolve(fixtures, "user.html"), {
|
||||
headers: {
|
||||
"Content-Type": "text/x-custom",
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
request(app).get("/").expect(200).expect("Content-Type", "text/x-custom").end(done);
|
||||
});
|
||||
|
||||
it("should not set headers on 404", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.sendFile(path.resolve(fixtures, "does-not-exist"), {
|
||||
headers: {
|
||||
"X-Foo": "Bar",
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
request(app).get("/").expect(404).expect(utils.shouldNotHaveHeader("X-Foo")).end(done);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with "immutable" option', function () {
|
||||
describe("when true", function () {
|
||||
it("should send cache-control header with immutable", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.sendFile(path.resolve(fixtures, "user.html"), {
|
||||
immutable: true,
|
||||
});
|
||||
});
|
||||
|
||||
request(app).get("/").expect(200).expect("Cache-Control", "public, max-age=0, immutable").end(done);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when false", function () {
|
||||
it("should not send cache-control header with immutable", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.sendFile(path.resolve(fixtures, "user.html"), {
|
||||
immutable: false,
|
||||
});
|
||||
});
|
||||
|
||||
request(app).get("/").expect(200).expect("Cache-Control", "public, max-age=0").end(done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('with "lastModified" option', function () {
|
||||
describe("when true", function () {
|
||||
it("should send last-modified header", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.sendFile(path.resolve(fixtures, "user.html"), {
|
||||
lastModified: true,
|
||||
});
|
||||
});
|
||||
|
||||
request(app).get("/").expect(200).expect(utils.shouldHaveHeader("Last-Modified")).end(done);
|
||||
});
|
||||
|
||||
it("should conditionally respond with if-modified-since", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.sendFile(path.resolve(fixtures, "user.html"), {
|
||||
lastModified: true,
|
||||
});
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get("/")
|
||||
.set("If-Modified-Since", new Date(Date.now() + 99999).toUTCString())
|
||||
.expect(304, done);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when false", function () {
|
||||
it("should not have last-modified header", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.sendFile(path.resolve(fixtures, "user.html"), {
|
||||
lastModified: false,
|
||||
});
|
||||
});
|
||||
|
||||
request(app).get("/").expect(200).expect(utils.shouldNotHaveHeader("Last-Modified")).end(done);
|
||||
});
|
||||
|
||||
it("should not honor if-modified-since", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.sendFile(path.resolve(fixtures, "user.html"), {
|
||||
lastModified: false,
|
||||
});
|
||||
});
|
||||
|
||||
request(app)
|
||||
.get("/")
|
||||
.set("If-Modified-Since", new Date(Date.now() + 99999).toUTCString())
|
||||
.expect(200)
|
||||
.expect(utils.shouldNotHaveHeader("Last-Modified"))
|
||||
.end(done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('with "maxAge" option', function () {
|
||||
it("should set cache-control max-age to milliseconds", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.sendFile(path.resolve(fixtures, "user.html"), {
|
||||
maxAge: 20000,
|
||||
});
|
||||
});
|
||||
|
||||
request(app).get("/").expect(200).expect("Cache-Control", "public, max-age=20").end(done);
|
||||
});
|
||||
|
||||
it("should cap cache-control max-age to 1 year", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.sendFile(path.resolve(fixtures, "user.html"), {
|
||||
maxAge: 99999999999,
|
||||
});
|
||||
});
|
||||
|
||||
request(app).get("/").expect(200).expect("Cache-Control", "public, max-age=31536000").end(done);
|
||||
});
|
||||
|
||||
it.todo("should min cache-control max-age to 0", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.sendFile(path.resolve(fixtures, "user.html"), {
|
||||
maxAge: -20000,
|
||||
});
|
||||
});
|
||||
|
||||
request(app).get("/").expect(200).expect("Cache-Control", "public, max-age=0").end(done);
|
||||
});
|
||||
|
||||
it.todo("should floor cache-control max-age", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.sendFile(path.resolve(fixtures, "user.html"), {
|
||||
maxAge: 21911.23,
|
||||
});
|
||||
});
|
||||
|
||||
request(app).get("/").expect(200).expect("Cache-Control", "public, max-age=21").end(done);
|
||||
});
|
||||
|
||||
describe("when cacheControl: false", function () {
|
||||
it("should not send cache-control", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.sendFile(path.resolve(fixtures, "user.html"), {
|
||||
cacheControl: false,
|
||||
maxAge: 20000,
|
||||
});
|
||||
});
|
||||
|
||||
request(app).get("/").expect(200).expect(utils.shouldNotHaveHeader("Cache-Control")).end(done);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when string", function () {
|
||||
it("should accept plain number as milliseconds", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.sendFile(path.resolve(fixtures, "user.html"), {
|
||||
maxAge: "20000",
|
||||
});
|
||||
});
|
||||
|
||||
request(app).get("/").expect(200).expect("Cache-Control", "public, max-age=20").end(done);
|
||||
});
|
||||
|
||||
it('should accept suffix "s" for seconds', function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.sendFile(path.resolve(fixtures, "user.html"), {
|
||||
maxAge: "20s",
|
||||
});
|
||||
});
|
||||
|
||||
request(app).get("/").expect(200).expect("Cache-Control", "public, max-age=20").end(done);
|
||||
});
|
||||
|
||||
it('should accept suffix "m" for minutes', function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.sendFile(path.resolve(fixtures, "user.html"), {
|
||||
maxAge: "20m",
|
||||
});
|
||||
});
|
||||
|
||||
request(app).get("/").expect(200).expect("Cache-Control", "public, max-age=1200").end(done);
|
||||
});
|
||||
|
||||
it('should accept suffix "d" for days', function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.sendFile(path.resolve(fixtures, "user.html"), {
|
||||
maxAge: "20d",
|
||||
});
|
||||
});
|
||||
|
||||
request(app).get("/").expect(200).expect("Cache-Control", "public, max-age=1728000").end(done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe.todo('with "root" option', function () {
|
||||
it("should allow relative path", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.sendFile("name.txt", {
|
||||
root: fixtures,
|
||||
});
|
||||
});
|
||||
|
||||
request(app).get("/").expect(200, "tobi", done);
|
||||
});
|
||||
|
||||
it("should allow up within root", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.sendFile("fake/../name.txt", {
|
||||
root: fixtures,
|
||||
});
|
||||
});
|
||||
|
||||
request(app).get("/").expect(200, "tobi", done);
|
||||
});
|
||||
|
||||
it.todo("should reject up outside root", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.sendFile(".." + path.sep + path.relative(path.dirname(fixtures), path.join(fixtures, "name.txt")), {
|
||||
root: fixtures,
|
||||
});
|
||||
});
|
||||
|
||||
request(app).get("/").expect(403, done);
|
||||
});
|
||||
|
||||
it("should reject reading outside root", function (done) {
|
||||
var app = express();
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.sendFile("../name.txt", {
|
||||
root: fixtures,
|
||||
});
|
||||
});
|
||||
|
||||
request(app).get("/").expect(403, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function createApp(path?, options?, fn?) {
|
||||
var app = express();
|
||||
|
||||
app.use(function sendFileMiddleware (req, res) {
|
||||
res.sendFile(path, options, fn);
|
||||
});
|
||||
|
||||
return app;
|
||||
}
|
||||
36
test/js/third_party/express/support/after.ts
vendored
36
test/js/third_party/express/support/after.ts
vendored
@@ -1,36 +0,0 @@
|
||||
/**
|
||||
* https://www.npmjs.com/package/after
|
||||
*
|
||||
* I refuse to install a 30 line function via npm
|
||||
*/
|
||||
module.exports = after;
|
||||
|
||||
/**
|
||||
* Invoke a callback after `n` calls
|
||||
*/
|
||||
function after(count, callback, err_cb) {
|
||||
var bail = false;
|
||||
err_cb = err_cb || noop;
|
||||
proxy.count = count;
|
||||
|
||||
return count === 0 ? callback() : proxy;
|
||||
|
||||
function proxy(err, result) {
|
||||
if (proxy.count <= 0) {
|
||||
throw new Error("after called too many times");
|
||||
}
|
||||
--proxy.count;
|
||||
|
||||
// after first error, rest are passed to err_cb
|
||||
if (err) {
|
||||
bail = true;
|
||||
callback(err);
|
||||
// future error callbacks will go to error handler
|
||||
callback = err_cb;
|
||||
} else if (proxy.count === 0 && !bail) {
|
||||
callback(null, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function noop() {}
|
||||
83
test/js/third_party/express/support/utils.ts
vendored
83
test/js/third_party/express/support/utils.ts
vendored
@@ -1,83 +0,0 @@
|
||||
/**
|
||||
* Module dependencies.
|
||||
* @private
|
||||
*/
|
||||
|
||||
var assert = require("node:assert");
|
||||
var { METHODS } = require("node:http");
|
||||
|
||||
/**
|
||||
* Module exports.
|
||||
* @public
|
||||
*/
|
||||
|
||||
exports.shouldHaveBody = shouldHaveBody;
|
||||
exports.shouldHaveHeader = shouldHaveHeader;
|
||||
exports.shouldNotHaveBody = shouldNotHaveBody;
|
||||
exports.shouldNotHaveHeader = shouldNotHaveHeader;
|
||||
exports.shouldSkipQuery = shouldSkipQuery;
|
||||
exports.methods = METHODS.map(method => method.toLowerCase()); // from lib/utils.js
|
||||
|
||||
/**
|
||||
* Assert that a supertest response has a specific body.
|
||||
*
|
||||
* @param {Buffer} buf
|
||||
* @returns {function}
|
||||
*/
|
||||
|
||||
function shouldHaveBody(buf) {
|
||||
return function (res) {
|
||||
var body = !Buffer.isBuffer(res.body) ? Buffer.from(res.text) : res.body;
|
||||
assert.ok(body, "response has body");
|
||||
assert.strictEqual(body.toString("hex"), buf.toString("hex"));
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that a supertest response does have a header.
|
||||
*
|
||||
* @param {string} header Header name to check
|
||||
* @returns {function}
|
||||
*/
|
||||
|
||||
function shouldHaveHeader(header) {
|
||||
return function (res) {
|
||||
assert.ok(header.toLowerCase() in res.headers, "should have header " + header);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that a supertest response does not have a body.
|
||||
*
|
||||
* @returns {function}
|
||||
*/
|
||||
|
||||
function shouldNotHaveBody() {
|
||||
return function (res) {
|
||||
assert.ok(res.text === "" || res.text === undefined);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that a supertest response does not have a header.
|
||||
*
|
||||
* @param {string} header Header name to check
|
||||
* @returns {function}
|
||||
*/
|
||||
function shouldNotHaveHeader(header) {
|
||||
return function (res) {
|
||||
assert.ok(!(header.toLowerCase() in res.headers), "should not have header " + header);
|
||||
};
|
||||
}
|
||||
|
||||
function getMajorVersion(versionString) {
|
||||
return versionString.split(".")[0];
|
||||
}
|
||||
|
||||
function shouldSkipQuery(versionString) {
|
||||
// Skipping HTTP QUERY tests on Node 21, it is reported in http.METHODS on 21.7.2 but not supported
|
||||
// update this implementation to run on supported versions of 21 once they exist
|
||||
// upstream tracking https://github.com/nodejs/node/issues/51562
|
||||
// express tracking issue: https://github.com/expressjs/express/issues/5615
|
||||
return Number(getMajorVersion(versionString)) === 21;
|
||||
}
|
||||
594
test/vendor.json
594
test/vendor.json
@@ -3,5 +3,597 @@
|
||||
"package": "elysia",
|
||||
"repository": "https://github.com/elysiajs/elysia",
|
||||
"tag": "1.1.24"
|
||||
},
|
||||
{
|
||||
"package": "koa",
|
||||
"repository": "https://github.com/koajs/koa",
|
||||
"tag": "2.16.1",
|
||||
"testPatterns": [
|
||||
"__tests__/*.test.js"
|
||||
],
|
||||
"testFailures": [
|
||||
"__tests__/application/onerror.test.js > app.onerror(err) > should do nothing if .silent",
|
||||
"__tests__/application/onerror.test.js > app.onerror(err) > should do nothing if status is 404",
|
||||
"__tests__/application/onerror.test.js > app.onerror(err) > should log the error to stderr",
|
||||
"__tests__/application/respond.test.js > app.respond > when .body is missing > with custom status=700 > should respond with the associated status message",
|
||||
"__tests__/application/respond.test.js > app.respond > when status and body property > should 204",
|
||||
"__tests__/application/respond.test.js > segmentation fault",
|
||||
"__tests__/application/response.test.js > app.response > should not include status message in body for http2",
|
||||
"__tests__/context/onerror.test.js > ctx.onerror(err) > should unset all headers",
|
||||
"__tests__/context/onerror.test.js > timeout",
|
||||
"__tests__/response/status.test.js > res.status= > when 204 > should strip content related header fields",
|
||||
"__tests__/response/status.test.js > res.status= > when 204 > should strip content related header fields after status set",
|
||||
"__tests__/response/status.test.js > res.status= > when 205 > should strip content related header fields",
|
||||
"__tests__/response/status.test.js > res.status= > when 205 > should strip content related header fields after status set",
|
||||
"__tests__/response/status.test.js > res.status= > when 304 > should strip content related header fields",
|
||||
"__tests__/response/status.test.js > res.status= > when 304 > should strip content related header fields after status set"
|
||||
]
|
||||
},
|
||||
{
|
||||
"package": "express",
|
||||
"repository": "https://github.com/expressjs/express",
|
||||
"tag": "5.1.0",
|
||||
"testPatterns": [
|
||||
"test/*.js",
|
||||
"test/acceptance/*.js"
|
||||
],
|
||||
"testFailures": [
|
||||
"test/Route.js > Route > should not stack overflow with a large sync stack",
|
||||
"test/Router.js > Router > should not stack overflow with a large sync middleware stack",
|
||||
"test/Router.js > Router > should not stack overflow with a large sync route stack",
|
||||
"test/Router.js > Router > should not stack overflow with many registered routes",
|
||||
"test/acceptance/downloads.js > downloads > GET /files/../index.js > should respond with 403",
|
||||
"test/acceptance/downloads.js > downloads > GET /files/../index.js > should respond with 403",
|
||||
"test/app.js > code 3",
|
||||
"test/app.options.js > OPTIONS > when error occurs in response handler > should pass error to callback",
|
||||
"test/app.router.js > app.router > methods > should include GET",
|
||||
"test/app.router.js > app.router > methods > should include PUT",
|
||||
"test/express.json.js > express.json() > should handle empty message-body",
|
||||
"test/express.raw.js > code 1",
|
||||
"test/express.static.js > code 13",
|
||||
"test/express.text.js > code 1",
|
||||
"test/express.urlencoded.js > code 1",
|
||||
"test/middleware.basic.js > middleware > .next() > should behave like connect",
|
||||
"test/req.xhr.js > code 1",
|
||||
"test/res.location.js > res > .location(url) > should consistently handle empty string input",
|
||||
"test/res.location.js > res > .location(url) > should consistently handle non-string inputs: array",
|
||||
"test/res.send.js > res > when .statusCode is 204 > should strip Content-* fields, Transfer-Encoding field, and body",
|
||||
"test/res.send.js > res > when .statusCode is 304 > should strip Content-* fields, Transfer-Encoding field, and body",
|
||||
"test/res.sendFile.js > res > .sendFile(path) > should not error if the client aborts",
|
||||
"test/res.sendFile.js > timeout",
|
||||
"test/res.set.js > res > .set(field, values) > should coerce to an array of strings",
|
||||
"test/res.status.js > res > .status(code) > accept valid ranges > should set the response status code to 700",
|
||||
"test/res.status.js > res > .status(code) > accept valid ranges > should set the response status code to 800",
|
||||
"test/res.status.js > res > .status(code) > accept valid ranges > should set the response status code to 900"
|
||||
]
|
||||
},
|
||||
{
|
||||
"package": "hono",
|
||||
"repository": "https://github.com/honojs/hono",
|
||||
"tag": "v4.7.6",
|
||||
"testPatterns": [
|
||||
"src/*.test.ts",
|
||||
"runtime-tests/bun/*.test.tsx"
|
||||
],
|
||||
"testFailures": [
|
||||
"src/adapter/bun/websocket.test.ts > createBunWebSocket() > Should events are called",
|
||||
"src/adapter/bun/websocket.test.ts > createWSContext() > Should send() and close() works",
|
||||
"src/adapter/bun/websocket.test.ts > upgradeWebSocket() > Should throw error when server is null",
|
||||
"src/adapter/cloudflare-pages/handler.test.ts > Adapter for Cloudflare Pages > Should not use `basePath()` if path argument is not passed",
|
||||
"src/adapter/cloudflare-pages/handler.test.ts > Adapter for Cloudflare Pages > Should return 200 response",
|
||||
"src/adapter/cloudflare-pages/handler.test.ts > Middleware adapter for Cloudflare Pages > Should handle a HTTPException by returning error.getResponse()",
|
||||
"src/adapter/cloudflare-pages/handler.test.ts > Middleware adapter for Cloudflare Pages > Should handle a non-Error thrown by next()",
|
||||
"src/adapter/cloudflare-pages/handler.test.ts > Middleware adapter for Cloudflare Pages > Should handle an Error thrown by next()",
|
||||
"src/adapter/cloudflare-pages/handler.test.ts > Middleware adapter for Cloudflare Pages > Should handle an HTTPException thrown by next()",
|
||||
"src/adapter/cloudflare-pages/handler.test.ts > Middleware adapter for Cloudflare Pages > Should rethrow an Error",
|
||||
"src/adapter/cloudflare-pages/handler.test.ts > Middleware adapter for Cloudflare Pages > Should rethrow non-Error exceptions",
|
||||
"src/adapter/cloudflare-pages/handler.test.ts > Middleware adapter for Cloudflare Pages > Should return the Pages response if the middleware does not return a response",
|
||||
"src/adapter/cloudflare-pages/handler.test.ts > Middleware adapter for Cloudflare Pages > Should return the middleware response",
|
||||
"src/adapter/cloudflare-pages/handler.test.ts > Middleware adapter for Cloudflare Pages > Should return the middleware response if next() is not called",
|
||||
"src/adapter/cloudflare-pages/handler.test.ts > Middleware adapter for Cloudflare Pages > Should return the middleware response when exceptions are handled",
|
||||
"src/adapter/cloudflare-pages/handler.test.ts > Middleware adapter for Cloudflare Pages > Should set the data in eventContext.data",
|
||||
"src/adapter/cloudflare-pages/handler.test.ts > serveStatic() > Should pass the raw request to ASSETS.fetch",
|
||||
"src/adapter/cloudflare-pages/handler.test.ts > serveStatic() > Should respond with 404 if ASSETS.fetch returns a 404 response",
|
||||
"src/adapter/cloudflare-workers/serve-static.test.ts > code 1",
|
||||
"src/adapter/cloudflare-workers/websocket.test.ts > upgradeWebSocket middleware > Should call next() when header does not have upgrade",
|
||||
"src/adapter/deno/websocket.test.ts > WebSockets > Should call next() when header does not have upgrade",
|
||||
"src/adapter/lambda-edge/handler.test.ts > code 3",
|
||||
"src/adapter/service-worker/handler.test.ts > ✗ ",
|
||||
"src/context.test.ts > Context > c.notFound()",
|
||||
"src/context.test.ts > Context header > Should be able to overwrite a fetch response with a new response.",
|
||||
"src/context.test.ts > Context header > Should be able to overwrite a response with a fetch response.",
|
||||
"src/context.test.ts > event and executionCtx > Should return the event if accessing c.event",
|
||||
"src/context.test.ts > event and executionCtx > Should return the executionCtx if accessing c.executionCtx",
|
||||
"src/helper/adapter/index.test.ts > getRuntimeKey > Should return the current runtime key",
|
||||
"src/helper/dev/index.test.ts > ✗ ",
|
||||
"src/helper/proxy/index.test.ts > Proxy Middleware > proxy > POST request",
|
||||
"src/helper/proxy/index.test.ts > Proxy Middleware > proxy > client disconnect",
|
||||
"src/helper/proxy/index.test.ts > Proxy Middleware > proxy > compressed",
|
||||
"src/helper/proxy/index.test.ts > Proxy Middleware > proxy > does not propagate undefined request headers",
|
||||
"src/helper/proxy/index.test.ts > Proxy Middleware > proxy > modify header",
|
||||
"src/helper/proxy/index.test.ts > Proxy Middleware > proxy > not found",
|
||||
"src/helper/proxy/index.test.ts > Proxy Middleware > proxy > remove hop-by-hop headers",
|
||||
"src/helper/proxy/index.test.ts > Proxy Middleware > proxy > specify hop-by-hop header by options",
|
||||
"src/helper/proxy/index.test.ts > Proxy Middleware > proxy > uncompressed",
|
||||
"src/helper/proxy/index.test.ts > ✗ ",
|
||||
"src/helper/streaming/stream.test.ts > Basic Streaming Helper > Check stream Response if aborted by abort signal",
|
||||
"src/helper/streaming/stream.test.ts > Basic Streaming Helper > Check stream Response if error occurred",
|
||||
"src/helper/streaming/stream.test.ts > Basic Streaming Helper > Check stream Response if pipe is aborted by abort signal",
|
||||
"src/helper/testing/index.test.ts > hono testClient > Should not throw an error with $ws()",
|
||||
"src/helper/websocket/index.test.ts > defineWebSocketHelper > When response is undefined, should call next()",
|
||||
"src/jsx/utils.test.ts > styleObjectForEach > Should output the number as it is, when a number type is passed > $property",
|
||||
"src/jsx/utils.test.ts > styleObjectForEach > Should output with px suffix, when a number type is passed > $property",
|
||||
"src/middleware/body-limit/index.test.ts > Body Limit Middleware > POST request > ReadableStream body > should return 413 response",
|
||||
"src/middleware/cache/index.test.ts > Cache Middleware > Should correctly apply a single Vary header from middleware",
|
||||
"src/middleware/cache/index.test.ts > Cache Middleware > Should correctly apply and return a single Vary header with Accept specified by middleware",
|
||||
"src/middleware/cache/index.test.ts > Cache Middleware > Should deduplicate while merging multiple Vary headers from middleware and handler",
|
||||
"src/middleware/cache/index.test.ts > Cache Middleware > Should merge Vary headers from middleware and handler without duplicating",
|
||||
"src/middleware/cache/index.test.ts > Cache Middleware > Should merge Vary headers specified by middleware as a string with additional headers added by handler",
|
||||
"src/middleware/cache/index.test.ts > Cache Middleware > Should not allow \"*\" as a Vary header in middleware configuration due to its impact on caching effectiveness",
|
||||
"src/middleware/cache/index.test.ts > Cache Middleware > Should not be enabled if caches is not defined",
|
||||
"src/middleware/cache/index.test.ts > Cache Middleware > Should not return cached response",
|
||||
"src/middleware/cache/index.test.ts > Cache Middleware > Should not return duplicate header values",
|
||||
"src/middleware/cache/index.test.ts > Cache Middleware > Should prevent duplication of Vary headers when identical ones are set by both middleware and handler",
|
||||
"src/middleware/cache/index.test.ts > Cache Middleware > Should return cached response",
|
||||
"src/middleware/cache/index.test.ts > Cache Middleware > Should return composed handler header values",
|
||||
"src/middleware/cache/index.test.ts > Cache Middleware > Should return composed middleware header values",
|
||||
"src/middleware/cache/index.test.ts > Customizing Caching Keys > Should retrieve cached response with dynamic cache name and key",
|
||||
"src/middleware/cache/index.test.ts > Customizing Caching Keys > Should use dynamically generated cache key",
|
||||
"src/middleware/cache/index.test.ts > Customizing Caching Keys > Should use dynamically generated cache name",
|
||||
"src/middleware/combine/index.test.ts > every > Should call all middleware",
|
||||
"src/middleware/combine/index.test.ts > every > Should return the same response a middleware returns if it short-circuits the chain",
|
||||
"src/middleware/combine/index.test.ts > every > Should throw error if any middleware returns false",
|
||||
"src/middleware/combine/index.test.ts > every > Should throw error if any middleware throws an error",
|
||||
"src/middleware/combine/index.test.ts > except > Should call all middleware, except the one that matches some of the condition function",
|
||||
"src/middleware/combine/index.test.ts > except > Should call all middleware, except the one that matches some of the conditions",
|
||||
"src/middleware/combine/index.test.ts > except > Should call all middleware, except the one that matches the condition",
|
||||
"src/middleware/combine/index.test.ts > some > Should call only the first middleware",
|
||||
"src/middleware/combine/index.test.ts > some > Should not call skipped middleware even if an error is thrown",
|
||||
"src/middleware/combine/index.test.ts > some > Should not call skipped middleware even if an error is thrown with returning truthy value middleware",
|
||||
"src/middleware/combine/index.test.ts > some > Should try to call the second middleware if the first one returns false",
|
||||
"src/middleware/combine/index.test.ts > some > Should try to call the second middleware if the first one throws an error",
|
||||
"src/middleware/compress/index.test.ts > Compress Middleware > Compression Behavior > should compress large responses with deflate",
|
||||
"src/middleware/compress/index.test.ts > Compress Middleware > Compression Behavior > should compress large responses with gzip",
|
||||
"src/middleware/compress/index.test.ts > Compress Middleware > Compression Behavior > should prioritize gzip over deflate when both are accepted",
|
||||
"src/middleware/compress/index.test.ts > Compress Middleware > Compression Behavior > should remove Content-Length when compressing",
|
||||
"src/middleware/compress/index.test.ts > Compress Middleware > Edge Cases > should compress custom 404 Not Found responses",
|
||||
"src/middleware/compress/index.test.ts > Compress Middleware > JSON Handling > should compress large JSON responses",
|
||||
"src/middleware/compress/index.test.ts > Compress Middleware > Streaming Responses > should compress streaming responses written in multiple chunks",
|
||||
"src/middleware/language/index.test.ts > languageDetector > Debug Mode > should log debug information when enabled",
|
||||
"src/middleware/language/index.test.ts > languageDetector > Debug Mode > should log errors in debug mode",
|
||||
"src/middleware/language/index.test.ts > languageDetector > Error Handling > should fall back to default language on error",
|
||||
"src/middleware/logger/index.test.ts > Logger by Middleware in NO_COLOR > Log status 200 with big body",
|
||||
"src/middleware/logger/index.test.ts > Logger by Middleware in NO_COLOR > Log status 200 with empty body",
|
||||
"src/middleware/logger/index.test.ts > Logger by Middleware in NO_COLOR > Log status 200 with small body",
|
||||
"src/middleware/logger/index.test.ts > Logger by Middleware in NO_COLOR > Log status 404",
|
||||
"src/middleware/logger/index.test.ts > Logger by Middleware in NO_COLOR > Time in seconds",
|
||||
"src/middleware/logger/index.test.ts > ✗ ",
|
||||
"src/middleware/method-override/index.test.ts > Method Override Middleware > Header > Should override POST to DELETE",
|
||||
"src/middleware/method-override/index.test.ts > SIGTRAP",
|
||||
"src/middleware/request-id/index.test.ts > Request ID Middleware > Should return random request id",
|
||||
"src/middleware/serve-static/index.test.ts > code 1",
|
||||
"src/middleware/timing/index.test.ts > Server-Timing API > Should not be enabled if the main app has the timing middleware",
|
||||
"src/request.test.ts > Body methods with caching > req.parseBody() > Return type > specify return type explicitly",
|
||||
"src/request.test.ts > Body methods with caching > req.parseBody() > Return type > without options",
|
||||
"src/request.test.ts > Body methods with caching > req.parseBody() > Return type > {all: true, dot: true}",
|
||||
"src/request.test.ts > Body methods with caching > req.parseBody() > Return type > {all: true}",
|
||||
"src/request.test.ts > Body methods with caching > req.parseBody() > Return type > {dot: true}",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > ALL and Star > Should return /x and star",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > ALL star, ALL star, GET static, ALL star... > Should return wildcard, star2 and bar",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > All > GET, all hello",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Basic Usage > GET, post hello",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Capture Group > Complex capturing group > GET request",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Capture Group > Non-capturing group > GET /foo/bar",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Capture Group > Non-capturing group > GET /foo/baz",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Capture Group > Non-capturing group > GET /foo/qux",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Capture Group > Non-capturing group with prefix > GET /foo/bar",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Capture Group > Non-capturing group with prefix > GET /foo/baz",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Capture Group > Non-capturing group with prefix > GET /foo/qux",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Capture Group > Simple capturing group > GET /foo/bar",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Capture Group > Simple capturing group > GET /foo/baz",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Capture Group > Simple capturing group > GET /foo/qux",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Capture complex multiple directories > GET /part1/middle-b/end-c/latest",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Capture complex multiple directories > GET /part1/middle-b/latest",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Capture multiple directories and optional > GET /foo/bar/contents",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Capture multiple directories and optional > GET /foo/bar/contents/123",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Capture regex pattern has trailing wildcard > GET /foo/bar/file.html",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Capture simple multiple directories > GET /foo/bar/file.html",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Complex > /*",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Complex > Default",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Complex > Named Param",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Complex > Regexp",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Complex > Wildcard",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Duplicate param name > child",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Duplicate param name > parent",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Duplicate param name > self",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > GET star, ALL static, GET star... > Should return /x and star",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > GET star, GET static, ALL star... > Should return star1, star2, and bar",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Including slashes > GET /js/chunk/123.js",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Including slashes > GET /js/chunk/nest/123.js",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Including slashes > GET /js/main.js",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Multi match > Blog > DELETE /entry",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Multi match > Blog > GET /",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Multi match > Blog > GET /entry/123",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Multi match > Blog > GET /entry/123/comment/456",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Multi match > Blog > POST /entry",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Multi match > `params` per a handler > GET /entry/123/show",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Multi match > hierarchy",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Optional route > GET /api/animals",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Optional route > GET /api/animals/dog",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Optional route > GET /v1",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Optional route > GET /v1/123",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Optional route > GET /v1/123/abc",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > REST API > GET /users/hono",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > REST API > GET /users/hono/posts",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Registration order > handler -> fallback",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Registration order > middleware -> handler",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Reserved words > Reserved words and named parameter",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Reserved words > Reserved words and optional named parameter",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Reserved words > Reserved words and wildcard",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Routing with a hostname > GET /hello",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Routing with a hostname > GET www1.example.com/hello",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Routing with a hostname > GET www2.example.com/hello",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Same path > GET /hey",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Trailing slash > GET /book",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Trailing slash > GET /book/",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Unknown method > UNKNOWN_METHOD /",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > Unknown method > UNKNOWN_METHOD /all",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > long prefix, then star > ALL and GET > GET /",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > long prefix, then star > ALL and GET > GET /long/prefix",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > long prefix, then star > ALL and GET > GET /long/prefix/test",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > long prefix, then star > GET only > GET /",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > long prefix, then star > GET only > GET /long/prefix",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > long prefix, then star > GET only > GET /long/prefix/test",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > non ascii characters > GET /$/hono",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > non ascii characters > GET /()/hono",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > page > GET /page",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > star > Under a certain path",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > star > top",
|
||||
"src/router/linear-router/router.test.ts > LinearRouter > Common > static routes of ALL and GET > get /foo",
|
||||
"src/router/linear-router/router.test.ts > ✗ ",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > ALL and Star > Should return /x and star",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > ALL star, ALL star, GET static, ALL star... > Should return wildcard, star2 and bar",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > All > GET, all hello",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Basic Usage > GET, post hello",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Capture Group > Complex capturing group > GET request",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Capture Group > Non-capturing group > GET /foo/bar",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Capture Group > Non-capturing group > GET /foo/baz",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Capture Group > Non-capturing group > GET /foo/qux",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Capture Group > Non-capturing group with prefix > GET /foo/bar",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Capture Group > Non-capturing group with prefix > GET /foo/baz",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Capture Group > Non-capturing group with prefix > GET /foo/qux",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Capture Group > Simple capturing group > GET /foo/bar",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Capture Group > Simple capturing group > GET /foo/baz",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Capture Group > Simple capturing group > GET /foo/qux",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Capture complex multiple directories > GET /part1/middle-b/end-c/latest",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Capture complex multiple directories > GET /part1/middle-b/latest",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Capture multiple directories and optional > GET /foo/bar/contents",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Capture multiple directories and optional > GET /foo/bar/contents/123",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Capture regex pattern has trailing wildcard > GET /foo/bar/file.html",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Capture simple multiple directories > GET /foo/bar/file.html",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Complex > /*",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Complex > Default",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Complex > Named Param",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Complex > Regexp",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Complex > Wildcard",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Duplicate param name > child",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Duplicate param name > parent",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Duplicate param name > self",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > GET star, ALL static, GET star... > Should return /x and star",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > GET star, GET static, ALL star... > Should return star1, star2, and bar",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Including slashes > GET /js/chunk/123.js",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Including slashes > GET /js/chunk/nest/123.js",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Including slashes > GET /js/main.js",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Multi match > Blog > DELETE /entry",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Multi match > Blog > GET /",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Multi match > Blog > GET /entry/123",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Multi match > Blog > GET /entry/123/comment/456",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Multi match > Blog > POST /entry",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Multi match > `params` per a handler > GET /entry/123/show",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Multi match > hierarchy",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Optional route > GET /api/animals",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Optional route > GET /api/animals/dog",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Optional route > GET /v1",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Optional route > GET /v1/123",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Optional route > GET /v1/123/abc",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > REST API > GET /users/hono",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > REST API > GET /users/hono/posts",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Registration order > handler -> fallback",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Registration order > middleware -> handler",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Reserved words > Reserved words and named parameter",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Reserved words > Reserved words and optional named parameter",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Reserved words > Reserved words and wildcard",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Routing with a hostname > GET /hello",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Routing with a hostname > GET www1.example.com/hello",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Routing with a hostname > GET www2.example.com/hello",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Same path > GET /hey",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Trailing slash > GET /book",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Trailing slash > GET /book/",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Unknown method > UNKNOWN_METHOD /",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > Unknown method > UNKNOWN_METHOD /all",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > long prefix, then star > ALL and GET > GET /",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > long prefix, then star > ALL and GET > GET /long/prefix",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > long prefix, then star > ALL and GET > GET /long/prefix/test",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > long prefix, then star > GET only > GET /",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > long prefix, then star > GET only > GET /long/prefix",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > long prefix, then star > GET only > GET /long/prefix/test",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > non ascii characters > GET /$/hono",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > non ascii characters > GET /()/hono",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > page > GET /page",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > star > Under a certain path",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > star > top",
|
||||
"src/router/pattern-router/router.test.ts > Pattern > Common > static routes of ALL and GET > get /foo",
|
||||
"src/router/pattern-router/router.test.ts > ✗ ",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > ALL and Star > Should return /x and star",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > ALL star, ALL star, GET static, ALL star... > Should return wildcard, star2 and bar",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > All > GET, all hello",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Basic Usage > GET, post hello",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Capture Group > Complex capturing group > GET request",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Capture Group > Non-capturing group > GET /foo/bar",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Capture Group > Non-capturing group > GET /foo/baz",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Capture Group > Non-capturing group > GET /foo/qux",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Capture Group > Non-capturing group with prefix > GET /foo/bar",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Capture Group > Non-capturing group with prefix > GET /foo/baz",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Capture Group > Non-capturing group with prefix > GET /foo/qux",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Capture Group > Simple capturing group > GET /foo/bar",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Capture Group > Simple capturing group > GET /foo/baz",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Capture Group > Simple capturing group > GET /foo/qux",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Capture complex multiple directories > GET /part1/middle-b/end-c/latest",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Capture complex multiple directories > GET /part1/middle-b/latest",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Capture multiple directories and optional > GET /foo/bar/contents",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Capture multiple directories and optional > GET /foo/bar/contents/123",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Capture regex pattern has trailing wildcard > GET /foo/bar/file.html",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Capture simple multiple directories > GET /foo/bar/file.html",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Complex > /*",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Complex > Default",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Complex > Named Param",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Complex > Regexp",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Complex > Wildcard",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Duplicate param name > child",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Duplicate param name > parent",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Duplicate param name > self",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > GET star, ALL static, GET star... > Should return /x and star",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > GET star, GET static, ALL star... > Should return star1, star2, and bar",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Including slashes > GET /js/chunk/123.js",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Including slashes > GET /js/chunk/nest/123.js",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Including slashes > GET /js/main.js",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Multi match > Blog > DELETE /entry",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Multi match > Blog > GET /",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Multi match > Blog > GET /entry/123",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Multi match > Blog > GET /entry/123/comment/456",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Multi match > Blog > POST /entry",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Multi match > `params` per a handler > GET /entry/123/show",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Multi match > hierarchy",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Optional route > GET /api/animals",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Optional route > GET /api/animals/dog",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Optional route > GET /v1",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Optional route > GET /v1/123",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Optional route > GET /v1/123/abc",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > REST API > GET /users/hono",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > REST API > GET /users/hono/posts",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Registration order > handler -> fallback",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Registration order > middleware -> handler",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Reserved words > Reserved words and named parameter",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Reserved words > Reserved words and optional named parameter",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Reserved words > Reserved words and wildcard",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Routing with a hostname > GET /hello",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Routing with a hostname > GET www1.example.com/hello",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Routing with a hostname > GET www2.example.com/hello",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Same path > GET /hey",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Trailing slash > GET /book",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Trailing slash > GET /book/",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Unknown method > UNKNOWN_METHOD /",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > Unknown method > UNKNOWN_METHOD /all",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > long prefix, then star > ALL and GET > GET /",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > long prefix, then star > ALL and GET > GET /long/prefix",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > long prefix, then star > ALL and GET > GET /long/prefix/test",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > long prefix, then star > GET only > GET /",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > long prefix, then star > GET only > GET /long/prefix",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > long prefix, then star > GET only > GET /long/prefix/test",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > non ascii characters > GET /$/hono",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > non ascii characters > GET /()/hono",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > page > GET /page",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > star > Under a certain path",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > star > top",
|
||||
"src/router/reg-exp-router/router.test.ts > RegExpRouter > Common > static routes of ALL and GET > get /foo",
|
||||
"src/router/reg-exp-router/router.test.ts > ✗ ",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > ALL and Star > Should return /x and star",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > ALL star, ALL star, GET static, ALL star... > Should return wildcard, star2 and bar",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > All > GET, all hello",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Basic Usage > GET, post hello",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Capture Group > Complex capturing group > GET request",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Capture Group > Non-capturing group > GET /foo/bar",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Capture Group > Non-capturing group > GET /foo/baz",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Capture Group > Non-capturing group > GET /foo/qux",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Capture Group > Non-capturing group with prefix > GET /foo/bar",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Capture Group > Non-capturing group with prefix > GET /foo/baz",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Capture Group > Non-capturing group with prefix > GET /foo/qux",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Capture Group > Simple capturing group > GET /foo/bar",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Capture Group > Simple capturing group > GET /foo/baz",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Capture Group > Simple capturing group > GET /foo/qux",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Capture complex multiple directories > GET /part1/middle-b/end-c/latest",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Capture complex multiple directories > GET /part1/middle-b/latest",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Capture multiple directories and optional > GET /foo/bar/contents",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Capture multiple directories and optional > GET /foo/bar/contents/123",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Capture regex pattern has trailing wildcard > GET /foo/bar/file.html",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Capture simple multiple directories > GET /foo/bar/file.html",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Complex > /*",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Complex > Default",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Complex > Named Param",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Complex > Regexp",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Complex > Wildcard",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Duplicate param name > child",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Duplicate param name > parent",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Duplicate param name > self",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > GET star, ALL static, GET star... > Should return /x and star",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > GET star, GET static, ALL star... > Should return star1, star2, and bar",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Including slashes > GET /js/chunk/123.js",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Including slashes > GET /js/chunk/nest/123.js",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Including slashes > GET /js/main.js",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Multi match > Blog > DELETE /entry",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Multi match > Blog > GET /",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Multi match > Blog > GET /entry/123",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Multi match > Blog > GET /entry/123/comment/456",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Multi match > Blog > POST /entry",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Multi match > `params` per a handler > GET /entry/123/show",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Multi match > hierarchy",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Optional route > GET /api/animals",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Optional route > GET /api/animals/dog",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Optional route > GET /v1",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Optional route > GET /v1/123",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Optional route > GET /v1/123/abc",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > REST API > GET /users/hono",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > REST API > GET /users/hono/posts",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Registration order > handler -> fallback",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Registration order > middleware -> handler",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Reserved words > Reserved words and named parameter",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Reserved words > Reserved words and optional named parameter",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Reserved words > Reserved words and wildcard",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Routing with a hostname > GET /hello",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Routing with a hostname > GET www1.example.com/hello",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Routing with a hostname > GET www2.example.com/hello",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Same path > GET /hey",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Trailing slash > GET /book",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Trailing slash > GET /book/",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Unknown method > UNKNOWN_METHOD /",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > Unknown method > UNKNOWN_METHOD /all",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > long prefix, then star > ALL and GET > GET /",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > long prefix, then star > ALL and GET > GET /long/prefix",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > long prefix, then star > ALL and GET > GET /long/prefix/test",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > long prefix, then star > GET only > GET /",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > long prefix, then star > GET only > GET /long/prefix",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > long prefix, then star > GET only > GET /long/prefix/test",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > non ascii characters > GET /$/hono",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > non ascii characters > GET /()/hono",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > page > GET /page",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > star > Under a certain path",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > star > top",
|
||||
"src/router/smart-router/router.test.ts > SmartRouter > Common > static routes of ALL and GET > get /foo",
|
||||
"src/router/smart-router/router.test.ts > ✗ ",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > ALL and Star > Should return /x and star",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > ALL star, ALL star, GET static, ALL star... > Should return wildcard, star2 and bar",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > All > GET, all hello",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Basic Usage > GET, post hello",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Capture Group > Complex capturing group > GET request",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Capture Group > Non-capturing group > GET /foo/bar",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Capture Group > Non-capturing group > GET /foo/baz",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Capture Group > Non-capturing group > GET /foo/qux",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Capture Group > Non-capturing group with prefix > GET /foo/bar",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Capture Group > Non-capturing group with prefix > GET /foo/baz",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Capture Group > Non-capturing group with prefix > GET /foo/qux",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Capture Group > Simple capturing group > GET /foo/bar",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Capture Group > Simple capturing group > GET /foo/baz",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Capture Group > Simple capturing group > GET /foo/qux",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Capture complex multiple directories > GET /part1/middle-b/end-c/latest",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Capture complex multiple directories > GET /part1/middle-b/latest",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Capture multiple directories and optional > GET /foo/bar/contents",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Capture multiple directories and optional > GET /foo/bar/contents/123",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Capture regex pattern has trailing wildcard > GET /foo/bar/file.html",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Capture simple multiple directories > GET /foo/bar/file.html",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Complex > /*",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Complex > Default",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Complex > Named Param",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Complex > Regexp",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Complex > Wildcard",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Duplicate param name > child",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Duplicate param name > parent",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Duplicate param name > self",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > GET star, ALL static, GET star... > Should return /x and star",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > GET star, GET static, ALL star... > Should return star1, star2, and bar",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Including slashes > GET /js/chunk/123.js",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Including slashes > GET /js/chunk/nest/123.js",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Including slashes > GET /js/main.js",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Multi match > Blog > DELETE /entry",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Multi match > Blog > GET /",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Multi match > Blog > GET /entry/123",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Multi match > Blog > GET /entry/123/comment/456",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Multi match > Blog > POST /entry",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Multi match > `params` per a handler > GET /entry/123/show",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Multi match > hierarchy",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Optional route > GET /api/animals",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Optional route > GET /api/animals/dog",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Optional route > GET /v1",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Optional route > GET /v1/123",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Optional route > GET /v1/123/abc",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > REST API > GET /users/hono",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > REST API > GET /users/hono/posts",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Registration order > handler -> fallback",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Registration order > middleware -> handler",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Reserved words > Reserved words and named parameter",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Reserved words > Reserved words and optional named parameter",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Reserved words > Reserved words and wildcard",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Routing with a hostname > GET /hello",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Routing with a hostname > GET www1.example.com/hello",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Routing with a hostname > GET www2.example.com/hello",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Same path > GET /hey",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Trailing slash > GET /book",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Trailing slash > GET /book/",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Unknown method > UNKNOWN_METHOD /",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > Unknown method > UNKNOWN_METHOD /all",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > long prefix, then star > ALL and GET > GET /",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > long prefix, then star > ALL and GET > GET /long/prefix",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > long prefix, then star > ALL and GET > GET /long/prefix/test",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > long prefix, then star > GET only > GET /",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > long prefix, then star > GET only > GET /long/prefix",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > long prefix, then star > GET only > GET /long/prefix/test",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > non ascii characters > GET /$/hono",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > non ascii characters > GET /()/hono",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > page > GET /page",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > star > Under a certain path",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > star > top",
|
||||
"src/router/trie-router/router.test.ts > TrieRouter > Common > static routes of ALL and GET > get /foo",
|
||||
"src/router/trie-router/router.test.ts > ✗ ",
|
||||
"src/utils/body.test.ts > BodyData > without options",
|
||||
"src/utils/body.test.ts > BodyData > {all: boolean, dot: boolean}",
|
||||
"src/utils/body.test.ts > BodyData > {all: boolean}",
|
||||
"src/utils/body.test.ts > BodyData > {all: true, dot: true}",
|
||||
"src/utils/body.test.ts > BodyData > {all: true}",
|
||||
"src/utils/body.test.ts > BodyData > {dot: boolean}",
|
||||
"src/utils/body.test.ts > BodyData > {dot: true}",
|
||||
"src/utils/body.test.ts > Parse Body Util > Return type > specify return type explicitly",
|
||||
"src/utils/body.test.ts > Parse Body Util > Return type > without options",
|
||||
"src/utils/body.test.ts > Parse Body Util > Return type > {all: boolean, dot: boolean}",
|
||||
"src/utils/body.test.ts > Parse Body Util > Return type > {all: boolean}",
|
||||
"src/utils/body.test.ts > Parse Body Util > Return type > {all: true, dot: true}",
|
||||
"src/utils/body.test.ts > Parse Body Util > Return type > {all: true}",
|
||||
"src/utils/body.test.ts > Parse Body Util > Return type > {dot: boolean}",
|
||||
"src/utils/body.test.ts > Parse Body Util > Return type > {dot: true}",
|
||||
"src/utils/body.test.ts > Parse Body Util > should not update file object properties",
|
||||
"src/utils/color.test.ts > ✗ ",
|
||||
"src/utils/concurrent.test.ts > concurrent execution > concurrency $concurrency, count $count",
|
||||
"src/utils/ipaddr.test.ts > convertIPv4ToString > convertIPv4ToString($input) === $expected",
|
||||
"src/utils/ipaddr.test.ts > convertIPv6ToString > convertIPv6ToString($input) === $expected",
|
||||
"src/utils/stream.test.ts > StreamingApi > abort()",
|
||||
"src/utils/stream.test.ts > StreamingApi > onAbort()",
|
||||
"src/utils/types.test.ts > JSONParsed > Set/Map > should convert Map to empty object",
|
||||
"src/utils/types.test.ts > JSONParsed > Set/Map > should convert Set to empty object",
|
||||
"src/utils/types.test.ts > JSONParsed > Should parse a complex interface",
|
||||
"src/utils/types.test.ts > JSONParsed > Should parse a complex type",
|
||||
"src/utils/types.test.ts > JSONParsed > array > should convert (T | undefined)[] type to JSONParsedT | null>[]",
|
||||
"src/utils/types.test.ts > JSONParsed > array > should convert Function[] type to null[]",
|
||||
"src/utils/types.test.ts > JSONParsed > array > should convert symbol[] type to null[]",
|
||||
"src/utils/types.test.ts > JSONParsed > array > should convert undefined[] type to null[]",
|
||||
"src/utils/types.test.ts > JSONParsed > array > should convert { key: readonly T[]} correctly",
|
||||
"src/utils/types.test.ts > JSONParsed > invalid types > should convert function type to never",
|
||||
"src/utils/types.test.ts > JSONParsed > invalid types > should convert symbol type to never",
|
||||
"src/utils/types.test.ts > JSONParsed > invalid types > should convert undefined type to never",
|
||||
"src/utils/types.test.ts > JSONParsed > object > should convert T | undefined to T | undefined",
|
||||
"src/utils/types.test.ts > JSONParsed > object > should omit keys with function value",
|
||||
"src/utils/types.test.ts > JSONParsed > object > should omit keys with invalid union",
|
||||
"src/utils/types.test.ts > JSONParsed > object > should omit keys with symbol value",
|
||||
"src/utils/types.test.ts > JSONParsed > object > should omit keys with undefined value",
|
||||
"src/utils/types.test.ts > JSONParsed > object > should omit symbol keys",
|
||||
"src/utils/types.test.ts > JSONParsed > primitives > should convert boolean type to boolean",
|
||||
"src/utils/types.test.ts > JSONParsed > primitives > should convert null type to null",
|
||||
"src/utils/types.test.ts > JSONParsed > primitives > should convert number type to number",
|
||||
"src/utils/types.test.ts > JSONParsed > primitives > should convert string type to string",
|
||||
"src/utils/types.test.ts > JSONParsed > toJSON > should convert { a: { toJSON() => T } } to { a: T }",
|
||||
"src/utils/types.test.ts > JSONParsed > toJSON > should convert { toJSON() => T } to T",
|
||||
"src/utils/types.test.ts > JSONParsed > toJSON > toJSON is not called recursively",
|
||||
"src/utils/types.test.ts > JSONParsed > tuple > should convert [T, S] type to [T, S]",
|
||||
"src/utils/types.test.ts > JSONParsed > tuple > should convert [T, undefined] type to [T, null]",
|
||||
"src/utils/url.test.ts > url > getPattern > regex pattern with next",
|
||||
"src/validator/validator.test.ts > Validator with using Zod directly > Should exclude Response & TypedResponse type"
|
||||
]
|
||||
}
|
||||
]
|
||||
]
|
||||
Reference in New Issue
Block a user