@coorpacademy/app-review 0.1.17 → 0.1.18

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 (63) hide show
  1. package/es/actions/api/post-answer.d.ts +5 -1
  2. package/es/actions/ui/answers.d.ts +1 -1
  3. package/es/actions/ui/answers.js +6 -4
  4. package/es/actions/ui/test/answers.test.js +15 -5
  5. package/es/reducers/data/index.d.ts +1 -1
  6. package/es/reducers/data/progression.d.ts +2 -1
  7. package/es/reducers/data/progression.js +2 -0
  8. package/es/reducers/data/test/progression.test.js +11 -26
  9. package/es/reducers/index.d.ts +1 -1
  10. package/es/reducers/ui/index.d.ts +1 -1
  11. package/es/reducers/ui/test/answers.test.js +4 -0
  12. package/es/test/util/services.mock.d.ts +1 -0
  13. package/es/test/util/services.mock.js +4 -1
  14. package/es/views/slides/index.js +1 -1
  15. package/es/views/slides/map-api-slide-to-ui.js +26 -22
  16. package/es/views/slides/test/fixtures/template.d.ts +4 -0
  17. package/es/views/slides/test/fixtures/{select-template.js → template.js} +82 -4
  18. package/es/views/slides/test/index.test.js +239 -0
  19. package/es/views/slides/test/map-api-slide-to-ui.test.js +4 -10
  20. package/es/views/slides/test/slide.template.on-change.test.d.ts +1 -0
  21. package/es/views/slides/test/slide.template.on-change.test.js +79 -0
  22. package/lib/actions/api/post-answer.d.ts +5 -1
  23. package/lib/actions/ui/answers.d.ts +1 -1
  24. package/lib/actions/ui/answers.js +6 -4
  25. package/lib/actions/ui/test/answers.test.js +24 -5
  26. package/lib/reducers/data/index.d.ts +1 -1
  27. package/lib/reducers/data/progression.d.ts +2 -1
  28. package/lib/reducers/data/progression.js +2 -0
  29. package/lib/reducers/data/test/progression.test.js +11 -26
  30. package/lib/reducers/index.d.ts +1 -1
  31. package/lib/reducers/ui/index.d.ts +1 -1
  32. package/lib/reducers/ui/test/answers.test.js +4 -0
  33. package/lib/test/util/services.mock.d.ts +1 -0
  34. package/lib/test/util/services.mock.js +4 -1
  35. package/lib/views/slides/index.js +1 -1
  36. package/lib/views/slides/map-api-slide-to-ui.js +34 -28
  37. package/lib/views/slides/test/fixtures/template.d.ts +4 -0
  38. package/lib/views/slides/test/fixtures/{select-template.js → template.js} +82 -4
  39. package/lib/views/slides/test/index.test.js +239 -0
  40. package/lib/views/slides/test/map-api-slide-to-ui.test.js +4 -10
  41. package/lib/views/slides/test/slide.template.on-change.test.d.ts +1 -0
  42. package/lib/views/slides/test/slide.template.on-change.test.js +82 -0
  43. package/package.json +3 -3
  44. package/src/actions/api/post-answer.ts +6 -1
  45. package/src/actions/ui/answers.ts +8 -6
  46. package/src/actions/ui/test/answers.test.ts +17 -5
  47. package/src/reducers/data/progression.ts +3 -1
  48. package/src/reducers/data/test/progression.test.ts +12 -28
  49. package/src/reducers/ui/test/answers.test.ts +5 -0
  50. package/src/test/util/services.mock.ts +4 -1
  51. package/src/views/slides/index.ts +1 -1
  52. package/src/views/slides/map-api-slide-to-ui.ts +63 -30
  53. package/src/views/slides/test/fixtures/{select-template.ts → template.ts} +82 -4
  54. package/src/views/slides/test/index.test.ts +253 -0
  55. package/src/views/slides/test/map-api-slide-to-ui.test.ts +4 -10
  56. package/src/views/slides/test/slide.template.on-change.test.ts +92 -0
  57. package/es/views/slides/test/fixtures/select-template.d.ts +0 -4
  58. package/es/views/slides/test/fixtures/text-template.d.ts +0 -4
  59. package/es/views/slides/test/fixtures/text-template.js +0 -58
  60. package/lib/views/slides/test/fixtures/select-template.d.ts +0 -4
  61. package/lib/views/slides/test/fixtures/text-template.d.ts +0 -4
  62. package/lib/views/slides/test/fixtures/text-template.js +0 -58
  63. package/src/views/slides/test/fixtures/text-template.ts +0 -62
