// @vitest-environment happy-dom
// SPDX-License-Identifier: AGPL-3.0-or-later
import {readFileSync} from 'node:fs';
import {resolve} from 'node:path';
import {NagbarToneKind} from '@app/features/app/components/layout/NagbarTones';
import {WELCOME_ROTATION} from '@app/features/app/components/setup/SetupWizardWelcomeRotation';
import {
AuthShellHintKind,
recordAuthShellHint,
resolveAuthShellPlaceholder,
} from '@app/features/app/components/skeleton/AuthShellHint';
import {SHELL_HINT_NAGBAR_TONE_ORDER, SHELL_HINT_VERSION} from '@app/features/app/components/skeleton/ShellHint';
import {
LEGACY_SHELL_HINT_NAGBAR_TONE_ORDER,
LEGACY_SHELL_HINT_SEED_VERSION,
legacyShellHintSeed,
} from '@fluxer/desktop_ipc/src/LegacyShellHintSeed';
import {createElement, type ReactNode} from 'react';
import {createRoot} from 'react-dom/client';
import {afterEach, expect, test, vi} from 'vitest';
vi.mock('@lingui/core/macro', () => {
const descriptor = (value: unknown): unknown => (typeof value === 'string' ? {message: value} : value);
return {msg: descriptor, t: descriptor, plural: () => '', select: () => '', selectOrdinal: () => ''};
});
vi.mock('@lingui/react/macro', () => ({
Trans: ({children}: {children?: ReactNode}) => children ?? null,
useLingui: () => ({i18n: {_: (descriptor: {message?: string}) => descriptor.message ?? ''}}),
}));
const html = readFileSync(resolve(process.cwd(), 'index.html'), 'utf8');
function readBootScript(): string {
const body = html.slice(html.indexOf('
'));
const match = /')[0];
expect(script).toContain('zoom-preboot');
const run = (mirror: string | null): string => {
document.documentElement.style.removeProperty('--custom-zoom');
if (mirror === null) {
localStorage.removeItem('fluxer:accessibility:zoom-preboot');
} else {
localStorage.setItem('fluxer:accessibility:zoom-preboot', mirror);
}
new Function(script)();
return document.documentElement.style.getPropertyValue('--custom-zoom');
};
expect(run('125')).toBe('125');
expect(run('75')).toBe('75');
expect(run(null)).toBe('');
expect(run('9999')).toBe('');
expect(run('not-a-number')).toBe('');
localStorage.removeItem('fluxer:accessibility:zoom-preboot');
});
function runSignedOutBootScript(pathname: string, storage: Readonly> = {}): HTMLElement | null {
return runBootScript(null, pathname, {signedIn: false, storage});
}
function setNativePlatform(native: boolean): void {
document.documentElement.classList.toggle('platform-native', native);
}
test('a signed-out boot paints the sign-in card at its final size instead of a flat background', () => {
setViewportWidth(1400);
const shell = runSignedOutBootScript('/login');
expect(shell?.dataset.auth).toBe('card');
expect(shell?.dataset.hint).toBe('default');
expect(shell?.dataset.height).toBe('214');
expect(shell?.querySelector('.fluxer-boot-auth-card')?.style.height).toBe('13.375rem');
expect(shell?.querySelectorAll('.fluxer-boot-auth-list > .fluxer-boot-block')).toHaveLength(2);
});
test('a signed-out boot on an app route paints the sign-in card the app redirects to', () => {
setViewportWidth(1400);
expect(runSignedOutBootScript('/channels/@me')?.dataset.category).toBe('login');
expect(runSignedOutBootScript('/channels/100/200')?.dataset.category).toBe('login');
});
test('a signed-out boot sizes the register card and the phone layout from their own defaults', () => {
setViewportWidth(1400);
expect(runSignedOutBootScript('/register')?.dataset.height).toBe('674');
setViewportWidth(390);
const mobile = runSignedOutBootScript('/register');
expect(mobile?.dataset.mobile).toBe('1');
expect(mobile?.dataset.height).toBe('592');
expect(mobile?.querySelector('.fluxer-boot-auth-mmain')).not.toBeNull();
});
test('a remembered auth card size wins over the default', () => {
setViewportWidth(1400);
recordAuthShellHint({pathname: '/login', mobile: false, kind: AuthShellHintKind.CARD, heightPx: 388, widthPx: 512});
const storage = {'fluxer:ui:auth-shell-hint': localStorage.getItem('fluxer:ui:auth-shell-hint') ?? ''};
const shell = runSignedOutBootScript('/login', storage);
expect(shell?.dataset.hint).toBe('hint');
expect(shell?.dataset.height).toBe('388');
expect(shell?.querySelector('.fluxer-boot-auth-card')?.style.maxWidth).toBe('32rem');
});
test('a remembered phone card is not used on a desktop-sized window', () => {
setViewportWidth(1400);
recordAuthShellHint({pathname: '/login', mobile: true, kind: AuthShellHintKind.CARD, heightPx: 500, widthPx: 342});
const storage = {'fluxer:ui:auth-shell-hint': localStorage.getItem('fluxer:ui:auth-shell-hint') ?? ''};
expect(runSignedOutBootScript('/login', storage)?.dataset.height).toBe('214');
});
test('a fresh desktop install paints the fullscreen welcome skeleton', () => {
setViewportWidth(1400);
setNativePlatform(true);
try {
const shell = runSignedOutBootScript('/login');
expect(shell?.dataset.auth).toBe('full');
expect(shell?.querySelector('.fluxer-boot-auth-full')).not.toBeNull();
expect(shell?.querySelector('.fluxer-boot-auth-wtext')?.textContent).toBe('Welcome');
} finally {
setNativePlatform(false);
}
});
test('the fullscreen welcome greets in the stored locale before the browser language', () => {
setViewportWidth(1400);
setNativePlatform(true);
try {
const shell = runSignedOutBootScript('/login', {locale: 'de'});
expect(shell?.querySelector('.fluxer-boot-auth-wtext')?.textContent).toBe('Willkommen');
} finally {
setNativePlatform(false);
}
});
test('the boot welcome words match the welcome rotation', () => {
const table = /var t=(\{[^}]*\});/u.exec(readBootScript());
expect(table).not.toBeNull();
const words = new Function(`return ${table?.[1] ?? '{}'}`)() as Record;
expect(words).toEqual(Object.fromEntries(WELCOME_ROTATION.map((entry) => [entry.code, entry.text])));
});
test('a shell that stamps a stored session paints the app shell even before the preboot mirror exists', () => {
setViewportWidth(1400);
document.documentElement.setAttribute('data-boot-session', '1');
try {
const shell = runSignedOutBootScript('/channels/@me');
expect(shell?.dataset.hint).toBe('default');
expect(shell?.dataset.auth).toBeUndefined();
} finally {
document.documentElement.removeAttribute('data-boot-session');
}
});
test('a session an older client stored paints the app shell before the preboot mirror exists', () => {
setViewportWidth(1400);
const shell = runSignedOutBootScript('/channels/200/300', {token: 'legacy-token', userId: '100'});
expect(shell?.dataset.hint).toBe('default');
expect(shell?.dataset.auth).toBeUndefined();
});
test('a half or emptied older session still paints the sign-in card', () => {
setViewportWidth(1400);
expect(runSignedOutBootScript('/channels/@me', {token: 'legacy-token'})?.dataset.auth).toBe('card');
expect(runSignedOutBootScript('/channels/@me', {token: 'null', userId: '100'})?.dataset.auth).toBe('card');
expect(
runSignedOutBootScript('/channels/@me', {
token: 'legacy-token',
userId: '100',
'fluxer:gateway:preboot:session': '0',
})?.dataset.auth,
).toBe('card');
});
test('a signed-out boot leaves routes without an auth card alone', () => {
setViewportWidth(1400);
expect(runSignedOutBootScript('/oauth2/authorize')).toBeNull();
});
test.each([
{pathname: '/login', width: 1400, native: false},
{pathname: '/login', width: 390, native: false},
{pathname: '/login', width: 1400, native: true},
{pathname: '/register', width: 1400, native: false},
{pathname: '/register', width: 390, native: false},
{pathname: '/forgot', width: 1400, native: false},
{pathname: '/invite/abc', width: 390, native: false},
])(
'the inline auth skeleton picks what the app placeholder picks for $pathname at $width px',
({pathname, width, native}) => {
setViewportWidth(width);
setNativePlatform(native);
try {
const shell = runSignedOutBootScript(pathname);
const placeholder = resolveAuthShellPlaceholder(pathname, {
mobile: width < 640,
native,
passkeyLikely: false,
});
expect(shell?.dataset.category).toBe(placeholder?.category);
expect(shell?.dataset.auth).toBe(placeholder?.kind);
expect(shell?.dataset.hint).toBe(placeholder?.source);
expect(Number(shell?.dataset.height)).toBe(placeholder?.heightPx);
} finally {
setNativePlatform(false);
}
},
);