jspsych 8.2.2 → 8.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.browser.js +69 -2
- package/dist/index.browser.js.map +1 -1
- package/dist/index.browser.min.js +6 -6
- package/dist/index.browser.min.js.map +1 -1
- package/dist/index.cjs +68 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +68 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/modules/plugins.ts +1 -0
- package/src/timeline/Trial.spec.ts +105 -1
- package/src/timeline/Trial.ts +78 -0
package/package.json
CHANGED
package/src/modules/plugins.ts
CHANGED
|
@@ -235,7 +235,7 @@ describe("Trial", () => {
|
|
|
235
235
|
});
|
|
236
236
|
|
|
237
237
|
it("respects the `save_trial_parameters` parameter", async () => {
|
|
238
|
-
const consoleSpy = jest.spyOn(console, "warn").mockImplementation();
|
|
238
|
+
const consoleSpy = jest.spyOn(console, "warn").mockImplementation(() => {});
|
|
239
239
|
|
|
240
240
|
TestPlugin.setParameterInfos({
|
|
241
241
|
stringParameter1: { type: ParameterType.STRING },
|
|
@@ -560,6 +560,110 @@ describe("Trial", () => {
|
|
|
560
560
|
});
|
|
561
561
|
});
|
|
562
562
|
|
|
563
|
+
describe("with parameter type mismatches", () => {
|
|
564
|
+
//TODO: redo these to expect errors on v9!
|
|
565
|
+
let consoleSpy: jest.SpyInstance;
|
|
566
|
+
|
|
567
|
+
beforeEach(() => {
|
|
568
|
+
consoleSpy = jest.spyOn(console, "warn").mockImplementation(() => {});
|
|
569
|
+
});
|
|
570
|
+
|
|
571
|
+
afterEach(() => {
|
|
572
|
+
consoleSpy.mockRestore();
|
|
573
|
+
});
|
|
574
|
+
|
|
575
|
+
it("errors on non-boolean values for boolean parameters", async () => {
|
|
576
|
+
TestPlugin.setParameterInfos({
|
|
577
|
+
boolParameter: { type: ParameterType.BOOL },
|
|
578
|
+
});
|
|
579
|
+
|
|
580
|
+
// this should work:
|
|
581
|
+
await createTrial({ type: TestPlugin, boolParameter: true }).run();
|
|
582
|
+
|
|
583
|
+
// this shouldn't:
|
|
584
|
+
await createTrial({ type: TestPlugin, boolParameter: "foo" }).run();
|
|
585
|
+
expect(consoleSpy).toHaveBeenCalledWith(
|
|
586
|
+
'A non-boolean value (`foo`) was provided for the boolean parameter "boolParameter" in the "test" plugin.'
|
|
587
|
+
);
|
|
588
|
+
});
|
|
589
|
+
|
|
590
|
+
it("errors on non-string values for string parameters", async () => {
|
|
591
|
+
TestPlugin.setParameterInfos({
|
|
592
|
+
stringParameter: { type: ParameterType.STRING },
|
|
593
|
+
});
|
|
594
|
+
|
|
595
|
+
// this should work:
|
|
596
|
+
await createTrial({ type: TestPlugin, stringParameter: "foo" }).run();
|
|
597
|
+
|
|
598
|
+
// this shouldn't:
|
|
599
|
+
await createTrial({ type: TestPlugin, stringParameter: 1 }).run();
|
|
600
|
+
expect(consoleSpy).toHaveBeenCalledWith(
|
|
601
|
+
'A non-string value (`1`) was provided for the parameter "stringParameter" in the "test" plugin.'
|
|
602
|
+
);
|
|
603
|
+
});
|
|
604
|
+
|
|
605
|
+
it("errors on non-numeric values for numeric parameters", async () => {
|
|
606
|
+
TestPlugin.setParameterInfos({
|
|
607
|
+
intParameter: { type: ParameterType.INT },
|
|
608
|
+
floatParameter: { type: ParameterType.FLOAT },
|
|
609
|
+
});
|
|
610
|
+
|
|
611
|
+
// this should work:
|
|
612
|
+
await createTrial({ type: TestPlugin, intParameter: 1, floatParameter: 1.5 }).run();
|
|
613
|
+
|
|
614
|
+
// this shouldn't:
|
|
615
|
+
await createTrial({ type: TestPlugin, intParameter: "foo", floatParameter: 1.5 }).run();
|
|
616
|
+
expect(consoleSpy).toHaveBeenCalledWith(
|
|
617
|
+
'A non-numeric value (`foo`) was provided for the numeric parameter "intParameter" in the "test" plugin.'
|
|
618
|
+
);
|
|
619
|
+
|
|
620
|
+
await createTrial({ type: TestPlugin, intParameter: 1, floatParameter: "foo" }).run();
|
|
621
|
+
expect(consoleSpy).toHaveBeenCalledWith(
|
|
622
|
+
'A non-numeric value (`foo`) was provided for the numeric parameter "floatParameter" in the "test" plugin.'
|
|
623
|
+
);
|
|
624
|
+
|
|
625
|
+
// this should warn but not error (behavior in v9):
|
|
626
|
+
await createTrial({ type: TestPlugin, intParameter: 1.5, floatParameter: 1.5 }).run();
|
|
627
|
+
expect(consoleSpy).toHaveBeenCalledWith(
|
|
628
|
+
`A float value (\`1.5\`) was provided for the integer parameter "intParameter" in the "test" plugin. The value will be truncated to an integer.`
|
|
629
|
+
);
|
|
630
|
+
});
|
|
631
|
+
|
|
632
|
+
it("errors on non-function values for function parameters", async () => {
|
|
633
|
+
TestPlugin.setParameterInfos({
|
|
634
|
+
functionParameter: { type: ParameterType.FUNCTION },
|
|
635
|
+
});
|
|
636
|
+
|
|
637
|
+
// this should work:
|
|
638
|
+
await createTrial({ type: TestPlugin, functionParameter: () => {} }).run();
|
|
639
|
+
|
|
640
|
+
// this shouldn't:
|
|
641
|
+
await createTrial({ type: TestPlugin, functionParameter: "foo" }).run();
|
|
642
|
+
expect(consoleSpy).toHaveBeenCalledWith(
|
|
643
|
+
'A non-function value (`foo`) was provided for the function parameter "functionParameter" in the "test" plugin.'
|
|
644
|
+
);
|
|
645
|
+
});
|
|
646
|
+
|
|
647
|
+
it("errors on select parameters with values not in the options array", async () => {
|
|
648
|
+
TestPlugin.setParameterInfos({
|
|
649
|
+
selectParameter: {
|
|
650
|
+
type: ParameterType.SELECT,
|
|
651
|
+
options: ["foo", "bar"],
|
|
652
|
+
},
|
|
653
|
+
});
|
|
654
|
+
|
|
655
|
+
// this should work:
|
|
656
|
+
await createTrial({ type: TestPlugin, selectParameter: "foo" }).run();
|
|
657
|
+
|
|
658
|
+
// this shouldn't:
|
|
659
|
+
|
|
660
|
+
await createTrial({ type: TestPlugin, selectParameter: "baz" }).run();
|
|
661
|
+
expect(consoleSpy).toHaveBeenCalledWith(
|
|
662
|
+
'The value "baz" is not a valid option for the parameter "selectParameter" in the "test" plugin. Valid options are: foo, bar.'
|
|
663
|
+
);
|
|
664
|
+
});
|
|
665
|
+
});
|
|
666
|
+
|
|
563
667
|
it("respects `default_iti` and `post_trial_gap``", async () => {
|
|
564
668
|
dependencies.getDefaultIti.mockReturnValue(100);
|
|
565
669
|
TestPlugin.setManualFinishTrialMode();
|
package/src/timeline/Trial.ts
CHANGED
|
@@ -360,6 +360,7 @@ export class Trial extends TimelineNode {
|
|
|
360
360
|
for (const [parameterName, parameterConfig] of Object.entries(parameterInfos)) {
|
|
361
361
|
const parameterPath = [...parentParameterPath, parameterName];
|
|
362
362
|
|
|
363
|
+
// evaluate parameter and validate required parameter
|
|
363
364
|
let parameterValue = this.getParameterValue(parameterPath, {
|
|
364
365
|
evaluateFunctions: parameterConfig.type !== ParameterType.FUNCTION,
|
|
365
366
|
replaceResult: (originalResult) => {
|
|
@@ -379,6 +380,83 @@ export class Trial extends TimelineNode {
|
|
|
379
380
|
},
|
|
380
381
|
});
|
|
381
382
|
|
|
383
|
+
// TODO: ensure that this throws an error in v9!
|
|
384
|
+
// major parameter type validation
|
|
385
|
+
if (!parameterConfig.array && parameterValue !== null) {
|
|
386
|
+
switch (parameterConfig.type) {
|
|
387
|
+
case ParameterType.BOOL:
|
|
388
|
+
if (typeof parameterValue !== "boolean") {
|
|
389
|
+
const parameterPathString = parameterPathArrayToString(parameterPath);
|
|
390
|
+
console.warn(
|
|
391
|
+
`A non-boolean value (\`${parameterValue}\`) was provided for the boolean parameter "${parameterPathString}" in the "${this.pluginInfo.name}" plugin.`
|
|
392
|
+
);
|
|
393
|
+
}
|
|
394
|
+
break;
|
|
395
|
+
// @ts-ignore falls through
|
|
396
|
+
case ParameterType.KEYS: // "ALL_KEYS", "NO_KEYS", and single key strings are checked here
|
|
397
|
+
if (Array.isArray(parameterValue)) break;
|
|
398
|
+
case ParameterType.STRING:
|
|
399
|
+
case ParameterType.HTML_STRING:
|
|
400
|
+
case ParameterType.KEY:
|
|
401
|
+
case ParameterType.AUDIO:
|
|
402
|
+
case ParameterType.VIDEO:
|
|
403
|
+
case ParameterType.IMAGE:
|
|
404
|
+
if (typeof parameterValue !== "string") {
|
|
405
|
+
const parameterPathString = parameterPathArrayToString(parameterPath);
|
|
406
|
+
console.warn(
|
|
407
|
+
`A non-string value (\`${parameterValue}\`) was provided for the parameter "${parameterPathString}" in the "${this.pluginInfo.name}" plugin.`
|
|
408
|
+
);
|
|
409
|
+
}
|
|
410
|
+
break;
|
|
411
|
+
case ParameterType.FLOAT:
|
|
412
|
+
case ParameterType.INT:
|
|
413
|
+
if (typeof parameterValue !== "number") {
|
|
414
|
+
const parameterPathString = parameterPathArrayToString(parameterPath);
|
|
415
|
+
console.warn(
|
|
416
|
+
`A non-numeric value (\`${parameterValue}\`) was provided for the numeric parameter "${parameterPathString}" in the "${this.pluginInfo.name}" plugin.`
|
|
417
|
+
);
|
|
418
|
+
}
|
|
419
|
+
break;
|
|
420
|
+
case ParameterType.FUNCTION:
|
|
421
|
+
if (typeof parameterValue !== "function") {
|
|
422
|
+
const parameterPathString = parameterPathArrayToString(parameterPath);
|
|
423
|
+
console.warn(
|
|
424
|
+
`A non-function value (\`${parameterValue}\`) was provided for the function parameter "${parameterPathString}" in the "${this.pluginInfo.name}" plugin.`
|
|
425
|
+
);
|
|
426
|
+
}
|
|
427
|
+
break;
|
|
428
|
+
case ParameterType.SELECT:
|
|
429
|
+
if (!parameterConfig.options) {
|
|
430
|
+
const parameterPathString = parameterPathArrayToString(parameterPath);
|
|
431
|
+
console.warn(
|
|
432
|
+
`The "options" array is required for the "select" parameter "${parameterPathString}" in the "${this.pluginInfo.name}" plugin.`
|
|
433
|
+
);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
// truncate floats to integers if the parameter type is INT
|
|
438
|
+
if (parameterConfig.type === ParameterType.INT && parameterValue % 1 !== 0) {
|
|
439
|
+
const parameterPathString = parameterPathArrayToString(parameterPath);
|
|
440
|
+
console.warn(
|
|
441
|
+
`A float value (\`${parameterValue}\`) was provided for the integer parameter "${parameterPathString}" in the "${this.pluginInfo.name}" plugin. The value will be truncated to an integer.`
|
|
442
|
+
);
|
|
443
|
+
|
|
444
|
+
parameterValue = Math.trunc(parameterValue);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
if (parameterConfig.type === ParameterType.SELECT) {
|
|
449
|
+
if (!parameterConfig.options.includes(parameterValue)) {
|
|
450
|
+
const parameterPathString = parameterPathArrayToString(parameterPath);
|
|
451
|
+
console.warn(
|
|
452
|
+
`The value "${parameterValue}" is not a valid option for the parameter "${parameterPathString}" in the "${
|
|
453
|
+
this.pluginInfo.name
|
|
454
|
+
}" plugin. Valid options are: ${parameterConfig.options.join(", ")}.`
|
|
455
|
+
);
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
// array validation
|
|
382
460
|
if (parameterConfig.array && !Array.isArray(parameterValue)) {
|
|
383
461
|
const parameterPathString = parameterPathArrayToString(parameterPath);
|
|
384
462
|
throw new Error(
|