From 1324361835de41a176757c3d9d0038b740cb4c76 Mon Sep 17 00:00:00 2001 From: Josh de Leeuw Date: Mon, 6 Mar 2023 10:09:24 -0500 Subject: [PATCH] Fix defaults for COMPLEX parameter types --- .changeset/odd-toes-walk.md | 5 ++ packages/jspsych/src/JsPsych.ts | 23 ++++------ .../tests/core/default-parameters.test.ts | 20 ++++++++ .../jspsych/tests/core/test-complex-plugin.ts | 46 +++++++++++++++++++ 4 files changed, 81 insertions(+), 13 deletions(-) create mode 100644 .changeset/odd-toes-walk.md create mode 100644 packages/jspsych/tests/core/test-complex-plugin.ts diff --git a/.changeset/odd-toes-walk.md b/.changeset/odd-toes-walk.md new file mode 100644 index 00000000..d50bc546 --- /dev/null +++ b/.changeset/odd-toes-walk.md @@ -0,0 +1,5 @@ +--- +"jspsych": patch +--- + +This fixes an issue when a plugin has a COMPLEX parameter and there is a default value specified at the root level of the parameter, rather than for each individual nested parameter (#2972). diff --git a/packages/jspsych/src/JsPsych.ts b/packages/jspsych/src/JsPsych.ts index 6dff7ee0..7463750d 100644 --- a/packages/jspsych/src/JsPsych.ts +++ b/packages/jspsych/src/JsPsych.ts @@ -781,7 +781,14 @@ export class JsPsych { for (const param in trial.type.info.parameters) { // check if parameter is complex with nested defaults if (trial.type.info.parameters[param].type === ParameterType.COMPLEX) { - if (trial.type.info.parameters[param].array === true) { + // check if parameter is undefined and has a default value + if (typeof trial[param] === "undefined" && trial.type.info.parameters[param].default) { + trial[param] = trial.type.info.parameters[param].default; + } + // if parameter is an array, iterate over each entry after confirming that there are + // entries to iterate over. this is common when some parameters in a COMPLEX type have + // default values and others do not. + if (trial.type.info.parameters[param].array === true && Array.isArray(trial[param])) { // iterate over each entry in the array trial[param].forEach(function (ip, i) { // check each parameter in the plugin description @@ -789,13 +796,7 @@ export class JsPsych { if (typeof trial[param][i][p] === "undefined" || trial[param][i][p] === null) { if (typeof trial.type.info.parameters[param].nested[p].default === "undefined") { console.error( - "You must specify a value for the " + - p + - " parameter (nested in the " + - param + - " parameter) in the " + - trial.type + - " plugin." + `You must specify a value for the ${p} parameter (nested in the ${param} parameter) in the ${trial.type.info.name} plugin.` ); } else { trial[param][i][p] = trial.type.info.parameters[param].nested[p].default; @@ -809,11 +810,7 @@ export class JsPsych { else if (typeof trial[param] === "undefined" || trial[param] === null) { if (typeof trial.type.info.parameters[param].default === "undefined") { console.error( - "You must specify a value for the " + - param + - " parameter in the " + - trial.type.info.name + - " plugin." + `You must specify a value for the ${param} parameter in the ${trial.type.info.name} plugin.` ); } else { trial[param] = trial.type.info.parameters[param].default; diff --git a/packages/jspsych/tests/core/default-parameters.test.ts b/packages/jspsych/tests/core/default-parameters.test.ts index 23fd22c7..6c5290e5 100644 --- a/packages/jspsych/tests/core/default-parameters.test.ts +++ b/packages/jspsych/tests/core/default-parameters.test.ts @@ -1,6 +1,8 @@ import surveyText from "@jspsych/plugin-survey-text"; import { startTimeline } from "@jspsych/test-utils"; +import jsPsychTestComplex from "./test-complex-plugin"; + describe("nested defaults", () => { test("work in basic situation", async () => { const { displayElement } = await startTimeline([ @@ -48,3 +50,21 @@ describe("nested defaults", () => { spy.mockRestore(); }); }); + +describe("defaults for COMPLEX parameters", () => { + test("default at the top level should work", async () => { + const { expectFinished, getData } = await startTimeline([ + { + type: jsPsychTestComplex, + }, + ]); + + await expectFinished(); + + expect(getData().values()[0].blocks).toEqual([ + { x: 10, y: 10 }, + { x: 20, y: 20 }, + { x: 30, y: 30 }, + ]); + }); +}); diff --git a/packages/jspsych/tests/core/test-complex-plugin.ts b/packages/jspsych/tests/core/test-complex-plugin.ts new file mode 100644 index 00000000..4cc53a7a --- /dev/null +++ b/packages/jspsych/tests/core/test-complex-plugin.ts @@ -0,0 +1,46 @@ +import { JsPsych, JsPsychPlugin, ParameterType, TrialType } from "jspsych"; + +const info = { + name: "test-complex-plugin", + parameters: { + blocks: { + type: ParameterType.COMPLEX, + array: true, + default: [ + { x: 10, y: 10 }, + { x: 20, y: 20 }, + { x: 30, y: 30 }, + ], + nested: { + x: { + type: ParameterType.INT, + default: undefined, + }, + y: { + type: ParameterType.INT, + default: undefined, + }, + }, + }, + }, +}; + +type Info = typeof info; + +class TestComplexPlugin implements JsPsychPlugin { + static info = info; + + constructor(private jsPsych: JsPsych) {} + + trial(display_element: HTMLElement, trial: TrialType) { + // save data + var trialdata = { + blocks: trial.blocks, + }; + + // next trial + this.jsPsych.finishTrial(trialdata); + } +} + +export default TestComplexPlugin;