Skip to content

Commit 0b874fe

Browse files
committed
drag and drop tests between suites and inside their own suite
1 parent 116d5fd commit 0b874fe

File tree

3 files changed

+81
-9
lines changed

3 files changed

+81
-9
lines changed

packages/selenium-ide/src/neo/components/Test/index.jsx

Lines changed: 77 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
import React from "react";
1919
import PropTypes from "prop-types";
20-
import { DragSource } from "react-dnd";
20+
import { DragSource, DropTarget } from "react-dnd";
2121
import classNames from "classnames";
2222
import { modifier } from "modifier-keys";
2323
import Callstack from "../Callstack";
@@ -28,20 +28,89 @@ import MoreButton from "../ActionButtons/More";
2828
import "./style.css";
2929

3030
export const Type = "test";
31+
3132
const testSource = {
3233
beginDrag(props) {
3334
return {
3435
id: props.test.id,
35-
suite: props.suite.id
36+
index: props.index,
37+
test: props.test,
38+
suite: props.suite
3639
};
40+
},
41+
isDragging(props, monitor) {
42+
return (props.test.id === monitor.getItem().id);
3743
}
3844
};
39-
function collect(connect, monitor) {
45+
46+
function collectSource(connect, monitor) {
4047
return {
4148
connectDragSource: connect.dragSource(),
4249
isDragging: monitor.isDragging()
4350
};
4451
}
52+
53+
const testTarget = {
54+
canDrop(props, monitor) {
55+
const test = monitor.getItem().test;
56+
const suite = props.suite;
57+
return !suite.containsTest(test);
58+
},
59+
hover(props, monitor, component) {
60+
// check if they are different suites
61+
const dragged = monitor.getItem();
62+
if (monitor.canDrop() && props.suite !== dragged.suite) {
63+
dragged.suite.removeTestCase(dragged.test);
64+
props.suite.addTestCase(dragged.test);
65+
dragged.suite = props.suite;
66+
dragged.index = props.suite.tests.length - 1;
67+
return;
68+
}
69+
const dragIndex = dragged.index;
70+
const hoverIndex = props.index;
71+
72+
// Don't replace items with themselves
73+
if (dragIndex === hoverIndex) {
74+
return;
75+
}
76+
77+
// Determine rectangle on screen
78+
const hoverBoundingRect = component.decoratedComponentInstance.node.getBoundingClientRect();
79+
80+
// Get vertical middle
81+
const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2;
82+
83+
// Determine mouse position
84+
const clientOffset = monitor.getClientOffset();
85+
86+
// Get pixels to the top
87+
const hoverClientY = clientOffset.y - hoverBoundingRect.top;
88+
89+
// Only perform the move when the mouse has crossed half of the items height
90+
// When dragging downwards, only move when the cursor is below 50%
91+
// When dragging upwards, only move when the cursor is above 50%
92+
93+
// Dragging downwards
94+
if (dragIndex < hoverIndex && hoverClientY < hoverMiddleY) {
95+
return;
96+
}
97+
98+
// Dragging upwards
99+
if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) {
100+
return;
101+
}
102+
103+
props.swapTests(dragIndex, hoverIndex);
104+
105+
// save time on index lookups
106+
monitor.getItem().index = hoverIndex;
107+
}
108+
};
109+
110+
const collectTarget = (connect) => ({
111+
connectDropTarget: connect.dropTarget()
112+
});
113+
45114
export default class Test extends React.Component {
46115
static propTypes = {
47116
className: PropTypes.string,
@@ -58,6 +127,7 @@ export default class Test extends React.Component {
58127
selectTest: PropTypes.func.isRequired,
59128
renameTest: PropTypes.func,
60129
removeTest: PropTypes.func,
130+
connectDropTarget: PropTypes.func,
61131
connectDragSource: PropTypes.func,
62132
moveSelectionUp: PropTypes.func,
63133
moveSelectionDown: PropTypes.func,
@@ -127,7 +197,7 @@ export default class Test extends React.Component {
127197
tabIndex={this.props.selected ? "0" : "-1"}
128198
onContextMenu={this.props.onContextMenu}
129199
style={{
130-
display: this.props.isDragging ? "none" : "block"
200+
opacity: this.props.isDragging ? "0" : "1"
131201
}}>
132202
<a
133203
ref={(button) => { this.button = button; }}
@@ -144,7 +214,7 @@ export default class Test extends React.Component {
144214
onClick={this.handleCallstackClick.bind(this, this.props.test, this.props.suite)}
145215
/> : undefined}
146216
</div>;
147-
return (this.props.connectDragSource ? this.props.connectDragSource(rendered) : rendered);
217+
return (this.props.connectDragSource ? this.props.connectDropTarget(this.props.connectDragSource(rendered)) : rendered);
148218
}
149219
}
150220

@@ -164,4 +234,5 @@ export class MenuTest extends React.Component {
164234
}
165235
}
166236

167-
export const DraggableTest = DragSource(Type, testSource, collect)(Test);
237+
238+
export const DraggableTest = DropTarget(Type, testTarget, collectTarget)(DragSource(Type, testSource, collectSource)(Test));

packages/selenium-ide/src/neo/components/TestList/index.jsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ export default class TestList extends Component {
6161
this.props.suite ?
6262
<DraggableTest
6363
className={PlaybackState.testState.get(test.id)}
64+
index={index}
6465
test={test}
6566
suite={this.props.suite}
6667
selected={UiState.selectedTest.test && test.id === UiState.selectedTest.test.id && this.props.suite.id === (UiState.selectedTest.suite ? UiState.selectedTest.suite.id : undefined)}
@@ -69,6 +70,7 @@ export default class TestList extends Component {
6970
changed={UiState.getTestState(test).modified}
7071
selectTest={UiState.selectTest}
7172
removeTest={this.props.removeTest ? () => { this.props.removeTest(test); } : undefined}
73+
swapTests={this.props.suite.swapTestCases}
7274
moveSelectionUp={() => { UiState.selectTestByIndex(index - 1, this.props.suite); }}
7375
moveSelectionDown={() => { UiState.selectTestByIndex(index + 1, this.props.suite); }}
7476
setSectionFocus={UiState.setSectionFocus}

packages/selenium-ide/src/neo/models/Suite.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,9 @@ export default class Suite {
3636
}
3737

3838
@computed get tests() {
39-
return this._tests;
40-
return this._tests.sort((t1, t2) => (
39+
return this.isParallel ? this._tests.sort((t1, t2) => (
4140
naturalCompare(t1.name, t2.name)
42-
));
41+
)) : this._tests;
4342
}
4443

4544
isTest(test) {

0 commit comments

Comments
 (0)