Nội dung bài học

Selenium WebDriver cho phép bạn giao tiếp với các trình duyệt khác nhau để thực hiện các lệnh và xác nhận trên các phần tử DOM.

Tuy nhiên, có những trường hợp mà các lệnh Webdriver thực tế sẽ không hoạt động hiệu quả như mong đợi. Đây là lúc JavaScriptExecutor xuất hiện bổ trợ cho chúng ta.

Trong bài viết này, chúng ta sẽ thảo luận về JavaScriptExecutor trong Selenium WebDriver. Cách khai báo, cách sử dụng JavaScriptExecutor trong Selenium. Chúng ta sẽ đi sâu hơn vào việc triển khai và khám phá các hàm khác nhau trong JavascriptExecutor cùng với các ví dụ thực tế.

JavaScriptExecutor trong Selenium là gì?

JavaScriptExecutor là một giao diện được cung cấp bởi Selenium Webdriver, trình bày cách thực thi JavaScript từ Webdriver. Giao diện này cung cấp các phương pháp để chạy JavaScript trên cửa sổ đã chọn hoặc trang hiện tại. JavaScriptExecutor là một giao diện có sẵn cho tất cả các ngôn ngữ hỗ trợ Selenium Framework .

Vì JavaScriptExecutor là một giao diện Selenium, nên không cần thêm plugin hoặc tiện ích bổ sung. Bạn có thể sử dụng nó trực tiếp bằng cách nhập gói  org.openqa.selenium.JavascriptExecutor.


Tại sao sử dụng JavaScriptExecutor trong Selenium?

Riêng Selenium Webdriver cho phép bạn thực hiện các thao tác trên các phần tử web như gửi dữ liệu, nhấp vào các nút, v.v. Tuy nhiên, như đã nói trước đây, có những trường hợp mà các lệnh của Webdriver sẽ không hoạt động như mong đợi do nhiều lý do khác nhau. Trong những trường hợp này, chúng tôi sẽ nhờ đến sự trợ giúp của JavaScriptExecutor.

Ví dụ: theo truyền thống để xác định vị trí một phần tử web, chúng ta sử dụng các chiến lược định vị web khác nhau như ID, Tên, bộ chọn CSS và XPath, v.v. Nếu các trình định vị này không hoạt động như mong đợi hoặc bạn đang xử lý một XPath phức tạp, bạn có thể sử dụng JavaScriptExecutor để thực hiện thao tác mong muốn trên WebElement.

Trên các dòng tương tự, để nhấp vào WebElement, chúng ta thường sử dụng click() phương pháp được cung cấp bởi Selenium Webdriver.

Đôi khi, phương thức click() có thể không hoạt động trên tất cả các trình duyệt web hoặc các điều khiển web có thể hoạt động khác nhau trên các trình duyệt khác nhau. Hay nó bị che bởi 1 phần tử khác chẵn hạn. Để khắc phục những tình huống như vậy, giao diện JavaScriptExecutor được sử dụng.

Như chúng ta đã biết, các trình duyệt có triển khai Javascript bên trong chúng và có thể hiểu các lệnh JavaScript. Do đó, hiểu JavaScriptExecutor trong Selenium sẽ cho phép bạn thực hiện một loạt các hoạt động hiệu quả và thanh lịch hơn.

 

Giới thiệu về các phương thức JavaScriptExecutor

JavaScriptExecutor trong Selenium cung cấp hai phương pháp mà qua đó chúng ta có thể chạy JavaScript trên cửa sổ đã chọn hoặc trang hiện tại.

a) executeScript

Phương thức này thực thi JavaScript trong ngữ cảnh của cửa sổ hoặc khung hiện đang được chọn trong Selenium. Tập lệnh sẽ được thực thi dưới dạng phần thân của một hàm ẩn danh.

b) executeAsyncScript

Phương thức này thực thi một đoạn mã JavaScript không đồng bộ trong ngữ cảnh của cửa sổ hoặc khung hiện đang được chọn trong Selenium. Ở đây, tập lệnh sẽ được thực thi dưới dạng phần thân của một hàm ẩn danh. Sự khác biệt chính giữa executeScript và executeAsyncScript là tập lệnh được gọi bằng thực thi executeAsyncScript phải báo hiệu về việc hoàn thành thực thi bằng cách sử dụng hàm gọi lại.

