Merge 1e6410ba67 into a1146fd4a3
This commit is contained in:
commit
451c2a6e79
|
|
@ -1210,6 +1210,9 @@ export class Frame extends SdkObject {
|
||||||
// Note: do not perform locator handlers checkpoint to avoid moving the mouse in the middle of a drag operation.
|
// Note: do not perform locator handlers checkpoint to avoid moving the mouse in the middle of a drag operation.
|
||||||
dom.assertDone(await this._retryWithProgressIfNotConnected(progress, target, options.strict, false /* performActionPreChecks */, async handle => {
|
dom.assertDone(await this._retryWithProgressIfNotConnected(progress, target, options.strict, false /* performActionPreChecks */, async handle => {
|
||||||
return handle._retryPointerAction(progress, 'move and up', false, async point => {
|
return handle._retryPointerAction(progress, 'move and up', false, async point => {
|
||||||
|
// NOTE: Normal browsers emit usually a lot of dragover/mousemove events during drag'n
|
||||||
|
// drop operations. We want to emit minimal (2) to make Angular CDK work.
|
||||||
|
await this._page.mouse.move(point.x, point.y);
|
||||||
await this._page.mouse.move(point.x, point.y);
|
await this._page.mouse.move(point.x, point.y);
|
||||||
await this._page.mouse.up();
|
await this._page.mouse.up();
|
||||||
}, {
|
}, {
|
||||||
|
|
|
||||||
112
tests/assets/drag-n-drop-manual.html
Normal file
112
tests/assets/drag-n-drop-manual.html
Normal file
|
|
@ -0,0 +1,112 @@
|
||||||
|
<style>
|
||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
body, html {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
div:not(.mouse-helper) {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
#source {
|
||||||
|
color: blue;
|
||||||
|
border: 1px solid black;
|
||||||
|
position: absolute;
|
||||||
|
left: 20px;
|
||||||
|
top: 20px;
|
||||||
|
width: 200px;
|
||||||
|
height: 100px;
|
||||||
|
cursor: move;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
#target {
|
||||||
|
border: 1px solid black;
|
||||||
|
position: absolute;
|
||||||
|
left: 40px;
|
||||||
|
top: 200px;
|
||||||
|
width: 400px;
|
||||||
|
height: 300px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div>
|
||||||
|
<p id="source">
|
||||||
|
Select this element, drag it to the Drop Zone and then release the selection to move the element.</p>
|
||||||
|
</div>
|
||||||
|
<div id="target">Drop Zone</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const sourceElement = document.getElementById('source');
|
||||||
|
const targetElement = document.getElementById('target');
|
||||||
|
|
||||||
|
let isDragging = false;
|
||||||
|
let offsetX, offsetY;
|
||||||
|
let originalPosition = { left: 0, top: 0 };
|
||||||
|
|
||||||
|
sourceElement.addEventListener('mousedown', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
const rect = sourceElement.getBoundingClientRect();
|
||||||
|
originalPosition = {
|
||||||
|
left: rect.left,
|
||||||
|
top: rect.top
|
||||||
|
};
|
||||||
|
|
||||||
|
offsetX = e.clientX - rect.left;
|
||||||
|
offsetY = e.clientY - rect.top;
|
||||||
|
|
||||||
|
isDragging = true;
|
||||||
|
sourceElement.style.border = 'dashed'
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener('mousemove', function(e) {
|
||||||
|
if (!isDragging) return;
|
||||||
|
|
||||||
|
sourceElement.style.left = (e.clientX - offsetX) + 'px';
|
||||||
|
sourceElement.style.top = (e.clientY - offsetY) + 'px';
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener('mouseup', function(e) {
|
||||||
|
if (!isDragging) return;
|
||||||
|
|
||||||
|
isDragging = false;
|
||||||
|
|
||||||
|
const sourceRect = sourceElement.getBoundingClientRect();
|
||||||
|
const targetRect = targetElement.getBoundingClientRect();
|
||||||
|
|
||||||
|
const isOverlapping = !(
|
||||||
|
sourceRect.right < targetRect.left ||
|
||||||
|
sourceRect.left > targetRect.right ||
|
||||||
|
sourceRect.bottom < targetRect.top ||
|
||||||
|
sourceRect.top > targetRect.bottom
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isOverlapping) {
|
||||||
|
targetElement.appendChild(sourceElement);
|
||||||
|
|
||||||
|
sourceElement.style.removeProperty('position')
|
||||||
|
sourceElement.style.removeProperty('top')
|
||||||
|
sourceElement.style.removeProperty('left')
|
||||||
|
|
||||||
|
console.log('Drop successful');
|
||||||
|
} else {
|
||||||
|
sourceElement.style.left = originalPosition.left + 'px';
|
||||||
|
sourceElement.style.top = originalPosition.top + 'px';
|
||||||
|
|
||||||
|
console.log('Drop failed - returning to original position');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener('mouseleave', function() {
|
||||||
|
if (isDragging) {
|
||||||
|
isDragging = false;
|
||||||
|
|
||||||
|
sourceElement.style.left = originalPosition.left + 'px';
|
||||||
|
sourceElement.style.top = originalPosition.top + 'px';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
|
@ -53,6 +53,25 @@ it.describe('Drag and drop', () => {
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should send the right events when using dragTo', async ({ server, page, browserName }) => {
|
||||||
|
await page.goto(server.PREFIX + '/drag-n-drop.html');
|
||||||
|
const events = await trackEvents(await page.$('body'));
|
||||||
|
await page.locator('#source').dragTo(page.locator('#target'));
|
||||||
|
expect(await events.jsonValue()).toEqual([
|
||||||
|
'mousemove at 120;86',
|
||||||
|
'mousedown at 120;86',
|
||||||
|
browserName === 'firefox' ? 'dragstart at 120;86' : 'mousemove at 240;350',
|
||||||
|
browserName === 'firefox' ? 'mousemove at 240;350' : 'dragstart at 120;86',
|
||||||
|
'dragenter at 240;350',
|
||||||
|
// NOTE: Normal browsers emit usually a lot of dragover events during drag'n
|
||||||
|
// drop operations. We want to emit minimal (2) to make Angular CDK work.
|
||||||
|
'dragover at 240;350',
|
||||||
|
'dragover at 240;350',
|
||||||
|
'drop at 240;350',
|
||||||
|
'dragend',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
it('should not send dragover on the first mousemove', async ({ server, page, browserName }) => {
|
it('should not send dragover on the first mousemove', async ({ server, page, browserName }) => {
|
||||||
it.fixme(browserName !== 'chromium');
|
it.fixme(browserName !== 'chromium');
|
||||||
|
|
||||||
|
|
@ -293,6 +312,34 @@ it.describe('Drag and drop', () => {
|
||||||
expect(await page.$eval('#target', target => target.contains(document.querySelector('#source')))).toBe(true); // could not find source in target
|
expect(await page.$eval('#target', target => target.contains(document.querySelector('#source')))).toBe(true); // could not find source in target
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should work with manual drag\'n drop and emit correct mousemove events', {
|
||||||
|
annotation: {
|
||||||
|
type: 'issue',
|
||||||
|
description: 'https://github.com/microsoft/playwright/issues/34688',
|
||||||
|
}
|
||||||
|
}, async ({ page, server }) => {
|
||||||
|
await page.goto(server.PREFIX + '/drag-n-drop-manual.html');
|
||||||
|
const events = await page.evaluateHandle(() => {
|
||||||
|
const events = [];
|
||||||
|
document.addEventListener('mousemove', (event: MouseEvent) => {
|
||||||
|
events.push({
|
||||||
|
type: event.type,
|
||||||
|
x: event.clientX,
|
||||||
|
y: event.clientY,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return events;
|
||||||
|
});
|
||||||
|
await page.dragAndDrop('#source', '#target');
|
||||||
|
expect(await events.jsonValue()).toEqual([
|
||||||
|
{ type: 'mousemove', x: 120, y: 86 },
|
||||||
|
// NOTE: Normal browsers emit usually a lot of mousemove events during drag'n
|
||||||
|
// drop operations. We want to emit minimal (2) to make Angular CDK work.
|
||||||
|
{ type: 'mousemove', x: 240, y: 350 },
|
||||||
|
{ type: 'mousemove', x: 240, y: 350 },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
it('should allow specifying the position', async ({ page, server }) => {
|
it('should allow specifying the position', async ({ page, server }) => {
|
||||||
await page.setContent(`
|
await page.setContent(`
|
||||||
<div style="width:100px;height:100px;background:red;" id="red">
|
<div style="width:100px;height:100px;background:red;" id="red">
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue