mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-20 09:09:35 +02:00
Review fixes for "place new, child and web tabs into groups". - Spawned tabs follow their parent only with the new synced setting spawnedTabsFollowParent (App Settings > Appearance > Tabs, off by default). TabLayoutService.sessionCreated() reads it fresh through a childrenFollowParent dep: off, a spawned session lands after its parent and is marked manual in the same write; on, it follows until moved by hand. The row menu shows the placement note and "Follow parent again" only when on. "New session" in a group menu is unaffected. zh-CN label and a Settings-Reference row. - applyLegacySessionRank marks a child manual only when the requested order splits it from its parent's block. A PUT of the current order, or one that moves a family together, leaves every stored placement alone. - The browser never echoes a create or delete through PUT /api/session-order, with or without groups: the layout service already re-projects the order and broadcasts it, and syncSessionOrder adopts it. - The placement note in the row menu is plain text described by the menu, not a focusable menu item. - A tab that first appears inside a collapsed group briefly marks that group's header. - i18n skips .tab-name, so tab names are never translated. - Tests: legacy-order cases for an unchanged order, a family reorder and a split; service cases for the setting and for order PUTs; the scheduled registration test now exercises register/undo; the grouped-create test binds port 0; one route case runs through the real layout service.
69 lines
3.0 KiB
TypeScript
69 lines
3.0 KiB
TypeScript
/**
|
|
* The "Spawned tabs follow their parent" setting (`spawnedTabsFollowParent`).
|
|
*
|
|
* SYNCED and OFF by default: the server does the placement, so the value must
|
|
* reach it (in SettingsUpdateSchema, never a per-device display key), and the
|
|
* layout service reads it at every session creation. These tests read the real
|
|
* schema, settings-ui.js, index.html, i18n.js, server.ts and the wiki.
|
|
*/
|
|
import { describe, expect, it } from 'vitest';
|
|
import { readFileSync } from 'node:fs';
|
|
import { resolve } from 'node:path';
|
|
import { SettingsUpdateSchema } from '../src/web/schemas.js';
|
|
|
|
const root = resolve(import.meta.dirname, '..');
|
|
const read = (path: string) => readFileSync(resolve(root, path), 'utf8');
|
|
const html = read('src/web/public/index.html');
|
|
const settingsUi = read('src/web/public/settings-ui.js');
|
|
const i18n = read('src/web/public/i18n.js');
|
|
const server = read('src/web/server.ts');
|
|
const wiki = read('docs/wiki/Settings-Reference.md');
|
|
|
|
const LABEL = 'Spawned Tabs Follow Their Parent';
|
|
|
|
describe('spawnedTabsFollowParent setting', () => {
|
|
it('is a synced boolean in the settings schema', () => {
|
|
expect(SettingsUpdateSchema.safeParse({ spawnedTabsFollowParent: true }).success).toBe(true);
|
|
expect(SettingsUpdateSchema.safeParse({ spawnedTabsFollowParent: 'yes' }).success).toBe(false);
|
|
});
|
|
|
|
it('is not a per-device display key', () => {
|
|
const start = settingsUi.indexOf('const displayKeys = new Set([');
|
|
const block = settingsUi.slice(start, settingsUi.indexOf(']);', start));
|
|
expect(start).toBeGreaterThan(-1);
|
|
expect(block).not.toContain('spawnedTabsFollowParent');
|
|
});
|
|
|
|
it('has an unchecked switch in App Settings > Appearance > Tabs, marked synced', () => {
|
|
const tabs = html.slice(html.indexOf('<h4>Tabs</h4><span class="set-scope">device</span>'));
|
|
const group = tabs.slice(0, tabs.indexOf('</section>'));
|
|
const row = group.match(
|
|
/<div class="set-row"[^>]*id="appSettingsSpawnedTabsFollowParentItem"[\s\S]*?<\/label>/
|
|
)?.[0];
|
|
expect(row).toBeTruthy();
|
|
expect(row).toContain(LABEL);
|
|
expect(row).toContain('<span class="set-tag">synced</span>');
|
|
expect(row).toMatch(/<input type="checkbox" id="appSettingsSpawnedTabsFollowParent">/);
|
|
});
|
|
|
|
it('loads as off unless explicitly true, and saves from the switch', () => {
|
|
expect(settingsUi).toContain(
|
|
"document.getElementById('appSettingsSpawnedTabsFollowParent').checked = settings.spawnedTabsFollowParent === true;"
|
|
);
|
|
expect(settingsUi).toContain(
|
|
"spawnedTabsFollowParent: document.getElementById('appSettingsSpawnedTabsFollowParent').checked,"
|
|
);
|
|
});
|
|
|
|
it('is read fresh by the layout service at creation time', () => {
|
|
expect(server).toMatch(
|
|
/childrenFollowParent: async \(\) => \(await this\.readSettings\(true\)\)\.spawnedTabsFollowParent === true/
|
|
);
|
|
});
|
|
|
|
it('has a zh-CN label and a wiki row', () => {
|
|
expect(i18n).toMatch(new RegExp(`'${LABEL}': '[^']+'`));
|
|
expect(wiki).toMatch(new RegExp(`\\| ${LABEL}\\s+\\|[^\\n]*Synced, off by default`));
|
|
});
|
|
});
|