chore: Upgrade to Vitest 4 and regroup tests for performance (#2618)
This commit is contained in:
@@ -29,9 +29,13 @@ import {
|
||||
|
||||
// Replace Ringtone with a fresh `mock<Ringtone>()` per construction so each
|
||||
// CallManager gets an isolated, type-safe ringtone we can assert on. The
|
||||
// real Ringtone creates an AudioContext, which we never want in tests.
|
||||
// real Ringtone creates an AudioContext, which we never want in tests. The
|
||||
// implementation must be callable with `new`, so it cannot be an arrow
|
||||
// function.
|
||||
vi.mock('../../../src/card-controller/call/ringtone', () => ({
|
||||
Ringtone: vi.fn().mockImplementation(() => mock<Ringtone>()),
|
||||
Ringtone: vi.fn().mockImplementation(function () {
|
||||
return mock<Ringtone>();
|
||||
}),
|
||||
}));
|
||||
|
||||
// Each test creates a new CallManager which constructs a new Ringtone, so the
|
||||
|
||||
@@ -12,20 +12,32 @@ import type { RingtoneConfig } from '../../../src/config/schema/live';
|
||||
// Each tone constructor returns a fresh `mock<>()` per `new` call; the mock
|
||||
// implementation persists across `vi.clearAllMocks()` (which only clears call
|
||||
// records, not implementations) so tests don't need per-test re-installation.
|
||||
// The implementations must be callable with `new`, so they cannot be arrow
|
||||
// functions.
|
||||
vi.mock('../../../src/card-controller/call/tones/chime', () => ({
|
||||
ChimeTone: vi.fn().mockImplementation(() => mock<ChimeTone>()),
|
||||
ChimeTone: vi.fn().mockImplementation(function () {
|
||||
return mock<ChimeTone>();
|
||||
}),
|
||||
}));
|
||||
vi.mock('../../../src/card-controller/call/tones/westminster', () => ({
|
||||
WestminsterTone: vi.fn().mockImplementation(() => mock<WestminsterTone>()),
|
||||
WestminsterTone: vi.fn().mockImplementation(function () {
|
||||
return mock<WestminsterTone>();
|
||||
}),
|
||||
}));
|
||||
vi.mock('../../../src/card-controller/call/tones/arpeggio', () => ({
|
||||
ArpeggioTone: vi.fn().mockImplementation(() => mock<ArpeggioTone>()),
|
||||
ArpeggioTone: vi.fn().mockImplementation(function () {
|
||||
return mock<ArpeggioTone>();
|
||||
}),
|
||||
}));
|
||||
vi.mock('../../../src/card-controller/call/tones/melody', () => ({
|
||||
MelodyTone: vi.fn().mockImplementation(() => mock<MelodyTone>()),
|
||||
MelodyTone: vi.fn().mockImplementation(function () {
|
||||
return mock<MelodyTone>();
|
||||
}),
|
||||
}));
|
||||
vi.mock('../../../src/card-controller/call/tones/custom', () => ({
|
||||
CustomTone: vi.fn().mockImplementation(() => mock<CustomTone>()),
|
||||
CustomTone: vi.fn().mockImplementation(function () {
|
||||
return mock<CustomTone>();
|
||||
}),
|
||||
}));
|
||||
|
||||
// Returns the most recently constructed instance of a mocked class.
|
||||
@@ -187,7 +199,7 @@ describe('lock', () => {
|
||||
describe('natural finish', () => {
|
||||
it('should release the lock when the tone fires its finished handler', () => {
|
||||
let finishedHandler: (() => void) | undefined;
|
||||
vi.mocked(ChimeTone).mockImplementationOnce(() => {
|
||||
vi.mocked(ChimeTone).mockImplementationOnce(function () {
|
||||
const tone = mock<ChimeTone>();
|
||||
vi.mocked(tone.start).mockImplementation((handler) => {
|
||||
finishedHandler = handler;
|
||||
|
||||
@@ -8,7 +8,7 @@ interface AudioMocks {
|
||||
// and pushed here in construction order, so tests can dispatch real events
|
||||
// and read real properties (`loop`, `currentTime`, etc.) on the instances.
|
||||
instances: HTMLAudioElement[];
|
||||
ctor: Mock<[string?], HTMLAudioElement>;
|
||||
ctor: Mock<(url?: string) => HTMLAudioElement>;
|
||||
}
|
||||
|
||||
// Uses real jsdom HTMLAudioElement instances and only stubs the parts jsdom
|
||||
@@ -33,7 +33,10 @@ const useAudioElementMocks = (): AudioMocks => {
|
||||
vi.spyOn(HTMLMediaElement.prototype, 'pause').mockImplementation(() => {});
|
||||
|
||||
const RealAudio = window.Audio;
|
||||
handle.ctor = vi.fn((url?: string) => {
|
||||
|
||||
// The source calls `new Audio(...)`, and a mock implementation must be
|
||||
// callable with `new`, so it cannot be an arrow function.
|
||||
handle.ctor = vi.fn(function (url?: string) {
|
||||
const audio = new RealAudio(url);
|
||||
handle.instances.push(audio);
|
||||
return audio;
|
||||
|
||||
@@ -10,7 +10,7 @@ import { mock, type MockProxy } from 'vitest-mock-extended';
|
||||
// over the same observable state.
|
||||
interface AudioMocks {
|
||||
audioContext: MockProxy<AudioContext>;
|
||||
audioContextCtor: Mock<[], MockProxy<AudioContext>>;
|
||||
audioContextCtor: Mock<() => MockProxy<AudioContext>>;
|
||||
|
||||
// Filled in the order `createOscillator()` / `createGain()` were called.
|
||||
oscillators: MockProxy<OscillatorNode>[];
|
||||
@@ -73,7 +73,11 @@ export const useAudioMocks = (): AudioMocks => {
|
||||
configurable: true,
|
||||
});
|
||||
|
||||
audio.audioContextCtor = vi.fn(() => audio.audioContext);
|
||||
// The source calls `new AudioContext()`, and a mock implementation must be
|
||||
// callable with `new`, so it cannot be an arrow function.
|
||||
audio.audioContextCtor = vi.fn(function () {
|
||||
return audio.audioContext;
|
||||
});
|
||||
vi.stubGlobal('AudioContext', audio.audioContextCtor);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user