当前位置: 代码网 > it编程>前端脚本>Python > 使用pytest结合Playwright实现页面元素在两个区域间拖拽功能

使用pytest结合Playwright实现页面元素在两个区域间拖拽功能

2026年01月23日 Python 我要评论
好的,下面是使用pytest结合playwright实现页面元素在两个区域间拖拽的完整示例。这个示例将创建一个包含两个区域(source 和 target)和一个可拖拽区块的 html 页面,然后使用

好的,下面是使用 pytest 结合 playwright 实现页面元素在两个区域间拖拽的完整示例。

这个示例将创建一个包含两个区域(sourcetarget)和一个可拖拽区块的 html 页面,然后使用 playwright 模拟将该区块从一个区域拖拽到另一个区域的操作。

示例场景

我们将创建一个简单的 html 页面,包含:

  1. source area: 包含一个可拖拽的区块(例如一个带颜色的 <div>)。
  2. target area: 一个空的区域,用于接收被拖拽的区块。
  3. javascript: 实现 html5 拖放 api,处理 dragstart, dragover, 和 drop 事件,以便将元素从 source 移动到 target

1. 创建示例 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 以便在容器内精确定位区块。
  • javascript:
    • dragstart: 设置拖拽数据(可选),添加视觉反馈类。
    • dragend: 移除视觉反馈类。
    • dragover必须调用 event.preventdefault(),否则 drop 事件不会触发。
    • drop必须调用 event.preventdefault()。然后执行元素的移动逻辑(removechild + appendchild)。
    • 为了演示双向拖拽,source-area 也监听了 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: 为每个测试函数提供一个新的浏览器页面实例,并在测试结束后自动关闭,确保测试隔离。
  • page.goto(): 导航到你的本地 html 文件。务必更新 file:///... 后面的路径为你实际存放 drag_drop_block.html 的绝对路径。
  • page.drag_and_drop(source, target): playwright 提供的核心方法,用于模拟拖放操作。它会处理底层的鼠标事件序列。
  • expect(...): playwright 的断言库,用于验证 dom 状态(元素是否存在、是否可见等)。它具有内置的智能等待机制。

3. 运行测试

在终端中,切换到包含 test_block_drag_drop.pydrag_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页面元素拖拽的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com