Các phương thức gọi sử dụng executeAsyncScript chủ yếu được sử dụng khi chế độ ngủ phải được thực hiện trong trình duyệt đang thử nghiệm hoặc khi các thử nghiệm phải được đồng bộ hóa trong ứng dụng AJAX.

Cả hai phương pháp đều cho phép chúng tôi trả về một giá trị bằng cách sử dụng từ khóa return và lưu trữ chúng trong một biến. Các kiểu dữ liệu có thể được trả về là:

  • Long
  • String
  • Boolean
  • List
  • WebElement

Cú pháp cơ bản của JavaScriptExecutor trong Selenium

Mục đích của phần này là cung cấp ý tưởng cấp cao về các bước triển khai của JavaScriptExecutor trong Selenium. Để chứng minh, chúng tôi đã sử dụng Java làm ngôn ngữ lập trình ưa thích.

Chúng ta hãy xem xét các bước chính.

Bước 1: Import package JavascriptExecutor.

Bước 2: Bây giờ để sử dụng JavascriptExecutor, hãy tạo một tham chiếu cho giao diện và gán nó cho cá thể WebDriver với cú pháp:

JavascriptExecutor js = (JavascriptExecutor) driver;

 

Bước 3: Chúng ta đã tạo một tham chiếu JavascriptExecutor. Bây giờ chúng ta gọi các phương thức executeAsyncScript / executeScript. Cú pháp cho executeScript đượcthể hiện dưới đây:

js.executeScript​(java.lang.String script, java.lang.Object... args)

Thông số:

script - JavaScript để thực thi
args - Các đối số của script. Có thể trống.

Trả lại giá trị

Boolean / Long / Double/ String/ List / Map / WebElement / Null.

 

Các tình huống sử dụng JavaScriptExecutor trong Selenium

Một số tình huống chúng ta có thể xử lý bằng cách sử dụng Giao diện JavaScriptExecutor

1. Nhấp vào một Element

js.executeScript("document.getElementById('id_of_element').click();");
//hoặc
js.executeScript("arguments[0].click();", buttonLogin);

Khi mà Selenium nó báo là không thể tương tác hay không thể click vào một phần tử web nghĩa là có thể nó đang bị che hoặc chưa load lên UI kịp thời. Khi đó thằng Javascript này nó click dựa vào DOM nên nó không quan tâm bị che. Có ví dụ code chạy bên dưới.


2. Để nhập văn bản vào hộp văn bản mà không sử dụng phương thức sendKeys ()

js.executeScript("document.getElementById('email').setAttribute('value','admin02@mailinator.com');");
js.executeScript("document.getElementById('password').setAttribute('value','123456');");

"value" là thuộc tính trong thẻ input. Ngoài thuộc tính "value" thì có thể dùng các thuộc tính còn lại như "placeholder", "innerHTML",...


3. Để xử lý Checkbox bằng cách chuyển giá trị là true hoặc false

js.executeScript("document.getElementById('id_of_element').checked=false;");
//hoặc
js.executeScript("document.getElementById('id_of_element').checked=true;");


4. Để tạo Alert trong Selenium Webdriver

js.executeScript("alert('Welcome To Anh Tester - Automation Testing');");


5. Để làm mới cửa sổ trình duyệt bằng Javascript

js.executeScript("history.go(0)");


6. Để lấy nội dung của toàn bộ trang web trong Selenium

String innerText = js.executeScript("return document.documentElement.innerText;").toString();
System.out.println(innerText);


7. Để lấy Tiêu đề của trang web

String titleText = js.executeScript("return document.title;").toString();
System.out.println(titleText);


8. Để lấy tên miền

String domainName= js.executeScript("return document.domain;").toString();
System.out.println(domainName);


9. Để lấy URL của một trang web

String url= js.executeScript("return document.URL;").toString();
System.out.println(url);


