@pie-element/ebsr 7.0.13 → 7.0.15-beta.1443

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.
Files changed (39) hide show
  1. package/CHANGELOG.md +328 -0
  2. package/configure/CHANGELOG.md +312 -0
  3. package/configure/lib/defaults.js +23 -4
  4. package/configure/lib/defaults.js.map +1 -1
  5. package/configure/lib/index.js +5 -5
  6. package/configure/lib/index.js.map +1 -1
  7. package/configure/lib/main.js +62 -50
  8. package/configure/lib/main.js.map +1 -1
  9. package/configure/package.json +3 -3
  10. package/configure/src/__tests__/__snapshots__/index.test.js.snap +4 -2
  11. package/configure/src/__tests__/index.test.js +164 -211
  12. package/configure/src/defaults.js +38 -19
  13. package/configure/src/index.js +8 -7
  14. package/configure/src/main.jsx +134 -147
  15. package/controller/CHANGELOG.md +20 -0
  16. package/controller/lib/defaults.js.map +1 -1
  17. package/controller/lib/index.js +91 -12
  18. package/controller/lib/index.js.map +1 -1
  19. package/controller/lib/utils.js.map +1 -1
  20. package/controller/package.json +2 -2
  21. package/controller/src/__tests__/index.test.js +113 -141
  22. package/controller/src/__tests__/utils.test.js +6 -9
  23. package/controller/src/defaults.js +1 -1
  24. package/controller/src/index.js +104 -69
  25. package/controller/src/utils.js +6 -4
  26. package/docs/config-schema.json +280 -0
  27. package/docs/config-schema.json.md +217 -1
  28. package/docs/demo/config.js +2 -2
  29. package/docs/demo/generate.js +3 -3
  30. package/docs/pie-schema.json +127 -0
  31. package/docs/pie-schema.json.md +96 -0
  32. package/lib/index.js +11 -8
  33. package/lib/index.js.map +1 -1
  34. package/lib/print.js +243 -0
  35. package/lib/print.js.map +1 -0
  36. package/package.json +8 -4
  37. package/src/__tests__/index.test.js +2 -7
  38. package/src/index.js +7 -5
  39. package/src/print.js +179 -0
@@ -8,38 +8,35 @@ import { Main } from '../main';
8
8
  import EbsrConfigure from '../index';
9
9
 
10
10
  jest.mock('react-dom', () => ({
11
- render: jest.fn()
11
+ render: jest.fn(),
12
12
  }));
13
13
 
14
14
  jest.mock('@pie-framework/pie-configure-events', () => ({
15
- ModelUpdatedEvent: update => {
15
+ ModelUpdatedEvent: (update) => {
16
16
  return {
17
17
  update,
18
18
  preventDefault: jest.fn(),
19
- stopImmediatePropagation: jest.fn()
19
+ stopImmediatePropagation: jest.fn(),
20
20
  };
21
- }
21
+ },
22
22
  }));
23
23
 
24
24
  jest.mock('@pie-lib/config-ui', () => ({
25
25
  choiceUtils: {
26
- firstAvailableIndex: jest.fn()
26
+ firstAvailableIndex: jest.fn(),
27
27
  },
28
28
  settings: {
29
- Panel: props => <div {...props} />,
29
+ Panel: (props) => <div {...props} />,
30
30
  toggle: jest.fn(),
31
31
  radio: jest.fn(),
32
- dropdown: jest.fn()
32
+ dropdown: jest.fn(),
33
33
  },
34
34
  layout: {
35
- ConfigLayout: props => <div>{props.children}</div>
36
- }
35
+ ConfigLayout: (props) => <div>{props.children}</div>,
36
+ },
37
37
  }));
38
38
 
39
- jest.mock(
40
- '@pie-element/multiple-choice/configure/lib',
41
- () => class MockConfigure {}
42
- );
39
+ jest.mock('@pie-element/multiple-choice/configure/lib', () => class MockConfigure {});
43
40
 
44
41
  const PART_A = 'partA';
45
42
  const PART_B = 'partB';
@@ -49,12 +46,12 @@ const createDefaultModel = (model, newModel = {}) => ({
49
46
  ...newModel,
50
47
  partA: {
51
48
  ...model.partA,
52
- ...newModel.partA
49
+ ...newModel.partA,
53
50
  },
54
51
  partB: {
55
52
  ...model.partB,
56
- ...newModel.partB
57
- }
53
+ ...newModel.partB,
54
+ },
58
55
  });
59
56
 
