diff --git a/.github/workflows/update-vendor.yml b/.github/workflows/update-vendor.yml index 7e1ad4ec21..cee2a681fa 100644 --- a/.github/workflows/update-vendor.yml +++ b/.github/workflows/update-vendor.yml @@ -16,6 +16,7 @@ jobs: matrix: package: - elysia + - express steps: - uses: actions/checkout@v4 diff --git a/scripts/runner.node.mjs b/scripts/runner.node.mjs index cdf824ddfb..87fc6ea6e3 100755 --- a/scripts/runner.node.mjs +++ b/scripts/runner.node.mjs @@ -492,7 +492,7 @@ async function runTests() { if (isBuildkite) { // Group flaky tests together, regardless of the title const context = flaky ? "flaky" : title; - const style = flaky || title.startsWith("vendor") ? "warning" : "error"; + const style = flaky ? "warning" : "error"; if (!flaky) attempt = 1; // no need to show the retries count on failures, we know it maxed out if (title.startsWith("vendor")) { @@ -644,7 +644,7 @@ async function runTests() { } if (vendorTests?.length) { - for (const { cwd: vendorPath, packageManager, testRunner, testPaths } of vendorTests) { + for (const { cwd: vendorPath, packageManager, testRunner, testPaths, build } of vendorTests) { if (!testPaths.length) { continue; } @@ -659,13 +659,12 @@ async function runTests() { throw new Error(`Unsupported package manager: ${packageManager}`); } - // build const buildResult = await spawnBun(execPath, { cwd: vendorPath, args: ["run", "build"], timeout: 60_000, }); - if (!buildResult.ok) { + if (build && !buildResult.ok) { throw new Error(`Failed to build vendor: ${buildResult.error}`); } @@ -1660,6 +1659,7 @@ function getTests(cwd) { * @property {string} [testRunner] * @property {string[]} [testExtensions] * @property {boolean | Record} [skipTests] + * @property {boolean} [build] */ /** @@ -1668,6 +1668,7 @@ function getTests(cwd) { * @property {string} packageManager * @property {string} testRunner * @property {string[]} testPaths + * @property {boolean} build */ /** @@ -1702,7 +1703,17 @@ async function getVendorTests(cwd) { return Promise.all( relevantVendors.map( - async ({ package: name, repository, tag, testPath, testExtensions, testRunner, packageManager, skipTests }) => { + async ({ + package: name, + repository, + tag, + testPath, + testExtensions, + testRunner, + packageManager, + skipTests, + build, + }) => { const vendorPath = join(cwd, "vendor", name); if (!existsSync(vendorPath)) { @@ -1779,6 +1790,7 @@ async function getVendorTests(cwd) { packageManager: packageManager || "bun", testRunner: testRunner || "bun", testPaths, + build: build ?? true, }; }, ), diff --git a/test/js/third_party/express/README.md b/test/js/third_party/express/README.md deleted file mode 100644 index 470f21b15e..0000000000 --- a/test/js/third_party/express/README.md +++ /dev/null @@ -1 +0,0 @@ -Test cases ported from [express](https://github.com/expressjs/express). MIT license. diff --git a/test/js/third_party/express/app.router.test.ts b/test/js/third_party/express/app.router.test.ts deleted file mode 100644 index 0c69478f09..0000000000 --- a/test/js/third_party/express/app.router.test.ts +++ /dev/null @@ -1,1108 +0,0 @@ -"use strict"; - -var after = require("./support/after"); -var express = require("express"), - request = require("supertest"), - assert = require("node:assert"), - methods = require("./support/utils").methods; - -var shouldSkipQuery = require("./support/utils").shouldSkipQuery; - -describe("app.router", function () { - it("should restore req.params after leaving router", function (done) { - var app = express(); - var router = new express.Router(); - - function handler1(req, res, next) { - res.setHeader("x-user-id", String(req.params.id)); - next(); - } - - function handler2(req, res) { - res.send(req.params.id); - } - - router.use(function (req, res, next) { - res.setHeader("x-router", String(req.params.id)); - next(); - }); - - app.get("/user/:id", handler1, router, handler2); - - request(app).get("/user/1").expect("x-router", "undefined").expect("x-user-id", "1").expect(200, "1", done); - }); - - describe("methods", function () { - methods.forEach(function (method) { - if (method === "connect") return; - - it("should include " + method.toUpperCase(), function (done) { - if (method === "query" && shouldSkipQuery(process.versions.node)) { - this.skip(); - } - var app = express(); - - app[method]("/foo", function (req, res) { - res.send(method); - }); - - request(app)[method]("/foo").expect(200, done); - }); - - it.todo("should reject numbers for app." + method, function () { - var app = express(); - assert.throws(app[method].bind(app, "/", 3), /argument handler must be a function/); - }); - }); - - it("should re-route when method is altered", function (done) { - var app = express(); - var cb = after(3, done); - - app.use(function (req, res, next) { - if (req.method !== "POST") return next(); - req.method = "DELETE"; - res.setHeader("X-Method-Altered", "1"); - next(); - }); - - app.delete("/", function (req, res) { - res.end("deleted everything"); - }); - - request(app).get("/").expect(404, cb); - - request(app).delete("/").expect(200, "deleted everything", cb); - - request(app).post("/").expect("X-Method-Altered", "1").expect(200, "deleted everything", cb); - }); - }); - - describe("decode params", function () { - it("should decode correct params", function (done) { - var app = express(); - - app.get("/:name", function (req, res) { - res.send(req.params.name); - }); - - request(app).get("/foo%2Fbar").expect("foo/bar", done); - }); - - it("should not accept params in malformed paths", function (done) { - var app = express(); - - app.get("/:name", function (req, res) { - res.send(req.params.name); - }); - - request(app).get("/%foobar").expect(400, done); - }); - - it("should not decode spaces", function (done) { - var app = express(); - - app.get("/:name", function (req, res) { - res.send(req.params.name); - }); - - request(app).get("/foo+bar").expect("foo+bar", done); - }); - - it("should work with unicode", function (done) { - var app = express(); - - app.get("/:name", function (req, res) { - res.send(req.params.name); - }); - - request(app).get("/%ce%b1").expect("\u03b1", done); - }); - }); - - it("should be .use()able", function (done) { - var app = express(); - - var calls = []; - - app.use(function (req, res, next) { - calls.push("before"); - next(); - }); - - app.get("/", function (req, res, next) { - calls.push("GET /"); - next(); - }); - - app.use(function (req, res, next) { - calls.push("after"); - res.json(calls); - }); - - request(app).get("/").expect(200, ["before", "GET /", "after"], done); - }); - - describe("when given a regexp", function () { - it("should match the pathname only", function (done) { - var app = express(); - - app.get(/^\/user\/[0-9]+$/, function (req, res) { - res.end("user"); - }); - - request(app).get("/user/12?foo=bar").expect("user", done); - }); - - it("should populate req.params with the captures", function (done) { - var app = express(); - - app.get(/^\/user\/([0-9]+)\/(view|edit)?$/, function (req, res) { - var id = req.params[0], - op = req.params[1]; - res.end(op + "ing user " + id); - }); - - request(app).get("/user/10/edit").expect("editing user 10", done); - }); - - if (supportsRegexp("(?.*)")) { - it.todo("should populate req.params with named captures", function (done) { - var app = express(); - var re = new RegExp("^/user/(?[0-9]+)/(view|edit)?$"); - - app.get(re, function (req, res) { - var id = req.params.userId, - op = req.params[0]; - res.end(op + "ing user " + id); - }); - - request(app).get("/user/10/edit").expect("editing user 10", done); - }); - } - - it("should ensure regexp matches path prefix", function (done) { - var app = express(); - var p = []; - - app.use(/\/api.*/, function (req, res, next) { - p.push("a"); - next(); - }); - app.use(/api/, function (req, res, next) { - p.push("b"); - next(); - }); - app.use(/\/test/, function (req, res, next) { - p.push("c"); - next(); - }); - app.use(function (req, res) { - res.end(); - }); - - request(app) - .get("/test/api/1234") - .expect(200, function (err) { - if (err) return done(err); - assert.deepEqual(p, ["c"]); - done(); - }); - }); - }); - - describe("case sensitivity", function () { - it("should be disabled by default", function (done) { - var app = express(); - - app.get("/user", function (req, res) { - res.end("tj"); - }); - - request(app).get("/USER").expect("tj", done); - }); - - describe('when "case sensitive routing" is enabled', function () { - it("should match identical casing", function (done) { - var app = express(); - - app.enable("case sensitive routing"); - - app.get("/uSer", function (req, res) { - res.end("tj"); - }); - - request(app).get("/uSer").expect("tj", done); - }); - - it("should not match otherwise", function (done) { - var app = express(); - - app.enable("case sensitive routing"); - - app.get("/uSer", function (req, res) { - res.end("tj"); - }); - - request(app).get("/user").expect(404, done); - }); - }); - }); - - describe("params", function () { - it("should overwrite existing req.params by default", function (done) { - var app = express(); - var router = new express.Router(); - - router.get("/:action", function (req, res) { - res.send(req.params); - }); - - app.use("/user/:user", router); - - request(app).get("/user/1/get").expect(200, '{"action":"get"}', done); - }); - - it("should allow merging existing req.params", function (done) { - var app = express(); - var router = new express.Router({ mergeParams: true }); - - router.get("/:action", function (req, res) { - var keys = Object.keys(req.params).sort(); - res.send( - keys.map(function (k) { - return [k, req.params[k]]; - }), - ); - }); - - app.use("/user/:user", router); - - request(app).get("/user/tj/get").expect(200, '[["action","get"],["user","tj"]]', done); - }); - - it("should use params from router", function (done) { - var app = express(); - var router = new express.Router({ mergeParams: true }); - - router.get("/:thing", function (req, res) { - var keys = Object.keys(req.params).sort(); - res.send( - keys.map(function (k) { - return [k, req.params[k]]; - }), - ); - }); - - app.use("/user/:thing", router); - - request(app).get("/user/tj/get").expect(200, '[["thing","get"]]', done); - }); - - it("should merge numeric indices req.params", function (done) { - var app = express(); - var router = new express.Router({ mergeParams: true }); - - router.get(/^\/(.*)\.(.*)/, function (req, res) { - var keys = Object.keys(req.params).sort(); - res.send( - keys.map(function (k) { - return [k, req.params[k]]; - }), - ); - }); - - app.use(/^\/user\/id:(\d+)/, router); - - request(app).get("/user/id:10/profile.json").expect(200, '[["0","10"],["1","profile"],["2","json"]]', done); - }); - - it("should merge numeric indices req.params when more in parent", function (done) { - var app = express(); - var router = new express.Router({ mergeParams: true }); - - router.get(/\/(.*)/, function (req, res) { - var keys = Object.keys(req.params).sort(); - res.send( - keys.map(function (k) { - return [k, req.params[k]]; - }), - ); - }); - - app.use(/^\/user\/id:(\d+)\/name:(\w+)/, router); - - request(app).get("/user/id:10/name:tj/profile").expect(200, '[["0","10"],["1","tj"],["2","profile"]]', done); - }); - - it("should merge numeric indices req.params when parent has same number", function (done) { - var app = express(); - var router = new express.Router({ mergeParams: true }); - - router.get(/\/name:(\w+)/, function (req, res) { - var keys = Object.keys(req.params).sort(); - res.send( - keys.map(function (k) { - return [k, req.params[k]]; - }), - ); - }); - - app.use(/\/user\/id:(\d+)/, router); - - request(app).get("/user/id:10/name:tj").expect(200, '[["0","10"],["1","tj"]]', done); - }); - - it("should ignore invalid incoming req.params", function (done) { - var app = express(); - var router = new express.Router({ mergeParams: true }); - - router.get("/:name", function (req, res) { - var keys = Object.keys(req.params).sort(); - res.send( - keys.map(function (k) { - return [k, req.params[k]]; - }), - ); - }); - - app.use("/user/", function (req, res, next) { - req.params = 3; // wat? - router(req, res, next); - }); - - request(app).get("/user/tj").expect(200, '[["name","tj"]]', done); - }); - - it("should restore req.params", function (done) { - var app = express(); - var router = new express.Router({ mergeParams: true }); - - router.get(/\/user:(\w+)\//, function (req, res, next) { - next(); - }); - - app.use(/\/user\/id:(\d+)/, function (req, res, next) { - router(req, res, function (err) { - var keys = Object.keys(req.params).sort(); - res.send( - keys.map(function (k) { - return [k, req.params[k]]; - }), - ); - }); - }); - - request(app).get("/user/id:42/user:tj/profile").expect(200, '[["0","42"]]', done); - }); - }); - - describe("trailing slashes", function () { - it("should be optional by default", function (done) { - var app = express(); - - app.get("/user", function (req, res) { - res.end("tj"); - }); - - request(app).get("/user/").expect("tj", done); - }); - - describe('when "strict routing" is enabled', function () { - it("should match trailing slashes", function (done) { - var app = express(); - - app.enable("strict routing"); - - app.get("/user/", function (req, res) { - res.end("tj"); - }); - - request(app).get("/user/").expect("tj", done); - }); - - it("should pass-though middleware", function (done) { - var app = express(); - - app.enable("strict routing"); - - app.use(function (req, res, next) { - res.setHeader("x-middleware", "true"); - next(); - }); - - app.get("/user/", function (req, res) { - res.end("tj"); - }); - - request(app).get("/user/").expect("x-middleware", "true").expect(200, "tj", done); - }); - - it("should pass-though mounted middleware", function (done) { - var app = express(); - - app.enable("strict routing"); - - app.use("/user/", function (req, res, next) { - res.setHeader("x-middleware", "true"); - next(); - }); - - app.get("/user/test/", function (req, res) { - res.end("tj"); - }); - - request(app).get("/user/test/").expect("x-middleware", "true").expect(200, "tj", done); - }); - - it("should match no slashes", function (done) { - var app = express(); - - app.enable("strict routing"); - - app.get("/user", function (req, res) { - res.end("tj"); - }); - - request(app).get("/user").expect("tj", done); - }); - - it("should match middleware when omitting the trailing slash", function (done) { - var app = express(); - - app.enable("strict routing"); - - app.use("/user/", function (req, res) { - res.end("tj"); - }); - - request(app).get("/user").expect(200, "tj", done); - }); - - it("should match middleware", function (done) { - var app = express(); - - app.enable("strict routing"); - - app.use("/user", function (req, res) { - res.end("tj"); - }); - - request(app).get("/user").expect(200, "tj", done); - }); - - it("should match middleware when adding the trailing slash", function (done) { - var app = express(); - - app.enable("strict routing"); - - app.use("/user", function (req, res) { - res.end("tj"); - }); - - request(app).get("/user/").expect(200, "tj", done); - }); - - it("should fail when omitting the trailing slash", function (done) { - var app = express(); - - app.enable("strict routing"); - - app.get("/user/", function (req, res) { - res.end("tj"); - }); - - request(app).get("/user").expect(404, done); - }); - - it("should fail when adding the trailing slash", function (done) { - var app = express(); - - app.enable("strict routing"); - - app.get("/user", function (req, res) { - res.end("tj"); - }); - - request(app).get("/user/").expect(404, done); - }); - }); - }); - - it('should allow literal "."', function (done) { - var app = express(); - - app.get("/api/users/:from..:to", function (req, res) { - var from = req.params.from, - to = req.params.to; - - res.end("users from " + from + " to " + to); - }); - - request(app).get("/api/users/1..50").expect("users from 1 to 50", done); - }); - - describe(":name", function () { - it("should denote a capture group", function (done) { - var app = express(); - - app.get("/user/:user", function (req, res) { - res.end(req.params.user); - }); - - request(app).get("/user/tj").expect("tj", done); - }); - - it("should match a single segment only", function (done) { - var app = express(); - - app.get("/user/:user", function (req, res) { - res.end(req.params.user); - }); - - request(app).get("/user/tj/edit").expect(404, done); - }); - - it("should allow several capture groups", function (done) { - var app = express(); - - app.get("/user/:user/:op", function (req, res) { - res.end(req.params.op + "ing " + req.params.user); - }); - - request(app).get("/user/tj/edit").expect("editing tj", done); - }); - - it.todo("should work following a partial capture group", function (done) { - var app = express(); - var cb = after(2, done); - - app.get("/user{s}/:user/:op", function (req, res) { - res.end(req.params.op + "ing " + req.params.user + (req.url.startsWith("/users") ? " (old)" : "")); - }); - - request(app).get("/user/tj/edit").expect("editing tj", cb); - - request(app).get("/users/tj/edit").expect("editing tj (old)", cb); - }); - - it("should work inside literal parenthesis", function (done) { - var app = express(); - - app.get("/:user\\(:op\\)", function (req, res) { - res.end(req.params.op + "ing " + req.params.user); - }); - - request(app).get("/tj(edit)").expect("editing tj", done); - }); - - it("should work in array of paths", function (done) { - var app = express(); - var cb = after(2, done); - - app.get(["/user/:user/poke", "/user/:user/pokes"], function (req, res) { - res.end("poking " + req.params.user); - }); - - request(app).get("/user/tj/poke").expect("poking tj", cb); - - request(app).get("/user/tj/pokes").expect("poking tj", cb); - }); - }); - - describe.todo(":name?", function () { - it("should denote an optional capture group", function (done) { - var app = express(); - - app.get("/user/:user{/:op}", function (req, res) { - var op = req.params.op || "view"; - res.end(op + "ing " + req.params.user); - }); - - request(app).get("/user/tj").expect("viewing tj", done); - }); - - it("should populate the capture group", function (done) { - var app = express(); - - app.get("/user/:user{/:op}", function (req, res) { - var op = req.params.op || "view"; - res.end(op + "ing " + req.params.user); - }); - - request(app).get("/user/tj/edit").expect("editing tj", done); - }); - }); - - describe.todo(":name*", function () { - it("should match one segment", function (done) { - var app = express(); - - app.get("/user/*user", function (req, res) { - res.end(req.params.user[0]); - }); - - request(app).get("/user/122").expect("122", done); - }); - - it("should match many segments", function (done) { - var app = express(); - - app.get("/user/*user", function (req, res) { - res.end(req.params.user.join("/")); - }); - - request(app).get("/user/1/2/3/4").expect("1/2/3/4", done); - }); - - it("should match zero segments", function (done) { - var app = express(); - - app.get("/user{/*user}", function (req, res) { - res.end(req.params.user); - }); - - request(app).get("/user").expect("", done); - }); - }); - - describe.todo(":name+", function () { - it("should match one segment", function (done) { - var app = express(); - - app.get("/user/*user", function (req, res) { - res.end(req.params.user[0]); - }); - - request(app).get("/user/122").expect(200, "122", done); - }); - - it("should match many segments", function (done) { - var app = express(); - - app.get("/user/*user", function (req, res) { - res.end(req.params.user.join("/")); - }); - - request(app).get("/user/1/2/3/4").expect(200, "1/2/3/4", done); - }); - - it("should not match zero segments", function (done) { - var app = express(); - - app.get("/user/*user", function (req, res) { - res.end(req.params.user); - }); - - request(app).get("/user").expect(404, done); - }); - }); - - describe.todo(".:name", function () { - it("should denote a format", function (done) { - var app = express(); - var cb = after(2, done); - - app.get("/:name.:format", function (req, res) { - res.end(req.params.name + " as " + req.params.format); - }); - - request(app).get("/foo.json").expect(200, "foo as json", cb); - - request(app).get("/foo").expect(404, cb); - }); - }); - - describe.todo(".:name?", function () { - it("should denote an optional format", function (done) { - var app = express(); - var cb = after(2, done); - - app.get("/:name{.:format}", function (req, res) { - res.end(req.params.name + " as " + (req.params.format || "html")); - }); - - request(app).get("/foo").expect(200, "foo as html", cb); - - request(app).get("/foo.json").expect(200, "foo as json", cb); - }); - }); - - describe.todo("when next() is called", function () { - it("should continue lookup", function (done) { - var app = express(), - calls = []; - - app.get("/foo{/:bar}", function (req, res, next) { - calls.push("/foo/:bar?"); - next(); - }); - - app.get("/bar", function () { - assert(0); - }); - - app.get("/foo", function (req, res, next) { - calls.push("/foo"); - next(); - }); - - app.get("/foo", function (req, res) { - calls.push("/foo 2"); - res.json(calls); - }); - - request(app).get("/foo").expect(200, ["/foo/:bar?", "/foo", "/foo 2"], done); - }); - }); - - describe('when next("route") is called', function () { - it("should jump to next route", function (done) { - var app = express(); - - function fn(req, res, next) { - res.set("X-Hit", "1"); - next("route"); - } - - app.get("/foo", fn, function (req, res) { - res.end("failure"); - }); - - app.get("/foo", function (req, res) { - res.end("success"); - }); - - request(app).get("/foo").expect("X-Hit", "1").expect(200, "success", done); - }); - }); - - describe('when next("router") is called', function () { - it("should jump out of router", function (done) { - var app = express(); - var router = express.Router(); - - function fn(req, res, next) { - res.set("X-Hit", "1"); - next("router"); - } - - router.get("/foo", fn, function (req, res) { - res.end("failure"); - }); - - router.get("/foo", function (req, res) { - res.end("failure"); - }); - - app.use(router); - - app.get("/foo", function (req, res) { - res.end("success"); - }); - - request(app).get("/foo").expect("X-Hit", "1").expect(200, "success", done); - }); - }); - - describe("when next(err) is called", function () { - it.todo("should break out of app.router", function (done) { - var app = express(), - calls = []; - - app.get("/foo{/:bar}", function (req, res, next) { - calls.push("/foo/:bar?"); - next(); - }); - - app.get("/bar", function () { - assert(0); - }); - - app.get("/foo", function (req, res, next) { - calls.push("/foo"); - next(new Error("fail")); - }); - - app.get("/foo", function () { - assert(0); - }); - - app.use(function (err, req, res, next) { - res.json({ - calls: calls, - error: err.message, - }); - }); - - request(app) - .get("/foo") - .expect(200, { calls: ["/foo/:bar?", "/foo"], error: "fail" }, done); - }); - - it("should call handler in same route, if exists", function (done) { - var app = express(); - - function fn1(req, res, next) { - next(new Error("boom!")); - } - - function fn2(req, res, next) { - res.send("foo here"); - } - - function fn3(err, req, res, next) { - res.send("route go " + err.message); - } - - app.get("/foo", fn1, fn2, fn3); - - app.use(function (err, req, res, next) { - res.end("error!"); - }); - - request(app).get("/foo").expect("route go boom!", done); - }); - }); - - // TODO: upgrade to express v5 - describe.todo("promise support", function () { - it("should pass rejected promise value", function (done) { - var app = express(); - var router = new express.Router(); - - router.use(function createError(req, res, next) { - return Promise.reject(new Error("boom!")); - }); - - router.use(function sawError(err, req, res, next) { - res.send("saw " + err.name + ": " + err.message); - }); - - app.use(router); - - request(app).get("/").expect(200, "saw Error: boom!", done); - }); - - it("should pass rejected promise without value", function (done) { - var app = express(); - var router = new express.Router(); - - router.use(function createError(req, res, next) { - return Promise.reject(); - }); - - router.use(function sawError(err, req, res, next) { - res.send("saw " + err.name + ": " + err.message); - }); - - app.use(router); - - request(app).get("/").expect(200, "saw Error: Rejected promise", done); - }); - - it("should ignore resolved promise", function (done) { - var app = express(); - var router = new express.Router(); - - router.use(function createError(req, res, next) { - res.send("saw GET /foo"); - return Promise.resolve("foo"); - }); - - router.use(function () { - done(new Error("Unexpected middleware invoke")); - }); - - app.use(router); - - request(app).get("/foo").expect(200, "saw GET /foo", done); - }); - - describe("error handling", function () { - it("should pass rejected promise value", function (done) { - var app = express(); - var router = new express.Router(); - - router.use(function createError(req, res, next) { - return Promise.reject(new Error("boom!")); - }); - - router.use(function handleError(err, req, res, next) { - return Promise.reject(new Error("caught: " + err.message)); - }); - - router.use(function sawError(err, req, res, next) { - res.send("saw " + err.name + ": " + err.message); - }); - - app.use(router); - - request(app).get("/").expect(200, "saw Error: caught: boom!", done); - }); - - it("should pass rejected promise without value", function (done) { - var app = express(); - var router = new express.Router(); - - router.use(function createError(req, res, next) { - return Promise.reject(); - }); - - router.use(function handleError(err, req, res, next) { - return Promise.reject(new Error("caught: " + err.message)); - }); - - router.use(function sawError(err, req, res, next) { - res.send("saw " + err.name + ": " + err.message); - }); - - app.use(router); - - request(app).get("/").expect(200, "saw Error: caught: Rejected promise", done); - }); - - it("should ignore resolved promise", function (done) { - var app = express(); - var router = new express.Router(); - - router.use(function createError(req, res, next) { - return Promise.reject(new Error("boom!")); - }); - - router.use(function handleError(err, req, res, next) { - res.send("saw " + err.name + ": " + err.message); - return Promise.resolve("foo"); - }); - - router.use(function () { - done(new Error("Unexpected middleware invoke")); - }); - - app.use(router); - - request(app).get("/foo").expect(200, "saw Error: boom!", done); - }); - }); - }); - - it("should allow rewriting of the url", function (done) { - var app = express(); - - app.get("/account/edit", function (req, res, next) { - req.user = { id: 12 }; // faux authenticated user - req.url = "/user/" + req.user.id + "/edit"; - next(); - }); - - app.get("/user/:id/edit", function (req, res) { - res.send("editing user " + req.params.id); - }); - - request(app).get("/account/edit").expect("editing user 12", done); - }); - - it.todo("should run in order added", function (done) { - var app = express(); - var path = []; - - app.get("/*path", function (req, res, next) { - path.push(0); - next(); - }); - - app.get("/user/:id", function (req, res, next) { - path.push(1); - next(); - }); - - app.use(function (req, res, next) { - path.push(2); - next(); - }); - - app.all("/user/:id", function (req, res, next) { - path.push(3); - next(); - }); - - app.get("/*splat", function (req, res, next) { - path.push(4); - next(); - }); - - app.use(function (req, res, next) { - path.push(5); - res.end(path.join(",")); - }); - - request(app).get("/user/1").expect(200, "0,1,2,3,4,5", done); - }); - - it("should be chainable", function () { - var app = express(); - assert.strictEqual( - app.get("/", function () {}), - app, - ); - }); - - it("should should not use disposed router/middleware", function (done) { - // more context: https://github.com/expressjs/express/issues/5743#issuecomment-2277148412 - - var app = express(); - var router = new express.Router(); - - router.use(function (req, res, next) { - res.setHeader("old", "foo"); - next(); - }); - - app.use(function (req, res, next) { - return router.handle(req, res, next); - }); - - app.get("/", function (req, res, next) { - res.send("yee"); - next(); - }); - - request(app) - .get("/") - .expect("old", "foo") - .expect(function (res) { - if (typeof res.headers["new"] !== "undefined") { - throw new Error("`new` header should not be present"); - } - }) - .expect(200, "yee", function (err, res) { - if (err) return done(err); - - router = new express.Router(); - - router.use(function (req, res, next) { - res.setHeader("new", "bar"); - next(); - }); - - request(app) - .get("/") - .expect("new", "bar") - .expect(function (res) { - if (typeof res.headers["old"] !== "undefined") { - throw new Error("`old` header should not be present"); - } - }) - .expect(200, "yee", done); - }); - }); -}); - -function supportsRegexp(source) { - try { - new RegExp(source); - return true; - } catch (e) { - return false; - } -} diff --git a/test/js/third_party/express/express.json.test.ts b/test/js/third_party/express/express.json.test.ts deleted file mode 100644 index 1cc87cf89b..0000000000 --- a/test/js/third_party/express/express.json.test.ts +++ /dev/null @@ -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 + "'"); - }; -} diff --git a/test/js/third_party/express/express.test.ts b/test/js/third_party/express/express.test.ts deleted file mode 100644 index f8017fafdd..0000000000 --- a/test/js/third_party/express/express.test.ts +++ /dev/null @@ -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(); - } -}); diff --git a/test/js/third_party/express/express.text.test.ts b/test/js/third_party/express/express.text.test.ts deleted file mode 100644 index 096ed48f21..0000000000 --- a/test/js/third_party/express/express.text.test.ts +++ /dev/null @@ -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("tobi").expect(200, '"tobi"', 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("tobi").expect(200, '"tobi"', 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("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"] === "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; -} diff --git a/test/js/third_party/express/fixtures/% of dogs.txt b/test/js/third_party/express/fixtures/% of dogs.txt deleted file mode 100644 index 3a4d1342e8..0000000000 --- a/test/js/third_party/express/fixtures/% of dogs.txt +++ /dev/null @@ -1 +0,0 @@ -20% \ No newline at end of file diff --git a/test/js/third_party/express/fixtures/.name b/test/js/third_party/express/fixtures/.name deleted file mode 100644 index fa66f37ff2..0000000000 --- a/test/js/third_party/express/fixtures/.name +++ /dev/null @@ -1 +0,0 @@ -tobi \ No newline at end of file diff --git a/test/js/third_party/express/fixtures/blog/index.html b/test/js/third_party/express/fixtures/blog/index.html deleted file mode 100644 index bcc6b1822f..0000000000 --- a/test/js/third_party/express/fixtures/blog/index.html +++ /dev/null @@ -1 +0,0 @@ -index \ No newline at end of file diff --git a/test/js/third_party/express/fixtures/blog/post/index.tmpl b/test/js/third_party/express/fixtures/blog/post/index.tmpl deleted file mode 100644 index a9a2a3b305..0000000000 --- a/test/js/third_party/express/fixtures/blog/post/index.tmpl +++ /dev/null @@ -1 +0,0 @@ -

blog post

\ No newline at end of file diff --git a/test/js/third_party/express/fixtures/name.txt b/test/js/third_party/express/fixtures/name.txt deleted file mode 100644 index 4599db462a..0000000000 --- a/test/js/third_party/express/fixtures/name.txt +++ /dev/null @@ -1 +0,0 @@ -tobi diff --git a/test/js/third_party/express/fixtures/nums.txt b/test/js/third_party/express/fixtures/nums.txt deleted file mode 100644 index e2e107ac61..0000000000 --- a/test/js/third_party/express/fixtures/nums.txt +++ /dev/null @@ -1 +0,0 @@ -123456789 \ No newline at end of file diff --git a/test/js/third_party/express/fixtures/user.html b/test/js/third_party/express/fixtures/user.html deleted file mode 100644 index f5b9962c5b..0000000000 --- a/test/js/third_party/express/fixtures/user.html +++ /dev/null @@ -1 +0,0 @@ -

{{user.name}}

\ No newline at end of file diff --git a/test/js/third_party/express/package.json b/test/js/third_party/express/package.json deleted file mode 100644 index b2cbcbb2c6..0000000000 --- a/test/js/third_party/express/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "express-test", - "version": "1.0.0", - "dependencies": { - "express": "4.18.2" - } -} diff --git a/test/js/third_party/express/res.json.test.ts b/test/js/third_party/express/res.json.test.ts deleted file mode 100644 index 15e39890e4..0000000000 --- a/test/js/third_party/express/res.json.test.ts +++ /dev/null @@ -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({ "&": "'); - }); - - 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); - }); - }); -}); diff --git a/test/js/third_party/express/res.send.test.ts b/test/js/third_party/express/res.send.test.ts deleted file mode 100644 index 72f2f09d44..0000000000 --- a/test/js/third_party/express/res.send.test.ts +++ /dev/null @@ -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("

hey

"); - }); - - request(app).get("/").expect("Content-Type", "text/html; charset=utf-8").expect(200, "

hey

", 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); - }); - }); - }); -}); diff --git a/test/js/third_party/express/res.sendFile.test.ts b/test/js/third_party/express/res.sendFile.test.ts deleted file mode 100644 index 70091179af..0000000000 --- a/test/js/third_party/express/res.sendFile.test.ts +++ /dev/null @@ -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; -} diff --git a/test/js/third_party/express/support/after.ts b/test/js/third_party/express/support/after.ts deleted file mode 100644 index 1a5779c47c..0000000000 --- a/test/js/third_party/express/support/after.ts +++ /dev/null @@ -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() {} diff --git a/test/js/third_party/express/support/utils.ts b/test/js/third_party/express/support/utils.ts deleted file mode 100644 index 4dd092a84e..0000000000 --- a/test/js/third_party/express/support/utils.ts +++ /dev/null @@ -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; -} diff --git a/test/vendor.json b/test/vendor.json index 05ca430f3a..1865e50950 100644 --- a/test/vendor.json +++ b/test/vendor.json @@ -3,5 +3,12 @@ "package": "elysia", "repository": "https://github.com/elysiajs/elysia", "tag": "1.4.12" + }, + { + "package": "express", + "repository": "https://github.com/expressjs/express", + "tag": "v5.1.0", + "testExtensions": ["js"], + "build": false } ]