Files
pargar/frontend/e2e/websocket.spec.ts
T

57 lines
1.9 KiB
TypeScript

import * as tls from "tls";
import { test, expect } from "@playwright/test";
import { BASE, requireAuth } from "./helpers";
test.describe("WebSocket", () => {
// Test WS via raw TLS to avoid browser HTTP/2 and Node.js http module quirks.
test("WS handshake with valid token succeeds", async () => {
const auth = requireAuth();
const statusCode = await new Promise<number>((resolve) => {
const socket = tls.connect(
{ host: "localhost", port: 443, rejectUnauthorized: false },
() => {
const handshake = [
"GET /api/ws HTTP/1.1",
"Host: localhost",
"Upgrade: websocket",
"Connection: Upgrade",
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==",
"Sec-WebSocket-Version: 13",
`Authorization: Bearer ${auth.accessToken!}`,
"",
"",
].join("\r\n");
socket.write(handshake);
},
);
let buf = "";
socket.on("data", (chunk) => {
buf += chunk.toString();
const firstLine = buf.split("\r\n")[0] ?? "";
const m = firstLine.match(/HTTP\/1\.\d\s+(\d+)/);
if (m) {
socket.destroy();
resolve(parseInt(m[1], 10));
}
});
socket.on("error", () => resolve(0));
setTimeout(() => { socket.destroy(); resolve(0); }, 8000);
});
expect(statusCode, `WS upgrade returned ${statusCode}`).toBe(101);
});
test("WS handshake without token is rejected", async ({ page }) => {
const result = await page.evaluate((wsUrl) => {
return new Promise<{ code: number }>((resolve) => {
const ws = new WebSocket(wsUrl);
ws.onclose = (e) => resolve({ code: e.code });
setTimeout(() => resolve({ code: -1 }), 6000);
});
}, BASE.replace("https", "wss") + "/api/ws");
expect(result.code).not.toBe(1000);
});
});