Files
festipod/scripts/setup-test-auth.ts
T
Sylvain Duchesne 6f9b3ece34 Data-layer BDD testing infrastructure and steps/frontend → steps/ui rename
- Rename steps/frontend/ to steps/ui/ across all modules and shared
- Add data-layer test harness (mock + real broker modes) with Playwright
- Add inscription data-layer steps (@data scenarios)
- Add test auth setup script and browser debug script
- Update docs (architecture, BDD testing, data-layer testing)
- Add ADR for headless wallet creation decision

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 18:01:46 +01:00

120 lines
3.8 KiB
TypeScript

/**
* One-time auth setup for data-layer testing.
*
* Two-step flow:
* Step 1: Opens nextgraph.net so you can create/import a wallet
* Step 2: Navigates to the broker redirect URL to authenticate the test app
*
* Saves auth state to playwright/.auth/ng-state.json for reuse by test runs.
*
* Usage: bun run test:auth-setup
*/
import { chromium } from 'playwright';
import * as http from 'http';
import * as path from 'path';
import * as fs from 'fs';
import * as readline from 'readline';
const AUTH_STATE_PATH = path.resolve('playwright/.auth/ng-state.json');
function prompt(question: string): Promise<string> {
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
return new Promise((resolve) => {
rl.question(question, (answer) => {
rl.close();
resolve(answer);
});
});
}
const SETUP_HTML = `<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>Festipod Test Auth Setup</title></head>
<body style="font-family: system-ui; padding: 2rem; text-align: center;">
<h2>Festipod — Test Auth Setup</h2>
<p id="status">Waiting for NextGraph session...</p>
<script type="module">
import { init, ng } from "@ng-org/web";
await init(
async (event) => {
document.getElementById("status").innerHTML =
'<span style="color: green; font-size: 1.5rem;">✓ Logged in!</span>' +
'<br><br>You can now close this browser window.';
console.log("[auth-setup] Session established:", event.session?.session_id);
},
true,
[]
);
</script>
</body>
</html>`;
async function main() {
console.log('=== NextGraph Auth Setup (2 steps) ===');
console.log('');
// ---- Step 1: Create / open wallet ----
console.log('STEP 1: Create or open your NextGraph wallet');
console.log('A browser will open at nextgraph.net.');
console.log('Create a wallet (or open an existing one), then come back here.');
console.log('');
const browser = await chromium.launch({ headless: false });
const context = await browser.newContext();
const page = await context.newPage();
await page.goto('https://nextgraph.net', { waitUntil: 'domcontentloaded' });
await prompt('Press ENTER here once your wallet is ready...');
// ---- Step 2: Authenticate the test app via broker redirect ----
console.log('');
console.log('STEP 2: Authenticating test app via broker...');
// Start a minimal HTTP server
const server = http.createServer((_req, res) => {
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
res.end(SETUP_HTML);
});
const port = await new Promise<number>((resolve) => {
server.listen(0, '127.0.0.1', () => {
resolve((server.address() as { port: number }).port);
});
});
const appUrl = `http://127.0.0.1:${port}`;
const brokerUrl = `https://nextgraph.net/redir/#/?o=${encodeURIComponent(appUrl)}`;
// Navigate the same page to the broker redirect
await page.goto(brokerUrl, { waitUntil: 'domcontentloaded' });
console.log('The broker should now show your wallet login.');
console.log('Log in, wait for "✓ Logged in!", then close the browser.');
console.log('');
// Wait for browser close
await new Promise<void>((resolve) => {
page.on('close', () => resolve());
browser.on('disconnected', () => resolve());
});
// Save storage state
try {
const state = await context.storageState();
fs.mkdirSync(path.dirname(AUTH_STATE_PATH), { recursive: true });
fs.writeFileSync(AUTH_STATE_PATH, JSON.stringify(state, null, 2));
console.log(`\nAuth state saved to: ${AUTH_STATE_PATH}`);
console.log('You can now run: bun run test:data');
} catch {
console.log('\nCould not save auth state — browser may have closed too quickly.');
}
try { await context.close(); } catch {}
try { await browser.close(); } catch {}
server.close();
}
main().catch(console.error);