Files
archy/tests/apps/podsteadr/media-browser.mjs

71 lines
4.4 KiB
JavaScript

// Actual packaged dashboard and API. Only signer is synthetic; never native UAT.
import { chromium, expect } from '@playwright/test';
import { createRequire } from 'node:module';
// Reuse the exact Podsteadr image's public dependency bytes, not a new npm install.
const { finalizeEvent, getPublicKey } = createRequire('/signer/package.json')('nostr-tools/pure');
import assert from 'node:assert/strict';
const base = 'http://127.0.0.1:8095';
const allowed = new Set([base, 'http://127.0.0.1:3000', 'http://127.0.0.1:8888']);
const secret = new Uint8Array(32).fill(1);
let signatures = 0;
const browser = await chromium.launch({ executablePath: process.env.CHROMIUM_EXECUTABLE,
headless: true, args: ['--no-sandbox', '--disable-dev-shm-usage'] });
try {
const context = await browser.newContext({ serviceWorkers: 'block', viewport: { width: 390, height: 844 } });
await context.route('**/*', route => allowed.has(new URL(route.request().url()).origin) ? route.continue() : route.abort());
await context.routeWebSocket('**/*', socket => socket.close());
await context.exposeFunction('fixtureSign', event => {
assert.equal(event.kind, 27235, 'Fixture must never sign a publication/payment');
assert.ok(event.tags.some(t => t[0] === 'u' && t[1] === base+'/api/auth/login'));
assert.ok(event.tags.some(t => t[0] === 'method' && t[1] === 'POST'));
signatures++;
return finalizeEvent(event, secret);
});
await context.addInitScript(pubkey => {
// This scenario substitutes only the signer, explicitly. Canonical bridge
// bytes/inclusion are checked separately; no native-broker credit is claimed.
window.__archipelagoNostr = true;
window.nostr = { getPublicKey: async () => pubkey, signEvent: event => window.fixtureSign(event) };
}, getPublicKey(secret));
const page = await context.newPage();
const errors = [];
page.on('pageerror', error => errors.push(error.message));
await page.goto(base+'/login');
assert.equal(await page.locator('script[src="/nostr-provider.js"][data-app-id="podsteadr"][data-no-nip98]').count(), 1);
await page.getByRole('button', { name: 'Log in with nostr', exact: true }).click();
await page.waitForURL(base+'/');
assert.equal(signatures, 1);
const streams = await (await context.request.get(base+'/api/streams')).json();
assert.equal(streams.length, 1);
const stream = streams[0];
await page.goto(base+'/streams/'+stream.id);
await expect(page.getByRole('heading', { name: stream.title, exact: true })).toBeVisible();
await expect(page.getByRole('heading', { name: 'Recordings', exact: true })).toBeVisible();
const target = page.getByLabel('Publish to podcast', { exact: true });
await target.selectOption({ label: 'Synthetic recording qualification' });
const podcastId = await target.inputValue();
const pending = page.waitForResponse(r => r.url() === base+'/api/streams/'+stream.id+'/recordings/publish' && r.request().method() === 'POST');
await page.getByRole('button', { name: 'Publish as episode', exact: true }).first().click();
const response = await pending;
assert.equal(response.status(), 201);
const episode = await response.json();
assert.equal(episode.price_sats, null);
await expect(page.getByText('Published! Feed:', { exact: false })).toBeVisible();
const feed = page.getByRole('link', { name: base+'/feeds/'+podcastId+'/feed.xml', exact: true });
await expect(feed).toBeVisible();
assert.equal((await context.request.get(episode.enclosure_url)).status(), 200);
for (const width of [390, 1440]) {
await page.setViewportSize({ width, height: 900 });
await page.reload();
await expect(page.getByRole('heading', { name: 'Recordings', exact: true })).toBeVisible();
assert.equal(await page.evaluate(() => document.documentElement.scrollWidth > innerWidth+1), false, `horizontal overflow at ${width}px`);
}
const podcast = await (await context.request.get(base+'/api/podcasts/'+podcastId)).json();
assert.equal(podcast.episodes.length, 2);
assert.ok(podcast.episodes.some(e => e.id === episode.id));
assert.equal(signatures, 1, 'Reload should retain the actual cookie session');
assert.deepEqual(errors, []);
await context.close();
console.log('PASS actual packaged dashboard synthetic-signer login→recording selection→free episode publication→feed, mobile/desktop reload, real cookie persistence; no native-identity/physical acceptance');
} finally { await browser.close(); }