8

微软出品自动化神器【Playwright+Java】系列(九)多线程、重定向、弹出新窗口、截图...

 1 year ago
source link: https://www.cnblogs.com/longronglang/p/17132832.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

关于Playwright系列的文章,真的很久没有写了,今天一个不小心官方API部分过完了,下面将为大家逐一演示,感兴趣的同学可以自行动手练习。

API部分

直白点说就是多线程下Playwright的使用,示例代码如下:

java
package org.example;

import com.microsoft.playwright.*;

import java.nio.file.Paths;

import static java.util.Arrays.asList;

public class PlaywrightThread extends Thread {
  private final String browserName;

  private PlaywrightThread(String browserName) {
    this.browserName = browserName;
  }

  public static void main(String[] args) throws InterruptedException {
    for (String browserName: asList("chromium", "webkit", "firefox")) {
      Thread thread = new PlaywrightThread(browserName);
      thread.start();
    }
  }

  @Override
  public void run() {
    try (Playwright playwright = Playwright.create()) {
      BrowserType browserType = getBrowserType(playwright, browserName);
      Browser browser = browserType.launch();
      Page page = browser.newPage();
      page.navigate("https://www.baidu.com/");
      page.locator("#kw").type("久曲健 博客园");
      page.locator("#kw").press("Enter");
      page.screenshot(new Page.ScreenshotOptions().setPath(Paths.get("user-agent-" + browserName + ".png")));
    }
  }

  private static BrowserType getBrowserType(Playwright playwright, String browserName) {
    switch (browserName) {
      case "chromium":
        return playwright.chromium();
      case "webkit":
        return playwright.webkit();
      case "firefox":
        return playwright.firefox();
      default:
        throw new IllegalArgumentException();
    }
  }
}

重定向到指定页面

跳转到指定页面,示例代码如下:

java
/**
 * @decription 跳转到指定页面
 * @author longrong.lang
 * @date 2023/02/18 9:15
 * @return: void
 */
@Test
public void testNavigations() {
    // 跳转到百度页面
    page.navigate("https://www.baidu.com/");
    //等待网络空闲是跳转
    page.navigate("https://www.baidu.com/", new Page.NavigateOptions()
            .setWaitUntil(WaitUntilState.NETWORKIDLE));
}

它有显示等待和页面交互操作自动等待,相比Selenium来比的话,对异步操作有自己的处理机制,示例代码如下:

java
/**
 * @decription 元素等待
 * @author longrong.lang
 * @date 2023/2/17 14:09
 * @return: void
 */
@Test
public void testWaitElement(){
    //在延迟加载的页面中,使用 Locator.waitFor()等待元素可见可能很有用。
    page.navigate("https://www.baidu.com/");
    page.locator("#kw").waitFor();
    //Page.click()这样的页面交互会自动等待元素。
    page.navigate("https://www.baidu.com/");
    page.locator("#kw").type("test");
    //自定义等待
    page.locator(".toindex").click(); //点击跳转
    page.waitForLoadState(LoadState.NETWORKIDLE); // 这在“网络空闲”之后处理
    //显示等待(异步调用建议使用)
    page.navigate("asynchronousProcessing.html");
    page.waitForNavigation(()->{
        page.locator("#submit").click(); //123主页
    });
    //单击一个元素可能会触发多个异步
    page.waitForNavigation(new Page.WaitForNavigationOptions().setUrl("**/login"), () -> {
        page.locator("#submit").click();
    });

}

弹出窗口处理

这个案例很有意思,在写对应的html案例时,发现这东西只在ie浏览器上生效( createPopup()方法只适用在IE !),这里还请读者朋友注意,所以你跑脚本报错,并不是你代码的问题哦,示例代码如下:

java
/**
 * @decription 弹出窗口处理
 * @author longrong.lang
 * @date 2023/02/18 11:08
 * @return: void
 */
@Test
public void testPopup(){
    // createPopup()方法只适用在IE !
    page.navigate("http://localhost:8080/proup_demo.html");
    Page popup = page.waitForPopup(() -> {
        page.locator("[onclick]").click();
    });
    popup.waitForLoadState(LoadState.LOAD);
}

分为快速截图、整页截图、存到缓存区、按照元素区域截图,示例代码如下:

highlighter- Go
/**
 * @decription 截图操作
 * @author longrong.lang
 * @date 2023/02/18 11:08
 * @return: void
 */
@Test
public void testScreenshot(){
    page.navigate("https://www.baidu.com/");
    //快速截图
    page.screenshot(new Page.ScreenshotOptions()
            .setPath(Paths.get("screenshot1.png")));
    //整页截图
    page.screenshot(new Page.ScreenshotOptions()
            .setPath(Paths.get("screenshot2.png"))
            .setFullPage(true));
    //存到缓冲区
    byte[] buffer = page.screenshot();
    System.out.println(Base64.getEncoder().encode(buffer));
    //按照元素区域截图
    page.locator("#kw").screenshot(new Locator.ScreenshotOptions().setPath(Paths.get("screenshot3.png")));
}

