"use strict";

var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");

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

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

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

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

var _react = _interopRequireDefault(require("react"));

var _chai = require("chai");

var _enzyme = require("enzyme");

var _immutable = require("immutable");

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

var _taking = require("../taking");

var _taking2 = require("../../../common/actions/taking");

var _QuizSession = _interopRequireDefault(require("../../../common/records/QuizSession"));

var _alerts = require("../../../common/actions/alerts");

var _fakeFetch = _interopRequireWildcard(require("../../../../tests/util/fakeFetch"));

var _Fetcher = _interopRequireDefault(require("../../../common/util/Fetcher"));

var _jsonify = require("../../../common/util/jsonify");

var _noop = _interopRequireDefault(require("../../../common/util/noop"));

describe('taking api actions creators', function () {
  var quizSessionId = '42';
  var fetchStub = sinon.stub();
  var dispatchStub = sinon.stub();
  var fakeResponseState = {
    taking: {
      responses: {}
    }
  };
  var fakeSessionItemsState = {
    sessionItems: {
      '42_1': {
        id: '1',
        item: {
          itemBody: 'STEM'
        },
        position: 1,
        quizSessionId: quizSessionId
      },
      '42_2': {
        id: '2',
        item: {
          itemBody: 'STEM TWO'
        },
        position: 10,
        quizSessionId: quizSessionId
      },
      '99_1': {
        id: '2',
        item: {
          itemBody: 'STEM THREE'
        },
        position: 5,
        quizSessionId: '99'
      }
    }
  };
  var getStateStub = sinon.stub();
  var fakeState = Object.assign({}, fakeResponseState, fakeSessionItemsState);
  useFakeFetching({
    dispatchStub: dispatchStub,
    getStateStub: getStateStub,
    fetchStub: fetchStub,
    fakeState: fakeState
  });
  var response = (0, _jsonify.jsoniblePromise)({});
  var fakeFetch = (0, _fakeFetch.default)(response);
  describe('confirmSessionStartPage', function () {
    var confirmSessionStartPageThunk = (0, _taking.confirmSessionStartPage)(quizSessionId);

    var stubbedConfirmSessionStartPageCall = function stubbedConfirmSessionStartPageCall() {
      _Fetcher.default.fakeFetch = fetchStub;
      confirmSessionStartPageThunk(dispatchStub, getStateStub);
    };

    it('should hit the correct endpoint', function () {
      stubbedConfirmSessionStartPageCall();
      (0, _chai.expect)(fetchStub.calledWith('/api/quiz_sessions/42')).to.be.true();
    });
    it('should call callback to handle error',
    /*#__PURE__*/
    (0, _asyncToGenerator2.default)(
    /*#__PURE__*/
    _regenerator.default.mark(function _callee() {
      var errorStub;
      return _regenerator.default.wrap(function _callee$(_context) {
        while (1) {
          switch (_context.prev = _context.next) {
            case 0:
              errorStub = sinon.stub();
              _Fetcher.default.fakeFetch = (0, _fakeFetch.makeFakeFetchFail)({
                response: {
                  status: 403
                }
              });
              _context.next = 4;
              return (0, _taking.confirmSessionStartPage)(quizSessionId, _noop.default, errorStub)(dispatchStub, getStateStub);

            case 4:
              (0, _chai.expect)(errorStub.called).to.be.true();

            case 5:
            case "end":
              return _context.stop();
          }
        }
      }, _callee);
    })));
    it('calls a custom callback',
    /*#__PURE__*/
    (0, _asyncToGenerator2.default)(
    /*#__PURE__*/
    _regenerator.default.mark(function _callee2() {
      var cb;
      return _regenerator.default.wrap(function _callee2$(_context2) {
        while (1) {
          switch (_context2.prev = _context2.next) {
            case 0:
              cb = sinon.stub();
              _Fetcher.default.fakeFetch = (0, _fakeFetch.default)((0, _jsonify.jsoniblePromise)({
                id: '234',
                allow_backtracking: true,
                one_at_a_time_type: false
              }));
              _context2.next = 4;
              return (0, _taking.confirmSessionStartPage)(quizSessionId, cb)(dispatchStub, getStateStub);

            case 4:
              (0, _chai.expect)(cb.called).to.be.true();

            case 5:
            case "end":
              return _context2.stop();
          }
        }
      }, _callee2);
    })));
  });
  describe('#getResumeData', function () {
    it('makes a request to the endpoint', function () {
      _Fetcher.default.fakeFetch = fetchStub;
      var quizSessionId = '11';
      (0, _taking.getResumeData)(quizSessionId)(dispatchStub);
      (0, _chai.expect)(fetchStub.calledWith('/api/quiz_sessions/11/session_item_responses/resume_data')).to.be.true();
    });
    it('dispatches the callback', function (done) {
      _Fetcher.default.fakeFetch = fetchStub;
      var response = [];
      _Fetcher.default.fakeFetch = (0, _fakeFetch.default)((0, _jsonify.jsoniblePromise)(response));
      (0, _taking.getResumeData)(quizSessionId)(dispatchStub).then(function (val) {
        (0, _chai.expect)(dispatchStub.called).to.be.true();
        done();
      });
    });
  });
  describe('getTimeRemaining', function () {
    it('makes a request to the endpoint', function () {
      _Fetcher.default.fakeFetch = fetchStub;
      var quizSessionId = '11';
      (0, _taking.getTimeRemaining)(quizSessionId, _noop.default)(dispatchStub, getStateStub);
      (0, _chai.expect)(fetchStub.calledWith('/api/quiz_sessions/11/time')).to.be.true();
    });
    it('calls the callback with the time', function (done) {
      var cbStub = sinon.stub();
      var response = {
        timeLeftInSeconds: 33
      };
      _Fetcher.default.fakeFetch = (0, _fakeFetch.default)((0, _jsonify.jsoniblePromise)(response));
      (0, _taking.getTimeRemaining)(quizSessionId, cbStub)(dispatchStub, getStateStub).then(function (val) {
        (0, _chai.expect)(cbStub.calledWith(response));
        done();
      });
    });
  });
  describe('recordQuizTime', function () {
    it('makes a request to the endpoint', function () {
      _Fetcher.default.fakeFetch = fetchStub;
      var quizSessionId = '11';
      (0, _taking.recordQuizTime)(quizSessionId, _noop.default)(dispatchStub, getStateStub);
      (0, _chai.expect)(fetchStub.calledWith('/api/quiz_sessions/11/record')).to.be.true();
    });
    it('calls the callback with the time', function (done) {
      var cbStub = sinon.stub();
      var response = {
        timeLeftInSeconds: 33
      };
      _Fetcher.default.fakeFetch = (0, _fakeFetch.default)((0, _jsonify.jsoniblePromise)(response));
      (0, _taking.recordQuizTime)(quizSessionId, cbStub)(dispatchStub, getStateStub).then(function (val) {
        (0, _chai.expect)(cbStub.calledWith(response));
        done();
      });
    });
  });
  describe('newQuizTakingSession', function () {
    it('should hit the correct endpoint', function () {
      _Fetcher.default.fakeFetch = fetchStub;
      (0, _taking.newQuizTakingSession)(quizSessionId)(dispatchStub, getStateStub);
      (0, _chai.expect)(fetchStub.calledWith('/api/quiz_sessions/42/take')).to.be.true();
    });
    it('should call callback to handle error',
    /*#__PURE__*/
    (0, _asyncToGenerator2.default)(
    /*#__PURE__*/
    _regenerator.default.mark(function _callee3() {
      var errorStub;
      return _regenerator.default.wrap(function _callee3$(_context3) {
        while (1) {
          switch (_context3.prev = _context3.next) {
            case 0:
              errorStub = sinon.stub();
              _Fetcher.default.fakeFetch = (0, _fakeFetch.makeFakeFetchFail)({
                response: {
                  status: 403
                }
              });
              _context3.next = 4;
              return (0, _taking.newQuizTakingSession)(quizSessionId, _noop.default, errorStub)(dispatchStub, getStateStub);

            case 4:
              (0, _chai.expect)(errorStub.called).to.be.true();

            case 5:
            case "end":
              return _context3.stop();
          }
        }
      }, _callee3);
    })));
    it('calls a custom callback',
    /*#__PURE__*/
    (0, _asyncToGenerator2.default)(
    /*#__PURE__*/
    _regenerator.default.mark(function _callee4() {
      var cb;
      return _regenerator.default.wrap(function _callee4$(_context4) {
        while (1) {
          switch (_context4.prev = _context4.next) {
            case 0:
              cb = sinon.stub();
              _Fetcher.default.fakeFetch = (0, _fakeFetch.default)((0, _jsonify.jsoniblePromise)({
                id: '234',
                allow_backtracking: true,
                one_at_a_time_type: false
              }));
              _context4.next = 4;
              return (0, _taking.newQuizTakingSession)(quizSessionId, cb)(dispatchStub, getStateStub);

            case 4:
              (0, _chai.expect)(cb.called).to.be.true();

            case 5:
            case "end":
              return _context4.stop();
          }
        }
      }, _callee4);
    })));
  });
  describe('onQuizSessionReadyForTaking', function () {
    var quizSession = {};
    var actions, dispatch;
    beforeEach(function () {
      dispatch = sinon.stub();
      (0, _taking.onQuizSessionReadyForTaking)(quizSession)(dispatch);
      (0, _chai.expect)(dispatch).to.have.been.calledOnce();
      actions = dispatch.firstCall.args[0];
    });
    it('dispatches a SESSION_STARTED_OR_RESUMED_EVENT action', function () {
      (0, _chai.expect)(actions.some(function (action) {
        return action.type === _constants.SESSION_STARTED_OR_RESUMED_EVENT;
      })).to.be.true();
    });
    it('dispatches a UPDATE_QUIZ_SESSION_STATUS_ON_PAGE_LOAD action', function () {
      (0, _chai.expect)(actions.some(function (action) {
        return action.type === _constants.UPDATE_QUIZ_SESSION_STATUS_ON_PAGE_LOAD;
      })).to.be.true();
    });
  });
  describe('submitStudentAccessCode', function () {
    it('should hit the correct endpoint', function () {
      _Fetcher.default.fakeFetch = fetchStub;
      (0, _taking.submitStudentAccessCode)(quizSessionId, 'code')(dispatchStub, getStateStub);
      (0, _chai.expect)(fetchStub.calledWith('/api/quiz_sessions/42/submit_student_access_code')).to.be.true();
    });
    it('should dispatch actions to handle results',
    /*#__PURE__*/
    (0, _asyncToGenerator2.default)(
    /*#__PURE__*/
    _regenerator.default.mark(function _callee5() {
      var action;
      return _regenerator.default.wrap(function _callee5$(_context5) {
        while (1) {
          switch (_context5.prev = _context5.next) {
            case 0:
              _Fetcher.default.fakeFetch = (0, _fakeFetch.default)((0, _jsonify.jsoniblePromise)({
                id: '234',
                accepted_student_access_code: false
              }));
              _context5.next = 3;
              return (0, _taking.submitStudentAccessCode)(quizSessionId, 'code')(dispatchStub, getStateStub);

            case 3:
              action = dispatchStub.firstCall.args[0];
              (0, _chai.expect)(action.type).to.equal(_constants.SET_UI);
              (0, _chai.expect)(action.payload.key).to.equal(_constants.STUDENT_ACCESS_CODE_STATUS);

            case 6:
            case "end":
              return _context5.stop();
          }
        }
      }, _callee5);
    })));
  });
  describe('#makeSessionItemCall', function () {
    var indexGetStub = sinon.stub();
    var showGetStub = sinon.stub();

    var noopDispatch = function noopDispatch() {};

    afterEach(function () {
      indexGetStub.resetHistory();
      showGetStub.resetHistory();
    });
    it('calls getSessionItems if backtracking is allowed', function () {
      var quizSession = new _QuizSession.default({
        allowBacktracking: true,
        oneAtATimeType: 'question'
      });
      (0, _taking.makeSessionItemCall)(quizSession, indexGetStub, showGetStub)(noopDispatch);
      (0, _chai.expect)(indexGetStub.called).to.be.true();
      (0, _chai.expect)(showGetStub.called).to.be.false();
    });
    it('calls getSessionItems if oqaat is off', function () {
      var quizSession = new _QuizSession.default({
        allowBacktracking: false,
        oneAtATimeType: null
      });
      (0, _taking.makeSessionItemCall)(quizSession, indexGetStub, showGetStub)(noopDispatch);
      (0, _chai.expect)(indexGetStub.called).to.be.true();
      (0, _chai.expect)(showGetStub.called).to.be.false();
    });
    it('calls getSingleSessionItem if oqaat is on and backtracking is disabled', function () {
      var quizSession = new _QuizSession.default({
        allowBacktracking: false,
        oneAtATimeType: 'question'
      });
      (0, _taking.makeSessionItemCall)(quizSession, indexGetStub, showGetStub)(noopDispatch);
      (0, _chai.expect)(showGetStub.called).to.be.true();
      (0, _chai.expect)(indexGetStub.called).to.be.false();
    });
  });
  describe('postQuizSession', function () {
    var postQuizSessionThunk = (0, _taking.postQuizSession)(quizSessionId);

    var stubbedPostQuizSessionCall = function stubbedPostQuizSessionCall() {
      _Fetcher.default.fakeFetch = fetchStub;
      postQuizSessionThunk(dispatchStub, getStateStub);
    };

    it('should hit the right endpoint', function () {
      stubbedPostQuizSessionCall();
      (0, _chai.expect)(fetchStub.calledWith('/api/quiz_sessions/42/submit')).to.be.true();
    });

    var fakePostQuizSession = function fakePostQuizSession() {
      _Fetcher.default.fakeFetch = fakeFetch;
      return (0, _taking.postQuizSession)(quizSessionId)(dispatchStub, getStateStub);
    };

    it('should trigger the quiz submission event', function (done) {
      // testrail test_id:  C2954600
      var submitQuizSessionEventAction = (0, _taking2.submitQuizSessionEvent)();
      fakePostQuizSession().then(function () {
        checkActionDispatched(dispatchStub, submitQuizSessionEventAction);
        done();
      });
    });
    it('should notify the screenreader that the quiz was submitted', function (done) {
      fakePostQuizSession().then(function () {
        checkActionDispatched(dispatchStub, (0, _alerts.screenreaderNotification)('Quiz submitted'), [['payload', 'uuid']]);
        done();
      });
    });
  });
  describe('submitQuiz', function () {
    it('should call showSubmitConfirmModal if there are unanswered questions', function () {
      (0, _taking.submitQuiz)(quizSessionId)(dispatchStub, getStateStub);
      var showSubmitConfirmThunk = dispatchStub.firstCall.args[0];
      (0, _chai.expect)(showSubmitConfirmThunk).to.be.a('function');
      showSubmitConfirmThunk(dispatchStub, getStateStub);
      var modalAction = dispatchStub.secondCall.args[0];
      (0, _chai.expect)(modalAction.type).to.equal(_constants.OPEN_MODAL);
    });
    it('should call showSubmitConfirmModal if no unanswered questions', function () {
      var answeredState = (0, _immutable.fromJS)(fakeState).set('sessionItems', (0, _immutable.fromJS)({}));
      var getAnsweredStateStub = sinon.stub().returns(answeredState);
      (0, _taking.submitQuiz)(quizSessionId)(dispatchStub, getAnsweredStateStub);
      var showSubmitConfirmThunk = dispatchStub.firstCall.args[0];
      (0, _chai.expect)(showSubmitConfirmThunk).to.be.a('function');
      showSubmitConfirmThunk(dispatchStub, getStateStub);
      var modalAction = dispatchStub.secondCall.args[0];
      (0, _chai.expect)(modalAction.type).to.equal(_constants.OPEN_MODAL);
    });
    it('should not call showSubmitConfirmModal when overridden', function () {
      var getAnsweredStateStub = sinon.stub().returns((0, _immutable.fromJS)({}));
      (0, _taking.submitQuiz)(quizSessionId, _noop.default, true)(dispatchStub, getAnsweredStateStub);
      var postQuizThunk = dispatchStub.firstCall.args[0];
      (0, _chai.expect)(postQuizThunk).to.be.a('function');
      _Fetcher.default.fakeFetch = fetchStub;
      postQuizThunk(dispatchStub, getAnsweredStateStub);
      (0, _chai.expect)(fetchStub.calledWith('/api/quiz_sessions/42/submit')).to.be.true();
    });
  });
  describe('showSubmitConfirmModal', function () {
    it('should open modal', function () {
      (0, _taking.showSubmitConfirmModal)(quizSessionId)(dispatchStub, getStateStub);
      (0, _chai.expect)(dispatchStub.getCall(0).args[0].type).to.equal(_constants.OPEN_MODAL);
    });
    it('should call submitModal with correct message', function () {
      var state = (0, _immutable.fromJS)((0, _objectSpread2.default)({}, fakeResponseState, fakeSessionItemsState));
      (0, _taking.showSubmitConfirmModal)(quizSessionId)(dispatchStub, sinon.stub().returns(state));
      var modalContent = (0, _enzyme.mount)(dispatchStub.firstCall.args[0].payload.options.text);
      var modalText = modalContent.text();
      var unansweredList = modalContent.find('ul');
      (0, _chai.expect)(modalText).to.include('The following questions have not been answered:');
      (0, _chai.expect)(unansweredList).to.contain(_react.default.createElement("li", null, "Question 1"));
      (0, _chai.expect)(unansweredList).to.contain(_react.default.createElement("li", null, "Question 10"));
      (0, _chai.expect)(unansweredList).not.to.contain(_react.default.createElement("li", null, "Question 5"));
      (0, _chai.expect)(modalText).to.include('Are you ready to submit?');
    });
  });
  describe('closeSubmitConfigModal', function () {
    it('should close the modal', function () {
      var state = (0, _immutable.fromJS)((0, _objectSpread2.default)({}, fakeResponseState, fakeSessionItemsState));
      (0, _taking.closeSubmitConfirmModal)(quizSessionId)(dispatchStub, sinon.stub().returns(state));
      (0, _chai.expect)(dispatchStub).to.have.been.calledOnceWith({
        type: _constants.CLOSE_MODAL,
        payload: {
          title: 'Unanswered Questions!'
        }
      });
    });
  });
  describe('messageForSubmitModal', function () {
    var renderModalContent = function renderModalContent(unanswered) {
      return (0, _enzyme.mount)(_react.default.createElement("div", null, (0, _taking.messageForSubmitModal)(unanswered)));
    };

    var assertConfirmMessage = function assertConfirmMessage(unanswered) {
      it('asks if the user is ready to submit', function () {
        var modalContent = renderModalContent(unanswered);
        (0, _chai.expect)(modalContent.text()).to.include('Upon submission you will not be able to change your answers. Are you ready to submit?');
      });
    };

    context('with unanswered questions', function () {
      var unanswered = [1, 2, 3, 10];
      assertConfirmMessage(unanswered);
      it('displays a list of unanswered questions', function () {
        var modalContent = renderModalContent(unanswered);
        var unansweredList = modalContent.find('ul');
        unanswered.forEach(function (n) {
          return (0, _chai.expect)(unansweredList).to.contain(_react.default.createElement("li", null, "Question ", n));
        });
      });
    });
    context('with many unanswered questions', function () {
      var unanswered = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
      assertConfirmMessage(unanswered);
      it('warns that multiple questions have not been answered', function () {
        var modalContent = renderModalContent(unanswered);
        (0, _chai.expect)(modalContent.text()).to.include('Multiple questions have not been answered');
      });
    });
    context('with all questions answered', function () {
      assertConfirmMessage([]);
    });
  });
  describe('nextQuestion', function () {
    var quizSessionId, allowBacktracking, currentQuestionIsLast, itemId, userResponse, largeFormatResponse;
    var dispatchStub = sinon.stub();
    var fetchStub = sinon.stub();
    var submitStub = sinon.stub().returns({
      type: 'ACTION'
    });
    beforeEach(function () {
      dispatchStub.resetHistory();
      fetchStub.resetHistory();
      submitStub.resetHistory();
      quizSessionId = '33';
      allowBacktracking = null;
      currentQuestionIsLast = null;
      itemId = null;
      userResponse = null;
      largeFormatResponse = null;
    });

    var makeCall = function makeCall() {
      var submit = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : submitStub;
      var args = [quizSessionId, allowBacktracking, currentQuestionIsLast, itemId, userResponse, largeFormatResponse, submit];
      return _taking.nextQuestion.apply(void 0, args);
    };

    context('backtracking is allowed', function () {
      beforeEach(function () {
        allowBacktracking = true;
      });
      afterEach(function () {
        _Fetcher.default.fakeFetch = null;
      });
      context('when current question is last', function () {
        beforeEach(function () {
          currentQuestionIsLast = true;
        });
        it('submits the quiz', function () {
          makeCall()(dispatchStub);
          (0, _chai.expect)(dispatchStub.called).to.be.true();
          (0, _chai.expect)(submitStub.called).to.be.true();
        });
        it('does not dispatch if the submit callback does not return anything', function () {
          var submit = sinon.stub().returns(void 0);
          makeCall(submit)(dispatchStub);
          (0, _chai.expect)(submit).to.have.been.called();
          (0, _chai.expect)(dispatchStub).not.to.have.been.called();
        });
      });
      context('when current question is not last', function () {
        it('dispatches a backtrackingNextQuestion action', function () {
          currentQuestionIsLast = false;
          makeCall()(dispatchStub);
          (0, _chai.expect)(dispatchStub.calledWith((0, _taking2.backtrackingNextQuestion)())).to.be.true();
        });
      });
    });
    context('backtracking is not allowed', function () {
      beforeEach(function () {
        allowBacktracking = false;
      });
      context('itemId is blank', function () {
        it('makes a post request to the correct endpoint with no data', function () {
          _Fetcher.default.fakeFetch = fetchStub;
          makeCall()(dispatchStub);
          var callArgs = fetchStub.firstCall.args;
          (0, _chai.expect)(callArgs[0].match(/33\/session_item_responses\/single_response_submit/)).to.exist();
          (0, _chai.expect)(callArgs[1].method).to.eq('POST');
          (0, _chai.expect)(callArgs[1].body).to.be.undefined();
        });
        it('sets the current session item if an item is returned from the endpoint',
        /*#__PURE__*/
        (0, _asyncToGenerator2.default)(
        /*#__PURE__*/
        _regenerator.default.mark(function _callee6() {
          var item, action, args;
          return _regenerator.default.wrap(function _callee6$(_context6) {
            while (1) {
              switch (_context6.prev = _context6.next) {
                case 0:
                  item = {
                    position: 5
                  };
                  _Fetcher.default.fakeFetch = (0, _fakeFetch.default)((0, _jsonify.jsoniblePromise)(item, {
                    status: 200
                  }));
                  action = (0, _taking2.setCurrentSessionItemPosition)(item.position);
                  _context6.next = 5;
                  return makeCall()(dispatchStub);

                case 5:
                  args = dispatchStub.firstCall.args;
                  (0, _chai.expect)(args[0][0][0].type).to.eql(_constants.ADD_SESSION_ITEMS);
                  (0, _chai.expect)(args[0][1]).to.eql(action);

                case 8:
                case "end":
                  return _context6.stop();
              }
            }
          }, _callee6);
        })));
      });
      context('itemId is present', function () {
        beforeEach(function () {
          itemId = '66';
          userResponse = {
            value: 'hello'
          };
          largeFormatResponse = {
            value: 'goodbye'
          };
        });
        it('makes a post request to the correct endpoint with data', function () {
          _Fetcher.default.fakeFetch = fetchStub;
          makeCall()(dispatchStub);
          var callArgs = fetchStub.firstCall.args;
          (0, _chai.expect)(callArgs[0].match(/33\/session_item_responses\/single_response_submit/)).to.exist();
          (0, _chai.expect)(callArgs[1].method).to.eq('POST');
          (0, _chai.expect)(callArgs[1].body).to.eq(JSON.stringify({
            sessionItemResponse: {
              itemId: '66',
              userResponse: {
                value: 'hello'
              },
              largeFormatResponse: {
                value: 'goodbye'
              }
            }
          }));
        });
      });
    });
  });
});