10. Để lấy Chiều cao và Chiều rộng của một trang web

js.executeScript("return window.innerHeight;").toString();
js.executeScript("return window.innerWidth;").toString();


11. Để tìm một phần tử ẩn (bị khuất) trong Selenium bằng JavaScriptExecutor

js.executeScript("arguments[0].click();", element);


12. Để điều hướng đến một trang khác bằng Javascript

js.executeScript("window.location = 'https://anhtester.com'");


13. Để thực hiện Cuộn chuột

a) Để cuộn trang theo chiều dọc 500px

js.executeScript("window.scrollBy(0,500)");


b) Để cuộn trang theo chiều dọc cho đến hết (cuối trang)

js.executeScript("window.scrollBy(0,document.body.scrollHeight)");


c) Để cuộn tới 1 phần tử trong trang (này dùng nhiều)

WebElement element = driver.findElement(By.id("id_of_element"));

js.executeScript("arguments[0].scrollIntoView(true);", element);



14. Thêm một phần tử trong DOM

Chúng ta cũng có thể thêm một phần tử trong DOM nếu được yêu cầu. Tuy nhiên, vì chỉ liên quan đến việc bắt chước các tương tác của người dùng trong trình duyệt, tùy chọn này có thể không được sử dụng.

js.executeScript("var btn=document.createElement('newButton');" + "document.body.appendChild(btn);");

 

15. Set và Get giá trị vào LocalStorage trên Browser

LocalStorage là nơi trong Browser để chứa các biến (Key) kèm giá trị tương ứng tồn tại trong suốt quá trình mở Browser đó. Giống giống Properties á. Mình có thể tận dụng để Set và Get giá trị trong quá trình chạy auto có sự chuyển trang chuyển tab gì đó xong sẽ dùng lại giá trị ban đầu thì LocalStorage rất hiệu quả đây.


Set giá trị vào LocalStorage trên Browser:

js.executeScript("window.localStorage.setItem(arguments[0],arguments[1])","key","value");

Ví dụ: js.executeScript("window.localStorage.setItem(arguments[0],arguments[1])","age","30");

Thì nó sẽ set giá trị 30 vào biến "age" trong browser. Lúc bấy giờ mình sẽ gọi hàm get để lấy nó ra dùng là xong.


Get giá trị từ LocalStorage trên Browser:

(String) js.executeScript("return window.localStorage.getItem(arguments[0])", "key");

Ví dụ: tiếp tục của ví dụ trên thì mình sẽ gọi key "age" ra để lấy giá trị 30:

String localGetVar = (String) js.executeScript("return window.localStorage.getItem(arguments[0])", "age");

Vậy là xong !!!


Chú ý:

Chúng ta có các hàm document.getElementBy* sau:

[Selenium Java] Bài 14: Cách dùng Javascript Executor để hành động | Anh TesterNó không có Xpath đâu nhen =))


Các lệnh Javascript tham khảo thêm:

https://www.w3schools.com/jsref/default.asp

 

Code demo JavascriptExecutor

package anhtester.com;

import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebElement;
import org.testng.annotations.Test;

public class TestJavaScript extends SetupBrowser {

    @Test
    public void jsExecutorDemo01() throws InterruptedException {
        // Creating the JavascriptExecutor interface object
        JavascriptExecutor js = (JavascriptExecutor) driver;

        driver.get("https://anhtester.com/");
        Thread.sleep(1000);

        // Click on "Website Testing" module using JavascriptExecutor
        WebElement button = driver.findElement(By.xpath("//h3[normalize-space()='Website Testing']"));
        js.executeScript("arguments[0].click();", button);
        Thread.sleep(1000);

        // Get page title and Domain using JavascriptExecutor
        String titleText = js.executeScript("return document.title;").toString();
        System.out.println("Page Title is: " + titleText);

        String domainName = js.executeScript("return document.domain;").toString();
        System.out.println("Domain is: " + domainName);

        // Add Alert window using JavascriptExecutor
        js.executeScript("alert('Successfully Logged In');");

        Thread.sleep(2000);
    }
}


Ví dụ sendKeys

