模拟拖拽,反应testutils不起作用

时间:2015-08-16 09:41:36

标签: javascript drag-and-drop reactjs karma-jasmine reactjs-testutils

我尝试使用jasmine,karma和React TestUtils测试我的ReactJS mixin的拖放功能。

没有抛出异常但是在调试时似乎在模拟事件时绑定到事件监听器的函数没有被执行。

你可以在这里克隆它: https://github.com/itsh01/react-dragdrop/tree/testing-simutale-events

非常感谢你。

这是我的测试:

beforeEach(function () {

    var CompDrag = React.createClass({
        mixins: [DragDropMixin],
        dragDrop: function dragDrop() {
            return {
                draggable: true,
                dropType: 'test',
                dataTransfer: {
                    test: true
                }
            };
        },
        render: function render() {
            return React.createElement('div', {});
        }
    });

    var CompDrop = React.createClass({
        mixins: [DragDropMixin],
        dragDrop: function dragDrop() {
            var self = this;
            return {
                droppable: true,
                acceptableTypes: ['test'],
                drop: function (data) {
                    self.setState(data);
                }
            };
        },
        render: function render() {
            return React.createElement('div', {});
        }
    });

    elementDrag = React.createElement(CompDrag, {});
    elementDrop = React.createElement(CompDrop, {});

});

...

it('should attach drop functionality when configured', function () {
    var renderedDrag = TestUtils.renderIntoDocument(elementDrag);
    var renderedDrop = TestUtils.renderIntoDocument(elementDrop);
    var nodeDrag = renderedDrag.getDOMNode();
    var nodeDrop = renderedDrop.getDOMNode();
    var mockEvent = {
        preventDefault: function () {},
        dataTransfer: {
            types: ["objtopass"],
            setData: function () {},
            getData: function () {
                return JSON.parse({
                    dropType: 'test',
                    data: {
                        test: true
                    }
                });
            }
        }
    };

    TestUtils.SimulateNative.dragStart(nodeDrag, mockEvent);
    TestUtils.Simulate.dragOver(nodeDrop, mockEvent);
    TestUtils.Simulate.drop(nodeDrop, mockEvent);

    expect(renderedDrop.state).not.toBeNull();
});

这是mixin:

'use strict';

var _ = lodash;

var DragDropMixin = {
    /*
     *  usage:
     *
     *  mixins: [DragDropMixin],
     *  dragDrop: function () {
     *
     *     return {
     *
     *         // when dragging an item
     *         draggable: true,
     *         dropType: 'myItem',
     *         dataTransfer: { myItemData: property }
     *
     *         // when dropping an item:
     *         droppable: true,
     *         acceptableDrops: ['myItem'],
     *         drop: function (myItem) {},
     *     };
     *  }
     *
     */
    isAttrEnabled: function (attr) {
        return this.dragDropData && this.dragDropData[attr];
    },
    isDroppable: function () {
        return this.isAttrEnabled('droppable');
    },
    isDraggable: function () {
        return this.isAttrEnabled('draggable');
    },
    componentDidMount: function () {
        var node = this.getDOMNode();

        this.dragDropData = this.dragDrop();

        if (this.isDroppable()) {
            node.addEventListener('dragover', this.handleDragOver, this);
            node.addEventListener('drop', this.handleDrop, this);
        }

        if (this.isDraggable()) {
            node.draggable = true;
            node.addEventListener('dragstart', this.handleDragStart, this);
        }
    },
    componentWillUnmount: function () {
        var node = this.getDOMNode();

        if (this.isDroppable()) {
            node.removeEventListener('dragover', this.handleDragOver);
            node.removeEventListener('drop', this.handleDrop);
        }

        if (this.isDraggable()) {
            node.removeEventListener('dragstart', this.handleDragStart);
        }
    },
    handleDragOver: function (e) {
        e.preventDefault();
    },
    handleDrop: function (e) {
        var jsonData = e.dataTransfer.getData('objToPass'),
            passedObj = JSON.parse(jsonData),
            acceptableDrops = this.dragDropData.acceptableDrops;

        e.preventDefault();

        if (!this.dragDropData.drop) {
            throw new Error('Must define drop function when using droppable');
        }

        if (_.includes(acceptableDrops, passedObj.dropType)) {
            this.dragDropData.drop(passedObj.data);
        }

    },
    handleDragStart: function (e) {
        var objToPass = {
            data: this.dragDropData.dataTransfer,
            dropType: this.dragDropData.dropType
        };

        e.dataTransfer.setData('objToPass', JSON.stringify(objToPass));
    }
};

再次感谢。

1 个答案:

答案 0 :(得分:2)

好的,明白了。

我实际上是在听原生事件并模拟React合成事件。

通过更改mixin来修复它:

componentDidMount: function () {
    var node = this.getDOMNode();

    this.dragDropData = this.dragDrop();

    if (this.isDroppable()) {
        node.ondragover = this.handleDragOver;
        node.ondrop = this.handleDrop;
    }

    if (this.isDraggable()) {
        node.draggable = true;
        node.ondragstart = this.handleDragStart;
    }
},

通过触发本机事件进行测试

    nodeDrag.ondragstart(mockEvent);
    nodeDrop.ondragover(mockEvent);
    nodeDrop.ondrop(mockEvent);

    expect(DragDropMixin.handleDrop).toHaveBeenCalled();
    expect(renderedDrop.state).toBeNull();