// 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}`); });