Skip to content

Commit

Permalink
mock the audioplayer module and add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
jodeleeuw committed Nov 8, 2023
1 parent f158774 commit d296962
Show file tree
Hide file tree
Showing 2 changed files with 161 additions and 3 deletions.
38 changes: 38 additions & 0 deletions packages/jspsych/src/modules/plugin-api/__mocks__/AudioPlayer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { AudioPlayerOptions } from "../AudioPlayer";

const actual = jest.requireActual("../AudioPlayer");

export const mockStop = jest.fn();

export const AudioPlayer = jest
.fn()
.mockImplementation((src: string, options: AudioPlayerOptions = { useWebAudio: false }) => {
let eventHandlers = {};

const mockInstance = Object.create(actual.AudioPlayer.prototype);

return Object.assign(mockInstance, {
load: jest.fn(),
play: jest.fn(() => {
setTimeout(() => {
if (eventHandlers["ended"]) {
for (const handler of eventHandlers["ended"]) {
handler();
}
}
}, 1000);
}),
stop: mockStop,
addEventListener: jest.fn((event, handler) => {
if (!eventHandlers[event]) {
eventHandlers[event] = [];
}
eventHandlers[event].push(handler);
}),
removeEventListener: jest.fn((event, handler) => {
if (eventHandlers[event] === handler) {
eventHandlers[event] = eventHandlers[event].filter((h) => h !== handler);
}
}),
});
});
126 changes: 123 additions & 3 deletions packages/plugin-audio-keyboard-response/src/index.spec.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,131 @@
import { pressKey, simulateTimeline, startTimeline } from "@jspsych/test-utils";
jest.mock("../../jspsych/src/modules/plugin-api/AudioPlayer");

import { flushPromises, pressKey, simulateTimeline, startTimeline } from "@jspsych/test-utils";
import { initJsPsych } from "jspsych";

//@ts-expect-error mock
import { mockStop } from "../../jspsych/src/modules/plugin-api/AudioPlayer";
import audioKeyboardResponse from ".";

jest.useFakeTimers();

beforeEach(() => {
jest.clearAllMocks();
});

describe("audio-keyboard-response", () => {
// this relies on AudioContext, which we haven't mocked yet
it.skip("works with all defaults", async () => {
const { expectFinished, expectRunning } = await startTimeline([
{
type: audioKeyboardResponse,
stimulus: "foo.mp3",
},
]);

expectRunning();

pressKey("a");

expectFinished();

await flushPromises();
});

it("works with use_webaudio:false", async () => {
const jsPsych = initJsPsych({ use_webaudio: false });

const { expectFinished, expectRunning } = await startTimeline(
[
{
type: audioKeyboardResponse,
stimulus: "foo.mp3",
},
],
jsPsych
);

await expectRunning();
pressKey("a");
await expectFinished();
});

it("ends when trial_ends_after_audio is true and audio finishes", async () => {
const jsPsych = initJsPsych({ use_webaudio: false });

const { expectFinished, expectRunning } = await startTimeline(
[
{
type: audioKeyboardResponse,
stimulus: "foo.mp3",
trial_ends_after_audio: true,
},
],
jsPsych
);

await expectRunning();

jest.runAllTimers();

await expectFinished();
});

it("prevents responses when response_allowed_while_playing is false", async () => {
const jsPsych = initJsPsych({ use_webaudio: false });

const { expectFinished, expectRunning } = await startTimeline(
[
{
type: audioKeyboardResponse,
stimulus: "foo.mp3",
response_allowed_while_playing: false,
},
],
jsPsych
);

await expectRunning();

pressKey("a");

await expectRunning();

jest.runAllTimers();

await expectRunning();

pressKey("a");

await expectFinished();
});

it("ends when trial_duration is shorter than the audio duration, stopping the audio", async () => {
const jsPsych = initJsPsych({ use_webaudio: false });

const { expectFinished, expectRunning } = await startTimeline(
[
{
type: audioKeyboardResponse,
stimulus: "foo.mp3",
trial_duration: 500,
},
],
jsPsych
);

await expectRunning();

expect(mockStop).not.toHaveBeenCalled();

jest.advanceTimersByTime(500);

expect(mockStop).toHaveBeenCalled();

await expectFinished();
});
});

describe("audio-keyboard-response simulation", () => {
test("data mode works", async () => {
const timeline = [
Expand All @@ -22,8 +143,7 @@ describe("audio-keyboard-response simulation", () => {
expect(typeof getData().values()[0].response).toBe("string");
});

// can't run this until we mock Audio elements.
test.skip("visual mode works", async () => {
test("visual mode works", async () => {
const jsPsych = initJsPsych({ use_webaudio: false });

const timeline = [
Expand Down

0 comments on commit d296962

Please sign in to comment.