clone

a self-hosted multitenant nostr relay with sites, file storage, git hosting, and inbox and outbox delivery

main
tinyrelay / scripts / qa / thread-navigation-browser.js
thread-navigation-browser.js 2.6K
1// Run with Playwright CLI on a disposable room page containing a thread link.2// Uses real link clicks, the bundled Fixi and morph, and browser history.3async page => {4 const roomURL = page.url().split("#")[0];5 if (!/\/rooms\/[a-z0-9_-]+$/.test(roomURL)) throw Error("Open a room with a thread before running this check.");6 const results = [], requests = [];7 const record = request => requests.push(request.url().split("?")[0]);8 page.on("request", record);9 const shell = async expected => {10 const state = await page.evaluate(() => ({11 headers: document.querySelectorAll("#topbar").length,12 contents: document.querySelectorAll("#content").length,13 sections: [...document.querySelectorAll("#content>section")].map(node => node.id),14 composers: document.querySelectorAll("room-compose").length15 }));16 if (state.headers !== 1 || state.contents !== 1 || state.sections.length !== 1 || state.sections[0] !== expected || state.composers > 1) throw Error(JSON.stringify(state));17 return state;18 };19 try {20 for (const width of [320, 390, 600]) {21 await page.setViewportSize({width, height:844});22 await page.goto(roomURL);23 await page.evaluate(() => { window.__threadNavigation = true; });24 await page.locator('#messages a[href*="/thread/"]').first().click();25 await page.waitForURL("**/thread/**");26 await shell("thread");27 if (!await page.evaluate(() => window.__threadNavigation)) throw Error("Thread navigation unexpectedly reloaded the page.");28 const back = page.locator("#mobile-back");29 const destination = await back.evaluate(node => node.href);30 if (!destination.includes("#msg-")) throw Error("Back link lost its message target.");31 await back.click();32 await page.waitForURL(destination);33 const returned = await shell("room");34 await page.locator("#mobile-back").click();35 await page.waitForURL("**/chat");36 const chat = await shell("chat");37 if (chat.composers !== 0) throw Error("Chat list kept the thread composer.");38 await page.goBack();39 await page.waitForFunction(() => document.querySelector("#content>section")?.id === "room");40 await shell("room");41 await page.goForward();42 await page.waitForFunction(() => document.querySelector("#content>section")?.id === "chat");43 await shell("chat");44 results.push({width, returned, history:true});45 }46 if (requests.some(path => /\/(?:null|undefined)$/.test(path))) throw Error("A stale handler requested an invalid navigation URL.");47 return results;48 } finally { page.off("request", record); }49}