"use strict";

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

var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));

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

var _InteractionType = _interopRequireDefault(require("quiz-interactions/lib/records/InteractionType"));

var _Alert = _interopRequireDefault(require("@instructure/ui-alerts/lib/components/Alert"));

var _BreadcrumbLink = _interopRequireDefault(require("@instructure/ui-breadcrumb/lib/components/Breadcrumb/BreadcrumbLink"));

var _Heading = _interopRequireDefault(require("@instructure/ui-elements/lib/components/Heading"));

var _Button = _interopRequireDefault(require("@instructure/ui-buttons/lib/components/Button"));

var _TextInput = _interopRequireDefault(require("@instructure/ui-forms/lib/components/TextInput"));

var _presenter = _interopRequireDefault(require("../presenter"));

var _Bank = _interopRequireDefault(require("../../../../common/records/Bank"));

var _BankEntry = _interopRequireDefault(require("../../../../common/records/BankEntry"));

var _EntrySave = _interopRequireDefault(require("../../../../common/components/resources/entry/EntrySave"));

var _Item = _interopRequireDefault(require("../../../../common/records/Item"));

var _ItemEdit = _interopRequireDefault(require("../../../../common/components/resources/item/ItemEdit"));

var _ItemFeedbackModal = _interopRequireDefault(require("../../../../building/components/resources/ItemFeedbackModal"));

var _Page = _interopRequireDefault(require("../../../../common/components/layout/Page"));

var _Stimulus = _interopRequireDefault(require("../../../../common/records/Stimulus"));

var _StimulusEditInfo = _interopRequireDefault(require("../../../../common/components/resources/stimulus/StimulusEditInfo"));

var _TagSuggestSelect = _interopRequireDefault(require("../../../../common/components/shared/TagSuggestSelect"));

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

var _items = require("../../../../building/api/items");

var _stimuli = require("../../../../building/api/stimuli");

var _immutable = _interopRequireDefault(require("immutable"));

