"use strict";

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

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

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

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

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

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

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

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

var _immutable = require("immutable");

var _dragAndDropUtils = require("../dragAndDropUtils");

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

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

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

var TestComponent =
/*#__PURE__*/
function (_Component) {
  (0, _inherits2.default)(TestComponent, _Component);

  function TestComponent() {
    var _getPrototypeOf2;

    var _this;

    (0, _classCallCheck2.default)(this, TestComponent);

    for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
      args[_key] = arguments[_key];
    }

    _this = (0, _possibleConstructorReturn2.default)(this, (_getPrototypeOf2 = (0, _getPrototypeOf3.default)(TestComponent)).call.apply(_getPrototypeOf2, [this].concat(args)));

    _this.storeStartQuizEntriesRef = function (node) {
      _this.startQuizEntries = node;
    };

    _this.storeQuizEntriesRef = function (node) {
      _this.quizEntries = node;
    };

    _this.storeEndQuizEntriesRef = function (node) {
      _this.endQuizEntries = node;
    };

    return _this;
  }

  (0, _createClass2.default)(TestComponent, [{
    key: "render",
    value: function render() {
      var style = {
        width: '100px',
        height: '100px'
      };
      return _react.default.createElement("div", null, _react.default.createElement("div", {
        style: style,
        ref: this.storeStartQuizEntriesRef
      }), _react.default.createElement("div", {
        style: style,
        ref: this.storeQuizEntriesRef
      }), _react.default.createElement("div", {
        style: style,
        ref: this.storeEndQuizEntriesRef
      }));
    }
  }]);
  TestComponent.displayName = "TestComponent";
  return TestComponent;
}(_react.Component);

