"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));

var _immutable = require("immutable");

var _chai = require("chai");

var _constants = require("@instructure/quiz-common/lib/constants");

var _modifications = _interopRequireDefault(require("../modifications"));

describe('modifications reducer', function () {
  var sharedExamplesForType = function sharedExamplesForType(topLevelKey, actionType) {
    var _ref = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {},
        _ref$deep = _ref.deep,
        deep = _ref$deep === void 0 ? false : _ref$deep;

    var modForIdOne = function modForIdOne(mods) {
      return {
        type: actionType,
        payload: {
          id: '1',
          modifications: mods
        }
      };
    };

    it('can add a value for an attr', function () {
      var initialState = (0, _immutable.fromJS)((0, _defineProperty2.default)({}, topLevelKey, {}));
      var action = modForIdOne({
        foo: 'bar'
      });
      var nextStateItem = (0, _modifications.default)(initialState, action).getIn([topLevelKey, '1']);
      (0, _chai.expect)(nextStateItem.equals((0, _immutable.fromJS)({
        id: '1',
        foo: 'bar'
      }))).to.be.true();
    });
    it('can replace a value for an attr', function () {
      var initialState = (0, _immutable.fromJS)((0, _defineProperty2.default)({}, topLevelKey, {
        1: {
          id: '1',
          foo: 'foo'
        }
      }));
      var action = modForIdOne({
        foo: 'bar'
      });
      var nextStateItem = (0, _modifications.default)(initialState, action).getIn([topLevelKey, '1']);
      (0, _chai.expect)(nextStateItem.equals((0, _immutable.fromJS)({
        id: '1',
        foo: 'bar'
      }))).to.be.true();
    });
    it('replaces set values (rather than merging)', function () {
      var initialState = (0, _immutable.fromJS)((0, _defineProperty2.default)({}, topLevelKey, {
        1: {
          id: '1',
          foo: (0, _immutable.Set)(['1', '2'])
        }
      }));
      var action = modForIdOne({
        foo: (0, _immutable.Set)(['3'])
      });
      var nextStateItem = (0, _modifications.default)(initialState, action).getIn([topLevelKey, '1']);
      (0, _chai.expect)(nextStateItem.equals((0, _immutable.fromJS)({
        id: '1',
        foo: (0, _immutable.Set)(['3'])
      }))).to.be.true();
    });

    if (deep) {
      it('deep merges object values', function () {
        var initialState = (0, _immutable.fromJS)((0, _defineProperty2.default)({}, topLevelKey, {
          1: {
            id: '1',
            foo: {
              1: 'hey'
            }
          }
        }));
        var action = modForIdOne({
          foo: {
            2: 'ho'
          }
        });
        var nextStateItem = (0, _modifications.default)(initialState, action).getIn([topLevelKey, '1']);
        (0, _chai.expect)(nextStateItem.equals((0, _immutable.fromJS)({
          id: '1',
          foo: {
            1: 'hey',
            2: 'ho'
          }
        }))).to.be.true();
      });
    } else {
      it('replaces object values (rather than merging)', function () {
        var initialState = (0, _immutable.fromJS)((0, _defineProperty2.default)({}, topLevelKey, {
          1: {
            id: '1',
            foo: {
              1: 'hey'
            }
          }
        }));
        var action = modForIdOne({
          foo: {
            2: 'ho'
          }
        });
        var nextStateItem = (0, _modifications.default)(initialState, action).getIn([topLevelKey, '1']);
        (0, _chai.expect)(nextStateItem.equals((0, _immutable.fromJS)({
          id: '1',
          foo: {
            2: 'ho'
          }
        }))).to.be.true();
      });
    }
  };

  describe('quizzes', function () {
    sharedExamplesForType('quizzes', _constants.QUIZ_MODIFICATION);
  });
  describe('items', function () {
    sharedExamplesForType('items', _constants.ITEM_MODIFICATION);
  });
  describe('quizEntries', function () {
    sharedExamplesForType('quizEntries', _constants.QUIZ_ENTRIES_MODIFICATION, {
      deep: true
    });
  });
  describe('quizSessionResults', function () {
    sharedExamplesForType('quizSessionResults', _constants.QUIZ_SESSION_RESULT_MODIFICATION);
  });
  describe('sessionItemResults', function () {
    sharedExamplesForType('sessionItemResults', _constants.SESSION_ITEM_RESULTS_MODIFICATION);
  });
  describe('banks', function () {
    sharedExamplesForType('banks', _constants.BANK_MODIFICATION);
  });
  describe('create temporary bank', function () {
    var initialState = (0, _immutable.fromJS)({
      banks: {}
    });

    var createBankAction = function createBankAction() {
      var payload = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
      return {
        type: _constants.CREATE_TEMPORARY_BANK,
        payload: payload
      };
    };

    it('creates a bank', function () {
      var state = (0, _modifications.default)(initialState, createBankAction());
      var nextStateItem = state.getIn(['banks', _constants.TEMPORARY_BANK_ID]);
      (0, _chai.expect)(nextStateItem.equals((0, _immutable.fromJS)({
        id: _constants.TEMPORARY_BANK_ID,
        title: ''
      }))).to.be.true();
    });
    it('creates a bank with a specified locale', function () {
      var state = (0, _modifications.default)(initialState, createBankAction({
        language: 'en'
      }));
      var nextStateItem = state.getIn(['banks', _constants.TEMPORARY_BANK_ID]);
      var bank = {
        id: _constants.TEMPORARY_BANK_ID,
        title: '',
        language: 'en'
      };
      (0, _chai.expect)(nextStateItem.toJS()).to.deep.equal(bank);
    });
  });
  describe('create temporary stimulus', function () {
    var initialState = (0, _immutable.fromJS)({
      quizzes: {
        id: '1'
      },
      quizEntries: {},
      stimuli: {}
    });
    var position = '77';
    var createStimulusAction = {
      type: _constants.CREATE_TEMPORARY_STIMULUS,
      payload: {
        position: position,
        quizId: '1'
      }
    };
    var state = (0, _modifications.default)(initialState, createStimulusAction);
    it('associates the quiz and the temp quiz entry', function () {
      var nextStateItem = state.getIn(['quizzes', '1', 'quizEntries']);
      (0, _chai.expect)(nextStateItem.equals((0, _immutable.fromJS)([_constants.TEMPORARY_QUIZ_ENTRY_ID]))).to.be.true();
    });
    it('adds temporary quiz entry associated with temporary item', function () {
      var nextStateItem = state.getIn(['quizEntries', _constants.TEMPORARY_QUIZ_ENTRY_ID, 'entry']);
      (0, _chai.expect)(nextStateItem).to.equal(_constants.TEMPORARY_STIMULUS_ID);
    });
    context('adds temporary quiz entry with position 0.1', function () {
      it('works with quizzes entries already created', function () {
        var nextStateItem = state.getIn(['quizEntries', _constants.TEMPORARY_QUIZ_ENTRY_ID, 'position']);
        (0, _chai.expect)(nextStateItem).to.equal(position - 0.1);
      });
      it('works with no quizzes entries already created', function () {
        var initialState = (0, _immutable.fromJS)({
          quizzes: {
            id: '1'
          },
          quizEntries: {},
          items: {}
        });
        var position = 0;
        var createStimulusActionForNewStimulus = {
          type: _constants.CREATE_TEMPORARY_STIMULUS,
          payload: {
            position: position,
            quizId: '1'
          }
        };
        var state = (0, _modifications.default)(initialState, createStimulusActionForNewStimulus);
        var nextStateItem = state.getIn(['quizEntries', _constants.TEMPORARY_QUIZ_ENTRY_ID, 'position']);
        (0, _chai.expect)(nextStateItem).to.equal(0.9);
      });
    });
    it('adds the temporary stimulus with data', function () {
      var nextStateItem = state.getIn(['stimuli', _constants.TEMPORARY_STIMULUS_ID, 'stimulusType']);
      (0, _chai.expect)(nextStateItem).to.equal('text');
    });
  });
  describe('modify stimulus', function () {
    var initialState = (0, _immutable.fromJS)({
      stimuli: (0, _defineProperty2.default)({}, _constants.TEMPORARY_STIMULUS_ID, {
        id: _constants.TEMPORARY_STIMULUS_ID,
        title: 'hello'
      })
    });
    var modifyStimulusAction = {
      type: _constants.STIMULUS_MODIFICATION,
      payload: {
        stimulus: {
          id: _constants.TEMPORARY_STIMULUS_ID,
          title: 'world'
        }
      }
    };
    var state = (0, _modifications.default)(initialState, modifyStimulusAction);
    it('overwrites the old stimulus data with the new one', function () {
      var nextStateItem = state.getIn(['stimuli', _constants.TEMPORARY_STIMULUS_ID, 'title']);
      (0, _chai.expect)(nextStateItem).to.equal('world');
    });
  });
  describe('clear temporary stimulus', function () {
    var initialState = (0, _immutable.fromJS)({
      quizzes: {
        44: {
          id: '44',
          quizEntries: [_constants.TEMPORARY_QUIZ_ENTRY_ID]
        }
      },
      quizEntries: (0, _defineProperty2.default)({}, _constants.TEMPORARY_QUIZ_ENTRY_ID, {
        id: _constants.TEMPORARY_QUIZ_ENTRY_ID,
        entry: _constants.TEMPORARY_STIMULUS_ID,
        entryType: 'Stimulus',
        position: 0.9
      }),
      stimuli: (0, _defineProperty2.default)({}, _constants.TEMPORARY_STIMULUS_ID, {
        id: _constants.TEMPORARY_STIMULUS_ID,
        title: 'hello'
      })
    });
    var clearStimulusAction = {
      type: _constants.CLEAR_TEMPORARY_STIMULUS,
      payload: {
        quizId: '44'
      }
    };
    var state = (0, _modifications.default)(initialState, clearStimulusAction);
    it('removes the quiz modifications', function () {
      var nextStateItem = state.getIn(['quizzes', '44', 'quizEntries']);
      (0, _chai.expect)(nextStateItem).to.be.empty();
    });
    it('removes the temporary quiz entry', function () {
      (0, _chai.expect)(state.getIn(['quizEntries', _constants.TEMPORARY_QUIZ_ENTRY_ID])).to.not.exist();
    });
    it('removes the temporary stimulus', function () {
      var nextStateItem = state.get('stimuli');
      (0, _chai.expect)(nextStateItem.equals((0, _immutable.fromJS)({}))).to.be.true();
    });
  });
  describe('create temporary item', function () {
    var initialState = (0, _immutable.fromJS)({
      quizzes: {
        1: {
          id: '1'
        }
      },
      quizEntries: {},
      items: {}
    });
    var position = '77';
    var createItemAction = {
      type: _constants.CREATE_TEMPORARY_ITEM,
      payload: {
        interactionTypeData: {
          scoringData: 'someData',
          properties: {
            hasLabels: true
          }
        },
        position: position,
        quizId: '1',
        parentEntryId: '66'
      }
    };
    var state = (0, _modifications.default)(initialState, createItemAction);
    it('associates the quiz and the temp quiz entry', function () {
      var nextStateItem = state.getIn(['quizzes', '1', 'quizEntries']);
      (0, _chai.expect)(nextStateItem.equals((0, _immutable.fromJS)([_constants.TEMPORARY_QUIZ_ENTRY_ID]))).to.be.true();
    });
    it('adds temporary quiz entry associated with temporary item', function () {
      var nextStateItem = state.getIn(['quizEntries', _constants.TEMPORARY_QUIZ_ENTRY_ID, 'entry']);
      (0, _chai.expect)(nextStateItem).to.equal(_constants.TEMPORARY_ITEM_ID);
    });
    it('adds the temporary quiz entry with stimulus quiz entry id', function () {
      var nextStateItem = state.getIn(['quizEntries', _constants.TEMPORARY_QUIZ_ENTRY_ID, 'stimulusQuizEntryId']);
      (0, _chai.expect)(nextStateItem).to.equal('66');
    });
    context('adds temporary quiz entry with position 0.1', function () {
      it('works with quizzes entries already created', function () {
        var nextStateItem = state.getIn(['quizEntries', _constants.TEMPORARY_QUIZ_ENTRY_ID, 'position']);
        (0, _chai.expect)(nextStateItem).to.equal(position - 0.1);
      });
      it('works with no quizzes entries already created', function () {
        var initialState = (0, _immutable.fromJS)({
          quizzes: {
            id: '1'
          },
          quizEntries: {},
          items: {}
        });
        var position = 0;
        var createItemActionForNewItem = {
          type: _constants.CREATE_TEMPORARY_ITEM,
          payload: {
            interactionTypeData: {
              scoringData: 'someData',
              properties: {
                hasLabels: true
              }
            },
            position: position,
            quizId: '1'
          }
        };
        var state = (0, _modifications.default)(initialState, createItemActionForNewItem);
        var nextStateItem = state.getIn(['quizEntries', _constants.TEMPORARY_QUIZ_ENTRY_ID, 'position']);
        (0, _chai.expect)(nextStateItem).to.equal(0.9);
      });
    });
    it('adds the temporary item with data', function () {
      var nextStateItem = state.getIn(['items', _constants.TEMPORARY_ITEM_ID, 'scoringData']);
      (0, _chai.expect)(nextStateItem).to.equal('someData');
    });
    it('includes properties in item data', function () {
      var nextStateItem = state.getIn(['items', _constants.TEMPORARY_ITEM_ID, 'properties', 'hasLabels']);
      (0, _chai.expect)(nextStateItem).to.be.true();
    });
  });
  describe('create temporary bank item', function () {
    var initialState = (0, _immutable.fromJS)({
      banks: {
        1: {
          id: '1'
        }
      },
      bankEntries: {},
      items: {}
    });
    var createBankItemAction = {
      type: _constants.CREATE_TEMPORARY_BANK_ITEM,
      payload: {
        interactionTypeData: {
          scoringData: 'someData',
          properties: {
            hasLabels: true
          }
        },
        bankId: '1',
        bankEntryType: 'Item'
      }
    };
    var state = (0, _modifications.default)(initialState, createBankItemAction);
    it('associates the bank and the temp bank entry', function () {
      var newStateItem = state.getIn(['banks', '1', 'bankEntries']);
      (0, _chai.expect)(newStateItem.equals((0, _immutable.fromJS)([_constants.TEMPORARY_BANK_ENTRY_ID]))).to.be.true();
    });
    it('adds temporary bank entry associated with temporary item', function () {
      var nextStateItem = state.getIn(['bankEntries', _constants.TEMPORARY_BANK_ENTRY_ID, 'entry']);
      (0, _chai.expect)(nextStateItem).to.equal(_constants.TEMPORARY_ITEM_ID);
    });
    it('adds the temporary item with data', function () {
      var nextStateItem = state.getIn(['items', _constants.TEMPORARY_ITEM_ID, 'scoringData']);
      (0, _chai.expect)(nextStateItem).to.equal('someData');
    });
  });
  describe('clear temporary item', function () {
    var initialState = (0, _immutable.fromJS)({
      quizzes: {
        1: {
          id: '1',
          quizEntries: [_constants.TEMPORARY_QUIZ_ENTRY_ID]
        }
      },
      quizEntries: (0, _defineProperty2.default)({}, _constants.TEMPORARY_QUIZ_ENTRY_ID, {
        id: _constants.TEMPORARY_QUIZ_ENTRY_ID,
        entry: _constants.TEMPORARY_ITEM_ID
      }),
      items: (0, _defineProperty2.default)({}, _constants.TEMPORARY_ITEM_ID, {
        id: _constants.TEMPORARY_ITEM_ID
      })
    });
    var clearTempItemAction = {
      type: _constants.CLEAR_TEMPORARY_ITEM,
      payload: {
        quizId: '1'
      }
    };
    var nextState = (0, _modifications.default)(initialState, clearTempItemAction);
    it('removes the association from the quiz', function () {
      var nextStateItem = nextState.getIn(['quizzes', '1', 'quizEntries']);
      (0, _chai.expect)(nextStateItem).to.be.empty();
    });
    it('clears the quiz entry', function () {
      (0, _chai.expect)(nextState.getIn(['quizEntries', _constants.TEMPORARY_QUIZ_ENTRY_ID])).to.not.exist();
    });
    it('clears the item', function () {
      (0, _chai.expect)(nextState.getIn(['items', _constants.TEMPORARY_ITEM_ID])).to.not.exist();
    });
  });
  describe('clear temporary bank item', function () {
    var initialState = (0, _immutable.fromJS)({
      banks: {
        1: {
          id: '1',
          bankEntries: [_constants.TEMPORARY_BANK_ENTRY_ID]
        }
      },
      bankEntries: (0, _defineProperty2.default)({}, _constants.TEMPORARY_BANK_ENTRY_ID, {
        id: _constants.TEMPORARY_BANK_ENTRY_ID,
        entry: _constants.TEMPORARY_ITEM_ID
      }),
      items: (0, _defineProperty2.default)({}, _constants.TEMPORARY_ITEM_ID, {
        id: _constants.TEMPORARY_ITEM_ID
      })
    });
    var clearTempItemAction = {
      type: _constants.CLEAR_TEMPORARY_BANK_ITEM,
      payload: {
        bankId: '1'
      }
    };
    var nextState = (0, _modifications.default)(initialState, clearTempItemAction);
    it('removes the association from the bank', function () {
      var nextStateItem = nextState.getIn(['banks', '1', 'bankEntries']);
      (0, _chai.expect)(nextStateItem).to.be.empty();
    });
    it('clears the bank entry', function () {
      (0, _chai.expect)(nextState.getIn(['bankEntries', _constants.TEMPORARY_BANK_ENTRY_ID])).to.not.exist();
    });
    it('clears the item', function () {
      (0, _chai.expect)(nextState.getIn(['items', _constants.TEMPORARY_ITEM_ID])).to.not.exist();
    });
  });
  describe('clear modifications', function () {
    it('clears the modifications on the object', function () {
      var initialState = (0, _immutable.fromJS)({
        testType: {
          1: {
            id: '1',
            testAttr: true
          }
        }
      });
      var clearTempItemAction = {
        type: _constants.CLEAR_MODIFICATIONS,
        payload: {
          objectType: 'testType',
          objectId: '1',
          deepKeys: []
        }
      };
      var nextState = (0, _modifications.default)(initialState, clearTempItemAction);
      var nextItemState = nextState.get('testType');
      (0, _chai.expect)(nextItemState.equals((0, _immutable.fromJS)({}))).to.be.true();
    });
    it('clears a specific property using deepKeys', function () {
      var initialState = (0, _immutable.fromJS)({
        testType: {
          1: {
            id: '1',
            testAttr: true
          }
        }
      });
      var clearTempItemAction = {
        type: _constants.CLEAR_MODIFICATIONS,
        payload: {
          objectType: 'testType',
          objectId: '1',
          deepKeys: ['testAttr']
        }
      };
      var nextState = (0, _modifications.default)(initialState, clearTempItemAction);
      var nextItemState = nextState.getIn(['testType', '1']);
      (0, _chai.expect)(nextItemState.equals((0, _immutable.fromJS)({
        id: '1'
      }))).to.be.true();
    });
  });
  describe('move temporary item', function () {
    var initialState = (0, _immutable.fromJS)({
      quizEntries: (0, _defineProperty2.default)({}, _constants.TEMPORARY_QUIZ_ENTRY_ID, {
        id: _constants.TEMPORARY_QUIZ_ENTRY_ID,
        entry: _constants.TEMPORARY_ITEM_ID,
        position: 2
      })
    });

    var stateAfterAction = function stateAfterAction(moveAction) {
      return (0, _modifications.default)(initialState, moveAction);
    };

    it('increments position if direction is down', function () {
      var moveAction = {
        type: _constants.MOVE_TEMPORARY_ITEM,
        payload: {
          direction: 'down'
        }
      };
      var nextState = stateAfterAction(moveAction);
      var nextStateItem = nextState.getIn(['quizEntries', _constants.TEMPORARY_QUIZ_ENTRY_ID, 'position']);
      (0, _chai.expect)(nextStateItem).to.equal(3);
    });
    it('decrements position if direction is up', function () {
      var moveAction = {
        type: _constants.MOVE_TEMPORARY_ITEM,
        payload: {
          direction: 'up'
        }
      };
      var nextState = stateAfterAction(moveAction);
      var nextStateItem = nextState.getIn(['quizEntries', _constants.TEMPORARY_QUIZ_ENTRY_ID, 'position']);
      (0, _chai.expect)(nextStateItem).to.equal(1);
    });
    it('moves to item position to 0.1 less than given position if moving up', function () {
      var moveAction = {
        type: _constants.MOVE_TEMPORARY_ITEM,
        payload: {
          position: 20,
          movingDown: false
        }
      };
      var nextState = stateAfterAction(moveAction);
      var nextStateItem = nextState.getIn(['quizEntries', _constants.TEMPORARY_QUIZ_ENTRY_ID, 'position']);
      (0, _chai.expect)(nextStateItem).to.equal(19.9);
    });
    it('moves to item position to 0.9 greater than given position if moving down', function () {
      var moveAction = {
        type: _constants.MOVE_TEMPORARY_ITEM,
        payload: {
          position: 20,
          movingDown: true
        }
      };
      var nextState = stateAfterAction(moveAction);
      var nextStateItem = nextState.getIn(['quizEntries', _constants.TEMPORARY_QUIZ_ENTRY_ID, 'position']);
      (0, _chai.expect)(nextStateItem).to.equal(20.9);
    });
    it('sets the stimulusQuizEntryId', function () {
      var moveAction = {
        type: _constants.MOVE_TEMPORARY_ITEM,
        payload: {
          stimulusQuizEntryId: '5'
        }
      };
      var nextState = stateAfterAction(moveAction);
      var nextStateItem = nextState.getIn(['quizEntries', _constants.TEMPORARY_QUIZ_ENTRY_ID, 'stimulusQuizEntryId']);
      (0, _chai.expect)(nextStateItem).to.equal('5');
    });
  });
});