I'm trying to test a custom hook I created that dynamically imports @vimeo/player.
Relevant part of useVideoPlayer- hook:
useEffect(() => {
async function setup() {
const { default: Player } = await import('@vimeo/player');
playerRef.current = new Player(
playerRef.current,
playerConfig,
);
playerRef.current.on('loaded', () => setIsLoading(false));
playerRef.current.getVideoTitle().then((t) => setTitle(t)).catch(handleErrorCallback);
}
if (playerRef?.current) {
setup();
}
return () => playerRef.current.destroy && playerRef.current.destroy();
}, [playerRef]);
This is the test asserting state is set correctly:
jest.mock('@vimeo/player', () => class MockPlayer {
constructor() {
this.events = new Map();
}
on(event, handler) {
this.events[event] = handler;
}
trigger(event) {
this.events[event]();
}
getVideoTitle() {
return Promise.resolve('title.mp4');
}
destroy() {
return jest.fn();
}
});
...
test.each([
['loaded', 'isLoading', true, false],
['bufferstart', 'isBuffering', false, true],
['play', 'isPlaying', false, true],
])('event: %s should set state: %s from %s to %s',
async (event, state, valueBefore, valueAfter) => {
const { result, waitForNextUpdate } = renderHook(useVideoPlayer, {
initialProps: { playerRef: ref, playerConfig },
});
console.log(result.current.playerRef.current);
/*
MockPlayer {
events: Map(0) {
loaded: [Function (anonymous)],
bufferstart: [Function (anonymous)],
bufferend: [Function (anonymous)],
play: [Function (anonymous)],
pause: [Function (anonymous)],
timeupdate: [Function (anonymous)]
}
}
*/
expect(result.current[state]).toEqual(valueBefore);
act(() => {
result.current.playerRef.current.trigger(event);
});
await waitForNextUpdate(); // need both, act and waitForNextUpdate to get rid of warnings
expect(result.current[state]).toEqual(valueAfter);
});
The test succeeds when I import Player non-dynamically, but fail with the dynamic import. What I don't understand is why the methods(on, trigger) are not available on MockPlayer - could someone help me understand? I guess I somehow have to wait until the promise of the dynamic import resolves?
Removing await waitForNextUpdate() and adding await waitForValueToChange(() => result.playerRef.current) fixed the issue.