73 lines
4.3 KiB
JavaScript
73 lines
4.3 KiB
JavaScript
// Shell link handling on the real dockview shell (preview harness `/?shell&split`, needs `vite dev`):
|
|
// "beside" links split once and reuse only their own side pane (never a feed the user opened), a link
|
|
// inside a side pane stays there, a plain new-tab link stays in its group, and a late `focused`
|
|
// report from a tab that a link just replaced does not bring it back.
|
|
//
|
|
// bun run dev (in another terminal) then node scripts/shell-links-check.mjs [baseUrl]
|
|
|
|
import { chromium } from 'playwright';
|
|
|
|
const base = process.argv[2] ?? 'http://127.0.0.1:1420';
|
|
const failures = [];
|
|
const check = (label, ok, detail = '') => {
|
|
console.log(`${ok ? 'ok ' : 'FAIL'} ${label}${detail ? ` (${detail})` : ''}`);
|
|
if (!ok) failures.push(label);
|
|
};
|
|
|
|
const browser = await chromium.launch();
|
|
const page = await browser.newPage({ viewport: { width: 1500, height: 900 } });
|
|
await page.goto(`${base}/?shell&split`);
|
|
await page.waitForFunction(() => window.__btEmit && window.__btShellLayout?.()?.groups.length >= 2);
|
|
await page.waitForTimeout(300);
|
|
|
|
const layout = () => page.evaluate(() => window.__btShellLayout());
|
|
const emit = (event, payload) => page.evaluate(([event, payload]) => window.__btEmit(event, payload), [event, payload]);
|
|
const settle = () => page.waitForTimeout(250);
|
|
const tabs = state => state.groups.map(group => group.urls.map(url => url.replace(/^https?:\/\//, '')));
|
|
|
|
const start = await layout();
|
|
const feed = start.groups[1];
|
|
check('harness starts with two groups side by side', start.groups.length === 2, JSON.stringify(tabs(start)));
|
|
|
|
// 1. A beside link from the left feed must not land in the right feed: it gets its own split.
|
|
await emit('tab-open', { url: 'https://example.com/one', from: 'tab0', background: false, beside: true });
|
|
await settle();
|
|
const one = await layout();
|
|
const side = one.groups.find(group => group.urls.includes('https://example.com/one'));
|
|
check('beside link from the left group splits a new pane', one.groups.length === 3 && side && side.id !== feed.id && side.id !== start.groups[0].id, JSON.stringify(tabs(one)));
|
|
check('the right feed keeps its tabs', JSON.stringify(one.groups.find(group => group.id === feed.id)?.tabs) === JSON.stringify(feed.tabs));
|
|
check('the side pane sits right of the source', side && side.left > one.groups[0].left);
|
|
|
|
// 2. The next beside link from the same source reuses that side pane.
|
|
await emit('tab-open', { url: 'https://example.com/two', from: 'tab0', background: false, beside: true });
|
|
await settle();
|
|
const two = await layout();
|
|
const side2 = two.groups.find(group => group.id === side?.id);
|
|
check('second beside link reuses the side pane', two.groups.length === 3 && side2?.urls.includes('https://example.com/two'), JSON.stringify(tabs(two)));
|
|
|
|
// 3. A beside link clicked inside the side pane stays in it.
|
|
await emit('tab-open', { url: 'https://example.com/three', from: side2?.active, background: false, beside: true });
|
|
await settle();
|
|
const three = await layout();
|
|
check('a beside link inside the side pane stays there', three.groups.length === 3 && three.groups.find(group => group.id === side?.id)?.urls.includes('https://example.com/three'), JSON.stringify(tabs(three)));
|
|
|
|
// 4. A plain new-tab link opens in its group and becomes active; a late focus from the replaced tab is ignored.
|
|
await emit('tab-open', { url: 'https://example.com/tab', from: 'tab0', background: false, beside: false });
|
|
await settle();
|
|
const opened = await layout();
|
|
const source = opened.groups.find(group => group.tabs.includes('tab0'));
|
|
const newTab = source.tabs[source.urls.indexOf('https://example.com/tab')];
|
|
check('a new-tab link opens in the source group, active', !!newTab && source.active === newTab, JSON.stringify(source));
|
|
await emit('tab-state', { id: 'tab0', focused: true });
|
|
await settle();
|
|
const afterFocus = (await layout()).groups.find(group => group.tabs.includes('tab0'));
|
|
check('a late focus from the replaced tab does not re-activate it', afterFocus.active === newTab, `${newTab} -> ${afterFocus.active}`);
|
|
|
|
// 5. A focused report from a visible pane still activates it (clicking into a split).
|
|
await emit('tab-state', { id: feed.active, focused: true });
|
|
await settle();
|
|
check('a focused visible pane becomes the active tab', (await layout()).active === feed.active);
|
|
|
|
await browser.close();
|
|
console.log(failures.length ? `\n${failures.length} failed` : '\nall passed');
|
|
process.exit(failures.length ? 1 : 0);
|