async page => { // Annotate & Export tab: CoNLL-U output and three download files, then // re-rendering edited CoNLL-U. Run against run_app.py (port 7871). await page.goto('http://127.0.0.1:7871/'); await page.getByRole('tab', {name:'Annotate & Export', exact:true}).click(); const panel = page.locator('[role="tabpanel"]:visible'); await panel.getByRole('button', {name:'Annotate', exact:true}).click(); const downloads = panel.locator('a[download^="ud-analysis"]'); await page.waitForFunction(() => document.querySelectorAll('[role="tabpanel"] a[download^="ud-analysis"]').length >= 3, null, {timeout:60000}); const names = await downloads.evaluateAll(links => links.map(link => link.getAttribute('download') || link.textContent.trim())); for (const suffix of ['.conllu', '.svg', '.png']) { if (!names.some(name => name.endsWith(suffix))) throw Error('Missing download ' + suffix + ': ' + names.join(', ')); } const conllu = await panel.locator('.cm-content').first().innerText(); if (!conllu.includes('# sent_id = 1')) throw Error('CoNLL-U output missing'); await panel.getByRole('button', {name:'Render CoNLL-U', exact:true}).click(); await page.waitForTimeout(500); await page.waitForFunction(() => !document.querySelector('[role="tabpanel"] .progress-text, [role="tabpanel"] .eta-bar'), null, {timeout:60000}); const rendered = await downloads.evaluateAll(links => links.map(link => link.getAttribute('download') || link.textContent.trim())); if (rendered.length !== 2 || !rendered.some(name => name.endsWith('.png'))) throw Error('Render should return SVG and PNG: ' + rendered.join(', ')); await page.screenshot({path:'output/playwright/export-tab.png', fullPage:true}); return {annotate:names, render:rendered}; }