import { setImmediate as flushMicroTasks } from "timers"; import { JsPsych } from "../src"; export function dispatchEvent(event: Event) { document.querySelector(".jspsych-display-element").dispatchEvent(event); } export function keyDown(key: string) { dispatchEvent(new KeyboardEvent("keydown", { key })); } export function keyUp(key: string) { dispatchEvent(new KeyboardEvent("keyup", { key })); } export function pressKey(key: string) { keyDown(key); keyUp(key); } export function mouseDownMouseUpTarget(target: Element) { target.dispatchEvent(new MouseEvent("mousedown", { bubbles: true })); target.dispatchEvent(new MouseEvent("mouseup", { bubbles: true })); } export function clickTarget(target: Element) { target.dispatchEvent(new MouseEvent("click", { bubbles: true })); } /** * https://github.com/facebook/jest/issues/2157#issuecomment-279171856 */ export function flushPromises() { return new Promise((resolve) => flushMicroTasks(resolve)); } /** * Runs the given timeline by calling `jsPsych.run()` on the provided JsPsych object. * * @param timeline The timeline that is passed to `jsPsych.run()` * @param jsPsych The jsPsych instance to be used. If left empty, a new instance will be created. If * a settings object is passed instead, the settings will be used to create the jsPsych instance. * * @returns An object containing test helper functions, the jsPsych instance, and the jsPsych * display element */ export async function startTimeline(timeline: any[], jsPsych: JsPsych | any = {}) { const jsPsychInstance = jsPsych instanceof JsPsych ? jsPsych : new JsPsych(jsPsych); let hasFinished = false; const finished = jsPsychInstance.run(timeline).then(() => { hasFinished = true; }); await flushPromises(); const displayElement = jsPsychInstance.getDisplayElement(); return { jsPsych: jsPsychInstance, displayElement, /** Shorthand for `jsPsych.getDisplayElement().innerHTML` */ getHTML: () => displayElement.innerHTML, /** Shorthand for `jsPsych.data.get()` */ getData: () => jsPsychInstance.data.get(), expectFinished: async () => { await flushPromises(); expect(hasFinished).toBe(true); }, expectRunning: async () => { await flushPromises(); expect(hasFinished).toBe(false); }, /** A promise that is resolved when `jsPsych.run()` is done. */ finished, }; }