@coorpacademy/progression-engine
Version:
320 lines (319 loc) • 10.2 kB
JavaScript
"use strict";
var _filter2 = _interopRequireDefault(require("lodash/fp/filter"));
var _assign2 = _interopRequireDefault(require("lodash/fp/assign"));
var _pipe2 = _interopRequireDefault(require("lodash/fp/pipe"));
var _omit2 = _interopRequireDefault(require("lodash/fp/omit"));
var _ava = _interopRequireDefault(require("ava"));
var _config = require("../../config");
var _ = require("..");
var _slides = _interopRequireDefault(require("./fixtures/slides"));
var _getSlide = _interopRequireDefault(require("./helpers/get-slide"));
var _states = require("./fixtures/states");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const config = (0, _config.getConfig)({
ref: 'learner',
version: '1'
});
const availableContent = [{
ref: '1.A1',
slides: (0, _filter2.default)({
chapter_id: '1.A1'
}, _slides.default),
rules: null
}];
const merge = arr2 => arr => {
return arr.map((v, i) => {
return (0, _assign2.default)(v, arr2[i]);
});
};
const createPartialAction = state => ({
type: 'answer',
payload: {
answer: [],
content: state.nextContent,
godMode: false
}
});
(0, _ava.default)('should return the slide with the highest position if any slides have a position', t => {
const state = Object.freeze(_states.firstState);
const currentSlide = (0, _getSlide.default)(_slides.default, state.nextContent);
const prioritySlides = (0, _pipe2.default)((0, _filter2.default)({
chapter_id: '1.A1'
}), merge([{
position: 0
}, {
position: 0
}, {
position: 0
}, {
_id: 'highest_position',
position: 1
}, {
position: 0
}]))(_slides.default);
const _availableContent = [{
ref: '1.A1',
slides: prioritySlides,
rules: null
}];
const partialAction = {
type: 'answer',
payload: {
answer: [],
content: state.nextContent,
godMode: true
}
};
const result1 = (0, _.computeNextStepAfterAnswer)(config, state, _availableContent, currentSlide, partialAction);
if (!result1) {
throw new Error('action should not be falsy');
}
t.deepEqual(result1, {
type: 'answer',
payload: {
answer: [],
content: state.nextContent,
godMode: true,
nextContent: {
type: 'slide',
ref: 'highest_position'
},
instructions: null,
isCorrect: true
}
});
const stateWithAdditionalSlide = {
..._states.firstState,
slides: [..._states.firstState.slides, result1.payload.nextContent.ref]
};
const result2 = (0, _.computeNextStepAfterAnswer)(config, stateWithAdditionalSlide, _availableContent, currentSlide, partialAction);
if (!result2) {
throw new Error('action should not be falsy');
}
t.deepEqual((0, _omit2.default)(['payload.nextContent.ref'], result2), {
type: 'answer',
payload: {
answer: [],
content: state.nextContent,
godMode: true,
nextContent: {
type: 'slide'
},
instructions: null,
isCorrect: true
}
});
});
(0, _ava.default)('should return a new slide when user is still alive', t => {
const state = Object.freeze(_states.stateBeforeGettingNextContent);
const currentSlide = (0, _getSlide.default)(_slides.default, state.nextContent);
const partialAction = {
type: 'answer',
payload: {
answer: [],
content: state.nextContent,
godMode: true
}
};
const result = (0, _.computeNextStepAfterAnswer)(config, state, availableContent, currentSlide, partialAction);
if (!result) {
throw new Error('action should not be falsy');
}
t.deepEqual((0, _omit2.default)(['payload.nextContent.ref'], result), {
type: 'answer',
payload: {
answer: [],
content: state.nextContent,
godMode: true,
nextContent: {
type: 'slide'
},
instructions: null,
isCorrect: true
}
});
t.regex(result.payload.nextContent.ref, /^1\.A1\.[2-9]+$/);
});
(0, _ava.default)("should return the fail endpoint when user has no more lives and can't request more lives", t => {
const state = Object.freeze(_states.oneLifeLeftState);
const currentSlide = (0, _getSlide.default)(_slides.default, state.nextContent);
const partialAction = createPartialAction(state);
const result = (0, _.computeNextStepAfterAnswer)(config, state, availableContent, currentSlide, partialAction);
t.deepEqual(result, {
type: 'answer',
payload: {
answer: [],
content: state.nextContent,
godMode: false,
nextContent: {
ref: 'failExitNode',
type: 'failure'
},
instructions: null,
isCorrect: false
}
});
});
(0, _ava.default)('should return the extraLife when user has no more lives but can request lives', t => {
const state = Object.freeze({
..._states.oneLifeLeftState,
remainingLifeRequests: 1
});
const currentSlide = (0, _getSlide.default)(_slides.default, state.nextContent);
const partialAction = createPartialAction(state);
const result = (0, _.computeNextStepAfterAnswer)(config, state, availableContent, currentSlide, partialAction);
t.deepEqual(result, {
type: 'answer',
payload: {
answer: [],
content: state.nextContent,
godMode: false,
nextContent: {
ref: 'extraLife',
type: 'node'
},
instructions: null,
isCorrect: false
}
});
});
(0, _ava.default)('should return a new slide, when user has no more lives but lives are disabled', t => {
const state = Object.freeze(_states.oneLifeLeftState);
const currentSlide = (0, _getSlide.default)(_slides.default, state.nextContent);
const partialAction = createPartialAction(state);
const livesDisabledConfig = {
...config,
livesDisabled: true
};
const result = (0, _.computeNextStepAfterAnswer)(livesDisabledConfig, state, availableContent, currentSlide, partialAction);
if (!result) {
throw new Error('action should not be falsy');
}
t.deepEqual((0, _omit2.default)(['payload.nextContent.ref'], result), {
type: 'answer',
payload: {
answer: [],
content: state.nextContent,
godMode: false,
nextContent: {
type: 'slide'
},
instructions: null,
isCorrect: false
}
});
t.regex(result.payload.nextContent.ref, /^1\.A1\.[2-9]+$/, 'does not work when lives are disabled in engine config');
});
(0, _ava.default)('should return isCorrect=true when the answer is correct and godmode is false', t => {
const state = Object.freeze(_states.stateBeforeGettingNextContent);
const currentSlide = (0, _getSlide.default)(_slides.default, state.nextContent);
const partialAction = {
type: 'answer',
payload: {
answer: ['foo', 'bar'],
content: state.nextContent,
godMode: false
}
};
const result = (0, _.computeNextStepAfterAnswer)(config, state, availableContent, currentSlide, partialAction);
if (!result) {
throw new Error('action should not be falsy');
}
t.true(result.payload.isCorrect);
});
(0, _ava.default)('should return isCorrect=false when the answer is incorrect and godmode is false', t => {
const state = Object.freeze(_states.stateBeforeGettingNextContent);
const currentSlide = (0, _getSlide.default)(_slides.default, state.nextContent);
const partialAction = {
type: 'answer',
payload: {
answer: ['this is not the answer'],
content: state.nextContent,
godMode: false
}
};
const result = (0, _.computeNextStepAfterAnswer)(config, state, availableContent, currentSlide, partialAction);
if (!result) {
throw new Error('action should not be falsy');
}
t.false(result.payload.isCorrect);
});
(0, _ava.default)('should return null if there is no available content', t => {
const state = Object.freeze(_states.stateBeforeGettingNextContent);
const currentSlide = (0, _getSlide.default)(_slides.default, state.nextContent);
const partialAction = createPartialAction(state);
t.is((0, _.computeNextStepAfterAnswer)(config, state, [], currentSlide, partialAction), null);
});
(0, _ava.default)('should return extralife endpoint when user has failed to answer, has no more lives but can request lives and has answered `config.slidesToComplete` number of slides', t => {
const state = Object.freeze({
..._states.stateBeforeGettingNextContent,
slides: ['1.A1.1', '1.A1.2', '1.A1.3'],
nextContent: {
type: 'slide',
ref: '1.A1.4'
},
remainingLifeRequests: 1,
lives: 1
});
const currentSlide = (0, _getSlide.default)(_slides.default, state.nextContent);
const partialAction = {
type: 'answer',
payload: {
answer: [],
content: state.nextContent,
godMode: false
}
};
const result = (0, _.computeNextStepAfterAnswer)(config, state, availableContent, currentSlide, partialAction);
t.deepEqual(result, {
type: 'answer',
payload: {
answer: [],
content: state.nextContent,
godMode: false,
nextContent: {
ref: 'extraLife',
type: 'node'
},
instructions: null,
isCorrect: false
}
});
});
(0, _ava.default)("should return failure endpoint when user has failed to answer, has no more lives, can't request lives and has answered `config.slidesToComplete` number of slides", t => {
const state = Object.freeze({
..._states.stateBeforeGettingNextContent,
slides: ['1.A1.1', '1.A1.2', '1.A1.3'],
nextContent: {
type: 'slide',
ref: '1.A1.4'
},
remainingLifeRequests: 0,
lives: 1
});
const currentSlide = (0, _getSlide.default)(_slides.default, state.nextContent);
const partialAction = {
type: 'answer',
payload: {
answer: [],
content: state.nextContent,
godMode: false
}
};
const result = (0, _.computeNextStepAfterAnswer)(config, state, availableContent, currentSlide, partialAction);
t.deepEqual(result, {
type: 'answer',
payload: {
answer: [],
content: state.nextContent,
godMode: false,
nextContent: {
ref: 'failExitNode',
type: 'failure'
},
instructions: null,
isCorrect: false
}
});
});
//# sourceMappingURL=compute-next-step-after-answer.js.map