Chrome DevTools Script Features
Script features using CDP.
Page being translated from English to Japanese. Do you speak Japanese? Help us to translate it by sending us pull requests!
While Selenium 4 provides direct access to the Chrome DevTools Protocol, these methods will eventually be removed when WebDriver BiDi implemented.
Script Pinning
ScriptKey key = ((JavascriptExecutor) driver).pin("return arguments;"); List<Object> arguments = (List<Object>) ((JavascriptExecutor) driver).executeScript(key, 1, true, element);
/examples/java/src/test/java/dev/selenium/bidi/cdp/ScriptTest.java
package dev.selenium.bidi.cdp; import static org.openqa.selenium.devtools.events.CdpEventTypes.domMutation; import dev.selenium.BaseTest; import java.time.Duration; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.openqa.selenium.*; import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.logging.HasLogEvents; import org.openqa.selenium.support.ui.WebDriverWait; public class ScriptTest extends BaseTest { @BeforeEach public void createSession() { driver = new ChromeDriver(); wait = new WebDriverWait(driver, Duration.ofSeconds(10)); } @Test public void pinScript() { driver.get("https://www.selenium.dev/selenium/web/xhtmlTest.html"); WebElement element = driver.findElement(By.id("id1")); ScriptKey key = ((JavascriptExecutor) driver).pin("return arguments;"); List<Object> arguments = (List<Object>) ((JavascriptExecutor) driver).executeScript(key, 1, true, element); Assertions.assertEquals(List.of(1L, true, element), arguments); } @Test public void mutatedElements() { driver.get("https://www.selenium.dev/selenium/web/dynamic.html"); CopyOnWriteArrayList<WebElement> mutations = new CopyOnWriteArrayList<>(); ((HasLogEvents) driver).onLogEvent(domMutation(e -> mutations.add(e.getElement()))); driver.findElement(By.id("reveal")).click(); wait.until(_d -> !mutations.isEmpty()); Assertions.assertEquals(mutations.get(0), driver.findElement(By.id("revealed"))); } }
var key = await new JavaScriptEngine(driver).PinScript("return arguments;"); var arguments = ((WebDriver)driver).ExecuteScript(key, 1, true, element);
/examples/dotnet/SeleniumDocs/BiDi/CDP/ScriptTest.cs
using System; using System.Collections; using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.IdentityModel.Tokens; using Microsoft.VisualStudio.TestTools.UnitTesting; using OpenQA.Selenium; using OpenQA.Selenium.Support.UI; namespace SeleniumDocs.BiDi.CDP { [TestClass] public class ScriptTest : BaseChromeTest { [TestMethod] public async Task PinScript() { driver.Url = "https://www.selenium.dev/selenium/web/xhtmlTest.html"; var element = driver.FindElement(By.Id("id1")); var key = await new JavaScriptEngine(driver).PinScript("return arguments;"); var arguments = ((WebDriver)driver).ExecuteScript(key, 1, true, element); var expected = new List<object> { 1L, true, element }; CollectionAssert.AreEqual(expected, (ICollection)arguments); } [TestMethod] public async Task MutatedElements() { driver.Url = "https://www.selenium.dev/selenium/web/dynamic.html"; var mutations = new List<IWebElement>(); using IJavaScriptEngine monitor = new JavaScriptEngine(driver); monitor.DomMutated += (_, e) => { var locator = By.CssSelector($"*[data-__webdriver_id='{e.AttributeData.TargetId}']"); mutations.Add(driver.FindElement(locator)); }; await monitor.StartEventMonitoring(); await monitor.EnableDomMutationMonitoring(); driver.FindElement(By.Id("reveal")).Click(); new WebDriverWait(driver, TimeSpan.FromSeconds(5)).Until(_ => !mutations.IsNullOrEmpty()); await monitor.DisableDomMutationMonitoring(); monitor.StopEventMonitoring(); var revealed = driver.FindElement(By.Id("revealed")); Assert.AreEqual(revealed, mutations[0]); } } }
key = driver.pin_script('return arguments;') arguments = driver.execute_script(key, 1, true, element)
/examples/ruby/spec/bidi/cdp/script_spec.rb
# frozen_string_literal: true require 'spec_helper' RSpec.describe 'Script' do let(:driver) { start_session } it 'pins script' do driver.get('https://www.selenium.dev/selenium/web/xhtmlTest.html') element = driver.find_element(id: 'id1') key = driver.pin_script('return arguments;') arguments = driver.execute_script(key, 1, true, element) expect(arguments).to eq([1, true, element]) end it 'gets mutated elements' do driver.get 'https://www.selenium.dev/selenium/web/dynamic.html' mutations = [] driver.on_log_event(:mutation) { |mutation| mutations << mutation.element } driver.find_element(id: 'reveal').click Selenium::WebDriver::Wait.new(timeout: 30).until { mutations.any? } expect(mutations).to include(driver.find_element(id: 'revealed')) end end
DOM Mutation Handlers
/examples/java/src/test/java/dev/selenium/bidi/cdp/NetworkTest.java
package dev.selenium.bidi.cdp; import com.google.common.net.MediaType; import dev.selenium.BaseTest; import java.net.*; import java.time.Duration; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Predicate; import java.util.function.Supplier; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.openqa.selenium.*; import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.devtools.DevTools; import org.openqa.selenium.devtools.HasDevTools; import org.openqa.selenium.devtools.NetworkInterceptor; import org.openqa.selenium.devtools.v137.browser.Browser; import org.openqa.selenium.devtools.v137.network.Network; import org.openqa.selenium.devtools.v137.performance.Performance; import org.openqa.selenium.devtools.v137.performance.model.Metric; import org.openqa.selenium.remote.http.*; import org.openqa.selenium.support.ui.WebDriverWait; public class NetworkTest extends BaseTest { @BeforeEach public void createSession() { driver = new ChromeDriver(); wait = new WebDriverWait(driver, Duration.ofSeconds(10)); } @Test public void basicAuthentication() { Predicate<URI> uriPredicate = uri -> uri.toString().contains("herokuapp.com"); Supplier<Credentials> authentication = UsernameAndPassword.of("admin", "admin"); ((HasAuthentication) driver).register(uriPredicate, authentication); driver.get("https://the-internet.herokuapp.com/basic_auth"); String successMessage = "Congratulations! You must have the proper credentials."; WebElement elementMessage = driver.findElement(By.tagName("p")); Assertions.assertEquals(successMessage, elementMessage.getText()); } @Test public void recordResponse() { CopyOnWriteArrayList<String> contentType = new CopyOnWriteArrayList<>(); try (NetworkInterceptor ignored = new NetworkInterceptor( driver, (Filter) next -> req -> { HttpResponse res = next.execute(req); contentType.add(res.getHeader("Content-Type")); return res; })) { driver.get("https://www.selenium.dev/selenium/web/blank.html"); wait.until(_d -> contentType.size() > 1); } Assertions.assertEquals("text/html; charset=utf-8", contentType.get(0)); } @Test public void transformResponses() { try (NetworkInterceptor ignored = new NetworkInterceptor( driver, Route.matching(req -> true) .to( () -> req -> new HttpResponse() .setStatus(200) .addHeader("Content-Type", MediaType.HTML_UTF_8.toString()) .setContent(Contents.utf8String("Creamy, delicious cheese!"))))) { driver.get("https://www.selenium.dev/selenium/web/blank.html"); } WebElement body = driver.findElement(By.tagName("body")); Assertions.assertEquals("Creamy, delicious cheese!", body.getText()); } @Test public void interceptRequests() { AtomicBoolean completed = new AtomicBoolean(false); try (NetworkInterceptor ignored = new NetworkInterceptor( driver, (Filter) next -> req -> { if (req.getUri().contains("one.js")) { req = new HttpRequest( HttpMethod.GET, req.getUri().replace("one.js", "two.js")); } completed.set(true); return next.execute(req); })) { driver.get("https://www.selenium.dev/selenium/web/devToolsRequestInterceptionTest.html"); driver.findElement(By.tagName("button")).click(); } Assertions.assertEquals("two", driver.findElement(By.id("result")).getText()); } @Test public void performanceMetrics() { driver.get("https://www.selenium.dev/selenium/web/frameset.html"); DevTools devTools = ((HasDevTools) driver).getDevTools(); devTools.createSession(); devTools.send(Performance.enable(Optional.empty())); List<Metric> metricList = devTools.send(Performance.getMetrics()); Map<String, Number> metrics = new HashMap<>(); for (Metric metric : metricList) { metrics.put(metric.getName(), metric.getValue()); } Assertions.assertTrue(metrics.get("DevToolsCommandDuration").doubleValue() > 0); Assertions.assertEquals(12, metrics.get("Frames").intValue()); } @Test public void setCookie() { DevTools devTools = ((HasDevTools) driver).getDevTools(); devTools.createSession(); devTools.send( Network.setCookie( "cheese", "gouda", Optional.empty(), Optional.of("www.selenium.dev"), Optional.empty(), Optional.of(true), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty())); driver.get("https://www.selenium.dev"); Cookie cheese = driver.manage().getCookieNamed("cheese"); Assertions.assertEquals("gouda", cheese.getValue()); } @Test public void waitForDownload() { driver.get("https://www.selenium.dev/selenium/web/downloads/download.html"); DevTools devTools = ((HasDevTools) driver).getDevTools(); devTools.createSession(); devTools.send( Browser.setDownloadBehavior( Browser.SetDownloadBehaviorBehavior.ALLOWANDNAME, Optional.empty(), Optional.of(""), Optional.of(true))); AtomicBoolean completed = new AtomicBoolean(false); devTools.addListener( Browser.downloadProgress(), e -> completed.set(Objects.equals(e.getState().toString(), "completed"))); driver.findElement(By.id("file-2")).click(); Assertions.assertDoesNotThrow(() -> wait.until(_d -> completed)); } }
async with driver.bidi_connection() as session: async with Log(driver, session).mutation_events() as event:
/examples/python/tests/bidi/cdp/test_script.py
import pytest import trio from selenium.webdriver.common.by import By from selenium.webdriver.common.log import Log from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC @pytest.mark.trio async def test_mutation(driver): async with driver.bidi_connection() as session: async with Log(driver, session).mutation_events() as event: await trio.to_thread.run_sync(lambda: driver.get('https://www.selenium.dev/selenium/web/dynamic.html')) await trio.to_thread.run_sync(lambda: WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.ID, "reveal")))) await trio.to_thread.run_sync(lambda: driver.find_element(By.ID, "reveal").click()) assert event["element"] == driver.find_element(By.ID, "revealed")
using IJavaScriptEngine monitor = new JavaScriptEngine(driver); monitor.DomMutated += (_, e) => { var locator = By.CssSelector($"*[data-__webdriver_id='{e.AttributeData.TargetId}']"); mutations.Add(driver.FindElement(locator)); }; await monitor.StartEventMonitoring(); await monitor.EnableDomMutationMonitoring();
/examples/dotnet/SeleniumDocs/BiDi/CDP/ScriptTest.cs
using System; using System.Collections; using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.IdentityModel.Tokens; using Microsoft.VisualStudio.TestTools.UnitTesting; using OpenQA.Selenium; using OpenQA.Selenium.Support.UI; namespace SeleniumDocs.BiDi.CDP { [TestClass] public class ScriptTest : BaseChromeTest { [TestMethod] public async Task PinScript() { driver.Url = "https://www.selenium.dev/selenium/web/xhtmlTest.html"; var element = driver.FindElement(By.Id("id1")); var key = await new JavaScriptEngine(driver).PinScript("return arguments;"); var arguments = ((WebDriver)driver).ExecuteScript(key, 1, true, element); var expected = new List<object> { 1L, true, element }; CollectionAssert.AreEqual(expected, (ICollection)arguments); } [TestMethod] public async Task MutatedElements() { driver.Url = "https://www.selenium.dev/selenium/web/dynamic.html"; var mutations = new List<IWebElement>(); using IJavaScriptEngine monitor = new JavaScriptEngine(driver); monitor.DomMutated += (_, e) => { var locator = By.CssSelector($"*[data-__webdriver_id='{e.AttributeData.TargetId}']"); mutations.Add(driver.FindElement(locator)); }; await monitor.StartEventMonitoring(); await monitor.EnableDomMutationMonitoring(); driver.FindElement(By.Id("reveal")).Click(); new WebDriverWait(driver, TimeSpan.FromSeconds(5)).Until(_ => !mutations.IsNullOrEmpty()); await monitor.DisableDomMutationMonitoring(); monitor.StopEventMonitoring(); var revealed = driver.FindElement(By.Id("revealed")); Assert.AreEqual(revealed, mutations[0]); } } }
driver.on_log_event(:mutation) { |mutation| mutations << mutation.element }
/examples/ruby/spec/bidi/cdp/script_spec.rb
# frozen_string_literal: true require 'spec_helper' RSpec.describe 'Script' do let(:driver) { start_session } it 'pins script' do driver.get('https://www.selenium.dev/selenium/web/xhtmlTest.html') element = driver.find_element(id: 'id1') key = driver.pin_script('return arguments;') arguments = driver.execute_script(key, 1, true, element) expect(arguments).to eq([1, true, element]) end it 'gets mutated elements' do driver.get 'https://www.selenium.dev/selenium/web/dynamic.html' mutations = [] driver.on_log_event(:mutation) { |mutation| mutations << mutation.element } driver.find_element(id: 'reveal').click Selenium::WebDriver::Wait.new(timeout: 30).until { mutations.any? } expect(mutations).to include(driver.find_element(id: 'revealed')) end end
Última modificação November 5, 2024: Add examples for Drivers HTTP Client in Java and Python (#2041) (2ce6752bfc8)