60
57
  const model = createDefaultModel(defaults.model, {
@@ -67,19 +64,20 @@ const model = createDefaultModel(defaults.model, {
67
64
  correct: true,
68
65
  feedback: {
69
66
  type: 'custom',
70
- value: 'foo'
71
- }
67
+ value: 'foo',
68
+ },
72
69
  },
73
70
  {
74
71
  value: 'green',
75
72
  label: 'Green',
76
73
  feedback: {
77
- type: 'default'
78
- }
79
- }
74
+ type: 'default',
75
+ },
76
+ },
80
77
  ],
81
78
  choicePrefix: 'numbers',
82
- prompt: `prompt ${PART_A}`
79
+ prompt: `prompt ${PART_A}`,
80
+ errors: {},
83
81
  },
84
82
  partB: {
85
83
  choiceMode: 'radio',
@@ -90,20 +88,21 @@ const model = createDefaultModel(defaults.model, {
90
88
  correct: true,
91
89
  feedback: {
92
90
  type: 'custom',
93
- value: 'foo'
94
- }
91
+ value: 'foo',
92
+ },
95
93
  },
96
94
  {
97
95
  value: 'purple',
98
96
  label: 'Purple',
99
97
  feedback: {
100
- type: 'default'
101
- }
102
- }
98
+ type: 'default',
99
+ },
100
+ },
103
101
  ],
104
102
  choicePrefix: 'numbers',
105
- prompt: `prompt ${PART_B}`
106
- }
103
+ prompt: `prompt ${PART_B}`,
104
+ errors: {},
105
+ },
107
106
  });
108
107
 
109
108
  describe('index', () => {
@@ -133,28 +132,28 @@ describe('index', () => {
133
132
  configuration={defaults.configuration}
134
133
  onConfigurationChanged={el.onConfigurationChanged}
135
134
  onModelChanged={el.onModelChanged}
136
- />
135
+ />,
137
136
  );
138
137
 
139
138
  // mock onModelChanged to dispatch a MODEL_UPDATED event (as multiple-choice does)
140
- main.instance().partA.onModelChanged = m => {
139
+ main.instance().partA.onModelChanged = (m) => {
141
140
  const event = new ModelUpdatedEvent(m, false);
142
141
 
143
142
  el.dispatchEvent({
144
143
  ...event,
145
144
  target: {
146
- getAttribute: jest.fn().mockReturnValue('A')
147
- }
145
+ getAttribute: jest.fn().mockReturnValue('A'),
146
+ },
148
147
  });
149
148
  };
150
- main.instance().partB.onModelChanged = m => {
149
+ main.instance().partB.onModelChanged = (m) => {
151
150
  const event = new ModelUpdatedEvent(m, false);
152
151
 
153
152
  el.dispatchEvent({
154
153
  ...event,
155
154
  target: {
156
- getAttribute: jest.fn().mockReturnValue('B')
157
- }
155
+ getAttribute: jest.fn().mockReturnValue('B'),
156
+ },
158
157
  });
159
158
  };
160
159
  });
@@ -166,7 +165,7 @@ describe('index', () => {
166
165
  });
167
166
  it('with-overrides-snapshot', () => {
168
167
  const m = EbsrConfigure.createDefaultModel({
169
- partA: { rationale: 'foo', teacherInstructions: 'ti' }
168
+ partA: { rationale: 'foo', teacherInstructions: 'ti' },
170
169
  });
171
170
  expect(m).toMatchSnapshot();
172
171
  });
@@ -197,12 +196,12 @@ describe('index', () => {
197
196
  expect(main.instance().partA.configuration).toEqual({
198
197
  ...defaults.configuration.partA,
199
198
  partLabels: defaults.configuration.partLabels,
200
- settingsPanelDisabled: true
199
+ settingsPanelDisabled: true,
201
200
  });
202
201
  expect(main.instance().partB.configuration).toEqual({
203
202
  ...defaults.configuration.partB,
204
203
  partLabels: defaults.configuration.partLabels,
205
- settingsPanelDisabled: true
204
+ settingsPanelDisabled: true,
206
205
  });
207
206
  });
208
207
  });
