@coorpacademy/app-review 0.2.9 → 0.2.10-alpha.16
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/es/actions/api/post-answer.js +10 -2
- package/es/actions/api/test/post-answer.test.js +64 -2
- package/es/actions/ui/next-slide.d.ts +14 -0
- package/es/actions/ui/next-slide.js +15 -0
- package/es/actions/ui/test/next-slide.test.d.ts +1 -0
- package/es/actions/ui/test/next-slide.test.js +63 -0
- package/es/reducers/data/index.d.ts +1 -1
- package/es/reducers/index.d.ts +1 -1
- package/es/test/index.test.js +0 -3
- package/es/types/common.d.ts +0 -8
- package/es/types/slides.d.ts +2 -1
- package/es/views/slides/map-api-slide-to-ui.js +5 -0
- package/es/views/slides/test/fixtures/slider.js +2 -1
- package/es/views/slides/test/slide.slider.on-slider-change.test.d.ts +1 -0
- package/es/views/slides/test/slide.slider.on-slider-change.test.js +63 -0
- package/lib/actions/api/post-answer.js +15 -3
- package/lib/actions/api/test/post-answer.test.js +74 -2
- package/lib/actions/ui/next-slide.d.ts +14 -0
- package/lib/actions/ui/next-slide.js +16 -0
- package/lib/actions/ui/test/next-slide.test.d.ts +1 -0
- package/lib/actions/ui/test/next-slide.test.js +64 -0
- package/lib/reducers/data/index.d.ts +1 -1
- package/lib/reducers/index.d.ts +1 -1
- package/lib/test/index.test.js +0 -3
- package/lib/types/common.d.ts +0 -8
- package/lib/types/slides.d.ts +2 -1
- package/lib/views/slides/map-api-slide-to-ui.js +5 -0
- package/lib/views/slides/test/fixtures/slider.js +2 -1
- package/lib/views/slides/test/slide.slider.on-slider-change.test.d.ts +1 -0
- package/lib/views/slides/test/slide.slider.on-slider-change.test.js +65 -0
- package/package.json +4 -4
- package/src/actions/api/post-answer.ts +9 -2
- package/src/actions/api/test/post-answer.test.ts +76 -2
- package/src/actions/ui/next-slide.ts +31 -0
- package/src/actions/ui/test/next-slide.test.ts +75 -0
- package/src/test/index.test.tsx +0 -3
- package/src/types/common.ts +0 -10
- package/src/types/slides.ts +2 -1
- package/src/views/slides/map-api-slide-to-ui.ts +5 -0
- package/src/views/slides/test/fixtures/slider.ts +2 -1
- package/src/views/slides/test/slide.slider.on-slider-change.test.ts +71 -0
|
@@ -2,6 +2,7 @@ import buildTask from '@coorpacademy/redux-task';
|
|
|
2
2
|
import get from 'lodash/fp/get';
|
|
3
3
|
import { fetchCorrection } from './fetch-correction';
|
|
4
4
|
import { fetchSlide } from './fetch-slide';
|
|
5
|
+
import { fetchEndRank, fetchStartRank } from './fetch-rank';
|
|
5
6
|
export const POST_ANSWER_REQUEST = '@@answer/POST_REQUEST';
|
|
6
7
|
export const POST_ANSWER_SUCCESS = '@@answer/POST_SUCCESS';
|
|
7
8
|
export const POST_ANSWER_FAILURE = '@@answer/POST_FAILURE';
|
|
@@ -20,7 +21,14 @@ export const postAnswer = async (dispatch, getState, { services }) => {
|
|
|
20
21
|
if (response.type === POST_ANSWER_SUCCESS) {
|
|
21
22
|
const updatedProgression = response.payload;
|
|
22
23
|
const slideRef = updatedProgression.state.nextContent.ref;
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
if (slideRef !== 'successExitNode') {
|
|
25
|
+
await dispatch(fetchSlide(slideRef));
|
|
26
|
+
await dispatch(fetchCorrection);
|
|
27
|
+
await dispatch(fetchStartRank);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
await dispatch(fetchCorrection);
|
|
31
|
+
await dispatch(fetchEndRank);
|
|
32
|
+
}
|
|
25
33
|
}
|
|
26
34
|
};
|
|
@@ -5,7 +5,11 @@ import { postAnswer, POST_ANSWER_FAILURE, POST_ANSWER_REQUEST, POST_ANSWER_SUCCE
|
|
|
5
5
|
import { freeTextSlide } from '../../../views/slides/test/fixtures/free-text';
|
|
6
6
|
import { CORRECTION_FETCH_REQUEST, CORRECTION_FETCH_SUCCESS } from '../fetch-correction';
|
|
7
7
|
import { SLIDE_FETCH_REQUEST, SLIDE_FETCH_SUCCESS } from '../fetch-slide';
|
|
8
|
+
import { qcmSlide } from '../../../views/slides/test/fixtures/qcm';
|
|
8
9
|
import { qcmGraphicSlide } from '../../../views/slides/test/fixtures/qcm-graphic';
|
|
10
|
+
import { templateSlide } from '../../../views/slides/test/fixtures/template';
|
|
11
|
+
import { sliderSlide } from '../../../views/slides/test/fixtures/slider';
|
|
12
|
+
import { RANK_FETCH_START_REQUEST, RANK_FETCH_START_SUCCESS, RANK_FETCH_END_REQUEST, RANK_FETCH_END_SUCCESS } from '../fetch-rank';
|
|
9
13
|
const progressionId = '123456789123';
|
|
10
14
|
const skillRef = '_skill-ref';
|
|
11
15
|
const answer = ['Lister vos tâches pour vous libérer l’esprit', 'Vous isoler dans un lieu calme'];
|
|
@@ -49,8 +53,8 @@ const initialState = {
|
|
|
49
53
|
}
|
|
50
54
|
}
|
|
51
55
|
};
|
|
52
|
-
test('should dispatch post-answer, fetch-slide and fetch-correction actions when the answer is submitted', async (t) => {
|
|
53
|
-
t.plan(
|
|
56
|
+
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) => {
|
|
57
|
+
t.plan(10);
|
|
54
58
|
const expectedActions = [
|
|
55
59
|
{ type: POST_ANSWER_REQUEST },
|
|
56
60
|
{
|
|
@@ -75,6 +79,13 @@ test('should dispatch post-answer, fetch-slide and fetch-correction actions when
|
|
|
75
79
|
type: CORRECTION_FETCH_SUCCESS,
|
|
76
80
|
meta: { slideRef: freeTextSlide._id },
|
|
77
81
|
payload: getChoicesCorrection(freeTextSlide._id)
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
type: RANK_FETCH_START_REQUEST
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
type: RANK_FETCH_START_SUCCESS,
|
|
88
|
+
payload: { rank: 93 }
|
|
78
89
|
}
|
|
79
90
|
];
|
|
80
91
|
const { dispatch, getState } = createTestStore(t, initialState, services, expectedActions);
|
|
@@ -83,6 +94,57 @@ test('should dispatch post-answer, fetch-slide and fetch-correction actions when
|
|
|
83
94
|
t.false(state.ui.slide.validateButton);
|
|
84
95
|
t.true(state.ui.slide.animateCorrectionPopin);
|
|
85
96
|
});
|
|
97
|
+
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) => {
|
|
98
|
+
t.plan(8);
|
|
99
|
+
const stateBeforeExitNode = {
|
|
100
|
+
data: {
|
|
101
|
+
progression: postAnswerResponses[sliderSlide.universalRef],
|
|
102
|
+
slides: {
|
|
103
|
+
[freeTextSlide._id]: freeTextSlide,
|
|
104
|
+
[qcmGraphicSlide._id]: qcmGraphicSlide,
|
|
105
|
+
[qcmSlide._id]: qcmSlide,
|
|
106
|
+
[sliderSlide._id]: sliderSlide
|
|
107
|
+
},
|
|
108
|
+
skills: [{ skillRef, custom: false, name: skillRef, slidesToReview: 5 }],
|
|
109
|
+
token: '1234',
|
|
110
|
+
corrections: {},
|
|
111
|
+
rank: {}
|
|
112
|
+
},
|
|
113
|
+
ui: {
|
|
114
|
+
currentSlideRef: templateSlide._id,
|
|
115
|
+
navigation: ['skills', 'slides'],
|
|
116
|
+
answers: ['Leaderboard', 'utilisateurs', 'étoiles'],
|
|
117
|
+
slide: {
|
|
118
|
+
validateButton: false
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
const expectedActions = [
|
|
123
|
+
{ type: POST_ANSWER_REQUEST },
|
|
124
|
+
{
|
|
125
|
+
type: POST_ANSWER_SUCCESS,
|
|
126
|
+
payload: postAnswerResponses[templateSlide._id]
|
|
127
|
+
},
|
|
128
|
+
{ type: CORRECTION_FETCH_REQUEST, meta: { slideRef: templateSlide._id } },
|
|
129
|
+
{
|
|
130
|
+
type: CORRECTION_FETCH_SUCCESS,
|
|
131
|
+
meta: { slideRef: templateSlide._id },
|
|
132
|
+
payload: getChoicesCorrection(templateSlide._id)
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
type: RANK_FETCH_END_REQUEST
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
type: RANK_FETCH_END_SUCCESS,
|
|
139
|
+
payload: { rank: 93 }
|
|
140
|
+
}
|
|
141
|
+
];
|
|
142
|
+
const { dispatch, getState } = createTestStore(t, stateBeforeExitNode, services, expectedActions);
|
|
143
|
+
await dispatch(postAnswer);
|
|
144
|
+
const state = getState();
|
|
145
|
+
t.false(state.ui.slide.validateButton);
|
|
146
|
+
t.true(state.ui.slide.animateCorrectionPopin);
|
|
147
|
+
});
|
|
86
148
|
test('should dispatch POST_ANSWER_REQUEST, then POST_ANSWER_FAILURE on error', async (t) => {
|
|
87
149
|
t.plan(3);
|
|
88
150
|
const expectedActions = [
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Dispatch } from 'redux';
|
|
2
|
+
import type { StoreState } from '../../reducers';
|
|
3
|
+
export declare const NEXT_SLIDE: "@@slide/NEXT_SLIDE";
|
|
4
|
+
declare type NextSlidePayload = {
|
|
5
|
+
currentSlideRef: string;
|
|
6
|
+
nextSlideRef: string;
|
|
7
|
+
animationType: string;
|
|
8
|
+
};
|
|
9
|
+
export declare type NextSlide = {
|
|
10
|
+
type: typeof NEXT_SLIDE;
|
|
11
|
+
payload: NextSlidePayload;
|
|
12
|
+
};
|
|
13
|
+
export declare const nextSlide: (dispatch: Dispatch, getState: () => StoreState) => NextSlide;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import get from 'lodash/fp/get';
|
|
2
|
+
export const NEXT_SLIDE = '@@slide/NEXT_SLIDE';
|
|
3
|
+
export const nextSlide = (dispatch, getState) => {
|
|
4
|
+
const state = getState();
|
|
5
|
+
const payload = {
|
|
6
|
+
currentSlideRef: get(['ui', 'currentSlideRef'], state),
|
|
7
|
+
nextSlideRef: get(['data', 'progression', 'state', 'nextContent', 'ref'], state),
|
|
8
|
+
animationType: state.data.progression?.state.isCorrect ? 'unstack' : 'restack'
|
|
9
|
+
};
|
|
10
|
+
const action = {
|
|
11
|
+
type: NEXT_SLIDE,
|
|
12
|
+
payload
|
|
13
|
+
};
|
|
14
|
+
return dispatch(action);
|
|
15
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import test from 'ava';
|
|
2
|
+
import pipe from 'lodash/fp/pipe';
|
|
3
|
+
import set from 'lodash/fp/set';
|
|
4
|
+
import { nextSlide, NEXT_SLIDE } from '../next-slide';
|
|
5
|
+
import { createTestStore } from '../../test/create-test-store';
|
|
6
|
+
import { getChoicesCorrection, postAnswerResponses, services } from '../../../test/util/services.mock';
|
|
7
|
+
import { freeTextSlide } from '../../../views/slides/test/fixtures/free-text';
|
|
8
|
+
import { qcmGraphicSlide } from '../../../views/slides/test/fixtures/qcm-graphic';
|
|
9
|
+
const progression = postAnswerResponses[freeTextSlide.universalRef];
|
|
10
|
+
const skillRef = '_skill-ref';
|
|
11
|
+
const answer = ['Vous isoler dans un lieu calme'];
|
|
12
|
+
const state = {
|
|
13
|
+
data: {
|
|
14
|
+
progression,
|
|
15
|
+
slides: {
|
|
16
|
+
[freeTextSlide.universalRef]: freeTextSlide,
|
|
17
|
+
[qcmGraphicSlide.universalRef]: qcmGraphicSlide
|
|
18
|
+
},
|
|
19
|
+
skills: [{ skillRef, custom: false, name: skillRef, slidesToReview: 5 }],
|
|
20
|
+
token: '1234',
|
|
21
|
+
corrections: { [freeTextSlide.universalRef]: getChoicesCorrection(freeTextSlide.universalRef) },
|
|
22
|
+
rank: { start: 93 }
|
|
23
|
+
},
|
|
24
|
+
ui: {
|
|
25
|
+
currentSlideRef: freeTextSlide._id,
|
|
26
|
+
navigation: ['loader', 'slides'],
|
|
27
|
+
answers: answer,
|
|
28
|
+
slide: {
|
|
29
|
+
validateButton: false,
|
|
30
|
+
animateCorrectionPopin: true,
|
|
31
|
+
showCorrectionPopin: true
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
test('should dispatch NEXT_SLIDE action when nextSlide is called and the progression state is correct', t => {
|
|
36
|
+
const expectedActions = [
|
|
37
|
+
{
|
|
38
|
+
type: NEXT_SLIDE,
|
|
39
|
+
payload: {
|
|
40
|
+
currentSlideRef: freeTextSlide.universalRef,
|
|
41
|
+
nextSlideRef: qcmGraphicSlide.universalRef,
|
|
42
|
+
animationType: 'unstack'
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
];
|
|
46
|
+
const { dispatch } = createTestStore(t, state, services, expectedActions);
|
|
47
|
+
dispatch(nextSlide);
|
|
48
|
+
});
|
|
49
|
+
test('should dispatch NEXT_SLIDE action when nextSlide is called and the progression state is not correct', t => {
|
|
50
|
+
const stateWithWrongAnswer = pipe(set(['data', 'progression', 'state', 'isCorrect'], false), set(['data', 'progression', 'state', 'allAnswers', 0, 'isCorrect'], false))(state);
|
|
51
|
+
const expectedActions = [
|
|
52
|
+
{
|
|
53
|
+
type: NEXT_SLIDE,
|
|
54
|
+
payload: {
|
|
55
|
+
currentSlideRef: freeTextSlide.universalRef,
|
|
56
|
+
nextSlideRef: qcmGraphicSlide.universalRef,
|
|
57
|
+
animationType: 'restack'
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
];
|
|
61
|
+
const { dispatch } = createTestStore(t, stateWithWrongAnswer, services, expectedActions);
|
|
62
|
+
dispatch(nextSlide);
|
|
63
|
+
});
|
|
@@ -19,5 +19,5 @@ declare const _default: import("redux").Reducer<import("redux").CombinedState<{
|
|
|
19
19
|
slides: SlidesState;
|
|
20
20
|
token: string;
|
|
21
21
|
rank: RankState;
|
|
22
|
-
}>, import("./corrections").CorrectionsAction | import("../../actions/api/post-answer").PostAnswerSuccessAction | import("../../actions/api/post-progression").ReceivedProgression | import("../../actions/api/fetch-skills").ReceivedSkills | import("./slides").SlidesAction | import("../../actions/data/token").StoreToken
|
|
22
|
+
}>, import("./corrections").CorrectionsAction | import("../../actions/api/fetch-rank").RankAction | import("../../actions/api/post-answer").PostAnswerSuccessAction | import("../../actions/api/post-progression").ReceivedProgression | import("../../actions/api/fetch-skills").ReceivedSkills | import("./slides").SlidesAction | import("../../actions/data/token").StoreToken>;
|
|
23
23
|
export default _default;
|
package/es/reducers/index.d.ts
CHANGED
|
@@ -19,5 +19,5 @@ declare const _default: import("redux").Reducer<import("redux").CombinedState<{
|
|
|
19
19
|
answers: import("./ui/answers").AnswerState;
|
|
20
20
|
slide: import("./ui/slide").UISlideState;
|
|
21
21
|
}>;
|
|
22
|
-
}>, import("./data/corrections").CorrectionsAction | import("../actions/ui/slides").SetCurrentSlide | import("../actions/api/post-answer").PostAnswerRequestAction | import("../actions/api/post-answer").PostAnswerSuccessAction | import("../actions/api/post-progression").ReceivedProgression | import("../actions/api/fetch-skills").ReceivedSkills | import("./data/slides").SlidesAction | import("../actions/data/token").StoreToken | import("../actions/
|
|
22
|
+
}>, import("./data/corrections").CorrectionsAction | import("../actions/ui/slides").SetCurrentSlide | import("../actions/api/fetch-rank").RankAction | import("../actions/api/post-answer").PostAnswerRequestAction | import("../actions/api/post-answer").PostAnswerSuccessAction | import("../actions/api/post-progression").ReceivedProgression | import("../actions/api/fetch-skills").ReceivedSkills | import("./data/slides").SlidesAction | import("../actions/data/token").StoreToken | import("../actions/ui/navigation").NavigateTo | import("../actions/ui/navigation").NavigateBack | import("../actions/ui/answers").EditAnswerAction>;
|
|
23
23
|
export default _default;
|
package/es/test/index.test.js
CHANGED
|
@@ -36,9 +36,6 @@ const clickAllSlides = async (t, container, accumulator = 0) => {
|
|
|
36
36
|
};
|
|
37
37
|
const appOptions = {
|
|
38
38
|
token: process.env.API_TEST_TOKEN || '',
|
|
39
|
-
templateContext: {
|
|
40
|
-
theme: { color: { primary: '#123' } }
|
|
41
|
-
},
|
|
42
39
|
skillRef: 'skill_NJC0jFKoH',
|
|
43
40
|
services
|
|
44
41
|
};
|
package/es/types/common.d.ts
CHANGED
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
declare type TemplateContextValues = {
|
|
2
|
-
brandTheme?: unknown;
|
|
3
|
-
theme?: unknown;
|
|
4
|
-
translations?: unknown;
|
|
5
|
-
};
|
|
6
1
|
export declare type ChoiceFromAPI = {
|
|
7
2
|
_id: string;
|
|
8
3
|
id?: string;
|
|
@@ -140,9 +135,6 @@ export declare type Options = {
|
|
|
140
135
|
};
|
|
141
136
|
export declare type AppOptions = {
|
|
142
137
|
token: string;
|
|
143
|
-
theme?: unknown;
|
|
144
|
-
translations?: unknown;
|
|
145
|
-
templateContext?: TemplateContextValues;
|
|
146
138
|
skillRef?: string;
|
|
147
139
|
services: Services;
|
|
148
140
|
};
|
package/es/types/slides.d.ts
CHANGED
|
@@ -44,8 +44,9 @@ export declare type DropDown = {
|
|
|
44
44
|
export declare type QuestionRange = {
|
|
45
45
|
type: 'slider';
|
|
46
46
|
placeholder?: string;
|
|
47
|
-
onChange?:
|
|
47
|
+
onChange?: (value: number) => void;
|
|
48
48
|
onChangeEnd?: Function;
|
|
49
|
+
onSliderChange?: (value: number) => void;
|
|
49
50
|
multi?: boolean;
|
|
50
51
|
value: number | number[];
|
|
51
52
|
title: string;
|
|
@@ -132,8 +132,13 @@ const sliderProps = (dispatch) => (answers, question) => {
|
|
|
132
132
|
title: `${currentValue} ${question.content.unitLabel}`,
|
|
133
133
|
value: sliderPosition,
|
|
134
134
|
onChange: (position) => {
|
|
135
|
+
// atom/range handler
|
|
135
136
|
const newValue = pipe(multiply(maxValue), round, get(__, values), _toString)(position);
|
|
136
137
|
dispatch(editAnswer([newValue]));
|
|
138
|
+
},
|
|
139
|
+
onSliderChange: (newValue) => {
|
|
140
|
+
// mobile/slider handler
|
|
141
|
+
dispatch(editAnswer([`${newValue}`]));
|
|
137
142
|
}
|
|
138
143
|
};
|
|
139
144
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import test from 'ava';
|
|
2
|
+
import get from 'lodash/fp/get';
|
|
3
|
+
import { mapStateToSlidesProps } from '..';
|
|
4
|
+
import { services } from '../../../test/util/services.mock';
|
|
5
|
+
import { createTestStore } from '../../../actions/test/create-test-store';
|
|
6
|
+
import { EDIT_SLIDER } from '../../../actions/ui/answers';
|
|
7
|
+
import { sliderSlide } from './fixtures/slider';
|
|
8
|
+
const progression = {
|
|
9
|
+
_id: '123456789123',
|
|
10
|
+
content: { type: 'skill', ref: '_skill-ref' },
|
|
11
|
+
engine: {
|
|
12
|
+
ref: 'review'
|
|
13
|
+
},
|
|
14
|
+
state: {
|
|
15
|
+
allAnswers: [],
|
|
16
|
+
isCorrect: true,
|
|
17
|
+
nextContent: {
|
|
18
|
+
ref: sliderSlide._id,
|
|
19
|
+
type: 'slide'
|
|
20
|
+
},
|
|
21
|
+
pendingSlides: [],
|
|
22
|
+
slides: [],
|
|
23
|
+
step: {
|
|
24
|
+
current: 1
|
|
25
|
+
},
|
|
26
|
+
stars: 0
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
const initialState = {
|
|
30
|
+
data: {
|
|
31
|
+
progression,
|
|
32
|
+
slides: {
|
|
33
|
+
[sliderSlide._id]: sliderSlide
|
|
34
|
+
},
|
|
35
|
+
skills: [],
|
|
36
|
+
token: '1234',
|
|
37
|
+
corrections: {},
|
|
38
|
+
rank: {}
|
|
39
|
+
},
|
|
40
|
+
ui: {
|
|
41
|
+
currentSlideRef: sliderSlide._id,
|
|
42
|
+
navigation: ['skills', 'slides'],
|
|
43
|
+
answers: [],
|
|
44
|
+
slide: {
|
|
45
|
+
validateButton: false
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
test('should dispatch EDIT_SLIDER action via the property onSliderChange of a Slider slide', t => {
|
|
50
|
+
t.plan(1);
|
|
51
|
+
const expectedActions = [
|
|
52
|
+
{
|
|
53
|
+
type: EDIT_SLIDER,
|
|
54
|
+
payload: ['111']
|
|
55
|
+
}
|
|
56
|
+
];
|
|
57
|
+
const { dispatch, getState } = createTestStore(t, initialState, services, expectedActions);
|
|
58
|
+
const props = mapStateToSlidesProps(getState(), dispatch);
|
|
59
|
+
const SlideProps = props.stack.slides['0'].answerUI?.model;
|
|
60
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
61
|
+
const onSliderChange = get('onSliderChange', SlideProps);
|
|
62
|
+
onSliderChange(111);
|
|
63
|
+
});
|
|
@@ -38,6 +38,7 @@ import buildTask from '@coorpacademy/redux-task';
|
|
|
38
38
|
import get from 'lodash/fp/get';
|
|
39
39
|
import { fetchCorrection } from './fetch-correction';
|
|
40
40
|
import { fetchSlide } from './fetch-slide';
|
|
41
|
+
import { fetchEndRank, fetchStartRank } from './fetch-rank';
|
|
41
42
|
export var POST_ANSWER_REQUEST = '@@answer/POST_REQUEST';
|
|
42
43
|
export var POST_ANSWER_SUCCESS = '@@answer/POST_SUCCESS';
|
|
43
44
|
export var POST_ANSWER_FAILURE = '@@answer/POST_FAILURE';
|
|
@@ -61,17 +62,28 @@ export var postAnswer = function (dispatch, getState, _a) {
|
|
|
61
62
|
return [4 /*yield*/, dispatch(action)];
|
|
62
63
|
case 1:
|
|
63
64
|
response = _b.sent();
|
|
64
|
-
if (!(response.type === POST_ANSWER_SUCCESS)) return [3 /*break*/,
|
|
65
|
+
if (!(response.type === POST_ANSWER_SUCCESS)) return [3 /*break*/, 8];
|
|
65
66
|
updatedProgression = response.payload;
|
|
66
67
|
slideRef = updatedProgression.state.nextContent.ref;
|
|
68
|
+
if (!(slideRef !== 'successExitNode')) return [3 /*break*/, 5];
|
|
67
69
|
return [4 /*yield*/, dispatch(fetchSlide(slideRef))];
|
|
68
70
|
case 2:
|
|
69
71
|
_b.sent();
|
|
70
72
|
return [4 /*yield*/, dispatch(fetchCorrection)];
|
|
71
73
|
case 3:
|
|
72
74
|
_b.sent();
|
|
73
|
-
|
|
74
|
-
case 4:
|
|
75
|
+
return [4 /*yield*/, dispatch(fetchStartRank)];
|
|
76
|
+
case 4:
|
|
77
|
+
_b.sent();
|
|
78
|
+
return [3 /*break*/, 8];
|
|
79
|
+
case 5: return [4 /*yield*/, dispatch(fetchCorrection)];
|
|
80
|
+
case 6:
|
|
81
|
+
_b.sent();
|
|
82
|
+
return [4 /*yield*/, dispatch(fetchEndRank)];
|
|
83
|
+
case 7:
|
|
84
|
+
_b.sent();
|
|
85
|
+
_b.label = 8;
|
|
86
|
+
case 8: return [2 /*return*/];
|
|
75
87
|
}
|
|
76
88
|
});
|
|
77
89
|
});
|
|
@@ -53,7 +53,11 @@ import { postAnswer, POST_ANSWER_FAILURE, POST_ANSWER_REQUEST, POST_ANSWER_SUCCE
|
|
|
53
53
|
import { freeTextSlide } from '../../../views/slides/test/fixtures/free-text';
|
|
54
54
|
import { CORRECTION_FETCH_REQUEST, CORRECTION_FETCH_SUCCESS } from '../fetch-correction';
|
|
55
55
|
import { SLIDE_FETCH_REQUEST, SLIDE_FETCH_SUCCESS } from '../fetch-slide';
|
|
56
|
+
import { qcmSlide } from '../../../views/slides/test/fixtures/qcm';
|
|
56
57
|
import { qcmGraphicSlide } from '../../../views/slides/test/fixtures/qcm-graphic';
|
|
58
|
+
import { templateSlide } from '../../../views/slides/test/fixtures/template';
|
|
59
|
+
import { sliderSlide } from '../../../views/slides/test/fixtures/slider';
|
|
60
|
+
import { RANK_FETCH_START_REQUEST, RANK_FETCH_START_SUCCESS, RANK_FETCH_END_REQUEST, RANK_FETCH_END_SUCCESS } from '../fetch-rank';
|
|
57
61
|
var progressionId = '123456789123';
|
|
58
62
|
var skillRef = '_skill-ref';
|
|
59
63
|
var answer = ['Lister vos tâches pour vous libérer l’esprit', 'Vous isoler dans un lieu calme'];
|
|
@@ -97,12 +101,12 @@ var initialState = {
|
|
|
97
101
|
}
|
|
98
102
|
}
|
|
99
103
|
};
|
|
100
|
-
test('should dispatch post-answer, fetch-slide and fetch-correction actions when the answer is submitted', function (t) { return __awaiter(void 0, void 0, void 0, function () {
|
|
104
|
+
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"', function (t) { return __awaiter(void 0, void 0, void 0, function () {
|
|
101
105
|
var expectedActions, _a, dispatch, getState, state;
|
|
102
106
|
return __generator(this, function (_b) {
|
|
103
107
|
switch (_b.label) {
|
|
104
108
|
case 0:
|
|
105
|
-
t.plan(
|
|
109
|
+
t.plan(10);
|
|
106
110
|
expectedActions = [
|
|
107
111
|
{ type: POST_ANSWER_REQUEST },
|
|
108
112
|
{
|
|
@@ -127,6 +131,13 @@ test('should dispatch post-answer, fetch-slide and fetch-correction actions when
|
|
|
127
131
|
type: CORRECTION_FETCH_SUCCESS,
|
|
128
132
|
meta: { slideRef: freeTextSlide._id },
|
|
129
133
|
payload: getChoicesCorrection(freeTextSlide._id)
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
type: RANK_FETCH_START_REQUEST
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
type: RANK_FETCH_START_SUCCESS,
|
|
140
|
+
payload: { rank: 93 }
|
|
130
141
|
}
|
|
131
142
|
];
|
|
132
143
|
_a = createTestStore(t, initialState, services, expectedActions), dispatch = _a.dispatch, getState = _a.getState;
|
|
@@ -140,6 +151,67 @@ test('should dispatch post-answer, fetch-slide and fetch-correction actions when
|
|
|
140
151
|
}
|
|
141
152
|
});
|
|
142
153
|
}); });
|
|
154
|
+
test('should dispatch post-answer, fetch-correction and fetch-end-rank actions when the answer is submitted and when the slide ref is "successExitNode"', function (t) { return __awaiter(void 0, void 0, void 0, function () {
|
|
155
|
+
var stateBeforeExitNode, expectedActions, _a, dispatch, getState, state;
|
|
156
|
+
var _b;
|
|
157
|
+
return __generator(this, function (_c) {
|
|
158
|
+
switch (_c.label) {
|
|
159
|
+
case 0:
|
|
160
|
+
t.plan(8);
|
|
161
|
+
stateBeforeExitNode = {
|
|
162
|
+
data: {
|
|
163
|
+
progression: postAnswerResponses[sliderSlide.universalRef],
|
|
164
|
+
slides: (_b = {},
|
|
165
|
+
_b[freeTextSlide._id] = freeTextSlide,
|
|
166
|
+
_b[qcmGraphicSlide._id] = qcmGraphicSlide,
|
|
167
|
+
_b[qcmSlide._id] = qcmSlide,
|
|
168
|
+
_b[sliderSlide._id] = sliderSlide,
|
|
169
|
+
_b),
|
|
170
|
+
skills: [{ skillRef: skillRef, custom: false, name: skillRef, slidesToReview: 5 }],
|
|
171
|
+
token: '1234',
|
|
172
|
+
corrections: {},
|
|
173
|
+
rank: {}
|
|
174
|
+
},
|
|
175
|
+
ui: {
|
|
176
|
+
currentSlideRef: templateSlide._id,
|
|
177
|
+
navigation: ['skills', 'slides'],
|
|
178
|
+
answers: ['Leaderboard', 'utilisateurs', 'étoiles'],
|
|
179
|
+
slide: {
|
|
180
|
+
validateButton: false
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
expectedActions = [
|
|
185
|
+
{ type: POST_ANSWER_REQUEST },
|
|
186
|
+
{
|
|
187
|
+
type: POST_ANSWER_SUCCESS,
|
|
188
|
+
payload: postAnswerResponses[templateSlide._id]
|
|
189
|
+
},
|
|
190
|
+
{ type: CORRECTION_FETCH_REQUEST, meta: { slideRef: templateSlide._id } },
|
|
191
|
+
{
|
|
192
|
+
type: CORRECTION_FETCH_SUCCESS,
|
|
193
|
+
meta: { slideRef: templateSlide._id },
|
|
194
|
+
payload: getChoicesCorrection(templateSlide._id)
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
type: RANK_FETCH_END_REQUEST
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
type: RANK_FETCH_END_SUCCESS,
|
|
201
|
+
payload: { rank: 93 }
|
|
202
|
+
}
|
|
203
|
+
];
|
|
204
|
+
_a = createTestStore(t, stateBeforeExitNode, services, expectedActions), dispatch = _a.dispatch, getState = _a.getState;
|
|
205
|
+
return [4 /*yield*/, dispatch(postAnswer)];
|
|
206
|
+
case 1:
|
|
207
|
+
_c.sent();
|
|
208
|
+
state = getState();
|
|
209
|
+
t.false(state.ui.slide.validateButton);
|
|
210
|
+
t.true(state.ui.slide.animateCorrectionPopin);
|
|
211
|
+
return [2 /*return*/];
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
}); });
|
|
143
215
|
test('should dispatch POST_ANSWER_REQUEST, then POST_ANSWER_FAILURE on error', function (t) { return __awaiter(void 0, void 0, void 0, function () {
|
|
144
216
|
var expectedActions, dispatch;
|
|
145
217
|
return __generator(this, function (_a) {
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Dispatch } from 'redux';
|
|
2
|
+
import type { StoreState } from '../../reducers';
|
|
3
|
+
export declare const NEXT_SLIDE: "@@slide/NEXT_SLIDE";
|
|
4
|
+
declare type NextSlidePayload = {
|
|
5
|
+
currentSlideRef: string;
|
|
6
|
+
nextSlideRef: string;
|
|
7
|
+
animationType: string;
|
|
8
|
+
};
|
|
9
|
+
export declare type NextSlide = {
|
|
10
|
+
type: typeof NEXT_SLIDE;
|
|
11
|
+
payload: NextSlidePayload;
|
|
12
|
+
};
|
|
13
|
+
export declare const nextSlide: (dispatch: Dispatch, getState: () => StoreState) => NextSlide;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import get from 'lodash/fp/get';
|
|
2
|
+
export var NEXT_SLIDE = '@@slide/NEXT_SLIDE';
|
|
3
|
+
export var nextSlide = function (dispatch, getState) {
|
|
4
|
+
var _a;
|
|
5
|
+
var state = getState();
|
|
6
|
+
var payload = {
|
|
7
|
+
currentSlideRef: get(['ui', 'currentSlideRef'], state),
|
|
8
|
+
nextSlideRef: get(['data', 'progression', 'state', 'nextContent', 'ref'], state),
|
|
9
|
+
animationType: ((_a = state.data.progression) === null || _a === void 0 ? void 0 : _a.state.isCorrect) ? 'unstack' : 'restack'
|
|
10
|
+
};
|
|
11
|
+
var action = {
|
|
12
|
+
type: NEXT_SLIDE,
|
|
13
|
+
payload: payload
|
|
14
|
+
};
|
|
15
|
+
return dispatch(action);
|
|
16
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
var _a, _b;
|
|
2
|
+
import test from 'ava';
|
|
3
|
+
import pipe from 'lodash/fp/pipe';
|
|
4
|
+
import set from 'lodash/fp/set';
|
|
5
|
+
import { nextSlide, NEXT_SLIDE } from '../next-slide';
|
|
6
|
+
import { createTestStore } from '../../test/create-test-store';
|
|
7
|
+
import { getChoicesCorrection, postAnswerResponses, services } from '../../../test/util/services.mock';
|
|
8
|
+
import { freeTextSlide } from '../../../views/slides/test/fixtures/free-text';
|
|
9
|
+
import { qcmGraphicSlide } from '../../../views/slides/test/fixtures/qcm-graphic';
|
|
10
|
+
var progression = postAnswerResponses[freeTextSlide.universalRef];
|
|
11
|
+
var skillRef = '_skill-ref';
|
|
12
|
+
var answer = ['Vous isoler dans un lieu calme'];
|
|
13
|
+
var state = {
|
|
14
|
+
data: {
|
|
15
|
+
progression: progression,
|
|
16
|
+
slides: (_a = {},
|
|
17
|
+
_a[freeTextSlide.universalRef] = freeTextSlide,
|
|
18
|
+
_a[qcmGraphicSlide.universalRef] = qcmGraphicSlide,
|
|
19
|
+
_a),
|
|
20
|
+
skills: [{ skillRef: skillRef, custom: false, name: skillRef, slidesToReview: 5 }],
|
|
21
|
+
token: '1234',
|
|
22
|
+
corrections: (_b = {}, _b[freeTextSlide.universalRef] = getChoicesCorrection(freeTextSlide.universalRef), _b),
|
|
23
|
+
rank: { start: 93 }
|
|
24
|
+
},
|
|
25
|
+
ui: {
|
|
26
|
+
currentSlideRef: freeTextSlide._id,
|
|
27
|
+
navigation: ['loader', 'slides'],
|
|
28
|
+
answers: answer,
|
|
29
|
+
slide: {
|
|
30
|
+
validateButton: false,
|
|
31
|
+
animateCorrectionPopin: true,
|
|
32
|
+
showCorrectionPopin: true
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
test('should dispatch NEXT_SLIDE action when nextSlide is called and the progression state is correct', function (t) {
|
|
37
|
+
var expectedActions = [
|
|
38
|
+
{
|
|
39
|
+
type: NEXT_SLIDE,
|
|
40
|
+
payload: {
|
|
41
|
+
currentSlideRef: freeTextSlide.universalRef,
|
|
42
|
+
nextSlideRef: qcmGraphicSlide.universalRef,
|
|
43
|
+
animationType: 'unstack'
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
];
|
|
47
|
+
var dispatch = createTestStore(t, state, services, expectedActions).dispatch;
|
|
48
|
+
dispatch(nextSlide);
|
|
49
|
+
});
|
|
50
|
+
test('should dispatch NEXT_SLIDE action when nextSlide is called and the progression state is not correct', function (t) {
|
|
51
|
+
var stateWithWrongAnswer = pipe(set(['data', 'progression', 'state', 'isCorrect'], false), set(['data', 'progression', 'state', 'allAnswers', 0, 'isCorrect'], false))(state);
|
|
52
|
+
var expectedActions = [
|
|
53
|
+
{
|
|
54
|
+
type: NEXT_SLIDE,
|
|
55
|
+
payload: {
|
|
56
|
+
currentSlideRef: freeTextSlide.universalRef,
|
|
57
|
+
nextSlideRef: qcmGraphicSlide.universalRef,
|
|
58
|
+
animationType: 'restack'
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
];
|
|
62
|
+
var dispatch = createTestStore(t, stateWithWrongAnswer, services, expectedActions).dispatch;
|
|
63
|
+
dispatch(nextSlide);
|
|
64
|
+
});
|
|
@@ -19,5 +19,5 @@ declare const _default: import("redux").Reducer<import("redux").CombinedState<{
|
|
|
19
19
|
slides: SlidesState;
|
|
20
20
|
token: string;
|
|
21
21
|
rank: RankState;
|
|
22
|
-
}>, import("./corrections").CorrectionsAction | import("../../actions/api/post-answer").PostAnswerSuccessAction | import("../../actions/api/post-progression").ReceivedProgression | import("../../actions/api/fetch-skills").ReceivedSkills | import("./slides").SlidesAction | import("../../actions/data/token").StoreToken
|
|
22
|
+
}>, import("./corrections").CorrectionsAction | import("../../actions/api/fetch-rank").RankAction | import("../../actions/api/post-answer").PostAnswerSuccessAction | import("../../actions/api/post-progression").ReceivedProgression | import("../../actions/api/fetch-skills").ReceivedSkills | import("./slides").SlidesAction | import("../../actions/data/token").StoreToken>;
|
|
23
23
|
export default _default;
|
package/lib/reducers/index.d.ts
CHANGED
|
@@ -19,5 +19,5 @@ declare const _default: import("redux").Reducer<import("redux").CombinedState<{
|
|
|
19
19
|
answers: import("./ui/answers").AnswerState;
|
|
20
20
|
slide: import("./ui/slide").UISlideState;
|
|
21
21
|
}>;
|
|
22
|
-
}>, import("./data/corrections").CorrectionsAction | import("../actions/ui/slides").SetCurrentSlide | import("../actions/api/post-answer").PostAnswerRequestAction | import("../actions/api/post-answer").PostAnswerSuccessAction | import("../actions/api/post-progression").ReceivedProgression | import("../actions/api/fetch-skills").ReceivedSkills | import("./data/slides").SlidesAction | import("../actions/data/token").StoreToken | import("../actions/
|
|
22
|
+
}>, import("./data/corrections").CorrectionsAction | import("../actions/ui/slides").SetCurrentSlide | import("../actions/api/fetch-rank").RankAction | import("../actions/api/post-answer").PostAnswerRequestAction | import("../actions/api/post-answer").PostAnswerSuccessAction | import("../actions/api/post-progression").ReceivedProgression | import("../actions/api/fetch-skills").ReceivedSkills | import("./data/slides").SlidesAction | import("../actions/data/token").StoreToken | import("../actions/ui/navigation").NavigateTo | import("../actions/ui/navigation").NavigateBack | import("../actions/ui/answers").EditAnswerAction>;
|
|
23
23
|
export default _default;
|
package/lib/test/index.test.js
CHANGED
|
@@ -132,9 +132,6 @@ var clickAllSlides = function (t, container, accumulator) {
|
|
|
132
132
|
};
|
|
133
133
|
var appOptions = {
|
|
134
134
|
token: process.env.API_TEST_TOKEN || '',
|
|
135
|
-
templateContext: {
|
|
136
|
-
theme: { color: { primary: '#123' } }
|
|
137
|
-
},
|
|
138
135
|
skillRef: 'skill_NJC0jFKoH',
|
|
139
136
|
services: services
|
|
140
137
|
};
|
package/lib/types/common.d.ts
CHANGED
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
declare type TemplateContextValues = {
|
|
2
|
-
brandTheme?: unknown;
|
|
3
|
-
theme?: unknown;
|
|
4
|
-
translations?: unknown;
|
|
5
|
-
};
|
|
6
1
|
export declare type ChoiceFromAPI = {
|
|
7
2
|
_id: string;
|
|
8
3
|
id?: string;
|
|
@@ -140,9 +135,6 @@ export declare type Options = {
|
|
|
140
135
|
};
|
|
141
136
|
export declare type AppOptions = {
|
|
142
137
|
token: string;
|
|
143
|
-
theme?: unknown;
|
|
144
|
-
translations?: unknown;
|
|
145
|
-
templateContext?: TemplateContextValues;
|
|
146
138
|
skillRef?: string;
|
|
147
139
|
services: Services;
|
|
148
140
|
};
|
package/lib/types/slides.d.ts
CHANGED
|
@@ -44,8 +44,9 @@ export declare type DropDown = {
|
|
|
44
44
|
export declare type QuestionRange = {
|
|
45
45
|
type: 'slider';
|
|
46
46
|
placeholder?: string;
|
|
47
|
-
onChange?:
|
|
47
|
+
onChange?: (value: number) => void;
|
|
48
48
|
onChangeEnd?: Function;
|
|
49
|
+
onSliderChange?: (value: number) => void;
|
|
49
50
|
multi?: boolean;
|
|
50
51
|
value: number | number[];
|
|
51
52
|
title: string;
|
|
@@ -145,8 +145,13 @@ var sliderProps = function (dispatch) {
|
|
|
145
145
|
title: "".concat(currentValue, " ").concat(question.content.unitLabel),
|
|
146
146
|
value: sliderPosition,
|
|
147
147
|
onChange: function (position) {
|
|
148
|
+
// atom/range handler
|
|
148
149
|
var newValue = pipe(multiply(maxValue), round, get(__, values), _toString)(position);
|
|
149
150
|
dispatch(editAnswer([newValue]));
|
|
151
|
+
},
|
|
152
|
+
onSliderChange: function (newValue) {
|
|
153
|
+
// mobile/slider handler
|
|
154
|
+
dispatch(editAnswer(["".concat(newValue)]));
|
|
150
155
|
}
|
|
151
156
|
};
|
|
152
157
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
var _a;
|
|
2
|
+
import test from 'ava';
|
|
3
|
+
import get from 'lodash/fp/get';
|
|
4
|
+
import { mapStateToSlidesProps } from '..';
|
|
5
|
+
import { services } from '../../../test/util/services.mock';
|
|
6
|
+
import { createTestStore } from '../../../actions/test/create-test-store';
|
|
7
|
+
import { EDIT_SLIDER } from '../../../actions/ui/answers';
|
|
8
|
+
import { sliderSlide } from './fixtures/slider';
|
|
9
|
+
var progression = {
|
|
10
|
+
_id: '123456789123',
|
|
11
|
+
content: { type: 'skill', ref: '_skill-ref' },
|
|
12
|
+
engine: {
|
|
13
|
+
ref: 'review'
|
|
14
|
+
},
|
|
15
|
+
state: {
|
|
16
|
+
allAnswers: [],
|
|
17
|
+
isCorrect: true,
|
|
18
|
+
nextContent: {
|
|
19
|
+
ref: sliderSlide._id,
|
|
20
|
+
type: 'slide'
|
|
21
|
+
},
|
|
22
|
+
pendingSlides: [],
|
|
23
|
+
slides: [],
|
|
24
|
+
step: {
|
|
25
|
+
current: 1
|
|
26
|
+
},
|
|
27
|
+
stars: 0
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
var initialState = {
|
|
31
|
+
data: {
|
|
32
|
+
progression: progression,
|
|
33
|
+
slides: (_a = {},
|
|
34
|
+
_a[sliderSlide._id] = sliderSlide,
|
|
35
|
+
_a),
|
|
36
|
+
skills: [],
|
|
37
|
+
token: '1234',
|
|
38
|
+
corrections: {},
|
|
39
|
+
rank: {}
|
|
40
|
+
},
|
|
41
|
+
ui: {
|
|
42
|
+
currentSlideRef: sliderSlide._id,
|
|
43
|
+
navigation: ['skills', 'slides'],
|
|
44
|
+
answers: [],
|
|
45
|
+
slide: {
|
|
46
|
+
validateButton: false
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
test('should dispatch EDIT_SLIDER action via the property onSliderChange of a Slider slide', function (t) {
|
|
51
|
+
var _a;
|
|
52
|
+
t.plan(1);
|
|
53
|
+
var expectedActions = [
|
|
54
|
+
{
|
|
55
|
+
type: EDIT_SLIDER,
|
|
56
|
+
payload: ['111']
|
|
57
|
+
}
|
|
58
|
+
];
|
|
59
|
+
var _b = createTestStore(t, initialState, services, expectedActions), dispatch = _b.dispatch, getState = _b.getState;
|
|
60
|
+
var props = mapStateToSlidesProps(getState(), dispatch);
|
|
61
|
+
var SlideProps = (_a = props.stack.slides['0'].answerUI) === null || _a === void 0 ? void 0 : _a.model;
|
|
62
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
63
|
+
var onSliderChange = get('onSliderChange', SlideProps);
|
|
64
|
+
onSliderChange(111);
|
|
65
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coorpacademy/app-review",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.10-alpha.16+979312a0a",
|
|
4
4
|
"description": "",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=16.15.0"
|
|
@@ -41,8 +41,8 @@
|
|
|
41
41
|
"./package.json": "./package.json"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@coorpacademy/components": "10.22.
|
|
45
|
-
"@coorpacademy/redux-task": "
|
|
44
|
+
"@coorpacademy/components": "10.22.25-alpha.16+979312a0a",
|
|
45
|
+
"@coorpacademy/redux-task": "1.1.5",
|
|
46
46
|
"cross-fetch": "^3.1.5",
|
|
47
47
|
"jwt-decode": "^3.1.2",
|
|
48
48
|
"react-redux": "^8.0.1",
|
|
@@ -78,5 +78,5 @@
|
|
|
78
78
|
"ts-node": "^10.9.1",
|
|
79
79
|
"typescript": "^4.7.4"
|
|
80
80
|
},
|
|
81
|
-
"gitHead": "
|
|
81
|
+
"gitHead": "979312a0adf811d29dd0f18ceef61194e2b2c69d"
|
|
82
82
|
}
|
|
@@ -5,6 +5,7 @@ import type {Options, ProgressionFromAPI} from '../../types/common';
|
|
|
5
5
|
import type {StoreState} from '../../reducers';
|
|
6
6
|
import {fetchCorrection} from './fetch-correction';
|
|
7
7
|
import {fetchSlide} from './fetch-slide';
|
|
8
|
+
import {fetchEndRank, fetchStartRank} from './fetch-rank';
|
|
8
9
|
|
|
9
10
|
export const POST_ANSWER_REQUEST = '@@answer/POST_REQUEST' as const;
|
|
10
11
|
export const POST_ANSWER_SUCCESS = '@@answer/POST_SUCCESS' as const;
|
|
@@ -38,7 +39,13 @@ export const postAnswer = async (
|
|
|
38
39
|
if (response.type === POST_ANSWER_SUCCESS) {
|
|
39
40
|
const updatedProgression = response.payload;
|
|
40
41
|
const slideRef = updatedProgression.state.nextContent.ref;
|
|
41
|
-
|
|
42
|
-
|
|
42
|
+
if (slideRef !== 'successExitNode') {
|
|
43
|
+
await dispatch(fetchSlide(slideRef));
|
|
44
|
+
await dispatch(fetchCorrection);
|
|
45
|
+
await dispatch(fetchStartRank);
|
|
46
|
+
} else {
|
|
47
|
+
await dispatch(fetchCorrection);
|
|
48
|
+
await dispatch(fetchEndRank);
|
|
49
|
+
}
|
|
43
50
|
}
|
|
44
51
|
};
|
|
@@ -16,7 +16,16 @@ import type {StoreState} from '../../../reducers';
|
|
|
16
16
|
import {freeTextSlide} from '../../../views/slides/test/fixtures/free-text';
|
|
17
17
|
import {CORRECTION_FETCH_REQUEST, CORRECTION_FETCH_SUCCESS} from '../fetch-correction';
|
|
18
18
|
import {SLIDE_FETCH_REQUEST, SLIDE_FETCH_SUCCESS} from '../fetch-slide';
|
|
19
|
+
import {qcmSlide} from '../../../views/slides/test/fixtures/qcm';
|
|
19
20
|
import {qcmGraphicSlide} from '../../../views/slides/test/fixtures/qcm-graphic';
|
|
21
|
+
import {templateSlide} from '../../../views/slides/test/fixtures/template';
|
|
22
|
+
import {sliderSlide} from '../../../views/slides/test/fixtures/slider';
|
|
23
|
+
import {
|
|
24
|
+
RANK_FETCH_START_REQUEST,
|
|
25
|
+
RANK_FETCH_START_SUCCESS,
|
|
26
|
+
RANK_FETCH_END_REQUEST,
|
|
27
|
+
RANK_FETCH_END_SUCCESS
|
|
28
|
+
} from '../fetch-rank';
|
|
20
29
|
|
|
21
30
|
const progressionId = '123456789123';
|
|
22
31
|
const skillRef = '_skill-ref';
|
|
@@ -63,8 +72,8 @@ const initialState: StoreState = {
|
|
|
63
72
|
}
|
|
64
73
|
};
|
|
65
74
|
|
|
66
|
-
test('should dispatch post-answer, fetch-slide and fetch-correction actions when the answer is submitted', async t => {
|
|
67
|
-
t.plan(
|
|
75
|
+
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);
|
|
68
77
|
const expectedActions = [
|
|
69
78
|
{type: POST_ANSWER_REQUEST},
|
|
70
79
|
{
|
|
@@ -89,6 +98,13 @@ test('should dispatch post-answer, fetch-slide and fetch-correction actions when
|
|
|
89
98
|
type: CORRECTION_FETCH_SUCCESS,
|
|
90
99
|
meta: {slideRef: freeTextSlide._id},
|
|
91
100
|
payload: getChoicesCorrection(freeTextSlide._id)
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
type: RANK_FETCH_START_REQUEST
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
type: RANK_FETCH_START_SUCCESS,
|
|
107
|
+
payload: {rank: 93}
|
|
92
108
|
}
|
|
93
109
|
];
|
|
94
110
|
|
|
@@ -102,6 +118,64 @@ test('should dispatch post-answer, fetch-slide and fetch-correction actions when
|
|
|
102
118
|
t.true(state.ui.slide.animateCorrectionPopin);
|
|
103
119
|
});
|
|
104
120
|
|
|
121
|
+
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);
|
|
123
|
+
|
|
124
|
+
const stateBeforeExitNode: StoreState = {
|
|
125
|
+
data: {
|
|
126
|
+
progression: postAnswerResponses[sliderSlide.universalRef],
|
|
127
|
+
slides: {
|
|
128
|
+
[freeTextSlide._id]: freeTextSlide,
|
|
129
|
+
[qcmGraphicSlide._id]: qcmGraphicSlide,
|
|
130
|
+
[qcmSlide._id]: qcmSlide,
|
|
131
|
+
[sliderSlide._id]: sliderSlide
|
|
132
|
+
},
|
|
133
|
+
skills: [{skillRef, custom: false, name: skillRef, slidesToReview: 5}],
|
|
134
|
+
token: '1234',
|
|
135
|
+
corrections: {},
|
|
136
|
+
rank: {}
|
|
137
|
+
},
|
|
138
|
+
ui: {
|
|
139
|
+
currentSlideRef: templateSlide._id,
|
|
140
|
+
navigation: ['skills', 'slides'],
|
|
141
|
+
answers: ['Leaderboard', 'utilisateurs', 'étoiles'],
|
|
142
|
+
slide: {
|
|
143
|
+
validateButton: false
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
const expectedActions = [
|
|
149
|
+
{type: POST_ANSWER_REQUEST},
|
|
150
|
+
{
|
|
151
|
+
type: POST_ANSWER_SUCCESS,
|
|
152
|
+
payload: postAnswerResponses[templateSlide._id]
|
|
153
|
+
},
|
|
154
|
+
{type: CORRECTION_FETCH_REQUEST, meta: {slideRef: templateSlide._id}},
|
|
155
|
+
{
|
|
156
|
+
type: CORRECTION_FETCH_SUCCESS,
|
|
157
|
+
meta: {slideRef: templateSlide._id},
|
|
158
|
+
payload: getChoicesCorrection(templateSlide._id)
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
type: RANK_FETCH_END_REQUEST
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
type: RANK_FETCH_END_SUCCESS,
|
|
165
|
+
payload: {rank: 93}
|
|
166
|
+
}
|
|
167
|
+
];
|
|
168
|
+
|
|
169
|
+
const {dispatch, getState} = createTestStore(t, stateBeforeExitNode, services, expectedActions);
|
|
170
|
+
|
|
171
|
+
await dispatch(postAnswer);
|
|
172
|
+
|
|
173
|
+
const state = getState();
|
|
174
|
+
|
|
175
|
+
t.false(state.ui.slide.validateButton);
|
|
176
|
+
t.true(state.ui.slide.animateCorrectionPopin);
|
|
177
|
+
});
|
|
178
|
+
|
|
105
179
|
test('should dispatch POST_ANSWER_REQUEST, then POST_ANSWER_FAILURE on error', async t => {
|
|
106
180
|
t.plan(3);
|
|
107
181
|
const expectedActions = [
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type {Dispatch} from 'redux';
|
|
2
|
+
import get from 'lodash/fp/get';
|
|
3
|
+
import type {StoreState} from '../../reducers';
|
|
4
|
+
|
|
5
|
+
export const NEXT_SLIDE = '@@slide/NEXT_SLIDE' as const;
|
|
6
|
+
|
|
7
|
+
type NextSlidePayload = {
|
|
8
|
+
currentSlideRef: string;
|
|
9
|
+
nextSlideRef: string;
|
|
10
|
+
animationType: string;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export type NextSlide = {
|
|
14
|
+
type: typeof NEXT_SLIDE;
|
|
15
|
+
payload: NextSlidePayload;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const nextSlide = (dispatch: Dispatch, getState: () => StoreState): NextSlide => {
|
|
19
|
+
const state = getState();
|
|
20
|
+
const payload = {
|
|
21
|
+
currentSlideRef: get(['ui', 'currentSlideRef'], state),
|
|
22
|
+
nextSlideRef: get(['data', 'progression', 'state', 'nextContent', 'ref'], state),
|
|
23
|
+
animationType: state.data.progression?.state.isCorrect ? 'unstack' : 'restack'
|
|
24
|
+
};
|
|
25
|
+
const action = {
|
|
26
|
+
type: NEXT_SLIDE,
|
|
27
|
+
payload
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
return dispatch(action);
|
|
31
|
+
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import test from 'ava';
|
|
2
|
+
import pipe from 'lodash/fp/pipe';
|
|
3
|
+
import set from 'lodash/fp/set';
|
|
4
|
+
import {StoreState} from '../../../reducers';
|
|
5
|
+
import {nextSlide, NEXT_SLIDE} from '../next-slide';
|
|
6
|
+
import {createTestStore} from '../../test/create-test-store';
|
|
7
|
+
import {
|
|
8
|
+
getChoicesCorrection,
|
|
9
|
+
postAnswerResponses,
|
|
10
|
+
services
|
|
11
|
+
} from '../../../test/util/services.mock';
|
|
12
|
+
import {freeTextSlide} from '../../../views/slides/test/fixtures/free-text';
|
|
13
|
+
import {qcmGraphicSlide} from '../../../views/slides/test/fixtures/qcm-graphic';
|
|
14
|
+
|
|
15
|
+
const progression = postAnswerResponses[freeTextSlide.universalRef];
|
|
16
|
+
const skillRef = '_skill-ref';
|
|
17
|
+
const answer = ['Vous isoler dans un lieu calme'];
|
|
18
|
+
|
|
19
|
+
const state: StoreState = {
|
|
20
|
+
data: {
|
|
21
|
+
progression,
|
|
22
|
+
slides: {
|
|
23
|
+
[freeTextSlide.universalRef]: freeTextSlide,
|
|
24
|
+
[qcmGraphicSlide.universalRef]: qcmGraphicSlide
|
|
25
|
+
},
|
|
26
|
+
skills: [{skillRef, custom: false, name: skillRef, slidesToReview: 5}],
|
|
27
|
+
token: '1234',
|
|
28
|
+
corrections: {[freeTextSlide.universalRef]: getChoicesCorrection(freeTextSlide.universalRef)},
|
|
29
|
+
rank: {start: 93}
|
|
30
|
+
},
|
|
31
|
+
ui: {
|
|
32
|
+
currentSlideRef: freeTextSlide._id,
|
|
33
|
+
navigation: ['loader', 'slides'],
|
|
34
|
+
answers: answer,
|
|
35
|
+
slide: {
|
|
36
|
+
validateButton: false,
|
|
37
|
+
animateCorrectionPopin: true,
|
|
38
|
+
showCorrectionPopin: true
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
test('should dispatch NEXT_SLIDE action when nextSlide is called and the progression state is correct', t => {
|
|
43
|
+
const expectedActions = [
|
|
44
|
+
{
|
|
45
|
+
type: NEXT_SLIDE,
|
|
46
|
+
payload: {
|
|
47
|
+
currentSlideRef: freeTextSlide.universalRef,
|
|
48
|
+
nextSlideRef: qcmGraphicSlide.universalRef,
|
|
49
|
+
animationType: 'unstack'
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
];
|
|
53
|
+
const {dispatch} = createTestStore(t, state, services, expectedActions);
|
|
54
|
+
dispatch(nextSlide);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test('should dispatch NEXT_SLIDE action when nextSlide is called and the progression state is not correct', t => {
|
|
58
|
+
const stateWithWrongAnswer = pipe(
|
|
59
|
+
set(['data', 'progression', 'state', 'isCorrect'], false),
|
|
60
|
+
set(['data', 'progression', 'state', 'allAnswers', 0, 'isCorrect'], false)
|
|
61
|
+
)(state);
|
|
62
|
+
|
|
63
|
+
const expectedActions = [
|
|
64
|
+
{
|
|
65
|
+
type: NEXT_SLIDE,
|
|
66
|
+
payload: {
|
|
67
|
+
currentSlideRef: freeTextSlide.universalRef,
|
|
68
|
+
nextSlideRef: qcmGraphicSlide.universalRef,
|
|
69
|
+
animationType: 'restack'
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
];
|
|
73
|
+
const {dispatch} = createTestStore(t, stateWithWrongAnswer, services, expectedActions);
|
|
74
|
+
dispatch(nextSlide);
|
|
75
|
+
});
|
package/src/test/index.test.tsx
CHANGED
package/src/types/common.ts
CHANGED
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
// TODO use type from components
|
|
2
|
-
type TemplateContextValues = {
|
|
3
|
-
brandTheme?: unknown;
|
|
4
|
-
theme?: unknown; // TODO type Theme
|
|
5
|
-
translations?: unknown; // TODO type Translations
|
|
6
|
-
};
|
|
7
|
-
|
|
8
1
|
// TODO: EDIT_CHOICES -> specify typing
|
|
9
2
|
export type ChoiceFromAPI = {
|
|
10
3
|
_id: string;
|
|
@@ -176,9 +169,6 @@ export type Options = {
|
|
|
176
169
|
|
|
177
170
|
export type AppOptions = {
|
|
178
171
|
token: string;
|
|
179
|
-
theme?: unknown;
|
|
180
|
-
translations?: unknown;
|
|
181
|
-
templateContext?: TemplateContextValues;
|
|
182
172
|
skillRef?: string;
|
|
183
173
|
services: Services;
|
|
184
174
|
};
|
package/src/types/slides.ts
CHANGED
|
@@ -59,8 +59,9 @@ export type DropDown = {
|
|
|
59
59
|
export type QuestionRange = {
|
|
60
60
|
type: 'slider';
|
|
61
61
|
placeholder?: string;
|
|
62
|
-
onChange?:
|
|
62
|
+
onChange?: (value: number) => void;
|
|
63
63
|
onChangeEnd?: Function;
|
|
64
|
+
onSliderChange?: (value: number) => void;
|
|
64
65
|
multi?: boolean;
|
|
65
66
|
value: number | number[];
|
|
66
67
|
title: string;
|
|
@@ -225,6 +225,7 @@ const sliderProps =
|
|
|
225
225
|
title: `${currentValue} ${question.content.unitLabel}`,
|
|
226
226
|
value: sliderPosition,
|
|
227
227
|
onChange: (position: number): void => {
|
|
228
|
+
// atom/range handler
|
|
228
229
|
const newValue: string = pipe(
|
|
229
230
|
multiply(maxValue),
|
|
230
231
|
round,
|
|
@@ -232,6 +233,10 @@ const sliderProps =
|
|
|
232
233
|
_toString
|
|
233
234
|
)(position);
|
|
234
235
|
dispatch(editAnswer([newValue]));
|
|
236
|
+
},
|
|
237
|
+
onSliderChange: (newValue: number): void => {
|
|
238
|
+
// mobile/slider handler
|
|
239
|
+
dispatch(editAnswer([`${newValue}`]));
|
|
235
240
|
}
|
|
236
241
|
};
|
|
237
242
|
};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import test from 'ava';
|
|
2
|
+
import get from 'lodash/fp/get';
|
|
3
|
+
import {ProgressionFromAPI} from '../../../types/common';
|
|
4
|
+
import {StoreState} from '../../../reducers';
|
|
5
|
+
import {mapStateToSlidesProps} from '..';
|
|
6
|
+
import {services} from '../../../test/util/services.mock';
|
|
7
|
+
import {createTestStore} from '../../../actions/test/create-test-store';
|
|
8
|
+
import {EDIT_SLIDER} from '../../../actions/ui/answers';
|
|
9
|
+
import {QuestionRange} from '../../../types/slides';
|
|
10
|
+
import {sliderSlide} from './fixtures/slider';
|
|
11
|
+
|
|
12
|
+
const progression: ProgressionFromAPI = {
|
|
13
|
+
_id: '123456789123',
|
|
14
|
+
content: {type: 'skill', ref: '_skill-ref'},
|
|
15
|
+
engine: {
|
|
16
|
+
ref: 'review'
|
|
17
|
+
},
|
|
18
|
+
state: {
|
|
19
|
+
allAnswers: [],
|
|
20
|
+
isCorrect: true,
|
|
21
|
+
nextContent: {
|
|
22
|
+
ref: sliderSlide._id,
|
|
23
|
+
type: 'slide'
|
|
24
|
+
},
|
|
25
|
+
pendingSlides: [],
|
|
26
|
+
slides: [],
|
|
27
|
+
step: {
|
|
28
|
+
current: 1
|
|
29
|
+
},
|
|
30
|
+
stars: 0
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const initialState: StoreState = {
|
|
35
|
+
data: {
|
|
36
|
+
progression,
|
|
37
|
+
slides: {
|
|
38
|
+
[sliderSlide._id]: sliderSlide
|
|
39
|
+
},
|
|
40
|
+
skills: [],
|
|
41
|
+
token: '1234',
|
|
42
|
+
corrections: {},
|
|
43
|
+
rank: {}
|
|
44
|
+
},
|
|
45
|
+
ui: {
|
|
46
|
+
currentSlideRef: sliderSlide._id,
|
|
47
|
+
navigation: ['skills', 'slides'],
|
|
48
|
+
answers: [],
|
|
49
|
+
slide: {
|
|
50
|
+
validateButton: false
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
test('should dispatch EDIT_SLIDER action via the property onSliderChange of a Slider slide', t => {
|
|
56
|
+
t.plan(1);
|
|
57
|
+
|
|
58
|
+
const expectedActions = [
|
|
59
|
+
{
|
|
60
|
+
type: EDIT_SLIDER,
|
|
61
|
+
payload: ['111']
|
|
62
|
+
}
|
|
63
|
+
];
|
|
64
|
+
const {dispatch, getState} = createTestStore(t, initialState, services, expectedActions);
|
|
65
|
+
const props = mapStateToSlidesProps(getState(), dispatch);
|
|
66
|
+
|
|
67
|
+
const SlideProps = props.stack.slides['0'].answerUI?.model as QuestionRange;
|
|
68
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
69
|
+
const onSliderChange = get('onSliderChange', SlideProps)!;
|
|
70
|
+
onSliderChange(111);
|
|
71
|
+
});
|