@@ -1,4 +1,4 @@
1
- import { concat, divide, get, getOr, head, includes, indexOf, isEmpty, map, multiply, pipe, rangeStep, round, size, toInteger, toString as _toString, __ } from 'lodash/fp';
1
+ import { concat, constant, divide, get, getOr, head, includes, indexOf, isEmpty, isNil, map, multiply, pipe, rangeStep, round, set, size, times, toInteger, toString as _toString, __ } from 'lodash/fp';
2
2
  import { editAnswer } from '../../actions/ui/answers';
3
3
  var qcmProps = function (dispatch) {
4
4
  return function (answers, question) {
@@ -10,7 +10,7 @@ var qcmProps = function (dispatch) {
10
10
  title: label,
11
11
  selected: includes(label, answers),
12
12
  onClick: function () {
13
- dispatch(editAnswer(label));
13
+ dispatch(editAnswer([label]));
14
14
  },
15
15
  ariaLabel: choice.label
16
16
  };
@@ -30,7 +30,7 @@ var qcmDragProps = function (dispatch) {
30
30
  selected: includes(label, answers),
31
31
  order: indexInAnswer,
32
32
  onClick: function () {
33
- dispatch(editAnswer(label));
33
+ dispatch(editAnswer([label]));
34
34
  }
35
35
  };
36
36
  }, question.content.choices)
@@ -48,29 +48,30 @@ var qcmGraphicProps = function (dispatch) {
48
48
  image: get('media.src.0.url', choice),
49
49
  selected: includes(label, answers),
50
50
  onClick: function () {
51
- dispatch(editAnswer(label));
51
+ dispatch(editAnswer([label]));
52
52
  }
53
53
  };
54
54
  }, question.content.choices)
55
55
  };
56
56
  };
57
57
  };
