You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Playwright+TypeScript点击按钮后无法定位元素求助

Playwright + TypeScript自动化测试定位元素失败问题解决方案

问题描述

点击「Go to Registration」按钮后,注册输入字段及按钮无法被自动化测试识别,报错信息如下:

Error: locator.waitFor: Target page, context or browser has been closed
Call log:
- waiting for locator('xpath=//input[@type="password"]') to be visible

已确认元素不在iframe中,无需切换上下文,尝试等待密码字段和注册按钮可见均无效。

页面代码

<div class="min-h-screen flex items-center justify-center bg-gray-100">
<div class="bg-white p-8 rounded-lg shadow-md w-full max-w-md">
<h1 class="text-2xl font-bold mb-6 text-center">Registration Form</h1>
<form class="space-y-4">

<div>
<label class="block text-sm font-medium text-gray-700">Username:</label>
<input class="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500" type="text" value="" name="username">
</div>

<div>
<label class="block text-sm font-medium text-gray-700">Email:</label>
<input class="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500" type="email" value="" name="email">
</div>

<div><label class="block text-sm font-medium text-gray-700">Password:</label>
<input class="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500" type="password" value="" name="password"></div>

<div>
<label class="block text-sm font-medium text-gray-700">Confirm Password:</label>
<input class="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500" type="password" value="" name="confirmPassword">
</div>

<button type="submit" class="w-full bg-blue-600 text-white py-2 px-4 rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2">Register</button></form></div>
</div>

原始测试代码

import { test, expect, chromium } from '@playwright/test';

test.describe('Password Input Field Validation', () => {

  test('verify password input field validation error messages', async () => {

    const browser = await chromium.launch({
        executablePath: 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe',  // Specify path to your Chrome executable
        headless: false, // Set to false to run Chrome with UI visible
        slowMo: 2000, // Optional: adds a slight delay to make interactions visible
    });
    const page = await browser.newPage();

    // Navigate to the page
    await page.goto('https://page-url');
    
    // Click on the "Go to Registration" button
    await page.click('text=Go to Registration');

    // Verify password input field, when have less than 8 characters
    submitPasswordAndCheckErrorMessage(page, "Pass1", true);

    // Verify password input field, when password is without an uppercase letter
    submitPasswordAndCheckErrorMessage(page, "password1", false);

    // Verify password input field, when password is without an lowercase letter
    submitPasswordAndCheckErrorMessage(page, "PASSWORD1", false);

    // Verify password input field, when password is without number
    submitPasswordAndCheckErrorMessage(page, "Password", false);

    // Verify password input field, when password has least 8 characters with 1 uppercase, 1 lowercase, and 1 number
    submitPasswordAndCheckErrorMessage(page, "Password1"), true);

    await browser.close();
  }); 
});

export const submitPasswordAndCheckErrorMessage = async (page: any, password: string, isAllAvailableCharters: boolean) => {
    const passwordField = page.locator('//input[@type="password"]');
    console.log(`Filling password field with: ${password}`);  // Log the password before filling
   
    // Fill the password field with the provided password
    await passwordField.waitFor({ state: 'visible' });
    await passwordField.fill(password);
  
    // Click the "Register" button
    await page.click('text=Register');
  
    // Verify the error message is visible
    const errorMessage = await page.locator('text=Password must be at least 8 characters with 1 uppercase, 1 lowercase, and 1 number.');
    if (password.length <= 8 && isAllAvailableCharters == true) {
        await expect(errorMessage).not.toBeVisible();
    } else {
        await expect(errorMessage).toBeVisible();
    }
  };

解决方案

1. 修复异步函数未等待问题

测试代码中调用异步函数submitPasswordAndCheckErrorMessage时未添加await,导致代码直接执行到await browser.close(),浏览器提前关闭,后续异步操作找不到页面上下文,这是报错的核心原因。给每个函数调用加上await:

await submitPasswordAndCheckErrorMessage(page, "Pass1", true);
await submitPasswordAndCheckErrorMessage(page, "password1", false);
// ...其他调用同理

2. 修正定位器歧义

原定位器//input[@type="password"]会匹配页面上两个密码输入框(密码和确认密码),导致定位不准确。改用name属性精准定位目标输入框:

const passwordField = page.locator('input[name="password"]');

3. 修复语法错误

最后一个函数调用存在语法错误,多了一个括号,修正为:

await submitPasswordAndCheckErrorMessage(page, "Password1", true);

4. 优化测试结构(可选)

建议使用Playwright Test内置的测试上下文,无需手动启动和关闭浏览器,框架会自动管理生命周期,减少人为错误:

// 去掉手动启动浏览器的代码,改用test自带的page参数
test('verify password input field validation error messages', async ({ page }) => {
    await page.goto('https://page-url');
    await page.click('text=Go to Registration');
    // ...后续测试步骤
});

5. 修正条件判断逻辑

原代码中错误信息判断逻辑有误,比如password.length <=8应该是判断长度小于8,结合规则修正:

if (password.length >= 8 && isAllAvailableCharters) {
    await expect(errorMessage).not.toBeVisible();
} else {
    await expect(errorMessage).toBeVisible();
}

修正后的完整测试代码

import { test, expect } from '@playwright/test';

test.describe('Password Input Field Validation', () => {

  test('verify password input field validation error messages', async ({ page }) => {
    await page.goto('https://page-url');
    
    await page.click('text=Go to Registration');

    await submitPasswordAndCheckErrorMessage(page, "Pass1", true);
    await submitPasswordAndCheckErrorMessage(page, "password1", false);
    await submitPasswordAndCheckErrorMessage(page, "PASSWORD1", false);
    await submitPasswordAndCheckErrorMessage(page, "Password", false);
    await submitPasswordAndCheckErrorMessage(page, "Password1", true);
  }); 
});

export const submitPasswordAndCheckErrorMessage = async (page: any, password: string, isAllAvailableCharters: boolean) => {
    const passwordField = page.locator('input[name="password"]');
    console.log(`Filling password field with: ${password}`);
   
    await passwordField.waitFor({ state: 'visible' });
    await passwordField.fill(password);
  
    await page.click('text=Register');
  
    const errorMessage = page.locator('text=Password must be at least 8 characters with 1 uppercase, 1 lowercase, and 1 number.');
    if (password.length >= 8 && isAllAvailableCharters) {
        await expect(errorMessage).not.toBeVisible();
    } else {
        await expect(errorMessage).toBeVisible();
    }
  };

内容的提问来源于stack exchange,提问作者Māris L

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 15:44:52