optimizely-oui
Version:
Optimizely's Component Library.
405 lines (351 loc) • 18.9 kB
JavaScript
;
var _react = _interopRequireDefault(require("react"));
var _immutable = _interopRequireDefault(require("immutable"));
var _reactDndTestBackend = _interopRequireDefault(require("react-dnd-test-backend"));
var _enzyme = require("enzyme");
var _reactDnd = require("react-dnd");
var _index = require("../index");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
// Sortable component requires a test HTML5 backend to render in unit tests
var Sortable = (0, _reactDnd.DragDropContext)(_reactDndTestBackend["default"])(_index.UnwrappedSortable);
var normalSortableData = _immutable["default"].fromJS([{
id: 1,
type: "item",
text: "Item A"
}, {
id: 2,
type: "item",
text: "Item B"
}, {
id: 3,
type: "item",
text: "Item C"
}, {
id: 4,
type: "item",
text: "Item D"
}, {
id: 5,
type: "item",
text: "Item E"
}]);
var groupedSortableData = _immutable["default"].fromJS([{
id: 1,
type: "item",
text: "Item A"
}, {
id: 2,
type: "item",
text: "Item B"
}, [{
id: 4,
type: "item",
text: "Item C"
}, {
id: 5,
type: "item",
text: "Item D"
}, {
id: 6,
type: "item",
text: "Item E"
}]]);
var renderItem = function renderItem(_ref) {
var item = _ref.item,
connectDragSource = _ref.connectDragSource;
return connectDragSource(_react["default"].createElement("div", null, item.get("text")));
};
describe("components/Sortable", function () {
var spyObj;
beforeEach(function () {
spyObj = {
changeHandler: function changeHandler() {
return null;
}
};
spyOn(spyObj, "changeHandler").and.stub();
});
describe("Normal Sorting", function () {
var component; // eslint-disable-line
beforeEach(function () {
component = (0, _enzyme.mount)(_react["default"].createElement(Sortable, {
defaultValue: normalSortableData,
renderItem: renderItem,
allowGrouping: false,
onChange: spyObj.changeHandler
}));
});
it("should render all draggable items in order", function () {
var itemA = component.find('[data-test-section="sortable-item-0"]');
expect(itemA.length).toBe(1);
expect(itemA.text()).toContain(normalSortableData.getIn([0, "text"]));
var itemB = component.find('[data-test-section="sortable-item-1"]');
expect(itemB.length).toBe(1);
expect(itemB.text()).toContain(normalSortableData.getIn([1, "text"]));
var itemC = component.find('[data-test-section="sortable-item-2"]');
expect(itemC.length).toBe(1);
expect(itemC.text()).toContain(normalSortableData.getIn([2, "text"]));
var itemD = component.find('[data-test-section="sortable-item-3"]');
expect(itemD.length).toBe(1);
expect(itemD.text()).toContain(normalSortableData.getIn([3, "text"]));
var itemE = component.find('[data-test-section="sortable-item-4"]');
expect(itemE.length).toBe(1);
expect(itemE.text()).toContain(normalSortableData.getIn([4, "text"]));
});
it("should allow items to be dragged and reordered", function () {
var backend = component.instance().getManager().getBackend();
var sourceItem = component.find('[data-test-section="sortable-item-0"]').closest("DragSource(SortableItem)");
expect(sourceItem.length).toBe(1);
var destinationTarget = component.find('[data-test-section="sortable-target-3"]').closest("DropTarget(SortTarget)");
expect(destinationTarget.length).toBe(1);
backend.simulateBeginDrag([sourceItem.instance().getHandlerId()]);
backend.simulateHover([destinationTarget.instance().getHandlerId()]);
backend.simulateDrop();
backend.simulateEndDrag();
component.update(); // Expect that the change callback was invoked
expect(spyObj.changeHandler.calls.count()).toBe(1); // Expect that the callback received a reordered result
var stateAfterDragging = spyObj.changeHandler.calls.first().args[0];
expect(stateAfterDragging.size).toBe(normalSortableData.size);
expect(stateAfterDragging.map(function (item) {
return item.get("id");
}).toJS()).toEqual([2, 3, 1, 4, 5]); // Expect that the list was rerendered with the new order
var itemA = component.find('[data-test-section="sortable-item-2"]');
expect(itemA.length).toBe(1);
expect(itemA.text()).toContain(normalSortableData.getIn([0, "text"]));
});
it("should render preview of item in drag layer when dragging", function () {
var backend = component.instance().getManager().getBackend();
var sourceItem = component.find('[data-test-section="sortable-item-0"]').closest("DragSource(SortableItem)");
expect(sourceItem.length).toBe(1);
var destinationTarget = component.find('[data-test-section="sortable-target-3"]').closest("DropTarget(SortTarget)");
expect(destinationTarget.length).toBe(1); // Suspend react-dnd in a dragging state and provide fake coordinates
backend.simulateBeginDrag([sourceItem.instance().getHandlerId()], {
clientOffset: {
x: 0,
y: 0
},
getSourceClientOffset: function getSourceClientOffset() {
return {
x: 3,
y: 4
};
}
});
component.update(); // Expect that the item preview was rerendered
var previewA = component.find('[data-test-section="sortable-item-preview-0"]');
expect(previewA.length).toBe(1);
expect(previewA.text()).toContain(normalSortableData.getIn([0, "text"])); // Expect that the preview was rendered in the correct location
var previewContainer = previewA.closest(".oui-sortable__drag-preview__item");
expect(previewContainer.length).toBe(1);
expect(previewContainer.props().style).toHaveProperty("transform", "translate(3px, 4px)"); // Release dragging state
backend.simulateDrop();
backend.simulateEndDrag();
});
it("should not reorder if dragging item over its leading target", function () {
var backend = component.instance().getManager().getBackend(); // Select group containing three items
var sourceItem = component.find('[data-test-section="sortable-item-1"]').closest("DragSource(SortableItem)");
expect(sourceItem.length).toBe(1); // Select a target above group
var destinationTarget = component.find('[data-test-section="sortable-target-1"]').closest("DropTarget(SortTarget)");
expect(destinationTarget.length).toBe(1);
backend.simulateBeginDrag([sourceItem.instance().getHandlerId()]);
backend.simulateHover([destinationTarget.instance().getHandlerId()]);
backend.simulateDrop();
backend.simulateEndDrag();
component.update(); // Expect that the change callback was invoked
expect(spyObj.changeHandler.calls.count()).toBe(1); // Expect that the value was not changed
var editingState = spyObj.changeHandler.calls.first().args[0];
expect(_immutable["default"].is(editingState, groupedSortableData));
});
it("should not reorder if dragging item over its trailing target", function () {
var backend = component.instance().getManager().getBackend(); // Select group containing three items
var sourceItem = component.find('[data-test-section="sortable-item-1"]').closest("DragSource(SortableItem)");
expect(sourceItem.length).toBe(1); // Select a target above group
var destinationTarget = component.find('[data-test-section="sortable-target-2"]').closest("DropTarget(SortTarget)");
expect(destinationTarget.length).toBe(1);
backend.simulateBeginDrag([sourceItem.instance().getHandlerId()]);
backend.simulateHover([destinationTarget.instance().getHandlerId()]);
backend.simulateDrop();
backend.simulateEndDrag();
component.update(); // Expect that the change callback was invoked
expect(spyObj.changeHandler.calls.count()).toBe(1); // Expect that the value was not changed
var editingState = spyObj.changeHandler.calls.first().args[0];
expect(_immutable["default"].is(editingState, groupedSortableData));
});
it("should convert ungrouped items to groups when enabling grouping", function () {
// Expect ungrouped item to be rendered when grouping is disabled
var itemA = component.find('[data-test-section="sortable-item-0"]');
expect(itemA.length).toBe(1);
expect(itemA.text()).toContain(normalSortableData.getIn([0, "text"])); // Enable grouping
component.setProps({
allowGrouping: true
});
component.update(); // Expect that ungrouped items are automatically wrapped in groups
var groupedItemA = component.find('[data-test-section="sortable-item-0-0"]');
expect(groupedItemA.length).toBe(1);
expect(groupedItemA.text()).toContain(normalSortableData.getIn([0, "text"]));
});
});
describe("Grouped Sorting", function () {
var component; // eslint-disable-line
beforeEach(function () {
component = (0, _enzyme.mount)(_react["default"].createElement(Sortable, {
defaultValue: groupedSortableData,
renderItem: renderItem,
allowGrouping: true,
onChange: spyObj.changeHandler
}));
});
it("should render all items in groups and in order", function () {
// Automatically created groups (ungrouped items automatically grouped)
// Group 1: [ itemA ]
var itemA = component.find('[data-test-section="sortable-item-0-0"]');
expect(itemA.length).toBe(1);
expect(itemA.text()).toContain(groupedSortableData.getIn([0, "text"])); // Group 2: [ itemB ]
var itemB = component.find('[data-test-section="sortable-item-1-0"]');
expect(itemB.length).toBe(1);
expect(itemB.text()).toContain(groupedSortableData.getIn([1, "text"])); // Manually created groups (defined in groupedSortableData)
// Group 3: [ itemC, itemD, itemE ]
var itemC = component.find('[data-test-section="sortable-item-2-0"]');
expect(itemC.length).toBe(1);
expect(itemC.text()).toContain(groupedSortableData.getIn([2, 0, "text"]));
var itemD = component.find('[data-test-section="sortable-item-2-1"]');
expect(itemD.length).toBe(1);
expect(itemD.text()).toContain(groupedSortableData.getIn([2, 1, "text"]));
var itemE = component.find('[data-test-section="sortable-item-2-2"]');
expect(itemE.length).toBe(1);
expect(itemE.text()).toContain(groupedSortableData.getIn([2, 2, "text"]));
});
it("should allow items to be reordered within a group", function () {
var backend = component.instance().getManager().getBackend(); // Select item and target within the same group
var sourceItem = component.find('[data-test-section="sortable-item-2-0"]').closest("DragSource(SortableItem)");
expect(sourceItem.length).toBe(1);
var destinationTarget = component.find('[data-test-section="sortable-target-2-3"]').closest("DropTarget(SortTarget)");
expect(destinationTarget.length).toBe(1);
backend.simulateBeginDrag([sourceItem.instance().getHandlerId()]);
backend.simulateHover([destinationTarget.instance().getHandlerId()]);
backend.simulateDrop();
backend.simulateEndDrag();
component.update(); // Expect that the change callback was invoked
expect(spyObj.changeHandler.calls.count()).toBe(1); // Expect that the items in the group were reordered
var itemC = component.find('[data-test-section="sortable-item-2-0"]');
expect(itemC.length).toBe(1);
expect(itemC.text()).toContain(groupedSortableData.getIn([2, 1, "text"]));
var itemD = component.find('[data-test-section="sortable-item-2-1"]');
expect(itemD.length).toBe(1);
expect(itemD.text()).toContain(groupedSortableData.getIn([2, 2, "text"]));
var itemE = component.find('[data-test-section="sortable-item-2-2"]');
expect(itemE.length).toBe(1);
expect(itemE.text()).toContain(groupedSortableData.getIn([2, 0, "text"]));
});
it("should allow items to be dragged outside of a group", function () {
var backend = component.instance().getManager().getBackend(); // Select item in a group and a target outside of that group
var sourceItem = component.find('[data-test-section="sortable-item-2-2"]').closest("DragSource(SortableItem)");
expect(sourceItem.length).toBe(1);
var destinationTarget = component.find('[data-test-section="sortable-target-3"]').closest("DropTarget(SortTarget)");
expect(destinationTarget.length).toBe(1);
backend.simulateBeginDrag([sourceItem.instance().getHandlerId()]);
backend.simulateHover([destinationTarget.instance().getHandlerId()]);
backend.simulateDrop();
backend.simulateEndDrag();
component.update(); // Expect that the change callback was invoked
expect(spyObj.changeHandler.calls.count()).toBe(1); // Expect that item was removed from original group
var itemE = component.find('[data-test-section="sortable-item-2-2"]');
expect(itemE.length).toBe(0); // Expect that item was moved to new position and within new group
var movedItemE = component.find('[data-test-section="sortable-item-3-0"]');
expect(movedItemE.length).toBe(1);
expect(movedItemE.text()).toContain(groupedSortableData.getIn([2, 2, "text"]));
});
it("should allow groups to be reordered", function () {
var backend = component.instance().getManager().getBackend(); // Select group containing three items
var sourceGroup = component.find('[data-test-section="sortable-group-2"]').closest("DragSource(SortableGroup)");
expect(sourceGroup.length).toBe(1); // Select a target above group
var destinationTarget = component.find('[data-test-section="sortable-target-1"]').closest("DropTarget(SortTarget)");
expect(destinationTarget.length).toBe(1);
backend.simulateBeginDrag([sourceGroup.instance().getHandlerId()]);
backend.simulateHover([destinationTarget.instance().getHandlerId()]);
backend.simulateDrop();
backend.simulateEndDrag();
component.update(); // Expect that the change callback was invoked
expect(spyObj.changeHandler.calls.count()).toBe(1); // Expect that the groups were reordered and maintain item order
var itemC = component.find('[data-test-section="sortable-item-1-0"]');
expect(itemC.length).toBe(1);
expect(itemC.text()).toContain(groupedSortableData.getIn([2, 0, "text"]));
var itemD = component.find('[data-test-section="sortable-item-1-1"]');
expect(itemD.length).toBe(1);
expect(itemD.text()).toContain(groupedSortableData.getIn([2, 1, "text"]));
var itemE = component.find('[data-test-section="sortable-item-1-2"]');
expect(itemE.length).toBe(1);
expect(itemE.text()).toContain(groupedSortableData.getIn([2, 2, "text"]));
});
it("should not reorder if dragging group over itself", function () {
var backend = component.instance().getManager().getBackend(); // Select group containing three items
var sourceGroup = component.find('[data-test-section="sortable-group-2"]').closest("DragSource(SortableGroup)");
expect(sourceGroup.length).toBe(1); // Select a target above group
var destinationTarget = component.find('[data-test-section="sortable-target-2"]').closest("DropTarget(SortTarget)");
expect(destinationTarget.length).toBe(1);
backend.simulateBeginDrag([sourceGroup.instance().getHandlerId()]);
backend.simulateHover([destinationTarget.instance().getHandlerId()]);
backend.simulateDrop();
backend.simulateEndDrag();
component.update(); // Expect that the change callback was invoked
expect(spyObj.changeHandler.calls.count()).toBe(1); // Expect that the value was not changed
var editingState = spyObj.changeHandler.calls.first().args[0];
expect(_immutable["default"].is(editingState.get(2), groupedSortableData.get(2)));
});
it("should not reorder if dragging group over another group", function () {
var backend = component.instance().getManager().getBackend(); // Select group containing three items
var sourceGroup = component.find('[data-test-section="sortable-group-2"]').closest("DragSource(SortableGroup)");
expect(sourceGroup.length).toBe(1); // Select a target within a different group
var destinationTarget = component.find('[data-test-section="sortable-target-1-0"]').closest("DropTarget(SortTarget)");
expect(destinationTarget.length).toBe(1);
backend.simulateBeginDrag([sourceGroup.instance().getHandlerId()]);
backend.simulateHover([destinationTarget.instance().getHandlerId()]);
backend.simulateDrop();
backend.simulateEndDrag();
component.update(); // Expect that the change callback was invoked
expect(spyObj.changeHandler.calls.count()).toBe(1); // Expect that the value was not changed
var editingState = spyObj.changeHandler.calls.first().args[0];
expect(_immutable["default"].is(editingState.get(2), groupedSortableData.get(2)));
});
it("should extract all items from groups when grouping is disabled", function () {
// Expect grouped item to be rendered when grouping is enabled
var itemA = component.find('[data-test-section="sortable-item-0-0"]');
expect(itemA.length).toBe(1);
expect(itemA.text()).toContain(groupedSortableData.getIn([0, "text"])); // Disable grouping
component.setProps({
allowGrouping: false
});
component.update(); // Expect that grouped items are automatically extracted from groups
var ungroupedItemA = component.find('[data-test-section="sortable-item-0"]');
expect(ungroupedItemA.length).toBe(1);
expect(ungroupedItemA.text()).toContain(groupedSortableData.getIn([0, "text"]));
});
});
describe("when given a className", function () {
it("appends it to the root element", function () {
var component = (0, _enzyme.mount)(_react["default"].createElement(Sortable, {
className: "extra-class",
defaultValue: normalSortableData,
renderItem: renderItem,
allowGrouping: false,
onChange: spyObj.changeHandler
}));
expect(component.prop("className").includes("extra-class")).toBe(true);
});
});
describe("when given an unknown prop", function () {
it("passes it to the root element", function () {
// @ts-ignore: `unknownProps` is not part of any typed interface and therefore a good test value.
var component = (0, _enzyme.mount)(_react["default"].createElement(Sortable, {
unknownProp: "some value",
defaultValue: normalSortableData,
renderItem: renderItem,
allowGrouping: false,
onChange: spyObj.changeHandler
}));
expect(component).toHaveProp({
unknownProp: "some value"
});
});
});
});