Scaffold playwright

This commit is contained in:
Jon Staab
2026-06-01 14:50:13 -07:00
parent 1dd0270f4f
commit 91145c38fb
11 changed files with 273 additions and 0 deletions
+29
View File
@@ -0,0 +1,29 @@
import type {SignedEvent} from "@welshman/util"
import type {RelayMockConfig} from "../../src/lib/test/relayMocks"
import relay1Events from "./fixtures/relay1.json"
// Fake relay urls used by tests. Each maps to a json fixture under ./fixtures/ and an entry in
// EVENTS_BY_RELAY below. To add a relay: drop a `<name>.json` file in ./fixtures/, import it, add a
// url here, and wire it into EVENTS_BY_RELAY.
export const FIXTURE_RELAYS = {
relay1: "wss://relay1.test/",
} as const
// The events each fake relay serves. The json files hold static, pre-signed events: schnorr
// signatures are non-deterministic, so events are signed once and committed verbatim (they pass
// verifyEvent, which netContext.isEventValid enforces). Regenerate with @welshman/signer:
// await Nip01Signer.fromSecret(secret).sign(makeEvent(kind, {content, created_at}))
const EVENTS_BY_RELAY: Record<string, SignedEvent[]> = {
[FIXTURE_RELAYS.relay1]: relay1Events as SignedEvent[],
}
// Build a RelayMockConfig populating the given fixture relays (all of them when none are passed).
// Any relay not included returns nothing, keeping tests offline.
export const relayFixtures = (...urls: string[]): RelayMockConfig => {
const selected = urls.length > 0 ? urls : Object.keys(EVENTS_BY_RELAY)
return {
relays: Object.fromEntries(selected.map(url => [url, EVENTS_BY_RELAY[url] ?? []])),
}
}
+29
View File
@@ -0,0 +1,29 @@
[
{
"kind": 0,
"content": "{\"name\":\"Alice\"}",
"tags": [],
"created_at": 1700000000,
"pubkey": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
"id": "9b3d138641b38364945b20d800268006c2cb7d974bb4b1d63a9f90f5ab974b90",
"sig": "de6b86274e7bcf6c02aa881ada1feee9e01ba320691711d4975916b3cd231ab43cf469a47c5db99503ed72707d5db85fede1ad3763c4fbd7c998d04f00eda6bc"
},
{
"kind": 1,
"content": "hello from the fixture relay",
"tags": [],
"created_at": 1700000000,
"pubkey": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
"id": "b9874875bfa8d830c5c9ef3673104360cf21b94848a311febfaf52f0a652b1a9",
"sig": "85df94a2e9884ac3d280145492d5191cde2948d49a824c443a1f5d2143633eff1e1789fa7e8843b6efc3dd2dc0d7e33322edb628125d8e35de8ddca1d06ca970"
},
{
"kind": 1,
"content": "reply from bob",
"tags": [],
"created_at": 1700000001,
"pubkey": "c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5",
"id": "171dcbdd63d474ba46da609e8b0104cbcf4801fbb581b6c343d9426280f9e1be",
"sig": "eecf26e616a6b70dc67c7eae16fc4fe159314647ba1d4581332257de7f070410aa9a9e41f571b9403ff145d16c9b32766846fce08516201263e25cf08c1ed8f1"
}
]
+30
View File
@@ -0,0 +1,30 @@
import type {Page} from "@playwright/test"
import type {RelayMockConfig} from "../../src/lib/test/relayMocks"
// Must match RELAY_MOCKS_KEY in src/lib/test/relayMocks.ts.
const RELAY_MOCKS_KEY = "__RELAY_MOCKS__"
// Hard safety net: intercept every real websocket so a test can never reach the network, even if
// some code path opens a socket directly (e.g. relay AUTH) rather than going through the adapter
// layer. We never call route.connectToServer(), so the socket connects to Playwright's in-process
// mock and simply receives nothing.
export const blockWebsockets = (page: Page) => page.routeWebSocket(/^wss?:\/\//, () => {})
// Inject the relay-mock config the app reads on startup. addInitScript runs before any page script
// on every navigation, so this must be called before page.goto().
export const injectRelayConfig = (page: Page, config: RelayMockConfig) =>
page.addInitScript(
([key, value]) => {
Object.assign(window, {[key]: value})
},
[RELAY_MOCKS_KEY, config] as const,
)
// Full network isolation plus optional fixtures, in one call. With no config, every relay returns
// nothing (requirement 1). Pass {relays: {url: events}} to populate specific relays (requirement 2).
export const setupRelayMocks = async (page: Page, config: RelayMockConfig = {}) => {
await blockWebsockets(page)
await injectRelayConfig(page, config)
}
export type {RelayMockConfig}