waybetter-for-x/apps/desktop/tests/backup.test.ts
2026-10-01 06:01:13 +07:00

64 lines
4.5 KiB
TypeScript

import assert from 'node:assert/strict';
import test from 'node:test';
import '../src/i18n/index.ts';
import { canonical, diffSections, isSecretKey, localSections, pickSections, stripSecrets } from '../../../waybetter/packages/shell/src/frame/backupModel.ts';
const current = {
themes: { theme: { preset: 'nord', themes: [] }, scopes: null },
plugins: { enabled: ['bt-focus-mode.plugin.js'], files: [{ file: 'mine.plugin.js', source: 'v1' }] },
customCss: { css: 'a{}' },
features: { hideViewCounts: true },
settings: { homeUrl: 'https://x.com/home', externalLinks: 'pane', siteLinks: 'same', restoreTabs: true },
alerts: { enabled: false, keywords: [] },
accounts: { profiles: [{ id: 'default', name: 'Main', color: '#1d9bf0' }], active: 'default' },
workspaces: { version: 1, default: null, items: [] },
decks: { decks: [], settings: {} },
};
type Loose = Record<string, any>; // eslint-disable-line @typescript-eslint/no-explicit-any
test('the preview shows one row per section with what would change; unchanged sections are unticked', () => {
const incoming = structuredClone(current) as Loose;
incoming.themes.theme = { preset: 'paper', themes: [{ id: 'mine', name: 'Mine' }] };
incoming.plugins = { enabled: ['mine.plugin.js', 'bt-thread-reader.plugin.js'], files: [{ file: 'mine.plugin.js', source: 'v2' }, { file: 'new.plugin.js', source: 'x' }] };
incoming.accounts.profiles.push({ id: 'work', name: 'Work', color: '#f91880' });
incoming.drafts = { drafts: [{ kind: 'post', text: 'hello' }] };
const rows = diffSections(current, incoming);
const by = Object.fromEntries(rows.map(row => [row.section, row]));
assert.deepEqual(rows.map(row => row.section), ['themes', 'plugins', 'customCss', 'features', 'settings', 'alerts', 'accounts', 'workspaces', 'decks', 'drafts']);
assert.ok(by.themes!.details.includes('Theme: nord → paper') && by.themes!.details.some(line => line.includes('1 imported theme')));
assert.ok(by.plugins!.details.some(line => line.includes('new.plugin.js')) && by.plugins!.details.some(line => line.startsWith('1 changed')));
assert.ok(by.plugins!.details.some(line => line.startsWith('Turns off: bt-focus-mode')));
assert.ok(by.accounts!.details[0]!.includes('Work') && by.accounts!.details.includes('No account is removed.'));
assert.equal(by.customCss!.status, 'same');
assert.equal(by.customCss!.checked, false);
assert.equal(by.themes!.checked, true);
assert.equal(by.drafts!.status, 'new');
assert.equal(by.drafts!.checked, false, 'drafts only when asked');
});
test('a backup from before the host kept the settings (xLinks) compares as the same setting', () => {
const old: Loose = { settings: { homeUrl: 'https://x.com/home', externalLinks: 'pane', xLinks: 'same', restoreTabs: true } };
assert.equal(diffSections(current, old)[0]!.status, 'same');
assert.equal(diffSections(old, { settings: current.settings })[0]!.status, 'same', 'and a settings file that was not saved since');
const changed = diffSections(current, { settings: { ...old.settings, xLinks: 'tab' } })[0]!;
assert.equal(changed.status, 'changed');
assert.ok(changed.details[0]!.includes('siteLinks') && !changed.details[0]!.includes('xLinks'), changed.details[0]);
});
test('only ticked sections are applied; decks by the shell, the rest natively; secrets never pass', () => {
const incoming: Loose = { ...current, settings: { ...current.settings, authToken: 'abc', nested: { Cookie: 'c' } }, unknown: { x: 1 } };
const { native, local } = pickSections(incoming, ['settings', 'decks', 'unknown', 'plugins']);
assert.deepEqual(Object.keys(native).sort(), ['plugins', 'settings']);
assert.deepEqual(Object.keys(local), ['decks']);
assert.ok(!canonical(native).includes('abc') && !canonical(native).includes('Cookie'));
});
test('secret-looking keys are recognized like the native backup does', () => {
for (const key of ['cookie', 'Cookies', 'auth_token', 'accessToken', 'ct0', 'password', 'x-csrf-token', 'sessionId', 'privateKey', 'passphrase', 'apiSecret']) assert.ok(isSecretKey(key), key);
for (const key of ['keywords', 'homeUrl', 'profiles', 'restoreTabs', 'theme', 'enabled']) assert.ok(!isSecretKey(key), key);
assert.deepEqual(stripSecrets({ a: [{ token: 1, b: 2 }] }), { a: [{ b: 2 }] });
const shell = localSections({ decks: [{ id: 'd1', name: 'Deck', columns: [], session: 'x' }], deckSettings: { width: 360 } });
assert.deepEqual(shell, { decks: { decks: [{ id: 'd1', name: 'Deck', columns: [] }], settings: { width: 360 } } });
assert.equal(canonical({ b: 1, a: [2, { d: 1, c: 2 }] }), canonical({ a: [2, { c: 2, d: 1 }], b: 1 }));
});