扫码阅读
手机扫码阅读

《PlayWright全解析——从入门到精通》-5

762 2023-07-17

处理对话框

默认情况下,PlayWright会自动取消对话框(所有对话框都默认选择“取消”),我们这里所说的对话框包括alert, confirm, prompt。我们可以通过在触发对话框弹出之前,注册处理对话框的方式,看下面的例子:

1 2 
page.on('dialog', dialog => dialog.accept()); await page.getByRole('button').click(); 

当设置过dialog.accept()之后,整个page后续任何弹出对话框都会按照accept处理。

但是注意了,必须在处理对话框的函数中,最后调用dialog.accept()dialog.dismiss(),否则对话框因为没有接受到确认或取消事件,会卡住整个页面,看下面的例子,就将出现卡住的情况:

1 2 
page.on('dialog', dialog => console.log(dialog.message())); await page.getByRole('button').click(); // 会一直卡在这里 

处理新的弹出页面

对PlayWright来说,页面对应的就是Page对象,当我们点击一个链接弹出一个新页面的时候,可以使用注册一个popup事件,来处理新窗口。

举个例子,假设页面上链接,文字叫“点我”,点击后会弹出新页面:

1 2 3 4 5 6 7 
// 注册一个“弹出”的事件,注意这里是一个Promise对象 const newPagePromise = page.waitForEvent('popup'); await page.getByText('点我').click(); const newPage = await newPagePromise; // 等待新页面的弹出. await newPage.waitForLoadState(); console.log(await ponewPagepup.title()); 

如果并不清楚哪个操作会弹出新页面,那么可以事先注册on事件:

1 2 3 4 5 
// 这里注册的函数,会在后面任何当前Page上弹出新页面时触发 page.on('popup', async popup => {  await popup.waitForLoadState();  console.log(await popup.title()); }) 

Frame处理

还记得Selenium中是如何处理页面中的Frame的吗?是使用switch方法来做的。PlayWright的做法和Selenium有点类似,核心都是要先定位到页面中的frame,然后再对frame中的元素进行操作。

PlayWright中有两个和Frame相关的类,一个是Frame,一个是FrameLocator。所谓的Frame,是页面中的一个 或者元素对象,可以理解为一个独立的Page对象。

而FrameLocator则是指向Frame的一个定位器。

分别来看下如何使用:

1 2 3 4 5 6 7 8 
// 通过frame的name属性定位到frame对象 const frame = page.frame('frame-login');  // 通过iframe引入的url地址定位frame对象 const frame = page.frame({ url: /.*domain.*/ });  // 操作frame对象中的元素 await frame?.getByRole('button', { name: /submit/i }).click(); 

注意,page.frame()方法返回的是Frame|null,所以在使用frame进行后面的操作时,需要用frame?来判断是否为null。

page.frame()方法的参数可以是一个字符串,表示frame的name属性,或者是一个对象:

1 2 3 4 
{  name?: string, // 表示frame的name属性  url?: string|regexp, // 字符串或者正则表达式,表示iframe的url } 

再看看FrameLocator,其实就是混在locator中一起用:

1 2 3 
// 定位一个在frame中的元素 const username = await page.frameLocator('.frame-class').getByLabel('User Name'); await username.fill('John'); 

page.frameLocator()方法的参数是一个字符串,和page.locator()方法的参数一样,通常就是css选择器或者xpath表达式。

一个Locator如果定位正好是一个ifram元素,那么也可以直接转换成FrameLocator:

1 
const frameLocator = locator.frameLocator(':scope'); 

执行Javascript脚本

在PlayWright中可以使用page.evaluate()或者locator.evaluate()方法来执行脚本。执行的是一个匿名函数,或者说是一个闭包,以lambda表达式的形式体现,这个函数的返回值将传递给evaluate方法,作为这个方法的返回值。

看个简单的例子:

1 
const href = await page.evaluate(() => document.location.href); 

还可以传参数:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 
// 传数字参数 await page.evaluate(num => num, 42);  // 传数字数组. await page.evaluate(array => array.length, [1, 2, 3]);  // 传对象 await page.evaluate(object => object.foo, { foo: 'bar' });  // 传elementHandle对象. const button = await page.evaluate('window.button'); await page.evaluate(button => button.textContent, button);  // locator.evaluate()的用法 await button.evaluate((button, from) => button.textContent.substring(from), 5);  // 传多个elementHandle对象 const button1 = await page.evaluate('window.button1'); const button2 = await page.evaluate('window.button2'); await page.evaluate(  o => o.button1.textContent + o.button2.textContent,  { button1, button2 });  // 解构多个参数的方式 await page.evaluate(  ({ button1, button2 }) => button1.textContent + button2.textContent,  { button1, button2 });  // 也可以传对象数组 await page.evaluate(  ([b1, b2]) => b1.textContent + b2.textContent,  [button1, button2]);  // 混合类型的数组 await page.evaluate(  x => x.button1.textContent + x.list[0].textContent + String(x.foo),  { button1, list: [button2], foo: null }); 
原文链接: https://mp.weixin.qq.com/s?__biz=MzU5ODE2OTc1OQ==&mid=2247496373&idx=1&sn=16989cce1321622b759aa014378cfa10

TestOps 助力提升价值交付质效

27 篇文章
浏览 13.2K
加入社区微信群
与行业大咖零距离交流学习
软件研发质量管理体系建设 白皮书上线