@lookit/record 0.0.4 → 2.0.0

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/dist/stop.d.ts CHANGED
@@ -1,7 +1,12 @@
1
- import { JsPsych, JsPsychPlugin } from "jspsych";
1
+ import { JsPsych, JsPsychPlugin, ParameterType, TrialType } from "jspsych";
2
2
  declare const info: {
3
3
  readonly name: "stop-record-plugin";
4
- readonly parameters: {};
4
+ readonly parameters: {
5
+ readonly locale: {
6
+ readonly type: ParameterType.STRING;
7
+ readonly default: "en-us";
8
+ };
9
+ };
5
10
  };
6
11
  type Info = typeof info;
7
12
  /** Stop recording. Used by researchers who want to record across trials. */
@@ -9,7 +14,12 @@ export default class StopRecordPlugin implements JsPsychPlugin<Info> {
9
14
  private jsPsych;
10
15
  static readonly info: {
11
16
  readonly name: "stop-record-plugin";
12
- readonly parameters: {};
17
+ readonly parameters: {
18
+ readonly locale: {
19
+ readonly type: ParameterType.STRING;
20
+ readonly default: "en-us";
21
+ };
22
+ };
13
23
  };
14
24
  private recorder;
15
25
  /**
@@ -24,7 +34,8 @@ export default class StopRecordPlugin implements JsPsychPlugin<Info> {
24
34
  * @param display_element - DOM element where jsPsych content is being
25
35
  * rendered (set in initJsPsych and automatically made available to a
26
36
  * plugin's trial method via jsPsych core).
37
+ * @param trial - Trial object with parameters/values.
27
38
  */
28
- trial(display_element: HTMLElement): void;
39
+ trial(display_element: HTMLElement, trial: TrialType<Info>): void;
29
40
  }
30
41
  export {};
