perfect-postcode/video/src/probe.ts
2026-05-11 21:38:26 +01:00

97 lines
3.9 KiB
TypeScript

import { chromium } from 'playwright';
import { APP_URL, AUTH_STATE_PATH, DASHBOARD_PATH } from './config.js';
import { viewportFor } from './script.js';
import { storyboards } from './storyboard.js';
async function main() {
// probe is a debug utility — pin it to the first storyboard's viewport.
const viewport = viewportFor(storyboards[0].video);
const browser = await chromium.launch({ headless: true });
const context = await browser.newContext({
storageState: AUTH_STATE_PATH,
viewport,
});
const page = await context.newPage();
page.on('request', (r) => {
if (r.url().includes('auth-refresh')) {
console.log('REQ', r.method(), r.url(), 'headers:', JSON.stringify(r.headers()));
}
});
page.on('response', async (r) => {
if (r.url().includes('auth-refresh')) {
const body = await r.text().catch(() => '');
console.log('RES', r.status(), r.url(), 'body:', body.slice(0, 200));
}
});
await page.goto(`${APP_URL}${DASHBOARD_PATH}`, { waitUntil: 'networkidle' });
await new Promise((r) => setTimeout(r, 1500));
await page.screenshot({ path: 'output/probe-1-initial.png', fullPage: false });
const ls = await page.evaluate(() => {
const v = localStorage.getItem('pocketbase_auth');
let parsed: unknown = null;
try { parsed = v ? JSON.parse(v) : null; } catch {}
return {
raw: v?.slice(0, 80),
hasToken: !!(parsed as { token?: string })?.token,
hasRecord: !!(parsed as { record?: unknown })?.record,
hasModel: !!(parsed as { model?: unknown })?.model,
};
});
console.log('pb_auth localStorage:', ls);
const refreshTest = await page.evaluate(async () => {
const stored = JSON.parse(localStorage.getItem('pb_auth') ?? '{}');
const r = await fetch('/pb/api/collections/users/auth-refresh', {
method: 'POST',
headers: { Authorization: stored.token },
});
return { status: r.status, body: (await r.text()).slice(0, 200) };
});
console.log('refresh test:', refreshTest);
// Try the SDK path directly. Reach into the Vite-served module graph.
const sdkRefresh = await page.evaluate(async () => {
type W = Window & { pb?: { collection: (n: string) => { authRefresh: () => Promise<unknown> }, authStore: { isValid: boolean, token: string, record: unknown } } };
const w = window as W;
if (!w.pb) return { error: 'window.pb not exposed' };
const before = { isValid: w.pb.authStore.isValid, hasToken: !!w.pb.authStore.token };
try {
const out = await w.pb.collection('users').authRefresh();
return { before, ok: true, out };
} catch (e) {
return { before, ok: false, error: String(e) };
}
});
console.log('SDK refresh:', sdkRefresh);
const aiCount = await page.locator('[data-tutorial="ai-filters"]').count();
const aiVisible = await page.locator('[data-tutorial="ai-filters"]').first().isVisible().catch(() => false);
const aiBtnCount = await page.locator('[data-tutorial="ai-filters"] button').count();
const filterCount = await page.locator('[data-filter-name]').count();
const filterNames = await page.locator('[data-filter-name]').evaluateAll((els) =>
els.map((e) => e.getAttribute('data-filter-name'))
);
const tutorialOverlay = await page.locator('[role="dialog"], [data-tutorial-step], .tutorial-overlay').count();
console.log({ aiCount, aiVisible, aiBtnCount, filterCount, filterNames, tutorialOverlay });
// Try clicking the AI button and check whether textarea appears
const aiBtn = page.locator('[data-tutorial="ai-filters"] button').first();
if (await aiBtn.isVisible()) {
await aiBtn.click();
await new Promise((r) => setTimeout(r, 600));
const taCount = await page.locator('[data-tutorial="ai-filters"] textarea').count();
console.log({ afterClick_taCount: taCount });
await page.screenshot({ path: 'output/probe-2-after-click.png' });
}
await browser.close();
}
main().catch((e) => {
console.error(e);
process.exit(1);
});