soulsync/webui/src/platform/shell/bridge.test.ts
Antti Kettunen d0245e3e16
test(webui): share shell bridge test helper
- add a reusable shell bridge factory for legacy shell-backed tests
- trim route and bridge fixtures down to only the overrides they need
2026-05-23 21:23:33 +03:00

94 lines
2.7 KiB
TypeScript

import { beforeEach, describe, expect, it, vi } from 'vitest';
import { createShellBridge } from '@/test/shell-bridge';
import type { ShellProfileContext } from './bridge';
import {
SHELL_PROFILE_CONTEXT_CHANGED_EVENT,
bindWindowWebRouter,
waitForShellContext,
} from './bridge';
describe('waitForShellContext', () => {
beforeEach(() => {
window.SoulSyncWebShellBridge = undefined;
});
it('resolves immediately when the shell already has a profile', async () => {
window.SoulSyncWebShellBridge = createShellBridge();
await expect(waitForShellContext()).resolves.toEqual({
bridge: window.SoulSyncWebShellBridge,
profile: {
profileId: 2,
isAdmin: true,
},
});
});
it('waits for the legacy shell to publish profile context', async () => {
const getCurrentProfileContext = vi.fn<() => ShellProfileContext | null>(() => null);
window.SoulSyncWebShellBridge = createShellBridge({
getCurrentProfileContext,
});
const contextPromise = waitForShellContext();
getCurrentProfileContext.mockReturnValue({ profileId: 5, isAdmin: false });
window.dispatchEvent(new CustomEvent(SHELL_PROFILE_CONTEXT_CHANGED_EVENT));
await expect(contextPromise).resolves.toEqual({
bridge: window.SoulSyncWebShellBridge,
profile: {
profileId: 5,
isAdmin: false,
},
});
});
});
describe('bindWindowWebRouter', () => {
it('navigates artist detail pages with source-aware URLs', async () => {
const navigate = vi.fn().mockResolvedValue(undefined);
bindWindowWebRouter({ navigate } as never);
await window.SoulSyncWebRouter?.navigateToPage('artist-detail', {
artistId: '2YZyLoL8N0Wb9xBt1NhZWg',
artistSource: 'spotify',
});
expect(navigate).toHaveBeenCalledWith({
href: '/artist-detail/spotify/2YZyLoL8N0Wb9xBt1NhZWg',
replace: false,
});
});
it('falls back artist detail URLs to library source when none is supplied', async () => {
const navigate = vi.fn().mockResolvedValue(undefined);
bindWindowWebRouter({ navigate } as never);
await window.SoulSyncWebRouter?.navigateToPage('artist-detail', {
artistId: '42',
replace: true,
});
expect(navigate).toHaveBeenCalledWith({
href: '/artist-detail/library/42',
replace: true,
});
});
it('refuses artist detail navigation without an artist id', async () => {
const navigate = vi.fn().mockResolvedValue(undefined);
bindWindowWebRouter({ navigate } as never);
await expect(
window.SoulSyncWebRouter?.navigateToPage('artist-detail', {} as never),
).resolves.toBe(false);
expect(navigate).not.toHaveBeenCalled();
});
});