mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-10-31 08:13:50 +00:00
89 lines
4.3 KiB
TypeScript
89 lines
4.3 KiB
TypeScript
import { beforeEach, describe, expect, it } from 'vitest';
|
|
import {
|
|
liteSegmentsFromPath,
|
|
liteSurfaceRootFor,
|
|
parseLitePath,
|
|
stashPendingLitePath,
|
|
takePendingLitePath,
|
|
} from '@/lib/lite-link-segments';
|
|
import { LITE_PENDING_PATH_KEY } from '@/lib/lite';
|
|
|
|
describe('parseLitePath', () => {
|
|
it('splits locale, surface and the remaining segments', () => {
|
|
expect(parseLitePath('/en/mail/thread/abc')).toEqual({ locale: 'en', surface: 'mail', segments: ['thread', 'abc'] });
|
|
expect(parseLitePath('/de/calendar/week/2026-09-17/')).toEqual({ locale: 'de', surface: 'calendar', segments: ['week', '2026-09-17'] });
|
|
expect(parseLitePath('/zh-TW/settings/reading')).toEqual({ locale: 'zh-TW', surface: 'settings', segments: ['reading'] });
|
|
});
|
|
|
|
it('treats the locale root as the mail surface with no segments', () => {
|
|
expect(parseLitePath('/en/')).toEqual({ locale: 'en', surface: 'mail', segments: [] });
|
|
expect(parseLitePath('/en')).toEqual({ locale: 'en', surface: 'mail', segments: [] });
|
|
});
|
|
|
|
it('ignores query and hash and decodes each segment exactly once', () => {
|
|
expect(parseLitePath('/en/contacts/card/a%2Fb?x=1#y')).toEqual({ locale: 'en', surface: 'contacts', segments: ['card', 'a/b'] });
|
|
expect(parseLitePath('/en/files/folder/100%25')).toEqual({ locale: 'en', surface: 'files', segments: ['folder', '100%'] });
|
|
// A broken escape is passed through verbatim rather than throwing.
|
|
expect(parseLitePath('/en/files/folder/%E0%A4%A')).toEqual({ locale: 'en', surface: 'files', segments: ['folder', '%E0%A4%A'] });
|
|
});
|
|
|
|
it('strips a sub-path mount prefix first', () => {
|
|
expect(parseLitePath('/webmail/fr/mail/message/m1', '/webmail')).toEqual({ locale: 'fr', surface: 'mail', segments: ['message', 'm1'] });
|
|
expect(parseLitePath('/webmail', '/webmail')).toEqual({ locale: null, surface: 'mail', segments: [] });
|
|
// A different first segment that merely shares the prefix text is not the prefix.
|
|
expect(parseLitePath('/webmailer/en/mail', '/webmail').surface).toBeNull();
|
|
});
|
|
|
|
it('returns no surface for login, pro and unknown paths', () => {
|
|
expect(parseLitePath('/en/login').surface).toBeNull();
|
|
expect(parseLitePath('/en/pro').surface).toBeNull();
|
|
expect(parseLitePath('/nonsense/deep').surface).toBeNull();
|
|
expect(parseLitePath('/nonsense/deep').locale).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe('liteSegmentsFromPath', () => {
|
|
it('only yields segments for the surface that is asking', () => {
|
|
expect(liteSegmentsFromPath('/en/mail/thread/t1', 'mail')).toEqual(['thread', 't1']);
|
|
expect(liteSegmentsFromPath('/en/mail/thread/t1', 'calendar')).toEqual([]);
|
|
expect(liteSegmentsFromPath('/en/', 'mail')).toEqual([]);
|
|
expect(liteSegmentsFromPath('/en/login', 'mail')).toEqual([]);
|
|
});
|
|
});
|
|
|
|
describe('liteSurfaceRootFor (404 shim target)', () => {
|
|
it('points a deep link at its surface shell, keeping locale and mount prefix', () => {
|
|
expect(liteSurfaceRootFor('/en/mail/thread/t1')).toBe('/en/mail/');
|
|
expect(liteSurfaceRootFor('/webmail/de/files/folder/x', '/webmail')).toBe('/webmail/de/files/');
|
|
});
|
|
|
|
it('returns null when there is nothing to replay', () => {
|
|
expect(liteSurfaceRootFor('/en/login')).toBeNull();
|
|
expect(liteSurfaceRootFor('/totally/unknown')).toBeNull();
|
|
// No locale in the URL: the shells are locale-prefixed, so nothing to load.
|
|
expect(liteSurfaceRootFor('/mail/thread/x')).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe('pending path hand-off', () => {
|
|
beforeEach(() => {
|
|
sessionStorage.clear();
|
|
});
|
|
|
|
it('parks a link and hands it to the owning surface exactly once', () => {
|
|
expect(stashPendingLitePath('/en/mail/thread/t1?x=1')).toBe(true);
|
|
expect(sessionStorage.getItem(LITE_PENDING_PATH_KEY)).toBe('/en/mail/thread/t1?x=1');
|
|
// Another surface leaves it alone.
|
|
expect(takePendingLitePath('calendar')).toBeNull();
|
|
expect(sessionStorage.getItem(LITE_PENDING_PATH_KEY)).toBe('/en/mail/thread/t1?x=1');
|
|
expect(takePendingLitePath('mail')).toBe('/en/mail/thread/t1?x=1');
|
|
expect(takePendingLitePath('mail')).toBeNull();
|
|
});
|
|
|
|
it('respects the mount prefix when matching the surface', () => {
|
|
stashPendingLitePath('/webmail/en/contacts/card/c1');
|
|
expect(takePendingLitePath('contacts')).toBeNull(); // without prefix: "webmail" is not a locale
|
|
expect(takePendingLitePath('contacts', '/webmail')).toBe('/webmail/en/contacts/card/c1');
|
|
});
|
|
});
|