文章目录
- 将以下 HTML 代码保存为 drag_drop_block.html 文件。 <!DOCTYPE html> <html lang=”en”> <head> <meta charset=”UTF-8″> <title>Block Drag & Drop Example</title> <style> body { font-family: Arial, sans-serif; margin: 40px; } .area { width: 300px; height: 200px; border: 2px dashed #ccc; display: inline-block; vertical-align: top; margin: 20px; padding: 10px; position: relative; } #source-area { background-color: #e0f7fa; /* Light Blue */ } #target-area { background-color: #f3e5f5; /* Light Purple */ } .draggable-block { width: 100px; height: 100px; background-color: #f44336; /* Red */ color: white; text-align: center; line-height: 100px; /* Vertically center text */ cursor: move; /* Show move cursor */ user-select: none; /* Prevent text selection */ position: absolute; /* Position within parent */ top: 30px; left: 50px; } .block-content { font-size: 12px; } /* Optional: Visual feedback during drag */ .draggable-block.dragging { opacity: 0.5; } /* Success indicator */ .success-indicator { color: green; font-weight: bold; display: none; /* Hidden initially */ } #target-area.success .success-indicator { display: block; } </style> </head> <body> <h1>Block Drag & Drop Test</h1> <div id=”source-area” class=”area”> <h3>Source Area</h3> <div id=”draggable-block” class=”draggable-block” draggable=”true”> <span class=”block-content”>Drag Me!</span> </div> </div> <div id=”target-area” class=”area”> <h3>Target Area</h3> <p class=”success-indicator”>Block dropped successfully!</p> </div> <script> const draggableBlock = document.getElementById(‘draggable-block’); const sourceArea = document.getElementById(‘source-area’); const targetArea = document.getElementById(‘target-area’); draggableBlock.addEventListener(‘dragstart’, function(event) { event.dataTransfer.setData(“text/plain”, “block-id”); // Optional: Set data // Add a class for visual feedback this.classList.add(‘dragging’); }); draggableBlock.addEventListener(‘dragend’, function(event) { // Remove visual feedback this.classList.remove(‘dragging’); }); targetArea.addEventListener(‘dragover’, function(event) { event.preventDefault(); // Crucial: Allows dropping }); targetArea.addEventListener(‘drop’, function(event) { event.preventDefault(); // Crucial: Allows dropping // Move the block from source to target // We know the block is the only draggable element in source sourceArea.removeChild(draggableBlock); targetArea.appendChild(draggableBlock); // Optional: Add success class to target area targetArea.classList.add(‘success’); }); // Allow dropping back into source area too (for demo purposes) sourceArea.addEventListener(‘dragover’, function(event) { event.preventDefault(); }); sourceArea.addEventListener(‘drop’, function(event) { event.preventDefault(); // Move the block from target back to source targetArea.removeChild(draggableBlock); sourceArea.appendChild(draggableBlock); // Remove success class from target area targetArea.classList.remove(‘success’); }); </script> </body> </html> 说明: draggable="true": 必须在可拖拽的元素上设置此属性。 CSS: 设置了 position: absolute 以便在容器内精确定位区块。 JavaScript: dragstart: 设置拖拽数据(可选),添加视觉反馈类。 dragend: 移除视觉反馈类。 dragover: 必须调用 event.preventDefault(),否则 drop 事件不会触发。 drop: 必须调用 event.preventDefault()。然后执行元素的移动逻辑(removeChild + appendChild)。 为了演示双向拖拽,source-area 也监听了 dragover 和 drop。
- 首先,确保安装了必要的库: pip install pytest playwright playwright install 然后,将以下 Python 代码保存为 test_block_drag_drop.py。 # test_block_drag_drop.py import pytest from playwright.sync_api import Page, expect # Pytest fixture to provide a fresh browser page for each test @pytest.fixture(scope=”function”) def page(context): “””Creates a new page for each test function.””” page = context.new_page() yield page page.close() def test_drag_block_from_source_to_target(page: Page): “”” Tests dragging a block from the source area to the target area. “”” # 1. Navigate to the HTML file # Update the path to point to where you saved the HTML file page.goto(“file:///absolute/path/to/your/drag_drop_block.html”) # 2. Define selectors for the draggable block and the target area source_area_selector = “#source-area” target_area_selector = “#target-area” draggable_block_selector = “#draggable-block” # 3. Verify initial state: block is in source area expect(page.locator(source_area_selector + ” ” + draggable_block_selector)).to_be_attached() expect(page.locator(target_area_selector + ” ” + draggable_block_selector)).not_to_be_attached() expect(page.locator(f”{target_area_selector} .success-indicator”)).not_to_be_visible() # 4. Perform the drag and drop operation page.drag_and_drop(draggable_block_selector, target_area_selector) # 5. Verify final state: block is in target area expect(page.locator(target_area_selector + ” ” + draggable_block_selector)).to_be_attached(message=”Block should be in target area after drop.”) expect(page.locator(source_area_selector + ” ” + draggable_block_selector)).not_to_be_attached(message=”Block should not be in source area after drop.”) expect(page.locator(f”{target_area_selector} .success-indicator”)).to_be_visible(message=”Success indicator should be visible in target area.”) def test_drag_block_back_to_source(page: Page): “”” Tests dragging the block back from the target area to the source area. “”” # 1. Navigate to the HTML file page.goto(“file:///absolute/path/to/your/drag_drop_block.html”) # 2. Define selectors source_area_selector = “#source-area” target_area_selector = “#target-area” draggable_block_selector = “#draggable-block” # 3. First, move the block to the target area (using the previous test’s logic or just do it here) # Initial state check expect(page.locator(source_area_selector + ” ” + draggable_block_selector)).to_be_attached() expect(page.locator(target_area_selector + ” ” + draggable_block_selector)).not_to_be_attached() # Drag to target first page.drag_and_drop(draggable_block_selector, target_area_selector) # Confirm it’s in target expect(page.locator(target_area_selector + ” ” + draggable_block_selector)).to_be_attached() expect(page.locator(source_area_selector + ” ” + draggable_block_selector)).not_to_be_attached() expect(page.locator(f”{target_area_selector} .success-indicator”)).to_be_visible() # 4. Now, drag the block back from target to source page.drag_and_drop(draggable_block_selector, source_area_selector) # 5. Verify final state: block is back in source area expect(page.locator(source_area_selector + ” ” + draggable_block_selector)).to_be_attached(message=”Block should be back in source area after second drop.”) expect(page.locator(target_area_selector + ” ” + draggable_block_selector)).not_to_be_attached(message=”Block should not be in target area after second drop.”) expect(page.locator(f”{target_area_selector} .success-indicator”)).not_to_be_visible(message=”Success indicator should be hidden after moving block back to source.”) 说明: Fixture page: 为每个测试函数提供一个新的浏览器页面实例,并在测试结束后自动关闭,确保测试隔离。 page.goto(): 导航到你的本地 HTML 文件。务必更新 file:///… 后面的路径为你实际存放 drag_drop_block.html 的绝对路径。 page.drag_and_drop(source, target): Playwright 提供的核心方法,用于模拟拖放操作。它会处理底层的鼠标事件序列。 expect(…): Playwright 的断言库,用于验证 DOM 状态(元素是否存在、是否可见等)。它具有内置的智能等待机制。
- 在终端中,切换到包含 test_block_drag_drop.py 和 drag_drop_block.html 的目录,然后运行: pytest test_block_drag_drop.py -v -v 选项提供更详细的输出。 如果配置正确,你应该会看到类似以下的输出,并且浏览器窗口会短暂出现以执行测试: ============================= test session starts ============================== platform linux — Python 3.x.y, pytest-x.x.x, pluggy-x.x.x rootdir: /path/to/your/test/directory collected 2 items test_block_drag_drop.py::test_drag_block_from_source_to_target PASSED [ 50%] test_block_drag_drop.py::test_drag_block_back_to_source PASSED [100%] ============================== 2 passed in 3.12s =============================== 这表明两个测试(从 source 到 target,以及从 target 回到 source)都成功通过了。 以上就是使用pytest结合Playwright实现页面元素在两个区域间拖拽功能的详细内容,更多关于pytest Playwright页面元素拖拽的资料请关注风君子博客其它相关文章! 您可能感兴趣的文章: python playwright–pytest-playwright、pytest-base-url插件编写用例 Python使用pytest-playwright的原因分析 python中playwright结合pytest执行用例的实现
目录
- 示例场景
- 1. 创建示例 HTML 页面 (drag_drop_block.html)
- 2. Pytest + Playwright 测试代码 (test_block_drag_drop.py)
- 3. 运行测试
好的,下面是使用 pytest 结合 Playwright 实现页面元素在两个区域间拖拽的完整示例。
这个示例将创建一个包含两个区域(source 和 target)和一个可拖拽区块的 HTML 页面,然后使用 Playwright 模拟将该区块从一个区域拖拽到另一个区域的操作。
我们将创建一个简单的 HTML 页面,包含:
- Source Area: 包含一个可拖拽的区块(例如一个带颜色的
<div>)。 - Target Area: 一个空的区域,用于接收被拖拽的区块。
- JavaScript: 实现 HTML5 拖放 API,处理
dragstart,dragover, 和drop事件,以便将元素从source移动到target。
将以下 HTML 代码保存为 drag_drop_block.html 文件。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Block Drag & Drop Example</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 40px;
}
.area {
width: 300px;
height: 200px;
border: 2px dashed #ccc;
display: inline-block;
vertical-align: top;
margin: 20px;
padding: 10px;
position: relative;
}
#source-area {
background-color: #e0f7fa; /* Light Blue */
}
#target-area {
background-color: #f3e5f5; /* Light Purple */
}
.draggable-block {
width: 100px;
height: 100px;
background-color: #f44336; /* Red */
color: white;
text-align: center;
line-height: 100px; /* Vertically center text */
cursor: move; /* Show move cursor */
user-select: none; /* Prevent text selection */
position: absolute; /* Position within parent */
top: 30px;
left: 50px;
}
.block-content {
font-size: 12px;
}
/* Optional: Visual feedback during drag */
.draggable-block.dragging {
opacity: 0.5;
}
/* Success indicator */
.success-indicator {
color: green;
font-weight: bold;
display: none; /* Hidden initially */
}
#target-area.success .success-indicator {
display: block;
}
</style>
</head>
<body>
<h1>Block Drag & Drop Test</h1>
<div id="source-area" class="area">
<h3>Source Area</h3>
<div id="draggable-block" class="draggable-block" draggable="true">
<span class="block-content">Drag Me!</span>
</div>
</div>
<div id="target-area" class="area">
<h3>Target Area</h3>
<p class="success-indicator">Block dropped successfully!</p>
</div>
<script>
const draggableBlock = document.getElementById('draggable-block');
const sourceArea = document.getElementById('source-area');
const targetArea = document.getElementById('target-area');
draggableBlock.addEventListener('dragstart', function(event) {
event.dataTransfer.setData("text/plain", "block-id"); // Optional: Set data
// Add a class for visual feedback
this.classList.add('dragging');
});
draggableBlock.addEventListener('dragend', function(event) {
// Remove visual feedback
this.classList.remove('dragging');
});
targetArea.addEventListener('dragover', function(event) {
event.preventDefault(); // Crucial: Allows dropping
});
targetArea.addEventListener('drop', function(event) {
event.preventDefault(); // Crucial: Allows dropping
// Move the block from source to target
// We know the block is the only draggable element in source
sourceArea.removeChild(draggableBlock);
targetArea.appendChild(draggableBlock);
// Optional: Add success class to target area
targetArea.classList.add('success');
});
// Allow dropping back into source area too (for demo purposes)
sourceArea.addEventListener('dragover', function(event) {
event.preventDefault();
});
sourceArea.addEventListener('drop', function(event) {
event.preventDefault();
// Move the block from target back to source
targetArea.removeChild(draggableBlock);
sourceArea.appendChild(draggableBlock);
// Remove success class from target area
targetArea.classList.remove('success');
});
</script>
</body>
</html>
说明:
draggable="true": 必须在可拖拽的元素上设置此属性。- CSS: 设置了
position: absolute以便在容器内精确定位区块。 - JavaScript:
dragstart: 设置拖拽数据(可选),添加视觉反馈类。dragend: 移除视觉反馈类。dragover: 必须调用event.preventDefault(),否则drop事件不会触发。drop: 必须调用event.preventDefault()。然后执行元素的移动逻辑(removeChild+appendChild)。- 为了演示双向拖拽,
source-area也监听了dragover和drop。
首先,确保安装了必要的库:
pip install pytest playwright playwright install
然后,将以下 Python 代码保存为 test_block_drag_drop.py。
# test_block_drag_drop.py
import pytest
from playwright.sync_api import Page, expect
# Pytest fixture to provide a fresh browser page for each test
@pytest.fixture(scope="function")
def page(context):
"""Creates a new page for each test function."""
page = context.new_page()
yield page
page.close()
def test_drag_block_from_source_to_target(page: Page):
"""
Tests dragging a block from the source area to the target area.
"""
# 1. Navigate to the HTML file
# Update the path to point to where you saved the HTML file
page.goto("file:///absolute/path/to/your/drag_drop_block.html")
# 2. Define selectors for the draggable block and the target area
source_area_selector = "#source-area"
target_area_selector = "#target-area"
draggable_block_selector = "#draggable-block"
# 3. Verify initial state: block is in source area
expect(page.locator(source_area_selector + " " + draggable_block_selector)).to_be_attached()
expect(page.locator(target_area_selector + " " + draggable_block_selector)).not_to_be_attached()
expect(page.locator(f"{target_area_selector} .success-indicator")).not_to_be_visible()
# 4. Perform the drag and drop operation
page.drag_and_drop(draggable_block_selector, target_area_selector)
# 5. Verify final state: block is in target area
expect(page.locator(target_area_selector + " " + draggable_block_selector)).to_be_attached(message="Block should be in target area after drop.")
expect(page.locator(source_area_selector + " " + draggable_block_selector)).not_to_be_attached(message="Block should not be in source area after drop.")
expect(page.locator(f"{target_area_selector} .success-indicator")).to_be_visible(message="Success indicator should be visible in target area.")
def test_drag_block_back_to_source(page: Page):
"""
Tests dragging the block back from the target area to the source area.
"""
# 1. Navigate to the HTML file
page.goto("file:///absolute/path/to/your/drag_drop_block.html")
# 2. Define selectors
source_area_selector = "#source-area"
target_area_selector = "#target-area"
draggable_block_selector = "#draggable-block"
# 3. First, move the block to the target area (using the previous test's logic or just do it here)
# Initial state check
expect(page.locator(source_area_selector + " " + draggable_block_selector)).to_be_attached()
expect(page.locator(target_area_selector + " " + draggable_block_selector)).not_to_be_attached()
# Drag to target first
page.drag_and_drop(draggable_block_selector, target_area_selector)
# Confirm it's in target
expect(page.locator(target_area_selector + " " + draggable_block_selector)).to_be_attached()
expect(page.locator(source_area_selector + " " + draggable_block_selector)).not_to_be_attached()
expect(page.locator(f"{target_area_selector} .success-indicator")).to_be_visible()
# 4. Now, drag the block back from target to source
page.drag_and_drop(draggable_block_selector, source_area_selector)
# 5. Verify final state: block is back in source area
expect(page.locator(source_area_selector + " " + draggable_block_selector)).to_be_attached(message="Block should be back in source area after second drop.")
expect(page.locator(target_area_selector + " " + draggable_block_selector)).not_to_be_attached(message="Block should not be in target area after second drop.")
expect(page.locator(f"{target_area_selector} .success-indicator")).not_to_be_visible(message="Success indicator should be hidden after moving block back to source.")
说明:
- Fixture
page: 为每个测试函数提供一个新的浏览器页面实例,并在测试结束后自动关闭,确保测试隔离。 page.goto(): 导航到你的本地 HTML 文件。务必更新file:///...后面的路径为你实际存放drag_drop_block.html的绝对路径。page.drag_and_drop(source, target): Playwright 提供的核心方法,用于模拟拖放操作。它会处理底层的鼠标事件序列。expect(...): Playwright 的断言库,用于验证 DOM 状态(元素是否存在、是否可见等)。它具有内置的智能等待机制。
在终端中,切换到包含 test_block_drag_drop.py 和 drag_drop_block.html 的目录,然后运行:
pytest test_block_drag_drop.py -v
-v选项提供更详细的输出。
如果配置正确,你应该会看到类似以下的输出,并且浏览器窗口会短暂出现以执行测试:
============================= test session starts ============================== platform linux -- Python 3.x.y, pytest-x.x.x, pluggy-x.x.x rootdir: /path/to/your/test/directory collected 2 items test_block_drag_drop.py::test_drag_block_from_source_to_target PASSED [ 50%] test_block_drag_drop.py::test_drag_block_back_to_source PASSED [100%] ============================== 2 passed in 3.12s ===============================
这表明两个测试(从 source 到 target,以及从 target 回到 source)都成功通过了。
以上就是使用pytest结合Playwright实现页面元素在两个区域间拖拽功能的详细内容,更多关于pytest Playwright页面元素拖拽的资料请关注风君子博客其它相关文章!
您可能感兴趣的文章:
- python playwright–pytest-playwright、pytest-base-url插件编写用例
- Python使用pytest-playwright的原因分析
- python中playwright结合pytest执行用例的实现