UNPKG

@coorpacademy/progression-engine

Version:

387 lines 8.84 kB
import test from 'ava'; import selectRule, { DEFAULT_SOURCE } from '../select-rule'; const createState = nextContent => ({ nextContent, lives: 4, stars: 0, livesDisabled: true, isCorrect: true, slides: [], requestedClues: [], viewedResources: [], step: { current: 0 }, remainingLifeRequests: 0, allAnswers: [], hasViewedAResourceAtThisStep: false, variables: {}, pendingSlides: [] }); test('should return null if no rules match', t => { const state = createState({ type: 'slide', ref: '' }); const rule = selectRule([], state); t.is(rule, null); }); const source = { type: 'slide', ref: '1.A1.1' }; const destination = { type: 'slide', ref: '1.A1.2' }; const defaultState = { nextContent: source, lives: 2, stars: 0, livesDisabled: true, isCorrect: true, slides: [], requestedClues: [], viewedResources: [], step: { current: 0 }, variables: {}, remainingLifeRequests: 0, allAnswers: [], hasViewedAResourceAtThisStep: false, pendingSlides: [] }; const chapterRules = [{ source: destination, destination: source, instructions: [], conditions: [{ target: { scope: 'variable', field: 'lives' }, operator: 'EQUALS', values: [2] }], priority: 0, ref: '1' }, { source, destination, instructions: [], conditions: [{ target: { scope: 'variable', field: 'lives' }, operator: 'EQUALS', values: [2] }], priority: 2, ref: 'low_priority' }, { source, destination, instructions: [], conditions: [{ target: { scope: 'variable', field: 'lives' }, operator: 'EQUALS', values: [2] }], priority: 0, ref: 'high_priority' }, { source, destination, instructions: [], conditions: [{ target: { scope: 'variable', field: 'lives' }, operator: 'EQUALS', values: [2] }], priority: 1, ref: 'mid_priority' }, { source: DEFAULT_SOURCE, destination, instructions: [], conditions: [{ target: { scope: 'variable', field: 'lives' }, operator: 'EQUALS', values: [2] }], priority: 0, ref: '3' }]; test('should select right chapter from source and priority', t => { const state = defaultState; const actualChapterRule = selectRule(chapterRules, state) || {}; t.is(actualChapterRule.ref, 'high_priority'); }); test('should select chapterRule with empty source if state is null', t => { const rule = selectRule(chapterRules, null); t.is(rule && rule.ref, '3'); }); test('should return no chapterRule if none match', t => { const state = { ...defaultState, nextContent: { type: 'slide', ref: 'noop' } }; const actualChapterRule = selectRule(chapterRules, state); t.is(actualChapterRule, null); }); test("should select chapterRule with 'slide' scope", t => { const slideScopedRules = [{ source, destination, instructions: [], conditions: [{ target: { scope: 'slide', ref: '1.A1.1', field: 'answer' }, operator: 'EQUALS', values: [['otherValue']] }], priority: 0, ref: 'answerOtherValue' }, { source, destination, instructions: [], conditions: [{ target: { scope: 'slide', ref: '1.A1.1', field: 'answer' }, operator: 'EQUALS', values: [['foo']] }], priority: 0, ref: 'answer' }, { source, destination, instructions: [], conditions: [{ target: { scope: 'slide', ref: '1.A1.1', field: 'isCorrect' }, operator: 'EQUALS', values: [true] }], priority: 0, ref: 'isCorrect' }]; const answerState = { ...defaultState, allAnswers: [{ slideRef: '1.A1.1', answer: ['bar'], isCorrect: true }, { slideRef: '1.A1.1', answer: ['foo'], isCorrect: false }] }; const answerChapterRule = selectRule(slideScopedRules, answerState); t.is((answerChapterRule || {}).ref, 'answer', "Don't support 'slide' scoped target with 'answer' field"); const noAnswerState = { ...defaultState, allAnswers: [] }; const noAnswerChapterRule = selectRule(slideScopedRules, noAnswerState); t.is(noAnswerChapterRule, null, "Don't support 'slide' scoped target with 'answer' field"); const isCorrectState = { ...defaultState, allAnswers: [{ slideRef: '1.A1.1', answer: ['bar'], isCorrect: true }] }; const isCorrectChapterRule = selectRule(slideScopedRules, isCorrectState); t.is((isCorrectChapterRule || {}).ref, 'isCorrect', "Don't support 'slide' scoped target with 'isCorrect' field"); const noIsCorrectState = { ...defaultState, allAnswers: [{ slideRef: '1.A1.1', answer: ['bar'], isCorrect: false }] }; const noIsCorrectChapterRule = selectRule(slideScopedRules, noIsCorrectState); t.is(noIsCorrectChapterRule, null, "Don't support 'slide' scoped target with 'isCorrect' field"); }); test("should select chapterRule with 'variables' scope", t => { const slideScopedRules = [{ source, destination, instructions: [], conditions: [{ target: { scope: 'variable', field: 'foo' }, operator: 'EQUALS', values: [1] }], priority: 0, ref: 'lives' }, { source, destination, instructions: [], conditions: [{ target: { scope: 'variable', field: 'lives' }, operator: 'GTE', values: [42] }], priority: 0, ref: 'lives' }, { source, destination, instructions: [], conditions: [{ target: { scope: 'variable', field: 'stars' }, operator: 'LTE', values: [-1] }], priority: 0, ref: 'stars' }, { source, destination, instructions: [], conditions: [{ target: { scope: 'variable', field: 'custom' }, operator: 'BETWEEN', values: [41, 43] }], priority: 0, ref: 'custom' }]; const livesState = { ...defaultState, lives: 42 }; const livesChapterRule = selectRule(slideScopedRules, livesState); t.is((livesChapterRule || {}).ref, 'lives', "Don't support 'variable' scoped target with 'lives' field"); const noLivesState = defaultState; const noLivesChapterRule = selectRule(slideScopedRules, noLivesState); t.is(noLivesChapterRule, null, "Don't support 'variable' scoped target with 'lives' field"); const starsState = { ...defaultState, stars: -1 }; const starsChapterRule = selectRule(slideScopedRules, starsState); t.is((starsChapterRule || {}).ref, 'stars', "Don't support 'variable' scoped target with 'stars' field"); const noStarsState = defaultState; const noStarsChapterRule = selectRule(slideScopedRules, noStarsState); t.is(noStarsChapterRule, null, "Don't support 'variable' scoped target with 'stars' field"); const customState = { ...defaultState, variables: { custom: 42 } }; const customChapterRule = selectRule(slideScopedRules, customState); t.is((customChapterRule || {}).ref, 'custom', "Don't support 'variable' scoped target with custom field"); const nocustomState = defaultState; const nocustomChapterRule = selectRule(slideScopedRules, nocustomState); t.is(nocustomChapterRule, null, "Don't support 'variable' scoped target with custom field"); }); test("should select a rule with source.ref:'*'", t => { const value = 111; const baseRule = { source, destination, instructions: [], conditions: [{ target: { scope: 'variable', field: 'foo' }, operator: 'EQUALS', values: [value] }], ref: '1' }; const sameSourceLowPriority = { ...baseRule, priority: 1 }; const globalSourceHighPriority = { ...baseRule, source: { type: 'slide', ref: '*' }, priority: 0 }; const rules = [sameSourceLowPriority, globalSourceHighPriority]; const state = { ...defaultState, variables: { foo: value } }; const selectedRule = selectRule(rules, state); t.deepEqual(selectedRule, globalSourceHighPriority); }); test("should select a random rule with source.ref:'*'", t => { const value = 111; const baseRule = { source, destination, instructions: [], conditions: [{ target: { scope: 'variable', field: 'foo' }, operator: 'EQUALS', values: [value] }], ref: '1', priority: 1 }; const rules = [baseRule, baseRule, baseRule]; const state = { ...defaultState, variables: { foo: value } }; const selectedRule = selectRule(rules, state); t.deepEqual(selectedRule, baseRule); }); //# sourceMappingURL=select-rule.js.map