Files
NetMesh/domain/toolbarItemLayout.test.ts
zhaolei 3c72efcb7f
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
[Init] Initial commit - NetMesh terminal manager
2026-09-13 18:24:01 +08:00

135 lines
4.1 KiB
TypeScript

import test from 'node:test';
import assert from 'node:assert/strict';
import {
moveToolbarItem,
normalizeToolbarItemLayout,
partitionToolbarItems,
reorderToolbarItems,
resetToolbarItemLayout,
setToolbarItemPlacement,
type ToolbarItemLayoutDefaults,
} from './toolbarItemLayout.ts';
const defaults: ToolbarItemLayoutDefaults = {
order: ['a', 'b', 'c', 'd'],
placement: {
a: 'show',
b: 'show',
c: 'collapse',
d: 'hide',
},
lockedIds: ['a'],
};
test('normalize restores defaults for null/invalid values', () => {
assert.deepEqual(normalizeToolbarItemLayout(null, defaults), {
order: ['a', 'b', 'c', 'd'],
placement: { a: 'show', b: 'show', c: 'collapse', d: 'hide' },
});
assert.deepEqual(normalizeToolbarItemLayout('nope', defaults), resetToolbarItemLayout(defaults));
});
test('normalize accepts legacy order-only arrays', () => {
const layout = normalizeToolbarItemLayout(['d', 'a', 'b', 'c'], defaults);
assert.deepEqual(layout.order, ['d', 'a', 'b', 'c']);
assert.equal(layout.placement.a, 'show');
assert.equal(layout.placement.c, 'collapse');
assert.equal(layout.placement.d, 'hide');
});
test('normalize appends new default ids and drops unknown ones', () => {
const layout = normalizeToolbarItemLayout(
{ order: ['c', 'ghost', 'a'], placement: { c: 'show', a: 'collapse' } },
defaults,
);
assert.deepEqual(layout.order, ['c', 'a', 'b', 'd']);
assert.equal(layout.placement.a, 'collapse');
assert.equal(layout.placement.b, 'show');
});
test('locked ids cannot be hidden', () => {
const layout = normalizeToolbarItemLayout(
{ order: ['a', 'b', 'c', 'd'], placement: { a: 'hide', b: 'show', c: 'show', d: 'show' } },
defaults,
);
assert.equal(layout.placement.a, 'show');
const next = setToolbarItemPlacement(layout, 'a', 'hide', defaults);
assert.equal(next.placement.a, 'show');
});
test('partition filters by availability and placement', () => {
const layout = normalizeToolbarItemLayout(null, defaults);
assert.deepEqual(partitionToolbarItems(layout), {
shown: ['a', 'b'],
collapsed: ['c'],
hidden: ['d'],
});
assert.deepEqual(partitionToolbarItems(layout, ['a', 'c', 'd']), {
shown: ['a'],
collapsed: ['c'],
hidden: ['d'],
});
});
test('set placement forces at least one reachable item', () => {
const layout = normalizeToolbarItemLayout(
{
order: ['a', 'b'],
placement: { a: 'show', b: 'hide' },
},
{ order: ['a', 'b'], requireReachable: true },
);
const next = setToolbarItemPlacement(layout, 'a', 'hide', {
order: ['a', 'b'],
requireReachable: true,
});
// a was the only reachable; hide is refused via ensureReachable restoring a
assert.equal(next.placement.a, 'show');
});
test('requireReachable ignores unavailable filler ids', () => {
const layout = normalizeToolbarItemLayout(
{
order: ['a', 'b', 'serialOnly'],
placement: { a: 'hide', b: 'hide', serialOnly: 'show' },
},
{
order: ['a', 'b', 'serialOnly'],
requireReachable: true,
},
);
// serialOnly is still "show" but not available for this session — must restore a/b.
const next = setToolbarItemPlacement(
layout,
'a',
'hide',
{ order: ['a', 'b', 'serialOnly'], requireReachable: true },
['a', 'b'],
);
assert.equal(next.placement.a === 'show' || next.placement.b === 'show', true);
});
test('move skips unavailable neighbors when availableIds is provided', () => {
const layout = normalizeToolbarItemLayout(
{
order: ['a', 'serialOnly', 'b'],
placement: { a: 'show', serialOnly: 'show', b: 'show' },
},
{ order: ['a', 'serialOnly', 'b'] },
);
const moved = moveToolbarItem(layout, 'a', 'later', ['a', 'b']);
assert.deepEqual(moved.order, ['b', 'serialOnly', 'a']);
});
test('reorder and move preserve placement map', () => {
const layout = normalizeToolbarItemLayout(null, defaults);
const reordered = reorderToolbarItems(layout, 'c', 'a', 'before');
assert.deepEqual(reordered.order, ['c', 'a', 'b', 'd']);
assert.equal(reordered.placement.c, 'collapse');
const moved = moveToolbarItem(layout, 'b', 'later');
assert.deepEqual(moved.order, ['a', 'c', 'b', 'd']);
});