Skip to content

Commit

Permalink
Changed AudioPlayer to implement interface; fixed build error; rewrot…
Browse files Browse the repository at this point in the history
…e plugins using AudioPlayer and added tests; changed test-utils' clickTarget to respect disabled forms
  • Loading branch information
Bankminer78 committed Jul 15, 2024
1 parent d296962 commit e2a9e6b
Show file tree
Hide file tree
Showing 7 changed files with 628 additions and 376 deletions.
10 changes: 9 additions & 1 deletion packages/jspsych/src/modules/plugin-api/AudioPlayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,15 @@ export interface AudioPlayerOptions {
audioContext?: AudioContext;
}

export class AudioPlayer {
export interface AudioPlayerInterface {
load(): Promise<void>;
play(): void;
stop(): void;
addEventListener(eventName: string, callback: EventListenerOrEventListenerObject): void;
removeEventListener(eventName: string, callback: EventListenerOrEventListenerObject): void;
}

export class AudioPlayer implements AudioPlayerInterface {
private audio: HTMLAudioElement | AudioBufferSourceNode;
private audioContext: AudioContext | null;
private useWebAudio: boolean;
Expand Down
159 changes: 151 additions & 8 deletions packages/plugin-audio-button-response/src/index.spec.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,70 @@
import { clickTarget, simulateTimeline, startTimeline } from "@jspsych/test-utils";
jest.mock("../../jspsych/src/modules/plugin-api/AudioPlayer");

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

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

jest.useFakeTimers();

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

// skip this until we figure out how to mock the audio loading
describe.skip("audio-button-response", () => {
describe("audio-button-response", () => {
it.only("works with all defaults", async () => {
const { expectFinished, expectRunning, displayElement, getHTML } = await startTimeline([
{
type: audioButtonResponse,
choices: ["choice1"],
stimulus: "foo.mp3",
},
]);

expectRunning();

console.log(getHTML());

clickTarget(displayElement.querySelector("button"));

expectFinished();

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

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

await expectRunning();

clickTarget(displayElement.querySelector("button"));

await expectFinished();
});
test("on_load event triggered after page setup complete", async () => {
const onLoadCallback = jest.fn();

const timeline = [
{
type: audioButtonResponse,
stimulus: "mymp3.mp3",
prompt: "foo",
choices: ["choice1"],
on_load: () => {
expect(getHTML()).toContain("foo");

clickTarget(displayElement.querySelector("button"));
onLoadCallback();
},
},
];
Expand All @@ -26,11 +73,107 @@ describe.skip("audio-button-response", () => {
use_webaudio: false,
});

const { getHTML, finished, displayElement } = await startTimeline(timeline, jsPsych);
await startTimeline(timeline, jsPsych);

expect(onLoadCallback).toHaveBeenCalled();
});
it("trial ends when button is clicked", async () => {
const jsPsych = initJsPsych({ use_webaudio: false });

const { expectFinished, expectRunning, displayElement } = await startTimeline(
[
{
type: audioButtonResponse,
stimulus: "foo.mp3",
prompt: "foo",
choices: ["choice1"],
},
],
jsPsych
);

await expectRunning();

expect(getHTML()).not.toContain("foo");
clickTarget(displayElement.querySelector("button"));

await expectFinished();
});

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

await finished;
const { expectFinished, expectRunning } = await startTimeline(
[
{
type: audioButtonResponse,
stimulus: "foo.mp3",
choices: ["choice1"],
trial_duration: 30000,
trial_ends_after_audio: true,
},
],
jsPsych
);

await expectRunning();

jest.runAllTimers();

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: audioButtonResponse,
stimulus: "foo.mp3",
choices: ["choice1"],
trial_duration: 500,
},
],
jsPsych
);

await expectRunning();

expect(mockStop).not.toHaveBeenCalled();

jest.advanceTimersByTime(500);

expect(mockStop).toHaveBeenCalled();

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

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

await expectRunning();

clickTarget(displayElement.querySelector("button"));

await expectRunning();

jest.runAllTimers();

await expectRunning();

clickTarget(displayElement.querySelector("button"));

await expectFinished();
});
});

Expand Down
Loading

0 comments on commit e2a9e6b

Please sign in to comment.