Something went wrong. Try again.
Monorepo for the nibling.run platform
Something went wrong. Try again.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162// Screenshot tour of the VS Code-restyled harness:// boot → expand node_modules → open two tabs with a dirty edit → run a guest// from the OUTPUT panel → open the tree context menu.// Start the dev server first (node scripts/serve.mjs on :8931), then run:// node scripts/screenshot-vscode.mjs// Shots land in /tmp/nib-shots-vc/*.png.import { chromium } from 'playwright';import { mkdirSync } from 'node:fs';
const DIR = '/tmp/nib-shots-vc';mkdirSync(DIR, { recursive: true });
const browser = await chromium.launch();const page = await browser.newPage({ viewport: { width: 1280, height: 800 } });
// 1. Boot: calm default — node_modules collapsed, editor empty.await page.goto('http://localhost:8931/demo/harness.html');await page.waitForSelector('#tree [data-path="/app"]', { timeout: 10000 });await page.waitForSelector('#sb-boot:has-text("VFS ready")', { timeout: 10000 });await page.waitForTimeout(500);await page.screenshot({ path: `${DIR}/1-boot.png` });console.log('1-boot.png — booted: explorer tree, empty editor, OUTPUT panel ready');
// 2. Expand node_modules via its twisty.await page.click('#tree [data-path="/app/node_modules"] .twisty');await page.waitForSelector('#tree [data-path="/app/node_modules/leftpad"]');await page.waitForTimeout(300);await page.screenshot({ path: `${DIR}/2-expanded.png` });console.log('2-expanded.png — node_modules expanded via its twisty (leftpad + shouty)');
// 3. Open two tabs, dirty one of them.await page.click('#tree [data-path="/app/main.cjs"]');await page.waitForSelector('#tabs .tab[data-path="/app/main.cjs"]');await page.waitForFunction(() => document.getElementById('content')?.value.includes('node:fs'), null, { timeout: 10000 });await page.click('#tree [data-path="/app/notes.md"]');await page.waitForSelector('#tabs .tab[data-path="/app/notes.md"]');await page.waitForFunction(() => document.getElementById('content')?.value === '# scratch\n', null, { timeout: 10000 });await page.fill('#content', '# scratch\nedited for the screenshot\n');await page.waitForSelector('#tabs .tab[data-path="/app/notes.md"][data-dirty="true"]');await page.waitForTimeout(300);await page.screenshot({ path: `${DIR}/3-tabs-dirty.png` });console.log('3-tabs-dirty.png — two tabs; notes.md dirty (● in tab), gutter line numbers visible');
// 4. Run a guest from the OUTPUT panel; its writeFileSync lands in the tree.await page.fill('#entry', '/app/writer.cjs');await page.click('#btn-run');await page.waitForSelector('#tree [data-path="/app/scratch/from-guest.txt"]', { timeout: 10000 });await page.waitForFunction(() => document.getElementById('exit')?.textContent === '0', null, { timeout: 10000 });await page.waitForTimeout(300);await page.screenshot({ path: `${DIR}/4-output-run.png` });console.log('4-output-run.png — guest ran in OUTPUT panel (stdout + exit badge 0), from-guest.txt in tree');
// 5. Context menu open on a tree row.await page.click('#tree [data-path="/app/notes.md"]', { button: 'right' });await page.waitForSelector('#context-menu', { state: 'visible' });await page.waitForTimeout(200);await page.screenshot({ path: `${DIR}/5-context-menu.png` });console.log('5-context-menu.png — tree context menu at the cursor (New File/New Folder/Rename/Delete/Copy Path)');
await browser.close();console.log(`done — 5 shots in ${DIR}`);