diff --git a/tests/plugins/plugin-preload.test.js b/tests/plugins/plugin-preload.test.js index a313a35d..dec6ebf7 100644 --- a/tests/plugins/plugin-preload.test.js +++ b/tests/plugins/plugin-preload.test.js @@ -7,367 +7,817 @@ describe('preload plugin', function () { require(root + 'plugins/jspsych-preload.js'); }); + afterEach(function() { + jest.clearAllMocks(); + }) + test('loads correctly', function () { expect(typeof window.jsPsych.plugins['preload']).not.toBe('undefined'); }); - test('auto_preload method works with simple timeline', function () { + describe('auto_preload', function() { - require(root + 'plugins/jspsych-image-keyboard-response.js'); + test('auto_preload method works with simple timeline and image stimulus', function () { - jsPsych.pluginAPI.preloadImages = jest.fn((x, cb) => { cb(); }); - jsPsych.pluginAPI.preloadAudio = jest.fn((x, cb) => { cb(); }); - jsPsych.pluginAPI.preloadVideo = jest.fn((x, cb) => { cb(); }); + require(root + 'plugins/jspsych-image-keyboard-response.js'); - var preload = { - type: 'preload', - auto_preload: true - } + jsPsych.pluginAPI.preloadImages = jest.fn((x, cb) => { cb(); }); - var trial = { - type: 'image-keyboard-response', - stimulus: 'img/foo.png', - render_on_canvas: false - } + var preload = { + type: 'preload', + auto_preload: true + } - jsPsych.init({ - timeline: [preload, trial] + var trial = { + type: 'image-keyboard-response', + stimulus: 'img/foo.png', + render_on_canvas: false + } + + jsPsych.init({ + timeline: [preload, trial] + }); + + expect(jsPsych.pluginAPI.preloadImages.mock.calls[0][0]).toStrictEqual(['img/foo.png']); + }); - - expect(jsPsych.pluginAPI.preloadImages.mock.calls[0][0]).toStrictEqual(['img/foo.png']); - }); - test('auto_preload method works with nested timeline', function () { + test('auto_preload method works with simple timeline and audio stimulus', function () { - require(root + 'plugins/jspsych-image-keyboard-response.js'); + require(root + 'plugins/jspsych-audio-keyboard-response.js'); - jsPsych.pluginAPI.preloadImages = jest.fn((x, cb) => { cb(); }); - jsPsych.pluginAPI.preloadAudio = jest.fn((x, cb) => { cb(); }); - jsPsych.pluginAPI.preloadVideo = jest.fn((x, cb) => { cb(); }); + jsPsych.pluginAPI.preloadAudio = jest.fn((x, cb) => { cb(); }); - var preload = { - type: 'preload', - auto_preload: true - } + var preload = { + type: 'preload', + auto_preload: true + } - var trial = { - type: 'image-keyboard-response', - render_on_canvas: false, - timeline: [ - {stimulus: 'img/foo.png'} - ] - } + var trial = { + type: 'audio-keyboard-response', + stimulus: 'sound/foo.mp3', + } - jsPsych.init({ - timeline: [preload, trial] + jsPsych.init({ + timeline: [preload, trial] + }); + + expect(jsPsych.pluginAPI.preloadAudio.mock.calls[0][0]).toStrictEqual(['sound/foo.mp3']); + }); - - expect(jsPsych.pluginAPI.preloadImages.mock.calls[0][0]).toStrictEqual(['img/foo.png']); - }); - test('auto_preload method works with looping timeline', function () { + test('auto_preload method works with simple timeline and video stimulus', function () { - require(root + 'plugins/jspsych-image-keyboard-response.js'); + require(root + 'plugins/jspsych-video-keyboard-response.js'); - jsPsych.pluginAPI.preloadImages = jest.fn((x, cb) => { cb(); }); - jsPsych.pluginAPI.preloadAudio = jest.fn((x, cb) => { cb(); }); - jsPsych.pluginAPI.preloadVideo = jest.fn((x, cb) => { cb(); }); + jsPsych.pluginAPI.preloadVideo = jest.fn((x, cb) => { cb(); }); - var preload = { - type: 'preload', - auto_preload: true - } + var preload = { + type: 'preload', + auto_preload: true + } - var trial = { - type: 'image-keyboard-response', - stimulus: 'img/foo.png', - render_on_canvas: false - } + var trial = { + type: 'video-keyboard-response', + stimulus: 'video/foo.mp4' + } - var count = 0; - var loop = { - timeline: [trial], - loop_function: function() { - if (count == 0) { - return true; - } else { - return false; + jsPsych.init({ + timeline: [preload, trial] + }); + + expect(jsPsych.pluginAPI.preloadVideo.mock.calls[0][0]).toStrictEqual(['video/foo.mp4']); + + }); + + test('auto_preload method works with nested timeline', function () { + + require(root + 'plugins/jspsych-image-keyboard-response.js'); + + jsPsych.pluginAPI.preloadImages = jest.fn((x, cb) => { cb(); }); + + var preload = { + type: 'preload', + auto_preload: true + } + + var trial = { + type: 'image-keyboard-response', + render_on_canvas: false, + timeline: [ + {stimulus: 'img/foo.png'} + ] + } + + jsPsych.init({ + timeline: [preload, trial] + }); + + expect(jsPsych.pluginAPI.preloadImages.mock.calls[0][0]).toStrictEqual(['img/foo.png']); + + }); + + test('auto_preload method works with looping timeline', function () { + + require(root + 'plugins/jspsych-image-keyboard-response.js'); + + jsPsych.pluginAPI.preloadImages = jest.fn((x, cb) => { cb(); }); + + var preload = { + type: 'preload', + auto_preload: true + } + + var trial = { + type: 'image-keyboard-response', + stimulus: 'img/foo.png', + render_on_canvas: false + } + + var count = 0; + var loop = { + timeline: [trial], + loop_function: function() { + if (count == 0) { + return true; + } else { + return false; + } } } - } - jsPsych.init({ - timeline: [preload, loop] + jsPsych.init({ + timeline: [preload, loop] + }); + + expect(jsPsych.pluginAPI.preloadImages.mock.calls[0][0]).toStrictEqual(['img/foo.png']); + }); - - expect(jsPsych.pluginAPI.preloadImages.mock.calls[0][0]).toStrictEqual(['img/foo.png']); - }); - test('auto_preload method works with conditional timeline', function () { + test('auto_preload method works with conditional timeline', function () { - require(root + 'plugins/jspsych-image-keyboard-response.js'); + require(root + 'plugins/jspsych-image-keyboard-response.js'); - jsPsych.pluginAPI.preloadImages = jest.fn((x, cb) => { cb(); }); - jsPsych.pluginAPI.preloadAudio = jest.fn((x, cb) => { cb(); }); - jsPsych.pluginAPI.preloadVideo = jest.fn((x, cb) => { cb(); }); + jsPsych.pluginAPI.preloadImages = jest.fn((x, cb) => { cb(); }); - var preload = { - type: 'preload', - auto_preload: true - } + var preload = { + type: 'preload', + auto_preload: true + } - var trial = { - type: 'image-keyboard-response', - stimulus: 'img/foo.png', - render_on_canvas: false - } + var trial = { + type: 'image-keyboard-response', + stimulus: 'img/foo.png', + render_on_canvas: false + } - var count = 0; - var conditional = { - timeline: [trial], - conditional_function: function() { - if (count == 0) { - return true; - } else { - return false; + var count = 0; + var conditional = { + timeline: [trial], + conditional_function: function() { + if (count == 0) { + return true; + } else { + return false; + } } } - } - jsPsych.init({ - timeline: [preload, conditional] + jsPsych.init({ + timeline: [preload, conditional] + }); + + expect(jsPsych.pluginAPI.preloadImages.mock.calls[0][0]).toStrictEqual(['img/foo.png']); + }); - - expect(jsPsych.pluginAPI.preloadImages.mock.calls[0][0]).toStrictEqual(['img/foo.png']); + + test('auto_preload method works with timeline variables when stim is statically defined in trial object', function () { + + require(root + 'plugins/jspsych-image-keyboard-response.js'); + + jsPsych.pluginAPI.preloadImages = jest.fn((x, cb) => { cb(); }); + + var preload = { + type: 'preload', + auto_preload: true + } + + var trial = { + type: 'image-keyboard-response', + stimulus: 'img/foo.png', + render_on_canvas: false, + data: jsPsych.timelineVariable('data') + } + + var trial_procedure = { + timeline: [trial], + timeline_variables: [ + {data: {trial: 1}}, + {data: {trial: 2}}, + {data: {trial: 3}} + ] + } + + jsPsych.init({ + timeline: [preload, trial_procedure] + }); + + expect(jsPsych.pluginAPI.preloadImages.mock.calls[0][0]).toStrictEqual(['img/foo.png']); + + }); + }); - test('auto_preload method works with timeline variables when stim is statically defined in trial object', function () { + describe('trials parameter', function() { - require(root + 'plugins/jspsych-image-keyboard-response.js'); + test('trials parameter works with simple timeline', function () { - jsPsych.pluginAPI.preloadImages = jest.fn((x, cb) => { cb(); }); - jsPsych.pluginAPI.preloadAudio = jest.fn((x, cb) => { cb(); }); - jsPsych.pluginAPI.preloadVideo = jest.fn((x, cb) => { cb(); }); + require(root + 'plugins/jspsych-image-keyboard-response.js'); - var preload = { - type: 'preload', - auto_preload: true - } + jsPsych.pluginAPI.preloadImages = jest.fn((x, cb) => { cb(); }); - var trial = { - type: 'image-keyboard-response', - stimulus: 'img/foo.png', - render_on_canvas: false, - data: jsPsych.timelineVariable('data') - } + var trial = { + type: 'image-keyboard-response', + stimulus: 'img/foo.png', + render_on_canvas: false + } - var trial_procedure = { - timeline: [trial], - timeline_variables: [ - {data: {trial: 1}}, - {data: {trial: 2}}, - {data: {trial: 3}} - ] - } + var preload = { + type: 'preload', + trials: [trial] + } - jsPsych.init({ - timeline: [preload, trial_procedure] + jsPsych.init({ + timeline: [preload] + }); + + expect(jsPsych.pluginAPI.preloadImages.mock.calls[0][0]).toStrictEqual(['img/foo.png']); + }); - - expect(jsPsych.pluginAPI.preloadImages.mock.calls[0][0]).toStrictEqual(['img/foo.png']); - }); - test('trials parameter works with simple timeline', function () { + test('trials parameter works with looping timeline', function () { - require(root + 'plugins/jspsych-image-keyboard-response.js'); + require(root + 'plugins/jspsych-image-keyboard-response.js'); - jsPsych.pluginAPI.preloadImages = jest.fn((x, cb) => { cb(); }); - jsPsych.pluginAPI.preloadAudio = jest.fn((x, cb) => { cb(); }); - jsPsych.pluginAPI.preloadVideo = jest.fn((x, cb) => { cb(); }); + jsPsych.pluginAPI.preloadImages = jest.fn((x, cb) => { cb(); }); - var trial = { - type: 'image-keyboard-response', - stimulus: 'img/foo.png', - render_on_canvas: false - } + var trial = { + type: 'image-keyboard-response', + stimulus: 'img/foo.png', + render_on_canvas: false + } - var preload = { - type: 'preload', - trials: [trial] - } - - jsPsych.init({ - timeline: [preload] - }); - - expect(jsPsych.pluginAPI.preloadImages.mock.calls[0][0]).toStrictEqual(['img/foo.png']); - }); - - test('trials parameter works with looping timeline', function () { - - require(root + 'plugins/jspsych-image-keyboard-response.js'); - - jsPsych.pluginAPI.preloadImages = jest.fn((x, cb) => { cb(); }); - jsPsych.pluginAPI.preloadAudio = jest.fn((x, cb) => { cb(); }); - jsPsych.pluginAPI.preloadVideo = jest.fn((x, cb) => { cb(); }); - - var trial = { - type: 'image-keyboard-response', - stimulus: 'img/foo.png', - render_on_canvas: false - } - - var count = 0; - var loop = { - timeline: [trial], - loop_function: function() { - if (count == 0) { - return true; - } else { - return false; + var count = 0; + var loop = { + timeline: [trial], + loop_function: function() { + if (count == 0) { + return true; + } else { + return false; + } } } - } - var preload = { - type: 'preload', - trials: [loop] - } + var preload = { + type: 'preload', + trials: [loop] + } - jsPsych.init({ - timeline: [preload] + jsPsych.init({ + timeline: [preload] + }); + + expect(jsPsych.pluginAPI.preloadImages.mock.calls[0][0]).toStrictEqual(['img/foo.png']); + }); - - expect(jsPsych.pluginAPI.preloadImages.mock.calls[0][0]).toStrictEqual(['img/foo.png']); - }); - test('trials parameter works with conditional timeline', function () { + test('trials parameter works with conditional timeline', function () { - require(root + 'plugins/jspsych-image-keyboard-response.js'); + require(root + 'plugins/jspsych-image-keyboard-response.js'); - jsPsych.pluginAPI.preloadImages = jest.fn((x, cb) => { cb(); }); - jsPsych.pluginAPI.preloadAudio = jest.fn((x, cb) => { cb(); }); - jsPsych.pluginAPI.preloadVideo = jest.fn((x, cb) => { cb(); }); + jsPsych.pluginAPI.preloadImages = jest.fn((x, cb) => { cb(); }); - var trial = { - type: 'image-keyboard-response', - stimulus: 'img/foo.png', - render_on_canvas: false - } + var trial = { + type: 'image-keyboard-response', + stimulus: 'img/foo.png', + render_on_canvas: false + } - var count = 0; - var conditional = { - timeline: [trial], - conditional_function: function() { - if (count == 0) { - return true; - } else { - return false; + var count = 0; + var conditional = { + timeline: [trial], + conditional_function: function() { + if (count == 0) { + return true; + } else { + return false; + } } } - } - var preload = { - type: 'preload', - trials: [conditional] - } + var preload = { + type: 'preload', + trials: [conditional] + } - jsPsych.init({ - timeline: [preload] + jsPsych.init({ + timeline: [preload] + }); + + expect(jsPsych.pluginAPI.preloadImages.mock.calls[0][0]).toStrictEqual(['img/foo.png']); + }); - - expect(jsPsych.pluginAPI.preloadImages.mock.calls[0][0]).toStrictEqual(['img/foo.png']); - }); - test('trials parameter works with timeline variables when stim is statically defined in trial object', function () { + test('trials parameter works with timeline variables when stim is statically defined in trial object', function () { - require(root + 'plugins/jspsych-image-keyboard-response.js'); + require(root + 'plugins/jspsych-image-keyboard-response.js'); - jsPsych.pluginAPI.preloadImages = jest.fn((x, cb) => { cb(); }); - jsPsych.pluginAPI.preloadAudio = jest.fn((x, cb) => { cb(); }); - jsPsych.pluginAPI.preloadVideo = jest.fn((x, cb) => { cb(); }); + jsPsych.pluginAPI.preloadImages = jest.fn((x, cb) => { cb(); }); - var trial = { - type: 'image-keyboard-response', - stimulus: 'img/foo.png', - render_on_canvas: false, - data: jsPsych.timelineVariable('data') - } + var trial = { + type: 'image-keyboard-response', + stimulus: 'img/foo.png', + render_on_canvas: false, + data: jsPsych.timelineVariable('data') + } - var trial_procedure = { - timeline: [trial], - timeline_variables: [ - {data: {trial: 1}}, - {data: {trial: 2}}, - {data: {trial: 3}} - ] - } + var trial_procedure = { + timeline: [trial], + timeline_variables: [ + {data: {trial: 1}}, + {data: {trial: 2}}, + {data: {trial: 3}} + ] + } - var preload = { - type: 'preload', - trials: [trial_procedure] - } + var preload = { + type: 'preload', + trials: [trial_procedure] + } - jsPsych.init({ - timeline: [preload] + jsPsych.init({ + timeline: [preload] + }); + + expect(jsPsych.pluginAPI.preloadImages.mock.calls[0][0]).toStrictEqual(['img/foo.png']); + }); + + }); + + describe('calls to pluginAPI preload functions', function() { + + test('auto_preload, trials, and manual preload array parameters can be used together', function () { + require(root + 'plugins/jspsych-image-keyboard-response.js'); + + jsPsych.pluginAPI.preloadImages = jest.fn((x, cb) => { cb(); }); + + var trial_1 = { + type: 'image-keyboard-response', + stimulus: 'img/foo.png', + render_on_canvas: false + } + + var trial_2 = { + type: 'image-keyboard-response', + stimulus: 'img/bar.png', + render_on_canvas: false + } + + var preload = { + type: 'preload', + auto_preload: true, + trials: [trial_2], + images: ['img/fizz.png'] + } + + jsPsych.init({ + timeline: [preload, trial_1] + }); + + expect(jsPsych.pluginAPI.preloadImages.mock.calls.length).toBe(1); + expect(jsPsych.pluginAPI.preloadImages.mock.calls[0][0].length).toBe(3); + expect(jsPsych.pluginAPI.preloadImages.mock.calls[0][0]).toContain('img/foo.png'); + expect(jsPsych.pluginAPI.preloadImages.mock.calls[0][0]).toContain('img/bar.png'); + expect(jsPsych.pluginAPI.preloadImages.mock.calls[0][0]).toContain('img/fizz.png'); + + }); + + test('plugin only attempts to load duplicate files once', function () { + require(root + 'plugins/jspsych-image-keyboard-response.js'); + + jsPsych.pluginAPI.preloadImages = jest.fn((x, cb) => { cb(); }); + + var trial_1 = { + type: 'image-keyboard-response', + stimulus: 'img/foo.png', + render_on_canvas: false + } + + var trial_2 = { + type: 'image-keyboard-response', + stimulus: 'img/foo.png', + render_on_canvas: false + } + + var preload = { + type: 'preload', + trials: [trial_2], + images: ['img/foo.png'] + } + + jsPsych.init({ + timeline: [preload, trial_1] + }); + + expect(jsPsych.pluginAPI.preloadImages.mock.calls.length).toBe(1); + expect(jsPsych.pluginAPI.preloadImages.mock.calls[0][0]).toStrictEqual(['img/foo.png']); + + }); + + }); + + describe('continue_after_error and error messages', function() { + + test('experiment continues when image loads successfully', function() { + + require(root + 'plugins/jspsych-image-keyboard-response.js'); + + var preload = { + type: 'preload', + auto_preload: true, + error_message: 'foo', + max_load_time: 100 + } + + var trial = { + type: 'image-keyboard-response', + stimulus: '../media/blue.png', + render_on_canvas: false + } + + jsPsych.init({ + timeline: [preload, trial] + }); + + setTimeout(function() { + expect(jsPsych.getDisplayElement().innerHTML).toMatch('