navigatorUiStore.test.ts 9.6 Ko
Télécharger le fichier
/* @vitest-environment jsdom */
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { useNavigatorUiStore } from './navigatorUiStore';
vi.mock('@octane/renderer', async () => {
const actual = await vi.importActual<typeof import('@octane/renderer')>('@octane/renderer');
return {
...actual,
NavigatorSearchCloseComposer: class {
constructor(_code?: string) {}
},
NavigatorSearchOpenComposer: class {
constructor(_code?: string) {}
},
NavigatorCategoryListModeComposer: class {
constructor(_code?: string, _mode?: number) {}
},
NavigatorSettingsSaveComposer: class {
constructor(_x?: number, _y?: number, _w?: number, _h?: number, _open?: boolean, _mode?: number) {}
}
};
});
vi.mock('../../api', async () => {
const actual = await vi.importActual<typeof import('../../api')>('../../api');
return {
...actual,
SendMessageComposer: vi.fn()
};
});
const INITIAL = {
isVisible: false,
isReady: false,
isCreatorOpen: false,
isRoomInfoOpen: false,
isRoomLinkOpen: false,
isOpenSavesSearches: false,
isLoading: false,
needsInit: true,
needsSearch: false,
currentTabCode: '',
currentFilter: '',
searchHistory: [],
searchHistoryOffset: -1
};
describe('useNavigatorUiStore', () => {
beforeEach(() => {
useNavigatorUiStore.setState(INITIAL);
});
it('exposes the documented defaults', () => {
const s = useNavigatorUiStore.getState();
expect(s.isVisible).toBe(false);
expect(s.isReady).toBe(false);
expect(s.isCreatorOpen).toBe(false);
expect(s.isRoomInfoOpen).toBe(false);
expect(s.isRoomLinkOpen).toBe(false);
expect(s.isOpenSavesSearches).toBe(false);
expect(s.isLoading).toBe(false);
expect(s.needsInit).toBe(true);
expect(s.needsSearch).toBe(false);
expect(s.currentTabCode).toBe('');
expect(s.currentFilter).toBe('');
});
describe('show / hide / toggle', () => {
it('show() sets isVisible true and requests a search', () => {
useNavigatorUiStore.getState().show();
expect(useNavigatorUiStore.getState().isVisible).toBe(true);
expect(useNavigatorUiStore.getState().needsSearch).toBe(true);
});
it('hide() sets isVisible false without touching needsSearch', () => {
useNavigatorUiStore.setState({ isVisible: true, needsSearch: false });
useNavigatorUiStore.getState().hide();
expect(useNavigatorUiStore.getState().isVisible).toBe(false);
expect(useNavigatorUiStore.getState().needsSearch).toBe(false);
});
it('toggle() flips visibility and requests a search on show', () => {
useNavigatorUiStore.getState().toggle();
expect(useNavigatorUiStore.getState().isVisible).toBe(true);
expect(useNavigatorUiStore.getState().needsSearch).toBe(true);
useNavigatorUiStore.setState({ needsSearch: false });
useNavigatorUiStore.getState().toggle();
expect(useNavigatorUiStore.getState().isVisible).toBe(false);
expect(useNavigatorUiStore.getState().needsSearch).toBe(false);
});
});
describe('creator panel', () => {
it('openCreator() opens both visible and creator', () => {
useNavigatorUiStore.getState().openCreator();
expect(useNavigatorUiStore.getState().isVisible).toBe(true);
expect(useNavigatorUiStore.getState().isCreatorOpen).toBe(true);
});
it('closeCreator() closes only the creator panel', () => {
useNavigatorUiStore.setState({ isVisible: true, isCreatorOpen: true });
useNavigatorUiStore.getState().closeCreator();
expect(useNavigatorUiStore.getState().isCreatorOpen).toBe(false);
expect(useNavigatorUiStore.getState().isVisible).toBe(true);
});
});
describe('roomInfo / roomLink / savesSearches', () => {
it('setRoomInfoOpen(true) and toggleRoomInfo flip the flag', () => {
useNavigatorUiStore.getState().setRoomInfoOpen(true);
expect(useNavigatorUiStore.getState().isRoomInfoOpen).toBe(true);
useNavigatorUiStore.getState().toggleRoomInfo();
expect(useNavigatorUiStore.getState().isRoomInfoOpen).toBe(false);
});
it('setRoomLinkOpen(true) and toggleRoomLink flip the flag', () => {
useNavigatorUiStore.getState().setRoomLinkOpen(true);
expect(useNavigatorUiStore.getState().isRoomLinkOpen).toBe(true);
useNavigatorUiStore.getState().toggleRoomLink();
expect(useNavigatorUiStore.getState().isRoomLinkOpen).toBe(false);
});
it('toggleSavesSearches() flips the sidebar flag', () => {
useNavigatorUiStore.getState().toggleSavesSearches();
expect(useNavigatorUiStore.getState().isOpenSavesSearches).toBe(true);
useNavigatorUiStore.getState().toggleSavesSearches();
expect(useNavigatorUiStore.getState().isOpenSavesSearches).toBe(false);
});
});
describe('lifecycle flags', () => {
it('setLoading(true) and setLoading(false) toggle isLoading', () => {
useNavigatorUiStore.getState().setLoading(true);
expect(useNavigatorUiStore.getState().isLoading).toBe(true);
useNavigatorUiStore.getState().setLoading(false);
expect(useNavigatorUiStore.getState().isLoading).toBe(false);
});
it('markReady() sets isReady true and is idempotent', () => {
useNavigatorUiStore.getState().markReady();
expect(useNavigatorUiStore.getState().isReady).toBe(true);
useNavigatorUiStore.getState().markReady();
expect(useNavigatorUiStore.getState().isReady).toBe(true);
});
it('markInitDone() flips needsInit to false', () => {
useNavigatorUiStore.getState().markInitDone();
expect(useNavigatorUiStore.getState().needsInit).toBe(false);
});
it('requestSearch() + consumeSearchRequest() are symmetric', () => {
useNavigatorUiStore.getState().requestSearch();
expect(useNavigatorUiStore.getState().needsSearch).toBe(true);
useNavigatorUiStore.getState().consumeSearchRequest();
expect(useNavigatorUiStore.getState().needsSearch).toBe(false);
});
});
describe('tab + filter', () => {
it("setTab('public') sets currentTabCode and clears currentFilter", () => {
useNavigatorUiStore.setState({ currentTabCode: 'events', currentFilter: 'habbo' });
useNavigatorUiStore.getState().setTab('public');
expect(useNavigatorUiStore.getState().currentTabCode).toBe('public');
expect(useNavigatorUiStore.getState().currentFilter).toBe('');
});
it("setFilter('cocco') sets currentFilter without touching tab", () => {
useNavigatorUiStore.getState().setTab('events');
useNavigatorUiStore.getState().setFilter('cocco');
expect(useNavigatorUiStore.getState().currentTabCode).toBe('events');
expect(useNavigatorUiStore.getState().currentFilter).toBe('cocco');
});
it('setTab on same code still resets currentFilter', () => {
useNavigatorUiStore.setState({ currentTabCode: 'public', currentFilter: 'test' });
useNavigatorUiStore.getState().setTab('public');
expect(useNavigatorUiStore.getState().currentTabCode).toBe('public');
expect(useNavigatorUiStore.getState().currentFilter).toBe('');
});
});
describe('search history', () => {
it('goes back and forward through searches without adding entries', () => {
const store = useNavigatorUiStore.getState();
store.setTab('hotel_view');
store.setFilter('tag:pool');
store.setSearch('myworld_view', '');
useNavigatorUiStore.getState().goBack();
expect(useNavigatorUiStore.getState().currentTabCode).toBe('hotel_view');
expect(useNavigatorUiStore.getState().currentFilter).toBe('tag:pool');
useNavigatorUiStore.getState().goBack();
expect(useNavigatorUiStore.getState().currentFilter).toBe('');
useNavigatorUiStore.getState().goForward();
expect(useNavigatorUiStore.getState().currentFilter).toBe('tag:pool');
expect(useNavigatorUiStore.getState().searchHistory).toHaveLength(3);
});
it('drops forward entries when a new search is made after going back', () => {
const store = useNavigatorUiStore.getState();
store.setTab('hotel_view');
store.setTab('myworld_view');
useNavigatorUiStore.getState().goBack();
useNavigatorUiStore.getState().setSearch('hotel_view', 'tag:music');
const { searchHistory, searchHistoryOffset } = useNavigatorUiStore.getState();
expect(searchHistory.map((entry) => entry.filter)).toEqual(['', 'tag:music']);
expect(searchHistoryOffset).toBe(1);
});
it('does not add the same search twice in a row and ignores back at the start', () => {
const store = useNavigatorUiStore.getState();
store.setTab('hotel_view');
store.setTab('hotel_view');
useNavigatorUiStore.getState().goBack();
expect(useNavigatorUiStore.getState().searchHistory).toHaveLength(1);
expect(useNavigatorUiStore.getState().currentTabCode).toBe('hotel_view');
});
});
});
