First touch with Puppeteer

Paul Li
7 min readJan 16, 2022

--

First touch with Puppeteer
First touch with Puppeteer

Introduction

Chrome DevTools 於 VER.97 隆重推出 Recorder Panel,讓 user 可以透過該功能來做些使用行為的紀錄甚至是自動化流程。User 可以憑藉頁面的操作行為讓 Chrome 將之轉換成 end to end testing 的 JavaScript code,以利日後再利用。除此之外,更可以將之匯出,分享給其他人~

玩過之後,發現它背後實際上是透過 Puppeteer 來加持並且完成這樣的 automation,也因為這樣,讓筆者想知道 Puppeteer 的點點滴滴,與 selenium 間的差異又是什麼?

經過簡單的 survey 之後,Puppeteer 可以跟 Chrome 做緊密的結合,並且透過 headless 的參數設置讓部署更加容易外,語法上亦包裝得更細緻,也因此撰寫起來更加的直覺,可以很快撰寫出我們所需要的 flow 出來。語法使用主要是透過 front-end 所熟悉的 CSS Selector 來快速找到 element 後,便可以透過一些操作,比方說:type、select、click、waitFor* …etc,便可以有效的模擬出一些操作出來。

由於非常直覺,所以筆者便能在很短的時間內便對自家服務 TW Yahoo 奇摩拍賣撰寫出簡單的一條龍測試(GitHub)。

相關的 step 如下所示:

  1. As a seller, I could submit a new merchandise.
  2. As a buyer, I could purchase merchandise.
  3. As a buyer, I could cancel an order.
  4. As a seller, I could terminate merchandise.

Useful API

透過 Puppeteer API 文件中可以發現它支援的 method 非常非常多,對於初學者來說可能會有點亂,所以筆者將透過上述的 automation 將幾個會用到的使用情境與大家分享~

Puppeteer 的起手式非常的容易,在安裝完 Puppeteer 後,只要透過下列的 code 便可以開啟一個新的瀏覽器頁籤出來。Developers 可以設置 launch 時所需要的條件來打造出所需要的測試環境出來。

測試不外乎就是「做了什麼樣的操作」、「期待什麼樣的結果」所組成的集合,即便 Pupeteer 提供這麼多樣的 Class 供 developer 操作,但大多均可以在 Page 以及 ElementHandle 間完成。只要熟悉這兩個 Class 所提供的 method,便可以輕鬆玩轉 80% 以上的操作行為了~

page.goto

前往特定頁面進行測試一直都是測試的第一步驟,Developer 可以透過 page.goto 進行前往特定網址的操作。

page.waitForSelector

由於有越來越多 client side render 的 web page,所以在進行任何操作之前,可以先透過 page.waitForSelector 來進行 element 是否已經 ready 的試探,default timeout 為 30 秒,可以藉由參數設置調整所需要的 timeout。

如上所示,適時的搭配 CSS Selector > :not(:empty) 亦可用來偵測部分 module 是否已經 ready。

page.waitForFunction

友善的 developer 總會讓頁面元素留下一些線索,方便我們知道特定操作的前後變化,它可能 classname、attribute 或者是 data-*,但是總是有例外的時候會發生,好比 TW Yahoo 拍賣 IM 的 text message,發送後就很單純只會 append 一個 message element 上去,也因為這樣,便無法直接透過 page.waitForSelector 來進行偵測了。

這時候可以搭配 page.waitForFunction 來自行定義我們所想監聽的變化,可以說彈性非常。

page.click、page.tap

確認 element ready 後,便可以開始進行一些操作,可以依照一開始設置的環境來搭配不同的點擊行為,page.click 基本上就是 mouse 的延伸,page.tap 則是 touchscreen 的延伸。早期比較嚴謹,這種 click 的行為僅能被用在那些可供點擊的 element 上,比方說 <a /><button /><input type=submit />上,不過 Puppeteer 打破這樣的限制,所以即使指定的是不可點擊 element,一樣可以正常運作不受影響。

page.waitForNavigation

當點擊了連結或者是會轉導頁面的行為時,通常都會偵測頁面是否已經完成轉導?便可以透過這個 page.waitNavigation 這個 method 來完成這樣的需求。

page.type

很多時候均需要進行一些 form elements 的操作,比方說 input[type=text] 內容的輸入等,便可以透過 page.type 來完成內容的輸入,不過要特別注意的是它是 append 的行為,並不會先做 clear 再 input,所以使用上要特別注意。

page.select

<select /> 也是 form element 操作的一員,透過 page.select 便可以針對特定的 element 進行賦值的行為。

elementHandle.uploadFile

上傳檔案亦是一門學問,比方說新增商品的時候總是免不了需要上傳商品圖片,要如何在 Puppeteer 中完成這樣的行為呢?這些 Puppeteer 通通都幫我們想好了,亦包裝了非常方便的 method 可以使用。

如下方的 code 所示,我們先透過 page.$ 找出 input[type=file] 這個 element 後(可取得 elementHandle),這時候再透過 elementHandle.uploadFile 來完成選取檔案的行為。

page.$eval、page.$$eval

雖然說 Puppeteer 已經封裝了很多實用的 methods,不過總是會有不堪用的情境出現,這時候 developers 可以透過 page.$eval、page.$$eval 直接掃出所需要的 elements 後,透過 callBack function 直接對 DOM 進行操作,便可以完成各式奇巧的行為了,可以說是終極的 methods。

Clear cookie

由於筆者需要在不同的登入身份進行切換,雖然說可以透過 cookie 的注入與清除來達到身份切換,但總是沒有直接清除 cookie 來的優雅與確實。所以可以透過清除 cookie 後再來完成 Yahoo login process,便可以輕易地完成身份切換。

透過上述的這些 method 交錯組合,便可以輕輕鬆鬆完成 80% 以上的 user interaction,是不是非常簡單且直覺?彈指之間便可以為服務打造出簡單的一條龍測試,趕快試試看吧~

#Puppeteer #EndToEndTesting #automation

Reference

--

--

Paul Li

Paul is the lead programmer of the AMP project at Yahoo Taiwan and is always eager for modern web technologies. He is also focusing on UX for vivid user flow.