@@ -3,6 +3,10 @@ declare const info: {
3
3
  readonly name: "video-config-plugin";
4
4
  readonly version: string;
5
5
  readonly parameters: {
6
+ readonly locale: {
7
+ readonly type: ParameterType.STRING;
8
+ readonly default: "en-us";
9
+ };
6
10
  readonly troubleshooting_intro: {
7
11
  /**
8
12
  * Optional string to appear at the start of the "Setup tips and
@@ -27,6 +31,30 @@ declare const info: {
27
31
  };
28
32
  type Info = typeof info;
29
33
  export type VideoConsentTrialType = TrialType<Info>;
34
+ export declare const html_params: {
35
+ webcam_container_id: string;
36
+ reload_button_id_text: string;
37
+ reload_button_id_cam: string;
38
+ camera_selection_id: string;
39
+ mic_selection_id: string;
40
+ next_button_id: string;
41
+ error_msg_div_id: string;
42
+ step1_id: string;
43
+ step2_id: string;
44
+ step3_id: string;
45
+ step_complete_class: string;
46
+ waiting_for_access_msg_id: string;
47
+ checking_mic_msg_id: string;
48
+ access_problem_msg_id: string;
49
+ setup_problem_msg_id: string;
50
+ chromeInitialPrompt: any;
51
+ chromeAlwaysAllow: any;
52
+ chromePermissions: any;
53
+ firefoxInitialPrompt: any;
54
+ firefoxChooseDevice: any;
55
+ firefoxDevicesBlocked: any;
56
+ checkmarkIcon: any;
57
+ };
30
58
  /**
31
59
  * **Video Config**.
32
60
  *
@@ -44,6 +72,10 @@ export default class VideoConfigPlugin implements JsPsychPlugin<Info> {
44
72
  readonly name: "video-config-plugin";
45
73
  readonly version: string;
46
74
  readonly parameters: {
75
+ readonly locale: {
76
+ readonly type: ParameterType.STRING;
77
+ readonly default: "en-us";
78
+ };
47
79
  readonly troubleshooting_intro: {
48
80
  /**
49
81
  * Optional string to appear at the start of the "Setup tips and
@@ -76,22 +108,6 @@ export default class VideoConfigPlugin implements JsPsychPlugin<Info> {
76
108
  private minVolume;
77
109
  private micChecked;
78
110
  private processorNode;
79
- private webcam_container_id;
80
- private reload_button_id_text;
81
- private reload_button_id_cam;
82
- private camera_selection_id;
83
- private mic_selection_id;
84
- private next_button_id;
85
- private error_msg_div_id;
86
- private step1_id;
87
- private step2_id;
88
- private step3_id;
89
- private step_complete_class;
90
- private step_complete_text;
91
- private waiting_for_access_msg;
92
- private checking_mic_msg;
93
- private access_problem_msg;
94
- private setup_problem_msg;
95
111
  /**
96
112
  * Constructor for video config plugin.
97
113
  *
@@ -108,8 +124,7 @@ export default class VideoConfigPlugin implements JsPsychPlugin<Info> {
108
124
  /**
109
125
  * Add HTML content to the page.
110
126
  *
111
- * @param troubleshooting_intro - Troubleshooting intro parameter from the
112
- * Trial object.
127
+ * @param trial - Trial object.
113
128
  */
114
129
  private addHtmlContent;
115
130
  /** Add event listeners to elements after they've been added to the page. */
@@ -264,8 +279,9 @@ export default class VideoConfigPlugin implements JsPsychPlugin<Info> {
264
279
  * Update the errors/messages div with information for the user about the
265
280
  * camera/mic checks.
266
281
  *
267
- * @param errorMsg - Message to display in the error message div. Pass an
268
- * empty string to clear any existing errors/messages.
282
+ * @param errorMsgId - Span element ID containing the message to display in
283
+ * the error message div. Call the function without an errorMsgId to clear
284
+ * the errors.
269
285
  */
270
286
  private updateErrors;
271
287
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lookit/record",
3
- "version": "0.0.4",
3
+ "version": "2.0.0",
4
4
  "description": "Recording extensions and plugins for CHS studies.",
5
5
  "homepage": "https://github.com/lookit/lookit-jspsych#readme",
6
6
  "bugs": {
@@ -34,20 +34,15 @@
34
34
  "@rollup/plugin-image": "^3.0.3",
35
35
  "@rollup/plugin-replace": "^6.0.1",
36
36
  "@types/audioworklet": "^0.0.60",
37
- "@types/js-yaml": "^4.0.9",
38
- "@types/node-polyglot": "^2.5.0",
39
37
  "handlebars": "^4.7.8",
40
- "i18next": "^23.15.1",
41
- "i18next-icu": "^2.3.0",
42
- "js-yaml": "^4.1.0",
43
38
  "rollup-plugin-dotenv": "^0.5.1",
44
39
  "rollup-plugin-polyfill-node": "^0.13.0",
45
40
  "rollup-plugin-string-import": "^1.2.4",
46
41
  "typescript": "^5.6.2"
47
42
  },
48
43
  "peerDependencies": {
49
- "@lookit/data": "^0.0.4",
50
- "@lookit/templates": "^0.0.1",
44
+ "@lookit/data": "^0.1.0",
45
+ "@lookit/templates": "^1.1.0",
51
46
  "jspsych": "^8.0.2"
52
47
  }
53
48
  }
@@ -46,15 +46,16 @@ const info = <const>{
46
46
  additional_segments: {
47
47
  type: ParameterType.COMPLEX,
48
48
  array: true,
49
+ default: [],
49
50
  nested: {
50
51
  title: {
51
52
  type: ParameterType.STRING,
52
53
  default: "",
53
54
  },
54
- },
55
- text: {
56
- type: ParameterType.STRING,
57
- default: "",
55
+ text: {
56
+ type: ParameterType.STRING,
57
+ default: "",
58
+ },
58
59
  },
59
60
  },
60
61
  prompt_all_adults: { type: ParameterType.BOOL, default: false },
package/src/index.spec.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { LookitWindow } from "@lookit/data/dist/types";
2
- import { initJsPsych } from "jspsych";
2
+ import { initJsPsych, PluginInfo, TrialType } from "jspsych";
3
3
  import { ExistingRecordingError, NoSessionRecordingError } from "./errors";
4
4
  import Rec from "./index";
5
5
  import Recorder from "./recorder";
@@ -96,7 +96,11 @@ test("Stop Recording", async () => {
96
96
 
97
97
  mockRecStop.mockImplementation(jest.fn().mockReturnValue(Promise.resolve()));
98
98
 
99
- await stopRec.trial(display_element);
99
+ const trial = {
100
+ locale: "en-us",
101
+ } as unknown as TrialType<PluginInfo>;
102
+
103
+ await stopRec.trial(display_element, trial);
100
104
 
101
105
  expect(jsPsych.finishTrial).toHaveBeenCalledTimes(1);
102
106
  expect(window.chs.sessionRecorder).toBeNull();
package/src/index.ts CHANGED
@@ -2,7 +2,7 @@ import { VideoConsentPlugin } from "./consentVideo";
2
2
  import StartRecordPlugin from "./start";
3
3
  import StopRecordPlugin from "./stop";
4
4
  import TrialRecordExtension from "./trial";
5
- import VideoConfigPlugin from "./video_config";
5
+ import VideoConfigPlugin from "./videoConfig";
6
6
 
7
7
  export default {
8
8
  TrialRecordExtension,
package/src/stop.ts CHANGED
@@ -1,13 +1,17 @@
1
1
  import { LookitWindow } from "@lookit/data/dist/types";
2
- import Handlebars from "handlebars";
3
- import { JsPsych, JsPsychPlugin } from "jspsych";
4
- import uploadingVideo from "../hbs/uploading-video.hbs";
2
+ import chsTemplates from "@lookit/templates";
3
+ import { JsPsych, JsPsychPlugin, ParameterType, TrialType } from "jspsych";
5
4
  import { NoSessionRecordingError } from "./errors";
6
5
  import Recorder from "./recorder";
7
6
 
8
7
  declare let window: LookitWindow;
9
8
 
10
- const info = <const>{ name: "stop-record-plugin", parameters: {} };
9
+ const info = <const>{
10
+ name: "stop-record-plugin",
11
+ parameters: {
12
+ locale: { type: ParameterType.STRING, default: "en-us" },
13
+ },
14
+ };
11
15
  type Info = typeof info;
12
16
 
13
17
  /** Stop recording. Used by researchers who want to record across trials. */
@@ -34,9 +38,10 @@ export default class StopRecordPlugin implements JsPsychPlugin<Info> {
34
38
  * @param display_element - DOM element where jsPsych content is being
35
39
  * rendered (set in initJsPsych and automatically made available to a
36
40
  * plugin's trial method via jsPsych core).
41
+ * @param trial - Trial object with parameters/values.
37
42
  */
38
- public trial(display_element: HTMLElement): void {
39
- display_element.innerHTML = Handlebars.compile(uploadingVideo)({});
43
+ public trial(display_element: HTMLElement, trial: TrialType<Info>): void {
44
+ display_element.innerHTML = chsTemplates.uploadingVideo(trial);
40
45
  this.recorder.stop().then(() => {
41
46
  window.chs.sessionRecorder = null;
42
47
  display_element.innerHTML = "";
@@ -1,16 +1,12 @@
1
1
  import { clickTarget } from "@jspsych/test-utils";
2
- import Handlebars from "handlebars";
2
+ import chsTemplates from "@lookit/templates";
3
3
  import { initJsPsych, JsPsych } from "jspsych";
4
- import videoConfig from "../hbs/video-config.hbs";
5
4
  import { NoStreamError } from "./errors";
6
- import chromeInitialPrompt from "./img/chrome_initialprompt.png";
7
- import chromeAlwaysAllow from "./img/chrome_step1_alwaysallow.png";
8
- import chromePermissions from "./img/chrome_step1_permissions.png";
9
- import firefoxInitialPrompt from "./img/firefox_initialprompt.png";
10
- import firefoxChooseDevice from "./img/firefox_prompt_choose_device.png";
11
- import firefoxDevicesBlocked from "./img/firefox_prompt_devices_blocked.png";
12
5
  import Recorder from "./recorder";
13
- import VideoConfigPlugin, { VideoConsentTrialType } from "./video_config";
6
+ import VideoConfigPlugin, {
7
+ html_params,
8
+ VideoConsentTrialType,
9
+ } from "./videoConfig";
14
10
 
15
11
  jest.mock("./recorder");
16
12
  jest.mock("@lookit/data");
@@ -42,7 +38,6 @@ jest.mock("jspsych", () => ({
42
38
  let display_el: HTMLBodyElement;
43
39
  let jsPsych: JsPsych;
44
40
  let video_config: VideoConfigPlugin;
45
- let html_params: object;
46
41
  let devices: MediaDeviceInfo[];
47
42
  let devicesObj: {
48
43
  cam1: MediaDeviceInfo;
@@ -55,6 +50,12 @@ let returnedDeviceLists: {
55
50
  mics: MediaDeviceInfo[];
56
51
  };
57
52
 
53
+ // Video consent trial object with defaults
54
+ const trial_info = {
55
+ locale: "en-us",
56
+ troubleshooting_intro: "",
57
+ } as VideoConsentTrialType;
58
+
58
59
  /**
59
60
  * Clean rendered html to be compared with DOM.
60
61
  *
@@ -70,6 +71,10 @@ const cleanHTML = (html: string) => {
70
71
  .replace(/\s*\/*>/gm, ">")
71
72
  // equals empty string
72
73
  .replace(/(="")/gm, "")
74
+ // convert &quot; to double quote
75
+ .replace(/(&quot;)/gm, '"')
76
+ // convert &#x27; to single quote
77
+ .replace(/(&#x27;)/gm, "'")
73
78
  );
74
79
  };
75
80
 
@@ -79,28 +84,6 @@ beforeEach(() => {
79
84
  video_config = new VideoConfigPlugin(jsPsych);
80
85
  video_config["display_el"] = display_el;
81
86
 
82
- // Set up parameters for rendering HTML template
83
- html_params = {
84
- webcam_container_id: video_config["webcam_container_id"],
85
- reload_button_id_cam: video_config["reload_button_id_cam"],
86
- camera_selection_id: video_config["camera_selection_id"],
87
- mic_selection_id: video_config["mic_selection_id"],
88
- step1_id: video_config["step1_id"],
89
- step2_id: video_config["step2_id"],
90
- step3_id: video_config["step3_id"],
91
- step_complete_class: video_config["step_complete_class"],
92
- step_complete_text: video_config["step_complete_text"],
93
- reload_button_id_text: video_config["reload_button_id_text"],
94
- next_button_id: video_config["next_button_id"],
95
- chromeInitialPrompt: chromeInitialPrompt,
96
- chromeAlwaysAllow: chromeAlwaysAllow,
97
- chromePermissions: chromePermissions,
98
- firefoxInitialPrompt: firefoxInitialPrompt,
99
- firefoxChooseDevice: firefoxChooseDevice,
100
- firefoxDevicesBlocked: firefoxDevicesBlocked,
101
- troubleshooting_intro: "",
102
- };
103
-
104
87
  // Mocks for handling media streams and devices
105
88
  const mic1 = {
106
89
  deviceId: "mic1",
@@ -158,10 +141,6 @@ afterEach(() => {
158
141
  });
159
142
 
160
143
  test("Video config trial method sets up trial", () => {
161
- const trial_info = {
162
- troubleshooting_intro: "",
163
- } as unknown as VideoConsentTrialType;
164
-
165
144
  // Set up mocks for upstream functions called in trial method.
166
145
  const addHtmlMock = jest
167
146
  .spyOn(video_config, "addHtmlContent")
@@ -195,11 +174,11 @@ test("Video config addHtmlContent loads template", () => {
195
174
 
196
175
  // Render the template with the HTML parameters.
197
176
  const rendered_trial_html = cleanHTML(
198
- Handlebars.compile(videoConfig)(html_params),
177
+ chsTemplates.videoConfig(trial_info, html_params),
199
178
  );
200
179
 
201
180
  // Run addHtmlContent to get the actual trial HTML.
202
- video_config["addHtmlContent"]("");
181
+ video_config["addHtmlContent"](trial_info);
203
182
  const displayed_html = cleanHTML(document.body.innerHTML);
204
183
 
205
184
  expect(displayed_html).toStrictEqual(rendered_trial_html);
@@ -209,19 +188,18 @@ test("Video config addHtmlContent loads template with custom troubleshooting tex
209
188
  expect(video_config["display_el"]?.innerHTML).toBe("");
210
189
 
211
190
  // Render the template with a custom trial parameter.
212
- const troubleshooting_intro = "Custom text.";
213
- const html_params_custom_intro = {
214
- ...html_params,
215
- troubleshooting_intro,
216
- };
191
+ const trial_info_custom_troubleshoot = {
192
+ locale: "en-us",
193
+ troubleshooting_intro: "Custom text.",
194
+ } as VideoConsentTrialType;
217
195
 
218
196
  // Remove new lines, indents (tabs or spaces), and empty HTML property values.
219
197
  const rendered_trial_html = cleanHTML(
220
- Handlebars.compile(videoConfig)(html_params_custom_intro),
198
+ chsTemplates.videoConfig(trial_info_custom_troubleshoot, html_params),
221
199
  );
222
200
 
223
201
  // Get the actual trial HTML
224
- video_config["addHtmlContent"](troubleshooting_intro);
202
+ video_config["addHtmlContent"](trial_info_custom_troubleshoot);
225
203
  const displayed_html = cleanHTML(document.body.innerHTML);
226
204
 
227
205
  expect(displayed_html).toStrictEqual(rendered_trial_html);
@@ -229,14 +207,14 @@ test("Video config addHtmlContent loads template with custom troubleshooting tex
229
207
 
230
208
  test("Video config add event listeners", async () => {
231
209
  expect(video_config["display_el"]?.innerHTML).toBe("");
232
- video_config["addHtmlContent"]("");
210
+ video_config["addHtmlContent"](trial_info);
233
211
 
234
212
  // Get relevant elements (device selection elements tested separately)
235
213
  const next_button_el = video_config["display_el"]?.querySelector(
236
- `#${video_config["next_button_id"]}`,
214
+ `#${html_params["next_button_id"]}`,
237
215
  ) as HTMLButtonElement;
238
216
  const reload_button_els = video_config["display_el"]?.querySelectorAll(
239
- `#${video_config["reload_button_id_cam"]}, #${video_config["reload_button_id_text"]}`,
217
+ `#${html_params["reload_button_id_cam"]}, #${html_params["reload_button_id_text"]}`,
240
218
  ) as NodeListOf<HTMLButtonElement>;
241
219
  const acc_button_els = document.getElementsByClassName(
242
220
  "lookit-jspsych-accordion",
@@ -291,41 +269,41 @@ test("Video config add event listeners", async () => {
291
269
  test("Video config enable next", () => {
292
270
  expect(video_config["display_el"]?.innerHTML).toBe("");
293
271
 
294
- video_config["addHtmlContent"]("");
272
+ video_config["addHtmlContent"](trial_info);
295
273
  const next_button_el = video_config["display_el"]?.querySelector(
296
- `#${video_config["next_button_id"]}`,
274
+ `#${html_params["next_button_id"]}`,
297
275
  ) as HTMLButtonElement;
298
276
 
299
277
  // When trial first loads, next button should exist but be disabled and no 'step_complete_class'
300
278
  expect(next_button_el).toBeTruthy();
301
279
  expect(
302
- next_button_el.classList.contains(video_config["step_complete_class"]),
280
+ next_button_el.classList.contains(html_params["step_complete_class"]),
303
281
  ).toBe(false);
304
282
  expect(next_button_el.disabled).toBe(true);
305
283
 
306
284
  // Calling with 'true' enables the button and adds the class.
307
285
  video_config["enableNext"](true);
308
286
  expect(
309
- next_button_el.classList.contains(video_config["step_complete_class"]),
287
+ next_button_el.classList.contains(html_params["step_complete_class"]),
310
288
  ).toBe(true);
311
289
  expect(next_button_el.disabled).toBe(false);
312
290
 
313
291
  // Calling with 'false' sets everything back.
314
292
  video_config["enableNext"](false);
315
293
  expect(
316
- next_button_el.classList.contains(video_config["step_complete_class"]),
294
+ next_button_el.classList.contains(html_params["step_complete_class"]),
317
295
  ).toBe(false);
318
296
  expect(next_button_el.disabled).toBe(true);
319
297
  });
320
298
 
321
299
  test("Video config update instructions", () => {
322
300
  expect(video_config["display_el"]?.innerHTML).toBe("");
323
- video_config["addHtmlContent"]("");
301
+ video_config["addHtmlContent"](trial_info);
324
302
 
325
303
  // Get the relevant elements from the instructions section.
326
- const step1_id = video_config["step1_id"];
327
- const step2_id = video_config["step2_id"];
328
- const step3_id = video_config["step3_id"];
304
+ const step1_id = html_params["step1_id"];
305
+ const step2_id = html_params["step2_id"];
306
+ const step3_id = html_params["step3_id"];
329
307
  const step1_span = video_config["display_el"]?.querySelector(
330
308
  `#${step1_id}-span`,
331
309
  ) as HTMLSpanElement;
@@ -376,27 +354,34 @@ test("Video config update instructions", () => {
376
354
 
377
355
  test("Video config update errors", () => {
378
356
  expect(video_config["display_el"]?.innerHTML).toBe("");
379
- video_config["addHtmlContent"]("");
357
+ video_config["addHtmlContent"](trial_info);
380
358
  const error_msg_div = video_config["display_el"]?.querySelector(
381
- `#${video_config["error_msg_div_id"]}`,
359
+ `#${html_params["error_msg_div_id"]}`,
382
360
  ) as HTMLDivElement;
383
361
 
384
- // Error/info message div is empty when the page first loads.
385
- expect(error_msg_div.innerHTML).toStrictEqual("");
386
-
387
- const test_msg = "Test message.";
388
- video_config["updateErrors"](test_msg);
362
+ // Error/info messages are all hidden when the page first loads.
363
+ const error_msg_elements = error_msg_div.querySelectorAll(
364
+ "span.error_msg",
365
+ ) as NodeListOf<HTMLSpanElement>;
366
+ error_msg_elements.forEach((span) => {
367
+ expect(span.style.display).toBe("none");
368
+ });
389
369
 
390
- expect(error_msg_div.innerHTML).toStrictEqual(test_msg);
370
+ // Calling with an error message ID displays the message element
371
+ video_config["updateErrors"](html_params["waiting_for_access_msg_id"]);
372
+ const waiting_for_access_msg_el = error_msg_div.querySelector(
373
+ `span#${html_params["waiting_for_access_msg_id"]}`,
374
+ ) as HTMLSpanElement;
375
+ expect(waiting_for_access_msg_el?.style.display).toBe("block");
391
376
  });
392
377
 
393
378
  test("Video config reload button click", async () => {
394
379
  expect(video_config["hasReloaded"]).toBe(false);
395
380
 
396
- video_config["addHtmlContent"]("");
381
+ video_config["addHtmlContent"](trial_info);
397
382
 
398
383
  const reload_button_els = video_config["display_el"]?.querySelectorAll(
399
- `#${video_config["reload_button_id_cam"]}, #${video_config["reload_button_id_text"]}`,
384
+ `#${html_params["reload_button_id_cam"]}, #${html_params["reload_button_id_text"]}`,
400
385
  ) as NodeListOf<HTMLButtonElement>;
401
386
 
402
387
  // Mock upstream function calls.
@@ -432,12 +417,12 @@ test("Video config reload button click", async () => {
432
417
  });
433
418
 
434
419
  test("Video config updateDeviceSelection", () => {
435
- video_config["addHtmlContent"]("");
420
+ video_config["addHtmlContent"](trial_info);
436
421
  const cam_selection_el = video_config["display_el"]?.querySelector(
437
- `#${video_config["camera_selection_id"]}`,
422
+ `#${html_params["camera_selection_id"]}`,
438
423
  ) as HTMLSelectElement;
439
424
  const mic_selection_el = video_config["display_el"]?.querySelector(
440
- `#${video_config["mic_selection_id"]}`,
425
+ `#${html_params["mic_selection_id"]}`,
441
426
  ) as HTMLSelectElement;
442
427
 
443
428
  expect(cam_selection_el).not.toBeUndefined();
@@ -583,9 +568,9 @@ test("Video config setupRecorder", async () => {
583
568
  // Adds error message when waiting for stream access, then clears the message after access is granted.
584
569
  expect(updateErrorsMock).toHaveBeenCalledTimes(2);
585
570
  expect(updateErrorsMock.mock.calls[0]).toStrictEqual([
586
- video_config["waiting_for_access_msg"],
571
+ html_params["waiting_for_access_msg_id"],
587
572
  ]);
588
- expect(updateErrorsMock.mock.calls[1]).toStrictEqual([""]);
573
+ expect(updateErrorsMock.mock.calls[1]).toStrictEqual([]);
589
574
  // Needs to request permissions before it can get device lists.
590
575
  expect(requestPermissionMock).toHaveBeenCalledWith({
591
576
  video: true,
@@ -603,15 +588,15 @@ test("Video config setupRecorder", async () => {
603
588
  });
604
589
 
605
590
  test("Video config setDevices", async () => {
606
- video_config["addHtmlContent"]("");
591
+ video_config["addHtmlContent"](trial_info);
607
592
  const cam_selection_el = video_config["display_el"]?.querySelector(
608
- `#${video_config["camera_selection_id"]}`,
593
+ `#${html_params["camera_selection_id"]}`,
609
594
  ) as HTMLSelectElement;
610
595
  const mic_selection_el = video_config["display_el"]?.querySelector(
611
- `#${video_config["mic_selection_id"]}`,
596
+ `#${html_params["mic_selection_id"]}`,
612
597
  ) as HTMLSelectElement;
613
598
  const next_button_el = video_config["display_el"]?.querySelector(
614
- `#${video_config["next_button_id"]}`,
599
+ `#${html_params["next_button_id"]}`,
615
600
  ) as HTMLButtonElement;
616
601
  video_config["recorder"] = new Recorder(jsPsych);
617
602
 
@@ -683,7 +668,7 @@ test("Video config setDevices", async () => {
683
668
  });
684
669
 
685
670
  test("Video config runStreamChecks throws NoStreamAccess", () => {
686
- video_config["addHtmlContent"]("");
671
+ video_config["addHtmlContent"](trial_info);
687
672
  video_config["recorder"] = new Recorder(initJsPsych());
688
673
  jest
689
674
  .spyOn(jsPsych.pluginAPI, "getCameraRecorder")
@@ -704,7 +689,7 @@ test("Video config runStreamChecks throws NoStreamAccess", () => {
704
689
  });
705
690
 
706
691
  test("Video config runStreamChecks throws Mic Check error", async () => {
707
- video_config["addHtmlContent"]("");
692
+ video_config["addHtmlContent"](trial_info);
708
693
  video_config["recorder"] = new Recorder(jsPsych);
709
694
 
710
695
  // Setup upstream mocks.
@@ -730,15 +715,15 @@ test("Video config runStreamChecks throws Mic Check error", async () => {
730
715
  // If the recorder mic check throws an error, then the plugin should update the error message and throw the error.
731
716
  expect(updateErrorsMock).toHaveBeenCalledTimes(2);
732
717
  expect(updateErrorsMock.mock.calls[0]).toStrictEqual([
733
- video_config["checking_mic_msg"],
718
+ html_params["checking_mic_msg_id"],
734
719
  ]);
735
720
  expect(updateErrorsMock.mock.calls[1]).toStrictEqual([
736
- video_config["setup_problem_msg"],
721
+ html_params["setup_problem_msg_id"],
737
722
  ]);
738
723
  });
739
724
 
740
725
  test("Video config runStreamChecks", async () => {
741
- video_config["addHtmlContent"]("");
726
+ video_config["addHtmlContent"](trial_info);
742
727
  video_config["recorder"] = new Recorder(jsPsych);
743
728
 
744
729
  // Setup upstream mocks.
@@ -765,14 +750,14 @@ test("Video config runStreamChecks", async () => {
765
750
  // Called twice: first with "checking mic" message, then to clear that message.
766
751
  expect(updateErrorsMock).toHaveBeenCalledTimes(2);
767
752
  expect(updateErrorsMock.mock.calls[0]).toStrictEqual([
768
- video_config["checking_mic_msg"],
753
+ html_params["checking_mic_msg_id"],
769
754
  ]);
770
- expect(updateErrorsMock.mock.calls[1]).toStrictEqual([""]);
755
+ expect(updateErrorsMock.mock.calls[1]).toStrictEqual([]);
771
756
  expect(checkMicMock).toHaveBeenCalledTimes(1);
772
757
  });
773
758
 
774
759
  test("Video config runStreamChecks enables next button when all checks have passed", async () => {
775
- video_config["addHtmlContent"]("");
760
+ video_config["addHtmlContent"](trial_info);
776
761
  video_config["recorder"] = new Recorder(jsPsych);
777
762
 
778
763
  // Setup upstream mocks.
@@ -840,7 +825,7 @@ test("Video config onDeviceChange event listener", async () => {
840
825
  });
841
826
 
842
827
  test("Video config device selection element on change event listener", async () => {
843
- video_config["addHtmlContent"]("");
828
+ video_config["addHtmlContent"](trial_info);
844
829
 
845
830
  // Mock upstream functions called by device selection change event listener.
846
831
  const setDevicesMock = jest