58
- var templateTextProps = function (choice, index) {
59
- // TODO: EDIT_CHOICES -> getAnswerValues
60
- var answers = [];
58
+ var updateTemplateAnswer = function (text, _answers, index, max) {
59
+ var answers = isEmpty(_answers) ? times(constant(undefined), max) : _answers;
60
+ return map(function (a) { return (isNil(a) ? '' : a); }, set(index, text, answers));
61
+ };
62
+ var templateTextProps = function (dispatch, answers, choice, index, maxLength) {
61
63
  return {
62
64
  type: 'text',
63
65
  name: getOr('', 'name', choice),
64
66
  placeholder: 'Type here',
65
67
  value: get(index, answers),
66
- // TODO: EDIT_CHOICES
67
- // eslint-disable-next-line no-console
68
- onChange: function () { return console.log('TODO: on choice change'); }
68
+ onChange: function (text) {
69
+ var newAnswers = updateTemplateAnswer(text, answers, index, maxLength);
70
+ dispatch(editAnswer(newAnswers));
71
+ }
69
72
  };
70
73
  };
71
- var templateSelectProps = function (choice, index) {
72
- // TODO: EDIT_CHOICES -> getAnswerValues
73
- var answers = [];
74
+ var templateSelectProps = function (dispatch, answers, choice, index, maxLength) {
74
75
  var answer = get(index, answers);
75
76
  var temporaryOption = {
76
77
  name: 'Select an answer',
@@ -90,21 +91,26 @@ var templateSelectProps = function (choice, index) {
90
91
  return {
91
92
  type: 'select',
92
93
  name: getOr('', 'name', choice),
93
- // TODO: EDIT_CHOICES
94
- // eslint-disable-next-line no-console
95
- onChange: function () { return console.log('TODO: on choice change'); },
94
+ onChange: function (text) {
95
+ var newAnswers = updateTemplateAnswer(text, answers, index, maxLength);
96
+ dispatch(editAnswer(newAnswers));
97
+ },
96
98
  options: isEmpty(answer) ? concat([temporaryOption], selectOptions) : selectOptions
97
99
  };
98
100
  };
99
- var templateProps = function (question) {
100
- // TODO: EDIT_CHOICES -> getChoices
101
- var choices = question.content.choices;
102
- return {
103
- type: 'template',
104
- template: get('content.template', question),
105
- answers: choices.map(function (choice, index) {
106
- return choice.type === 'text' ? templateTextProps(choice, index) : templateSelectProps(choice, index);
107
- })
101
+ var templateProps = function (dispatch) {
102
+ return function (answers, question) {
103
+ var choices = question.content.choices;
104
+ var maxLength = size(choices);
105
+ return {
106
+ type: 'template',
107
+ template: get('content.template', question),
108
+ answers: choices.map(function (choice, index) {
109
+ return choice.type === 'text'
110
+ ? templateTextProps(dispatch, answers, choice, index, maxLength)
111
+ : templateSelectProps(dispatch, answers, choice, index, maxLength);
112
+ })
113
+ };
108
114
  };
109
115
  };
110
116
  var basicProps = function (dispatch) {
@@ -114,7 +120,7 @@ var basicProps = function (dispatch) {
114
120
  placeholder: question.content.placeholder || '',
115
121
  value: answers[0] || '',
116
122
  onChange: function (text) {
117
- dispatch(editAnswer(text));
123
+ dispatch(editAnswer([text]));
118
124
  }
119
125
  };
120
126
  };
@@ -139,7 +145,7 @@ var sliderProps = function (dispatch) {
139
145
  value: sliderPosition,
140
146
  onChange: function (position) {
141
147
  var newValue = pipe(multiply(maxValue), round, get(__, values), _toString)(position);
142
- dispatch(editAnswer(newValue));
148
+ dispatch(editAnswer([newValue]));
143
149
  }
144
150
  };
145
151
  };
@@ -158,7 +164,7 @@ var getAnswerUIModel = function (question, answers, dispatch) {
158
164
  case 'basic':
159
165
  return basicProps(dispatch)(answers, question);
160
166
  case 'template':
161
- return templateProps(question);
167
+ return templateProps(dispatch)(answers, question);
162
168
  case 'slider':
163
169
  return sliderProps(dispatch)(answers, question);
164
170
  default:
@@ -0,0 +1,4 @@
1
+ import { UISlide } from '../..';
2
+ import { SlideFromAPI } from '../../../../types/common';
3
+ export declare const templateSlide: SlideFromAPI;
4
+ export declare const templateUISlide: Partial<UISlide>;
@@ -1,8 +1,8 @@
1
1
  import noop from 'lodash/fp/noop';
2
- export var selectTemplateSlide = {
2
+ export var templateSlide = {
3
3
  question: {
4
4
  content: {
5
- template: 'La vue {{sel80495}} présente la liste des utilisateurs ayant le plus grand nombre d’étoiles cumulées.',
5
+ template: 'La vue {{sel80495}} présente la liste des {{inp58402}} ayant le plus grand nombre d’{{sel80496}} cumulées.',
6
6
  choices: [
7
7
  {
8
8
  items: [
@@ -30,6 +30,45 @@ export var selectTemplateSlide = {
30
30
  _id: '5b57464e3b594d002e8829f3',
31
31
  name: 'sel80495',
32
32
  type: 'select'
33
+ },
34
+ {
35
+ media: {
36
+ src: [],
37
+ posters: [],
38
+ subtitles: []
39
+ },
40
+ items: [],
41
+ _id: '62433c2c58920f02c4950de0',
42
+ type: 'text',
43
+ name: 'inp58402',
44
+ id: '62433c2c58920f02c4950de0'
45
+ },
46
+ {
47
+ items: [
48
+ {
49
+ _id: '5b57464e3b594d002e8829f7',
50
+ value: 'sli_N13-hG3kX.choice_NJgC3aznJm',
51
+ text: 'étoiles'
52
+ },
53
+ {
54
+ _id: '5b57464e3b594d002e8829f6',
55
+ value: 'sli_N13-hG3kX.choice_EJZ02aMny7',
56
+ text: 'idées'
57
+ },
58
+ {
59
+ _id: '5b57464e3b594d002e8829f5',
60
+ value: 'sli_N13-hG3kX.choice_4keCaf21Q',
61
+ text: 'envies'
62
+ },
63
+ {
64
+ _id: '5b57464e3b594d002e8829f4',
65
+ value: 'sli_N13-hG3kX.choice_NkbJAMn17',
66
+ text: 'images'
67
+ }
68
+ ],
69
+ _id: '5b57464e3b594d002e8829f3',
70
+ name: 'sel80496',
71
+ type: 'select'
33
72
  }
34
73
  ]
35
74
  },
@@ -46,13 +85,13 @@ export var selectTemplateSlide = {
46
85
  type: 'course'
47
86
  }
48
87
  };
49
- export var selectTemplateUISlide = {
88
+ export var templateUISlide = {
50
89
  questionText: 'Complétez la phrase ci-dessous.',
51
90
  answerUI: {
52
91
  help: 'Saisissez votre réponse ou sélectionnez la bonne réponse dans le(s) menu(s) déroulant(s).',
53
92
  model: {
54
93
  type: 'template',
55
- template: 'La vue {{sel80495}} présente la liste des utilisateurs ayant le plus grand nombre d’étoiles cumulées.',
94
+ template: 'La vue {{sel80495}} présente la liste des {{inp58402}} ayant le plus grand nombre d’{{sel80496}} cumulées.',
56
95
  answers: [
57
96
  {
58
97
  type: 'select',
@@ -85,6 +124,45 @@ export var selectTemplateUISlide = {
85
124
  selected: false
86
125
  }
87
126
  ]
127
+ },
128
+ {
129
+ type: 'text',
130
+ name: 'inp58402',
131
+ placeholder: 'Type here',
132
+ value: undefined,
133
+ onChange: noop
134
+ },
135
+ {
136
+ type: 'select',
137
+ name: 'sel80496',
138
+ onChange: noop,
139
+ options: [
140
+ { name: 'Select an answer', value: '', validOption: false, selected: true },
141
+ {
142
+ name: 'étoiles',
143
+ value: 'étoiles',
144
+ validOption: true,
145
+ selected: false
146
+ },
147
+ {
148
+ name: 'idées',
149
+ value: 'idées',
150
+ validOption: true,
151
+ selected: false
152
+ },
153
+ {
154
+ name: 'envies',
155
+ value: 'envies',
156
+ validOption: true,
157
+ selected: false
158
+ },
159
+ {
160
+ name: 'images',
161
+ value: 'images',
162
+ validOption: true,
163
+ selected: false
164
+ }
165
+ ]
88
166
  }
89
167
  ]
90
168
  }
@@ -232,3 +232,242 @@ test('should create initial props when the slide is on the state', function (t)
232
232
  }
233
233
  });
234
234
  });
235
+ test('should create props when the next slide is on the state', function (t) {
236
+ var state = {
237
+ data: {
238
+ progression: {
239
+ _id: '62b1d1087aa12f00253f40ee',
240
+ content: {
241
+ ref: '_skill-ref',
242
+ type: 'skill'
243
+ },
244
+ engine: {
245
+ ref: 'review'
246
+ },
247
+ state: {
248
+ allAnswers: [
249
+ {
250
+ slideRef: 'sli_VJYjJnJhg',
251
+ isCorrect: true,
252
+ answer: ['Benchmark']
253
+ }
254
+ ],
255
+ isCorrect: true,
256
+ nextContent: {
257
+ ref: 'sli_VkSQroQnx',
258
+ type: 'slide'
259
+ },
260
+ content: {
261
+ ref: 'sli_VJYjJnJhg',
262
+ type: 'slide'
263
+ },
264
+ pendingSlides: [],
265
+ slides: ['sli_VJYjJnJhg'],
266
+ step: {
267
+ current: 2
268
+ },
269
+ stars: 4
270
+ }
271
+ },
272
+ skills: [],
273
+ slides: {
274
+ sli_VJYjJnJhg: {
275
+ question: {
276
+ content: {
277
+ media: {
278
+ src: [],
279
+ posters: [],
280
+ subtitles: []
281
+ },
282
+ label: '',
283
+ placeholder: 'Type here',
284
+ id: 'sli_VJYjJnJhg.choice_1'
285
+ },
286
+ type: 'basic',
287
+ header: 'Which term is used to describe the act of asking what the usual salary is for the position you are applying for?',
288
+ explanation: 'Type your answer.'
289
+ },
290
+ klf: 'To negotiate your salary when being hired, you have to establish a benchmark beforehand. In other words, you should assess the salary to which you aspire by enquiring about the remuneration paid in the same industry, the same region and the same position.',
291
+ tips: 'According to Insee, Paris salaries are 20-25% higher compared with those of the provinces in 2015.',
292
+ universalRef: 'sli_VJYjJnJhg',
293
+ id: 'sli_VJYjJnJhg',
294
+ parentContentTitle: {
295
+ title: 'Developing the review app',
296
+ type: 'course'
297
+ }
298
+ },
299
+ sli_VkSQroQnx: {
300
+ question: {
301
+ content: {
302
+ media: {
303
+ src: [],
304
+ posters: [],
305
+ subtitles: []
306
+ },
307
+ choices: [
308
+ {
309
+ media: {
310
+ src: [
311
+ {
312
+ _id: '624efd915948a7013083e986',
313
+ mimeType: 'image/jpeg',
314
+ url: '//static.coorpacademy.com/content/CoorpAcademy/content-partnerships/cockpit-partner-au-feminin/default/true-1512554153232.jpg',
315
+ id: '624efd915948a7013083e986'
316
+ }
317
+ ],
318
+ posters: [],
319
+ subtitles: [],
320
+ type: 'img'
321
+ },
322
+ items: [],
323
+ _id: '624efd915948a7013083e985',
324
+ label: 'Vrai',
325
+ value: 'sli_VkSQroQnx.choice_NJesyUo7nx',
326
+ id: '624efd915948a7013083e985'
327
+ },
328
+ {
329
+ media: {
330
+ src: [
331
+ {
332
+ _id: '624efd915948a7013083e988',
333
+ mimeType: 'image/jpeg',
334
+ url: '//static.coorpacademy.com/content/CoorpAcademy/content-partnerships/cockpit-partner-au-feminin/default/false-1512554160848.jpg',
335
+ id: '624efd915948a7013083e988'
336
+ }
337
+ ],
338
+ posters: [],
339
+ subtitles: [],
340
+ type: 'img'
341
+ },
342
+ items: [],
343
+ _id: '624efd915948a7013083e987',
344
+ label: 'Faux',
345
+ value: 'sli_VkSQroQnx.choice_VkgayLjX3e',
346
+ id: '624efd915948a7013083e987'
347
+ }
348
+ ]
349
+ },
350
+ type: 'qcmGraphic',
351
+ header: 'Pour mener une bonne négociation, il ne faut ressentir aucune émotion. Vrai ou faux ?',
352
+ explanation: 'Sélectionnez la bonne réponse.'
353
+ },
354
+ klf: "Il ne faut pas prendre la négociation comme une affaire personnelle, afin de rester centré sur son sujet. Mais cela ne signifie pas être dépourvu de toute émotion, car celles-ci peuvent être de vrais atouts. À condition de réussir à les exprimer sans accuser l'autre d'en être à l'origine.",
355
+ tips: "Pour gérer ses émotions, il faut d'abord les identifier, notamment en analysant ses ressentis physiques et en trouvant l'élément déclencheur.",
356
+ universalRef: 'sli_VkSQroQnx',
357
+ id: 'sli_VkSQroQnx',
358
+ parentContentTitle: {
359
+ title: 'Developing the review app',
360
+ type: 'course'
361
+ }
362
+ }
363
+ },
364
+ token: 'undefined'
365
+ },
366
+ ui: {
367
+ currentSlideRef: 'sli_VJYjJnJhg',
368
+ navigation: ['loader', 'slides'],
369
+ answers: ['My value'],
370
+ slide: {
371
+ validateButton: false
372
+ }
373
+ }
374
+ };
375
+ var props = mapStateToSlidesProps(state, identity);
376
+ t.is(props.congratsProps, undefined);
377
+ t.deepEqual(omit(['onQuitClick'], props.header), {
378
+ 'aria-label': 'aria-header-wrapper',
379
+ closeButtonAriaLabel: 'aria-close-button',
380
+ mode: '__revision_mode',
381
+ skillName: '__agility',
382
+ steps: [
383
+ {
384
+ current: true,
385
+ icon: 'right',
386
+ value: '1'
387
+ },
388
+ {
389
+ // FIX ME: update on PR -> https://trello.com/c/qOSDa8Fm/2715-app-review-props-dynamiques-pour-les-step-items-du-header-bas%C3%A9-sur-le-state
390
+ current: true,
391
+ icon: 'no-answer',
392
+ value: '2'
393
+ },
394
+ {
395
+ current: false,
396
+ icon: 'no-answer',
397
+ value: '3'
398
+ },
399
+ {
400
+ current: false,
401
+ icon: 'no-answer',
402
+ value: '4'
403
+ },
404
+ {
405
+ current: false,
406
+ icon: 'no-answer',
407
+ value: '5'
408
+ }
409
+ ]
410
+ });
411
+ t.deepEqual(omit(['validateButton', 'slides'], props.stack), {
412
+ correctionPopinProps: undefined,
413
+ endReview: false
414
+ });
415
+ t.true(props.stack.validateButton.disabled);
416
+ t.deepEqual(omit('answerUI', props.stack.slides['0']), {
417
+ hidden: false,
418
+ position: 0,
419
+ loading: false,
420
+ parentContentTitle: 'From "Developing the review app" course',
421
+ questionText: 'Which term is used to describe the act of asking what the usual salary is for the position you are applying for?'
422
+ });
423
+ t.deepEqual(omit('model.onChange', props.stack.slides['0'].answerUI), {
424
+ help: 'Type your answer.',
425
+ model: {
426
+ placeholder: 'Type here',
427
+ type: 'freeText',
428
+ value: 'My value'
429
+ }
430
+ });
431
+ t.deepEqual(omit(['0', '1.answerUI.model.answers.0.onClick', '1.answerUI.model.answers.1.onClick'], props.stack.slides), {
432
+ '1': {
433
+ answerUI: {
434
+ help: 'Sélectionnez la bonne réponse.',
435
+ model: {
436
+ answers: [
437
+ {
438
+ image: '//static.coorpacademy.com/content/CoorpAcademy/content-partnerships/cockpit-partner-au-feminin/default/true-1512554153232.jpg',
439
+ selected: false,
440
+ title: 'Vrai'
441
+ },
442
+ {
443
+ image: '//static.coorpacademy.com/content/CoorpAcademy/content-partnerships/cockpit-partner-au-feminin/default/false-1512554160848.jpg',
444
+ selected: false,
445
+ title: 'Faux'
446
+ }
447
+ ],
448
+ type: 'qcmGraphic'
449
+ }
450
+ },
451
+ hidden: false,
452
+ loading: false,
453
+ position: 1,
454
+ parentContentTitle: 'From "Developing the review app" course',
455
+ questionText: 'Pour mener une bonne négociation, il ne faut ressentir aucune émotion. Vrai ou faux ?'
456
+ },
457
+ '2': {
458
+ hidden: false,
459
+ position: 2,
460
+ loading: true
461
+ },
462
+ '3': {
463
+ hidden: false,
464
+ position: 3,
465
+ loading: true
466
+ },
467
+ '4': {
468
+ hidden: false,
469
+ position: 4,
470
+ loading: true
471
+ }
472
+ });
473
+ });
@@ -16,8 +16,7 @@ import { qcmUISlide, qcmSlide } from './fixtures/qcm';
16
16
  import { qcmDragUISlide, qcmDragSlide } from './fixtures/qcm-drag';
17
17
  import { freeTextSlide, freeTextUISlide } from './fixtures/free-text';
18
18
  import { qcmGraphicUISlide, qcmGraphicSlide } from './fixtures/qcm-graphic';
19
- import { textTemplateSlide, textTemplateUISlide } from './fixtures/text-template';
20
- import { selectTemplateSlide, selectTemplateUISlide } from './fixtures/select-template';
19
+ import { templateSlide, templateUISlide } from './fixtures/template';
21
20
  import { sliderSlide, sliderUISlide } from './fixtures/slider';
22
21
  var _mapApiSlideToUi = mapApiSlideToUi(identity);
23
22
  var macro = test.macro({
@@ -35,15 +34,10 @@ test('qcm graphic', macro, {
35
34
  answers: [],
36
35
  expectedUiSlide: qcmGraphicUISlide
37
36
  });
38
- test('text template', macro, {
39
- slide: textTemplateSlide,
37
+ test('template', macro, {
38
+ slide: templateSlide,
40
39
  answers: [],
41
- expectedUiSlide: textTemplateUISlide
42
- });
43
- test('select template', macro, {
44
- slide: selectTemplateSlide,
45
- answers: [],
46
- expectedUiSlide: selectTemplateUISlide
40
+ expectedUiSlide: templateUISlide
47
41
  });
48
42
  test('free text', macro, { slide: freeTextSlide, answers: [], expectedUiSlide: freeTextUISlide });
49
43
  test('slider', macro, { slide: sliderSlide, answers: [], expectedUiSlide: sliderUISlide });
@@ -0,0 +1,82 @@
1
+ var _a;
2
+ import test from 'ava';
3
+ import omit from 'lodash/fp/omit';
4
+ import get from 'lodash/fp/get';
5
+ import { mapStateToSlidesProps } from '..';
6
+ import { services } from '../../../test/util/services.mock';
7
+ import { createTestStore } from '../../../actions/test/create-test-store';
8
+ import { EDIT_TEMPLATE } from '../../../actions/ui/answers';
9
+ import { templateSlide } from './fixtures/template';
10
+ var progression = {
11
+ _id: '123456789123',
12
+ content: { type: 'skill', ref: '_skill-ref' },
13
+ engine: {
14
+ ref: 'review'
15
+ },
16
+ state: {
17
+ allAnswers: [],
18
+ isCorrect: true,
19
+ nextContent: {
20
+ ref: templateSlide.id,
21
+ type: 'slide'
22
+ },
23
+ pendingSlides: [],
24
+ slides: [],
25
+ step: {
26
+ current: 1
27
+ },
28
+ stars: 0
29
+ }
30
+ };
31
+ var initialState = {
32
+ data: {
33
+ progression: progression,
34
+ slides: (_a = {},
35
+ _a[templateSlide.id] = templateSlide,
36
+ _a),
37
+ skills: [],
38
+ token: '1234'
39
+ },
40
+ ui: {
41
+ currentSlideRef: templateSlide.id,
42
+ navigation: ['skills', 'slides'],
43
+ answers: [],
44
+ slide: {
45
+ validateButton: false
46
+ }
47
+ }
48
+ };
49
+ test('should dispatch EDIT_TEMPLATE action via the property onChange of a Template Text slide', function (t) {
50
+ var _a;
51
+ t.plan(2);
52
+ var expectedActions = [{ type: EDIT_TEMPLATE, payload: ['', 'test', ''] }];
53
+ var _b = createTestStore(t, initialState, services, expectedActions), dispatch = _b.dispatch, getState = _b.getState;
54
+ var props = mapStateToSlidesProps(getState(), dispatch);
55
+ t.deepEqual(omit('answerUI', props.stack.slides['0']), {
56
+ hidden: false,
57
+ position: 0,
58
+ loading: false,
59
+ parentContentTitle: 'From "Developing the review app" course',
60
+ questionText: 'Complétez la phrase ci-dessous.'
61
+ });
62
+ var SlideProps = (_a = props.stack.slides['0'].answerUI) === null || _a === void 0 ? void 0 : _a.model;
63
+ var onChange = get(['1', 'onChange'], SlideProps.answers);
64
+ onChange('test');
65
+ });
66
+ test('should dispatch EDIT_TEMPLATE action via the property onChange of a Template Select slide', function (t) {
67
+ var _a;
68
+ t.plan(2);
69
+ var expectedActions = [{ type: EDIT_TEMPLATE, payload: ['Catalogue', '', ''] }];
70
+ var _b = createTestStore(t, initialState, services, expectedActions), dispatch = _b.dispatch, getState = _b.getState;
71
+ var props = mapStateToSlidesProps(getState(), dispatch);
72
+ t.deepEqual(omit('answerUI', props.stack.slides['0']), {
73
+ hidden: false,
74
+ position: 0,
75
+ loading: false,
76
+ parentContentTitle: 'From "Developing the review app" course',
77
+ questionText: 'Complétez la phrase ci-dessous.'
78
+ });
79
+ var SlideProps = (_a = props.stack.slides['0'].answerUI) === null || _a === void 0 ? void 0 : _a.model;
80
+ var onChange = get(['0', 'onChange'], SlideProps.answers);
81
+ onChange('Catalogue');
82
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coorpacademy/app-review",
3
- "version": "0.1.17",
3
+ "version": "0.1.18",
4
4
  "description": "",
5
5
  "engines": {
6
6
  "node": ">=16.15.0"
@@ -41,7 +41,7 @@
41
41
  "./package.json": "./package.json"
42
42
  },
43
43
  "dependencies": {
44
- "@coorpacademy/components": "10.22.11",
44
+ "@coorpacademy/components": "10.22.12",
45
45
  "@coorpacademy/redux-task": "^1.1.5",
46
46
  "cross-fetch": "^3.1.5",
47
47
  "jwt-decode": "^3.1.2",
@@ -78,5 +78,5 @@
78
78
  "ts-node": "^10.9.1",
79
79
  "typescript": "^4.7.4"
80
80
  },
81
- "gitHead": "7191ac405f4eebce61c459722595014ea973818c"
81
+ "gitHead": "2b9abf8c945cd56a6a47091836e4961917580782"
82
82
  }
@@ -1,7 +1,7 @@
1
1
  import type {Dispatch} from 'redux';
2
2
  import buildTask from '@coorpacademy/redux-task';
3
3
  import get from 'lodash/fp/get';
4
- import type {Options} from '../../types/common';
4
+ import type {Options, ProgressionFromAPI} from '../../types/common';
5
5
  import type {StoreState} from '../../reducers';
6
6
  import {fetchSlide} from './fetch-slide';
7
7
 
@@ -13,6 +13,11 @@ export type PostAnswerRequestAction = {
13
13
  type: typeof POST_ANSWER_REQUEST;
14
14
  };
15
15
 
16
+ export type PostAnswerSuccessAction = {
17
+ type: typeof POST_ANSWER_SUCCESS;
18
+ payload: ProgressionFromAPI;
19
+ };
20
+
16
21
  export const postAnswer = async (
17
22
  dispatch: Dispatch,
18
23
  getState: () => StoreState,