@Test
public void jsExecutorDemo02() throws InterruptedException {

    JavascriptExecutor js = (JavascriptExecutor) driver;

    driver.get("https://crm.anhtester.com/signin");
    Thread.sleep(1000);

    // sendKeys text on input
    js.executeScript("document.getElementById('email').setAttribute('value','admin02@mailinator.com');");
    js.executeScript("document.getElementById('password').setAttribute('value','123456');");

    js.executeScript("document.getElementsByClassName('btn-primary')[0].click()");
    Thread.sleep(2000);

}


Ví dụ Scroll and Click

@Test
public void jsExecutorDemo03() throws InterruptedException {

    JavascriptExecutor js = (JavascriptExecutor) driver;

    //Gọi lại hàm login
    jsExecutorDemo02();

    WebElement webElement = driver.findElement(By.xpath("//span[normalize-space()='Store']"));
    //webElement.click();  //Nếu dùng dòng này đơn thuần sẽ không click được

    // Scroll to element and click
    js.executeScript("arguments[0].scrollIntoView(true);", webElement);
    Thread.sleep(1000);
    js.executeScript("arguments[0].click();", webElement);

    Thread.sleep(2000);
}


Nếu mình dùng dòng lệnh webElement.click(); thì nó sẽ không được vì nó bị che bởi 1 element khác là cái dropdown bên ngoài.

Còn dùng Js để click thì nó dựa vào DOM để click nên không quan tâm bị che.


Ví dụ về Set và Get LocalStorage với Javascript

@Test
public void localStorage() throws InterruptedException {

    String localGetVar = "";

    driver.navigate().to("https://anhtester.com");
    Thread.sleep(1000);

    JavascriptExecutor js = (JavascriptExecutor) driver;

    //Set giá trị
    js.executeScript("window.localStorage.setItem(arguments[0],arguments[1])", "age", "30");

    Thread.sleep(1000);

    //Get giá trị
    localGetVar = (String) js.executeScript("return window.localStorage.getItem(arguments[0])", "age");

    System.out.println(localGetVar);

    Thread.sleep(1000);
}



Cái SetupBrowser là class viết riêng chứa createDriver closeDriver cái browser (driver).

package anhtester.com;

import io.github.bonigarcia.wdm.WebDriverManager;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.*;

import java.util.concurrent.TimeUnit;

public class SetupBrowser {

    public WebDriver driver;

    @BeforeClass
    public void createDriver() {
        WebDriverManager.chromedriver().setup();
        driver = new ChromeDriver();
        System.out.println("Started Driver");
        driver.manage().window().maximize();
        driver.manage().timeouts().pageLoadTimeout(20, TimeUnit.SECONDS);
        driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
    }

    @AfterClass
    public void closeDriver() {
        driver.quit();
        System.out.println("Closed Driver");
    }

}
​​​

Cộng đồng Automation Testing Việt Nam:

🌱 Telegram Automation Testing:   Cộng đồng Automation Testing
🌱 
Facebook Group Automation: Cộng đồng Automation Testing Việt Nam
🌱 
Facebook Fanpage: Cộng đồng Automation Testing Việt Nam - Selenium
🌱 Telegram
Manual Testing:   Cộng đồng Manual Testing
🌱 
Facebook Group Manual: Cộng đồng Manual Testing Việt Nam

  • Anh Tester

    Đường dẫu khó chân vẫn cần bước đi
    Đời dẫu khổ tâm vẫn cần nghĩ thấu


Cộng đồng Automation Testing Việt Nam:

🌱 Telegram Automation Testing:   Cộng đồng Automation Testing
🌱 
Facebook Group Automation: Cộng đồng Automation Testing Việt Nam
🌱 
Facebook Fanpage: Cộng đồng Automation Testing Việt Nam - Selenium
🌱 Telegram
Manual Testing:   Cộng đồng Manual Testing
🌱 
Facebook Group Manual: Cộng đồng Manual Testing Việt Nam

Chia sẻ kiến thức lên trang

Bạn có thể đăng bài để chia sẻ kiến thức, bài viết của chính bạn lên trang Anh Tester Blog

Danh sách bài học