@coorpacademy/app-review 0.1.21 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/es/actions/api/fetch-correction.d.ts +11 -0
- package/es/actions/api/fetch-correction.js +19 -0
- package/es/actions/api/fetch-skills.d.ts +2 -2
- package/es/actions/api/fetch-skills.js +3 -3
- package/es/actions/api/fetch-slide.js +1 -1
- package/es/actions/api/post-answer.js +3 -5
- package/es/actions/api/post-progression.js +2 -4
- package/es/actions/api/test/fetch-correction.test.d.ts +1 -0
- package/es/actions/api/test/fetch-correction.test.js +73 -0
- package/es/actions/api/test/fetch-skills.test.js +3 -1
- package/es/actions/api/test/fetch-slide.test.js +2 -0
- package/es/actions/api/test/post-answer.test.js +12 -7
- package/es/actions/api/test/post-progression.test.js +3 -1
- package/es/actions/ui/test/answers.test.js +1 -1
- package/es/reducers/data/index.d.ts +2 -2
- package/es/reducers/data/slides.js +2 -2
- package/es/reducers/data/test/token.test.js +3 -3
- package/es/reducers/data/token.d.ts +2 -2
- package/es/reducers/data/token.js +1 -1
- package/es/reducers/index.d.ts +1 -1
- package/es/reducers/ui/current-slide-ref.js +1 -1
- package/es/services/fetch-slide.js +1 -1
- package/es/services/post-answer.js +3 -3
- package/es/services/post-progression.js +2 -2
- package/es/services/test/fetch-slide.test.js +1 -1
- package/es/services/test/post-answer.test.js +9 -1
- package/es/services/test/post-progression.test.js +12 -1
- package/es/test/util/services.mock.d.ts +2 -1
- package/es/test/util/services.mock.js +2 -2
- package/es/types/common.d.ts +1 -1
- package/es/views/slides/test/fixtures/free-text.js +1 -1
- package/es/views/slides/test/fixtures/qcm-drag.js +1 -1
- package/es/views/slides/test/fixtures/qcm-graphic.js +1 -1
- package/es/views/slides/test/fixtures/qcm.js +1 -1
- package/es/views/slides/test/fixtures/slider.js +1 -1
- package/es/views/slides/test/fixtures/template.js +1 -1
- package/es/views/slides/test/slide.template.on-change.test.js +3 -3
- package/lib/actions/api/fetch-correction.d.ts +11 -0
- package/lib/actions/api/fetch-correction.js +20 -0
- package/lib/actions/api/fetch-skills.d.ts +2 -2
- package/lib/actions/api/fetch-skills.js +8 -55
- package/lib/actions/api/fetch-slide.js +1 -1
- package/lib/actions/api/post-answer.js +3 -5
- package/lib/actions/api/post-progression.js +2 -4
- package/lib/actions/api/test/fetch-correction.test.d.ts +1 -0
- package/lib/actions/api/test/fetch-correction.test.js +133 -0
- package/lib/actions/api/test/fetch-skills.test.js +3 -1
- package/lib/actions/api/test/fetch-slide.test.js +2 -0
- package/lib/actions/api/test/post-answer.test.js +12 -7
- package/lib/actions/api/test/post-progression.test.js +3 -1
- package/lib/actions/ui/test/answers.test.js +1 -1
- package/lib/reducers/data/index.d.ts +2 -2
- package/lib/reducers/data/slides.js +2 -2
- package/lib/reducers/data/test/token.test.js +3 -3
- package/lib/reducers/data/token.d.ts +2 -2
- package/lib/reducers/data/token.js +1 -1
- package/lib/reducers/index.d.ts +1 -1
- package/lib/reducers/ui/current-slide-ref.js +1 -1
- package/lib/services/fetch-slide.js +1 -1
- package/lib/services/post-answer.js +4 -4
- package/lib/services/post-progression.js +2 -2
- package/lib/services/test/fetch-slide.test.js +1 -1
- package/lib/services/test/post-answer.test.js +9 -1
- package/lib/services/test/post-progression.test.js +12 -1
- package/lib/test/util/services.mock.d.ts +2 -1
- package/lib/test/util/services.mock.js +2 -2
- package/lib/types/common.d.ts +1 -1
- package/lib/views/slides/test/fixtures/free-text.js +1 -1
- package/lib/views/slides/test/fixtures/qcm-drag.js +1 -1
- package/lib/views/slides/test/fixtures/qcm-graphic.js +1 -1
- package/lib/views/slides/test/fixtures/qcm.js +1 -1
- package/lib/views/slides/test/fixtures/slider.js +1 -1
- package/lib/views/slides/test/fixtures/template.js +1 -1
- package/lib/views/slides/test/slide.template.on-change.test.js +3 -3
- package/package.json +2 -2
- package/src/actions/api/fetch-correction.ts +33 -0
- package/src/actions/api/fetch-skills.ts +5 -5
- package/src/actions/api/fetch-slide.ts +1 -1
- package/src/actions/api/post-answer.ts +3 -5
- package/src/actions/api/post-progression.ts +2 -4
- package/src/actions/api/test/fetch-correction.test.ts +94 -0
- package/src/actions/api/test/fetch-skills.test.ts +3 -1
- package/src/actions/api/test/fetch-slide.test.ts +2 -0
- package/src/actions/api/test/post-answer.test.ts +12 -7
- package/src/actions/api/test/post-progression.test.ts +3 -1
- package/src/actions/ui/test/answers.test.ts +3 -3
- package/src/reducers/data/index.ts +1 -1
- package/src/reducers/data/slides.ts +2 -2
- package/src/reducers/data/test/token.test.ts +3 -3
- package/src/reducers/data/token.ts +2 -2
- package/src/reducers/ui/current-slide-ref.ts +1 -1
- package/src/services/fetch-slide.ts +1 -1
- package/src/services/post-answer.ts +3 -3
- package/src/services/post-progression.ts +2 -2
- package/src/services/test/fetch-slide.test.ts +1 -1
- package/src/services/test/post-answer.test.ts +9 -1
- package/src/services/test/post-progression.test.ts +12 -1
- package/src/test/util/services.mock.ts +2 -2
- package/src/types/common.ts +1 -1
- package/src/views/slides/test/fixtures/free-text.ts +1 -1
- package/src/views/slides/test/fixtures/qcm-drag.ts +1 -1
- package/src/views/slides/test/fixtures/qcm-graphic.ts +1 -1
- package/src/views/slides/test/fixtures/qcm.ts +1 -1
- package/src/views/slides/test/fixtures/slider.ts +1 -1
- package/src/views/slides/test/fixtures/template.ts +1 -1
- package/src/views/slides/test/slide.template.on-change.test.ts +3 -3
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Dispatch } from 'redux';
|
|
2
|
+
import type { StoreState } from '../../reducers';
|
|
3
|
+
import type { CorrectionFromAPI, Options } from '../../types/common';
|
|
4
|
+
export declare const CORRECTION_FETCH_REQUEST: "@@correction/FETCH_REQUEST";
|
|
5
|
+
export declare const CORRECTION_FETCH_SUCCESS: "@@correction/FETCH_SUCCESS";
|
|
6
|
+
export declare const CORRECTION_FETCH_FAILURE: "@@correction/FETCH_FAILURE";
|
|
7
|
+
export declare type FetchCorrection = {
|
|
8
|
+
type: typeof CORRECTION_FETCH_SUCCESS;
|
|
9
|
+
payload: CorrectionFromAPI | void;
|
|
10
|
+
};
|
|
11
|
+
export declare const fetchCorrection: (dispatch: Dispatch, getState: () => StoreState, { services }: Options) => FetchCorrection;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import buildTask from '@coorpacademy/redux-task';
|
|
2
|
+
import get from 'lodash/fp/get';
|
|
3
|
+
export const CORRECTION_FETCH_REQUEST = '@@correction/FETCH_REQUEST';
|
|
4
|
+
export const CORRECTION_FETCH_SUCCESS = '@@correction/FETCH_SUCCESS';
|
|
5
|
+
export const CORRECTION_FETCH_FAILURE = '@@correction/FETCH_FAILURE';
|
|
6
|
+
export const fetchCorrection = (dispatch, getState, { services }) => {
|
|
7
|
+
const action = buildTask({
|
|
8
|
+
types: [CORRECTION_FETCH_REQUEST, CORRECTION_FETCH_SUCCESS, CORRECTION_FETCH_FAILURE],
|
|
9
|
+
task: () => {
|
|
10
|
+
const state = getState();
|
|
11
|
+
const token = get(['data', 'token'], state);
|
|
12
|
+
const progressionId = get(['data', 'progression', '_id'], state);
|
|
13
|
+
const answer = get(['ui', 'answers'], state);
|
|
14
|
+
const slideRef = get(['ui', 'currentSlideRef'], state);
|
|
15
|
+
return services.fetchCorrection(slideRef, token, progressionId, answer);
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
return dispatch(action);
|
|
19
|
+
};
|
|
@@ -5,7 +5,7 @@ export declare const SKILLS_FETCH_REQUEST: "@@skills/FETCH_REQUEST";
|
|
|
5
5
|
export declare const SKILLS_FETCH_SUCCESS: "@@skills/FETCH_SUCCESS";
|
|
6
6
|
export declare const SKILLS_FETCH_FAILURE: "@@skills/FETCH_FAILURE";
|
|
7
7
|
export declare type ReceivedSkills = {
|
|
8
|
-
type:
|
|
8
|
+
type: typeof SKILLS_FETCH_SUCCESS;
|
|
9
9
|
payload: Skill[];
|
|
10
10
|
};
|
|
11
|
-
export declare const fetchSkills: (dispatch: Dispatch, getState: () => StoreState, { services }: Options) =>
|
|
11
|
+
export declare const fetchSkills: (dispatch: Dispatch, getState: () => StoreState, { services }: Options) => ReceivedSkills;
|
|
@@ -3,14 +3,14 @@ import get from 'lodash/fp/get';
|
|
|
3
3
|
export const SKILLS_FETCH_REQUEST = '@@skills/FETCH_REQUEST';
|
|
4
4
|
export const SKILLS_FETCH_SUCCESS = '@@skills/FETCH_SUCCESS';
|
|
5
5
|
export const SKILLS_FETCH_FAILURE = '@@skills/FETCH_FAILURE';
|
|
6
|
-
export const fetchSkills =
|
|
6
|
+
export const fetchSkills = (dispatch, getState, { services }) => {
|
|
7
7
|
const action = buildTask({
|
|
8
8
|
types: [SKILLS_FETCH_REQUEST, SKILLS_FETCH_SUCCESS, SKILLS_FETCH_FAILURE],
|
|
9
9
|
task: () => {
|
|
10
10
|
const state = getState();
|
|
11
|
-
const token = get('data
|
|
11
|
+
const token = get(['data', 'token'], state);
|
|
12
12
|
return services.fetchSkills(token);
|
|
13
13
|
}
|
|
14
14
|
});
|
|
15
|
-
|
|
15
|
+
return dispatch(action);
|
|
16
16
|
};
|
|
@@ -14,7 +14,7 @@ export const fetchSlide = (slideRef) => async (dispatch, getState, { services })
|
|
|
14
14
|
},
|
|
15
15
|
task: () => {
|
|
16
16
|
const state = getState();
|
|
17
|
-
const token = get('data
|
|
17
|
+
const token = get(['data', 'token'], state);
|
|
18
18
|
return services.fetchSlide(slideRef, token);
|
|
19
19
|
},
|
|
20
20
|
meta: { slideRef }
|
|
@@ -6,16 +6,14 @@ export const POST_ANSWER_SUCCESS = '@@answer/POST_SUCCESS';
|
|
|
6
6
|
export const POST_ANSWER_FAILURE = '@@answer/POST_FAILURE';
|
|
7
7
|
export const postAnswer = async (dispatch, getState, { services }) => {
|
|
8
8
|
const state = getState();
|
|
9
|
-
const token = get('data
|
|
10
|
-
const answer = get('ui
|
|
9
|
+
const token = get(['data', 'token'], state);
|
|
10
|
+
const answer = get(['ui', 'answers'], state);
|
|
11
11
|
const progression = state.data.progression;
|
|
12
12
|
if (!progression)
|
|
13
13
|
throw new Error('cannot answer question of inexisting progression');
|
|
14
14
|
const action = buildTask({
|
|
15
15
|
types: [POST_ANSWER_REQUEST, POST_ANSWER_SUCCESS, POST_ANSWER_FAILURE],
|
|
16
|
-
task: () =>
|
|
17
|
-
return services.postAnswer(progression, token, answer);
|
|
18
|
-
}
|
|
16
|
+
task: () => services.postAnswer(progression, token, answer)
|
|
19
17
|
});
|
|
20
18
|
const response = await dispatch(action);
|
|
21
19
|
if (response.type === POST_ANSWER_SUCCESS) {
|
|
@@ -6,12 +6,10 @@ export const POST_PROGRESSION_SUCCESS = '@@progression/POST_SUCCESS';
|
|
|
6
6
|
export const POST_PROGRESSION_FAILURE = '@@progression/POST_FAILURE';
|
|
7
7
|
export const postProgression = (skillRef) => async (dispatch, getState, { services }) => {
|
|
8
8
|
const state = getState();
|
|
9
|
-
const token = get('data
|
|
9
|
+
const token = get(['data', 'token'], state);
|
|
10
10
|
const action = buildTask({
|
|
11
11
|
types: [POST_PROGRESSION_REQUEST, POST_PROGRESSION_SUCCESS, POST_PROGRESSION_FAILURE],
|
|
12
|
-
task: () =>
|
|
13
|
-
return services.postProgression(skillRef, token);
|
|
14
|
-
}
|
|
12
|
+
task: () => services.postProgression(skillRef, token)
|
|
15
13
|
});
|
|
16
14
|
const response = await dispatch(action);
|
|
17
15
|
if (response.type === POST_PROGRESSION_SUCCESS) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import test from 'ava';
|
|
2
|
+
import { getChoicesCorrection, postAnswerResponses, services as mockedServices } from '../../../test/util/services.mock';
|
|
3
|
+
import { createTestStore } from '../../test/create-test-store';
|
|
4
|
+
import { CORRECTION_FETCH_FAILURE, CORRECTION_FETCH_REQUEST, CORRECTION_FETCH_SUCCESS, fetchCorrection } from '../fetch-correction';
|
|
5
|
+
import { freeTextSlide } from '../../../views/slides/test/fixtures/free-text';
|
|
6
|
+
import { qcmSlide } from '../../../views/slides/test/fixtures/qcm';
|
|
7
|
+
const progression = postAnswerResponses[freeTextSlide.universalRef];
|
|
8
|
+
const skillRef = '_skill-ref';
|
|
9
|
+
const answer = ['Lister vos tâches pour vous libérer l’esprit', 'Vous isoler dans un lieu calme'];
|
|
10
|
+
const initialState = {
|
|
11
|
+
data: {
|
|
12
|
+
progression,
|
|
13
|
+
slides: {
|
|
14
|
+
[freeTextSlide.universalRef]: freeTextSlide,
|
|
15
|
+
[qcmSlide.universalRef]: qcmSlide
|
|
16
|
+
},
|
|
17
|
+
skills: [{ skillRef, custom: false, name: skillRef, slidesToReview: 5 }],
|
|
18
|
+
token: '1234'
|
|
19
|
+
},
|
|
20
|
+
ui: {
|
|
21
|
+
currentSlideRef: freeTextSlide._id,
|
|
22
|
+
navigation: ['skills', 'slides'],
|
|
23
|
+
answers: answer,
|
|
24
|
+
slide: {
|
|
25
|
+
validateButton: false
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
test('should dispatch CORRECTION_FETCH_SUCCESS actions when fetchCorrection returns a correction object', async (t) => {
|
|
30
|
+
t.plan(6);
|
|
31
|
+
const services = {
|
|
32
|
+
...mockedServices,
|
|
33
|
+
fetchCorrection: (slideRef, token, progressionId, _answer) => {
|
|
34
|
+
t.is(slideRef, freeTextSlide.universalRef);
|
|
35
|
+
t.is(token, '1234');
|
|
36
|
+
t.is(progression._id, progressionId);
|
|
37
|
+
t.is(_answer, answer);
|
|
38
|
+
return Promise.resolve(getChoicesCorrection(slideRef));
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
const expectedActions = [
|
|
42
|
+
{ type: CORRECTION_FETCH_REQUEST },
|
|
43
|
+
{
|
|
44
|
+
type: CORRECTION_FETCH_SUCCESS,
|
|
45
|
+
payload: getChoicesCorrection(freeTextSlide.universalRef)
|
|
46
|
+
}
|
|
47
|
+
];
|
|
48
|
+
const { dispatch } = createTestStore(t, initialState, services, expectedActions);
|
|
49
|
+
await dispatch(fetchCorrection);
|
|
50
|
+
});
|
|
51
|
+
test('should dispatch CORRECTION_FETCH_FAILURE action when fetchCorrection fails', async (t) => {
|
|
52
|
+
t.plan(6);
|
|
53
|
+
const services = {
|
|
54
|
+
...mockedServices,
|
|
55
|
+
fetchCorrection: (slideRef, token, progressionId, _answer) => {
|
|
56
|
+
t.is(slideRef, freeTextSlide.universalRef);
|
|
57
|
+
t.is(token, '1234');
|
|
58
|
+
t.is(progression._id, progressionId);
|
|
59
|
+
t.is(_answer, answer);
|
|
60
|
+
return Promise.reject(new Error('unexpected'));
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
const expectedActions = [
|
|
64
|
+
{ type: CORRECTION_FETCH_REQUEST },
|
|
65
|
+
{
|
|
66
|
+
type: CORRECTION_FETCH_FAILURE,
|
|
67
|
+
payload: new Error('unexpected'),
|
|
68
|
+
error: true
|
|
69
|
+
}
|
|
70
|
+
];
|
|
71
|
+
const { dispatch } = createTestStore(t, initialState, services, expectedActions);
|
|
72
|
+
await dispatch(fetchCorrection);
|
|
73
|
+
});
|
|
@@ -18,7 +18,8 @@ const initialState = {
|
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
};
|
|
21
|
-
test('should dispatch SKILLS_FETCH_SUCCESS actions when fetchSkills
|
|
21
|
+
test('should dispatch SKILLS_FETCH_SUCCESS actions when fetchSkills returns a list of skills', async (t) => {
|
|
22
|
+
t.plan(3);
|
|
22
23
|
const services = {
|
|
23
24
|
...mockedServices,
|
|
24
25
|
fetchSkills: token => {
|
|
@@ -37,6 +38,7 @@ test('should dispatch SKILLS_FETCH_SUCCESS actions when fetchSkills return a lis
|
|
|
37
38
|
await dispatch(fetchSkills);
|
|
38
39
|
});
|
|
39
40
|
test('should dispatch SKILLS_FETCH_FAILURE action when fetchSkills fails', async (t) => {
|
|
41
|
+
t.plan(3);
|
|
40
42
|
const services = {
|
|
41
43
|
...mockedServices,
|
|
42
44
|
fetchSkills: token => {
|
|
@@ -21,6 +21,7 @@ const initialState = {
|
|
|
21
21
|
}
|
|
22
22
|
};
|
|
23
23
|
test('should dispatch FETCH_SUCCESS and SET_CURRENT_SLIDE actions when fetchSlide return a slide', async (t) => {
|
|
24
|
+
t.plan(5);
|
|
24
25
|
const services = {
|
|
25
26
|
...mockedServices,
|
|
26
27
|
fetchSlide: (slideRef, token) => {
|
|
@@ -42,6 +43,7 @@ test('should dispatch FETCH_SUCCESS and SET_CURRENT_SLIDE actions when fetchSlid
|
|
|
42
43
|
await dispatch(fetchSlide('sli_VJYjJnJhg'));
|
|
43
44
|
});
|
|
44
45
|
test('should dispatch SLIDE_FETCH_FAILURE action when fetchSlide fails', async (t) => {
|
|
46
|
+
t.plan(4);
|
|
45
47
|
const services = {
|
|
46
48
|
...mockedServices,
|
|
47
49
|
fetchSlide: (slideRef, token) => {
|
|
@@ -21,7 +21,7 @@ const initialState = {
|
|
|
21
21
|
allAnswers: [],
|
|
22
22
|
isCorrect: true,
|
|
23
23
|
nextContent: {
|
|
24
|
-
ref: freeTextSlide.
|
|
24
|
+
ref: freeTextSlide._id,
|
|
25
25
|
type: 'slide'
|
|
26
26
|
},
|
|
27
27
|
pendingSlides: [],
|
|
@@ -33,13 +33,13 @@ const initialState = {
|
|
|
33
33
|
}
|
|
34
34
|
},
|
|
35
35
|
slides: {
|
|
36
|
-
[freeTextSlide.
|
|
36
|
+
[freeTextSlide._id]: freeTextSlide
|
|
37
37
|
},
|
|
38
38
|
skills: [{ skillRef, custom: false, name: skillRef, slidesToReview: 5 }],
|
|
39
39
|
token: '1234'
|
|
40
40
|
},
|
|
41
41
|
ui: {
|
|
42
|
-
currentSlideRef: freeTextSlide.
|
|
42
|
+
currentSlideRef: freeTextSlide._id,
|
|
43
43
|
navigation: ['skills', 'slides'],
|
|
44
44
|
answers: answer,
|
|
45
45
|
slide: {
|
|
@@ -48,16 +48,17 @@ const initialState = {
|
|
|
48
48
|
}
|
|
49
49
|
};
|
|
50
50
|
test('should dispatch POST_ANSWER_REQUEST, then POST_ANSWER_SUCCESS when the updated progression is returned', async (t) => {
|
|
51
|
+
t.plan(4);
|
|
51
52
|
const expectedActions = [
|
|
52
53
|
{ type: POST_ANSWER_REQUEST },
|
|
53
54
|
{
|
|
54
55
|
type: POST_ANSWER_SUCCESS,
|
|
55
|
-
payload: postAnswerResponses[freeTextSlide.
|
|
56
|
+
payload: postAnswerResponses[freeTextSlide._id]
|
|
56
57
|
},
|
|
57
|
-
{ type: SLIDE_FETCH_REQUEST, meta: { slideRef: qcmGraphicSlide.
|
|
58
|
+
{ type: SLIDE_FETCH_REQUEST, meta: { slideRef: qcmGraphicSlide._id } },
|
|
58
59
|
{
|
|
59
60
|
type: SLIDE_FETCH_SUCCESS,
|
|
60
|
-
meta: { slideRef: qcmGraphicSlide.
|
|
61
|
+
meta: { slideRef: qcmGraphicSlide._id },
|
|
61
62
|
payload: qcmGraphicSlide
|
|
62
63
|
},
|
|
63
64
|
{ type: SET_CURRENT_SLIDE, payload: qcmGraphicSlide }
|
|
@@ -66,6 +67,7 @@ test('should dispatch POST_ANSWER_REQUEST, then POST_ANSWER_SUCCESS when the upd
|
|
|
66
67
|
await dispatch(postAnswer);
|
|
67
68
|
});
|
|
68
69
|
test('should dispatch POST_ANSWER_REQUEST, then POST_ANSWER_FAILURE on error', async (t) => {
|
|
70
|
+
t.plan(3);
|
|
69
71
|
const expectedActions = [
|
|
70
72
|
{ type: POST_ANSWER_REQUEST },
|
|
71
73
|
{
|
|
@@ -76,7 +78,10 @@ test('should dispatch POST_ANSWER_REQUEST, then POST_ANSWER_FAILURE on error', a
|
|
|
76
78
|
];
|
|
77
79
|
const { dispatch } = createTestStore(t, initialState, {
|
|
78
80
|
...services,
|
|
79
|
-
postAnswer: () =>
|
|
81
|
+
postAnswer: () => {
|
|
82
|
+
t.pass();
|
|
83
|
+
return Promise.reject(new Error('unexpected'));
|
|
84
|
+
}
|
|
80
85
|
}, expectedActions);
|
|
81
86
|
await dispatch(postAnswer);
|
|
82
87
|
});
|
|
@@ -21,7 +21,8 @@ const initialState = {
|
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
};
|
|
24
|
-
test('should dispatch POST_PROGRESSION_SUCCESS and SLIDE_FETCH_REQUEST actions when postProgression
|
|
24
|
+
test('should dispatch POST_PROGRESSION_SUCCESS and SLIDE_FETCH_REQUEST actions when postProgression returns a progression', async (t) => {
|
|
25
|
+
t.plan(9);
|
|
25
26
|
const progression = {
|
|
26
27
|
_id: '62b1d1087aa12f00253f40ee',
|
|
27
28
|
content: {
|
|
@@ -84,6 +85,7 @@ test('should dispatch POST_PROGRESSION_SUCCESS and SLIDE_FETCH_REQUEST actions w
|
|
|
84
85
|
await dispatch(postProgression('skill_12345'));
|
|
85
86
|
});
|
|
86
87
|
test('should dispatch POST_PROGRESSION_FAILURE action when postProgression fails', async (t) => {
|
|
88
|
+
t.plan(4);
|
|
87
89
|
const services = {
|
|
88
90
|
...mockedServices,
|
|
89
91
|
postProgression: (skillRef, token) => {
|
|
@@ -50,7 +50,7 @@ const initialState = {
|
|
|
50
50
|
}
|
|
51
51
|
};
|
|
52
52
|
const buildInitialState = (state, question) => {
|
|
53
|
-
return pipe(set(['data', 'progression', 'state', 'nextContent', 'ref'], question.
|
|
53
|
+
return pipe(set(['data', 'progression', 'state', 'nextContent', 'ref'], question._id), set(['data', 'slides', question._id], question), set(['ui', 'currentSlideRef'], question._id))(state);
|
|
54
54
|
};
|
|
55
55
|
test('should dispatch EDIT_BASIC action when editAnswer is called', async (t) => {
|
|
56
56
|
const state = buildInitialState(initialState, freeTextSlide);
|
|
@@ -7,12 +7,12 @@ export declare type DataState = {
|
|
|
7
7
|
progression: ProgressionState;
|
|
8
8
|
skills: SkillsState;
|
|
9
9
|
slides: SlidesState;
|
|
10
|
-
token
|
|
10
|
+
token: TokenState;
|
|
11
11
|
};
|
|
12
12
|
declare const _default: import("redux").Reducer<import("redux").CombinedState<{
|
|
13
13
|
progression: ProgressionState;
|
|
14
14
|
skills: SkillsState;
|
|
15
15
|
slides: SlidesState;
|
|
16
|
-
token:
|
|
16
|
+
token: string;
|
|
17
17
|
}>, 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>;
|
|
18
18
|
export default _default;
|
|
@@ -6,11 +6,11 @@ const reducer = (state = initialState, action) => {
|
|
|
6
6
|
switch (action.type) {
|
|
7
7
|
case SLIDE_FETCH_REQUEST: {
|
|
8
8
|
const { meta } = action;
|
|
9
|
-
return set(meta.slideRef, null, state);
|
|
9
|
+
return set([meta.slideRef], null, state);
|
|
10
10
|
}
|
|
11
11
|
case SLIDE_FETCH_SUCCESS: {
|
|
12
12
|
const slide = action.payload;
|
|
13
|
-
return set(slide.
|
|
13
|
+
return set([slide._id], slide, state);
|
|
14
14
|
}
|
|
15
15
|
default:
|
|
16
16
|
return state;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import test from 'ava';
|
|
2
2
|
import reducer from '../token';
|
|
3
3
|
import { STORE_TOKEN } from '../../../actions/data/token';
|
|
4
|
-
test('should have
|
|
4
|
+
test('should have initial value', t => {
|
|
5
5
|
const state = reducer(undefined, {});
|
|
6
|
-
t.is(state,
|
|
6
|
+
t.is(state, '');
|
|
7
7
|
});
|
|
8
8
|
test('should set the value of STORE_TOKEN action', t => {
|
|
9
|
-
const state = reducer(
|
|
9
|
+
const state = reducer('', { type: STORE_TOKEN, payload: 'token' });
|
|
10
10
|
t.is(state, 'token');
|
|
11
11
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { StoreToken } from '../../actions/data/token';
|
|
2
|
-
export declare type TokenState = string
|
|
3
|
-
declare const reducer: (state:
|
|
2
|
+
export declare type TokenState = string;
|
|
3
|
+
declare const reducer: (state: string | undefined, action: StoreToken) => TokenState;
|
|
4
4
|
export default reducer;
|
package/es/reducers/index.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ declare const _default: import("redux").Reducer<import("redux").CombinedState<{
|
|
|
9
9
|
progression: import("./data/progression").ProgressionState;
|
|
10
10
|
skills: import("./data/skills").SkillsState;
|
|
11
11
|
slides: import("./data/slides").SlidesState;
|
|
12
|
-
token:
|
|
12
|
+
token: string;
|
|
13
13
|
}>;
|
|
14
14
|
ui: import("redux").CombinedState<{
|
|
15
15
|
currentSlideRef: string;
|
|
@@ -3,7 +3,7 @@ import decode from 'jwt-decode';
|
|
|
3
3
|
import { toJSON } from './tools/fetch-responses';
|
|
4
4
|
export const fetchSlide = async (slideRef, token) => {
|
|
5
5
|
const { host } = decode(token);
|
|
6
|
-
const response = await crossFetch(`${host}/api/
|
|
6
|
+
const response = await crossFetch(`${host}/api/v1/slides/${slideRef}/parentContentTitle`, {
|
|
7
7
|
headers: { authorization: token }
|
|
8
8
|
});
|
|
9
9
|
return toJSON(response);
|
|
@@ -3,14 +3,14 @@ import decode from 'jwt-decode';
|
|
|
3
3
|
import { toJSON } from './tools/fetch-responses';
|
|
4
4
|
export const postAnswer = async (progression, token, answer) => {
|
|
5
5
|
const progressionId = progression._id;
|
|
6
|
-
const
|
|
6
|
+
const slideRef = progression.state.nextContent.ref;
|
|
7
7
|
const { host } = decode(token);
|
|
8
8
|
const response = await crossFetch(`${host}/api/v2/progressions/${progressionId}/answers`, {
|
|
9
9
|
method: 'post',
|
|
10
|
-
headers: { authorization: token },
|
|
10
|
+
headers: { authorization: token, 'content-type': 'application/json' },
|
|
11
11
|
body: JSON.stringify({
|
|
12
12
|
content: {
|
|
13
|
-
ref:
|
|
13
|
+
ref: slideRef,
|
|
14
14
|
type: 'slide'
|
|
15
15
|
},
|
|
16
16
|
answer
|
|
@@ -5,11 +5,11 @@ export const postProgression = async (skillRef, token) => {
|
|
|
5
5
|
const { host } = decode(token);
|
|
6
6
|
const response = await crossFetch(`${host}/api/v2/progressions`, {
|
|
7
7
|
method: 'post',
|
|
8
|
-
headers: { authorization: token },
|
|
8
|
+
headers: { authorization: token, 'content-type': 'application/json' },
|
|
9
9
|
body: JSON.stringify({
|
|
10
10
|
content: {
|
|
11
11
|
ref: skillRef,
|
|
12
|
-
type: '
|
|
12
|
+
type: 'skill'
|
|
13
13
|
},
|
|
14
14
|
engine: {
|
|
15
15
|
ref: 'review',
|
|
@@ -4,7 +4,7 @@ import { qcmDragSlide } from '../../views/slides/test/fixtures/qcm-drag';
|
|
|
4
4
|
import { fetchSlide } from '../fetch-slide';
|
|
5
5
|
test.before(() => {
|
|
6
6
|
nock('http://localhost:3000')
|
|
7
|
-
.get('/api/
|
|
7
|
+
.get('/api/v1/slides/sli_123546/parentContentTitle')
|
|
8
8
|
.reply(200, qcmDragSlide);
|
|
9
9
|
});
|
|
10
10
|
test.after(() => {
|
|
@@ -63,7 +63,15 @@ const result = {
|
|
|
63
63
|
};
|
|
64
64
|
test.before(() => {
|
|
65
65
|
const moocApi = nock('http://localhost:3000');
|
|
66
|
-
moocApi
|
|
66
|
+
moocApi
|
|
67
|
+
.post('/api/v2/progressions/123456123456/answers', {
|
|
68
|
+
content: {
|
|
69
|
+
ref: 'sli_NkvrWPFF2',
|
|
70
|
+
type: 'slide'
|
|
71
|
+
},
|
|
72
|
+
answer
|
|
73
|
+
})
|
|
74
|
+
.reply(200, result);
|
|
67
75
|
});
|
|
68
76
|
test.after(() => {
|
|
69
77
|
nock.cleanAll();
|
|
@@ -28,7 +28,18 @@ const result = {
|
|
|
28
28
|
};
|
|
29
29
|
test.before(() => {
|
|
30
30
|
const moocApi = nock('http://localhost:3000');
|
|
31
|
-
moocApi
|
|
31
|
+
moocApi
|
|
32
|
+
.post('/api/v2/progressions', {
|
|
33
|
+
content: {
|
|
34
|
+
ref: '_skill-ref',
|
|
35
|
+
type: 'skill'
|
|
36
|
+
},
|
|
37
|
+
engine: {
|
|
38
|
+
ref: 'review',
|
|
39
|
+
version: '1'
|
|
40
|
+
}
|
|
41
|
+
})
|
|
42
|
+
.reply(200, result);
|
|
32
43
|
});
|
|
33
44
|
test.after(() => {
|
|
34
45
|
nock.cleanAll();
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { ProgressionFromAPI, Services } from '../../types/common';
|
|
1
|
+
import { CorrectionFromAPI, ProgressionFromAPI, Services } from '../../types/common';
|
|
2
2
|
export declare const postProgressionResponse: ProgressionFromAPI;
|
|
3
3
|
export declare const postAnswerResponses: Record<string, ProgressionFromAPI>;
|
|
4
4
|
export declare const progressionSlideWithPendingSlide: ProgressionFromAPI;
|
|
5
|
+
export declare const getChoicesCorrection: (ref: string, wrongChoice?: boolean) => CorrectionFromAPI;
|
|
5
6
|
export declare const services: Services;
|
|
@@ -327,7 +327,7 @@ export const progressionSlideWithPendingSlide = {
|
|
|
327
327
|
stars: 32
|
|
328
328
|
}
|
|
329
329
|
};
|
|
330
|
-
const getChoicesCorrection = (ref, wrongChoice = false) => {
|
|
330
|
+
export const getChoicesCorrection = (ref, wrongChoice = false) => {
|
|
331
331
|
switch (ref) {
|
|
332
332
|
case qcmSlide.universalRef: {
|
|
333
333
|
const correctAnswer = [get('question.content.choices.0.label', qcmSlide)];
|
|
@@ -393,7 +393,7 @@ const getChoicesCorrection = (ref, wrongChoice = false) => {
|
|
|
393
393
|
};
|
|
394
394
|
export const services = {
|
|
395
395
|
fetchSkills: () => Promise.resolve(fetchSkillsResponse),
|
|
396
|
-
fetchSlide: ref => Promise.resolve({ ...getSlideFixture(ref), universalRef: ref,
|
|
396
|
+
fetchSlide: ref => Promise.resolve({ ...getSlideFixture(ref), universalRef: ref, _id: ref }),
|
|
397
397
|
postProgression: () => Promise.resolve(postProgressionResponse),
|
|
398
398
|
postAnswer: progression => {
|
|
399
399
|
const currentSlide = progression.state.nextContent.ref;
|
package/es/types/common.d.ts
CHANGED
|
@@ -62,13 +62,13 @@ export declare type TemplateQuestion = Omit<BaseQuestion, 'content'> & {
|
|
|
62
62
|
};
|
|
63
63
|
export declare type Question = QcmQuestion | QcmGraphicQuestion | QcmDragQuestion | BasicQuestion | SliderQuestion | TemplateQuestion;
|
|
64
64
|
export declare type SlideFromAPI = {
|
|
65
|
+
_id: string;
|
|
65
66
|
question: Question;
|
|
66
67
|
klf: string;
|
|
67
68
|
universalRef: string;
|
|
68
69
|
tips?: string;
|
|
69
70
|
clue?: string;
|
|
70
71
|
hasClue?: boolean;
|
|
71
|
-
id: string;
|
|
72
72
|
parentContentTitle: {
|
|
73
73
|
title: string;
|
|
74
74
|
type: 'chapter' | 'course';
|
|
@@ -18,7 +18,7 @@ export const freeTextSlide = {
|
|
|
18
18
|
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.',
|
|
19
19
|
tips: 'According to Insee, Paris salaries are 20-25% higher compared with those of the provinces in 2015.',
|
|
20
20
|
universalRef: 'sli_VJYjJnJhg',
|
|
21
|
-
|
|
21
|
+
_id: 'sli_VJYjJnJhg',
|
|
22
22
|
parentContentTitle: {
|
|
23
23
|
title: 'Developing the review app',
|
|
24
24
|
type: 'course'
|
|
@@ -65,7 +65,7 @@ export const qcmDragSlide = {
|
|
|
65
65
|
klf: "Le burn out s'installe en quatre étapes : tout d'abord, l'implication (investissement émotionnel et/ou affectif, sacrifice de sa vie privée) ; en second, la stagnation (premières déceptions, signes de fatigue) ; ensuite, la frustration (efforts non reconnus) ; et enfin, la démoralisation (problèmes de concentration, sentiment d'inutilité, désespoir).",
|
|
66
66
|
tips: "Encadré par la loi, l'entretien professionnel a pour but d'aider le collaborateur à verbaliser ses difficultés et à construire son projet professionnel.",
|
|
67
67
|
universalRef: 'sli_4yGBq-mCg',
|
|
68
|
-
|
|
68
|
+
_id: 'sli_4yGBq-mCg',
|
|
69
69
|
parentContentTitle: {
|
|
70
70
|
title: 'Using redux',
|
|
71
71
|
type: 'chapter'
|
|
@@ -57,7 +57,7 @@ export const qcmGraphicSlide = {
|
|
|
57
57
|
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.",
|
|
58
58
|
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.",
|
|
59
59
|
universalRef: 'sli_VkSQroQnx',
|
|
60
|
-
|
|
60
|
+
_id: 'sli_VkSQroQnx',
|
|
61
61
|
parentContentTitle: {
|
|
62
62
|
title: 'Developing the review app',
|
|
63
63
|
type: 'course'
|
|
@@ -66,7 +66,7 @@ export const qcmSlide = {
|
|
|
66
66
|
tips: 'En 2021, le média en ligne Numerama a créé un NFT vendu aux enchères sur OpenSea. Sur cette plateforme, il est obligatoire de mettre un prix de réserve, autrement dit un prix minimum au-dessous duquel la vente ne sera pas automatiquement acceptée. Sur OpenSea il ne peut être inférieur à 1 ETH. Si le prix de réserve est atteint, pas de problème, les "gas fees" (les frais de gaz) sont couverts par OpenSea. Mais, si ce n’est pas le cas, c’est au vendeur de s’en acquitter. <br/>Le NFT en question est parti à 0,021 ETH, soit 40€ au cours de l\'époque, un prix inférieur au prix de réserve. Numerama a dû acquitter des frais de gaz, et payer 190 €. <br/>Avec les NFT, on ne gagne pas à tous les coups.',
|
|
67
67
|
universalRef: 'sli_N1XACJobn',
|
|
68
68
|
hasClue: true,
|
|
69
|
-
|
|
69
|
+
_id: 'sli_N1XACJobn',
|
|
70
70
|
parentContentTitle: {
|
|
71
71
|
title: 'Developing the review app',
|
|
72
72
|
type: 'course'
|
|
@@ -13,7 +13,7 @@ export const sliderSlide = {
|
|
|
13
13
|
klf: 'Dans le cadre d’un projet local, la communauté de communes du Thouarsais, dans le Poitou (ouest de la France), a développé un parc diversifié d’énergies renouvelables : éolien, biomasse, solaire… En sept ans seulement, entre 2007 et 2014, la part d’énergies renouvelables est passée de zéro à un tiers !',
|
|
14
14
|
tips: 'En 2014, le Thouarsais a reçu la médaille de bronze du championnat européen des énergies renouvelables.',
|
|
15
15
|
universalRef: 'sli_VkAzsCLKb',
|
|
16
|
-
|
|
16
|
+
_id: 'sli_VkAzsCLKb',
|
|
17
17
|
parentContentTitle: {
|
|
18
18
|
title: 'Developing the review app',
|
|
19
19
|
type: 'course'
|
|
@@ -79,7 +79,7 @@ export const templateSlide = {
|
|
|
79
79
|
klf: 'L’apprenant peut aussi évaluer sa performance grâce à un classement disponible sur la vue leaderboard. Elle compare sa position par rapport à celle des autres apprenants de la plateforme.',
|
|
80
80
|
tips: "La position d'un apprenant peut être aussi consultée depuis le header ou en-tête de la page. Elle se met à jour à chaque fois qu'un apprenant obtient des étoiles.",
|
|
81
81
|
universalRef: 'sli_N13-hG3kX',
|
|
82
|
-
|
|
82
|
+
_id: 'sli_N13-hG3kX',
|
|
83
83
|
parentContentTitle: {
|
|
84
84
|
title: 'Developing the review app',
|
|
85
85
|
type: 'course'
|
|
@@ -16,7 +16,7 @@ const progression = {
|
|
|
16
16
|
allAnswers: [],
|
|
17
17
|
isCorrect: true,
|
|
18
18
|
nextContent: {
|
|
19
|
-
ref: templateSlide.
|
|
19
|
+
ref: templateSlide._id,
|
|
20
20
|
type: 'slide'
|
|
21
21
|
},
|
|
22
22
|
pendingSlides: [],
|
|
@@ -31,13 +31,13 @@ const initialState = {
|
|
|
31
31
|
data: {
|
|
32
32
|
progression,
|
|
33
33
|
slides: {
|
|
34
|
-
[templateSlide.
|
|
34
|
+
[templateSlide._id]: templateSlide
|
|
35
35
|
},
|
|
36
36
|
skills: [],
|
|
37
37
|
token: '1234'
|
|
38
38
|
},
|
|
39
39
|
ui: {
|
|
40
|
-
currentSlideRef: templateSlide.
|
|
40
|
+
currentSlideRef: templateSlide._id,
|
|
41
41
|
navigation: ['skills', 'slides'],
|
|
42
42
|
answers: [],
|
|
43
43
|
slide: {
|