feat: release toolbox portal 0.1.0

This commit is contained in:
2026-07-20 18:40:51 +02:00
commit 5d2e466ad6
55 changed files with 11127 additions and 0 deletions

78
src/preferences.test.ts Normal file
View File

@@ -0,0 +1,78 @@
import { describe, expect, it } from 'vitest';
import {
PREFERENCES_KEY,
cleanPreferences,
defaultPreferences,
moveId,
parsePreferences,
readPreferences,
sortAppIds,
writePreferences,
} from './preferences';
describe('preferences', () => {
it('round-trips namespaced settings', () => {
const preferences = {
...defaultPreferences,
pinned: ['app.two'],
order: ['app.two', 'app.one'],
hidden: ['app.one'],
theme: 'dark' as const,
};
writePreferences(preferences);
expect(localStorage.getItem(PREFERENCES_KEY)).toContain('app.two');
expect(readPreferences()).toEqual(preferences);
});
it('falls back safely for corrupt stored JSON', () => {
localStorage.setItem(PREFERENCES_KEY, '{nope');
expect(readPreferences()).toEqual(defaultPreferences);
});
it('validates imported JSON and removes duplicate ids', () => {
expect(
parsePreferences({
version: 1,
pinned: ['app.one', 'app.one'],
order: [],
hidden: [],
theme: 'system',
}).pinned
).toEqual(['app.one']);
expect(() => parsePreferences({ version: 2 })).toThrow(/version/i);
expect(() =>
parsePreferences({
version: 1,
pinned: 'app.one',
order: [],
hidden: [],
theme: 'system',
})
).toThrow(/pinned/i);
});
it('cleans stale ids, pins first, and supports personal ordering', () => {
const cleaned = cleanPreferences(
{
version: 1,
pinned: ['app.three', 'missing'],
hidden: ['missing'],
order: ['app.two', 'missing'],
theme: 'system',
},
['app.one', 'app.two', 'app.three']
);
expect(cleaned.order).toEqual(['app.two', 'app.one', 'app.three']);
expect(cleaned.hidden).toEqual([]);
expect(sortAppIds(['app.one', 'app.two', 'app.three'], cleaned)).toEqual([
'app.three',
'app.two',
'app.one',
]);
expect(moveId(cleaned.order, 'app.one', -1)).toEqual([
'app.one',
'app.two',
'app.three',
]);
});
});