UNPKG

@coorpacademy/progression-engine

Version:

320 lines (319 loc) 10.2 kB
"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