Files
stack/packages/webui/tests/tester-browser.test.mjs

47 lines
3.9 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import { readFileSync } from 'node:fs';
import { testerBrowser } from './tester-browser-fixture.mjs';
import { testerFixture, testerChat } from './tester-fixture.mjs';
test('tester Console banner exposes only instance route and name editors and saves a route as tester', { timeout: 60000 }, async t => {
const s = await testerFixture(t), b = await testerBrowser(s.web);
try {
const wait = expr => b.evaluate(`(async()=>{for(let n=0;n<150;n++){if(${expr})return true;await new Promise(r=>setTimeout(r,30));}throw Error('wait failed: '+${JSON.stringify(expr)});})()`);
await b.navigate(`http://mosaic-tester.invalid/#/settings/routing`);
await wait('!!document.querySelector("#tester-banner") && document.querySelector("#routes-form button[type=submit]")?.disabled === false');
assert.match(await b.evaluate('document.querySelector("#tester-banner")?.textContent ?? ""'), /tester/i);
assert.equal(await b.evaluate('document.querySelector("#routes-form button[type=submit]").disabled'), false);
assert.ok(await b.evaluate('[...document.querySelectorAll("#settings-nav a")].some(a=>a.getAttribute("href")==="#/settings/agents")'));
assert.ok(await b.evaluate('[...document.querySelectorAll("#settings-nav a")].some(a=>a.getAttribute("href")==="#/settings/names")'));
assert.equal(await b.evaluate('!!document.querySelector("#launch-settings-form, .assistant-form, #token-limits-table [data-limit-reset], #send-section")'), false);
const selector = JSON.stringify('[data-route=\'["coder","thinking"]\']');
await b.evaluate(`(()=>{const e=document.querySelector(${selector});e.value='low';e.dispatchEvent(new Event('change',{bubbles:true}));document.querySelector('#routes-form').requestSubmit();return true;})()`);
await wait('document.querySelector("#routes-receipt")?.textContent.startsWith("Routes saved")');
assert.equal(JSON.parse(readFileSync(s.file, 'utf8')).roles.coder.vars.thinking, 'low');
assert.equal(s.history().at(-1).actor, 'tester');
assert.ok(s.lines.some(l => l.includes('routes user="tester"')));
} finally { await b.close(); }
});
test('row 177: the tester Console chat composer is enabled and a send shows in its own thread', { timeout: 60000 }, async t => {
const s = await testerChat(t), b = await testerBrowser(s.web);
try {
const wait = expr => b.evaluate(`(async()=>{for(let n=0;n<150;n++){if(${expr})return true;await new Promise(r=>setTimeout(r,30));}throw Error('wait failed: '+${JSON.stringify(expr)});})()`);
const tester = s.broker.bindTester({ business: 'demo' });
const project = s.broker.request(tester, { verb: 'project.create', args: { name: 'probe work' } }).id;
const thread = s.broker.request(tester, { verb: 'thread.create', args: { project, name: 'probe' } }).id;
await b.navigate(`http://mosaic-tester.invalid/#/chat/threads/${thread}`);
await wait('!!document.querySelector("#tester-banner") && document.querySelector("#chat-body")?.disabled === false');
await b.evaluate(`(()=>{const e=document.querySelector('#chat-body');e.value='from the tester console';e.dispatchEvent(new Event('input',{bubbles:true}));document.querySelector('#chat-send-form').requestSubmit();return true;})()`);
await wait('document.querySelector("#chat-receipt")?.textContent.includes("Accepted")');
// The log shows a send at the next read, as on the human Console; Refresh reads now.
await wait('!document.querySelector("#refresh").disabled');
await b.evaluate('document.querySelector("#refresh").click(),true');
await wait('document.querySelector(".chat-log")?.textContent.includes("from the tester console")');
const m = s.store.get("SELECT * FROM messages WHERE body='from the tester console'");
assert.equal(m.from_role, 'tester'); assert.equal(m.from_run, 'tester-cli');
assert.ok(s.lines.some(l => l.includes('action=send user="tester"')));
} finally { await b.close(); }
});