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
135 lines
4.1 KiB
TypeScript
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']);
|
|
});
|