使用pytest結(jié)合Playwright實現(xiàn)頁面元素在兩個區(qū)域間拖拽功能
好的,下面是使用 pytest 結(jié)合 Playwright 實現(xiàn)頁面元素在兩個區(qū)域間拖拽的完整示例。
這個示例將創(chuàng)建一個包含兩個區(qū)域(source 和 target)和一個可拖拽區(qū)塊的 HTML 頁面,然后使用 Playwright 模擬將該區(qū)塊從一個區(qū)域拖拽到另一個區(qū)域的操作。
示例場景
我們將創(chuàng)建一個簡單的 HTML 頁面,包含:
- Source Area: 包含一個可拖拽的區(qū)塊(例如一個帶顏色的
<div>)。 - Target Area: 一個空的區(qū)域,用于接收被拖拽的區(qū)塊。
- JavaScript: 實現(xiàn) HTML5 拖放 API,處理
dragstart,dragover, 和drop事件,以便將元素從source移動到target。
1. 創(chuàng)建示例 HTML 頁面 (drag_drop_block.html)
將以下 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以便在容器內(nèi)精確定位區(qū)塊。 - JavaScript:
dragstart: 設置拖拽數(shù)據(jù)(可選),添加視覺反饋類。dragend: 移除視覺反饋類。dragover: 必須調(diào)用event.preventDefault(),否則drop事件不會觸發(fā)。drop: 必須調(diào)用event.preventDefault()。然后執(zhí)行元素的移動邏輯(removeChild+appendChild)。- 為了演示雙向拖拽,
source-area也監(jiān)聽了dragover和drop。
2. Pytest + Playwright 測試代碼 (test_block_drag_drop.py)
首先,確保安裝了必要的庫:
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: 為每個測試函數(shù)提供一個新的瀏覽器頁面實例,并在測試結(jié)束后自動關閉,確保測試隔離。 page.goto(): 導航到你的本地 HTML 文件。務必更新file:///...后面的路徑為你實際存放drag_drop_block.html的絕對路徑。page.drag_and_drop(source, target): Playwright 提供的核心方法,用于模擬拖放操作。它會處理底層的鼠標事件序列。expect(...): Playwright 的斷言庫,用于驗證 DOM 狀態(tài)(元素是否存在、是否可見等)。它具有內(nèi)置的智能等待機制。
3. 運行測試
在終端中,切換到包含 test_block_drag_drop.py 和 drag_drop_block.html 的目錄,然后運行:
pytest test_block_drag_drop.py -v
-v選項提供更詳細的輸出。
如果配置正確,你應該會看到類似以下的輸出,并且瀏覽器窗口會短暫出現(xiàn)以執(zhí)行測試:
============================= 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結(jié)合Playwright實現(xiàn)頁面元素在兩個區(qū)域間拖拽功能的詳細內(nèi)容,更多關于pytest Playwright頁面元素拖拽的資料請關注腳本之家其它相關文章!
相關文章
使用pipenv管理python虛擬環(huán)境的全過程
pipenv 是Kenneth Reitz大神的作品,能夠有效管理Python多個環(huán)境,各種包,接下來通過本文給大家分享使用pipenv管理python虛擬環(huán)境的全過程,感興趣的朋友一起看看吧2021-09-09
wxpython 最小化到托盤與歡迎圖片的實現(xiàn)方法
這篇文章主要分享一個python實例代碼,使用wxpython實現(xiàn)最小化到托盤與歡迎圖片,需要的朋友可以參考下2014-06-06
Python實現(xiàn)批量將MP3音頻轉(zhuǎn)為WAV格式詳解
這篇文章主要介紹了通過Python實現(xiàn)將MP3音頻轉(zhuǎn)為WAV格式的方法,文中的示例代碼講解詳細,對我們學習Python有一定幫助,感興趣的可以了解一下2021-12-12
Python使用Socket(Https)Post登錄百度的實現(xiàn)代碼
以前都是用一些高級模塊,封裝的比較好,今天嘗試使用socket模塊登錄百度,弄了半天才弄好,主要由于百度在登陸頁使用了https,我們需要對socket進行一定處理2012-05-05
關于python?-m?http.server的一些安全問題詳解
這篇文章主要介紹了關于python?-m?http.server的一些安全問題的相關資料,文章還列舉了該模塊已知的安全漏洞,并建議在生產(chǎn)環(huán)境中使用專業(yè)的服務器替代,文中通過代碼介紹的非常詳細,需要的朋友可以參考下2026-01-01
Python實現(xiàn)刪除windows下的長路徑文件
這篇文章主要為大家詳細介紹一下如何利用Python語言實現(xiàn)刪除windows下的長路徑文件功能,文中的示例代碼講解詳細,具有一定參考借鑒價值,感興趣的可以了解一下2022-07-07

