import type { Page } from "@playwright/test"; export const TEST_IDENTITIES = { tyler: { privateKey: "3dbaebadb5dfd777ff25149ee230d907a15a9e1294b40b830661e65bb42f6c03", pubkey: "e5ebc6cdb579be112e336cc319b5989b4bb6af11786ea90dbe52b5f08d741b34", username: "tyler", }, alice: { privateKey: "3fa69cbac1dcb9b7b6ac83117c74bd23bb1e717fe8fc7cfda67b47bb4323383d", pubkey: "953d3363262e86b770419834c53d2446409db6d918a57f8f339d495d54ab001f", username: "alice", }, bob: { privateKey: "7667ae87cbc50ac0b2251b115c9c51aca7e2da65301b28ecf82f4e4c5260a6bb", pubkey: "bb22a5299220cad76ffd46190ccbeede8ab5dc260faa28b6e5a2cb31b9aff260", username: "bob", }, charlie: { privateKey: "813fc3bb90587a82b2bfee9b833503e7686c7480681850b3d789c6987e997fc8", pubkey: "554cef57437abac34522ac2c9f0490d685b72c80478cf9f7ed6f9570ee8624ea", username: "charlie", }, outsider: { privateKey: "91bd673543195c0c78fc74a881545dcc8cd6ea6d0f9f8efb3225d58c4bc70dad", pubkey: "df8e91b86fda13a9a67896df77232f7bdab2ba9c3e165378e1ba3d24c13a328e", username: "outsider", }, } as const; type BridgeMode = "mock" | "relay"; type MockBridgeOptions = { mintTokenError?: string; seededTokens?: Array<{ id: string; name: string; scopes: string[]; channel_ids: string[]; created_at: string; expires_at: string | null; last_used_at: string | null; revoked_at: string | null; token?: string; }>; }; type BridgeOptions = { mode: BridgeMode; mock?: MockBridgeOptions; relayHttpUrl?: string; relayWsUrl?: string; user?: keyof typeof TEST_IDENTITIES; }; export async function installBridge(page: Page, options: BridgeOptions) { const identity = options.mode === "relay" ? TEST_IDENTITIES[options.user ?? "tyler"] : undefined; await page.addInitScript( ({ identity: bridgeIdentity, mock, mode, relayHttpUrl, relayWsUrl }) => { const notificationLog: Array<{ body: string | null; title: string; }> = []; const notificationInstances: MockNotification[] = []; class MockNotification extends EventTarget { static permission: NotificationPermission = "granted"; static async requestPermission(): Promise { return MockNotification.permission; } body: string | null; onclick: ((event: Event) => void) | null = null; title: string; constructor(title: string, options?: NotificationOptions) { super(); this.title = title; this.body = options?.body ?? null; notificationInstances.push(this); notificationLog.push({ body: this.body, title: this.title, }); } close() {} } Object.defineProperty(window, "Notification", { configurable: true, value: MockNotification, writable: true, }); const testWindow = window as Window & { __SPROUT_E2E__?: Record; __SPROUT_E2E_APP_BADGE_COUNT__?: number; __SPROUT_E2E_CLICK_NOTIFICATION__?: (index: number) => boolean; __SPROUT_E2E_NOTIFICATIONS__?: Array<{ body: string | null; title: string; }>; }; const currentConfig = testWindow.__SPROUT_E2E__ ?? {}; testWindow.__SPROUT_E2E__ = { ...currentConfig, identity: bridgeIdentity ?? currentConfig.identity, mock, mode, relayHttpUrl: relayHttpUrl ?? currentConfig.relayHttpUrl, relayWsUrl: relayWsUrl ?? currentConfig.relayWsUrl, }; testWindow.__SPROUT_E2E_APP_BADGE_COUNT__ = 0; testWindow.__SPROUT_E2E_CLICK_NOTIFICATION__ = (index: number) => { const notification = notificationInstances[index]; if (!notification) { return false; } const event = new Event("click"); notification.dispatchEvent(event); notification.onclick?.(event); return true; }; testWindow.__SPROUT_E2E_NOTIFICATIONS__ = notificationLog; }, { identity, mock: options.mock, mode: options.mode, relayHttpUrl: options.relayHttpUrl, relayWsUrl: options.relayWsUrl, }, ); } export async function installMockBridge(page: Page, mock?: MockBridgeOptions) { await installBridge(page, { mode: "mock", mock }); } export async function installRelayBridge( page: Page, user: keyof typeof TEST_IDENTITIES = "tyler", ) { await installBridge(page, { mode: "relay", user }); }