Files
GitLite/scripts/workspaces.test.mjs
T
Christoph be073a8f39 feat(workspaces): add workspace sessions and management
Introduce workspace support to group repositories and store per-workspace
open tabs and the last active repository. Integrate a workspace picker into
the repository tab bar and add workspace controls to the dashboard to
create, edit, switch and delete workspaces. Persist and migrate workspace
preferences robustly and include tests for migration, corruption and edge
cases.

- Persist per-workspace sessions and active repo to localStorage
- Add workspace picker in tabs and dashboard management hooks
- Include migration/validation logic and unit tests for edge cases
2026-09-11 14:15:27 +02:00

46 lines
2.8 KiB
JavaScript

import assert from 'node:assert/strict';
import { readFileSync } from 'node:fs';
import test from 'node:test';
import ts from 'typescript';
const source = readFileSync(new URL('../src/lib/workspaces.ts', import.meta.url), 'utf8');
const compiled = ts.transpileModule(source, { compilerOptions: { module: ts.ModuleKind.ESNext, target: ts.ScriptTarget.ES2022 } }).outputText;
const { readWorkspaces, WORKSPACES_KEY } = await import(`data:text/javascript;base64,${Buffer.from(compiled).toString('base64')}`);
const storage = values => ({ getItem: key => values[key] ?? null });
test('migrates dashboard assignments without copying unrelated tabs into a workspace', () => {
const result = readWorkspaces(storage({ 'gitty.dashboard.v1': JSON.stringify({
workspaces: [{ id: 'workspace-a', name: 'A' }, { id: 'workspace-b', name: 'B' }],
assignments: { '/a': 'workspace-a', '/b': 'workspace-b', '/closed': 'workspace-a' },
}) }), ['/a', '/b', '/outside']);
assert.deepEqual(result.workspaces[0], { id: 'workspace-a', name: 'A', repositories: ['/a', '/closed'], openPaths: ['/a'], activePath: '/a' });
assert.deepEqual(result.workspaces[1].openPaths, ['/b']);
assert.deepEqual(result.defaultSession.openPaths, ['/a', '/b', '/outside']);
});
test('restores independent tab order and last active repository', () => {
const saved = { selectedId: 'workspace-a', workspaces: [
{ id: 'workspace-a', name: 'A', repositories: ['/a', '/b'], openPaths: ['/b', '/a'], activePath: '/a' },
{ id: 'workspace-b', name: 'B', repositories: ['/b'], openPaths: [], activePath: '' },
], defaultSession: { openPaths: ['/outside'], activePath: '/outside' } };
assert.deepEqual(readWorkspaces(storage({ [WORKSPACES_KEY]: JSON.stringify(saved) }), []), saved);
});
test('drops invalid memberships and stale active paths from saved sessions', () => {
const saved = { selectedId: 'deleted', workspaces: [null, { id: 'workspace-a', name: 'A',
repositories: ['/a', '/a', null], openPaths: ['/removed', '/a', 3], activePath: '/removed' }],
defaultSession: { openPaths: ['/outside'], activePath: '/removed' } };
const result = readWorkspaces(storage({ [WORKSPACES_KEY]: JSON.stringify(saved) }), []);
assert.equal(result.selectedId, '');
assert.deepEqual(result.workspaces[0].openPaths, ['/a']);
assert.equal(result.workspaces[0].activePath, '/a');
assert.deepEqual(result.workspaces[0].repositories, ['/a']);
assert.equal(result.defaultSession.activePath, '/outside');
});
test('unavailable or corrupt preferences preserve existing repository tabs', () => {
for (const source of [storage({ [WORKSPACES_KEY]: '{broken' }), { getItem() { throw new Error('Storage unavailable'); } }]) {
assert.deepEqual(readWorkspaces(source, ['/existing']).defaultSession.openPaths, ['/existing']);
}
});