diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/bundler/bun-build-api.test.ts | 23 | ||||
-rw-r--r-- | test/js/bun/http/serve.test.ts | 32 | ||||
-rw-r--r-- | test/js/bun/plugin/module-plugins.ts | 38 | ||||
-rw-r--r-- | test/js/bun/plugin/plugins.test.ts | 78 | ||||
-rw-r--r-- | test/js/bun/resolve/import-meta.test.js | 2 | ||||
-rw-r--r-- | test/js/bun/resolve/png/test-png-import.test.js | 4 | ||||
-rw-r--r-- | test/js/bun/resolve/resolve.test.ts | 143 | ||||
-rw-r--r-- | test/js/node/net/node-net.test.ts | 7 | ||||
-rw-r--r-- | test/js/node/process/process.test.js | 6 | ||||
-rw-r--r-- | test/js/web/fetch/fetch.test.ts | 102 |
10 files changed, 425 insertions, 10 deletions
diff --git a/test/bundler/bun-build-api.test.ts b/test/bundler/bun-build-api.test.ts index 3c2308d94..d1f1a10b8 100644 --- a/test/bundler/bun-build-api.test.ts +++ b/test/bundler/bun-build-api.test.ts @@ -290,4 +290,27 @@ describe("Bun.build", () => { // depends on the ws package in the test/node_modules. expect(content).toContain("var websocket = __toESM(require_websocket(), 1);"); }); + + test("module() throws error", async () => { + expect(() => + Bun.build({ + entrypoints: [join(import.meta.dir, "./fixtures/trivial/bundle-ws.ts")], + plugins: [ + { + name: "test", + setup: b => { + b.module("ad", () => { + return { + exports: { + hello: "world", + }, + loader: "object", + }; + }); + }, + }, + ], + }), + ).toThrow(); + }); }); diff --git a/test/js/bun/http/serve.test.ts b/test/js/bun/http/serve.test.ts index be271cf33..67b7614b2 100644 --- a/test/js/bun/http/serve.test.ts +++ b/test/js/bun/http/serve.test.ts @@ -1237,14 +1237,42 @@ it("server.requestIP (v6)", async () => { fetch(req, server) { return Response.json(server.requestIP(req)); }, - hostname: "0000:0000:0000:0000:0000:0000:0000:0001", + hostname: "::1", }); const response = await fetch(`http://localhost:${server.port}`).then(x => x.json()); expect(response).toEqual({ - address: "0000:0000:0000:0000:0000:0000:0000:0001", + address: "::1", family: "IPv6", port: expect.any(Number), }); server.stop(true); }); + +it("server.requestIP (unix)", async () => { + const unix = "/tmp/bun-serve.sock"; + const server = Bun.serve({ + unix, + fetch(req, server) { + return Response.json(server.requestIP(req)); + }, + }); + const requestText = `GET / HTTP/1.1\r\nHost: localhost\r\n\r\n`; + const received: Buffer[] = []; + const { resolve, promise } = Promise.withResolvers<void>(); + const connection = await Bun.connect({ + unix, + socket: { + data(socket, data) { + received.push(data); + resolve(); + }, + }, + }); + connection.write(requestText); + connection.flush(); + await promise; + expect(Buffer.concat(received).toString()).toEndWith("\r\n\r\nnull"); + connection.end(); + server.stop(true); +}); diff --git a/test/js/bun/plugin/module-plugins.ts b/test/js/bun/plugin/module-plugins.ts new file mode 100644 index 000000000..d6034c5df --- /dev/null +++ b/test/js/bun/plugin/module-plugins.ts @@ -0,0 +1,38 @@ +import { plugin } from "bun"; +plugin({ + name: "i am virtual!", + setup(builder) { + builder.module("my-virtual-module-async", async () => { + // check + await Bun.sleep(1); + return { + exports: { + hello: "world", + }, + loader: "object", + }; + }); + + builder.module("my-virtual-module-sync", () => { + return { + exports: { + hello: "world", + }, + loader: "object", + }; + }); + + builder.onLoad({ filter: /.*/, namespace: "rejected-promise" }, async ({ path }) => { + throw new Error("Rejected Promise"); + }); + + builder.onResolve({ filter: /.*/, namespace: "rejected-promise2" }, ({ path }) => ({ + namespace: "rejected-promise2", + path, + })); + + builder.onLoad({ filter: /.*/, namespace: "rejected-promise2" }, ({ path }) => { + return Promise.reject(new Error("Rejected Promise")); + }); + }, +}); diff --git a/test/js/bun/plugin/plugins.test.ts b/test/js/bun/plugin/plugins.test.ts index c2827f600..2d3cfa1fa 100644 --- a/test/js/bun/plugin/plugins.test.ts +++ b/test/js/bun/plugin/plugins.test.ts @@ -185,6 +185,7 @@ plugin({ // This is to test that it works when imported from a separate file import "../../third_party/svelte"; +import "./module-plugins"; describe("require", () => { it("SSRs `<h1>Hello world!</h1>` with Svelte", () => { @@ -210,6 +211,83 @@ describe("require", () => { }); }); +describe("module", () => { + it("throws with require()", () => { + expect(() => require("my-virtual-module-async")).toThrow(); + }); + + it("async module works with async import", async () => { + // @ts-expect-error + const { hello } = await import("my-virtual-module-async"); + + expect(hello).toBe("world"); + delete require.cache["my-virtual-module-async"]; + }); + + it("sync module module works with require()", async () => { + const { hello } = require("my-virtual-module-sync"); + + expect(hello).toBe("world"); + delete require.cache["my-virtual-module-sync"]; + }); + + it("sync module module works with require.resolve()", async () => { + expect(require.resolve("my-virtual-module-sync")).toBe("my-virtual-module-sync"); + delete require.cache["my-virtual-module-sync"]; + }); + + it("sync module module works with import", async () => { + // @ts-expect-error + const { hello } = await import("my-virtual-module-sync"); + + expect(hello).toBe("world"); + delete require.cache["my-virtual-module-sync"]; + }); + + it("modules are overridable", async () => { + // @ts-expect-error + let { hello, there } = await import("my-virtual-module-sync"); + expect(there).toBeUndefined(); + expect(hello).toBe("world"); + + Bun.plugin({ + setup(builder) { + builder.module("my-virtual-module-sync", () => ({ + exports: { + there: true, + }, + loader: "object", + })); + }, + }); + + { + const { there, hello } = require("my-virtual-module-sync"); + expect(there).toBe(true); + expect(hello).toBeUndefined(); + } + + Bun.plugin({ + setup(builder) { + builder.module("my-virtual-module-sync", () => ({ + exports: { + yo: true, + }, + loader: "object", + })); + }, + }); + + { + // @ts-expect-error + const { there, hello, yo } = await import("my-virtual-module-sync"); + expect(yo).toBe(true); + expect(hello).toBeUndefined(); + expect(there).toBeUndefined(); + } + }); +}); + describe("dynamic import", () => { it("SSRs `<h1>Hello world!</h1>` with Svelte", async () => { const { default: App }: any = await import("./hello.svelte"); diff --git a/test/js/bun/resolve/import-meta.test.js b/test/js/bun/resolve/import-meta.test.js index a940d0c87..e0e3bb11e 100644 --- a/test/js/bun/resolve/import-meta.test.js +++ b/test/js/bun/resolve/import-meta.test.js @@ -102,7 +102,7 @@ it("Module.createRequire(file://url).resolve(file://url)", () => { const createdRequire = Module.createRequire(import.meta.url); const result1 = createdRequire.resolve("./require-json.json"); - const result2 = createdRequire.resolve("file://./require-json.json"); + const result2 = createdRequire.resolve(`file://${expected}`); expect(result1).toBe(expected); expect(result2).toBe(expected); }); diff --git a/test/js/bun/resolve/png/test-png-import.test.js b/test/js/bun/resolve/png/test-png-import.test.js index f4a809e7a..ca2d0b9ce 100644 --- a/test/js/bun/resolve/png/test-png-import.test.js +++ b/test/js/bun/resolve/png/test-png-import.test.js @@ -1,7 +1,7 @@ import { expect, test } from "bun:test"; import { resolve } from "path"; -// import MyPNG from "./test-png.png"; +import MyPNG from "./test-png.png"; -test.todo("png import", () => { +test("png import", () => { expect(MyPNG).toBe(resolve(__dirname, "./test-png.png")); }); diff --git a/test/js/bun/resolve/resolve.test.ts b/test/js/bun/resolve/resolve.test.ts index a9272fb3f..217d3dc81 100644 --- a/test/js/bun/resolve/resolve.test.ts +++ b/test/js/bun/resolve/resolve.test.ts @@ -92,7 +92,6 @@ it("file url in import resolves", async () => { }); writeFileSync(`${dir}/test.js`, `import {foo} from 'file://${dir}/index.js';\nconsole.log(foo);`); - console.log("dir", dir); const { exitCode, stdout } = Bun.spawnSync({ cmd: [bunExe(), `${dir}/test.js`], env: bunEnv, @@ -102,13 +101,97 @@ it("file url in import resolves", async () => { expect(stdout.toString("utf8")).toBe("1\n"); }); +it("invalid file url in import throws error", async () => { + const dir = tempDirWithFiles("fileurl", {}); + writeFileSync(`${dir}/test.js`, `import {foo} from 'file://\0invalid url';\nconsole.log(foo);`); + + const { exitCode, stdout, stderr } = Bun.spawnSync({ + cmd: [bunExe(), `${dir}/test.js`], + env: bunEnv, + cwd: import.meta.dir, + }); + expect(exitCode).not.toBe(0); + expect(stderr.toString("utf8")).toContain("file://\0invalid url"); +}); + it("file url in await import resolves", async () => { const dir = tempDirWithFiles("fileurl", { "index.js": "export const foo = 1;", }); writeFileSync(`${dir}/test.js`, `const {foo} = await import('file://${dir}/index.js');\nconsole.log(foo);`); - console.log("dir", dir); + const { exitCode, stdout } = Bun.spawnSync({ + cmd: [bunExe(), `${dir}/test.js`], + env: bunEnv, + cwd: import.meta.dir, + }); + expect(exitCode).toBe(0); + expect(stdout.toString("utf8")).toBe("1\n"); +}); + +it("file url with special characters in await import resolves", async () => { + const filename = "🅱️ndex.js"; + const dir = tempDirWithFiles("file url", { + [filename]: "export const foo = 1;", + }); + writeFileSync( + `${dir}/test.js`, + `const {foo} = await import('file://${dir.replace(/ /g, "%20")}/${encodeURIComponent( + filename, + )}');\nconsole.log(foo);`, + ); + + const { exitCode, stdout } = Bun.spawnSync({ + cmd: [bunExe(), `${dir}/test.js`], + env: bunEnv, + cwd: import.meta.dir, + }); + expect(exitCode).toBe(0); + expect(stdout.toString("utf8")).toBe("1\n"); +}); + +it("file url with special characters not encoded in await import resolves", async () => { + const filename = "🅱️ndex.js"; + const dir = tempDirWithFiles("file url", { + [filename]: "export const foo = 1;", + }); + writeFileSync(`${dir}/test.js`, `const {foo} = await import('file://${dir}/${filename}');\nconsole.log(foo);`); + + const { exitCode, stdout } = Bun.spawnSync({ + cmd: [bunExe(), `${dir}/test.js`], + env: bunEnv, + cwd: import.meta.dir, + }); + expect(exitCode).toBe(0); + expect(stdout.toString("utf8")).toBe("1\n"); +}); + +it("file url with special characters in import statement resolves", async () => { + const filename = "🅱️ndex.js"; + const dir = tempDirWithFiles("file url", { + [filename]: "export const foo = 1;", + }); + writeFileSync( + `${dir}/test.js`, + `import {foo} from 'file://${dir.replace(/ /g, "%20")}/${encodeURIComponent(filename)}';\nconsole.log(foo);`, + ); + + const { exitCode, stdout } = Bun.spawnSync({ + cmd: [bunExe(), `${dir}/test.js`], + env: bunEnv, + cwd: import.meta.dir, + }); + expect(exitCode).toBe(0); + expect(stdout.toString("utf8")).toBe("1\n"); +}); + +it("file url with special characters not encoded in import statement resolves", async () => { + const filename = "🅱️ndex.js"; + const dir = tempDirWithFiles("file url", { + [filename]: "export const foo = 1;", + }); + writeFileSync(`${dir}/test.js`, `import {foo} from 'file://${dir}/${filename}';\nconsole.log(foo);`); + const { exitCode, stdout } = Bun.spawnSync({ cmd: [bunExe(), `${dir}/test.js`], env: bunEnv, @@ -124,7 +207,6 @@ it("file url in require resolves", async () => { }); writeFileSync(`${dir}/test.js`, `const {foo} = require('file://${dir}/index.js');\nconsole.log(foo);`); - console.log("dir", dir); const { exitCode, stdout } = Bun.spawnSync({ cmd: [bunExe(), `${dir}/test.js`], env: bunEnv, @@ -134,6 +216,61 @@ it("file url in require resolves", async () => { expect(stdout.toString("utf8")).toBe("1\n"); }); +it("file url with special characters in require resolves", async () => { + const filename = "🅱️ndex.js"; + const dir = tempDirWithFiles("file url", { + [filename]: "export const foo = 1;", + }); + writeFileSync( + `${dir}/test.js`, + `const {foo} = require('file://${dir.replace(/ /g, "%20")}/${encodeURIComponent(filename)}');\nconsole.log(foo);`, + ); + + const { exitCode, stdout } = Bun.spawnSync({ + cmd: [bunExe(), `${dir}/test.js`], + env: bunEnv, + cwd: import.meta.dir, + }); + expect(exitCode).toBe(0); + expect(stdout.toString("utf8")).toBe("1\n"); +}); + +it("file url in require.resolve resolves", async () => { + const dir = tempDirWithFiles("fileurl", { + "index.js": "export const foo = 1;", + }); + writeFileSync(`${dir}/test.js`, `const to = require.resolve('file://${dir}/index.js');\nconsole.log(to);`); + + const { exitCode, stdout } = Bun.spawnSync({ + cmd: [bunExe(), `${dir}/test.js`], + env: bunEnv, + cwd: import.meta.dir, + }); + expect(exitCode).toBe(0); + expect(stdout.toString("utf8")).toBe(`${dir}/index.js\n`); +}); + +it("file url with special characters in require resolves", async () => { + const filename = "🅱️ndex.js"; + const dir = tempDirWithFiles("file url", { + [filename]: "export const foo = 1;", + }); + writeFileSync( + `${dir}/test.js`, + `const to = require.resolve('file://${dir.replace(/ /g, "%20")}/${encodeURIComponent( + filename, + )}');\nconsole.log(to);`, + ); + + const { exitCode, stdout } = Bun.spawnSync({ + cmd: [bunExe(), `${dir}/test.js`], + env: bunEnv, + cwd: import.meta.dir, + }); + expect(exitCode).toBe(0); + expect(stdout.toString("utf8")).toBe(`${dir}/${filename}\n`); +}); + it("import long string should not segfault", async () => { try { await import("a".repeat(10000)); diff --git a/test/js/node/net/node-net.test.ts b/test/js/node/net/node-net.test.ts index 109391af5..a16ac6db1 100644 --- a/test/js/node/net/node-net.test.ts +++ b/test/js/node/net/node-net.test.ts @@ -411,3 +411,10 @@ it("should handle connection error (unix)", done => { done(); }); }); + +it("Socket has a prototype", () => { + function Connection() {} + function Connection2() {} + require("util").inherits(Connection, Socket); + require("util").inherits(Connection2, require("tls").TLSSocket); +}); diff --git a/test/js/node/process/process.test.js b/test/js/node/process/process.test.js index a4a8862a2..4fb678dce 100644 --- a/test/js/node/process/process.test.js +++ b/test/js/node/process/process.test.js @@ -407,7 +407,8 @@ describe("signal", () => { stdout: "pipe", }); const prom = child.exited; - process.kill(child.pid, "SIGTERM"); + const ret = process.kill(child.pid, "SIGTERM"); + expect(ret).toBe(true); await prom; expect(child.signalCode).toBe("SIGTERM"); }); @@ -418,7 +419,8 @@ describe("signal", () => { stdout: "pipe", }); const prom = child.exited; - process.kill(child.pid, 9); + const ret = process.kill(child.pid, 9); + expect(ret).toBe(true); await prom; expect(child.signalCode).toBe("SIGKILL"); }); diff --git a/test/js/web/fetch/fetch.test.ts b/test/js/web/fetch/fetch.test.ts index 85e2296cd..8c5e27f88 100644 --- a/test/js/web/fetch/fetch.test.ts +++ b/test/js/web/fetch/fetch.test.ts @@ -1241,6 +1241,16 @@ describe("Request", () => { expect(req.signal.aborted).toBe(true); }); + it("copies method (#6144)", () => { + const request = new Request("http://localhost:1337/test", { + method: "POST", + }); + const new_req = new Request(request, { + body: JSON.stringify({ message: "Hello world" }), + }); + expect(new_req.method).toBe("POST"); + }); + it("cloned signal", async () => { gc(); const controller = new AbortController(); @@ -1692,3 +1702,95 @@ it("should throw RedirectURLTooLong when location is too long", async () => { expect(err.code).toStrictEqual("RedirectURLTooLong"); server.stop(true); }); + +it("304 not modified with missing content-length does not cause a request timeout", async () => { + const server = await Bun.listen({ + socket: { + open(socket) { + socket.write("HTTP/1.1 304 Not Modified\r\n\r\n"); + socket.flush(); + setTimeout(() => { + socket.end(); + }, 9999).unref(); + }, + data() {}, + close() {}, + }, + port: 0, + hostname: "localhost", + }); + + const response = await fetch(`http://${server.hostname}:${server.port}/`); + expect(response.status).toBe(304); + expect(await response.arrayBuffer()).toHaveLength(0); + server.stop(true); +}); + +it("304 not modified with missing content-length and connection close does not cause a request timeout", async () => { + const server = await Bun.listen({ + socket: { + open(socket) { + socket.write("HTTP/1.1 304 Not Modified\r\nConnection: close\r\n\r\n"); + socket.flush(); + setTimeout(() => { + socket.end(); + }, 9999).unref(); + }, + data() {}, + close() {}, + }, + port: 0, + hostname: "localhost", + }); + + const response = await fetch(`http://${server.hostname}:${server.port}/`); + expect(response.status).toBe(304); + expect(await response.arrayBuffer()).toHaveLength(0); + server.stop(true); +}); + +it("304 not modified with content-length 0 and connection close does not cause a request timeout", async () => { + const server = await Bun.listen({ + socket: { + open(socket) { + socket.write("HTTP/1.1 304 Not Modified\r\nConnection: close\r\nContent-Length: 0\r\n\r\n"); + socket.flush(); + setTimeout(() => { + socket.end(); + }, 9999).unref(); + }, + data() {}, + close() {}, + }, + port: 0, + hostname: "localhost", + }); + + const response = await fetch(`http://${server.hostname}:${server.port}/`); + expect(response.status).toBe(304); + expect(await response.arrayBuffer()).toHaveLength(0); + server.stop(true); +}); + +it("304 not modified with 0 content-length does not cause a request timeout", async () => { + const server = await Bun.listen({ + socket: { + open(socket) { + socket.write("HTTP/1.1 304 Not Modified\r\nContent-Length: 0\r\n\r\n"); + socket.flush(); + setTimeout(() => { + socket.end(); + }, 9999).unref(); + }, + data() {}, + close() {}, + }, + port: 0, + hostname: "localhost", + }); + + const response = await fetch(`http://${server.hostname}:${server.port}/`); + expect(response.status).toBe(304); + expect(await response.arrayBuffer()).toHaveLength(0); + server.stop(true); +}); |