@@ -214,8 +213,8 @@ describe('index', () => {
214
213
  el.dispatchEvent({
215
214
  ...event,
216
215
  target: {
217
- getAttribute: jest.fn().mockReturnValue(key)
218
- }
216
+ getAttribute: jest.fn().mockReturnValue(key),
217
+ },
219
218
  });
220
219
 
221
220
  expect(ReactDOM.render).toBeCalled();
@@ -224,30 +223,20 @@ describe('index', () => {
224
223
  };
225
224
 
226
225
  describe('onModelUpdated', () => {
227
- assetOnModelUpdated(
228
- 'dispatching MODEL_UPDATED updates model.partA',
229
- 'A',
230
- { updatedA: true },
231
- { updatedA: true }
232
- );
233
- assetOnModelUpdated(
234
- 'dispatching MODEL_UPDATED updates model.partB',
235
- 'B',
236
- { updatedB: true },
237
- { updatedB: true }
238
- );
226
+ assetOnModelUpdated('dispatching MODEL_UPDATED updates model.partA', 'A', { updatedA: true }, { updatedA: true });
227
+ assetOnModelUpdated('dispatching MODEL_UPDATED updates model.partB', 'B', { updatedB: true }, { updatedB: true });
239
228
 
240
229
  assetOnModelUpdated(
241
230
  'dispatching MODEL_UPDATED with update undefined does not update model.partA',
242
231
  'A',
243
232
  undefined,
244
- createDefaultModel(model).partA
233
+ createDefaultModel(model).partA,
245
234
  );
246
235
  assetOnModelUpdated(
247
236
  'dispatching MODEL_UPDATED with update undefined does not update model.partB',
248
237
  'B',
249
238
  undefined,
250
- createDefaultModel(model).partB
239
+ createDefaultModel(model).partB,
251
240
  );
252
241
  });
253
242
 
@@ -261,126 +250,90 @@ describe('index', () => {
261
250
  };
262
251
 
263
252
  describe('part update', () => {
264
- assetPartUpdate(
265
- 'Dispatching Model Updated Event will update Teacher Instructions',
266
- 'partA',
267
- { ...model.partA, teacherInstructions: 'Part A Teacher Instructions' }
268
- );
269
- assetPartUpdate(
270
- 'Dispatching Model Updated Event will update Teacher Instructions',
271
- 'partB',
272
- { ...model.partB, teacherInstructions: 'Part B Teacher Instructions' }
273
- );
274
- assetPartUpdate(
275
- 'Dispatching Model Updated Event will update Prompt',
276
- 'partA',
277
- { ...model.partA, prompt: 'Prompt A' }
278
- );
279
- assetPartUpdate(
280
- 'Dispatching Model Updated Event will update Prompt',
281
- 'partB',
282
- { ...model.partA, prompt: 'Prompt B' }
283
- );
253
+ assetPartUpdate('Dispatching Model Updated Event will update Teacher Instructions', 'partA', {
254
+ ...model.partA,
255
+ teacherInstructions: 'Part A Teacher Instructions',
256
+ });
257
+ assetPartUpdate('Dispatching Model Updated Event will update Teacher Instructions', 'partB', {
258
+ ...model.partB,
259
+ teacherInstructions: 'Part B Teacher Instructions',
260
+ });
261
+ assetPartUpdate('Dispatching Model Updated Event will update Prompt', 'partA', {
262
+ ...model.partA,
263
+ prompt: 'Prompt A',
264
+ });
265
+ assetPartUpdate('Dispatching Model Updated Event will update Prompt', 'partB', {
266
+ ...model.partA,
267
+ prompt: 'Prompt B',
268
+ });
284
269
 
285
- assetPartUpdate(
286
- 'Dispatching Model Updated Event will update Choices - ADD CHOICE',
287
- 'partA',
288
- {
289
- ...model.partA,
290
- choices: [
291
- ...model.partA.choices,
292
- {
293
- label: 'label',
294
- value: utils.firstAvailableIndex(
295
- model.partA.choices.map(c => c.value),
296
- 0
297
- ),
298
- feedback: {
299
- type: 'none'
300
- }
301
- }
302
- ]
303
- }
304
- );
305
- assetPartUpdate(
306
- 'Dispatching Model Updated Event will update Choices - ADD CHOICE',
307
- 'partB',
308
- {
309
- ...model.partB,
310
- choices: [
311
- ...model.partB.choices,
312
- {
313
- label: 'label',
314
- value: utils.firstAvailableIndex(
315
- model.partB.choices.map(c => c.value),
316
- 0
317
- ),
318
- feedback: {
319
- type: 'none'
320
- }
321
- }
322
- ]
323
- }
324
- );
325
- assetPartUpdate(
326
- 'Dispatching Model Updated Event will update Choices - REMOVE CHOICE',
327
- 'partA',
328
- {
329
- ...model.partA,
330
- choices: model.partA.choices.splice(0, 2)
331
- }
332
- );
333
- assetPartUpdate(
334
- 'Dispatching Model Updated Event will update Choices - REMOVE CHOICE',
335
- 'partB',
336
- {
337
- ...model.partB,
338
- choices: model.partB.choices.splice(0, 2)
339
- }
340
- );
341
- assetPartUpdate(
342
- 'Dispatching Model Updated Event will update Choices - CHANGE CHOICE',
343
- 'partA',
344
- {
345
- ...model.partA,
346
- choices: model.partA.choices.splice(1, 1, {
347
- correct: true,
348
- value: 'green',
349
- label: value => value.charAt(0).toUpperCase() + value.slice(1),
270
+ assetPartUpdate('Dispatching Model Updated Event will update Choices - ADD CHOICE', 'partA', {
271
+ ...model.partA,
272
+ choices: [
273
+ ...model.partA.choices,
274
+ {
275
+ label: 'label',
276
+ value: utils.firstAvailableIndex(
277
+ model.partA.choices.map((c) => c.value),
278
+ 0,
279
+ ),
350
280
  feedback: {
351
281
  type: 'none',
352
- value: ''
353
- }
354
- })
355
- }
356
- );
357
- assetPartUpdate(
358
- 'Dispatching Model Updated Event will update Choices - CHANGE CHOICE',
359
- 'partB',
360
- {
361
- ...model.partB,
362
- choices: model.partB.choices.splice(1, 1, {
363
- correct: true,
364
- value: 'green',
365
- label: value => value.charAt(0).toUpperCase() + value.slice(1),
282
+ },
283
+ },
284
+ ],
285
+ });
286
+ assetPartUpdate('Dispatching Model Updated Event will update Choices - ADD CHOICE', 'partB', {
287
+ ...model.partB,
288
+ choices: [
289
+ ...model.partB.choices,
290
+ {
291
+ label: 'label',
292
+ value: utils.firstAvailableIndex(
293
+ model.partB.choices.map((c) => c.value),
294
+ 0,
295
+ ),
366
296
  feedback: {
367
297
  type: 'none',
368
- value: ''
369
- }
370
- })
371
- }
372
- );
298
+ },
299
+ },
300
+ ],
301
+ });
302
+ assetPartUpdate('Dispatching Model Updated Event will update Choices - REMOVE CHOICE', 'partA', {
303
+ ...model.partA,
304
+ choices: model.partA.choices.splice(0, 2),
305
+ });
306
+ assetPartUpdate('Dispatching Model Updated Event will update Choices - REMOVE CHOICE', 'partB', {
307
+ ...model.partB,
308
+ choices: model.partB.choices.splice(0, 2),
309
+ });
310
+ assetPartUpdate('Dispatching Model Updated Event will update Choices - CHANGE CHOICE', 'partA', {
311
+ ...model.partA,
312
+ choices: model.partA.choices.splice(1, 1, {
313
+ correct: true,
314
+ value: 'green',
315
+ label: (value) => value.charAt(0).toUpperCase() + value.slice(1),
316
+ feedback: {
317
+ type: 'none',
318
+ value: '',
319
+ },
320
+ }),
321
+ });
322
+ assetPartUpdate('Dispatching Model Updated Event will update Choices - CHANGE CHOICE', 'partB', {
323
+ ...model.partB,
324
+ choices: model.partB.choices.splice(1, 1, {
325
+ correct: true,
326
+ value: 'green',
327
+ label: (value) => value.charAt(0).toUpperCase() + value.slice(1),
328
+ feedback: {
329
+ type: 'none',
330
+ value: '',
331
+ },
332
+ }),
333
+ });
373
334
 
374
- assetPartUpdate(
375
- 'Dispatching Model Updated Event will update Choices',
376
- 'partA',
377
- { ...model.partA, choices: [] }
378
- );
379
- assetPartUpdate(
380
- 'Dispatching Model Updated Event will update Choices',
381
- 'partB',
382
- { ...model.partB, choices: [] }
383
- );
335
+ assetPartUpdate('Dispatching Model Updated Event will update Choices', 'partA', { ...model.partA, choices: [] });
336
+ assetPartUpdate('Dispatching Model Updated Event will update Choices', 'partB', { ...model.partB, choices: [] });
384
337
  });
385
338
  });
