import assert from 'node:assert/strict'; import test from 'node:test'; import { DEFAULT_PROFILE, addProfile, defaultProfiles, normalizeProfiles, newProfileId, removeProfile, renameProfile, setActiveProfile, tabProfile, validProfileId, } from '../src/shell/profileModel.ts'; test('profile ids are safe directory names', () => { for (const bad of ['', 'p', '..', 'p/../x', 'P1', 'p-1', 'x1', 'p.1', `p${'a'.repeat(33)}`, 1, null]) assert.equal(validProfileId(bad), false, String(bad)); assert.ok(validProfileId('default')); assert.ok(validProfileId('p1abc')); for (let n = 0; n < 50; n++) assert.ok(validProfileId(newProfileId())); }); test('normalize always keeps the default profile and drops garbage', () => { assert.deepEqual(normalizeProfiles(null), defaultProfiles()); const settings = normalizeProfiles({ profiles: [{ id: 'p1', name: ' Work ', color: '#FF0000' }, { id: 'p1', name: 'dup', color: '#000000' }, { id: '../x', name: 'evil', color: '#000000' }, { id: 'p2', name: '', color: '#000000' }], active: 'p9', }); assert.deepEqual(settings.profiles.map(p => p.id), [DEFAULT_PROFILE, 'p1']); assert.equal(settings.profiles[1]!.name, 'Work'); assert.equal(settings.profiles[1]!.color, '#ff0000'); assert.equal(settings.active, DEFAULT_PROFILE); }); test('more than five accounts can be added and switched', () => { let settings = defaultProfiles(); for (let n = 0; n < 12; n++) settings = addProfile(settings, `Account ${n}`, `p${n}x`); assert.equal(settings.profiles.length, 13); assert.equal(settings.active, 'p11x'); assert.equal(setActiveProfile(settings, 'p3x').active, 'p3x'); assert.equal(setActiveProfile(settings, 'nope').active, 'p11x'); assert.throws(() => addProfile(settings, 'dup', 'p3x')); }); test('rename, remove and tab fallback', () => { let settings = addProfile(defaultProfiles(), 'Alt', 'palt'); assert.equal(renameProfile(settings, 'palt', ' ').profiles[1]!.name, 'Alt'); settings = renameProfile(settings, 'palt', 'Brand'); assert.equal(settings.profiles[1]!.name, 'Brand'); assert.equal(removeProfile(settings, DEFAULT_PROFILE), settings); const removed = removeProfile(settings, 'palt'); assert.equal(removed.active, DEFAULT_PROFILE); assert.equal(tabProfile(removed, 'palt').id, DEFAULT_PROFILE); assert.equal(tabProfile(settings, undefined).id, DEFAULT_PROFILE); assert.equal(tabProfile(settings, 'palt').name, 'Brand'); }); test('an account seen natively survives normalization; forged or broken ones do not', async () => { const { accountLabel } = await import('../src/shell/profileModel.ts'); const settings = normalizeProfiles({ active: 'default', profiles: [ { id: 'default', name: 'Fishies', color: '#1d9bf0', account: { handle: 'playfishies', name: 'Fishies', avatar: 'https://pbs.twimg.com/profile_images/1/a_x96.jpg', signedIn: true } }, { id: 'p1', name: 'x', color: '#f91880', account: { handle: 'bad handle!', name: 'x', signedIn: true } }, { id: 'p2', name: 'y', color: '#00ba7c', account: { handle: 'CRTkafa', name: 'CRT', avatar: 'https://evil.test/a.png', signedIn: false } }, ], }); assert.equal(settings.profiles[0]!.account?.handle, 'playfishies'); assert.equal(settings.profiles[1]!.account, undefined); assert.equal(settings.profiles[2]!.account?.avatar, undefined); assert.deepEqual(accountLabel(settings.profiles[0]!), { title: 'Fishies', detail: '@playfishies', state: 'signed-in' }); assert.deepEqual(accountLabel(settings.profiles[2]!), { title: 'CRT', detail: '@CRTkafa ยท signed out', state: 'signed-out' }); assert.equal(accountLabel(settings.profiles[1]!).state, 'new'); }); test('a new account is a placeholder until someone signs in there', () => { const settings = addProfile(defaultProfiles(), undefined, 'pnew'); assert.equal(settings.active, 'pnew'); assert.equal(settings.profiles[1]!.name, 'New account'); assert.equal(settings.profiles[1]!.account, undefined); });