@coorpacademy/app-review 0.2.12 → 0.3.1-alpha.1

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 (198) hide show
  1. package/es/actions/api/fetch-correction.js +1 -1
  2. package/es/actions/api/post-answer.d.ts +6 -0
  3. package/es/actions/api/post-answer.js +3 -1
  4. package/es/actions/ui/answers.d.ts +3 -0
  5. package/es/actions/ui/answers.js +3 -1
  6. package/es/reducers/index.d.ts +1 -1
  7. package/es/reducers/ui/answers.d.ts +4 -2
  8. package/es/reducers/ui/answers.js +6 -3
  9. package/es/reducers/ui/index.d.ts +4 -4
  10. package/es/reducers/ui/slide.d.ts +6 -4
  11. package/es/reducers/ui/slide.js +12 -4
  12. package/es/views/slides/index.js +4 -4
  13. package/lib/actions/api/fetch-correction.js +1 -1
  14. package/lib/actions/api/post-answer.d.ts +6 -0
  15. package/lib/actions/api/post-answer.js +4 -2
  16. package/lib/actions/ui/answers.d.ts +3 -0
  17. package/lib/actions/ui/answers.js +3 -1
  18. package/lib/reducers/index.d.ts +1 -1
  19. package/lib/reducers/ui/answers.d.ts +4 -2
  20. package/lib/reducers/ui/answers.js +6 -3
  21. package/lib/reducers/ui/index.d.ts +4 -4
  22. package/lib/reducers/ui/slide.d.ts +6 -4
  23. package/lib/reducers/ui/slide.js +12 -4
  24. package/lib/views/slides/index.js +4 -4
  25. package/package.json +4 -4
  26. package/src/actions/api/fetch-correction.ts +1 -1
  27. package/src/actions/api/post-answer.ts +5 -1
  28. package/src/actions/api/test/fetch-correction.test.ts +6 -2
  29. package/src/actions/api/test/fetch-rank.test.ts +2 -4
  30. package/src/actions/api/test/fetch-skills.test.ts +2 -4
  31. package/src/actions/api/test/fetch-slide.test.ts +2 -4
  32. package/src/actions/api/test/post-answer.test.ts +52 -13
  33. package/src/actions/api/test/post-progression.test.ts +2 -4
  34. package/src/actions/data/test/token.test.ts +2 -4
  35. package/src/actions/ui/answers.ts +4 -1
  36. package/src/actions/ui/test/answers.test.ts +38 -14
  37. package/src/actions/ui/test/next-slide.test.ts +8 -4
  38. package/src/actions/ui/test/slides.test.ts +2 -4
  39. package/src/reducers/data/test/progression.test.ts +1 -0
  40. package/src/reducers/ui/answers.ts +11 -5
  41. package/src/reducers/ui/index.ts +2 -2
  42. package/src/reducers/ui/slide.ts +30 -9
  43. package/src/reducers/ui/test/answers.test.ts +61 -13
  44. package/src/reducers/ui/test/slide.test.ts +36 -7
  45. package/src/views/skills/test/skills.test.ts +4 -8
  46. package/src/views/slides/index.ts +4 -4
  47. package/src/views/slides/test/index.test.ts +173 -28
  48. package/src/views/slides/test/slide.free-text.on-change.test.ts +7 -2
  49. package/src/views/slides/test/slide.qcm-drag.on-click.test.ts +7 -2
  50. package/src/views/slides/test/slide.qcm-graphic.on-click.test.ts +7 -2
  51. package/src/views/slides/test/slide.qcm.on-click.test.ts +7 -2
  52. package/src/views/slides/test/slide.slider.on-change.test.ts +7 -2
  53. package/src/views/slides/test/slide.slider.on-slider-change.test.ts +7 -2
  54. package/src/views/slides/test/slide.template.on-change.test.ts +12 -4
  55. package/es/actions/api/test/fetch-correction.test.d.ts +0 -1
  56. package/es/actions/api/test/fetch-correction.test.js +0 -91
  57. package/es/actions/api/test/fetch-rank.test.d.ts +0 -1
  58. package/es/actions/api/test/fetch-rank.test.js +0 -100
  59. package/es/actions/api/test/fetch-skills.test.d.ts +0 -1
  60. package/es/actions/api/test/fetch-skills.test.js +0 -61
  61. package/es/actions/api/test/fetch-slide.test.d.ts +0 -1
  62. package/es/actions/api/test/fetch-slide.test.js +0 -68
  63. package/es/actions/api/test/post-answer.test.d.ts +0 -1
  64. package/es/actions/api/test/post-answer.test.js +0 -172
  65. package/es/actions/api/test/post-progression.test.d.ts +0 -1
  66. package/es/actions/api/test/post-progression.test.js +0 -109
  67. package/es/actions/data/test/token.test.d.ts +0 -1
  68. package/es/actions/data/test/token.test.js +0 -27
  69. package/es/actions/ui/test/answers.test.d.ts +0 -1
  70. package/es/actions/ui/test/answers.test.js +0 -117
  71. package/es/actions/ui/test/next-slide.test.d.ts +0 -1
  72. package/es/actions/ui/test/next-slide.test.js +0 -63
  73. package/es/actions/ui/test/slides.test.d.ts +0 -1
  74. package/es/actions/ui/test/slides.test.js +0 -28
  75. package/es/reducers/data/test/corrections.test.d.ts +0 -1
  76. package/es/reducers/data/test/corrections.test.js +0 -27
  77. package/es/reducers/data/test/progression.test.d.ts +0 -1
  78. package/es/reducers/data/test/progression.test.js +0 -24
  79. package/es/reducers/data/test/rank.test.d.ts +0 -1
  80. package/es/reducers/data/test/rank.test.js +0 -59
  81. package/es/reducers/data/test/skills.test.d.ts +0 -1
  82. package/es/reducers/data/test/skills.test.js +0 -12
  83. package/es/reducers/data/test/slides.test.d.ts +0 -1
  84. package/es/reducers/data/test/slides.test.js +0 -21
  85. package/es/reducers/data/test/token.test.d.ts +0 -1
  86. package/es/reducers/data/test/token.test.js +0 -11
  87. package/es/reducers/ui/test/answers.test.d.ts +0 -1
  88. package/es/reducers/ui/test/answers.test.js +0 -31
  89. package/es/reducers/ui/test/current-slide-ref.test.d.ts +0 -1
  90. package/es/reducers/ui/test/current-slide-ref.test.js +0 -12
  91. package/es/reducers/ui/test/navigation.test.d.ts +0 -1
  92. package/es/reducers/ui/test/navigation.test.js +0 -15
  93. package/es/reducers/ui/test/slide.test.d.ts +0 -1
  94. package/es/reducers/ui/test/slide.test.js +0 -24
  95. package/es/services/test/fetch-correction.test.d.ts +0 -1
  96. package/es/services/test/fetch-correction.test.js +0 -39
  97. package/es/services/test/fetch-rank.test.d.ts +0 -1
  98. package/es/services/test/fetch-rank.test.js +0 -24
  99. package/es/services/test/fetch-skills.test.d.ts +0 -1
  100. package/es/services/test/fetch-skills.test.js +0 -29
  101. package/es/services/test/fetch-slide.test.d.ts +0 -1
  102. package/es/services/test/fetch-slide.test.js +0 -22
  103. package/es/services/test/post-answer.test.d.ts +0 -1
  104. package/es/services/test/post-answer.test.js +0 -88
  105. package/es/services/test/post-progression.test.d.ts +0 -1
  106. package/es/services/test/post-progression.test.js +0 -56
  107. package/es/views/skills/test/skills.test.d.ts +0 -1
  108. package/es/views/skills/test/skills.test.js +0 -98
  109. package/es/views/slides/test/index.test.d.ts +0 -1
  110. package/es/views/slides/test/index.test.js +0 -979
  111. package/es/views/slides/test/map-api-slide-to-ui.test.d.ts +0 -1
  112. package/es/views/slides/test/map-api-slide-to-ui.test.js +0 -36
  113. package/es/views/slides/test/slide.free-text.on-change.test.d.ts +0 -1
  114. package/es/views/slides/test/slide.free-text.on-change.test.js +0 -72
  115. package/es/views/slides/test/slide.qcm-drag.on-click.test.d.ts +0 -1
  116. package/es/views/slides/test/slide.qcm-drag.on-click.test.js +0 -72
  117. package/es/views/slides/test/slide.qcm-graphic.on-click.test.d.ts +0 -1
  118. package/es/views/slides/test/slide.qcm-graphic.on-click.test.js +0 -72
  119. package/es/views/slides/test/slide.qcm.on-click.test.d.ts +0 -1
  120. package/es/views/slides/test/slide.qcm.on-click.test.js +0 -74
  121. package/es/views/slides/test/slide.slider.on-change.test.d.ts +0 -1
  122. package/es/views/slides/test/slide.slider.on-change.test.js +0 -73
  123. package/es/views/slides/test/slide.slider.on-slider-change.test.d.ts +0 -1
  124. package/es/views/slides/test/slide.slider.on-slider-change.test.js +0 -63
  125. package/es/views/slides/test/slide.template.on-change.test.d.ts +0 -1
  126. package/es/views/slides/test/slide.template.on-change.test.js +0 -85
  127. package/lib/actions/api/test/fetch-correction.test.d.ts +0 -1
  128. package/lib/actions/api/test/fetch-correction.test.js +0 -151
  129. package/lib/actions/api/test/fetch-rank.test.d.ts +0 -1
  130. package/lib/actions/api/test/fetch-rank.test.js +0 -171
  131. package/lib/actions/api/test/fetch-skills.test.d.ts +0 -1
  132. package/lib/actions/api/test/fetch-skills.test.js +0 -120
  133. package/lib/actions/api/test/fetch-slide.test.d.ts +0 -1
  134. package/lib/actions/api/test/fetch-slide.test.js +0 -127
  135. package/lib/actions/api/test/post-answer.test.d.ts +0 -1
  136. package/lib/actions/api/test/post-answer.test.js +0 -254
  137. package/lib/actions/api/test/post-progression.test.d.ts +0 -1
  138. package/lib/actions/api/test/post-progression.test.js +0 -167
  139. package/lib/actions/data/test/token.test.d.ts +0 -1
  140. package/lib/actions/data/test/token.test.js +0 -72
  141. package/lib/actions/ui/test/answers.test.d.ts +0 -1
  142. package/lib/actions/ui/test/answers.test.js +0 -233
  143. package/lib/actions/ui/test/next-slide.test.d.ts +0 -1
  144. package/lib/actions/ui/test/next-slide.test.js +0 -64
  145. package/lib/actions/ui/test/slides.test.d.ts +0 -1
  146. package/lib/actions/ui/test/slides.test.js +0 -73
  147. package/lib/reducers/data/test/corrections.test.d.ts +0 -1
  148. package/lib/reducers/data/test/corrections.test.js +0 -28
  149. package/lib/reducers/data/test/progression.test.d.ts +0 -1
  150. package/lib/reducers/data/test/progression.test.js +0 -24
  151. package/lib/reducers/data/test/rank.test.d.ts +0 -1
  152. package/lib/reducers/data/test/rank.test.js +0 -59
  153. package/lib/reducers/data/test/skills.test.d.ts +0 -1
  154. package/lib/reducers/data/test/skills.test.js +0 -12
  155. package/lib/reducers/data/test/slides.test.d.ts +0 -1
  156. package/lib/reducers/data/test/slides.test.js +0 -22
  157. package/lib/reducers/data/test/token.test.d.ts +0 -1
  158. package/lib/reducers/data/test/token.test.js +0 -11
  159. package/lib/reducers/ui/test/answers.test.d.ts +0 -1
  160. package/lib/reducers/ui/test/answers.test.js +0 -31
  161. package/lib/reducers/ui/test/current-slide-ref.test.d.ts +0 -1
  162. package/lib/reducers/ui/test/current-slide-ref.test.js +0 -12
  163. package/lib/reducers/ui/test/navigation.test.d.ts +0 -1
  164. package/lib/reducers/ui/test/navigation.test.js +0 -15
  165. package/lib/reducers/ui/test/slide.test.d.ts +0 -1
  166. package/lib/reducers/ui/test/slide.test.js +0 -24
  167. package/lib/services/test/fetch-correction.test.d.ts +0 -1
  168. package/lib/services/test/fetch-correction.test.js +0 -95
  169. package/lib/services/test/fetch-rank.test.d.ts +0 -1
  170. package/lib/services/test/fetch-rank.test.js +0 -78
  171. package/lib/services/test/fetch-skills.test.d.ts +0 -1
  172. package/lib/services/test/fetch-skills.test.js +0 -83
  173. package/lib/services/test/fetch-slide.test.d.ts +0 -1
  174. package/lib/services/test/fetch-slide.test.js +0 -76
  175. package/lib/services/test/post-answer.test.d.ts +0 -1
  176. package/lib/services/test/post-answer.test.js +0 -142
  177. package/lib/services/test/post-progression.test.d.ts +0 -1
  178. package/lib/services/test/post-progression.test.js +0 -110
  179. package/lib/views/skills/test/skills.test.d.ts +0 -1
  180. package/lib/views/skills/test/skills.test.js +0 -98
  181. package/lib/views/slides/test/index.test.d.ts +0 -1
  182. package/lib/views/slides/test/index.test.js +0 -990
  183. package/lib/views/slides/test/map-api-slide-to-ui.test.d.ts +0 -1
  184. package/lib/views/slides/test/map-api-slide-to-ui.test.js +0 -47
  185. package/lib/views/slides/test/slide.free-text.on-change.test.d.ts +0 -1
  186. package/lib/views/slides/test/slide.free-text.on-change.test.js +0 -74
  187. package/lib/views/slides/test/slide.qcm-drag.on-click.test.d.ts +0 -1
  188. package/lib/views/slides/test/slide.qcm-drag.on-click.test.js +0 -74
  189. package/lib/views/slides/test/slide.qcm-graphic.on-click.test.d.ts +0 -1
  190. package/lib/views/slides/test/slide.qcm-graphic.on-click.test.js +0 -74
  191. package/lib/views/slides/test/slide.qcm.on-click.test.d.ts +0 -1
  192. package/lib/views/slides/test/slide.qcm.on-click.test.js +0 -76
  193. package/lib/views/slides/test/slide.slider.on-change.test.d.ts +0 -1
  194. package/lib/views/slides/test/slide.slider.on-change.test.js +0 -75
  195. package/lib/views/slides/test/slide.slider.on-slider-change.test.d.ts +0 -1
  196. package/lib/views/slides/test/slide.slider.on-slider-change.test.js +0 -65
  197. package/lib/views/slides/test/slide.template.on-change.test.d.ts +0 -1
  198. package/lib/views/slides/test/slide.template.on-change.test.js +0 -88