386
339
 
@@ -406,7 +359,7 @@ describe('main', () => {
406
359
  configuration={defaults.configuration}
407
360
  onConfigurationChanged={el.onConfigurationChanged}
408
361
  onModelChanged={el.onModelChanged}
409
- />
362
+ />,
410
363
  );
411
364
  });
412
365
 
@@ -424,29 +377,29 @@ describe('main', () => {
424
377
  'changes partA - checkbox',
425
378
  {
426
379
  partA: {
427
- choiceMode: 'checkbox'
428
- }
380
+ choiceMode: 'checkbox',
381
+ },
429
382
  },
430
383
  {
431
384
  ...model,
432
385
  partA: {
433
- choiceMode: 'checkbox'
434
- }
435
- }
386
+ choiceMode: 'checkbox',
387
+ },
388
+ },
436
389
  );
437
390
  assertOnModelChanged(
438
391
  'changes partA - choicePrefix',
439
392
  {
440
393
  partA: {
441
- choicePrefix: 'numbers'
442
- }
394
+ choicePrefix: 'numbers',
395
+ },
443
396
  },
444
397
  {
445
398
  ...model,
446
399
  partA: {
447
- choicePrefix: 'numbers'
448
- }
449
- }
400
+ choicePrefix: 'numbers',
401
+ },
402
+ },
450
403
  );
