import { describe, it, expect } from "bun:test"; import { unsafe, spawn, readableStreamToText } from "bun"; import { bunExe } from "bunExe"; import { gc } from "./gc"; import { bunEnv } from "bunEnv"; const TEST_WEBSOCKET_HOST = process.env.TEST_WEBSOCKET_HOST || "wss://ws.postman-echo.com/raw"; describe("WebSocket", () => { it("should connect", async () => { const ws = new WebSocket(TEST_WEBSOCKET_HOST); await new Promise((resolve, reject) => { ws.onopen = resolve; ws.onerror = reject; }); var closed = new Promise((resolve, reject) => { ws.onclose = resolve; }); ws.close(); await closed; }); it("should connect over https", async () => { const ws = new WebSocket(TEST_WEBSOCKET_HOST.replaceAll("wss:", "https:")); await new Promise((resolve, reject) => { ws.onopen = resolve; ws.onerror = reject; }); var closed = new Promise((resolve, reject) => { ws.onclose = resolve; }); ws.close(); await closed; }); it("supports headers", done => { const server = Bun.serve({ port: 8024, fetch(req, server) { expect(req.headers.get("X-Hello")).toBe("World"); expect(req.headers.get("content-type")).toBe("lolwut"); server.stop(); done(); return new Response(); }, websocket: { open(ws) { ws.close(); }, }, }); const ws = new WebSocket(`ws://${server.hostname}:${server.port}`, { headers: { "X-Hello": "World", "content-type": "lolwut", }, }); }); it("should connect over http", done => { const server = Bun.serve({ port: 8025, fetch(req, server) { server.stop(); done(); return new Response(); }, websocket: { open(ws) { ws.close(); }, }, }); const ws = new WebSocket(`http://${server.hostname}:${server.port}`, {}); }); it("should send and receive messages", async () => { const ws = new WebSocket(TEST_WEBSOCKET_HOST); await new Promise((resolve, reject) => { ws.onopen = resolve; ws.onerror = reject; ws.onclose = () => { reject("WebSocket closed"); }; }); const count = 10; // 10 messages in burst var promise = new Promise((resolve, reject) => { var remain = count; ws.onmessage = event => { gc(true); expect(event.data).toBe("Hello World!"); remain--; if (remain <= 0) { ws.onmessage = () => {}; resolve(); } }; ws.onerror = reject; }); for (let i = 0; i < count; i++) { ws.send("Hello World!"); gc(true); } await promise; var echo = 0; // 10 messages one at a time function waitForEcho() { return new Promise((resolve, reject) => { gc(true); const msg = `Hello World! ${echo++}`; ws.onmessage = event => { expect(event.data).toBe(msg); resolve(); }; ws.onerror = reject; ws.onclose = reject; ws.send(msg); gc(true); }); } gc(true); for (let i = 0; i < count; i++) await waitForEcho(); ws.onclose = () => {}; ws.onerror = () => {}; ws.close(); gc(true); }); }); describe("websocket in subprocess", () => { var port = 8765; it("should exit", async () => { let messageReceived = false; const server = Bun.serve({ port: port++, fetch(req, server) { if (server.upgrade(req)) { return; } return new Response("http response"); }, websocket: { open(ws) { ws.send("hello websocket"); }, message(ws) { messageReceived = true; ws.close(); }, close(ws) {}, }, }); const subprocess = Bun.spawn({ cmd: [bunExe(), import.meta.dir + "/websocket-subprocess.ts", `http://${server.hostname}:${server.port}`], stderr: "pipe", stdin: "pipe", stdout: "pipe", env: bunEnv, }); expect(await subprocess.exited).toBe(0); expect(messageReceived).toBe(true); server.stop(true); }); it("should exit after killed", async () => { const subprocess = Bun.spawn({ cmd: [bunExe(), import.meta.dir + "/websocket-subprocess.ts", TEST_WEBSOCKET_HOST], stderr: "pipe", stdin: "pipe", stdout: "pipe", env: bunEnv, }); subprocess.kill(); expect(await subprocess.exited).toBe("SIGHUP"); }); it("should exit with invalid url", async () => { const subprocess = Bun.spawn({ cmd: [bunExe(), import.meta.dir + "/websocket-subprocess.ts", "invalid url"], stderr: "pipe", stdin: "pipe", stdout: "pipe", env: bunEnv, }); expect(await subprocess.exited).toBe(1); }); it("should exit after timeout", async () => { let messageReceived = false; let start = 0; const server = Bun.serve({ port: port++, fetch(req, server) { if (server.upgrade(req)) { return; } return new Response("http response"); }, websocket: { open(ws) { start = performance.now(); ws.send("timeout"); }, message(ws, message) { messageReceived = true; expect(performance.now() - start >= 300).toBe(true); ws.close(); }, close(ws) {}, }, }); const subprocess = Bun.spawn({ cmd: [bunExe(), import.meta.dir + "/websocket-subprocess.ts", `http://${server.hostname}:${server.port}`], stderr: "pipe", stdin: "pipe", stdout: "pipe", env: bunEnv, }); expect(await subprocess.exited).toBe(0); expect(messageReceived).toBe(true); server.stop(true); }); it("should exit after server stop and 0 messages", async () => { const server = Bun.serve({ port: port++, fetch(req, server) { if (server.upgrade(req)) { return; } return new Response("http response"); }, websocket: { open(ws) {}, message(ws, message) {}, close(ws) {}, }, }); const subprocess = Bun.spawn({ cmd: [bunExe(), import.meta.dir + "/websocket-subprocess.ts", `http://${server.hostname}:${server.port}`], stderr: "pipe", stdin: "pipe", stdout: "pipe", env: bunEnv, }); server.stop(true); expect(await subprocess.exited).toBe(0); }); }); >feat/create-astro-ui Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/scripts/stats (unfollow)
AgeCommit message (Expand)AuthorFilesLines
2023-08-22Fix turbolink changesetGravatar bluwy 5-5/+1
2023-08-22chore: update lock fileGravatar Emanuele Stoppa 1-9/+151
2023-08-22chore: update bug report to use the `astro info` command (#8175)Gravatar Emanuele Stoppa 1-25/+5
2023-08-22Remove turbolinks integration (#8186)Gravatar Bjorn Lu 8-317/+0
2023-08-22[ci] formatGravatar ematipico 2-35/+42
2023-08-22add: config error if `outDir` is inside `publicDir` (#8152)Gravatar André Alves 3-0/+13
2023-08-22Deprecate drafts feature (#8099)Gravatar Bjorn Lu 7-7/+41
2023-08-21Use more permissive type for `defineCollection` schema option (#8163)Gravatar Chris Swithinbank 2-5/+7
2023-08-21feat: style scoped hash is lowercase (#8180)Gravatar Emanuele Stoppa 4-7/+48
2023-08-21RC Release candidate (#8179)Gravatar Matthew Phillips 2-1/+32
2023-08-21Set Markdoc integration version to a minor (#8177)Gravatar Matthew Phillips 1-1/+1
2023-08-21fix(@astrojs/node): handler should work with `express` (#8176)Gravatar Emanuele Stoppa 7-16/+221
2023-08-21[docs] deprecate build.split and build.excludeMiddleware in config ref (#8158)Gravatar Sarah Rainsberger 1-25/+7
2023-08-21chore: lock fileGravatar Emanuele Stoppa 1-0/+4
2023-08-21[ci] formatGravatar natemoo-re 4-9/+15
2023-08-21Stringify shouldn't throw on user object during rendering (#8127)Gravatar Nate Moore 9-46/+115
2023-08-21[ci] formatGravatar natemoo-re 1-1/+4
2023-08-21fix(dev): open to base path (#8123)Gravatar Nate Moore 2-1/+8
2023-08-21chore(gitpod): resolve potential globbing and word splitting issue (#8124)Gravatar Ben Elan 1-1/+1
2023-08-21fix(#6965): fix build stats (#8122)Gravatar Nate Moore 2-1/+8
2023-08-21only update our own history entires during back navigation through view trans...Gravatar Martin Trapp 2-3/+11
2023-08-21fix: reinsert attribute to specify direction of ViewTransition (forward / bac...Gravatar Martin Trapp 2-7/+12
2023-08-21Remove deprecated APIs (#8170)Gravatar Bjorn Lu 4-107/+5
2023-08-21Remove pre-shiki v0.14 theme names (#8169)Gravatar Bjorn Lu 6-80/+14
2023-08-21[docs] JSX framework integration READMEs (#8151)Gravatar Sarah Rainsberger 3-0/+104
2023-08-21fix(assets): Add missing type for imageConfig export (#8171)Gravatar Erika 2-1/+7
2023-08-21Deprecate simple objects from endpoints (#8132)Gravatar Bjorn Lu 20-201/+243
2023-08-18[docs] update scopedStyleStragegy default and description (#8148)Gravatar Sarah Rainsberger 1-2/+2
2023-08-18[ci] release (#8145)astro@2.10.12@astrojs/react@2.3.2@astrojs/node@5.3.5Gravatar Houston (Bot) 46-92/+98
2023-08-18Fix missing package file regression (#8149)Gravatar Matthew Phillips 2-1/+7
2023-08-18fix(node): delegate preview's not found and error handling to core/app (#8141)Gravatar Arsh 2-9/+6
2023-08-18Replace `class:list` implementation with `clsx` (#8142)Gravatar Nate Moore 12-68/+133
2023-08-18[ci] formatGravatar matthewp 1-1/+4
2023-08-18fix(data collections): normalize file paths for DataEntry.id (#8144)Gravatar Arsh 2-1/+6
2023-08-18[ci] release (beta) (#8140)astro@3.0.0-beta.4Gravatar Houston (Bot) 41-65/+72
2023-08-18[error messages] Update image errors-data.ts (#8126)Gravatar Sarah Rainsberger 1-12/+12
2023-08-18fix(polyfills): Use object shape for Stackblitz polyfill listGravatar Princesseuh 1-2/+2
2023-08-18fix: polyfill File using undici instead of node:buffer (#8139)Gravatar Erika 2-8/+9
2023-08-18[ci] release (beta) (#8073)create-astro@4.0.0-beta.1astro@3.0.0-beta.3@astrojs/vercel@4.0.0-beta.3@astrojs/telemetry@3.0.0-beta.2@astrojs/svelte@4.0.0-beta.1@astrojs/solid-js@3.0.0-beta.2@astrojs/react@3.0.0-beta.3@astrojs/mdx@1.0.0-beta.1@astrojs/cloudflare@7.0.0-beta.2Gravatar Houston (Bot) 63-117/+389
2023-08-18[ci] release (#8138)astro@2.10.11@astrojs/react@2.3.1Gravatar Houston (Bot) 44-80/+82
2023-08-18[ci] formatGravatar natemoo-re 1-1/+1
2023-08-18Fix 404 response leading to an infinite loop when there is no 404 page (#8136)Gravatar André Alves 2-1/+10
2023-08-18fix(react): add missing export (#8137)Gravatar Nate Moore 2-1/+7
2023-08-18[ci] release (#8096)create-astro@3.2.2astro@2.10.10@astrojs/vercel@3.8.2@astrojs/svelte@3.1.1@astrojs/solid-js@2.2.1@astrojs/react@2.3.0Gravatar Houston (Bot) 63-197/+186
2023-08-18changeset(next): inlineStylesheets default switch is major (#8133)Gravatar Arsh 1-1/+1
2023-08-18feat: add polyfills for stackblitz (#8130)Gravatar Erika 7-6/+86