Files
stack/packages/webui/tests/org-lan-bind-browser.test.mjs
jason.woltje 68fd66903b feat(webui): U3 dashboard, projects and inbox across organizations (#1873)
In organization mode #/ is the cross-organization dashboard (sample 02),
#/projects lists every organization's projects with sort, filters and the
shared By org / Flat grouping (sample 04), and #/inbox lists decisions
across organizations with per-organization decide paths and terminal
commands carrying --org and the full id (sample 05). The per-organization
board moves to #/board and the organization's own project list to #/chat,
which keeps the project surface. Reads go through workspace-data.js; a
read an organization could not make says not read, never zero. Polling
repaints in place and keeps focus, caret and scroll.
2026-11-10 13:35:49 -06:00

45 lines
3.1 KiB
JavaScript

// org-lan-bind: a browser on another machine opens the dev owner Console by an allowed LAN name
// (http://lan.test:PORT/, mapped to 127.0.0.1 for the test) and creates a project. That origin
// is not a secure context, so Chromium sends no Fetch Metadata and has no crypto.randomUUID.
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { startServer } from '../src/serve.mjs';
import { createDevOwner } from '../src/dev-owner.mjs';
import { browser } from './browser.mjs';
import { close } from './fixture.mjs';
const ID = '20000000-0000-4000-8000-000000000002';
test('an allowed LAN name loads the org page and creates a project', { timeout: 45000 }, async t => {
const projects = [], created = [];
const organizations = {
list: async () => [{ id: 'alpha', label: 'alpha', busHealthy: true }],
resolve: async id => id === 'alpha' ? {
busHealthy: true, send: async () => ({}),
reads: { business: async () => ({ business: { id, projects: ['work'] } }), busStatus: async () => ({ live: true }) },
bus: { inbox: async () => [], agents: async () => [], messages: async () => ({ messages: [] }), tasks: async () => [] },
chat: {
projects: async () => projects, threads: async () => [],
createProject: async args => { created.push(args); const row = { id: ID, ...args }; projects.push(row); return row; },
},
} : null,
};
const server = await startServer({ host: '0.0.0.0', port: 0, devAllowHosts: ['lan.test'], sso: createDevOwner(), organizations, send: async () => ({}), board: 'http://127.0.0.1:9', log: () => {} });
t.after(() => close(server));
const port = server.address().port;
const b = await browser({ machine: false, args: ['--host-resolver-rules=MAP lan.test 127.0.0.1'] }); t.after(() => b.close());
const wait = expression => b.evaluate(`(async()=>{for(let i=0;i<300;i++){if(${expression})return;await new Promise(r=>setTimeout(r,30))}throw Error(${JSON.stringify(expression)})})()`);
const input = (selector, value) => b.evaluate(`(()=>{const e=document.querySelector(${JSON.stringify(selector)});e.value=${JSON.stringify(value)};e.dispatchEvent(new Event('input',{bubbles:true}));e.dispatchEvent(new Event('change',{bubbles:true}));})()`);
const click = selector => b.evaluate(`document.querySelector(${JSON.stringify(selector)}).click()`);
await b.navigate(`http://lan.test:${port}/#/orgs/alpha/chat`);
assert.deepEqual(await b.evaluate('({ host: location.host, secure: isSecureContext, uuid: typeof crypto.randomUUID })'), { host: `lan.test:${port}`, secure: false, uuid: 'undefined' });
await wait('window.MosaicOrg?.id === "alpha" && !!document.querySelector("#chat-repo option[value=work]")');
await click('.project-create summary');
await input('#chat-project-name', 'Work'); await input('#chat-repo', 'work');
await click('#chat-project-form button[type=submit]');
await wait('/\\/projects\\/[0-9a-f-]{36}/i.test(location.hash)');
assert.equal(await b.evaluate('location.hash'), `#/orgs/alpha/projects/${ID}`);
assert.deepEqual(created, [{ name: 'Work', repo: 'work' }]);
assert.equal(await b.evaluate('location.host'), `lan.test:${port}`);
});