forked from coracle/flotilla
Scaffold playwright
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
import {on} from "@welshman/lib"
|
||||
import {isRelayUrl, normalizeRelayUrl} from "@welshman/util"
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import {AbstractAdapter, AdapterEvent, LocalAdapter, Repository, netContext} from "@welshman/net"
|
||||
import type {ClientMessage, NetContext, RelayMessage} from "@welshman/net"
|
||||
|
||||
// The window key Playwright writes the mock config to (see e2e/support/relayMocks.ts). Keep it in
|
||||
// sync with the literal duplicated there.
|
||||
export const RELAY_MOCKS_KEY = "__RELAY_MOCKS__"
|
||||
|
||||
export type RelayMockConfig = {
|
||||
// Map of relay url -> events that relay should return. Any relay NOT listed returns nothing (an
|
||||
// immediate EOSE), which is what keeps tests offline and reproducible by default.
|
||||
relays?: Record<string, TrustedEvent[]>
|
||||
}
|
||||
|
||||
// Wraps welshman's LocalAdapter so we reuse its REQ/EVENT/CLOSE handling against an in-memory
|
||||
// Repository, but re-emits its messages under the real relay url instead of LOCAL_RELAY_URL. That
|
||||
// keeps relay attribution / relay-scoped behaviour (e.g. NIP-29 groups) working as it would over a
|
||||
// real socket. (Composition rather than inheritance because LocalAdapter emits via a private method
|
||||
// that hardcodes LOCAL_RELAY_URL.)
|
||||
class FixtureAdapter extends AbstractAdapter {
|
||||
readonly local: LocalAdapter
|
||||
|
||||
constructor(
|
||||
readonly url: string,
|
||||
repository: Repository,
|
||||
) {
|
||||
super()
|
||||
|
||||
this.local = new LocalAdapter(repository)
|
||||
|
||||
const forward = (message: RelayMessage) => this.emit(AdapterEvent.Receive, message, this.url)
|
||||
|
||||
this._unsubscribers.push(
|
||||
on(this.local, AdapterEvent.Receive, forward),
|
||||
() => this.local.cleanup(),
|
||||
)
|
||||
}
|
||||
|
||||
get sockets() {
|
||||
return this.local.sockets
|
||||
}
|
||||
|
||||
get urls() {
|
||||
return [this.url]
|
||||
}
|
||||
|
||||
send(message: ClientMessage) {
|
||||
this.local.send(message)
|
||||
}
|
||||
}
|
||||
|
||||
// Override netContext.getAdapter so every real relay url is served from memory and no websocket is
|
||||
// ever created for it. Non-relay urls (e.g. the local:// repository relay) fall through to
|
||||
// welshman's default handling.
|
||||
export const installRelayMocks = (config: RelayMockConfig) => {
|
||||
const reposByUrl = new Map<string, Repository>()
|
||||
|
||||
for (const [url, events] of Object.entries(config.relays ?? {})) {
|
||||
const repository = new Repository()
|
||||
repository.load(events)
|
||||
reposByUrl.set(normalizeRelayUrl(url), repository)
|
||||
}
|
||||
|
||||
const emptyRepository = new Repository()
|
||||
const fallback = netContext.getAdapter
|
||||
|
||||
netContext.getAdapter = ((url: string, context: NetContext) => {
|
||||
if (!isRelayUrl(url)) {
|
||||
return fallback ? fallback(url, context) : undefined
|
||||
}
|
||||
|
||||
const repository = reposByUrl.get(normalizeRelayUrl(url)) ?? emptyRepository
|
||||
|
||||
return new FixtureAdapter(url, repository)
|
||||
}) as NetContext["getAdapter"]
|
||||
}
|
||||
|
||||
// Called once on app startup. Installs the mocks only when Playwright has injected a config, so it
|
||||
// is a no-op for real users.
|
||||
export const maybeInstallRelayMocks = () => {
|
||||
const config = (globalThis as Record<string, unknown>)[RELAY_MOCKS_KEY] as
|
||||
| RelayMockConfig
|
||||
| undefined
|
||||
|
||||
if (config) {
|
||||
installRelayMocks(config)
|
||||
}
|
||||
|
||||
return Boolean(config)
|
||||
}
|
||||
@@ -23,6 +23,7 @@
|
||||
import * as app from "@welshman/app"
|
||||
import {isMobile} from "@lib/html"
|
||||
import * as implicit from "@lib/implicit"
|
||||
import {maybeInstallRelayMocks} from "@lib/test/relayMocks"
|
||||
import AppContainer from "@app/components/AppContainer.svelte"
|
||||
import ModalContainer from "@app/components/ModalContainer.svelte"
|
||||
import {setupHistory} from "@app/util/history"
|
||||
@@ -46,6 +47,12 @@
|
||||
|
||||
const {children} = $props()
|
||||
|
||||
// Test-only: when Playwright has injected window.__RELAY_MOCKS__, serve relays from in-memory
|
||||
// fixtures instead of the network. No-op for real users; stripped from production builds.
|
||||
if (import.meta.env.DEV) {
|
||||
maybeInstallRelayMocks()
|
||||
}
|
||||
|
||||
const policies = [authPolicy, blockPolicy, trustPolicy, mostlyRestrictedPolicy]
|
||||
|
||||
// Add stuff to window for convenience
|
||||
|
||||
Reference in New Issue
Block a user