"use strict";

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

var _testUtils = _interopRequireDefault(require("react-dom/test-utils"));

var _immutable = require("immutable");

var _ToggleDetails = _interopRequireDefault(require("@instructure/ui-toggle-details/lib/components/ToggleDetails"));

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

var _mouseEventOn = _interopRequireDefault(require("../../../../../../../tests/util/mouseEventOn"));

var _featureCheck = require("../../../../../../common/util/featureCheck");

var _reduxStore = require("../../../../../../reduxStore");

var _QuizEntry = _interopRequireDefault(require("../../../../../records/QuizEntry"));

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

var _WarningWrapper = _interopRequireDefault(require("../../../WarningWrapper"));

var _AddToBankModal = _interopRequireDefault(require("../../../../../../banks/components/AddToBankModal"));

var _AddToBankOptions = _interopRequireDefault(require("../../../../../../building/components/resources/AddToBankOptions"));

var _index = _interopRequireDefault(require("../index"));

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

var _StimulusShowInfo = _interopRequireDefault(require("../../StimulusShowInfo"));

var styles = {
  componentId: 'eCUGW',
  template: function template(theme) {
    return "\n\n.StimulusEdit__styles__stimulus {\n  padding-top: ".concat(theme.stimulusPadding || 'inherit', ";\n  padding-bottom: ").concat(theme.stimulusPadding || 'inherit', ";\n}\n\n.StimulusEdit__styles__footer {\n  display: flex;\n  justify-content: flex-end;\n}\n\n.StimulusEdit__styles__buttonWrapper {\n  padding-left: ").concat(theme.buttonWrapperPadding || 'inherit', ";\n}\n\n.StimulusEdit__styles__header {\n  height: 1rem;\n  padding-left: ").concat(theme.headerPadding || 'inherit', ";\n  padding-right: ").concat(theme.headerPadding || 'inherit', ";\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n}\n\n.StimulusEdit__styles__stimulusContent {\n  height: 100%;\n  padding: ").concat(theme.stimulusContentPadding || 'inherit', ";\n}\n\n.StimulusEdit__styles__stimulusLabel {\n  color: ").concat(theme.stimulusLabelColor || 'inherit', ";\n  font-size: ").concat(theme.stimulusLabelFontSize || 'inherit', ";\n}\n\n.StimulusEdit__styles__stimulusButtons {\n  flex: 0 0 auto;\n  display: inline-flex;\n  text-align: right;\n  z-index: ").concat(theme.stimulusButtonsZIndex || 'inherit', ";\n  color: ").concat(theme.stimulusButtonsColor || 'inherit', ";\n}\n\n[dir=\"ltr\"] .StimulusEdit__styles__stimulusButtons {\n  text-align: right;\n}\n\n[dir=\"rtl\"] .StimulusEdit__styles__stimulusButtons {\n  text-align: right;\n}\n\n.StimulusEdit__styles__stimulusButtons button {\n  background-color: transparent;\n  background-color: initial;\n}\n\n.StimulusEdit__styles__optionWrapper {\n  padding-top: ").concat(theme.optionPadding || 'inherit', ";\n}\n");
  },
  'stimulus': 'StimulusEdit__styles__stimulus',
  'footer': 'StimulusEdit__styles__footer',
  'buttonWrapper': 'StimulusEdit__styles__buttonWrapper',
  'header': 'StimulusEdit__styles__header',
  'stimulusContent': 'StimulusEdit__styles__stimulusContent',
  'stimulusLabel': 'StimulusEdit__styles__stimulusLabel',
  'stimulusButtons': 'StimulusEdit__styles__stimulusButtons',
  'optionWrapper': 'StimulusEdit__styles__optionWrapper'
};
describe('StimulusEdit', function () {
  var sandbox = sinon.createSandbox();
  var clearStub = sandbox.stub();
  var clearNextQuizEntryStub = sandbox.stub();
  var createStimulusStub = sandbox.stub().resolves({
    id: 55
  });
  var createStimulusAndQuizEntryStub = sandbox.stub().resolves({
    id: '3'
  });
  var createTempStimulusStub = sandbox.stub();
  var modifyStub = sandbox.stub();
  var clearModificationsStub = sandbox.stub();
  var switchOnEditingStub = sandbox.stub();
  var switchOffEditingStub = sandbox.stub();
  var showErrorStub = sandbox.stub();
  var hideErrorStub = sandbox.stub();
  var getQuizEntriesStub = sandbox.stub();
  var updateQuizEntryStub = sandbox.stub();
  var updateStimulusStub = sandbox.stub().resolves();
  var setUiStub = sandbox.stub();
  var screenreaderNotificationStub = sandbox.stub();
  var openDeleteStimulusModalStub = sandbox.stub();
  var stimulus = new _Stimulus.default({
    id: 55,
    title: 'Title',
    instructions: 'Instructions',
    body: 'Body',
    sourceUrl: 'Source URL'
  });
  sandbox.stub(stimulus, 'hasModifications').returns(true);
  var tempStimulus = new _Stimulus.default({
    id: _constants.TEMPORARY_STIMULUS_ID,
    title: 'Title',
    instructions: 'Instructions',
    body: 'Body',
    sourceUrl: 'Source URL'
  });
  var quizEntry = new _QuizEntry.default({
    id: 3
  });
  var defaultProps = {
    stimulus: stimulus,
    workingStimulus: stimulus,
    quizEntry: quizEntry,
    workingQuizEntry: quizEntry,
    quizEntries: (0, _immutable.fromJS)([{}, {}]),
    quizId: '100',
    clearModifications: clearModificationsStub,
    clearNextQuizEntry: clearNextQuizEntryStub,
    displayPosition: 1,
    guid: 'g1234',
    fileUpload: sandbox.stub(),
    clearTemporaryStimulus: clearStub,
    createStimulus: createStimulusStub,
    createTempStimulus: createTempStimulusStub,
    getQuizEntries: getQuizEntriesStub,
    modifyStimulus: modifyStub,
    switchOnEditing: switchOnEditingStub,
    switchOffEditing: switchOffEditingStub,
    updateQuizEntry: function updateQuizEntry() {
      updateQuizEntryStub.apply(void 0, arguments);
      return {
        then: function then(cb) {
          return cb();
        }
      };
    },
    showError: showErrorStub,
    hideError: hideErrorStub,
    updateStimulus: function updateStimulus() {
      updateStimulusStub.apply(void 0, arguments);
      return {
        then: function then(cb) {
          return cb();
        }
      };
    },
    createStimulusAndQuizEntry: createStimulusAndQuizEntryStub,
    setUi: setUiStub,
    screenreaderNotification: screenreaderNotificationStub,
    openDeleteStimulusModal: openDeleteStimulusModalStub,
    progressValue: 0,
    setUploadStatus: sandbox.stub(),
    connectDragSource: function connectDragSource(C) {
      return C;
    },
    appContainer: '.root',
    onEditToggle: function onEditToggle() {}
  };
  var testbed = createTestbed(withContext(_presenter.default), defaultProps);
  var DELETE_STIMULUS_MODAL_BUTTON = 1;
  afterEach(function () {
    sandbox.resetHistory();
  });

  var findTestbedCancelButton = function findTestbedCancelButton(testbed) {
    var selector = ".".concat(styles.footer, " button");
    return testbed.findChildrenBySelector(selector)[0];
  };

  var findTestbedSaveButton = function findTestbedSaveButton(testbed) {
    var selector = ".".concat(styles.footer, " button");
    return testbed.findChildrenBySelector(selector)[1];
  };

  context('errors', function () {
    var renderWithAttrs = function renderWithAttrs(attrs) {
      var errorsShowing = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
      var stim = stimulus.merge(attrs);
      testbed.render({
        stimulus: stim,
        errorsShowing: errorsShowing
      });
    };

    it('displays no errors when stimulus is valid', function () {
      renderWithAttrs({});
      expect(testbed.rootNode.innerText.match('Title cannot be blank')).to.not.exist();
    });
    it('focuses on the title on mount', function () {
      renderWithAttrs({});
      expect(document.activeElement).to.not.be.false();
    });
    it('displays an error when title is blank', function () {
      renderWithAttrs({
        title: ''
      });
      expect(testbed.rootNode.innerText.match('Title cannot be blank')).to.exist();
    });
    it('displays an error when body is blank', function () {
      renderWithAttrs({
        body: ''
      });
      expect(testbed.rootNode.innerText.match('Content cannot be blank')).to.exist();
    });
    it('displays no errors when errorsShowing is falsey', function () {
      renderWithAttrs({
        body: '',
        title: ''
      }, false);
      expect(testbed.rootNode.innerText.match('Content cannot be blank')).to.not.exist();
    });
  });
  it('tries to open the delete stimulus modal on click', function () {
    testbed.render();
    var button = testbed.findChildrenByTagNameAndAttribute('div', 'role', 'button')[DELETE_STIMULUS_MODAL_BUTTON];

    _testUtils.default.Simulate.click(button);

    expect(openDeleteStimulusModalStub).to.have.been.called();
  });
  it('renders an immutability warning wrapper when not banked', function () {
    testbed.render();
    var wrapper = testbed.findChildByType(_WarningWrapper.default);
    expect(wrapper).to.exist();
  });
  it('renders as show when banked', function () {
    testbed.render({
      isBankedContent: true
    });
    var wrapper = testbed.findChildByType(_StimulusShowInfo.default);
    expect(wrapper).to.exist();
  });
  it('clears temporary stimulus on delete stimulus button click when temporary', function () {
    testbed.render({
      stimulus: tempStimulus
    });
    var button = testbed.findChildrenByTagNameAndAttribute('div', 'role', 'button')[DELETE_STIMULUS_MODAL_BUTTON];

    _testUtils.default.Simulate.click(button);

    expect(openDeleteStimulusModalStub).to.have.not.been.called();
    expect(clearStub).to.have.been.called();
  });
  describe('discard changes', function () {
    it('clears if temporary stimulus', function () {
      testbed.render({
        stimulus: tempStimulus
      });
      var button = findTestbedCancelButton(testbed);

      _testUtils.default.Simulate.click(button);

      expect(clearStub).to.have.been.calledWith(defaultProps.quizId);
    });
    it('clears modifications and turns off editing', function () {
      testbed.render();
      var button = findTestbedCancelButton(testbed);

      _testUtils.default.Simulate.click(button);

      expect(clearModificationsStub).to.have.been.called();
      expect(switchOffEditingStub).to.have.been.called();
    });
    it('sets shouldClone to false', function () {
      testbed.render();
      var button = findTestbedCancelButton(testbed);

      _testUtils.default.Simulate.click(button);

      expect(setUiStub).to.be.calledWith(_constants.SHOULD_CLONE_ITEM, false);
    });
  });
  describe('clicked outside', function () {
    var clickOutside = function clickOutside() {
      var outerElement = document.createElement('div');
      outerElement.className = 'root';
      document.body.appendChild(outerElement);
      (0, _mouseEventOn.default)(outerElement, 'click');
    };

    it('submits on outside click', function (done) {
      testbed.render();
      clickOutside();
      setTimeout(function () {
        expect(clearModificationsStub).to.have.been.called();
        done();
      });
    });
    it('calls switchOffEditing if immutable', function () {
      sandbox.stub(stimulus, 'isImmutable').returns(true);
      testbed.render();
      clickOutside();
      expect(switchOffEditingStub).to.have.been.called();
    });
    it('calls switchOffEditing if banked', function () {
      testbed.render({
        isBankedContent: true
      });
      clickOutside();
      expect(switchOffEditingStub).to.have.been.called();
    });
  });
  describe('saving', function () {
    context('invalid', function () {
      it('shows errors if the stimulus is invalid', function () {
        var stim = stimulus.merge({
          title: ''
        });

        stim.isValid = function () {
          return false;
        };

        testbed.render({
          workingStimulus: stim
        });
        var button = findTestbedSaveButton(testbed);

        _testUtils.default.Simulate.click(button);

        expect(showErrorStub).to.have.been.calledWith(defaultProps.guid);
      });
      it('clears the nextQuizEntry if invalid', function () {
        var stim = stimulus.merge({
          title: ''
        });

        stim.isValid = function () {
          return false;
        };

        testbed.render({
          workingStimulus: stim
        });
        var button = findTestbedSaveButton(testbed);

        _testUtils.default.Simulate.click(button);

        expect(clearNextQuizEntryStub).to.have.been.called();
      });
      it('does not update the stimulus if the stimulus is invalid', function () {
        var stim = stimulus.merge({
          title: ''
        });

        stim.isValid = function () {
          return false;
        };

        testbed.render({
          workingStimulus: stim
        });
        var button = findTestbedSaveButton(testbed);

        _testUtils.default.Simulate.click(button);

        expect(hideErrorStub).to.have.not.been.called();
        expect(updateStimulusStub).to.have.not.been.called();
      });
    });
    it('hides the errors if the stimulus is valid', function () {
      testbed.render();
      var button = findTestbedSaveButton(testbed);

      _testUtils.default.Simulate.click(button);

      expect(showErrorStub).to.have.not.been.called();
      expect(hideErrorStub).to.have.been.calledWith(defaultProps.guid);
    });
    it('clears the temporary stimulus on save', function (done) {
      testbed.render({
        stimulus: tempStimulus
      });
      var button = findTestbedSaveButton(testbed);

      _testUtils.default.Simulate.click(button);

      setTimeout(function () {
        expect(clearStub).to.have.been.calledWith(defaultProps.quizId);
        done();
      });
    });
    it('calls all methods in afterSubmit', function (done) {
      testbed.render();
      var button = findTestbedSaveButton(testbed);

      _testUtils.default.Simulate.click(button);

      setTimeout(function () {
        expect(clearModificationsStub).to.have.been.called();
        expect(switchOffEditingStub).to.have.been.called();
        expect(setUiStub).to.have.been.called();
        expect(screenreaderNotificationStub).to.have.been.called();
        done();
      });
    });
    it('cannot be created twice if submit is double clicked', function () {
      testbed.render();
      var button = findTestbedSaveButton(testbed);

      _testUtils.default.Simulate.click(button);

      _testUtils.default.Simulate.click(button);

      expect(updateStimulusStub).to.have.been.calledOnce();
    });
    context('with normal stimulus', function () {
      it('shows the correct save text', function () {
        testbed.render();
        expect(testbed.rootNode.innerText.match('Save Stimulus')).to.exist();
      });
      it('updates the stimulus on save', function (done) {
        testbed.render();
        var button = findTestbedSaveButton(testbed);

        _testUtils.default.Simulate.click(button);

        setTimeout(function () {
          expect(updateStimulusStub).to.have.been.calledOnce();
          done();
        });
      });
      context('when updating stimulus fails', function () {
        it('re-enables button', function (done) {
          testbed.render({
            updateStimulus: sandbox.stub().rejects()
          });
          var button = findTestbedSaveButton(testbed);

          _testUtils.default.Simulate.click(button);

          setTimeout(function () {
            expect(button.disabled).to.be.false();
            done();
          });
        });
      });
    });
    context('with tempStimulus', function () {
      it('creates the stimulus and quiz entry on save', function () {
        testbed.render({
          stimulus: tempStimulus
        });
        var button = findTestbedSaveButton(testbed);

        _testUtils.default.Simulate.click(button);

        expect(createStimulusAndQuizEntryStub).to.have.been.calledWith(defaultProps.quizId);
      });
      it('clears the temporary stimulus on save', function (done) {
        testbed.render({
          stimulus: tempStimulus
        });
        var button = findTestbedSaveButton(testbed);

        _testUtils.default.Simulate.click(button);

        setTimeout(function () {
          expect(clearStub).to.have.been.calledWith(defaultProps.quizId);
          done();
        });
      });
      it('calls switchOffEditing on save', function (done) {
        testbed.render({
          stimulus: tempStimulus
        });
        var button = findTestbedSaveButton(testbed);

        _testUtils.default.Simulate.click(button);

        setTimeout(function () {
          expect(switchOffEditingStub).to.have.been.called();
          done();
        });
      });
      it('shows the correct save text', function () {
        testbed.render({
          stimulus: tempStimulus
        });
        expect(testbed.rootNode.innerText.match('Add Stimulus')).to.exist();
      });
      it('creates the next quiz entry when needed', function (done) {
        testbed.render({
          stimulus: tempStimulus,
          nextQuizEntry: (0, _immutable.Map)()
        });
        var button = findTestbedSaveButton(testbed);

        _testUtils.default.Simulate.click(button);

        setTimeout(function () {
          expect(createTempStimulusStub).to.have.been.called();
          expect(clearNextQuizEntryStub).to.have.been.called();
          done();
        });
      });
      context('when creating stimulus or quiz entry fails', function () {
        it('re-enables button', function (done) {
          testbed.render({
            stimulus: tempStimulus,
            createStimulusAndQuizEntry: sandbox.stub().rejects()
          });
          var button = findTestbedSaveButton(testbed);

          _testUtils.default.Simulate.click(button);

          setTimeout(function () {
            expect(button.disabled).to.be.false();
            done();
          });
        });
      });
    });
    context('with shouldClone as true', function () {
      it('calls createStimulus', function () {
        testbed.render({
          shouldClone: true
        });
        var button = findTestbedSaveButton(testbed);

        _testUtils.default.Simulate.click(button);

        expect(createStimulusStub).to.have.been.called();
      });
      it('calls updateQuizEntry', function (done) {
        testbed.render({
          shouldClone: true
        });
        var button = findTestbedSaveButton(testbed);

        _testUtils.default.Simulate.click(button);

        setTimeout(function () {
          expect(updateQuizEntryStub).to.have.been.called();
          done();
        });
      });
      it('calls getQuizEntries', function (done) {
        testbed.render({
          shouldClone: true
        });
        var button = findTestbedSaveButton(testbed);

        _testUtils.default.Simulate.click(button);

        setTimeout(function () {
          expect(getQuizEntriesStub).to.have.been.called();
          done();
        });
      });
      it('calls all methods in afterSubmit', function (done) {
        testbed.render();
        var button = findTestbedSaveButton(testbed);

        _testUtils.default.Simulate.click(button);

        setTimeout(function () {
          expect(clearModificationsStub).to.have.been.called();
          expect(switchOffEditingStub).to.have.been.called();
          expect(setUiStub).to.have.been.called();
          expect(screenreaderNotificationStub).to.have.been.called();
          done();
        });
      });
      context('when cloning stimulus fails', function () {
        it('re-enables button', function (done) {
          testbed.render({
            shouldClone: true,
            createStimulus: sandbox.stub().rejects()
          });
          var button = findTestbedSaveButton(testbed);

          _testUtils.default.Simulate.click(button);

          setTimeout(function () {
            expect(button.disabled).to.be.false();
            done();
          });
        });
      });
      context('when updating quiz entry fails', function () {
        it('re-enables button', function (done) {
          testbed.render({
            shouldClone: true,
            updateQuizEntry: sandbox.stub().rejects()
          });
          var button = findTestbedSaveButton(testbed);

          _testUtils.default.Simulate.click(button);

          setTimeout(function () {
            expect(button.disabled).to.be.false();
            done();
          });
        });
      });
    });
  });
  describe('modifications', function () {
    var clock = null;
    beforeEach(function () {
      clock = sinon.useFakeTimers();
    });
    afterEach(function () {
      clock.restore();
    });
    it('clears modifications on unmount', function () {
      clearModificationsStub.resetHistory(); // Be extra sure we've reset this stub

      testbed.render();
      testbed.unmount();
      clock.tick(20);
      expect(clearModificationsStub).to.have.been.calledOnce();
    });
  });
  describe('adding to banks', function () {
    beforeEach(function () {
      // needed for withTestFeatures to work
      (0, _reduxStore.unsetFakeStore)();
    });
    (0, _featureCheck.withTestFeatures)(['stimulus_banking']);
    it('renders AddToBankOptions', function () {
      testbed.render();
      var details = testbed.findChildByType(_ToggleDetails.default);
      var button = testbed.findChildrenByTagName('button', details)[0];

      _testUtils.default.Simulate.click(button);

      var bankOptions = testbed.findChildByType(_AddToBankOptions.default);
      expect(bankOptions).to.not.be.undefined();
    });
    it('renders AddToBankModal', function () {
      testbed.render();
      var modal = testbed.findChildByType(_AddToBankModal.default);
      expect(modal).to.not.be.undefined();
    });
    it('disables submit on continue', function () {
      var subject = testbed.render();
      testbed.findChildByType(_AddToBankModal.default).props.onContinue();
      expect(subject.refs.composedComponent.state.canSubmit).to.be.false();
    });
    it('creates the entry for the bank if it does not exist', function () {
      testbed.render({
        stimulus: tempStimulus
      });
      testbed.findChildByType(_AddToBankModal.default).props.getEntry();
      expect(updateStimulusStub).not.to.have.been.called();
      expect(createStimulusStub).to.have.been.called();
    });
    it('updates the entry and returns it for the bank if it exists', function () {
      testbed.render();
      testbed.findChildByType(_AddToBankModal.default).props.getEntry();
      expect(createStimulusStub).not.to.have.been.called();
      expect(updateStimulusStub).to.have.been.called();
    });
    it('creates the entry for the bank if immutable with changes', function () {
      testbed.render({
        shouldClone: true
      });
      testbed.findChildByType(_AddToBankModal.default).props.getEntry();
      expect(updateStimulusStub).not.to.have.been.called();
      expect(createStimulusStub).to.have.been.called();
    });
    it('updates the quiz entry with freshly banked content', function () {
      var bankEntry = {
        id: '11'
      };
      testbed.render();
      testbed.findChildByType(_AddToBankModal.default).props.onAdd(bankEntry);
      expect(updateQuizEntryStub).to.have.been.calledWith('100', 3, {
        entryId: '11',
        entryType: 'BankEntry'
      });
    });
  });
  describe('test with connect', function () {
    var connectedTestbed = createTestbed(withContext(_index.default), defaultProps);
    shouldRenderComponent(connectedTestbed, {}, _presenter.default);
  });
  describe('a11y tests', function () {
    it('should meet a11y standards', function (done) {
      testbed.render(); // ignoring button-name because of the textcolor tinymce plugin

      testbed.checkA11yStandards(done, {
        ignores: ['aria-allowed-role', // TODO: remove this when canvas-rce is fixed
        'button-name']
      });
    });
  });
});