Javascript 在react testutils不工作的情况下模拟拖放

Javascript 在react testutils不工作的情况下模拟拖放,javascript,drag-and-drop,reactjs,karma-jasmine,reactjs-testutils,Javascript,Drag And Drop,Reactjs,Karma Jasmine,Reactjs Testutils,我正在尝试使用jasmine、karma和React TestUtils测试我的ReactJS mixin的拖放功能 没有引发异常,但在调试时,似乎在模拟事件时没有执行绑定到事件侦听器的函数 您可以在此处克隆它: 事先非常感谢 这是我的测试: beforeEach(function () { var CompDrag = React.createClass({ mixins: [DragDropMixin], dragDrop: function dr

我正在尝试使用jasmine、karma和React TestUtils测试我的ReactJS mixin的拖放功能

没有引发异常,但在调试时,似乎在模拟事件时没有执行绑定到事件侦听器的函数

您可以在此处克隆它:

事先非常感谢

这是我的测试:

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();
});
这是混音器:

'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));
    }
};
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;
    }
},
再次感谢。

好的,明白了

我实际上是在听本地事件和模拟合成事件

通过更改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));
    }
};
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();