Files
Portfolio/tests/unit/use-audio-intent.test.ts

67 lines
2.2 KiB
TypeScript

import { defineComponent, h, readonly, shallowRef } from 'vue';
import { mount } from '@vue/test-utils';
import { describe, expect, it, vi } from 'vitest';
import { resolveChapterIntent } from '@/audio/journey-music-state';
import {
useAudioIntent,
type AudioIntentBinding,
} from '@/composables/useAudioIntent';
import type { JourneySectionsBinding } from '@/composables/useJourneySections';
import type { SectionId } from '@/content/types';
import type { NavigationState } from '@/journey/navigation-controller';
import type { JourneySnapshot } from '@/journey/types';
const sectionIds = [
'start', 'profile', 'experience', 'infrastructure',
'selected-builds', 'additional-work', 'toolkit', 'contact',
] as const satisfies readonly SectionId[];
describe('useAudioIntent', () => {
it('seeds the first measured deep-link section before audio activation', () => {
const snapshot = shallowRef<JourneySnapshot>({
scrollY: 7_200,
routeProgress: 1,
direction: 0,
acceleration: 0,
driveSpeed: 0.18,
activeSectionId: 'contact',
chapter: 'destination',
sign: null,
arrived: true,
sectionActivation: {
layoutRevision: 4,
activeHeadingOffsetVh: -0.2,
nextHeadingOffsetVh: null,
},
});
const navigation = shallowRef<NavigationState>({
epoch: 1,
source: 'initial',
phase: 'settled',
destinationId: 'contact',
signDestinationId: null,
});
let frame: ((now: number, value: JourneySnapshot) => boolean) | null = null;
const journey: JourneySectionsBinding = {
snapshot: readonly(snapshot),
requestFrame: vi.fn(),
subscribeFrame(listener) {
frame = listener;
return () => { frame = null; };
},
};
let binding: AudioIntentBinding | null = null;
const wrapper = mount(defineComponent({
setup() {
binding = useAudioIntent({ canonicalIds: sectionIds, journey, navigation });
return () => h('div');
},
}));
expect(frame).not.toBeNull();
frame!(16, snapshot.value);
expect(binding!.chapter.value).toEqual(resolveChapterIntent('contact'));
wrapper.unmount();
});
});