现在位置: 首页 > Playwright 教程 > 正文

Playwright Frame 与新窗口

本章介绍如何处理 iframe、弹窗对话框、新标签页以及 Playwright 的事件系统。


iframe 操作

Playwright 通过 frameLocator() 来定位和操作 iframe 内的元素。

page.frameLocator() 定位 iframe

实例

test('操作 iframe 中的元素', async ({ page }) => {
  await page.goto('https://www.runoob.com/iframe-demo');

  // 定位 iframe,然后在其中定位元素
  const iframe = page.frameLocator('#my-iframe');

  // 在 iframe 内操作元素
  await iframe.getByRole('button', { name: '提交' }).click();
  await iframe.getByLabel('用户名').fill('runoob_user');

  // 在 iframe 内断言
  await expect(iframe.getByText('操作成功')).toBeVisible();
});

获取所有 Frame

实例

// 获取页面中所有 frame(包括主 frame 和 iframe)
const frames = page.frames();
console.log('页面共', frames.length, '个 frame');

frames.forEach(frame => {
  console.log('Frame:', frame.name(), frame.url());
});

嵌套 iframe

Playwright 的 frameLocator() 支持链式调用,可以深入嵌套的 iframe。

实例

// 嵌套 iframe:外层 → 内层 → 元素
const innerButton = page
  .frameLocator('#outer-frame')
  .frameLocator('#inner-frame')
  .getByRole('button', { name: '确认' });

await innerButton.click();

弹窗处理(Dialogs)

Playwright 对浏览器原生弹窗(alert、confirm、prompt)有默认处理策略。

默认行为

Playwright 默认自动关闭所有弹窗:

弹窗类型默认行为
alert()自动确认(关闭)
confirm()自动确认(返回 true)
prompt()自动确认(返回空字符串)

自定义弹窗处理

通过 page.on('dialog') 可以拦截并自定义处理弹窗。

实例

test('自定义处理弹窗', async ({ page }) => {
  // 在触发弹窗之前注册监听器
  page.on('dialog', async dialog => {
    console.log('弹窗类型:', dialog.type());
    console.log('弹窗消息:', dialog.message());

    if (dialog.type() === 'confirm') {
      // 取消确认框
      await dialog.dismiss();
    } else if (dialog.type() === 'prompt') {
      // 输入自定义内容
      await dialog.accept('RUNOOB 输入的内容');
    } else {
      // 其他类型直接确认
      await dialog.accept();
    }
  });

  // 触发弹窗的操作
  await page.getByRole('button', { name: '删除' }).click();
});

Dialog 对象方法

方法说明
dialog.accept(promptText?)确认弹窗(prompt 时可传入输入文本)
dialog.dismiss()取消弹窗
dialog.message()获取弹窗的提示消息
dialog.type()获取弹窗类型:'alert' | 'confirm' | 'prompt' | 'beforeunload'

新窗口与新标签页

当点击链接或按钮打开新标签页时,Playwright 提供了多种方式来获取新页面。

page.waitForEvent('popup') 等待弹窗

实例

test('处理新标签页', async ({ page }) => {
  // 在点击之前先准备等待新页面事件
  const popupPromise = page.waitForEvent('popup');

  // 点击打开新窗口的链接
  await page.getByRole('link', { name: '新窗口打开' }).click();

  // 获取新打开的页面
  const popup = await popupPromise;

  // 在新页面上操作
  await expect(popup).toHaveTitle(/RUNOOB/);
  await popup.getByRole('button', { name: '确定' }).click();

  // 关闭新页面
  await popup.close();
});

context.on('page') 监听新页面

实例

test('监听 Context 中所有新页面', async ({ context, page }) => {
  // 监听整个 Context 中的新页面创建
  context.on('page', async newPage => {
    console.log('新页面打开了:', newPage.url());
    // 等待新页面加载完成
    await newPage.waitForLoadState();
    // 在新页面上操作
  });

  await page.goto('https://www.runoob.com/');
  // 后续打开新窗口的操作会自动触发上述监听器
});

Playwright 事件系统

Playwright 的 Page 和 Context 对象都是事件发射器,你可以监听各种事件。

常用页面事件

事件触发时机
request页面发起网络请求时
response收到网络响应时
dialog出现 alert/confirm/prompt 弹窗时
download开始下载文件时
popup新页面(弹窗/新标签页)打开时
console页面输出 console 消息时
pageerror页面出现未捕获的 JavaScript 错误时
load页面加载完成时
close页面关闭时

事件监听方法

实例

// 持续监听
page.on('request', request => {
  console.log('请求:', request.method(), request.url());
});

// 单次监听(触发一次后自动移除)
page.once('dialog', dialog => {
  dialog.accept();
});

// 移除监听
const handler = (request) => { /* ... */ };
page.on('request', handler);
page.off('request', handler);