自動化測試 x Puppeteer - 玩偶QA參一咖 Day06


今日任務: DOM 陣列操作

下圖為自己簽署當中,Assign 標籤的頁面,假設我們想要把元素放到指定的位子,和之前一樣,我們需要先透過 selector 找到頁面上的元素,再將滑鼠移動到指定的位子然後點擊。大家可以發現,左側所有的欄位,它們的 selector (在這邊是 class )都是一樣的,所以才對今天的任務下了「DOM陣列操作」的命名。

在本日任務中,將會示範把簽名(Signature)放入頁面的過程。

動作A:索取到頁面左側所有的元素

  1. Inspect 左側元素,發現它們的 class 是 "sc-hARARD.dlziMd"
  2. 在A區塊寫下
    const fields = page.$$(".sc-hARARD.dlziMd")
    console.log("The length of fields is ", fields.length) //利用console.log看看fields裡面有幾個元素,預期是六個。
    

執行程式,卻得到0個結果,然後也沒有 Error Message 。這是因為它尋找對應元素時,該元素還沒有被 loading 到頁面上,所以我們的確會得到0這個答案。

為了確定頁面有先 load 進我們的目標元素,我們可以在剛剛的程式碼上方加入

awiat page.waitForSelector(".sc-hARARD.dlziMd")

這次就會是6個了。


動作B: 點選簽名欄位(Signature)

在有了 fields 變數之後,要對 Signature 進行操作就變得非常簡單,我們在B區塊當中寫下

await fields[0].click

結果卻什麼都沒有反應,坦白說這是我預期之外的事情XD,因為我自己之前是這樣子做但是很順利地就成功點擊了,不過沒關係,在 Issues 上也有人有相同的困擾,他們也提供了一些方法來代替click。
(link:https://github.com/puppeteer/puppeteer/issues/3347 (ctrl+f: evaluate))
(link:https://github.com/puppeteer/puppeteer/issues/2526 (ctrl+f: querySelectorAll 第三個))

參考了上面的兩個連結,看到有一個我們之前都沒有用過的函式,evaluate,其中,我們參考上方圖片當中提供的做法,其程式碼為

await page.evaluate(() => { document.querySelectorAll('.qv64e')[1].click(); });

我們可以利用 evaluate 把想要執行的動作包在裡面,而因為我們的動作是單純的 click 事件,並不需要回傳什麼東西,所以箭頭(=>)符號前面放一個空的小括號就可以了,在 Puppeteer的技術文件當中也有提到一些有回傳值的例子,大家可以看看。

總之,上方程式碼和我們想要做的事情非常的相近,可以代替 page.click,而且也能同時透過陣列的形式指定操作元素,非常的方便。

所以我們把B區塊的程式碼改成
await page.evaluate(() => { document.querySelectorAll('.sc-hARARD.dlziMd')[0].click(); });
這時候應該就可以得到我們預期的畫面了


動作C: 點選 Eric (如果有遇到沒有姓名標籤的情況,這要先建立一個自己的簽名,建一次就一勞永逸了)

  1. Inspect 發現它的class是 "sc-jQMNup.bugmmO"
  2. 在C區塊再次嘗試基本的 click 動作XD(希望這次不要沒有反應),不過因為自己有以前的經驗,知道會需要等待頁面 loading 元素,所以我們也加上 waitForSelector
    await page.waitForSelector(".sc-jQMNup.bugmmO")
    await page.click(".sc-jQMNup.bugmmO")
    

    這時候右上方就會跳出 Apply 按鈕

動作D: 點擊Apply按鈕

  1. Inspect 發現它的 class 是 "sc-fjdhpX.cXKOsV"
  2. 在D區塊寫下,
    await page.click(".sc-fjdhpX.cXKOsV")
    
    這時候會發現自己的滑鼠變成十字,這是在提示我們可以進行下一個動作了,要移動滑鼠到指定位置,並左鍵頁面。

動作E: 左鍵頁面

在E區塊寫下:

await page.waitFor(1)
await page.mouse.click(500,175) // 大家可以針對自己喜歡的位置做調整

這裡的程式碼很直覺,page.mouse.click(500,175),後面的座標就是我們希望它點的地方。至於為甚麼會需要 waitFor(1),是因為我發現如果少了這行程式碼,click 事件就沒有如預期的做出我們想要做的事情。一般而言,是不希望看到使用 waitFor(x) 這種函式,因為它會降低程式的執行效率,不過在這裡的情況比較不同,我們不像是之前可以 waitForSelector 可以等待元素出現之後立即下一個動作,我們現在是要對滑鼠做動作,並沒有像是 waitForMouse 之類的函式,所以我們就折衷使用 waitFor(1)來確保mouse.click可以順利被觸發。

下圖為執行成果:

有將簽名檔順利地放上我們的檔案就算是完成今日的任務了,以下是目前的程式碼,


今天的總結:

  1. 在點擊陣列中其中一個元素時,雖然沒有順利地被執行,但也因此多認識了 page.evaluate 的辦法。(參考動作A)
  2. 有時候要 Assign 頁面元素給變數時,可以利用 waitForSelector 確保元素有真的存在。(參考動作C)
  3. page.mouse.click(x,y)的用法(參考動作E)

下回預告: 做到這邊的大家應該都已經非常熟悉 Puppeteer 的語法了,在明天我們就會把剩下的一點點的操作完成了!

#Puppeteer





在此系列文章中以Kdan Mobile主打服務之一的DottedSign做為Puppeteer的實作範例,從最開始的「環境建置」到稍微複雜的「切換頁面、上傳檔案」皆會走過,看完系列文章後我們就會得到一個能獨立完成任務的QA程式了呦^_^

留言討論