T-HUB/apps/web/scripts/manual-shots.mjs
glass beadian aa5e262f3a Tactical Media Broadcast Hub — initial release
Self-hosted multi-platform broadcast newsroom for activist collectives:
publishing pipeline with group approval and DST-proof scheduling, TweetDeck-style
column wall with hostile-content-safe rendering, live control room with Auto
Director, bridged chat governance with polls and quorum, distributed sandboxed
transcode workers, encrypted content-addressed archive, monthly analytics.

MIT licensed. See README.md and docs/.
2026-10-10 11:56:42 +00:00

85 lines
3.4 KiB
JavaScript

import { chromium } from "playwright";
import { mkdirSync } from "node:fs";
const BASE = "http://localhost:3111";
const OUT = "runs/manual/shots";
mkdirSync(OUT, { recursive: true });
const browser = await chromium.launch();
const ctx = await browser.newContext({ viewport: { width: 1440, height: 900 }, deviceScaleFactor: 2 });
const page = await ctx.newPage();
const errors = [];
page.on("pageerror", (e) => errors.push(String(e).slice(0, 150)));
async function shot(name) {
await page.waitForTimeout(500);
await page.screenshot({ path: `${OUT}/${name}.png` });
console.log(`✓ ${name}`);
}
async function safeClick(text, fallback) {
try { await page.getByRole("button", { name: text, timeout: 5000 }).click(); }
catch { try { await page.getByText(text, { timeout: 3000 }).first().click(); }
catch { if (fallback) fallback(); else console.log(` (skip: ${text})`); } }
}
async function safeType(selector, text) {
try { const el = page.locator(selector).first(); await el.click({ timeout: 5000 }); await el.fill(text); }
catch { console.log(` (skip type: ${selector})`); }
}
// ONBOARDING
await page.goto(`${BASE}/onboard`); await page.waitForTimeout(1500);
// redirect to /onboarding
await page.goto(`${BASE}/onboarding`); await page.waitForTimeout(1500);
await shot("onboard-01-start");
safeType("input", "Global News Desk");
await shot("onboard-02-named");
safeClick("Continue");
await shot("onboard-03-invite");
safeType("textarea", "sarah@globalnews.io, marcus@globalnews.io");
await shot("onboard-04-emails-filled");
safeClick("Continue");
await shot("onboard-05-connect");
// STREAMS
await page.goto(`${BASE}/streams`); await page.waitForTimeout(1000);
await shot("streams-01-overview");
await page.keyboard.press("j"); await page.keyboard.press("j"); await page.keyboard.press("j");
await shot("streams-02-item-selected");
await page.keyboard.press("r");
await shot("streams-03-repost-toast");
await page.keyboard.press("q");
await shot("streams-04-quote-popover");
try { const ta = page.locator("textarea").first(); if (await ta.isVisible({ timeout: 3000 })) { await ta.fill("This analysis is essential reading for anyone tracking the Fed's next move."); } } catch {}
await shot("streams-05-quote-typed");
await page.keyboard.press("Escape");
// COMPOSE
await page.goto(`${BASE}/compose`); await page.waitForTimeout(1000);
await shot("compose-01-blank");
try { const ed = page.locator(".ProseMirror").first(); await ed.click({ timeout: 5000 }); await page.keyboard.type("Breaking: Central bank signals first rate cut of the year as inflation cools to 2.1%. Full analysis at globalnews.io/fed-rates #markets #economy"); } catch { console.log(" (compose editor not found)"); }
await shot("compose-02-typed");
// CONNECTIONS
await page.goto(`${BASE}/connections`); await page.waitForTimeout(800);
await shot("connections-01-overview");
// TEAM
await page.goto(`${BASE}/team`); await page.waitForTimeout(800);
await shot("team-01-overview");
// INBOX
await page.goto(`${BASE}/inbox`); await page.waitForTimeout(800);
await shot("inbox-01-overview");
// AUDIT
await page.goto(`${BASE}/audit`); await page.waitForTimeout(800);
await shot("audit-01-overview");
try { await page.locator("tr").filter({ hasText: "credential" }).first().click({ timeout: 5000 }); } catch {}
await shot("audit-02-diff-open");
await browser.close();
console.log(`\nShots: ${OUT}/`);
console.log(`Errors: ${errors.length}`);
for (const e of errors.slice(0, 5)) console.log(` ${e}`);