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
相关产品推荐
相关产品推荐