describe('BankEntry', function () {
  var type = new _InteractionType.default({
    name: 'Multiple Choice',
    slug: 'choice'
  });

  var item = _Item.default.create({
    id: '666',
    title: 'Tough Color Question',
    itemBody: 'Which color is happiest?',
    scoringData: {
      value: 'id'
    }
  });

  sinon.stub(item, 'getInteractionType').returns(type);
  sinon.stub(item, 'hasFeedback').returns(true);

  var stimulus = _Stimulus.default.create({
    id: '555',
    title: 'Stuff'
  });

  sinon.stub(stimulus, 'hasModifications').returns(true);

  var bankEntry = _BankEntry.default.create({
    id: '1',
    entry: _Item.default.create({
      id: '666'
    }),
    entryType: 'Item',
    updatedAt: new Date()
  });

  sinon.stub(bankEntry, 'getEntry').returns(item);

  var stimulusBankEntry = _BankEntry.default.create({
    id: '2',
    entry: _Stimulus.default.create(),
    entryType: 'Stimulus',
    updatedAt: new Date()
  });

  sinon.stub(stimulusBankEntry, 'getEntry').returns(stimulus);

  var bank = _Bank.default.create({
    id: '1',
    title: 'Units of Measurement'
  });

  var navigateBankStub = sinon.stub();
  var navigateBanksStub = sinon.stub();
  var updateItemStub = sinon.stub();
  var updateStimulusStub = sinon.stub();
  var clearModifcationsStub = sinon.stub();
  var createEntryAndBankEntryStub = sinon.stub();
  var setPendingAdditionTagAssociationsStub = sinon.stub();
  var setPendingDeletionTagAssociationsStub = sinon.stub();
  var createTagAssociationsStub = sinon.stub();
  var deleteTagAssociationsStub = sinon.stub();
  var clearTemporaryBankItemStub = sinon.stub();
  var setUiStub = sinon.stub();
  var openModalStub = sinon.stub();
  var changeItemTitleStub = sinon.stub();
  var setTagInputStub = sinon.stub();
  var getTagSuggestionsStub = sinon.stub();
  var setTagSuggestionsStub = sinon.stub();
  var getBankEntryStub = sinon.stub();
  var entryProps = {
    getBank: function getBank() {},
    getBankEntry: getBankEntryStub,
    bank: bank,
    bankId: bank.id,
    bankEntry: bankEntry,
    bankEntryId: bankEntry.id,
    changeItemTitle: changeItemTitleStub,
    navigateToBanks: navigateBanksStub,
    navigateToBank: navigateBankStub,
    updateItem: updateItemStub,
    updateStimulus: updateStimulusStub,
    createEntryAndBankEntry: createEntryAndBankEntryStub,
    setPendingAdditionTagAssociations: setPendingAdditionTagAssociationsStub,
    setPendingDeletionTagAssociations: setPendingDeletionTagAssociationsStub,
    setTagInput: setTagInputStub,
    setTagSuggestions: setTagSuggestionsStub,
    getTagSuggestions: getTagSuggestionsStub,
    setShouldClone: function setShouldClone() {},
    clearModifications: clearModifcationsStub,
    createTagAssociations: createTagAssociationsStub,
    deleteTagAssociations: deleteTagAssociationsStub,
    clearTemporaryBankItem: clearTemporaryBankItemStub,
    setUi: setUiStub,
    openModal: openModalStub
  };
  var testbed = createTestbed(_presenter.default, entryProps);
  var BankEntryWithContext = withContext(_presenter.default);
  var connectedTestbed = createTestbed(BankEntryWithContext, entryProps);
  var clock = null;
  beforeEach(function () {
    clock = sinon.useFakeTimers();
    sinon.stub(item, 'hasModifications').returns(true);
  });
  afterEach(function () {
    clock.restore();
    item.hasModifications.restore();
    navigateBankStub.resetHistory();
    navigateBanksStub.resetHistory();
    updateItemStub.resetHistory();
    updateStimulusStub.resetHistory();
    clearModifcationsStub.resetHistory();
    createEntryAndBankEntryStub.resetHistory();
    setPendingAdditionTagAssociationsStub.resetHistory();
    setPendingDeletionTagAssociationsStub.resetHistory();
    clearTemporaryBankItemStub.resetHistory();
    createTagAssociationsStub.resetHistory();
    deleteTagAssociationsStub.resetHistory();
    setUiStub.resetHistory();
    openModalStub.resetHistory();
    changeItemTitleStub.resetHistory();
    setTagInputStub.resetHistory();
    getTagSuggestionsStub.resetHistory();
    setTagSuggestionsStub.resetHistory();
    getBankEntryStub.resetHistory();
  });
  it('renders a Page component', function () {
    var output = testbed.renderShallowly();
    expect(output.find(_Page.default)).to.have.length(1);
  });
  describe('navigation', function () {
    it('renders Bank Entry app navigation', function () {
      var output = testbed.renderShallowly();
      var crumbs = output.find(_BreadcrumbLink.default);
      expect(crumbs.length).to.eq(2);
      var link = crumbs.first();
      expect(link.render().text()).to.contain('Units of Measurement');
      var link2 = crumbs.at(1);
      expect(link2.render().text()).to.contain('Edit Item');
    });
    it('calls right methods perform navigation', function () {
      var output = testbed.renderShallowly();
      var crumbs = output.find(_BreadcrumbLink.default);
      crumbs.first().simulate('click');
      expect(navigateBankStub.called).to.be.true();
    });
    it('does not render a return-to-build button when not passed a navigateToBuild prop', function () {
      var output = testbed.renderShallowly({
        navigateToBuild: null
      });
      var buttons = output.find(_Button.default);
      var texts = buttons.map(function (button) {
        return buttons.first().prop('children');
      });
      expect(texts.join()).to.not.include('Return');
    });
  });
  context('with item entry type', function () {
    it('renders BankEntry app header', function () {
      var output = testbed.renderShallowly();
      var heading = output.find(_Heading.default);
      expect(heading.render().text()).to.eq('Multiple Choice | Item 666');
    });
    it('renders bank entry', function () {
      var output = testbed.renderShallowly();
      var entryRows = output.find(_ItemEdit.default);
      expect(entryRows.length).to.eq(1);
    });
    it('renders the title field', function () {
      var output = testbed.renderShallowly();
      var title = output.find(_TextInput.default);
      expect(title.length).to.eq(1);
    });
    it('renders a warning that edits will appear on any assessment using the item', function () {
      var output = connectedTestbed.mount();
      var alert = output.find(_Alert.default);
      expect(alert.length).to.eq(1);
      expect(alert.text()).to.include('Edits made here will appear on any assessment using this item');
    });
    it('updates the title field on change', function () {
      var output = testbed.renderShallowly();
      var title = output.find(_TextInput.default);
      title.prop('onChange')({
        target: {
          value: 'some new title'
        }
      });
      expect(changeItemTitleStub).to.have.been.calledWith('666', 'some new title');
    });
    it('submitHandler calls updateItem for edit', function () {
      connectedTestbed.render();
      var entrySaveRow = connectedTestbed.findChildrenByType(_EntrySave.default);
      entrySaveRow[0].props.submitHandler();
      expect(updateItemStub).to.be.called();
    });
    it('passes null contextUuid to ItemEdit', function () {
      // important because outcomes does not use course context for item banks
      var output = testbed.renderShallowly();
      expect(output.find(_ItemEdit.default).props().contextUuid).to.equal(null);
    });
    it('does not render tag select', function () {
      var output = testbed.renderShallowly({
        useBankTags: false
      });
      expect(output.find(_TagSuggestSelect.default)).to.have.length(0);
    });
    it('renders tag select', function () {
      var output = testbed.renderShallowly({
        useBankTags: true
      });
      expect(output.find(_TagSuggestSelect.default)).to.have.length(1);
    });
  });
  context('with stimulus entry type', function () {
    it('renders BankEntry app header', function () {
      var output = testbed.renderShallowly({
        bankEntry: stimulusBankEntry,
        bankEntryId: stimulusBankEntry.id
      });
      var heading = output.find(_Heading.default);
      expect(heading.render().text()).to.eq('Stimulus | Stimulus 555');
    });
    it('renders bank entry', function () {
      var output = testbed.renderShallowly({
        bankEntry: stimulusBankEntry,
        bankEntryId: stimulusBankEntry.id
      });
      var entryRows = output.find(_StimulusEditInfo.default);
      expect(entryRows.length).to.eq(1);
    });
    it('does not render the extra title field', function () {
      var output = testbed.renderShallowly({
        bankEntry: stimulusBankEntry,
        bankEntryId: stimulusBankEntry.id
      });
      var title = output.find(_TextInput.default);
      expect(title.length).to.eq(0);
    });
    it('renders a warning that edits will appear on any assessment using the stimulus', function () {
      var output = connectedTestbed.mount({
        bankEntry: stimulusBankEntry,
        bankEntryId: stimulusBankEntry.id
      });
      var alert = output.find(_Alert.default);
      expect(alert.length).to.eq(1);
      expect(alert.text()).to.include('Edits made here will appear on any assessment using this item');
    });
    it('submitHandler calls updateStimulus for edit', function () {
      connectedTestbed.render({
        bankEntry: stimulusBankEntry,
        bankEntryId: stimulusBankEntry.id
      });
      var entrySaveRow = connectedTestbed.findChildrenByType(_EntrySave.default);
      entrySaveRow[0].props.submitHandler();
      expect(updateStimulusStub).to.be.called();
    });
  });
  it('renders entry save', function () {
    var output = testbed.renderShallowly();
    var entrySaveRow = output.find(_EntrySave.default);
    expect(entrySaveRow.length).to.eq(2);
  });
  describe('tags', function () {
    it('shows tag when no pending tag changes', function () {
      connectedTestbed.render({
        tagAssociations: _immutable.default.fromJS([{
          id: '1'
        }])
      });
      var bankEntry = connectedTestbed.findChildrenByType(_presenter.default)[0];
      expect(bankEntry.visibleTags().length).to.eq(1);
    });
    it('does not show tag when pending tag deletion', function () {
      connectedTestbed.render({
        tagAssociations: _immutable.default.fromJS([{
          id: '1'
        }]),
        pendingDeletionTags: _immutable.default.fromJS([{
          id: '1'
        }])
      });
      var bankEntry = connectedTestbed.findChildrenByType(_presenter.default)[0];
      expect(bankEntry.visibleTags().length).to.eq(0);
    });
    it('shows pending tag additions', function () {
      connectedTestbed.render({
        tagAssociations: _immutable.default.fromJS([{
          id: '1',
          tag_value: 'alpha'
        }]),
        pendingAdditionTags: _immutable.default.fromJS([{
          id: '2',
          tag_value: 'beta'
        }])
      });
      var bankEntry = connectedTestbed.findChildrenByType(_presenter.default)[0];
      expect(bankEntry.visibleTags().length).to.eq(2);
    });
    it('removes redundant pending additional tag', function () {
      connectedTestbed.render({
        tagAssociations: _immutable.default.fromJS([{
          id: '1',
          tag_value: 'alpha'
        }]),
        pendingAdditionTags: _immutable.default.fromJS([{
          tag_value: 'alpha'
        }])
      });
      var bankEntry = connectedTestbed.findChildrenByType(_presenter.default)[0];
      expect(bankEntry.visibleTags().length).to.eq(1);
    });
    it('sets pending addition tag associations', function () {
      connectedTestbed.render({
        tagAssociations: _immutable.default.List()
      });
      var bankEntry = connectedTestbed.findChildrenByType(_presenter.default);
      bankEntry[0].handleTagChange([{
        id: '20',
        value: 'boo'
      }]);
      expect(setPendingAdditionTagAssociationsStub).to.be.calledWith('Item', '666', [{
        tag_value: 'boo'
      }]);
    });
    it('sets pending addition tag associations for created tags', function () {
      connectedTestbed.render({
        tagAssociations: _immutable.default.List()
      });
      var bankEntry = connectedTestbed.findChildrenByType(_presenter.default);
      bankEntry[0].handleTagChange([{
        id: null,
        value: 'boo'
      }]);
      expect(setPendingAdditionTagAssociationsStub).to.be.calledWith('Item', '666', [{
        tag_value: 'boo'
      }]);
    });
    it('sets pending deletion tag associations', function () {
      connectedTestbed.render({
        tagAssociations: _immutable.default.fromJS([{
          id: '1'
        }])
      });
      var bankEntry = connectedTestbed.findChildrenByType(_presenter.default);
      bankEntry[0].handleTagChange([]);
      expect(setPendingDeletionTagAssociationsStub).to.be.calledWith('Item', '666', [{
        id: '1'
      }]);
    });
    it('restoring a deleted tag clears pending changes', function () {
      connectedTestbed.render({
        tagAssociations: _immutable.default.fromJS([{
          id: '1',
          tag_value: 'apple'
        }])
      });
      var bankEntry = connectedTestbed.findChildrenByType(_presenter.default);
      bankEntry[0].handleTagChange([{
        id: '1',
        value: 'apple'
      }]);
      expect(setPendingAdditionTagAssociationsStub).to.be.calledWith('Item', '666', []);
      expect(setPendingDeletionTagAssociationsStub).to.be.calledWith('Item', '666', []);
    });
  });
  it('submitHandler creates tag',
  /*#__PURE__*/
  (0, _asyncToGenerator2.default)(
  /*#__PURE__*/
  _regenerator.default.mark(function _callee() {
    var entrySaveRow;
    return _regenerator.default.wrap(function _callee$(_context) {
      while (1) {
        switch (_context.prev = _context.next) {
          case 0:
            connectedTestbed.render({
              tagAssociations: _immutable.default.fromJS([{
                id: '1'
              }]),
              pendingAdditionTags: _immutable.default.fromJS([{
                tag_value: 'hi'
              }])
            });
            entrySaveRow = connectedTestbed.findChildrenByType(_EntrySave.default);
            expect(entrySaveRow[0].props.submitHandler).to.not.be.undefined();
            _context.next = 5;
            return entrySaveRow[0].props.submitHandler();

          case 5:
            expect(createTagAssociationsStub).to.be.calledWith('1', 'Item', '666', _immutable.default.List(['hi']));

          case 6:
          case "end":
            return _context.stop();
        }
      }
    }, _callee);
  })));
  it('submitHandler deletes tag',
  /*#__PURE__*/
  (0, _asyncToGenerator2.default)(
  /*#__PURE__*/
  _regenerator.default.mark(function _callee2() {
    var entrySaveRow;
    return _regenerator.default.wrap(function _callee2$(_context2) {
      while (1) {
        switch (_context2.prev = _context2.next) {
          case 0:
            connectedTestbed.render({
              tagAssociations: _immutable.default.fromJS([{
                id: '1'
              }]),
              pendingDeletionTags: _immutable.default.fromJS([{
                id: '1'
              }])
            });
            entrySaveRow = connectedTestbed.findChildrenByType(_EntrySave.default);
            expect(entrySaveRow[0].props.submitHandler).to.not.be.undefined();
            _context2.next = 5;
            return entrySaveRow[0].props.submitHandler();

          case 5:
            expect(deleteTagAssociationsStub).to.be.calledWith('1', 'Item', '666', _immutable.default.List('1'));

          case 6:
          case "end":
            return _context2.stop();
        }
      }
    }, _callee2);
  })));
  it('submitHandler clears modifications and navigates back to Bank',
  /*#__PURE__*/
  (0, _asyncToGenerator2.default)(
  /*#__PURE__*/
  _regenerator.default.mark(function _callee3() {
    var entrySaveRow;
    return _regenerator.default.wrap(function _callee3$(_context3) {
      while (1) {
        switch (_context3.prev = _context3.next) {
          case 0:
            connectedTestbed.render();
            entrySaveRow = connectedTestbed.findChildrenByType(_EntrySave.default);
            expect(entrySaveRow[0].props.submitHandler).to.not.be.undefined();
            _context3.next = 5;
            return entrySaveRow[0].props.submitHandler();

          case 5:
            expect(clearModifcationsStub).to.be.called();
            expect(navigateBankStub).to.be.called();

          case 7:
          case "end":
            return _context3.stop();
        }
      }
    }, _callee3);
  })));
  it('submitHandler calls createEntryAndBankEntry when creating new item',
  /*#__PURE__*/
  (0, _asyncToGenerator2.default)(
  /*#__PURE__*/
  _regenerator.default.mark(function _callee4() {
    var tempItem, tempBankEntry, entrySaveRow;
    return _regenerator.default.wrap(function _callee4$(_context4) {
      while (1) {
        switch (_context4.prev = _context4.next) {
          case 0:
            tempItem = _Item.default.create({
              id: '1'
            });
            sinon.stub(tempItem, 'getWorkingInstance').returns(tempItem);
            tempBankEntry = _BankEntry.default.create({
              id: '1',
              entry: tempItem
            });
            sinon.stub(tempItem, 'isTemporary').returns(true);
            sinon.stub(tempBankEntry, 'getEntry').returns(tempItem);
            connectedTestbed.render({
              bankEntry: tempBankEntry
            });
            entrySaveRow = connectedTestbed.findChildrenByType(_EntrySave.default);
            _context4.next = 9;
            return entrySaveRow[0].props.submitHandler();

          case 9:
            expect(createEntryAndBankEntryStub).to.be.called();
            expect(clearModifcationsStub).to.be.called();
            expect(clearTemporaryBankItemStub).to.be.called();

          case 12:
          case "end":
            return _context4.stop();
        }
      }
    }, _callee4);
  })));
  it('submitHandler clones immutable item properly', function () {
    var cloneBankEntryStub = sinon.stub();
    updateItemStub.resetHistory();
    connectedTestbed.render({
      shouldClone: true,
      cloneBankEntry: cloneBankEntryStub
    });
    var entrySaveRow = connectedTestbed.findChildrenByType(_EntrySave.default);
    entrySaveRow[0].props.submitHandler();
    expect(cloneBankEntryStub).to.be.calledWith(bankEntry, _items.createItem);
    expect(updateItemStub.called).to.be.false();
  });
  it('submitHandler clones item without modifications except pending tags',
  /*#__PURE__*/
  (0, _asyncToGenerator2.default)(
  /*#__PURE__*/
  _regenerator.default.mark(function _callee5() {
    var cloneBankEntryStub, entrySaveRow;
    return _regenerator.default.wrap(function _callee5$(_context5) {
      while (1) {
        switch (_context5.prev = _context5.next) {
          case 0:
            item.hasModifications.restore();
            sinon.stub(item, 'hasModifications').returns(false);
            cloneBankEntryStub = sinon.stub().returns({
              id: '1000',
              entry_type: 'Item',
              entry: {
                id: '2000'
              }
            });
            updateItemStub.resetHistory();
            connectedTestbed.render({
              shouldClone: true,
              cloneBankEntry: cloneBankEntryStub,
              tagAssociations: _immutable.default.fromJS([{
                tag_value: 'boo'
              }]),
              pendingAdditionTags: _immutable.default.fromJS([{
                tag_value: 'hi'
              }])
            });
            entrySaveRow = connectedTestbed.findChildrenByType(_EntrySave.default);
            _context5.next = 8;
            return entrySaveRow[0].props.submitHandler();

          case 8:
            expect(cloneBankEntryStub).to.be.calledWith(bankEntry, _items.createItem);
            expect(createTagAssociationsStub).to.be.calledWith('1000', 'Item', '2000', ['boo', 'hi']);
            expect(setPendingAdditionTagAssociationsStub).to.be.calledWith('Item', '666', []);
            expect(setPendingDeletionTagAssociationsStub).to.be.calledWith('Item', '666', []);

          case 12:
          case "end":
            return _context5.stop();
        }
      }
    }, _callee5);
  })));
  it('submitHandler clones immutable stimulus properly', function () {
    var cloneBankEntryStub = sinon.stub();
    updateStimulusStub.resetHistory();
    connectedTestbed.render({
      shouldClone: true,
      cloneBankEntry: cloneBankEntryStub,
      bankEntry: stimulusBankEntry
    });
    var entrySaveRow = connectedTestbed.findChildrenByType(_EntrySave.default);
    entrySaveRow[0].props.submitHandler();
    expect(cloneBankEntryStub).to.be.calledWith(stimulusBankEntry, _stimuli.createStimulus);
    expect(updateStimulusStub.called).to.be.false();
  });
  it('cancelHandler navigates back to Bank', function () {
    connectedTestbed.render();
    var entrySaveRow = connectedTestbed.findChildrenByType(_EntrySave.default);
    expect(entrySaveRow[0].props.cancelHandler).to.not.be.undefined();
    entrySaveRow[0].props.cancelHandler();
    expect(navigateBankStub).to.be.called();
  });
  it('clearChanges clears modifications', function () {
    connectedTestbed.render();
    var entrySaveRow = connectedTestbed.findChildrenByType(_EntrySave.default);
    expect(entrySaveRow[0].props.clearChanges).to.not.be.undefined();
    entrySaveRow[0].props.clearChanges();
    expect(clearModifcationsStub).to.be.called();
  });
  it('clearChanges clears pending deletion tag associations', function () {
    connectedTestbed.render();
    var entrySaveRow = connectedTestbed.findChildrenByType(_EntrySave.default);
    expect(entrySaveRow[0].props.clearChanges).to.not.be.undefined();
    entrySaveRow[0].props.clearChanges();
    expect(setPendingDeletionTagAssociationsStub).to.be.calledWith('Item', '666', []);
  });
  it('clearChanges clears pending addition tag associations', function () {
    connectedTestbed.render();
    var entrySaveRow = connectedTestbed.findChildrenByType(_EntrySave.default);
    expect(entrySaveRow[0].props.clearChanges).to.not.be.undefined();
    entrySaveRow[0].props.clearChanges();
    expect(setPendingAdditionTagAssociationsStub).to.be.calledWith('Item', '666', []);
  });
  describe('item feedback', function () {
    it('renders item feedback modal with bank parent', function () {
      var shallowTestbed = testbed.renderShallowly();
      var feedbackModal = shallowTestbed.find(_ItemFeedbackModal.default);
      expect(feedbackModal.prop('parentId')).to.eq(bank.id);
      expect(feedbackModal.prop('parentType')).to.eq(_constants.PARENT_TYPE_BANK);
    });
    it('calls open item feedback modal', function () {
      var shallowTestbed = testbed.renderShallowly();
      var feedbackButton = shallowTestbed.find(_Button.default).first();
      feedbackButton.simulate('click');
      expect(setUiStub).to.have.been.called();
      expect(openModalStub).to.have.been.calledWith(_constants.ITEM_FEEDBACK_MODAL);
    });
  }); // FIXME: shallow rendering doesn't make sense for a11y tests

  xit('should meet a11y standards', function (done) {
    testbed.renderShallowly();
    testbed.checkA11yStandards(done);
  });
});