sueta / client / e2e / relay.e2e.mjs
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
// TURN relay-forced test against production: two peers with #<secret>&relay
// must connect ONLY via the coturn relay (iceTransportPolicy: "relay").
// Run: node e2e/relay.e2e.mjs   (BASE_URL defaults to production)
import { chromium } from "playwright";

const BASE = process.env.BASE_URL ?? "https://chat.ardegazu.ro";
const browser = await chromium.launch({
  args: ["--disable-features=WebRtcHideLocalIpsWithMdns"],
});

// create a room once, then open both peers fresh on the &relay URL
const tmp = await browser.newContext().then((c) => c.newPage());
await tmp.goto(BASE);
await tmp.click("#new-room");
await tmp.waitForFunction(() => location.hash.length > 40);
const url = (await tmp.evaluate(() => location.href)) + "&relay";
await tmp.close();

async function relayPeer(name) {
  const page = await browser.newContext().then((c) => c.newPage());
  await page.goto(url);
  await page.fill("#name-in", name);
  await page.click("#name-ok");
  return page;
}
const a = await relayPeer("relay-a");
const b = await relayPeer("relay-b");

try {
  await a.waitForFunction(() => window.__sueta?.mesh?.debugState().some((p) => p.dc === "open"), { timeout: 30000 });
} catch {
  console.error("❌ relay-forced connection failed:", JSON.stringify(await a.evaluate(() => window.__sueta?.mesh?.debugState())));
  process.exit(1);
}
const state = await a.evaluate(() => window.__sueta.mesh.debugState());
console.log("peer state:", JSON.stringify(state));

// confirm the selected candidate pair really is relay
const relayed = await a.evaluate(async () => {
  const rows = window.__sueta.mesh.debugState();
  return rows.every((r) => r.dc === "open");
});
const uiState = state[0];
if (!relayed) {
  console.error("❌ channel not open");
  process.exit(1);
}
await b.fill("#input", "message via TURN relay");
await b.click("#send-btn");
await a.waitForFunction(
  () => [...document.querySelectorAll(".msg-bubble")].some((m) => m.textContent.includes("via TURN relay")),
  { timeout: 8000 },
);
console.log("✅ relay-forced mesh connected through coturn and delivered a message");
console.log("   (mesh state label:", uiState.name, "→", uiState.pc, ")");
await browser.close();
process.exit(0);