@@ -65,19 +65,26 @@ const initialState: StoreState = {
65
65
  ui: {
66
66
  currentSlideRef: freeTextSlide._id,
67
67
  navigation: ['skills', 'slides'],
68
- answers: answer,
68
+ answers: {
69
+ [freeTextSlide._id]: answer
70
+ },
69
71
  slide: {
70
- validateButton: false
72
+ [freeTextSlide._id]: {
73
+ validateButton: true,
74
+ animateCorrectionPopin: false,
75
+ showCorrectionPopin: false
76
+ }
71
77
  }
72
78
  }
73
79
  };
74
80
 
75
81
  test('should dispatch post-answer, fetch-slide and fetch-correction and fetch-start-rank actions when the answer is submitted and when the slide ref is not "successExitNode"', async t => {
76
- t.plan(10);
82
+ t.plan(9);
77
83
  const expectedActions = [
78
- {type: POST_ANSWER_REQUEST},
84
+ {type: POST_ANSWER_REQUEST, meta: {slideRef: freeTextSlide._id}},
79
85
  {
80
86
  type: POST_ANSWER_SUCCESS,
87
+ meta: {slideRef: freeTextSlide._id},
81
88
  payload: postAnswerResponses[freeTextSlide._id]
82
89
  },
83
90
  {
@@ -114,12 +121,15 @@ test('should dispatch post-answer, fetch-slide and fetch-correction and fetch-st
114
121
 
115
122
  const state = getState();
116
123
 
117
- t.false(state.ui.slide.validateButton);
118
- t.true(state.ui.slide.animateCorrectionPopin);
124
+ t.deepEqual(state.ui.slide[freeTextSlide._id], {
125
+ validateButton: false,
126
+ animateCorrectionPopin: true,
127
+ showCorrectionPopin: true
128
+ });
119
129
  });
120
130
 
121
131
  test('should dispatch post-answer, fetch-correction and fetch-end-rank actions when the answer is submitted and when the slide ref is "successExitNode"', async t => {
122
- t.plan(8);
132
+ t.plan(7);
123
133
 
124
134
  const stateBeforeExitNode: StoreState = {
125
135
  data: {
@@ -138,17 +148,42 @@ test('should dispatch post-answer, fetch-correction and fetch-end-rank actions w
138
148
  ui: {
139
149
  currentSlideRef: templateSlide._id,
140
150
  navigation: ['skills', 'slides'],
141
- answers: ['Leaderboard', 'utilisateurs', 'étoiles'],
151
+ answers: {
152
+ [freeTextSlide._id]: answer,
153
+ [qcmGraphicSlide._id]: ['qcm-graphic answer'],
154
+ [qcmSlide._id]: ['qcm-slide answer'],
155
+ [sliderSlide._id]: ['Leaderboard', 'utilisateurs', 'étoiles']
156
+ },
142
157
  slide: {
143
- validateButton: false
158
+ [freeTextSlide._id]: {
159
+ validateButton: false,
160
+ animateCorrectionPopin: false,
161
+ showCorrectionPopin: false
162
+ },
163
+ [qcmGraphicSlide._id]: {
164
+ validateButton: false,
165
+ animateCorrectionPopin: false,
166
+ showCorrectionPopin: false
167
+ },
168
+ [qcmSlide._id]: {
169
+ validateButton: false,
170
+ animateCorrectionPopin: false,
171
+ showCorrectionPopin: false
172
+ },
173
+ [sliderSlide._id]: {
174
+ validateButton: true,
175
+ animateCorrectionPopin: false,
176
+ showCorrectionPopin: false
177
+ }
144
178
  }
145
179
  }
146
180
  };
147
181
 
148
182
  const expectedActions = [
149
- {type: POST_ANSWER_REQUEST},
183
+ {type: POST_ANSWER_REQUEST, meta: {slideRef: templateSlide._id}},
150
184
  {
151
185
  type: POST_ANSWER_SUCCESS,
186
+ meta: {slideRef: templateSlide._id},
152
187
  payload: postAnswerResponses[templateSlide._id]
153
188
  },
154
189
  {type: CORRECTION_FETCH_REQUEST, meta: {slideRef: templateSlide._id}},
@@ -172,16 +207,20 @@ test('should dispatch post-answer, fetch-correction and fetch-end-rank actions w
172
207
 
173
208
  const state = getState();
174
209
 
175
- t.false(state.ui.slide.validateButton);
176
- t.true(state.ui.slide.animateCorrectionPopin);
210
+ t.deepEqual(state.ui.slide[templateSlide._id], {
211
+ validateButton: false,
212
+ animateCorrectionPopin: true,
213
+ showCorrectionPopin: true
214
+ });
177
215
  });
178
216
 
179
217
  test('should dispatch POST_ANSWER_REQUEST, then POST_ANSWER_FAILURE on error', async t => {
180
218
  t.plan(3);
181
219
  const expectedActions = [
182
- {type: POST_ANSWER_REQUEST},
220
+ {type: POST_ANSWER_REQUEST, meta: {slideRef: freeTextSlide._id}},
183
221
  {
184
222
  type: POST_ANSWER_FAILURE,
223
+ meta: {slideRef: freeTextSlide._id},
185
224
  payload: new Error('unexpected'),
186
225
  error: true
187
226
  }
@@ -25,10 +25,8 @@ const initialState: StoreState = {
25
25
  ui: {
26
26
  currentSlideRef: '',
27
27
  navigation: [],
28
- answers: [],
29
- slide: {
30
- validateButton: false
31
- }
28
+ answers: {},
29
+ slide: {}
32
30
  }
33
31
  };
34
32
 
@@ -16,10 +16,8 @@ const initialState: StoreState = {
16
16
  ui: {
17
17
  currentSlideRef: '',
18
18
  navigation: [],
19
- answers: [],
20
- slide: {
21
- validateButton: false
22
- }
19
+ answers: {},
20
+ slide: {}
23
21
  }
24
22
  };
25
23
 
@@ -1,5 +1,6 @@
1
1
  import flatten from 'lodash/fp/flatten';
2
2
  import get from 'lodash/fp/get';
3
+ import getOr from 'lodash/fp/getOr';
3
4
  import includes from 'lodash/fp/includes';
4
5
  import pull from 'lodash/fp/pull';
5
6
  import {Dispatch} from 'redux';
@@ -29,6 +30,7 @@ export type EditAnswerAction = {
29
30
  | typeof EDIT_TEMPLATE
30
31
  | typeof EDIT_BASIC
31
32
  | typeof EDIT_SLIDER;
33
+ meta: {slideRef: string};
32
34
  payload: string[];
33
35
  };
34
36
 
@@ -56,7 +58,7 @@ export const editAnswer =
56
58
  (dispatch: Dispatch, getState: () => StoreState): EditAnswerAction => {
57
59
  const state = getState();
58
60
  const currentSlideRef = get(['ui', 'currentSlideRef'], state);
59
- const userAnswers = get(['ui', 'answers'], state);
61
+ const userAnswers = getOr([], ['ui', 'answers', currentSlideRef], state);
60
62
  const slide = get(['data', 'slides', currentSlideRef], state);
61
63
 
62
64
  if (!slide) throw new Error('No slide was found');
@@ -69,6 +71,7 @@ export const editAnswer =
69
71
 
70
72
  return dispatch({
71
73
  type,
74
+ meta: {slideRef: currentSlideRef},
72
75
  payload: buildAnswer(userAnswers, questionType, answer)
73
76
  });
74
77
  };
@@ -1,4 +1,5 @@
1
1
  import test from 'ava';
2
+ import get from 'lodash/fp/get';
2
3
  import pipe from 'lodash/fp/pipe';
3
4
  import set from 'lodash/fp/set';
4
5
  import omit from 'lodash/fp/omit';
@@ -50,10 +51,8 @@ const initialState: StoreState = {
50
51
  ui: {
51
52
  currentSlideRef: '',
52
53
  navigation: [],
53
- answers: [],
54
- slide: {
55
- validateButton: false
56
- }
54
+ answers: {},
55
+ slide: {}
57
56
  }
58
57
  };
59
58
 
@@ -67,7 +66,7 @@ const buildInitialState = (state: StoreState, question: SlideFromAPI): StoreStat
67
66
 
68
67
  test('editAnswer should throw an Error if the slide is not found', async t => {
69
68
  const state = buildInitialState(initialState, freeTextSlide);
70
- const expectedActions = [{type: undefined, payload: []}];
69
+ const expectedActions = [{type: undefined, meta: {slideRef: ''}, payload: []}];
71
70
  const {dispatch} = createTestStore(
72
71
  t,
73
72
  omit(['data', 'slides'], state) as StoreState,
@@ -96,24 +95,38 @@ test('editAnswer should throw an Error for unsupported questions', async t => {
96
95
 
97
96
  test('should dispatch EDIT_BASIC action when editAnswer is called', async t => {
98
97
  const state = buildInitialState(initialState, freeTextSlide);
99
- const expectedActions = [{type: ANSWER_EDIT.basic, payload: ['My Answer']}];
98
+ const expectedActions = [
99
+ {type: ANSWER_EDIT.basic, meta: {slideRef: freeTextSlide.universalRef}, payload: ['My Answer']}
100
+ ];
100
101
  const {dispatch} = createTestStore(t, state, services, expectedActions);
101
102
  await dispatch(editAnswer(['My Answer']));
102
103
  });
103
104
 
104
105
  test('should dispatch EDIT_QCM action when editAnswer is called', async t => {
105
106
  let state = buildInitialState(initialState, qcmSlide);
106
- state = set(['ui', 'answers'], ['My First Answer', 'My Second Answer'], state);
107
- const expectedActions = [{type: ANSWER_EDIT.qcm, payload: ['My First Answer']}];
107
+ const currentSlideRef = get(['ui', 'currentSlideRef'], state);
108
+ state = set(['ui', 'answers', currentSlideRef], ['My First Answer', 'My Second Answer'], state);
109
+ const expectedActions = [
110
+ {type: ANSWER_EDIT.qcm, meta: {slideRef: qcmSlide.universalRef}, payload: ['My First Answer']}
111
+ ];
108
112
  const {dispatch} = createTestStore(t, state, services, expectedActions);
109
113
  await dispatch(editAnswer(['My Second Answer']));
110
114
  });
111
115
 
112
116
  test('should dispatch EDIT_QCM_GRAPHIC action when editAnswer is called', async t => {
113
117
  let state = buildInitialState(initialState, qcmGraphicSlide);
114
- state = set(['ui', 'answers'], ['My First Answer', 'My Second Answer', 'My Third Answer'], state);
118
+ const currentSlideRef = get(['ui', 'currentSlideRef'], state);
119
+ state = set(
120
+ ['ui', 'answers', currentSlideRef],
121
+ ['My First Answer', 'My Second Answer', 'My Third Answer'],
122
+ state
123
+ );
115
124
  const expectedActions = [
116
- {type: ANSWER_EDIT.qcmGraphic, payload: ['My First Answer', 'My Third Answer']}
125
+ {
126
+ type: ANSWER_EDIT.qcmGraphic,
127
+ meta: {slideRef: qcmGraphicSlide.universalRef},
128
+ payload: ['My First Answer', 'My Third Answer']
129
+ }
117
130
  ];
118
131
  const {dispatch} = createTestStore(t, state, services, expectedActions);
119
132
  await dispatch(editAnswer(['My Second Answer']));
@@ -121,9 +134,14 @@ test('should dispatch EDIT_QCM_GRAPHIC action when editAnswer is called', async
121
134
 
122
135
  test('should dispatch EDIT_QCM_DRAG action when editAnswer is called', async t => {
123
136
  let state = buildInitialState(initialState, qcmDragSlide);
124
- state = set(['ui', 'answers'], ['My First Answer', 'My Second Answer'], state);
137
+ const currentSlideRef = get(['ui', 'currentSlideRef'], state);
138
+ state = set(['ui', 'answers', currentSlideRef], ['My First Answer', 'My Second Answer'], state);
125
139
  const expectedActions = [
126
- {type: ANSWER_EDIT.qcmDrag, payload: ['My First Answer', 'My Second Answer', 'My Third Answer']}
140
+ {
141
+ type: ANSWER_EDIT.qcmDrag,
142
+ meta: {slideRef: qcmDragSlide.universalRef},
143
+ payload: ['My First Answer', 'My Second Answer', 'My Third Answer']
144
+ }
127
145
  ];
128
146
  const {dispatch} = createTestStore(t, state, services, expectedActions);
129
147
  await dispatch(editAnswer(['My Third Answer']));
@@ -131,7 +149,9 @@ test('should dispatch EDIT_QCM_DRAG action when editAnswer is called', async t =
131
149
 
132
150
  test('should dispatch EDIT_SLIDER action when editAnswer is called', async t => {
133
151
  const state = buildInitialState(initialState, sliderSlide);
134
- const expectedActions = [{type: ANSWER_EDIT.slider, payload: ['5']}];
152
+ const expectedActions = [
153
+ {type: ANSWER_EDIT.slider, meta: {slideRef: sliderSlide.universalRef}, payload: ['5']}
154
+ ];
135
155
  const {dispatch} = createTestStore(t, state, services, expectedActions);
136
156
  await dispatch(editAnswer(['5']));
137
157
  });
@@ -140,7 +160,11 @@ test('should dispatch EDIT_TEMPLATE action when editAnswer is called', async t =
140
160
  let state = buildInitialState(initialState, templateSlide);
141
161
  state = set(['ui', 'answers'], ['Catalogue', '', 'étoiles'], state);
142
162
  const expectedActions = [
143
- {type: ANSWER_EDIT.template, payload: ['Catalogue', 'My Answer', 'étoiles']}
163
+ {
164
+ type: ANSWER_EDIT.template,
165
+ meta: {slideRef: templateSlide.universalRef},
166
+ payload: ['Catalogue', 'My Answer', 'étoiles']
167
+ }
144
168
  ];
145
169
  const {dispatch} = createTestStore(t, state, services, expectedActions);
146
170
  await dispatch(editAnswer(['Catalogue', 'My Answer', 'étoiles']));
@@ -31,11 +31,15 @@ const state: StoreState = {
31
31
  ui: {
32
32
  currentSlideRef: freeTextSlide._id,
33
33
  navigation: ['loader', 'slides'],
34
- answers: answer,
34
+ answers: {
35
+ [freeTextSlide._id]: answer
36
+ },
35
37
  slide: {
36
- validateButton: false,
37
- animateCorrectionPopin: true,
38
- showCorrectionPopin: true
38
+ [freeTextSlide._id]: {
39
+ validateButton: false,
40
+ animateCorrectionPopin: true,
41
+ showCorrectionPopin: true
42
+ }
39
43
  }
40
44
  }
41
45
  };
@@ -17,10 +17,8 @@ const initialState: StoreState = {
17
17
  ui: {
18
18
  currentSlideRef: '',
19
19
  navigation: [],
20
- answers: [],
21
- slide: {
22
- validateButton: false
23
- }
20
+ answers: {},
21
+ slide: {}
24
22
  }
25
23
  };
26
24
 
@@ -21,6 +21,7 @@ test('should set the value of POST_PROGRESSION_SUCCESS action', t => {
21
21
  test('should set the value of POST_ANSWER_SUCCESS action', t => {
22
22
  const state = reducer(null, {
23
23
  type: POST_ANSWER_SUCCESS,
24
+ meta: {slideRef: freeTextSlide.universalRef},
24
25
  payload: postAnswerResponses[freeTextSlide.universalRef]
25
26
  });
26
27
  t.deepEqual(state, postAnswerResponses[freeTextSlide.universalRef]);
@@ -1,15 +1,21 @@
1
- import {includes, values} from 'lodash/fp';
1
+ import {includes, set, values} from 'lodash/fp';
2
2
  import {EditAnswerAction, ANSWER_EDIT} from '../../actions/ui/answers';
3
3
 
4
- export type AnswerState = string[];
4
+ export type UISlideAnswer = string[];
5
5
  const ANSWER_EDIT_ACTIONS = values(ANSWER_EDIT);
6
6
 
7
+ export type UIAnswerState = Record<string, UISlideAnswer>;
8
+
9
+ export const initialState: UIAnswerState = {};
10
+
7
11
  const reducer = (
8
12
  // eslint-disable-next-line default-param-last
9
- state: AnswerState = [],
13
+ state: UIAnswerState = initialState,
10
14
  action: EditAnswerAction
11
- ): AnswerState => {
12
- return includes(action.type, ANSWER_EDIT_ACTIONS) ? action.payload : state;
15
+ ): UIAnswerState => {
16
+ return includes(action.type, ANSWER_EDIT_ACTIONS)
17
+ ? set(action.meta.slideRef, action.payload, initialState)
18
+ : state;
13
19
  };
14
20
 
15
21
  export default reducer;
@@ -2,13 +2,13 @@ import {combineReducers} from 'redux';
2
2
 
3
3
  import currentSlideRef, {CurrentSlideRefState} from './current-slide-ref';
4
4
  import navigation, {NavigationState} from './navigation';
5
- import answers, {AnswerState} from './answers';
5
+ import answers, {UIAnswerState} from './answers';
6
6
  import slide, {UISlideState} from './slide';
7
7
 
8
8
  export type UIState = {
9
9
  currentSlideRef: CurrentSlideRefState;
10
10
  navigation: NavigationState;
11
- answers: AnswerState;
11
+ answers: UIAnswerState;
12
12
  slide: UISlideState;
13
13
  };
14
14
 
@@ -12,35 +12,56 @@ import {
12
12
  EDIT_TEMPLATE
13
13
  } from '../../actions/ui/answers';
14
14
  import {PostAnswerRequestAction, POST_ANSWER_REQUEST} from '../../actions/api/post-answer';
15
- import {CORRECTION_FETCH_SUCCESS, ReceivedCorrection} from '../../actions/api/fetch-correction';
15
+ import {ReceivedCorrection, CORRECTION_FETCH_SUCCESS} from '../../actions/api/fetch-correction';
16
+ import {FetchSlide, SLIDE_FETCH_REQUEST} from '../../actions/api/fetch-slide';
16
17
 
17
- export type UISlideState = {
18
+ export type UISlide = {
18
19
  validateButton: boolean;
19
- animateCorrectionPopin?: boolean;
20
- showCorrectionPopin?: boolean;
20
+ animateCorrectionPopin: boolean;
21
+ showCorrectionPopin: boolean;
21
22
  };
22
23
 
23
- export const initialState: UISlideState = {validateButton: false};
24
+ export type UISlideState = Record<string, UISlide>;
25
+
26
+ export const initialState: UISlideState = {};
24
27
 
25
28
  const reducer = (
26
29
  // eslint-disable-next-line default-param-last
27
30
  state: UISlideState = initialState,
28
- action: PostAnswerRequestAction | EditAnswerAction | ReceivedCorrection
31
+ action: FetchSlide | PostAnswerRequestAction | EditAnswerAction | ReceivedCorrection
29
32
  ): UISlideState => {
30
33
  switch (action.type) {
34
+ case SLIDE_FETCH_REQUEST: {
35
+ return set(
36
+ [action.meta.slideRef],
37
+ {
38
+ validateButton: false,
39
+ animateCorrectionPopin: false,
40
+ showCorrectionPopin: false
41
+ },
42
+ state
43
+ );
44
+ }
31
45
  case EDIT_QCM:
32
46
  case EDIT_QCM_GRAPHIC:
33
47
  case EDIT_QCM_DRAG:
34
48
  case EDIT_TEMPLATE:
35
49
  case EDIT_BASIC:
36
50
  case EDIT_SLIDER: {
37
- return pipe(compact, isEmpty)(action.payload) ? initialState : {validateButton: true};
51
+ return set(
52
+ [action.meta.slideRef, 'validateButton'],
53
+ !pipe(compact, isEmpty)(action.payload),
54
+ state
55
+ );
38
56
  }
39
57
  case POST_ANSWER_REQUEST: {
40
- return initialState;
58
+ return set([action.meta.slideRef, 'validateButton'], false, state);
41
59
  }
42
60
  case CORRECTION_FETCH_SUCCESS: {
43
- return pipe(set(['animateCorrectionPopin'], true), set(['showCorrectionPopin'], true))(state);
61
+ return pipe(
62
+ set([action.meta.slideRef, 'animateCorrectionPopin'], true),
63
+ set([action.meta.slideRef, 'showCorrectionPopin'], true)
64
+ )(state);
44
65
  }
45
66
  default:
46
67
  return state;
@@ -1,38 +1,86 @@
1
1
  import test from 'ava';
2
2
  import reducer from '../answers';
3
3
  import {EditAnswerAction, ANSWER_EDIT} from '../../../actions/ui/answers';
4
+ import {freeTextSlide} from '../../../views/slides/test/fixtures/free-text';
5
+ import {qcmDragSlide} from '../../../views/slides/test/fixtures/qcm-drag';
6
+ import {qcmSlide} from '../../../views/slides/test/fixtures/qcm';
7
+ import {qcmGraphicSlide} from '../../../views/slides/test/fixtures/qcm-graphic';
8
+ import {sliderSlide} from '../../../views/slides/test/fixtures/slider';
9
+ import {templateSlide} from '../../../views/slides/test/fixtures/template';
4
10
 
5
11
  test('should have initial value', t => {
6
12
  const state = reducer(undefined, {} as EditAnswerAction);
7
- t.deepEqual(state, []);
13
+ t.deepEqual(state, {});
8
14
  });
9
15
 
10
16
  test('should set the value of EDIT_BASIC action', t => {
11
- const state = reducer([], {type: ANSWER_EDIT.basic, payload: ['value']});
12
- t.deepEqual(state, ['value']);
17
+ const state = reducer(
18
+ {},
19
+ {
20
+ type: ANSWER_EDIT.basic,
21
+ meta: {slideRef: freeTextSlide.universalRef},
22
+ payload: ['value']
23
+ }
24
+ );
25
+ t.deepEqual(state, {[freeTextSlide.universalRef]: ['value']});
13
26
  });
14
27
 
15
28
  test('should set the value of EDIT_QCM action', t => {
16
- const state = reducer([], {type: ANSWER_EDIT.qcm, payload: ['value1', 'value2']});
17
- t.deepEqual(state, ['value1', 'value2']);
29
+ const state = reducer(
30
+ {},
31
+ {
32
+ type: ANSWER_EDIT.qcm,
33
+ meta: {slideRef: qcmSlide.universalRef},
34
+ payload: ['value1', 'value2']
35
+ }
36
+ );
37
+ t.deepEqual(state, {[qcmSlide.universalRef]: ['value1', 'value2']});
18
38
  });
19
39
 
20
40
  test('should set the value of EDIT_QCM_GRAPHIC action', t => {
21
- const state = reducer([], {type: ANSWER_EDIT.qcmGraphic, payload: ['True', 'False']});
22
- t.deepEqual(state, ['True', 'False']);
41
+ const state = reducer(
42
+ {},
43
+ {
44
+ type: ANSWER_EDIT.qcmGraphic,
45
+ meta: {slideRef: qcmGraphicSlide.universalRef},
46
+ payload: ['True', 'False']
47
+ }
48
+ );
49
+ t.deepEqual(state, {[qcmGraphicSlide.universalRef]: ['True', 'False']});
23
50
  });
24
51
 
25
52
  test('should set the value of EDIT_QCM_DRAG action', t => {
26
- const state = reducer([], {type: ANSWER_EDIT.qcmDrag, payload: ['value1', 'value2']});
27
- t.deepEqual(state, ['value1', 'value2']);
53
+ const state = reducer(
54
+ {},
55
+ {
56
+ type: ANSWER_EDIT.qcmDrag,
57
+ meta: {slideRef: qcmDragSlide.universalRef},
58
+ payload: ['value1', 'value2']
59
+ }
60
+ );
61
+ t.deepEqual(state, {[qcmDragSlide.universalRef]: ['value1', 'value2']});
28
62
  });
29
63
 
30
64
  test('should set the value of EDIT_SLIDER action', t => {
31
- const state = reducer([], {type: ANSWER_EDIT.slider, payload: ['5']});
32
- t.deepEqual(state, ['5']);
65
+ const state = reducer(
66
+ {},
67
+ {
68
+ type: ANSWER_EDIT.slider,
69
+ meta: {slideRef: sliderSlide.universalRef},
70
+ payload: ['5']
71
+ }
72
+ );
73
+ t.deepEqual(state, {[sliderSlide.universalRef]: ['5']});
33
74
  });
34
75
 
35
76
  test('should set the value of EDIT_TEMPLATE action', t => {
36
- const state = reducer([], {type: ANSWER_EDIT.template, payload: ['value1', 'value2']});
37
- t.deepEqual(state, ['value1', 'value2']);
77
+ const state = reducer(
78
+ {},
79
+ {
80
+ type: ANSWER_EDIT.template,
81
+ meta: {slideRef: templateSlide.universalRef},
82
+ payload: ['value1', 'value2']
83
+ }
84
+ );
85
+ t.deepEqual(state, {[templateSlide.universalRef]: ['value1', 'value2']});
38
86
  });
@@ -1,14 +1,44 @@
1
1
  import test from 'ava';
2
2
  import reducer, {initialState} from '../slide';
3
3
  import {EDIT_BASIC} from '../../../actions/ui/answers';
4
- import {PostAnswerRequestAction} from '../../../actions/api/post-answer';
4
+ import {PostAnswerRequestAction, POST_ANSWER_REQUEST} from '../../../actions/api/post-answer';
5
5
  import {CORRECTION_FETCH_SUCCESS} from '../../../actions/api/fetch-correction';
6
+ import {SLIDE_FETCH_REQUEST} from '../../../actions/api/fetch-slide';
6
7
 
7
- test('should use initial state if no answers are found when an EditAnswerAction is received', t => {
8
- const state = reducer(undefined, {type: EDIT_BASIC, payload: ['']});
8
+ test('should set validateButton, animateCorrectionPopin and showCorrectionPopin to false if SLIDE_FETCH_REQUEST is received', t => {
9
+ const state = reducer(undefined, {
10
+ type: SLIDE_FETCH_REQUEST,
11
+ meta: {slideRef: '1234'}
12
+ });
13
+ t.truthy(state);
14
+ t.deepEqual(state, {
15
+ '1234': {validateButton: false, animateCorrectionPopin: false, showCorrectionPopin: false}
16
+ });
17
+ });
18
+
19
+ test('should set validateButton to false if no answers are found when an EditAnswerAction is received', t => {
20
+ const state = reducer(undefined, {type: EDIT_BASIC, meta: {slideRef: '1234'}, payload: ['']});
21
+ t.truthy(state);
22
+ t.deepEqual(state, {'1234': {validateButton: false}});
23
+ });
24
+
25
+ test('should set validateButton to true if answers are found when an EditAnswerAction is received', t => {
26
+ const state = reducer(undefined, {
27
+ type: EDIT_BASIC,
28
+ meta: {slideRef: '1234'},
29
+ payload: ['answer']
30
+ });
31
+ t.truthy(state);
32
+ t.deepEqual(state, {'1234': {validateButton: true}});
33
+ });
34
+
35
+ test('should set validateButton to false if POST_ANSWER_REQUEST is received', t => {
36
+ const state = reducer(undefined, {
37
+ type: POST_ANSWER_REQUEST,
38
+ meta: {slideRef: '1234'}
39
+ });
9
40
  t.truthy(state);
10
- t.false(state.validateButton);
11
- t.falsy(state.animateCorrectionPopin);
41
+ t.deepEqual(state, {'1234': {validateButton: false}});
12
42
  });
13
43
 
14
44
  test('should set animateCorrectionPopin to true if CORRECTION_FETCH_SUCCESS is received', t => {
@@ -18,8 +48,7 @@ test('should set animateCorrectionPopin to true if CORRECTION_FETCH_SUCCESS is r
18
48
  meta: {slideRef: '1234'}
19
49
  });
20
50
  t.truthy(state);
21
- t.false(state.validateButton);
22
- t.true(state.animateCorrectionPopin);
51
+ t.deepEqual(state, {'1234': {animateCorrectionPopin: true, showCorrectionPopin: true}});
23
52
  });
24
53
 
25
54
  test('should return state directly when there is no corresponding action handler + have an initial state', t => {
@@ -17,10 +17,8 @@ test('should create initial props when there are no skills on the state', t => {
17
17
  ui: {
18
18
  currentSlideRef: '',
19
19
  navigation: ['loader', 'skills'],
20
- answers: [],
21
- slide: {
22
- validateButton: false
23
- }
20
+ answers: {},
21
+ slide: {}
24
22
  }
25
23
  };
26
24
 
@@ -63,10 +61,8 @@ test('should create initial props when skills on the state', t => {
63
61
  ui: {
64
62
  currentSlideRef: '',
65
63
  navigation: ['loader', 'skills'],
66
- answers: [],
67
- slide: {
68
- validateButton: false
69
- }
64
+ answers: {},
65
+ slide: {}
70
66
  }
71
67
  };
72
68
 
@@ -165,16 +165,16 @@ const buildStackSlides = (state: StoreState, dispatch: Dispatch): SlidesStack =>
165
165
  const slideFromAPI = get(slideRef, state.data.slides);
166
166
  if (!slideFromAPI) return set(index, uiSlide, acc);
167
167
 
168
- const answers = state.ui.answers;
168
+ const answers = getOr([], ['ui', 'answers', slideRef], state);
169
169
  const {questionText, answerUI} = mapApiSlideToUi(dispatch)(slideFromAPI, answers);
170
170
  const parentContentTitle = getOr('', 'parentContentTitle.title', slideFromAPI);
171
171
  const parentContentType = getOr('', 'parentContentTitle.type', slideFromAPI);
172
172
 
173
173
  const isCurrentSlideRef = currentSlideRef === slideRef;
174
174
  const animateCorrectionPopin =
175
- isCurrentSlideRef && getOr(false, ['ui', 'slide', 'animateCorrectionPopin'], state);
175
+ isCurrentSlideRef && get(['ui', 'slide', slideRef, 'animateCorrectionPopin'], state);
176
176
  const showCorrectionPopin =
177
- isCurrentSlideRef && getOr(false, ['ui', 'slide', 'showCorrectionPopin'], state);
177
+ isCurrentSlideRef && get(['ui', 'slide', slideRef, 'showCorrectionPopin'], state);
178
178
 
179
179
  const updatedUiSlide = pipe(
180
180
  set('showCorrectionPopin', showCorrectionPopin),
@@ -320,7 +320,7 @@ export const mapStateToSlidesProps = (state: StoreState, dispatch: Dispatch): Sl
320
320
  slides: buildStackSlides(state, dispatch),
321
321
  validateButton: {
322
322
  label: '__validate',
323
- disabled: !get('ui.slide.validateButton', state),
323
+ disabled: !get(['ui', 'slide', currentSlideRef, 'validateButton'], state),
324
324
  onClick: /* istanbul ignore next */ (): void => {
325
325
  dispatch(postAnswer);
326
326
  }