var test = require('node:test'), assert = require('node:assert/strict'), cp = require('node:child_process'), path = require('node:path'); var chromium = require('playwright').chromium; test('native task tabs open real bounded transcripts/output and retain completed tasks', { timeout: 90000 }, async function (t) { var child = cp.fork(path.join(__dirname, 'fixtures/pane-reuse-server.cjs'), [], { env: Object.assign({}, process.env, { CLAY_BACKGROUND_TASKS: '1' }), stdio: ['ignore', 'pipe', 'pipe', 'ipc'] }); t.after(function () { child.kill('SIGTERM'); }); child.stdout.resume(); child.stderr.resume(); var info = await new Promise(function (resolve) { child.once('message', resolve); }); var browser = await chromium.launch({ headless: true }); t.after(function () { return browser.close(); }); var page = await browser.newPage({ viewport: { width: 1280, height: 850 } }), errors = []; page.on('console', function (message) { if (message.type() === 'error') errors.push(message.text()); }); page.on('pageerror', function (error) { errors.push(error.message); }); var base = 'http://127.0.0.1:' + info.port; if (!process.env.CLAY_TASK_COMPILED) await require('./fixtures/source-module-runtime.cjs').install(page); await page.goto(base + '/fixture/login'); var data = await (await page.request.get(base + '/fixture/state')).json(); await page.locator('.session-item[data-session-id="' + data.standaloneId + '"]').first().click(); await page.waitForFunction(function (id) { return Array.from(document.querySelectorAll('iframe')).some(function (frame) { var live = frame.clayPane && frame.clayPane.identity(); return live && live.ready && live.sessionId === id; }); }, data.standaloneId); await page.request.post(base + '/fixture/background-tasks?id=' + data.standaloneId); var host = page; // A singleton may be rendered through its authenticated pane document. await page.waitForFunction(function () { return (document.querySelector('[data-background-task="agent-a"]') && document.querySelector('[data-background-task="agent-a"]').getClientRects().length) || Array.from(document.querySelectorAll('iframe')).some(function (frame) { try { var chip = frame.contentDocument.querySelector('[data-background-task="agent-a"]'); return chip && chip.getClientRects().length; } catch (e) { return false; } }); }).catch(function (error) { assert.fail(error.message + ' ยท Browser errors: ' + JSON.stringify(errors)); }); for (var frame of page.frames()) if (await frame.locator('[data-background-task="agent-a"]').isVisible()) host = frame; await host.locator('[data-background-task="agent-a"]').click(); var viewer = host.locator('#background-task-viewer'); await viewer.getByText('Task transcript 1 row 0', { exact: true }).waitFor(); assert.equal(await host.locator('#background-tasks-bar').count(), 0); assert.match(await viewer.innerText(), /Parent agent/); assert.match(await viewer.innerText(), /Background agent/); await viewer.locator('.tool-header').first().click(); assert.match(await viewer.locator('.tool-item.expanded').first().innerText(), /fixture.txt/); await page.request.post(base + '/fixture/background-tasks?id=' + data.standaloneId); await viewer.getByText('Task transcript 2 row 0', { exact: true }).waitFor(); assert.equal(await viewer.locator('.tool-item.expanded').count(), 1); await viewer.getByRole('button', { name: 'Next', exact: true }).click(); await viewer.getByText('Task transcript 2 row 104', { exact: true }).waitFor(); await viewer.getByRole('button', { name: 'Previous', exact: true }).click(); await viewer.getByText('Task transcript 2 row 0', { exact: true }).waitFor(); await host.locator('body').press('Escape'); await viewer.waitFor({ state: 'detached' }); assert.equal(await host.locator('[data-background-task="agent-a"]').evaluate(function (el) { return el === document.activeElement; }), true); await host.locator('[data-background-task="shell-a"]').click(); await viewer.getByText('Native shell output 2', { exact: true }).waitFor(); assert.match(await viewer.innerText(), /Last 8 KiB/); await host.getByRole('button', { name: 'Stop Run checks', exact: true }).click(); await host.getByRole('button', { name: 'Stop Run checks', exact: true }).waitFor({ state: 'detached' }); await host.locator('[data-background-task="shell-a"]').click(); await viewer.getByText('Native shell output 2', { exact: true }).waitFor(); await viewer.getByRole('status').filter({ hasText: 'Finished' }).waitFor(); var stopped = await (await page.request.get(base + '/fixture/background-tasks?id=' + data.standaloneId)).json(); assert.deepEqual(stopped.stopped, ['shell-a']); await page.setViewportSize({ width: 420, height: 760 }); await host.waitForFunction(function () { var el = document.getElementById('background-task-viewer'); if (!el) return false; var rect = el.getBoundingClientRect(); return innerWidth <= 420 && rect.width <= innerWidth && rect.x >= 0; }); var box = await viewer.boundingBox(); assert.ok(box.width <= 420 && box.x >= 0, JSON.stringify(box)); await page.request.post(base + '/fixture/switch?id=' + data.otherIds[0]); await viewer.waitFor({ state: 'detached' }); assert.equal(await host.locator('[data-background-task]').count(), 0); assert.deepEqual(errors, []); });