clone

tiny dependency-free nostr libraries for plain html, each under 5kb and named for an element. public domain

main
nobel / test / e2e.test.js
e2e.test.js 4.0K
1// Drives the demo in headless Chromium against the dev server's in-memory relay.2import { assert, assertEquals } from "jsr:@std/assert@1";3import { chromium } from "npm:playwright@1.58";4import { serve } from "../server.ts";56// Use CHROMIUM if set, else the newest headless shell already in the Playwright cache.7async function chromiumPath() {8 if (Deno.env.get("CHROMIUM")) return Deno.env.get("CHROMIUM");9 const cache = `${Deno.env.get("HOME")}/Library/Caches/ms-playwright`;10 try {11 const dirs = [...Deno.readDirSync(cache)].map((d) => d.name).filter((n) => n.startsWith("chromium_headless_shell-")).sort();12 const dir = `${cache}/${dirs.at(-1)}`;13 const arch = [...Deno.readDirSync(dir)][0].name;14 return `${dir}/${arch}/chrome-headless-shell`;15 } catch { return undefined; }16}1718Deno.test({ name: "demo: post, render, profile, like, cache", sanitizeResources: false, sanitizeOps: false }, async (t) => {19 const server = serve(0);20 const url = `http://localhost:${server.addr.port}/demo/`;21 const browser = await chromium.launch({ executablePath: await chromiumPath() });22 const page = await browser.newPage();23 const errors = [];24 page.on("pageerror", (e) => errors.push(e.message));25 try {26 await page.goto(url);2728 await t.step("helium signs a note, xenon publishes it and renders it", async () => {29 await page.fill("#compose textarea", "hello <b>nobel</b> https://example.com/x");30 await page.fill("#compose input", "nobel");31 await page.click("#compose button");32 await page.waitForSelector("#feed li");33 const li = page.locator("#feed li").first();34 assertEquals(await li.locator("p b").count(), 0, "content must be escaped");35 assertEquals(await li.locator("p a").getAttribute("href"), "https://example.com/x");36 assertEquals(await li.locator(".tag").textContent(), "nobel");37 assertEquals(await li.locator("time").textContent(), "now");38 assertEquals(await page.inputValue("#compose textarea"), "", "form resets after an OK");39 });4041 await t.step("radon fills names after a kind 0 is published", async () => {42 await page.fill("#profile input", "Ada");43 await page.click("#profile button");44 await page.waitForFunction(() => document.querySelector("#feed li b")?.textContent === "Ada");45 await page.waitForFunction(() => document.querySelector("#me")?.textContent === "Ada");46 });4748 await t.step("newest events sort to the top", async () => {49 await page.fill("#compose textarea", "second");50 await page.click("#compose button");51 await page.waitForFunction(() => document.querySelectorAll("#feed li").length === 2);52 await page.waitForFunction(() => document.querySelector("#feed li p").textContent === "second");53 });5455 await t.step("template buttons publish reactions", async () => {56 await page.locator("#feed li button").first().click();57 await page.waitForFunction(() => /kind 7 .*ok/.test(document.querySelector("#log").textContent), null, { timeout: 5000 })58 .catch(async (e) => { throw new Error(`status: ${await page.textContent("#log")}`, { cause: e }); });59 });6061 await t.step("argon serves the feed from IndexedDB on reload", async () => {62 await page.addInitScript(() => {63 window.__from = [];64 document.addEventListener("nhy:event", (e) => e.detail.event.kind === 1 && window.__from.push(e.detail.from));65 });66 await page.reload();67 await page.waitForFunction(() => document.querySelectorAll("#feed li").length === 2);68 await page.waitForTimeout(300);69 const from = await page.evaluate(() => window.__from);70 assertEquals(from.slice(0, 2), ["argon", "argon"], "cache delivers first");71 assert(await page.evaluate(async () => (await argon.query([{ kinds: [1] }])).length === 2));72 });7374 await t.step("identical events from cache and relay render once", async () => {75 await page.waitForTimeout(300);76 assertEquals(await page.locator("#feed li").count(), 2);77 });7879 assertEquals(errors, []);80 } finally {81 await browser.close();82 await server.shutdown();83 }84});