处理新页面

就是新句柄处理,只不过是连个窗口罢了,超链接带target="_blank"标识,示例代码如下:

java
/**
 * @decription 新窗口处理
 * @author longrong.lang
 * @date 2023/02/18 11:53
 * @return: void
 */
@Test
public void testHandlingNewPage() {
    page.navigate("https://www.baidu.com/");
    Page newPage = context.waitForPage(() -> {
        page.locator("#s-top-left .c-color-t:nth-of-type(4)").click();
    });
    newPage.waitForLoadState();
    System.out.println(newPage.title());
}

录制生成脚本

启动命令如下:

cmd
mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI -D exec.args="codegen www.baidu.com"

54ef506190df47098e2d2b7b23e1a008~tplv-k3u1fbpfcp-watermark.image?

模拟指定窗口大小录制

运行命令如下:

cmd
mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI -D exec.args="codegen --viewport-size=800,600 www.baidu.com"

edb680e04d024881b9fc8b74836c38ce~tplv-k3u1fbpfcp-watermark.image?

模拟设备录制

运行命令如下:

cmd
mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI -D exec.args='codegen --device="iPhone 11" playwright.dev'

我这执行完报错,不到为啥,也不到官方是怎么成功的,很好奇!

用python的打开命令居然能,很诡异是抗拒Java吗?

python
playwright open --device="iPhone 13 Pro" www.baidu.com

661b287b96e94c05abbeb1b63bb2eeb9~tplv-k3u1fbpfcp-watermark.image?

使用Playwright,脚本录制结束后会自动生成视频,示例代码如下:

java
context = browser.newContext(new Browser.NewContextOptions().setRecordVideoDir(Paths.get("videos/")));  
//确保context关闭,以便保存视频。  
context.close();

页面对象模式

这个可以用SeleniumpageObject模式一样,目的是为了代码维护方便,这里我以登录功能为例进行演示,登录页面需要存放元素定位和控件操作行为,示例代码如下:

java
package org.example;


import com.microsoft.playwright.Locator;
import com.microsoft.playwright.Page;
/**
 * @description 存放页面控件及操作
 * @author longrong.lang
 * @version 1.0
 * @date 2023/02/18 15:07
 */
public class LoginPage {
  private final Page page;
  private final Locator username;
  private final Locator password;
  private final Locator login_btn;
  private final Locator error_msg;


  public LoginPage(Page page) {
    this.page = page;
    this.username = page.locator("input[type='text']");
    this.password = page.locator("[type='password']");
    this.login_btn = page.locator("button");
    this.error_msg = page.locator("#alert");
  }

  public void open() {
    page.navigate("http://localhost:8080/login");
  }

  /**
   * @decription 登录操作
   * @author longrong.lang
   * @date 2023/02/18 15:03
   * @param user
   * @param pwd
   * @return: java.lang.String
   */
  public String login(String user,String pwd) {
    open();
    username.fill(user);
    password.fill(pwd);
    login_btn.click();
    String content = error_msg.textContent();
    return content;
  }
}

测试类部分,示例代码如下:

java
package org.example;

import com.microsoft.playwright.*;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

/**
 * @description 测试登录功能
 * @author longrong.lang
 * @version 1.0
 * @date 2023/02/18 15:07
 */
public class TestLogin {
    static Playwright playwright;
    static Browser browser;
    static BrowserContext context;
    static Page page;
    @BeforeClass
    static void launchBrowser() {
        playwright = Playwright.create();
        browser = playwright.chromium().launch(new BrowserType.LaunchOptions()
                .setHeadless(false));
        context = browser.newContext();
        page = context.newPage();
    }

    @Test
    public void testLogin() {
        LoginPage loginPage = new LoginPage(page);
        String errorMsg = loginPage.login("1", "1");
        Assert.assertEquals(errorMsg,"用户名或密码错误!");
    }

    @AfterClass
    public void afterClass() {
        browser.close();
        context.close();
        playwright.close();
    }
}

总的来说,还是很开心的,而且很有成就感,终于把Playwright+Java系列教程写完了。

可能有些同学会好奇说,网上不是有都是吗,你可以找找Java系列,我敢说,即便是有大部分抄袭我的比较多,抄袭我能理解加个出处行吗?如下图:

72f6faa2df904dd19aa815f0cff4f385~tplv-k3u1fbpfcp-watermark.image?

真的突然让我想到了洲哥那句话,总会有那么几个让你恶心的狗逼,但已经被恶心了就恶心了,随它去吧!

开心的是,证明我写的还是不错的,要不他也不能抄袭不是吗?

__EOF__


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK