import React, {act} from 'react'; import {createRoot, type Root} from 'react-dom/client'; import {BrowserIdentityProvider, usePageIdentity} from './BrowserIdentity'; import {useAuth} from '../../context/AuthContext'; jest.mock('../../context/AuthContext',()=>({useAuth:jest.fn()})); jest.mock('../../api/includedAppsApi',()=>({listIncludedApps:jest.fn().mockResolvedValue([])})); const auth=useAuth as jest.Mock; (globalThis as typeof globalThis&{IS_REACT_ACT_ENVIRONMENT:boolean}).IS_REACT_ACT_ENVIRONMENT=true; let container:HTMLDivElement,root:Root; function render(element:React.ReactElement){act(()=>root.render(element));return{rerender:(next:React.ReactElement)=>act(()=>root.render(next))};} function Page({name,icon}:{name:string;icon?:string}) {usePageIdentity(name,icon);return

{name}

;} let candidates:Array<{onload:(()=>void)|null;onerror:(()=>void)|null;naturalWidth:number;src:string}>; let imageMock:jest.SpyInstance; function favicon(){return document.querySelector('#conductor-favicon')!;} beforeEach(()=>{ jest.useFakeTimers();candidates=[]; container=document.createElement('div');document.body.appendChild(container);root=createRoot(container); window.history.replaceState({},'','/'); auth.mockReturnValue({user:{id:'admin-1',role:'admin'},loading:false,setupRequired:false}); imageMock=jest.spyOn(window,'Image').mockImplementation(()=>{ const candidate={onload:null,onerror:null,naturalWidth:32,src:''}; candidates.push(candidate);return candidate as unknown as HTMLImageElement; }); document.head.innerHTML=''; }); afterEach(()=>{act(()=>root.unmount());container.remove();imageMock.mockRestore();jest.useRealTimers();}); test('an earlier icon load cannot overwrite the next application identity',()=>{ const screen=render(); const lateLoad=candidates[candidates.length-1].onload!; screen.rerender(); act(()=>lateLoad()); expect(document.title).toBe('Second app · Conductor'); expect(favicon().getAttribute('href')).toBe('/favicon.svg'); }); test('signing out clears app identity even if its icon finishes loading afterward',()=>{ const screen=render(); const lateLoad=candidates[candidates.length-1].onload!; auth.mockReturnValue({user:null,loading:false,setupRequired:false}); screen.rerender(); act(()=>lateLoad()); expect(document.title).toBe('Sign in · Conductor'); expect(favicon().getAttribute('href')).toBe('/favicon.svg'); }); test('failed and timed-out icons retain a working default',()=>{ const screen=render(); act(()=>candidates[candidates.length-1].onerror!()); expect(favicon().getAttribute('href')).toBe('/favicon.svg'); screen.rerender(); const lateLoad=candidates[candidates.length-1].onload!; act(()=>{jest.advanceTimersByTime(5001);lateLoad();}); expect(document.title).toBe('Slow icon · Conductor'); expect(favicon().getAttribute('href')).toBe('/favicon.svg'); });