describe('dragAndDropUtils', function () {
  var testbed = createTestbed(TestComponent, {});
  var windowOverrideIE = {
    navigator: {
      userAgent: ['Edge/', 'Trident/', 'MSIE ']
    }
  };
  var windowOverrideChrome = {
    navigator: {
      userAgent: ['Chrome']
    }
  };
  describe('#usingIE', function () {
    it('returns true if using IE or Edge', function () {
      var isIE = (0, _dragAndDropUtils.usingIE)(windowOverrideIE);
      expect(isIE).to.be.true();
    });
    it('returns false if not using IE or Edge', function () {
      var isIE = (0, _dragAndDropUtils.usingIE)(windowOverrideChrome);
      expect(isIE).to.be.false();
    });
  });
  describe('#chooseDragConnection', function () {
    it('chooses dragSource when using IE or Edge', function () {
      var dragSource = 1;
      var dragPreview = 2;
      var chosenConnection = (0, _dragAndDropUtils.chooseDragConnection)(dragSource, dragPreview, windowOverrideIE);
      expect(chosenConnection).to.be.equal(dragSource);
    });
    it('chooses dragPreview when using IE or Edge', function () {
      var dragSource = 1;
      var dragPreview = 2;
      var chosenConnection = (0, _dragAndDropUtils.chooseDragConnection)(dragSource, dragPreview, windowOverrideChrome);
      expect(chosenConnection).to.be.equal(dragPreview);
    });
  });
  describe('#getBoundsForComponent', function () {
    it('returns the bounds of the corresponding DOM element', function () {
      testbed.render();
      var bodyMargin = parseFloat(window.getComputedStyle(document.body).margin);

      var _getBoundsForComponen = (0, _dragAndDropUtils.getBoundsForComponent)(testbed.subject.quizEntries),
          top = _getBoundsForComponen.top,
          bottom = _getBoundsForComponen.bottom,
          right = _getBoundsForComponen.right,
          left = _getBoundsForComponen.left;

      expect(top).to.equal(100 + bodyMargin);
      expect(bottom).to.equal(200 + bodyMargin);
      expect(right).to.equal(100 + bodyMargin);
      expect(left).to.equal(bodyMargin);
    });
  });
  describe('#posObjFromQuizEntry', function () {
    it('returns a correct newPositionObj when from above and above half', function () {
      testbed.render();

      var quizEntryDragging = _QuizEntry.default.create({
        position: 1
      });

      var quizEntryHovered = _QuizEntry.default.create({
        position: 2
      });

      var mousePos = {
        x: 50,
        y: 140
      };
      var posObj = (0, _dragAndDropUtils.posObjFromQuizEntry)(quizEntryDragging, quizEntryHovered, mousePos, testbed.subject.quizEntries, false);
      expect(posObj).to.deep.equal({
        position: 2,
        intoEmptyStimulus: false,
        aboveHalf: true,
        fromAbove: true
      });
    });
    it('returns a correct newPositionObj when from above and below half', function () {
      testbed.render();

      var quizEntryDragging = _QuizEntry.default.create({
        position: 1
      });

      var quizEntryHovered = _QuizEntry.default.create({
        position: 2
      });

      var mousePos = {
        x: 50,
        y: 190
      };
      var posObj = (0, _dragAndDropUtils.posObjFromQuizEntry)(quizEntryDragging, quizEntryHovered, mousePos, testbed.subject.quizEntries, false);
      expect(posObj).to.deep.equal({
        position: 2,
        intoEmptyStimulus: false,
        aboveHalf: false,
        fromAbove: true
      });
    });
    it('returns a correct newPositionObj when from below and above half', function () {
      testbed.render();

      var quizEntryDragging = _QuizEntry.default.create({
        position: 2
      });

      var quizEntryHovered = _QuizEntry.default.create({
        position: 1
      });

      var mousePos = {
        x: 50,
        y: 140
      };
      var posObj = (0, _dragAndDropUtils.posObjFromQuizEntry)(quizEntryDragging, quizEntryHovered, mousePos, testbed.subject.quizEntries, false);
      expect(posObj).to.deep.equal({
        position: 1,
        intoEmptyStimulus: false,
        aboveHalf: true,
        fromAbove: false
      });
    });
    it('returns a correct newPositionObj when from below and below half', function () {
      testbed.render();

      var quizEntryDragging = _QuizEntry.default.create({
        position: 2
      });

      var quizEntryHovered = _QuizEntry.default.create({
        position: 1
      });

      var mousePos = {
        x: 50,
        y: 160
      };
      var posObj = (0, _dragAndDropUtils.posObjFromQuizEntry)(quizEntryDragging, quizEntryHovered, mousePos, testbed.subject.quizEntries, false);
      expect(posObj).to.deep.equal({
        position: 1,
        intoEmptyStimulus: false,
        aboveHalf: false,
        fromAbove: false
      });
    });
    context('into stimulus', function () {
      it('correctly indicates intoEmptyStimulus when on right half', function () {
        testbed.render();

        var quizEntryDragging = _QuizEntry.default.create({
          position: 1
        });

        var quizEntryHovered = _QuizEntry.default.create({
          position: 2,
          entryType: 'Stimulus'
        });

        var mousePos = {
          x: 70,
          y: 165
        };
        var posObj = (0, _dragAndDropUtils.posObjFromQuizEntry)(quizEntryDragging, quizEntryHovered, mousePos, testbed.subject.quizEntries, false);
        expect(posObj).to.deep.equal({
          position: 2,
          intoEmptyStimulus: true,
          aboveHalf: false,
          fromAbove: true
        });
      });
      it('should not be intoEmptyStimulus when on right half when not deep', function () {
        testbed.render();

        var quizEntryDragging = _QuizEntry.default.create({
          position: 1
        });

        var quizEntryHovered = _QuizEntry.default.create({
          position: 2,
          entryType: 'Stimulus'
        });

        var mousePos = {
          x: 70,
          y: 180
        };
        var posObj = (0, _dragAndDropUtils.posObjFromQuizEntry)(quizEntryDragging, quizEntryHovered, mousePos, testbed.subject.quizEntries, false);
        expect(posObj).to.deep.equal({
          position: 2,
          intoEmptyStimulus: false,
          aboveHalf: false,
          fromAbove: true
        });
      });
      it('does not return intoEmptyStimulus if on left half', function () {
        testbed.render();

        var quizEntryDragging = _QuizEntry.default.create({
          position: 1
        });

        var quizEntryHovered = _QuizEntry.default.create({
          position: 2,
          entryType: 'Stimulus'
        });

        var mousePos = {
          x: 30,
          y: 165
        };
        var posObj = (0, _dragAndDropUtils.posObjFromQuizEntry)(quizEntryDragging, quizEntryHovered, mousePos, testbed.subject.quizEntries, false);
        expect(posObj).to.deep.equal({
          position: 2,
          intoEmptyStimulus: false,
          aboveHalf: false,
          fromAbove: true
        });
      });
      it('returns null if not empty and on right half', function () {
        testbed.render();

        var quizEntryDragging = _QuizEntry.default.create({
          position: 1
        });

        var quizEntryHovered = _QuizEntry.default.create({
          position: 2,
          entryType: 'Stimulus'
        });

        sinon.stub(quizEntryHovered, 'getNestedEntries').returns((0, _immutable.List)([1, 2, 3]));
        var mousePos = {
          x: 70,
          y: 155
        };
        var posObj = (0, _dragAndDropUtils.posObjFromQuizEntry)(quizEntryDragging, quizEntryHovered, mousePos, testbed.subject.quizEntries, false);
        expect(posObj).to.be.null();
      });
      it('does not return null if not empty and on right half, but not deep', function () {
        testbed.render();

        var quizEntryDragging = _QuizEntry.default.create({
          position: 1
        });

        var quizEntryHovered = _QuizEntry.default.create({
          position: 2,
          entryType: 'Stimulus'
        });

        sinon.stub(quizEntryHovered, 'getNestedEntries').returns((0, _immutable.List)([1, 2, 3]));
        var mousePos = {
          x: 70,
          y: 180
        };
        var posObj = (0, _dragAndDropUtils.posObjFromQuizEntry)(quizEntryDragging, quizEntryHovered, mousePos, testbed.subject.quizEntries, false);
        expect(posObj).to.deep.equal({
          position: 2,
          intoEmptyStimulus: false,
          aboveHalf: false,
          fromAbove: true
        });
      });
      it('returns null if dragging stimulus into stimulus', function () {
        testbed.render();

        var quizEntryDragging = _QuizEntry.default.create({
          position: 1,
          entryType: 'Stimulus'
        });

        var quizEntryHovered = _QuizEntry.default.create({
          position: 2,
          entryType: 'Item',
          stimulusQuizEntryId: '5'
        });

        sinon.stub(quizEntryHovered, 'getNestedEntries').returns((0, _immutable.List)([1, 2, 3]));
        var mousePos = {
          x: 70,
          y: 155
        };
        var posObj = (0, _dragAndDropUtils.posObjFromQuizEntry)(quizEntryDragging, quizEntryHovered, mousePos, testbed.subject.quizEntries, false);
        expect(posObj).to.be.null();
      });
    });
  });
  describe('#posObjFromNonQuizEntry', function () {
    it('returns the right positionObj if above all quizEntries', function () {
      testbed.render();
      var mousePos = {
        x: 50,
        y: 40
      };
      var _testbed$subject = testbed.subject,
          startQuizEntries = _testbed$subject.startQuizEntries,
          endQuizEntries = _testbed$subject.endQuizEntries;

      var quizEntryDragging = _QuizEntry.default.create({
        position: 1
      });

      var posObj = (0, _dragAndDropUtils.posObjFromNonQuizEntry)(quizEntryDragging, startQuizEntries, endQuizEntries, mousePos, (0, _immutable.List)());
      expect(posObj).to.deep.equal({
        position: 1,
        intoEmptyStimulus: false,
        aboveHalf: true,
        fromAbove: false
      });
    });
    it('returns the right positionObj if below all quizEntries and last quizEntry is not in stimulus', function () {
      testbed.render();
      var mousePos = {
        x: 50,
        y: 330
      };
      var _testbed$subject2 = testbed.subject,
          startQuizEntries = _testbed$subject2.startQuizEntries,
          endQuizEntries = _testbed$subject2.endQuizEntries;
      var quizEntries = (0, _immutable.List)([new _QuizEntry.default({
        position: 1
      }), new _QuizEntry.default({
        position: 2
      }), new _QuizEntry.default({
        position: 3
      })]);

      var quizEntryDragging = _QuizEntry.default.create({
        position: 1
      });

      var posObj = (0, _dragAndDropUtils.posObjFromNonQuizEntry)(quizEntryDragging, startQuizEntries, endQuizEntries, mousePos, quizEntries);
      expect(posObj).to.deep.equal({
        position: 3,
        intoEmptyStimulus: false,
        aboveHalf: false,
        fromAbove: true
      });
    });
    it('returns the right positionObj if below all quizEntries and last quizEntry is in stimulus', function () {
      testbed.render();
      var mousePos = {
        x: 50,
        y: 330
      };
      var _testbed$subject3 = testbed.subject,
          startQuizEntries = _testbed$subject3.startQuizEntries,
          endQuizEntries = _testbed$subject3.endQuizEntries;
      var quizEntries = (0, _immutable.List)([new _QuizEntry.default({
        position: 1
      }), new _QuizEntry.default({
        id: '4',
        position: 2
      }), new _QuizEntry.default({
        stimulusQuizEntryId: '4',
        position: 3
      })]);

      var quizEntryDragging = _QuizEntry.default.create({
        position: 1
      });

      var posObj = (0, _dragAndDropUtils.posObjFromNonQuizEntry)(quizEntryDragging, startQuizEntries, endQuizEntries, mousePos, quizEntries);
      expect(posObj).to.deep.equal({
        position: 2,
        intoEmptyStimulus: false,
        aboveHalf: false,
        fromAbove: true
      });
    });
    it('returns null if between top and bottom', function () {
      testbed.render();
      var mousePos = {
        x: 50,
        y: 150
      };
      var _testbed$subject4 = testbed.subject,
          startQuizEntries = _testbed$subject4.startQuizEntries,
          endQuizEntries = _testbed$subject4.endQuizEntries;

      var quizEntryDragging = _QuizEntry.default.create({
        position: 1
      });

      var posObj = (0, _dragAndDropUtils.posObjFromNonQuizEntry)(quizEntryDragging, startQuizEntries, endQuizEntries, mousePos, (0, _immutable.List)());
      expect(posObj).to.be.null();
    });
  });
  var moveQuizEntryStub = sinon.stub();
  var newHoverPositionStub = sinon.stub();
  var setUiStub = sinon.stub();
  var openMoveImmutableModalStub = sinon.stub();
  afterEach(function () {
    moveQuizEntryStub.resetHistory();
    newHoverPositionStub.resetHistory();
    setUiStub.resetHistory();
    openMoveImmutableModalStub.resetHistory();
  });
  describe('#onQuizEntryHover', function () {
    var props = {
      newHoverPosition: newHoverPositionStub
    };
    var examplePosObj = {
      position: 2,
      aboveHalf: true,
      fromAbove: false,
      intoEmptyStimulus: false
    };
    var monitor = {
      getItem: function getItem() {
        return {
          position: 3
        };
      }
    };
    it('returns null if inSidebar and sidebar is closed', function () {
      testbed.render();
      var customProps = {
        newHoverPosition: newHoverPositionStub,
        sidebarOpen: false
      };
      (0, _dragAndDropUtils.onQuizEntryHover)(customProps, monitor, testbed.subject.quizEntries, _constants.SIDEBAR_ITEM_REF);
      expect(newHoverPositionStub).to.have.not.been.called();
    });
    it('calls the newHoverPosition action with correct arguments', function () {
      testbed.render();
      var createPosStub = sinon.stub().returns(examplePosObj);
      (0, _dragAndDropUtils.onQuizEntryHover)(props, monitor, testbed.subject.quizEntries, 'quiz_entry', createPosStub);
      var newPosition = newHoverPositionStub.getCall(0).args[0];
      expect(newPosition).to.deep.equal(examplePosObj);
    });
    it('does not call the action if nothing has changed', function () {
      testbed.render();
      var createPosStub = sinon.stub().returns(examplePosObj);
      var monitor = {
        getItem: function getItem() {
          return examplePosObj;
        }
      };
      (0, _dragAndDropUtils.onQuizEntryHover)(props, monitor, testbed.subject.quizEntries, 'quiz_entry', createPosStub);
      expect(newHoverPositionStub).to.have.not.been.called();
    });
  });
  describe('onQuizEntryDrop', function () {
    var targetQuizEntry = _QuizEntry.default.create({
      position: 2,
      id: 2
    });

    var props = {
      moveQuizEntry: moveQuizEntryStub,
      setUi: setUiStub,
      openMoveImmutableModal: openMoveImmutableModalStub,
      quizEntry: targetQuizEntry,
      quizEntries: (0, _immutable.List)([targetQuizEntry]),
      quizId: 1,
      dndPositionObj: (0, _immutable.Map)({
        position: 2,
        aboveHalf: false,
        fromAbove: true,
        intoEmptyStimulus: false
      })
    };
    var getDropResultStub = sinon.stub().returns({});
    var sharedMonitor = {
      getDropResult: getDropResultStub,
      getItem: function getItem() {
        return {
          quizEntry: _QuizEntry.default.create({
            position: 1,
            id: 1
          }) // moving quizEntry

        };
      }
    };
    it('move quiz entry action called with correct moveTo position', function () {
      (0, _dragAndDropUtils.onQuizEntryDrop)(props, sharedMonitor, null, 'refname');
      expect(moveQuizEntryStub.getCall(0).args[1]).to.be.equal(2);
    });
    it('move quiz entry action called with correct item id', function () {
      (0, _dragAndDropUtils.onQuizEntryDrop)(props, sharedMonitor, null, 'refname');
      expect(moveQuizEntryStub.getCall(0).args[3]).to.be.equal(1);
    });
    it('does not call any action if inSidebar and sidebar is not open', function () {
      var customProps = Object.assign({}, props, {
        sidebarOpen: false
      });
      (0, _dragAndDropUtils.onQuizEntryDrop)(customProps, sharedMonitor, null, _constants.SIDEBAR_ITEM_REF);
      expect(moveQuizEntryStub).to.have.not.been.called();
    });
    it('does not call any action if drop was already handled', function () {
      var monitor = {
        getItem: function getItem() {
          return {
            quizEntry: _QuizEntry.default.create()
          };
        },
        getDropResult: function getDropResult() {
          return {
            handledDrop: true
          };
        }
      };
      (0, _dragAndDropUtils.onQuizEntryDrop)(props, monitor, null, 'refname');
      expect(moveQuizEntryStub).to.have.not.been.called();
    });
    it('does not move item if moveTo position and stimulusQuizEntryId are unchanged', function () {
      var monitor = {
        getDropResult: getDropResultStub,
        getItem: function getItem() {
          return {
            quizEntry: _QuizEntry.default.create({
              position: 2,
              id: 1
            })
          };
        }
      };
      (0, _dragAndDropUtils.onQuizEntryDrop)(props, monitor, null, 'refname');
      expect(moveQuizEntryStub).to.have.not.been.called();
    });
    it('does not move stimulus if moving to same position', function () {
      var quizEntry = _QuizEntry.default.create({
        position: 2,
        id: 2,
        entryType: 'Stimulus'
      });

      sinon.stub(quizEntry, 'getNestedEntries').returns((0, _immutable.List)([1, 2, 3]));
      var monitor = {
        getDropResult: getDropResultStub,
        getItem: function getItem() {
          return {
            quizEntry: quizEntry
          };
        }
      };
      var customProps = Object.assign({}, props, {
        quizEntry: quizEntry
      });
      (0, _dragAndDropUtils.onQuizEntryDrop)(customProps, monitor, null, 'refname');
      expect(moveQuizEntryStub).to.have.not.been.called();
    });
    context('with an immutable item', function () {
      var immutableQE = _QuizEntry.default.create({
        position: 3,
        id: 2,
        stimulusQuizEntryId: '4',
        entryType: 'Item'
      });

      sinon.stub(immutableQE, 'getEntry').returns(new _Item.default({
        status: 'immutable'
      }));
      var monitor = {
        getDropResult: getDropResultStub,
        getItem: function getItem() {
          return {
            quizEntry: immutableQE
          };
        }
      };
      it('sets move immutable data correctly', function () {
        (0, _dragAndDropUtils.onQuizEntryDrop)(props, monitor, null, 'refname');
        expect(setUiStub.firstCall.args[1].toJS()).to.deep.eq({
          movedInSidebar: false,
          quizId: 1,
          position: 2,
          stimulusQuizEntryId: '',
          quizEntryId: 2
        });
      });
      it('opens the moveImmutable modal', function () {
        (0, _dragAndDropUtils.onQuizEntryDrop)(props, monitor, null, 'refname');
        expect(openMoveImmutableModalStub).to.be.called();
      });
      it('does not call moveQuizEntry', function () {
        (0, _dragAndDropUtils.onQuizEntryDrop)(props, monitor, null, 'refname');
        expect(moveQuizEntryStub).not.to.have.been.called();
      });
    });
    context('with temporary item', function () {
      var moveQuizEntryPromise = function moveQuizEntryPromise(a, b, c, d, moveTempItemCb) {
        moveTempItemCb();
      };

      var moveTempItemStub = sinon.stub();
      var quizEntriesWithTemporaryItem = (0, _immutable.List)([_QuizEntry.default.create({
        id: 1,
        position: 1
      }), _QuizEntry.default.create({
        id: 2,
        position: 2
      }), _QuizEntry.default.create({
        id: _constants.TEMPORARY_QUIZ_ENTRY_ID,
        position: 3
      }), _QuizEntry.default.create({
        id: 4,
        position: 4
      }), _QuizEntry.default.create({
        id: 5,
        position: 5
      })]);
      afterEach(function () {
        moveTempItemStub.resetHistory();
      });

      var moveFromTo = function moveFromTo(fromPosition, toPosition) {
        var monitor = {
          getDropResult: getDropResultStub,
          getItem: function getItem() {
            return {
              quizEntry: _QuizEntry.default.create({
                position: fromPosition,
                id: fromPosition === 3 ? _constants.TEMPORARY_QUIZ_ENTRY_ID : fromPosition
              })
            };
          }
        };
        var propsWithTempItem = {
          moveQuizEntry: moveQuizEntryPromise,
          moveTemporaryQuizEntry: moveTempItemStub,
          quizEntries: quizEntriesWithTemporaryItem,
          newHoverPosition: newHoverPositionStub,
          dndPositionObj: (0, _immutable.Map)({
            position: toPosition,
            aboveHalf: true,
            fromAbove: false,
            intoEmptyStimulus: false
          }),
          setUi: function setUi() {}
        };
        (0, _dragAndDropUtils.onQuizEntryDrop)(propsWithTempItem, monitor, null, 'refname');
      };

      it('moves the temporary item up when an item above it is dropped on it', function () {
        moveFromTo(1, 3);
        expect(moveTempItemStub.calledWith('up')).to.be.true();
      });
      it('moves the temporary item up when an item above it is dropped passed it', function () {
        moveFromTo(1, 5);
        expect(moveTempItemStub.calledWith('up')).to.be.true();
      });
      it('moves the temporary item down when an item below it is dropped on it', function () {
        moveFromTo(4, 3);
        expect(moveTempItemStub.calledWith('down')).to.be.true();
      });
      it('moves the temporary item down when an item below it is dropped passed it', function () {
        moveFromTo(4, 2);
        expect(moveTempItemStub.calledWith('down')).to.be.true();
      });
      it('does not move the temporary item when an item above it is dropped above it', function () {
        moveFromTo(1, 2);
        expect(moveTempItemStub.called).to.be.false();
      });
      it('does not move the temporary item when an item below it is dropped below it', function () {
        moveFromTo(4, 5);
        expect(moveTempItemStub.called).to.be.false();
      });
      it('moves the temporary item to a specific position when it is being dragged', function () {
        moveFromTo(3, 1);
        expect(moveTempItemStub.calledWith(1)).to.be.true();
      });
    });
  });
});