Files
2026-07-13 12:34:04 +08:00

223 lines
6.6 KiB
JavaScript

'use strict';
const test = require('node:test');
const assert = require('node:assert/strict');
const {
SAVED_TAB_SESSION_COLLAPSED_KEY,
SAVED_TAB_SESSION_ORDER_KEY,
applySavedTabSessionOrder,
detachSavedSessionTabToNewSession,
buildSavedSessionTabToken,
buildSavedTabSessionOrder,
buildSavedTabSessionOrderWithInsertedSession,
moveSavedSessionTabsByTokens,
normalizeSavedTabSessionCollapsedState,
normalizeSavedTabSessionOrder,
parseSavedSessionTabToken,
reorderSavedSessionTabsByTokens,
} = require('./session-manager.js');
test('session manager exposes the saved session order storage key', () => {
assert.equal(SAVED_TAB_SESSION_ORDER_KEY, 'savedTabSessionOrder');
});
test('session manager exposes the saved session collapsed storage key', () => {
assert.equal(SAVED_TAB_SESSION_COLLAPSED_KEY, 'savedTabSessionCollapsedState');
});
test('normalizeSavedTabSessionOrder keeps unique non-empty ids in order', () => {
assert.deepEqual(
normalizeSavedTabSessionOrder(['session-a', '', null, 'session-b', 'session-a']),
['session-a', 'session-b']
);
});
test('normalizeSavedTabSessionCollapsedState keeps only explicit true flags for known sessions', () => {
assert.deepEqual(
normalizeSavedTabSessionCollapsedState(
{
'session-a': true,
'session-b': false,
'': true,
'session-c': 'yes',
},
[
{ id: 'session-a' },
{ id: 'session-b' },
]
),
{ 'session-a': true }
);
});
test('applySavedTabSessionOrder sorts sessions by persisted ids and appends new ones', () => {
const ordered = applySavedTabSessionOrder(
[
{ id: 'session-c', name: 'C' },
{ id: 'session-a', name: 'A' },
{ id: 'session-b', name: 'B' },
],
['session-b', 'session-a']
);
assert.deepEqual(
ordered.map(session => session.id),
['session-b', 'session-a', 'session-c']
);
});
test('buildSavedTabSessionOrder reflects the current ordered session ids', () => {
assert.deepEqual(
buildSavedTabSessionOrder([
{ id: 'session-b' },
{ id: 'session-a' },
{ id: 'session-b' },
]),
['session-b', 'session-a']
);
});
test('saved session tab tokens round-trip session id and index', () => {
const token = buildSavedSessionTabToken('session-a', 2);
assert.equal(token, 'session-a::2');
assert.deepEqual(parseSavedSessionTabToken(token), { sessionId: 'session-a', tabIndex: 2 });
});
test('reorderSavedSessionTabsByTokens reorders tabs within one session', () => {
const reordered = reorderSavedSessionTabsByTokens(
{
id: 'session-a',
tabs: [{ title: 'A' }, { title: 'B' }, { title: 'C' }],
},
['session-a::2', 'session-a::0', 'session-a::1']
);
assert.deepEqual(reordered.map(tab => tab.title), ['C', 'A', 'B']);
});
test('moveSavedSessionTabsByTokens preserves target tabs when moving across sessions', () => {
const moved = moveSavedSessionTabsByTokens({
sourceSession: {
id: 'session-a',
tabs: [{ title: 'A' }, { title: 'A2' }],
},
targetSession: {
id: 'session-b',
tabs: [{ title: 'B' }],
},
sourceOrderTokens: ['session-a::1'],
targetOrderTokens: ['session-a::0', 'session-b::0'],
draggedToken: 'session-a::0',
});
assert.deepEqual(moved.sourceTabs.map(tab => tab.title), ['A2']);
assert.deepEqual(moved.targetTabs.map(tab => tab.title), ['A', 'B']);
});
test('buildSavedTabSessionOrderWithInsertedSession inserts new sessions at the top, bottom, or before a gap target', () => {
const sessions = [
{ id: 'session-a', name: 'A' },
{ id: 'session-b', name: 'B' },
{ id: 'session-c', name: 'C' },
];
assert.deepEqual(
buildSavedTabSessionOrderWithInsertedSession(sessions, 'session-new', {
placement: 'before',
}),
['session-new', 'session-a', 'session-b', 'session-c']
);
assert.deepEqual(
buildSavedTabSessionOrderWithInsertedSession(sessions, 'session-new', {
placement: 'after',
}),
['session-a', 'session-b', 'session-c', 'session-new']
);
assert.deepEqual(
buildSavedTabSessionOrderWithInsertedSession(sessions, 'session-new', {
placement: 'before',
insertBeforeSessionId: 'session-c',
}),
['session-a', 'session-b', 'session-new', 'session-c']
);
});
test('detachSavedSessionTabToNewSession inserts a new middle session and rebuilds the source tabs/groups', () => {
const result = detachSavedSessionTabToNewSession({
sessions: [
{
id: 'session-a',
name: 'Morning',
savedAt: '2026-05-22T08:00:00.000Z',
source: 'manual',
tabs: [
{ url: 'https://a.test', title: 'A', groupKey: 'group-a', groupLabel: 'Group A' },
{ url: 'https://b.test', title: 'B', groupKey: 'group-b', groupLabel: 'Group B' },
],
groups: [
{ key: 'group-a', label: 'Group A', manualGroupId: '', tabUrls: ['https://a.test'] },
{ key: 'group-b', label: 'Group B', manualGroupId: '', tabUrls: ['https://b.test'] },
],
},
{
id: 'session-c',
name: 'Later',
savedAt: '2026-05-22T08:10:00.000Z',
source: 'manual',
tabs: [{ url: 'https://c.test', title: 'C' }],
groups: [],
},
],
draggedToken: 'session-a::1',
placement: 'before',
insertBeforeSessionId: 'session-c',
now: '2026-05-22T09:30:00.000Z',
});
assert.deepEqual(result.orderIds, [
'session-a',
result.createdSession.id,
'session-c',
]);
assert.deepEqual(result.sessions[0].tabs.map(tab => tab.url), ['https://a.test']);
assert.deepEqual(result.sessions[0].groups.map(group => group.key), ['group-a']);
assert.equal(result.createdSession.name, 'B');
assert.deepEqual(result.createdSession.tabs.map(tab => tab.url), ['https://b.test']);
});
test('detachSavedSessionTabToNewSession deletes the source session when its last tab is moved out', () => {
const result = detachSavedSessionTabToNewSession({
sessions: [
{
id: 'session-a',
name: 'Solo',
savedAt: '2026-05-22T08:00:00.000Z',
source: 'manual',
tabs: [{ url: 'https://solo.test', title: 'Solo' }],
groups: [],
},
{
id: 'session-b',
name: 'Next',
savedAt: '2026-05-22T08:10:00.000Z',
source: 'manual',
tabs: [{ url: 'https://next.test', title: 'Next' }],
groups: [],
},
],
draggedToken: 'session-a::0',
placement: 'before',
insertBeforeSessionId: 'session-b',
now: '2026-05-22T09:30:00.000Z',
});
assert.equal(result.sourceSessionRemoved, true);
assert.deepEqual(
result.sessions.map(session => session.id),
[result.createdSession.id, 'session-b']
);
});