451
404
  assertOnModelChanged(
452
405
  'changes partA - partialScoring',
@@ -455,94 +408,94 @@ describe('main', () => {
455
408
  },
456
409
  {
457
410
  ...model,
458
- partialScoring: false
459
- }
411
+ partialScoring: false,
412
+ },
460
413
  );
461
414
  assertOnModelChanged(
462
415
  'changes partA - lockChoiceOrder',
463
416
  {
464
417
  partA: {
465
- lockChoiceOrder: true
466
- }
418
+ lockChoiceOrder: true,
419
+ },
467
420
  },
468
421
  {
469
422
  ...model,
470
423
  partA: {
471
- lockChoiceOrder: true
472
- }
473
- }
424
+ lockChoiceOrder: true,
425
+ },
426
+ },
474
427
  );
475
428
  assertOnModelChanged(
476
429
  'changes partA - scoringType',
477
430
  {
478
- scoringType: 'auto'
431
+ scoringType: 'auto',
479
432
  },
480
433
  {
481
434
  ...model,
482
- scoringType: 'auto'
483
- }
435
+ scoringType: 'auto',
436
+ },
484
437
  );
485
438
  assertOnModelChanged(
486
439
  'changes partB - checkbox',
487
440
  {
488
441
  partB: {
489
- choiceMode: 'checkbox'
490
- }
442
+ choiceMode: 'checkbox',
443
+ },
491
444
  },
492
445
  {
493
446
  ...model,
494
447
  partB: {
495
- choiceMode: 'checkbox'
496
- }
497
- }
448
+ choiceMode: 'checkbox',
449
+ },
450
+ },
498
451
  );
499
452
  assertOnModelChanged(
500
453
  'changes partB - choicePrefix',
501
454
  {
502
455
  partB: {
503
- choicePrefix: 'numbers'
504
- }
456
+ choicePrefix: 'numbers',
457
+ },
505
458
  },
506
459
  {
507
460
  ...model,
508
461
  partB: {
509
- choicePrefix: 'numbers'
510
- }
511
- }
462
+ choicePrefix: 'numbers',
463
+ },
464
+ },
512
465
  );
513
466
  assertOnModelChanged(
514
467
  'changes partB - partialScoring',
515
468
  {
516
- partialScoring: false
469
+ partialScoring: false,
517
470
  },
518
471
  {
519
472
  ...model,
520
- partialScoring: false
521
- }
473
+ partialScoring: false,
474
+ },
522
475
  );
523
476
  assertOnModelChanged(
524
477
  'changes partB - lockChoiceOrder',
525
478
  {
526
479
  partB: {
527
- lockChoiceOrder: true
528
- }
480
+ lockChoiceOrder: true,
481
+ },
529
482
  },
530
483
  {
531
484
  ...model,
532
485
  partB: {
533
- lockChoiceOrder: true
534
- }
535
- }
486
+ lockChoiceOrder: true,
487
+ },
488
+ },
536
489
  );
537
490
  assertOnModelChanged(
538
491
  'changes partB - scoringType',
539
492
  {
540
- scoringType: 'auto'
493
+ scoringType: 'auto',
541
494
  },
542
495
  {
543
496
  ...model,
544
- scoringType: 'auto'
545
- }
497
+ scoringType: 'auto',
498
+ },
546
499
  );
547
500
  });
548
501
  });