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.JavascriptExecuto
r
.
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.
driver.findElement(By.id("button")).click();
Đô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.
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.
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.
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à:
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.
import org.openqa.selenium.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.
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
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.
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",...
js.executeScript("document.getElementById('id_of_element').checked=false;");
//hoặc
js.executeScript("document.getElementById('id_of_element').checked=true;");
js.executeScript("alert('Welcome To Anh Tester - Automation Testing');");
js.executeScript("history.go(0)");
String innerText = js.executeScript("return document.documentElement.innerText;").toString();
System.out.println(innerText);
String titleText = js.executeScript("return document.title;").toString();
System.out.println(titleText);
String domainName= js.executeScript("return document.domain;").toString();
System.out.println(domainName);
String url= js.executeScript("return document.URL;").toString();
System.out.println(url);
js.executeScript("return window.innerHeight;").toString();
js.executeScript("return window.innerWidth;").toString();
js.executeScript("arguments[0].click();", element);
js.executeScript("window.location = 'https://anhtester.com'");
js.executeScript("window.scrollTo(0,500)");
js.executeScript("window.scrollTo(0,document.body.scrollHeight)");
WebElement element = driver.findElement(By.id("id_of_element"));
js.executeScript("arguments[0].scrollIntoView(true);", element);
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);");
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.
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.
(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úng ta có các hàm document.getElementBy* sau:Nó không có Xpath đâu nhen =))
https://www.w3schools.com/jsref/default.asp
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);
}
}
@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);
}
@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.
@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 và 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");
}
}
Severity: Notice
Message: Undefined variable: new
Filename: post/post_detail.php
Line Number: 384
Backtrace:
File: /home/anhtest2/public_html/application/views/frontend/post/post_detail.php
Line: 384
Function: _error_handler
File: /home/anhtest2/public_html/application/views/frontend/layout/layout_view.php
Line: 370
Function: view
File: /home/anhtest2/public_html/application/core/MY_Controller.php
Line: 34
Function: view
File: /home/anhtest2/public_html/application/controllers/frontend/Post.php
Line: 59
Function: render
File: /home/anhtest2/public_html/index.php
Line: 315
Function: require_once
Severity: Notice
Message: Trying to get property 'slug' of non-object
Filename: post/post_detail.php
Line Number: 384
Backtrace:
File: /home/anhtest2/public_html/application/views/frontend/post/post_detail.php
Line: 384
Function: _error_handler
File: /home/anhtest2/public_html/application/views/frontend/layout/layout_view.php
Line: 370
Function: view
File: /home/anhtest2/public_html/application/core/MY_Controller.php
Line: 34
Function: view
File: /home/anhtest2/public_html/application/controllers/frontend/Post.php
Line: 59
Function: render
File: /home/anhtest2/public_html/index.php
Line: 315
Function: require_once
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