Skip to content

Commit 858c25a

Browse files
authored
Merge pull request #1953 from b-vamsipunnam/feature/drag-and-drop-to-frame
Add "Drag And Drop Across Frames" keyword for cross-frame drag and drop support
2 parents e495938 + 54584bc commit 858c25a

4 files changed

Lines changed: 394 additions & 1 deletion

File tree

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
*** Settings ***
2+
Documentation Tests for the custom Drag And Drop Across Frames keyword
3+
... in cross-frame drag-and-drop scenarios.
4+
Resource ../resource.robot
5+
Test Setup Go To Page "frames/draganddrop.html"
6+
7+
*** Test Cases ***
8+
Drag And Drop Across Frames Works From Default Content
9+
[Documentation] Verifies drag-and-drop from default content to a target inside an iframe.
10+
Wait Until Page Contains Element id=defaultSource 10s
11+
Drag And Drop Across Frames id=defaultSource id=target id=targetFrame
12+
Select Frame id=targetFrame
13+
Element Should Contain id=target Dropped Successfully!
14+
Unselect Frame
15+
16+
Drag And Drop Across Frames Works From Source Frame
17+
[Documentation] Verifies drag-and-drop from a source iframe to a target iframe.
18+
Wait Until Page Contains Element id=sourceFrame 10s
19+
Select Frame id=sourceFrame
20+
Wait Until Page Contains Element id=frameSource 10s
21+
Unselect Frame
22+
Drag And Drop Across Frames id=frameSource id=target id=targetFrame id=sourceFrame
23+
Select Frame id=targetFrame
24+
Element Should Contain id=target Dropped Successfully!
25+
Unselect Frame
26+
27+
Drag And Drop Across Frames Returns To Default Content
28+
[Documentation] Verifies that the keyword returns to default content after execution.
29+
Wait Until Page Contains Element id=defaultSource 10s
30+
Drag And Drop Across Frames id=defaultSource id=target id=targetFrame
31+
Page Should Not Contain Element id=target
32+
33+
Drag And Drop Across Frames Hides Default Source Element
34+
[Documentation] Verifies that the default source element becomes hidden after a successful drop.
35+
Wait Until Page Contains Element id=defaultSource 10s
36+
Drag And Drop Across Frames id=defaultSource id=target id=targetFrame
37+
Element Should Not Be Visible id=defaultSource
38+
39+
Drag And Drop Across Frames Hides Frame Source Element
40+
[Documentation] Verifies that the frame source element becomes hidden after a successful drop.
41+
Wait Until Page Contains Element id=sourceFrame 10s
42+
Drag And Drop Across Frames id=frameSource id=target id=targetFrame id=sourceFrame
43+
Select Frame id=sourceFrame
44+
Element Should Not Be Visible id=frameSource
45+
Unselect Frame
46+
47+
Drag And Drop Across Frames Fails With Invalid Target Frame
48+
[Documentation] Verifies that the keyword fails when the target frame locator is invalid.
49+
Wait Until Page Contains Element id=defaultSource 10s
50+
Run Keyword And Expect Error
51+
... Element with locator 'id=missingFrame' not found.
52+
... Drag And Drop Across Frames
53+
... id=defaultSource id=target id=missingFrame
54+
55+
Drag And Drop Across Frames Fails With Invalid Target
56+
[Documentation] Verifies that the keyword fails when the target element is not found inside the target iframe.
57+
Wait Until Page Contains Element id=defaultSource 10s
58+
Run Keyword And Expect Error
59+
... Element with locator 'id=missingTarget' not found.
60+
... Drag And Drop Across Frames
61+
... id=defaultSource id=missingTarget id=targetFrame
62+
63+
Drag And Drop Across Frames Fails With Invalid Source Frame
64+
[Documentation] Verifies that the keyword fails when the source frame locator is invalid.
65+
Wait Until Page Contains Element id=defaultSource 10s
66+
Run Keyword And Expect Error
67+
... Element with locator 'id=missingSourceFrame' not found.
68+
... Drag And Drop Across Frames
69+
... id=frameSource id=target id=targetFrame id=missingSourceFrame
70+
71+
Drag And Drop Across Frames Fails With Invalid Source
72+
[Documentation] Verifies that the keyword fails when the source element is not found.
73+
Wait Until Page Contains Element id=defaultSource 10s
74+
Run Keyword And Expect Error
75+
... Element with locator 'id=missingSource' not found.
76+
... Drag And Drop Across Frames
77+
... id=missingSource id=target id=targetFrame
Lines changed: 260 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,260 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<title>Drag And Drop Across Frames Test Page</title>
6+
<style>
7+
body {
8+
font-family: Arial, sans-serif;
9+
margin: 40px;
10+
background: #f0f0f0;
11+
}
12+
13+
.frame-wrapper {
14+
display: flex;
15+
gap: 40px;
16+
margin-top: 40px;
17+
}
18+
19+
iframe {
20+
width: 500px;
21+
height: 350px;
22+
border: 3px solid #333;
23+
background: white;
24+
}
25+
26+
#defaultSource,
27+
#dragGhost {
28+
width: 150px;
29+
height: 150px;
30+
background: lightblue;
31+
text-align: center;
32+
line-height: 150px;
33+
font-size: 20px;
34+
cursor: grab;
35+
user-select: none;
36+
}
37+
38+
#dragGhost {
39+
position: fixed;
40+
display: none;
41+
z-index: 10000;
42+
border: 2px solid #333;
43+
opacity: 0.85;
44+
pointer-events: none;
45+
}
46+
47+
#status {
48+
margin-top: 20px;
49+
font-weight: bold;
50+
}
51+
</style>
52+
</head>
53+
<body>
54+
55+
<h2>Drag And Drop Across Frames Test Page</h2>
56+
57+
<div id="defaultSource">Default Source</div>
58+
59+
<div class="frame-wrapper">
60+
<iframe id="sourceFrame"></iframe>
61+
<iframe id="targetFrame"></iframe>
62+
</div>
63+
64+
<div id="dragGhost"></div>
65+
66+
<script>
67+
const sourceFrame = document.getElementById("sourceFrame");
68+
const targetFrame = document.getElementById("targetFrame");
69+
const defaultSource = document.getElementById("defaultSource");
70+
const dragGhost = document.getElementById("dragGhost");
71+
72+
let dragging = false;
73+
let activeSource = null;
74+
75+
sourceFrame.srcdoc = `
76+
<!DOCTYPE html>
77+
<html>
78+
<head>
79+
<style>
80+
body {
81+
margin: 40px;
82+
font-family: Arial, sans-serif;
83+
background: white;
84+
}
85+
86+
#frameSource {
87+
width: 150px;
88+
height: 150px;
89+
background: lightblue;
90+
text-align: center;
91+
line-height: 150px;
92+
font-size: 20px;
93+
cursor: grab;
94+
user-select: none;
95+
}
96+
</style>
97+
</head>
98+
<body>
99+
<div id="frameSource">Frame Source</div>
100+
</body>
101+
</html>
102+
`;
103+
104+
targetFrame.srcdoc = `
105+
<!DOCTYPE html>
106+
<html>
107+
<head>
108+
<style>
109+
body {
110+
margin: 0;
111+
background: white;
112+
font-family: Arial, sans-serif;
113+
}
114+
115+
#target {
116+
width: 350px;
117+
height: 220px;
118+
background: lightgreen;
119+
margin: 60px auto;
120+
text-align: center;
121+
line-height: 220px;
122+
font-size: 26px;
123+
border: 4px dashed black;
124+
}
125+
</style>
126+
</head>
127+
<body>
128+
<div id="target">Drop Here</div>
129+
</body>
130+
</html>
131+
`;
132+
133+
window.onload = function () {
134+
const sourceDoc = sourceFrame.contentDocument;
135+
const targetDoc = targetFrame.contentDocument;
136+
137+
const frameSource = sourceDoc.getElementById("frameSource");
138+
139+
defaultSource.addEventListener("mousedown", function (event) {
140+
startDrag("default", event.clientX, event.clientY);
141+
event.preventDefault();
142+
});
143+
144+
frameSource.addEventListener("mousedown", function (event) {
145+
const sourceRect = sourceFrame.getBoundingClientRect();
146+
147+
startDrag(
148+
"frame",
149+
sourceRect.left + event.clientX,
150+
sourceRect.top + event.clientY
151+
);
152+
153+
event.preventDefault();
154+
});
155+
156+
document.addEventListener("mousemove", function (event) {
157+
if (!dragging) return;
158+
moveGhost(event.clientX, event.clientY);
159+
});
160+
161+
document.addEventListener("mouseup", function (event) {
162+
if (!dragging) return;
163+
finishDrag(event.clientX, event.clientY);
164+
});
165+
166+
sourceDoc.addEventListener("mousemove", function (event) {
167+
if (!dragging) return;
168+
169+
const rect = sourceFrame.getBoundingClientRect();
170+
moveGhost(rect.left + event.clientX, rect.top + event.clientY);
171+
});
172+
173+
sourceDoc.addEventListener("mouseup", function (event) {
174+
if (!dragging) return;
175+
176+
const rect = sourceFrame.getBoundingClientRect();
177+
finishDrag(rect.left + event.clientX, rect.top + event.clientY);
178+
});
179+
180+
targetDoc.addEventListener("mousemove", function (event) {
181+
if (!dragging) return;
182+
183+
const rect = targetFrame.getBoundingClientRect();
184+
moveGhost(rect.left + event.clientX, rect.top + event.clientY);
185+
});
186+
187+
targetDoc.addEventListener("mouseup", function (event) {
188+
if (!dragging) return;
189+
190+
const rect = targetFrame.getBoundingClientRect();
191+
finishDrag(rect.left + event.clientX, rect.top + event.clientY);
192+
});
193+
};
194+
195+
function startDrag(source, x, y) {
196+
dragging = true;
197+
activeSource = source;
198+
199+
dragGhost.innerText = source === "default" ? "Default Source" : "Frame Source";
200+
dragGhost.style.display = "block";
201+
202+
moveGhost(x, y);
203+
}
204+
205+
function moveGhost(x, y) {
206+
dragGhost.style.left = (x - 75) + "px";
207+
dragGhost.style.top = (y - 75) + "px";
208+
}
209+
210+
function finishDrag(x, y) {
211+
if (isInsideTarget(x, y)) {
212+
completeDrop();
213+
} else {
214+
resetDrag();
215+
}
216+
}
217+
218+
function isInsideTarget(x, y) {
219+
const target = targetFrame.contentDocument.getElementById("target");
220+
const frameRect = targetFrame.getBoundingClientRect();
221+
const targetRect = target.getBoundingClientRect();
222+
223+
const globalLeft = frameRect.left + targetRect.left;
224+
const globalTop = frameRect.top + targetRect.top;
225+
const globalRight = globalLeft + targetRect.width;
226+
const globalBottom = globalTop + targetRect.height;
227+
228+
return (
229+
x >= globalLeft &&
230+
x <= globalRight &&
231+
y >= globalTop &&
232+
y <= globalBottom
233+
);
234+
}
235+
236+
function completeDrop() {
237+
if (activeSource === "default") {
238+
defaultSource.style.display = "none";
239+
}
240+
241+
if (activeSource === "frame") {
242+
const frameSource = sourceFrame.contentDocument.getElementById("frameSource");
243+
frameSource.style.display = "none";
244+
}
245+
246+
const target = targetFrame.contentDocument.getElementById("target");
247+
target.innerText = "Dropped Successfully!";
248+
249+
resetDrag();
250+
}
251+
252+
function resetDrag() {
253+
dragging = false;
254+
activeSource = null;
255+
dragGhost.style.display = "none";
256+
}
257+
</script>
258+
259+
</body>
260+
</html>

0 commit comments

Comments
 (0)