Files
webmail/lib/__tests__/lite-mounted-href.test.ts

60 lines
3.0 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import { hrefToString, mountedHref, stripMountedPathname } from '@/lib/lite-mounted-href';
describe('hrefToString', () => {
it('passes strings through and serialises next-intl href objects', () => {
expect(hrefToString('/settings?tab=x')).toBe('/settings?tab=x');
expect(hrefToString({ pathname: '/mail', query: { a: 1, b: ['x', 'y'], skip: undefined }, hash: 'top' })).toBe('/mail?a=1&b=x&b=y#top');
expect(hrefToString({ pathname: '/calendar' })).toBe('/calendar');
});
});
describe('mountedHref', () => {
it('adds the runtime mount and the locale', () => {
expect(mountedHref('/settings', 'en', '/webmail')).toBe('/webmail/en/settings');
expect(mountedHref('/', 'de', '/webmail')).toBe('/webmail/de/');
expect(mountedHref('/?mode=x', 'de', '/webmail')).toBe('/webmail/de/?mode=x');
expect(mountedHref('/login?mode=add-account', 'en', '/bulwark')).toBe('/bulwark/en/login?mode=add-account');
expect(mountedHref({ pathname: '/contacts', query: { id: 'c1' } }, 'en', '/webmail')).toBe('/webmail/en/contacts?id=c1');
});
it('behaves like next-intl at the site root', () => {
expect(mountedHref('/settings', 'en', '')).toBe('/en/settings');
expect(mountedHref('/', 'en', '')).toBe('/en/');
});
it('is idempotent and leaves external, relative and protocol-relative hrefs alone', () => {
expect(mountedHref('/webmail/en/mail', 'en', '/webmail')).toBe('/webmail/en/mail');
expect(mountedHref('/webmail', 'en', '/webmail')).toBe('/webmail');
expect(mountedHref('/en/mail', 'en', '')).toBe('/en/mail');
expect(mountedHref('https://example.com/x', 'en', '/webmail')).toBe('https://example.com/x');
expect(mountedHref('//cdn.example.com/x', 'en', '/webmail')).toBe('//cdn.example.com/x');
expect(mountedHref('thread/1', 'en', '/webmail')).toBe('thread/1');
expect(mountedHref('#anchor', 'en', '/webmail')).toBe('#anchor');
});
it('does not mistake a path that merely starts with the mount text for a mounted one', () => {
expect(mountedHref('/webmailer', 'en', '/webmail')).toBe('/webmail/en/webmailer');
});
});
describe('stripMountedPathname', () => {
it('drops the mount, the locale and a trailing slash', () => {
expect(stripMountedPathname('/webmail/en/settings/', '/webmail')).toBe('/settings');
expect(stripMountedPathname('/webmail/en/calendar/week/2026-09-17', '/webmail')).toBe('/calendar/week/2026-09-17');
expect(stripMountedPathname('/webmail/en/', '/webmail')).toBe('/');
expect(stripMountedPathname('/webmail/zh-TW', '/webmail')).toBe('/');
expect(stripMountedPathname('/webmail', '/webmail')).toBe('/');
});
it('matches next-intl at the site root and during prerendering (no mount)', () => {
expect(stripMountedPathname('/en/mail', '')).toBe('/mail');
expect(stripMountedPathname('/', '')).toBe('/');
expect(stripMountedPathname('', '')).toBe('/');
});
it('keeps paths without a locale as they are', () => {
expect(stripMountedPathname('/webmail/nope/x', '/webmail')).toBe('/nope/x');
});
});