diff --git a/examples/dotnet/SeleniumDocs/BaseTest.cs b/examples/dotnet/SeleniumDocs/BaseTest.cs index 084553b3170b..e8fbd15f5cec 100644 --- a/examples/dotnet/SeleniumDocs/BaseTest.cs +++ b/examples/dotnet/SeleniumDocs/BaseTest.cs @@ -1,5 +1,6 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using OpenQA.Selenium; +using OpenQA.Selenium.Chrome; namespace SeleniumDocs { @@ -7,6 +8,20 @@ public class BaseTest { protected IWebDriver driver; + public void StartDriver() + { + driver = new ChromeDriver(); + } + + public void StartDriver(string browserVersion) + { + ChromeOptions options = new ChromeOptions + { + BrowserVersion = browserVersion + }; + driver = new ChromeDriver(options); + } + [TestCleanup] public void QuitDriver() { diff --git a/examples/dotnet/SeleniumDocs/Bidirectional/BidiApiTest.cs b/examples/dotnet/SeleniumDocs/Bidirectional/BidiApiTest.cs deleted file mode 100644 index c666e2e14041..000000000000 --- a/examples/dotnet/SeleniumDocs/Bidirectional/BidiApiTest.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System.Threading.Tasks; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using OpenQA.Selenium; - -namespace SeleniumDocs.Bidirectional -{ - [TestClass] - public class BidiApiTest : BaseChromeTest - { - [TestMethod] - public async Task InterceptNetworkForAuthentication() - { - var handler = new NetworkAuthenticationHandler() - { - UriMatcher = _ => true, - Credentials = new PasswordCredentials("admin", "admin") - }; - - INetwork networkInterceptor = driver.Manage().Network; - networkInterceptor.AddAuthenticationHandler(handler); - - await networkInterceptor.StartMonitoring(); - driver.Navigate().GoToUrl("https://the-internet.herokuapp.com/basic_auth"); - await networkInterceptor.StopMonitoring(); - - Assert.AreEqual("Congratulations! You must have the proper credentials.", driver.FindElement(By.TagName("p")).Text); - - } - - [TestMethod] - public async Task InterceptNetworkResponse() - { - var handler = new NetworkResponseHandler() - { - ResponseMatcher = httpresponse => true, - ResponseTransformer = http => new() - { - StatusCode = 200, - Body = "Creamy, delicious cheese!" - } - }; - - INetwork networkInterceptor = driver.Manage().Network; - networkInterceptor.AddResponseHandler(handler); - - await networkInterceptor.StartMonitoring(); - driver.Navigate().GoToUrl("https://www.selenium.dev"); - await networkInterceptor.StopMonitoring(); - - StringAssert.Contains(driver.PageSource, "delicious cheese"); - } - - [TestMethod] - public async Task InterceptNetworkRequest() - { - var handler = new NetworkRequestHandler() - { - RequestMatcher = httprequest => true, - ResponseSupplier = http => new() - { - StatusCode = 200, - Body = "Creamy, delicious cheese!" - } - }; - - INetwork networkInterceptor = driver.Manage().Network; - networkInterceptor.AddRequestHandler(handler); - - await networkInterceptor.StartMonitoring(); - driver.Navigate().GoToUrl("https://www.selenium.dev"); - await networkInterceptor.StopMonitoring(); - - StringAssert.Contains(driver.PageSource, "delicious cheese"); - } - } -} diff --git a/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/BidiApiTest.cs b/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/BidiApiTest.cs new file mode 100644 index 000000000000..f088fb915cab --- /dev/null +++ b/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/BidiApiTest.cs @@ -0,0 +1,189 @@ +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.Bidirectional.ChromeDevTools +{ + [TestClass] + public class BidiApiTest : BaseChromeTest + { + [TestMethod] + public async Task BasicAuthentication() + { + var handler = new NetworkAuthenticationHandler() + { + UriMatcher = uri => uri.AbsoluteUri.Contains("herokuapp"), + Credentials = new PasswordCredentials("admin", "admin") + }; + + var networkInterceptor = driver.Manage().Network; + networkInterceptor.AddAuthenticationHandler(handler); + + await networkInterceptor.StartMonitoring(); + driver.Navigate().GoToUrl("https://the-internet.herokuapp.com/basic_auth"); + await networkInterceptor.StopMonitoring(); + + Assert.AreEqual("Congratulations! You must have the proper credentials.", + driver.FindElement(By.TagName("p")).Text); + } + + [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 + { + 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(); + 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]); + } + + [TestMethod] + public async Task ConsoleLogs() + { + driver.Url = "https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html"; + + using IJavaScriptEngine monitor = new JavaScriptEngine(driver); + var messages = new List(); + monitor.JavaScriptConsoleApiCalled += (_, e) => + { + messages.Add(e.MessageContent); + }; + + await monitor.StartEventMonitoring(); + driver.FindElement(By.Id("consoleLog")).Click(); + driver.FindElement(By.Id("consoleError")).Click(); + new WebDriverWait(driver, TimeSpan.FromSeconds(5)).Until(_ => messages.Count > 1); + monitor.StopEventMonitoring(); + + Assert.IsTrue(messages.Contains("Hello, world!")); + Assert.IsTrue(messages.Contains("I am console error")); + } + + [TestMethod] + public async Task JsErrors() + { + driver.Url = "https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html"; + + using IJavaScriptEngine monitor = new JavaScriptEngine(driver); + var messages = new List(); + monitor.JavaScriptExceptionThrown += (_, e) => + { + messages.Add(e.Message); + }; + + await monitor.StartEventMonitoring(); + driver.FindElement(By.Id("jsException")).Click(); + new WebDriverWait(driver, TimeSpan.FromSeconds(5)).Until(_ => !messages.IsNullOrEmpty()); + monitor.StopEventMonitoring(); + + Assert.IsTrue(messages.Contains("Uncaught")); + } + + [TestMethod] + public async Task RecordNetworkResponse() + { + var contentType = new List(); + + INetwork networkInterceptor = driver.Manage().Network; + networkInterceptor.NetworkResponseReceived += (_, e) => + { + contentType.Add(e.ResponseHeaders["content-type"]); + }; + + await networkInterceptor.StartMonitoring(); + driver.Navigate().GoToUrl("https://www.selenium.dev/selenium/web/blank.html"); + await networkInterceptor.StopMonitoring(); + + Assert.AreEqual("text/html; charset=utf-8", contentType[0]); + } + + [TestMethod] + public async Task TransformNetworkResponse() + { + var handler = new NetworkResponseHandler() + { + ResponseMatcher = _ => true, + ResponseTransformer = _ => new HttpResponseData + { + StatusCode = 200, + Body = "Creamy, delicious cheese!" + } + }; + + INetwork networkInterceptor = driver.Manage().Network; + networkInterceptor.AddResponseHandler(handler); + + await networkInterceptor.StartMonitoring(); + driver.Navigate().GoToUrl("https://www.selenium.dev"); + await networkInterceptor.StopMonitoring(); + + var body = driver.FindElement(By.TagName("body")); + Assert.AreEqual("Creamy, delicious cheese!", body.Text); + } + + [TestMethod] + public async Task TransformNetworkRequest() + { + var handler = new NetworkRequestHandler + { + RequestMatcher = request => request.Url.Contains("one.js"), + RequestTransformer = request => + { + request.Url = request.Url.Replace("one", "two"); + + return request; + } + }; + + INetwork networkInterceptor = driver.Manage().Network; + networkInterceptor.AddRequestHandler(handler); + + await networkInterceptor.StartMonitoring(); + driver.Url = "https://www.selenium.dev/selenium/web/devToolsRequestInterceptionTest.html"; + driver.FindElement(By.TagName("button")).Click(); + await networkInterceptor.StopMonitoring(); + + Assert.AreEqual("two", driver.FindElement(By.Id("result")).Text); + } + } +} \ No newline at end of file diff --git a/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/CdpApiTest.cs b/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/CdpApiTest.cs new file mode 100644 index 000000000000..f02a25c4ad19 --- /dev/null +++ b/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/CdpApiTest.cs @@ -0,0 +1,91 @@ +using System; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using OpenQA.Selenium; +using OpenQA.Selenium.DevTools; +using OpenQA.Selenium.DevTools.V118.Network; +using OpenQA.Selenium.DevTools.V118.Performance; + +namespace SeleniumDocs.Bidirectional.ChromeDevtools +{ + [TestClass] + public class CdpApiTest : BaseTest + { + [TestInitialize] + public void Startup() + { + StartDriver("118"); + } + + [TestMethod] + public async Task SetCookie() + { + var session = ((IDevTools)driver).GetDevToolsSession(); + var domains = session.GetVersionSpecificDomains(); + await domains.Network.Enable(new OpenQA.Selenium.DevTools.V118.Network.EnableCommandSettings()); + + var cookieCommandSettings = new SetCookieCommandSettings + { + Name = "cheese", + Value = "gouda", + Domain = "www.selenium.dev", + Secure = true + }; + + await domains.Network.SetCookie(cookieCommandSettings); + + driver.Url = "https://www.selenium.dev"; + OpenQA.Selenium.Cookie cheese = driver.Manage().Cookies.GetCookieNamed("cheese"); + Assert.AreEqual("gouda", cheese.Value); + } + + [TestMethod] + public async Task PerformanceMetrics() + { + driver.Url = "https://www.selenium.dev/selenium/web/frameset.html"; + + var session = ((IDevTools)driver).GetDevToolsSession(); + var domains = session.GetVersionSpecificDomains(); + await domains.Performance.Enable(new OpenQA.Selenium.DevTools.V118.Performance.EnableCommandSettings()); + + var metricsResponse = + await session.SendCommand( + new GetMetricsCommandSettings() + ); + + var metrics = metricsResponse.Metrics.ToDictionary( + dict => dict.Name, + dict => dict.Value + ); + + Assert.IsTrue(metrics["DevToolsCommandDuration"] > 0); + Assert.AreEqual(12, metrics["Frames"]); + } + + [TestMethod] + public async Task BasicAuth() + { + var session = ((IDevTools)driver).GetDevToolsSession(); + var domains = session.GetVersionSpecificDomains(); + await domains.Network.Enable(new OpenQA.Selenium.DevTools.V118.Network.EnableCommandSettings()); + + var encodedAuth = Convert.ToBase64String(Encoding.Default.GetBytes("admin:admin")); + var headerSettings = new SetExtraHTTPHeadersCommandSettings + { + Headers = new Headers() + { + { "authorization", "Basic " + encodedAuth } + } + }; + + await domains.Network.SetExtraHTTPHeaders(headerSettings); + + driver.Url = "https://the-internet.herokuapp.com/basic_auth"; + + var element = driver.FindElement(By.TagName("p")); + Assert.AreEqual("Congratulations! You must have the proper credentials.", element.Text); + } + } +} \ No newline at end of file diff --git a/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/CdpEndpointTest.cs b/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/CdpEndpointTest.cs new file mode 100644 index 000000000000..ff4c4d089c3c --- /dev/null +++ b/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/CdpEndpointTest.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using OpenQA.Selenium; +using OpenQA.Selenium.Chrome; + +namespace SeleniumDocs.Bidirectional.ChromeDevtools +{ + [TestClass] + public class CdpEndpointTest : BaseTest + { + private readonly Dictionary emptyDictionary = new(); + + [TestInitialize] + public void Startup() + { + StartDriver(); + } + + [TestMethod] + public void SetCookie() + { + var cookie = new Dictionary + { + { "name", "cheese" }, + { "value", "gouda" }, + { "domain", "www.selenium.dev" }, + { "secure", true } + }; + + ((ChromeDriver)driver).ExecuteCdpCommand("Network.setCookie", cookie); + + driver.Url = "https://www.selenium.dev"; + Cookie cheese = driver.Manage().Cookies.GetCookieNamed("cheese"); + Assert.AreEqual("gouda", cheese.Value); + + } + + [TestMethod] + public void PerformanceMetrics() + { + driver.Url = "https://www.selenium.dev/selenium/web/frameset.html"; + + ((ChromeDriver)driver).ExecuteCdpCommand("Performance.enable", emptyDictionary); + + Dictionary response = (Dictionary)((ChromeDriver)driver) + .ExecuteCdpCommand("Performance.getMetrics", emptyDictionary); + + Object[] metricList = (object[])response["metrics"]; + var metrics = metricList.OfType>() + .ToDictionary( + dict => (string)dict["name"], + dict => dict["value"] + ); + + Assert.IsTrue((double)metrics["DevToolsCommandDuration"] > 0); + Assert.AreEqual((long)12, metrics["Frames"]); + } + + [TestMethod] + public void BasicAuth() + { + ((ChromeDriver)driver).ExecuteCdpCommand("Network.enable", emptyDictionary); + + string encodedAuth = Convert.ToBase64String(Encoding.Default.GetBytes("admin:admin")); + var headers = new Dictionary + { + { "headers", new Dictionary { { "authorization", "Basic " + encodedAuth } } } + }; + + ((ChromeDriver)driver).ExecuteCdpCommand("Network.setExtraHTTPHeaders", headers); + + driver.Url = "https://the-internet.herokuapp.com/basic_auth"; + + var element = driver.FindElement(By.TagName("p")); + Assert.AreEqual("Congratulations! You must have the proper credentials.", element.Text); + } + } +} \ No newline at end of file diff --git a/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtoolsTest.cs b/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtoolsTest.cs deleted file mode 100644 index c849ace22431..000000000000 --- a/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtoolsTest.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; - -namespace SeleniumDocs.Bidirectional -{ - [TestClass] - public class ChomeDevtoolsTest : BaseTest - { - - } -} \ No newline at end of file diff --git a/examples/dotnet/SeleniumDocs/Bidirectional/BidirectionalW3c/BrowsingContextTest.cs b/examples/dotnet/SeleniumDocs/Bidirectional/WebDriverBiDi/BrowsingContextTest.cs similarity index 71% rename from examples/dotnet/SeleniumDocs/Bidirectional/BidirectionalW3c/BrowsingContextTest.cs rename to examples/dotnet/SeleniumDocs/Bidirectional/WebDriverBiDi/BrowsingContextTest.cs index 744752e9a307..7de31af093f6 100644 --- a/examples/dotnet/SeleniumDocs/Bidirectional/BidirectionalW3c/BrowsingContextTest.cs +++ b/examples/dotnet/SeleniumDocs/Bidirectional/WebDriverBiDi/BrowsingContextTest.cs @@ -1,6 +1,6 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; -namespace SeleniumDocs.Bidirectional.BidirectionalW3c +namespace SeleniumDocs.Bidirectional.WebDriverBiDi { [TestClass] public class BrowsingContextTest : BaseTest diff --git a/examples/dotnet/SeleniumDocs/Bidirectional/BidirectionalW3c/LogTest.cs b/examples/dotnet/SeleniumDocs/Bidirectional/WebDriverBiDi/LogTest.cs similarity index 69% rename from examples/dotnet/SeleniumDocs/Bidirectional/BidirectionalW3c/LogTest.cs rename to examples/dotnet/SeleniumDocs/Bidirectional/WebDriverBiDi/LogTest.cs index 82c63d872f0c..54e3f92884b2 100644 --- a/examples/dotnet/SeleniumDocs/Bidirectional/BidirectionalW3c/LogTest.cs +++ b/examples/dotnet/SeleniumDocs/Bidirectional/WebDriverBiDi/LogTest.cs @@ -1,6 +1,6 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; -namespace SeleniumDocs.Bidirectional.BidirectionalW3c +namespace SeleniumDocs.Bidirectional.WebDriverBiDi { [TestClass] public class LogTest : BaseTest diff --git a/examples/java/pom.xml b/examples/java/pom.xml index f868e879241e..8cc5470f2436 100644 --- a/examples/java/pom.xml +++ b/examples/java/pom.xml @@ -40,7 +40,7 @@ com.titusfortner selenium-logger - 2.2.1 + 2.4.0 diff --git a/examples/java/src/test/java/dev/selenium/BaseTest.java b/examples/java/src/test/java/dev/selenium/BaseTest.java index eea3bccf9eb3..56a41689cd02 100644 --- a/examples/java/src/test/java/dev/selenium/BaseTest.java +++ b/examples/java/src/test/java/dev/selenium/BaseTest.java @@ -11,7 +11,8 @@ import org.openqa.selenium.support.ui.WebDriverWait; public class BaseTest { - public WebDriver driver; + protected WebDriver driver; + protected WebDriverWait wait; public WebElement getLocatedElement(WebDriver driver, By by) { WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5)); diff --git a/examples/java/src/test/java/dev/selenium/bidirectional/BidiApiTest.java b/examples/java/src/test/java/dev/selenium/bidirectional/BidiApiTest.java deleted file mode 100644 index 4c46b7a383f5..000000000000 --- a/examples/java/src/test/java/dev/selenium/bidirectional/BidiApiTest.java +++ /dev/null @@ -1,70 +0,0 @@ -package dev.selenium.bidirectional; - -import static org.openqa.selenium.remote.http.Contents.utf8String; - -import com.google.common.net.MediaType; -import dev.selenium.BaseChromeTest; -import java.net.URI; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Predicate; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.openqa.selenium.By; -import org.openqa.selenium.HasAuthentication; -import org.openqa.selenium.JavascriptExecutor; -import org.openqa.selenium.UsernameAndPassword; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.devtools.NetworkInterceptor; -import org.openqa.selenium.devtools.events.CdpEventTypes; -import org.openqa.selenium.devtools.events.DomMutationEvent; -import org.openqa.selenium.logging.HasLogEvents; -import org.openqa.selenium.remote.http.HttpResponse; -import org.openqa.selenium.remote.http.Route; - -public class BidiApiTest extends BaseChromeTest { - @Test - public void registerBasicAuth() { - Predicate uriPredicate = uri -> uri.getHost().contains("the-internet.herokuapp.com"); - ((HasAuthentication) driver).register(uriPredicate, UsernameAndPassword.of("admin", "admin")); - - driver.get("https://the-internet.herokuapp.com/basic_auth"); - - Assertions.assertTrue(driver.getPageSource().contains("Basic Auth")); - } - - @Test - public void domMutation() throws InterruptedException { - driver.get("https://www.google.com"); - WebElement span = driver.findElement(By.cssSelector("span")); - - AtomicReference seen = new AtomicReference<>(); - CountDownLatch latch = new CountDownLatch(1); - ((HasLogEvents) driver).onLogEvent(CdpEventTypes.domMutation(mutation -> { - seen.set(mutation); - latch.countDown(); - })); - - ((JavascriptExecutor) driver).executeScript("arguments[0].setAttribute('cheese', 'gouda');", - span); - - Assertions.assertTrue(latch.await(10, TimeUnit.SECONDS)); - Assertions.assertEquals("cheese", seen.get().getAttributeName()); - Assertions.assertEquals("gouda", seen.get().getCurrentValue()); - } - - @Test - public void interceptNetworkResponse() { - NetworkInterceptor interceptor = new NetworkInterceptor( - driver, Route.matching(req -> true) - .to(() -> req -> new HttpResponse() - .setStatus(200) - .addHeader("Content-Type", MediaType.HTML_UTF_8.toString()) - .setContent(utf8String("Creamy, delicious cheese!")))); - driver.get("https://www.selenium.dev"); - String source = driver.getPageSource(); - - Assertions.assertTrue(source.contains("delicious cheese")); - } -} diff --git a/examples/java/src/test/java/dev/selenium/bidirectional/ChromeDevtoolsTest.java b/examples/java/src/test/java/dev/selenium/bidirectional/ChromeDevtoolsTest.java deleted file mode 100644 index 347655044e28..000000000000 --- a/examples/java/src/test/java/dev/selenium/bidirectional/ChromeDevtoolsTest.java +++ /dev/null @@ -1,7 +0,0 @@ -package dev.selenium.bidirectional; - -import dev.selenium.BaseTest; - -public class ChromeDevtoolsTest extends BaseTest { - -} diff --git a/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/BidiApiTest.java b/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/BidiApiTest.java new file mode 100644 index 000000000000..cb657347d34c --- /dev/null +++ b/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/BidiApiTest.java @@ -0,0 +1,155 @@ +package dev.selenium.bidirectional.chrome_devtools; + +import static org.openqa.selenium.devtools.events.CdpEventTypes.consoleEvent; +import static org.openqa.selenium.devtools.events.CdpEventTypes.domMutation; + +import com.google.common.net.MediaType; +import dev.selenium.BaseTest; +import java.net.*; +import java.time.Duration; +import java.util.List; +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.Disabled; +import org.junit.jupiter.api.Test; +import org.openqa.selenium.*; +import org.openqa.selenium.chrome.ChromeDriver; +import org.openqa.selenium.devtools.NetworkInterceptor; +import org.openqa.selenium.logging.HasLogEvents; +import org.openqa.selenium.remote.http.*; +import org.openqa.selenium.support.ui.WebDriverWait; + +public class BidiApiTest extends BaseTest { + + @BeforeEach + public void createSession() { + driver = new ChromeDriver(); + wait = new WebDriverWait(driver, Duration.ofSeconds(10)); + } + + @Test + public void basicAuthentication() { + Predicate uriPredicate = uri -> uri.toString().contains("herokuapp.com"); + Supplier 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 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 arguments = + (List) ((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 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"))); + } + + @Test + public void consoleLogs() { + driver.get("https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html"); + + CopyOnWriteArrayList messages = new CopyOnWriteArrayList<>(); + ((HasLogEvents) driver).onLogEvent(consoleEvent(e -> messages.add(e.getMessages().get(0)))); + + driver.findElement(By.id("consoleLog")).click(); + driver.findElement(By.id("consoleError")).click(); + + wait.until(_d -> messages.size() > 1); + Assertions.assertTrue(messages.contains("Hello, world!")); + Assertions.assertTrue(messages.contains("I am console error")); + } + + @Test + public void recordResponse() { + CopyOnWriteArrayList 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 + @Disabled("Not working yet") + 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()); + } +} diff --git a/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/CdpApiTest.java b/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/CdpApiTest.java new file mode 100644 index 000000000000..0e149ff968a6 --- /dev/null +++ b/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/CdpApiTest.java @@ -0,0 +1,160 @@ +package dev.selenium.bidirectional.chrome_devtools; + +import com.google.common.collect.ImmutableMap; +import dev.selenium.BaseTest; +import java.time.Duration; +import java.util.*; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.atomic.AtomicBoolean; + +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.chrome.ChromeOptions; +import org.openqa.selenium.devtools.DevTools; +import org.openqa.selenium.devtools.HasDevTools; +import org.openqa.selenium.devtools.v118.browser.Browser; +import org.openqa.selenium.devtools.v118.network.Network; +import org.openqa.selenium.devtools.v118.network.model.Headers; +import org.openqa.selenium.devtools.v118.performance.Performance; +import org.openqa.selenium.devtools.v118.performance.model.Metric; +import org.openqa.selenium.devtools.v118.runtime.Runtime; +import org.openqa.selenium.support.ui.WebDriverWait; + +public class CdpApiTest extends BaseTest { + DevTools devTools; + + @BeforeEach + public void createSession() { + ChromeOptions options = new ChromeOptions(); + options.setBrowserVersion("118"); + driver = new ChromeDriver(options); + wait = new WebDriverWait(driver, Duration.ofSeconds(10)); + } + + @Test + public void setCookie() { + 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 performanceMetrics() { + driver.get("https://www.selenium.dev/selenium/web/frameset.html"); + + devTools = ((HasDevTools) driver).getDevTools(); + devTools.createSession(); + devTools.send(Performance.enable(Optional.empty())); + + List metricList = devTools.send(Performance.getMetrics()); + + Map 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 basicAuth() { + devTools = ((HasDevTools) driver).getDevTools(); + devTools.createSession(); + devTools.send(Network.enable(Optional.of(100000), Optional.of(100000), Optional.of(100000))); + + String encodedAuth = Base64.getEncoder().encodeToString("admin:admin".getBytes()); + Map headers = ImmutableMap.of("Authorization", "Basic " + encodedAuth); + + devTools.send(Network.setExtraHTTPHeaders(new Headers(headers))); + + driver.get("https://the-internet.herokuapp.com/basic_auth"); + + Assertions.assertEquals( + "Congratulations! You must have the proper credentials.", + driver.findElement(By.tagName("p")).getText()); + } + + @Test + public void consoleLogs() { + driver.get("https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html"); + + DevTools devTools = ((HasDevTools) driver).getDevTools(); + devTools.createSession(); + devTools.send(Runtime.enable()); + + CopyOnWriteArrayList logs = new CopyOnWriteArrayList<>(); + devTools.addListener( + Runtime.consoleAPICalled(), + event -> logs.add((String) event.getArgs().get(0).getValue().orElse(""))); + + driver.findElement(By.id("consoleLog")).click(); + + wait.until(_d -> !logs.isEmpty()); + Assertions.assertEquals("Hello, world!", logs.get(0)); + } + + + @Test + public void jsErrors() { + driver.get("https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html"); + + DevTools devTools = ((HasDevTools) driver).getDevTools(); + devTools.createSession(); + devTools.send(Runtime.enable()); + + CopyOnWriteArrayList errors = new CopyOnWriteArrayList<>(); + devTools.getDomains().events().addJavascriptExceptionListener(errors::add); + + driver.findElement(By.id("jsException")).click(); + + wait.until(_d -> !errors.isEmpty()); + Assertions.assertTrue(errors.get(0).getMessage().contains("Error: Not working")); + } + + @Test + public void waitForDownload() { + driver.get("https://www.selenium.dev/selenium/web/downloads/download.html"); + + 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)); + } +} diff --git a/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/CdpEndpointTest.java b/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/CdpEndpointTest.java new file mode 100644 index 000000000000..c8845e727d4d --- /dev/null +++ b/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/CdpEndpointTest.java @@ -0,0 +1,74 @@ +package dev.selenium.bidirectional.chrome_devtools; + +import com.google.common.collect.ImmutableMap; +import dev.selenium.BaseTest; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.Cookie; +import org.openqa.selenium.chrome.ChromeDriver; +import org.openqa.selenium.chromium.HasCdp; + +import java.util.Base64; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class CdpEndpointTest extends BaseTest { + @BeforeEach + public void createSession() { + driver = new ChromeDriver(); + } + + @Test + public void setCookie() { + Map cookie = new HashMap<>(); + cookie.put("name", "cheese"); + cookie.put("value", "gouda"); + cookie.put("domain", "www.selenium.dev"); + cookie.put("secure", true); + + ((HasCdp) driver).executeCdpCommand("Network.setCookie", cookie); + + driver.get("https://www.selenium.dev"); + Cookie cheese = driver.manage().getCookieNamed("cheese"); + Assertions.assertEquals("gouda", cheese.getValue()); + } + + @Test + public void performanceMetrics() { + driver.get("https://www.selenium.dev/selenium/web/frameset.html"); + + ((HasCdp) driver).executeCdpCommand("Performance.enable", new HashMap<>()); + + Map response = + ((HasCdp) driver).executeCdpCommand("Performance.getMetrics", new HashMap<>()); + List> metricList = (List>) response.get("metrics"); + + Map metrics = new HashMap<>(); + for (Map metric : metricList) { + metrics.put((String) metric.get("name"), (Number) metric.get("value")); + } + + Assertions.assertTrue(metrics.get("DevToolsCommandDuration").doubleValue() > 0); + Assertions.assertEquals(12, metrics.get("Frames").intValue()); + } + + @Test + public void basicAuth() { + ((HasCdp) driver).executeCdpCommand("Network.enable", new HashMap<>()); + + String encodedAuth = Base64.getEncoder().encodeToString("admin:admin".getBytes()); + Map headers = + ImmutableMap.of("headers", ImmutableMap.of("authorization", "Basic " + encodedAuth)); + + ((HasCdp) driver).executeCdpCommand("Network.setExtraHTTPHeaders", headers); + + driver.get("https://the-internet.herokuapp.com/basic_auth"); + + Assertions.assertEquals( + "Congratulations! You must have the proper credentials.", + driver.findElement(By.tagName("p")).getText()); + } +} diff --git a/examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java b/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java similarity index 99% rename from examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java rename to examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java index e38e1b7421b0..6efc1425c899 100644 --- a/examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java +++ b/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java @@ -1,4 +1,4 @@ -package dev.selenium.bidirectional.bidirectional_w3c; +package dev.selenium.bidirectional.webdriver_bidi; import dev.selenium.BaseTest; import java.util.List; diff --git a/examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/LogTest.java b/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/LogTest.java similarity index 87% rename from examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/LogTest.java rename to examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/LogTest.java index 9ddcc92a21ad..c5d634576faa 100644 --- a/examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/LogTest.java +++ b/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/LogTest.java @@ -1,10 +1,10 @@ -package dev.selenium.bidirectional.bidirectional_w3c; +package dev.selenium.bidirectional.webdriver_bidi; import dev.selenium.BaseTest; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; + +import java.time.Duration; +import java.util.concurrent.*; + import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -16,6 +16,7 @@ import org.openqa.selenium.bidi.log.StackTrace; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.firefox.FirefoxOptions; +import org.openqa.selenium.support.ui.WebDriverWait; class LogTest extends BaseTest { @@ -26,6 +27,21 @@ public void setup() { driver = new FirefoxDriver(options); } + @Test + public void jsErrors() { + CopyOnWriteArrayList logs = new CopyOnWriteArrayList<>(); + + try (LogInspector logInspector = new LogInspector(driver)) { + logInspector.onConsoleEntry(logs::add); + } + + driver.get("https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html"); + driver.findElement(By.id("consoleLog")).click(); + + new WebDriverWait(driver, Duration.ofSeconds(5)).until(_d -> !logs.isEmpty()); + Assertions.assertEquals("Hello, world!", logs.get(0).getText()); + } + @Test void testListenToConsoleLog() throws ExecutionException, InterruptedException, TimeoutException { try (LogInspector logInspector = new LogInspector(driver)) { diff --git a/examples/java/src/test/java/dev/selenium/browsers/ChromeTest.java b/examples/java/src/test/java/dev/selenium/browsers/ChromeTest.java index 6bc06013094f..7a0cfde32200 100644 --- a/examples/java/src/test/java/dev/selenium/browsers/ChromeTest.java +++ b/examples/java/src/test/java/dev/selenium/browsers/ChromeTest.java @@ -11,6 +11,9 @@ import org.openqa.selenium.chrome.ChromeDriverService; import org.openqa.selenium.chrome.ChromeOptions; import org.openqa.selenium.chromium.ChromiumDriverLogLevel; +import org.openqa.selenium.logging.LogEntries; +import org.openqa.selenium.logging.LogType; +import org.openqa.selenium.logging.LoggingPreferences; import org.openqa.selenium.print.PrintOptions; import java.io.*; @@ -18,6 +21,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.Base64; +import java.util.logging.Level; import java.util.regex.Pattern; public class ChromeTest { @@ -38,8 +42,15 @@ public void quit() { @Test public void basicOptions() throws IOException { ChromeOptions options = new ChromeOptions(); +// options.setExperimentalOption("perfLoggingPrefs", ImmutableMap.of("enableNetwork", true)); + LoggingPreferences logPrefs = new LoggingPreferences(); + logPrefs.enable(LogType.BROWSER, Level.ALL); + logPrefs.enable(LogType.PERFORMANCE, Level.ALL); + options.setCapability(ChromeOptions.LOGGING_PREFS, logPrefs); + driver = new ChromeDriver(options); driver.get("https://www.selenium.dev"); + driver.manage().logs().get(LogType.PERFORMANCE).forEach(System.out::println); String content = driver.print(new PrintOptions()).getContent(); byte[] bytes = Base64.getDecoder().decode(content); @@ -87,6 +98,20 @@ public void excludeSwitches() { driver = new ChromeDriver(options); } + @Test + public void loggingPreferences() { + ChromeOptions options = new ChromeOptions(); + LoggingPreferences logPrefs = new LoggingPreferences(); + logPrefs.enable(LogType.PERFORMANCE, Level.ALL); + options.setCapability(ChromeOptions.LOGGING_PREFS, logPrefs); + + driver = new ChromeDriver(options); + driver.get("https://www.selenium.dev"); + + LogEntries logEntries = driver.manage().logs().get(LogType.PERFORMANCE); + Assertions.assertFalse(logEntries.getAll().isEmpty()); + } + @Test public void logsToFile() throws IOException { ChromeDriverService service = new ChromeDriverService.Builder() diff --git a/examples/python/requirements.txt b/examples/python/requirements.txt index 9cf30bd51d1d..8a840ce60c50 100644 --- a/examples/python/requirements.txt +++ b/examples/python/requirements.txt @@ -1,3 +1,5 @@ selenium==4.14.0 pytest +trio +pytest-trio flake8 diff --git a/examples/python/tests/bidirectional/chrome_devtools/test_bidi_api.py b/examples/python/tests/bidirectional/chrome_devtools/test_bidi_api.py new file mode 100644 index 000000000000..b7e7a89b728a --- /dev/null +++ b/examples/python/tests/bidirectional/chrome_devtools/test_bidi_api.py @@ -0,0 +1,42 @@ +import pytest +from selenium.webdriver.common.bidi.console import Console +from selenium.webdriver.common.by import By +from selenium.webdriver.common.log import Log + + +@pytest.mark.trio +async def test_mutation(driver): + async with driver.bidi_connection() as session: + log = Log(driver, session) + + async with log.mutation_events() as event: + driver.get('https://www.selenium.dev/selenium/web/dynamic.html') + driver.find_element(By.ID, "reveal").click() + + assert event["element"] == driver.find_element(By.ID, "revealed") + + +@pytest.mark.trio +async def test_console_log(driver): + driver.get('https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html') + + async with driver.bidi_connection() as session: + log = Log(driver, session) + + async with log.add_listener(Console.ALL) as messages: + driver.find_element(by=By.ID, value='consoleLog').click() + + assert messages["message"] == "Hello, world!" + + +@pytest.mark.trio +async def test_js_error(driver): + driver.get('https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html') + + async with driver.bidi_connection() as session: + log = Log(driver, session) + + async with log.add_js_error_listener() as messages: + driver.find_element(by=By.ID, value='jsException').click() + + assert "Error: Not working" in messages.exception_details.exception.description diff --git a/examples/python/tests/bidirectional/chrome_devtools/test_cdp_api.py b/examples/python/tests/bidirectional/chrome_devtools/test_cdp_api.py new file mode 100644 index 000000000000..ff8a639b78d1 --- /dev/null +++ b/examples/python/tests/bidirectional/chrome_devtools/test_cdp_api.py @@ -0,0 +1,54 @@ +import base64 + +import pytest +from selenium.webdriver.common.by import By +from selenium.webdriver.common.devtools.v118.network import Headers + + +@pytest.mark.trio +async def test_set_cookie(driver): + async with driver.bidi_connection() as connection: + execution = connection.devtools.network.set_cookie( + name="cheese", + value="gouda", + domain="www.selenium.dev", + secure=True + ) + + await connection.session.execute(execution) + + driver.get("https://www.selenium.dev") + cheese = driver.get_cookie("cheese") + + assert cheese["value"] == "gouda" + + +@pytest.mark.trio +async def test_performance(driver): + driver.get('https://www.selenium.dev/selenium/web/frameset.html') + + async with driver.bidi_connection() as connection: + await connection.session.execute(connection.devtools.performance.enable()) + + metric_list = await connection.session.execute(connection.devtools.performance.get_metrics()) + + metrics = {metric.name: metric.value for metric in metric_list} + + assert metrics["DevToolsCommandDuration"] > 0 + assert metrics["Frames"] == 12 + + +@pytest.mark.trio +async def test_basic_auth(driver): + async with driver.bidi_connection() as connection: + await connection.session.execute(connection.devtools.network.enable()) + + credentials = base64.b64encode("admin:admin".encode()).decode() + auth = {'authorization': 'Basic ' + credentials} + + await connection.session.execute(connection.devtools.network.set_extra_http_headers(Headers(auth))) + + driver.get('https://the-internet.herokuapp.com/basic_auth') + + success = driver.find_element(by=By.TAG_NAME, value='p') + assert success.text == 'Congratulations! You must have the proper credentials.' diff --git a/examples/python/tests/bidirectional/chrome_devtools/test_cdp_endpoint.py b/examples/python/tests/bidirectional/chrome_devtools/test_cdp_endpoint.py new file mode 100644 index 000000000000..85f3b295d439 --- /dev/null +++ b/examples/python/tests/bidirectional/chrome_devtools/test_cdp_endpoint.py @@ -0,0 +1,44 @@ +import base64 + +from selenium.webdriver.common.by import By + + +def test_set_cookie(driver): + cookie = {'name': 'cheese', + 'value': 'gouda', + 'domain': 'www.selenium.dev', + 'secure': True} + + driver.execute_cdp_cmd('Network.setCookie', cookie) + + driver.get('https://www.selenium.dev') + cheese = driver.get_cookie(cookie['name']) + + assert cheese['value'] == 'gouda' + + +def test_performance(driver): + driver.get('https://www.selenium.dev/selenium/web/frameset.html') + + driver.execute_cdp_cmd('Performance.enable', {}) + + metric_list = driver.execute_cdp_cmd('Performance.getMetrics', {})["metrics"] + + metrics = {metric["name"]: metric["value"] for metric in metric_list} + + assert metrics["DevToolsCommandDuration"] > 0 + assert metrics["Frames"] == 12 + + +def test_basic_auth(driver): + driver.execute_cdp_cmd("Network.enable", {}) + + credentials = base64.b64encode("admin:admin".encode()).decode() + headers = {'headers': {'authorization': 'Basic ' + credentials}} + + driver.execute_cdp_cmd('Network.setExtraHTTPHeaders', headers) + + driver.get('https://the-internet.herokuapp.com/basic_auth') + + success = driver.find_element(by=By.TAG_NAME, value='p') + assert success.text == 'Congratulations! You must have the proper credentials.' diff --git a/examples/python/tests/bidirectional/test_bidi_api.py b/examples/python/tests/bidirectional/test_bidi_api.py deleted file mode 100644 index 53b695b6fc83..000000000000 --- a/examples/python/tests/bidirectional/test_bidi_api.py +++ /dev/null @@ -1,2 +0,0 @@ -from selenium import webdriver - diff --git a/examples/python/tests/bidirectional/test_chrome_devtools.py b/examples/python/tests/bidirectional/test_chrome_devtools.py deleted file mode 100644 index 48efad98a7d9..000000000000 --- a/examples/python/tests/bidirectional/test_chrome_devtools.py +++ /dev/null @@ -1 +0,0 @@ -from selenium import webdriver diff --git a/examples/python/tests/bidirectional/bidirectional_w3c/test_browsing_context.py b/examples/python/tests/bidirectional/webdriver_bidi/test_browsing_context.py similarity index 100% rename from examples/python/tests/bidirectional/bidirectional_w3c/test_browsing_context.py rename to examples/python/tests/bidirectional/webdriver_bidi/test_browsing_context.py diff --git a/examples/python/tests/bidirectional/bidirectional_w3c/test_log.py b/examples/python/tests/bidirectional/webdriver_bidi/test_log.py similarity index 100% rename from examples/python/tests/bidirectional/bidirectional_w3c/test_log.py rename to examples/python/tests/bidirectional/webdriver_bidi/test_log.py diff --git a/examples/ruby/Gemfile b/examples/ruby/Gemfile index 0c4560e32484..817fd1133545 100644 --- a/examples/ruby/Gemfile +++ b/examples/ruby/Gemfile @@ -8,4 +8,13 @@ gem 'rspec', '~> 3.0' gem 'rubocop', '~> 1.35' gem 'rubocop-rspec', '~> 2.12' gem 'selenium-devtools', '~> 0.116' -gem 'selenium-webdriver', '= 4.14.0' + +if ENV['SE_NIGHTLY'] + source 'https://rubygems.pkg.github.com/seleniumhq' do + selenium = 'selenium-webdriver' + gem selenium, '~> 4.15.0.nightly' + end +else + gem 'selenium-webdriver', '= 4.14.0' +end + diff --git a/examples/ruby/spec/bidirectional/bidi_api_spec.rb b/examples/ruby/spec/bidirectional/bidi_api_spec.rb deleted file mode 100644 index 9b13557e22f3..000000000000 --- a/examples/ruby/spec/bidirectional/bidi_api_spec.rb +++ /dev/null @@ -1,6 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe 'BiDi API' do -end diff --git a/examples/ruby/spec/bidirectional/bidirectional_w3c/browsing_context_spec.rb b/examples/ruby/spec/bidirectional/bidirectional_w3c/browsing_context_spec.rb deleted file mode 100644 index 38d4ca5508d5..000000000000 --- a/examples/ruby/spec/bidirectional/bidirectional_w3c/browsing_context_spec.rb +++ /dev/null @@ -1,6 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe 'Browsing Context' do -end diff --git a/examples/ruby/spec/bidirectional/chrome_devtools/bidi_api_spec.rb b/examples/ruby/spec/bidirectional/chrome_devtools/bidi_api_spec.rb new file mode 100644 index 000000000000..40b5a103b59d --- /dev/null +++ b/examples/ruby/spec/bidirectional/chrome_devtools/bidi_api_spec.rb @@ -0,0 +1,100 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'BiDi API' do + let(:driver) { start_session } + + it 'does basic authentication' do + driver.register(username: 'admin', + password: 'admin', + uri: /herokuapp/) + + driver.get('https://the-internet.herokuapp.com/basic_auth') + + expect(driver.find_element(tag_name: 'p').text).to eq('Congratulations! You must have the proper credentials.') + end + + 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 + + it 'listens for console logs' do + driver.get('https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html') + + logs = [] + driver.on_log_event(:console) { |log| logs << log.args.first } + + driver.find_element(id: 'consoleLog').click + driver.find_element(id: 'consoleError').click + + Selenium::WebDriver::Wait.new.until { logs.size > 1 } + expect(logs).to include 'Hello, world!' + expect(logs).to include 'I am console error' + end + + it 'listens for js exception' do + driver.get('https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html') + + exceptions = [] + driver.on_log_event(:exception) { |exception| exceptions << exception } + + driver.find_element(id: 'jsException').click + + Selenium::WebDriver::Wait.new.until { exceptions.any? } + expect(exceptions.first&.description).to include 'Error: Not working' + end + + it 'records network response' do + content_type = [] + driver.intercept do |request, &continue| + continue.call(request) do |response| + content_type << response.headers["content-type"] + end + end + + driver.get('https://www.selenium.dev/selenium/web/blank.html') + expect(content_type.first).to eq('text/html; charset=utf-8') + end + + it 'transforms network response' do + driver.intercept do |request, &continue| + continue.call(request) do |response| + response.body = 'Creamy, delicious cheese!' if request.url.include?('blank') + end + end + + driver.get('https://www.selenium.dev/selenium/web/blank.html') + expect(driver.find_element(tag_name: 'body').text).to eq('Creamy, delicious cheese!') + end + + it 'intercepts network request' do + driver.intercept do |request, &continue| + uri = URI(request.url) + request.url = uri.to_s.gsub('one', 'two') if uri.path&.end_with?('one.js') + continue.call(request) + end + + driver.get('https://www.selenium.dev/selenium/web/devToolsRequestInterceptionTest.html') + driver.find_element(tag_name: 'button').click + expect(driver.find_element(id: 'result').text).to eq('two') + end +end diff --git a/examples/ruby/spec/bidirectional/chrome_devtools/cdp_api_spec.rb b/examples/ruby/spec/bidirectional/chrome_devtools/cdp_api_spec.rb new file mode 100644 index 000000000000..4b6051b9548f --- /dev/null +++ b/examples/ruby/spec/bidirectional/chrome_devtools/cdp_api_spec.rb @@ -0,0 +1,78 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'Chrome DevTools' do + let(:driver) { start_session } + + it 'sets cookie' do + driver.devtools.network.set_cookie(name: 'cheese', + value: 'gouda', + domain: 'www.selenium.dev', + secure: true) + + driver.get('https://www.selenium.dev') + cheese = driver.manage.cookie_named('cheese') + + expect(cheese[:value]).to eq 'gouda' + end + + it 'gets performance metrics' do + driver.get('https://www.selenium.dev/selenium/web/frameset.html') + + driver.devtools.performance.enable + + metric_list = driver.devtools.performance.get_metrics.dig('result', 'metrics') + + metrics = metric_list.each_with_object({}) do |metric, hash| + hash[metric['name']] = metric['value'] + end + + expect(metrics['DevToolsCommandDuration']).to be > 0 + expect(metrics['Frames']).to eq 12 + end + + it 'does basic authentication' do + driver.devtools.network.enable + + credentials = Base64.strict_encode64('admin:admin') + + driver.devtools.network.set_extra_http_headers(headers: { authorization: "Basic #{credentials}" }) + + driver.get('https://the-internet.herokuapp.com/basic_auth') + + expect(driver.find_element(tag_name: 'p').text).to eq('Congratulations! You must have the proper credentials.') + end + + it 'listens for console logs' do + driver.get('https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html') + + driver.devtools.runtime.enable + + logs = [] + driver.devtools.runtime.on(:console_api_called) do |params| + logs << params['args'].first['value'] + end + + driver.find_element(id: 'consoleLog').click + + Selenium::WebDriver::Wait.new.until { logs.any? } + expect(logs).to include 'Hello, world!' + end + + it 'waits for downloads', except: {platform: :windows} do + driver.get('https://www.selenium.dev/selenium/web/downloads/download.html') + + driver.devtools.browser.set_download_behavior(behavior: 'allow', + download_path: '', + events_enabled: true) + + driver.devtools.browser.on(:download_progress) do |progress| + @completed = progress['state'] == 'completed' + end + + driver.find_element(id: 'file-2').click + + expect { Selenium::WebDriver::Wait.new.until { @completed } }.not_to raise_exception + end +end diff --git a/examples/ruby/spec/bidirectional/chrome_devtools/cdp_endpoint_spec.rb b/examples/ruby/spec/bidirectional/chrome_devtools/cdp_endpoint_spec.rb new file mode 100644 index 000000000000..543f8c81fe43 --- /dev/null +++ b/examples/ruby/spec/bidirectional/chrome_devtools/cdp_endpoint_spec.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'Execute CDP' do + let(:driver) { start_session } + + it 'sets cookie' do + cookie = {name: 'cheese', + value: 'gouda', + domain: 'www.selenium.dev', + secure: true} + + driver.execute_cdp('Network.setCookie', **cookie) + + driver.get('https://www.selenium.dev') + cheese = driver.manage.cookie_named(cookie[:name]) + + expect(cheese[:value]).to eq 'gouda' + end + + it 'gets performance metrics' do + driver.get('https://www.selenium.dev/selenium/web/frameset.html') + + driver.execute_cdp('Performance.enable') + + metric_list = driver.execute_cdp('Performance.getMetrics')['metrics'] + + metrics = metric_list.each_with_object({}) do |metric, hash| + hash[metric['name']] = metric['value'] + end + + expect(metrics['DevToolsCommandDuration']).to be > 0 + expect(metrics['Frames']).to eq 12 + end + + it 'sets basic authentication' do + driver.execute_cdp('Network.enable') + + credentials = Base64.strict_encode64('admin:admin') + headers = {authorization: "Basic #{credentials}"} + + driver.execute_cdp('Network.setExtraHTTPHeaders', headers: headers) + + driver.get('https://the-internet.herokuapp.com/basic_auth') + + expect(driver.find_element(tag_name: 'p').text).to eq('Congratulations! You must have the proper credentials.') + end +end diff --git a/examples/ruby/spec/bidirectional/chrome_devtools_spec.rb b/examples/ruby/spec/bidirectional/chrome_devtools_spec.rb deleted file mode 100644 index 53a22e52e1af..000000000000 --- a/examples/ruby/spec/bidirectional/chrome_devtools_spec.rb +++ /dev/null @@ -1,6 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe 'CDP' do -end diff --git a/examples/ruby/spec/bidirectional/webdriver_bidi/browsing_context_spec.rb b/examples/ruby/spec/bidirectional/webdriver_bidi/browsing_context_spec.rb new file mode 100644 index 000000000000..13e106f77e00 --- /dev/null +++ b/examples/ruby/spec/bidirectional/webdriver_bidi/browsing_context_spec.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'Browsing Context' do + it 'opens a window without browsing context' + it 'opens a window with browsing context' + it 'opens a tab without browsing context' + it 'opens a tab with browsing context' + it 'uses existing window' + it 'navigates to url with readiness state' + it 'navigates to url without readiness state' + it 'gets browsing context tree with depth' + it 'gets browsing context tree without depth' + it 'gets all browsing contexts' + it 'closes a tab' + it 'closes a window' + + +end diff --git a/examples/ruby/spec/bidirectional/bidirectional_w3c/log_spec.rb b/examples/ruby/spec/bidirectional/webdriver_bidi/log_spec.rb similarity index 54% rename from examples/ruby/spec/bidirectional/bidirectional_w3c/log_spec.rb rename to examples/ruby/spec/bidirectional/webdriver_bidi/log_spec.rb index 6bcddcf8a88d..cde9854b1e4e 100644 --- a/examples/ruby/spec/bidirectional/bidirectional_w3c/log_spec.rb +++ b/examples/ruby/spec/bidirectional/webdriver_bidi/log_spec.rb @@ -3,4 +3,7 @@ require 'spec_helper' RSpec.describe 'Log Inspector' do + it 'listens to console log' + it 'gets JS exceptions' + it 'gets JS logs' end diff --git a/examples/ruby/spec/spec_helper.rb b/examples/ruby/spec/spec_helper.rb index 755acb4ed1b3..b03fe52f4dfc 100644 --- a/examples/ruby/spec/spec_helper.rb +++ b/examples/ruby/spec/spec_helper.rb @@ -41,4 +41,16 @@ def start_firefox options = Selenium::WebDriver::Options.firefox(timeouts: {implicit: 1500}) @driver = Selenium::WebDriver.for :firefox, options: options end + + # This can be removed with Selenium 4.14 + module Selenium + module WebDriver + module Atoms + def atom_script(function_name) + format("/* #{function_name} */return (%s).apply(null, arguments)", + atom: read_atom(function_name)) + end + end + end + end end diff --git a/website_and_docs/content/documentation/webdriver/bidirectional/_index.ja.md b/website_and_docs/content/documentation/webdriver/bidirectional/_index.ja.md index cbe1f7846858..39b4dfdadd99 100644 --- a/website_and_docs/content/documentation/webdriver/bidirectional/_index.ja.md +++ b/website_and_docs/content/documentation/webdriver/bidirectional/_index.ja.md @@ -32,7 +32,12 @@ better matching the evented nature of the browser DOM. As it is not a good idea to tie your tests to a specific version of any browser, the Selenium project recommends using WebDriver BiDi wherever possible. -However, until the specification is complete there are many useful things that -CDP (Chrome DevTools Protocol) offers. To help keep your tests independent -and portable, Selenium offers some useful helper classes as well. At the -moment, they use the CDP, but soon it could be done using WebDriver BiDi. +While the specification is in works, the browser vendors are parallely implementing +the [WebDriver BiDirectional Protocol](https://w3c.github.io/webdriver-bidi/). +Refer [web-platform-tests dashboard](https://wpt.fyi/results/webdriver/tests/bidi?label=experimental&label=master&aligned&view=subtest) +to see how far along the browser vendors are. +Selenium is trying to keep up with the browser vendors and has started implementing W3C BiDi APIs. +The goal is to ensure APIs are W3C compliant and uniform among the different language bindings. + +However, until the specification and corresponding Selenium implementation is complete there are many useful things that +CDP offers. Selenium offers some useful helper classes that use CDP. \ No newline at end of file diff --git a/website_and_docs/content/documentation/webdriver/bidirectional/_index.pt-br.md b/website_and_docs/content/documentation/webdriver/bidirectional/_index.pt-br.md index fe258438d7a6..218ad8df93a3 100644 --- a/website_and_docs/content/documentation/webdriver/bidirectional/_index.pt-br.md +++ b/website_and_docs/content/documentation/webdriver/bidirectional/_index.pt-br.md @@ -32,7 +32,12 @@ better matching the evented nature of the browser DOM. As it is not a good idea to tie your tests to a specific version of any browser, the Selenium project recommends using WebDriver BiDi wherever possible. -However, until the specification is complete there are many useful things that -CDP (Chrome DevTools Protocol) offers. To help keep your tests independent -and portable, Selenium offers some useful helper classes as well. At the -moment, they use the CDP, but soon it could be done using WebDriver BiDi. \ No newline at end of file +While the specification is in works, the browser vendors are parallely implementing +the [WebDriver BiDirectional Protocol](https://w3c.github.io/webdriver-bidi/). +Refer [web-platform-tests dashboard](https://wpt.fyi/results/webdriver/tests/bidi?label=experimental&label=master&aligned&view=subtest) +to see how far along the browser vendors are. +Selenium is trying to keep up with the browser vendors and has started implementing W3C BiDi APIs. +The goal is to ensure APIs are W3C compliant and uniform among the different language bindings. + +However, until the specification and corresponding Selenium implementation is complete there are many useful things that +CDP offers. Selenium offers some useful helper classes that use CDP. \ No newline at end of file diff --git a/website_and_docs/content/documentation/webdriver/bidirectional/_index.zh-cn.md b/website_and_docs/content/documentation/webdriver/bidirectional/_index.zh-cn.md index 861c3d07357d..731e9555de00 100644 --- a/website_and_docs/content/documentation/webdriver/bidirectional/_index.zh-cn.md +++ b/website_and_docs/content/documentation/webdriver/bidirectional/_index.zh-cn.md @@ -23,10 +23,12 @@ Selenium正在与浏览器供应商合作创建 通过这样完善流事件的能力, 以便更好地匹配浏览器DOM的事件性质. -因为将测试受限于特定浏览器的特定版本是个坏主意, -Selenium项目建议尽可能使用WebDriver BiDi. -然而, 在规范完成之前, CDP提供了许多有用的东西. -为了帮助保持测试的独立性和可移植性, -Selenium提供了一些有用的辅助类. -目前, 这些应用程序使用CDP, -但我们将尽快提供WebDriver Bidi的实现. \ No newline at end of file +While the specification is in works, the browser vendors are parallely implementing +the [WebDriver BiDirectional Protocol](https://w3c.github.io/webdriver-bidi/). +Refer [web-platform-tests dashboard](https://wpt.fyi/results/webdriver/tests/bidi?label=experimental&label=master&aligned&view=subtest) +to see how far along the browser vendors are. +Selenium is trying to keep up with the browser vendors and has started implementing W3C BiDi APIs. +The goal is to ensure APIs are W3C compliant and uniform among the different language bindings. + +However, until the specification and corresponding Selenium implementation is complete there are many useful things that +CDP offers. Selenium offers some useful helper classes that use CDP. \ No newline at end of file diff --git a/website_and_docs/content/documentation/webdriver/bidirectional/bidi_api.en.md b/website_and_docs/content/documentation/webdriver/bidirectional/bidi_api.en.md deleted file mode 100644 index eff352acf2e3..000000000000 --- a/website_and_docs/content/documentation/webdriver/bidirectional/bidi_api.en.md +++ /dev/null @@ -1,500 +0,0 @@ ---- -title: "BiDirectional API (CDP implementation)" -linkTitle: "BiDi API (CDP implementation)" -weight: 1 ---- - -The following list of APIs will be growing as the Selenium -project works through supporting real world use cases. If there -is additional functionality you'd like to see, please raise a -[feature request](https://github.com/SeleniumHQ/selenium/issues/new?assignees=&labels=&template=feature.md). - -## Register Basic Auth - -Some applications make use of browser authentication to secure pages. -With Selenium, you can automate the input of basic auth credentials whenever they arise. - -{{< tabpane langEqualsHeader=true >}} -{{< badge-examples >}} -{{< tab header="Java" >}} -{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/BidiApiTest.java/#L29-L32" >}} -{{< /tab >}} -{{< tab header="Python" text=true >}} -{{< badge-code >}} -{{< /tab >}} -{{< tab header="CSharp" text=true >}} -{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/BidiApiTest.cs#L13-L24" >}} -{{< /tab >}} -{{< tab header="Ruby" >}} -require 'selenium-webdriver' - -driver = Selenium::WebDriver.for :chrome - -begin - driver.devtools.new - driver.register(username: 'username', password: 'password') - driver.get '' -ensure - driver.quit -end -{{< /tab >}} -{{< tab header="JavaScript" >}} -const {Builder} = require('selenium-webdriver'); - -(async function example() { - try { - let driver = await new Builder() - .forBrowser('chrome') - .build(); - - const pageCdpConnection = await driver.createCDPConnection('page'); - await driver.register('username', 'password', pageCdpConnection); - await driver.get('https://the-internet.herokuapp.com/basic_auth'); - await driver.quit(); - }catch (e){ - console.log(e) - } -}()) -{{< /tab >}} -{{< tab header="Kotlin" >}} -val uriPredicate = Predicate { uri: URI -> - uri.host.contains("your-domain.com") - } -(driver as HasAuthentication).register(uriPredicate, UsernameAndPassword.of("admin", "password")) -driver.get("https://your-domain.com/login") -{{< /tab >}} -{{< /tabpane >}} - -## Mutation Observation - -Mutation Observation is the ability to capture events via -WebDriver BiDi when there are DOM mutations on a specific -element in the DOM. - -{{< tabpane langEqualsHeader=true >}} -{{< badge-examples >}} -{{< tab header="Java" >}} -{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/BidiApiTest.java/#L39-L50" >}} -{{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -from selenium.webdriver.common.by import By -from selenium.webdriver.support.wait import WebDriverWait - -driver = webdriver.Chrome() -async with driver.log.mutation_events() as event: - pages.load("dynamic.html") - driver.find_element(By.ID, "reveal").click() - WebDriverWait(driver, 5)\ - .until(EC.visibility_of(driver.find_element(By.ID, "revealed"))) - -assert event["attribute_name"] == "style" -assert event["current_value"] == "" -assert event["old_value"] == "display:none;" - - {{< /tab >}} - {{< tab header="CSharp" >}} -List attributeValueChanges = new List(); -DefaultWait> wait = new DefaultWait>(attributeValueChanges); -wait.Timeout = TimeSpan.FromSeconds(3); - -using IJavaScriptEngine monitor = new JavaScriptEngine(driver); -monitor.DomMutated += (sender, e) => -{ - attributeValueChanges.Add(e.AttributeData); -}; -await monitor.StartEventMonitoring(); - -driver.Navigate().GoToUrl("http://www.google.com"); -IWebElement span = driver.FindElement(By.CssSelector("span")); - -await monitor.EnableDomMutationMonitoring(); -((IJavaScriptExecutor) driver).ExecuteScript("arguments[0].setAttribute('cheese', 'gouda');", span); - -wait.Until((list) => list.Count > 0); -Console.WriteLine("Found {0} DOM mutation events", attributeValueChanges.Count); -foreach(var record in attributeValueChanges) -{ - Console.WriteLine("Attribute name: {0}", record.AttributeName); - Console.WriteLine("Attribute value: {0}", record.AttributeValue); -} - -await monitor.DisableDomMutationMonitoring(); - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :firefox -begin - driver.on_log_event(:mutation) { |mutation| mutations.push(mutation) } - driver.navigate.to url_for('dynamic.html') - driver.find_element(id: 'reveal').click - wait.until { mutations.any? } - mutation = mutations.first - expect(mutation.element).to eq(driver.find_element(id: 'revealed')) - expect(mutation.attribute_name).to eq('style') - expect(mutation.current_value).to eq('') - expect(mutation.old_value).to eq('display:none;') -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" >}} -const {Builder, until} = require('selenium-webdriver'); -const assert = require("assert"); - -(async function example() { - try { - let driver = await new Builder() - .forBrowser('chrome') - .build(); - - const cdpConnection = await driver.createCDPConnection('page'); - await driver.logMutationEvents(cdpConnection, event => { - assert.deepStrictEqual(event['attribute_name'], 'style'); - assert.deepStrictEqual(event['current_value'], ""); - assert.deepStrictEqual(event['old_value'], "display:none;"); - }); - - await driver.get('dynamic.html'); - await driver.findElement({id: 'reveal'}).click(); - let revealed = driver.findElement({id: 'revealed'}); - await driver.wait(until.elementIsVisible(revealed), 5000); - await driver.quit(); - }catch (e){ - console.log(e) - } -}()) - {{< /tab >}} - {{< tab header="Kotlin" text=true >}} -{{< badge-code >}} - {{< /tab >}} -{{< /tabpane >}} - -## Listen to `console.log` events - -Listen to the `console.log` events and register callbacks to process the event. - -{{< tabpane langEqualsHeader=true >}} -{{< badge-examples >}} -{{< tab header="Java" >}} -ChromeDriver driver = new ChromeDriver(); -DevTools devTools = driver.getDevTools(); -devTools.createSession(); -devTools.send(Log.enable()); -devTools.addListener(Log.entryAdded(), - logEntry -> { - System.out.println("log: "+logEntry.getText()); - System.out.println("level: "+logEntry.getLevel()); - }); -driver.get("http://the-internet.herokuapp.com/broken_images"); -// Check the terminal output for the browser console messages. -driver.quit(); -{{< /tab >}} -{{< tab header="Python" >}} -import trio -from selenium import webdriver -from selenium.webdriver.common.log import Log - -async def printConsoleLogs(): - chrome_options = webdriver.ChromeOptions() - driver = webdriver.Chrome() - driver.get("http://www.google.com") - - async with driver.bidi_connection() as session: - log = Log(driver, session) - from selenium.webdriver.common.bidi.console import Console - async with log.add_listener(Console.ALL) as messages: - driver.execute_script("console.log('I love cheese')") - print(messages["message"]) - - driver.quit() - -trio.run(printConsoleLogs) -{{< /tab >}} -{{< tab header="CSharp" >}} -using IJavaScriptEngine monitor = new JavaScriptEngine(driver); -List consoleMessages = new List(); -monitor.JavaScriptConsoleApiCalled += (sender, e) => -{ - Console.WriteLine("Log: {0}", e.MessageContent); -}; -await monitor.StartEventMonitoring(); -{{< /tab >}} -{{< tab header="Ruby" >}} -require 'selenium-webdriver' - -driver = Selenium::WebDriver.for :chrome -begin - driver.get 'http://www.google.com' - logs = [] - driver.on_log_event(:console) do |event| - logs.push(event) - puts logs.length - end - - driver.execute_script('console.log("here")') - -ensure - driver.quit -end -{{< /tab >}} -{{< tab header="JavaScript" >}} -const {Builder} = require('selenium-webdriver'); -(async () => { - try { - let driver = new Builder() - .forBrowser('chrome') - .build(); - - const cdpConnection = await driver.createCDPConnection('page'); - await driver.onLogEvent(cdpConnection, function (event) { - console.log(event['args'][0]['value']); - }); - await driver.executeScript('console.log("here")'); - await driver.quit(); - }catch (e){ - console.log(e); - } -})() -{{< /tab >}} -{{< tab header="Kotlin" >}} -fun kotlinConsoleLogExample() { - val driver = ChromeDriver() - val devTools = driver.devTools - devTools.createSession() - - val logConsole = { c: ConsoleEvent -> print("Console log message is: " + c.messages)} - devTools.domains.events().addConsoleListener(logConsole) - - driver.get("https://www.google.com") - - val executor = driver as JavascriptExecutor - executor.executeScript("console.log('Hello World')") - - val input = driver.findElement(By.name("q")) - input.sendKeys("Selenium 4") - input.sendKeys(Keys.RETURN) - driver.quit() -} -{{< /tab >}} -{{< /tabpane >}} - -## Listen to JS Exceptions - -Listen to the JS Exceptions -and register callbacks to process the exception details. - -{{< tabpane langEqualsHeader=true >}} -{{< badge-examples >}} -{{< tab header="Java" >}} -import org.openqa.selenium.*; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.devtools.DevTools; - -public void jsExceptionsExample() { - ChromeDriver driver = new ChromeDriver(); - DevTools devTools = driver.getDevTools(); - devTools.createSession(); - - List jsExceptionsList = new ArrayList<>(); - Consumer addEntry = jsExceptionsList::add; - devTools.getDomains().events().addJavascriptExceptionListener(addEntry); - - driver.get(""); - - WebElement link2click = driver.findElement(By.linkText("")); - ((JavascriptExecutor) driver).executeScript("arguments[0].setAttribute(arguments[1], arguments[2]);", - link2click, "onclick", "throw new Error('Hello, world!')"); - link2click.click(); - - for (JavascriptException jsException : jsExceptionsList) { - System.out.println("JS exception message: " + jsException.getMessage()); - System.out.println("JS exception system information: " + jsException.getSystemInformation()); - jsException.printStackTrace(); - } -} -{{< /tab >}} -{{< tab header="Python" >}} -async def catchJSException(): - chrome_options = webdriver.ChromeOptions() - driver = webdriver.Chrome() - - async with driver.bidi_connection() as session: - driver.get("") - log = Log(driver, session) - async with log.add_js_error_listener() as messages: - # Operation on the website that throws an JS error - print(messages) - - driver.quit() -{{< /tab >}} -{{< tab header="CSharp" >}} -List exceptionMessages = new List(); -using IJavaScriptEngine monitor = new JavaScriptEngine(driver); -monitor.JavaScriptExceptionThrown += (sender, e) => -{ - exceptionMessages.Add(e.Message); -}; - -await monitor.StartEventMonitoring(); - -driver.Navigate.GoToUrl(""); - -IWebElement link2click = driver.FindElement(By.LinkText("")); -((IJavaScriptExecutor) driver).ExecuteScript("arguments[0].setAttribute(arguments[1], arguments[2]);", - link2click, "onclick", "throw new Error('Hello, world!')"); -link2click.Click(); - -foreach (string message in exceptionMessages) -{ - Console.WriteLine("JS exception message: {0}", message); -} -{{< /tab >}} -{{< tab header="Ruby" >}} -require 'selenium-webdriver' - -driver = Selenium::WebDriver.for :chrome -begin - driver.get '' - exceptions = [] - driver.on_log_event(:exception) do |event| - exceptions.push(event) - puts exceptions.length - end - - #Actions causing JS exceptions - -ensure - driver.quit -end -{{< /tab >}} -{{< tab header="JavaScript" >}} -const {Builder, By} = require('selenium-webdriver'); -(async () => { - try { - let driver = new Builder() - .forBrowser('chrome') - .build(); - - const cdpConnection = await driver.createCDPConnection('page') - await driver.onLogException(cdpConnection, function (event) { - console.log(event['exceptionDetails']); - }) - await driver.get('https://the-internet.herokuapp.com'); - const link = await driver.findElement(By.linkText('Checkboxes')); - await driver.executeScript("arguments[0].setAttribute(arguments[1], arguments[2]);", link, "onclick","throw new Error('Hello, world!')"); - await link.click(); - await driver.quit(); - }catch (e){ - console.log(e); - } -})() -{{< /tab >}} -{{< tab header="Kotlin" >}} -fun kotlinJsErrorListener() { - val driver = ChromeDriver() - val devTools = driver.devTools - devTools.createSession() - - val logJsError = { j: JavascriptException -> print("Javascript error: '" + j.localizedMessage + "'.") } - devTools.domains.events().addJavascriptExceptionListener(logJsError) - - driver.get("https://www.google.com") - - val link2click = driver.findElement(By.name("q")) - (driver as JavascriptExecutor).executeScript( - "arguments[0].setAttribute(arguments[1], arguments[2]);", - link2click, "onclick", "throw new Error('Hello, world!')" - ) - link2click.click() - - driver.quit() -} -{{< /tab >}} -{{< /tabpane >}} - -## Network Interception - -If you want to capture network events coming into the browser and you want manipulate them you are able to do -it with the following examples. - -### Intercept Responses - -{{< tabpane langEqualsHeader=true >}} -{{< badge-examples >}} -{{< tab header="Java" >}} -{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/BidiApiTest.java#L59-L66" >}} -{{< /tab >}} -{{< tab header="Python" >}} -Currently unavailable in python due the inability to mix certain async and sync commands -{{< /tab >}} -{{< tab header="CSharp" text=true >}} -{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/BidiApiTest.cs#L33-L48" >}} -{{< /tab >}} -{{< tab header="Ruby" >}} -require 'selenium-webdriver' - -driver = Selenium::WebDriver.for :chrome -driver.intercept do |request, &continue| - uri = URI(request.url) - if uri.path.end_with?('one.js') - uri.path = '/devtools_request_interception_test/two.js' - request.url = uri.to_s - end - continue.call(request) -end -driver.navigate.to url_for('devToolsRequestInterceptionTest.html') -driver.find_element(tag_name: 'button').click -expect(driver.find_element(id: 'result').text).to eq('two') -{{< /tab >}} - -{{< tab header="JavaScript" >}} -const connection = await driver.createCDPConnection('page') -let url = fileServer.whereIs("/cheese") -let httpResponse = new HttpResponse(url) -httpResponse.addHeaders("Content-Type", "UTF-8") -httpResponse.body = "sausages" -await driver.onIntercept(connection, httpResponse, async function () { - let body = await driver.getPageSource() - assert.strictEqual(body.includes("sausages"), true, `Body contains: ${body}`) -}) -driver.get(url) -{{< /tab >}} -{{< tab header="Kotlin" >}} -val driver = ChromeDriver() -val interceptor = new NetworkInterceptor( - driver, - Route.matching(req -> true) - .to(() -> req -> new HttpResponse() - .setStatus(200) - .addHeader("Content-Type", MediaType.HTML_UTF_8.toString()) - .setContent(utf8String("Creamy, delicious cheese!")))) - - driver.get(appServer.whereIs("/cheese")) - - String source = driver.getPageSource() -{{< /tab >}} -{{< /tabpane >}} - -### Intercept Requests - -{{< tabpane text=true langEqualsHeader=true >}} -{{< tab header="Java" >}} -{{< badge-code >}} -{{< /tab >}} -{{< tab header="Python" >}} -{{< badge-code >}} -{{< /tab >}} -{{< tab header="CSharp" >}} -{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/BidiApiTest.cs#L56-L71" >}} -{{< /tab >}} -{{< tab header="Ruby" >}} -{{< badge-code >}} -{{< /tab >}} -{{< tab header="JavaScript" >}} -{{< badge-code >}} -{{< /tab >}} -{{< tab header="Kotlin" >}} -{{< badge-code >}} -{{< /tab >}} -{{< /tabpane >}} diff --git a/website_and_docs/content/documentation/webdriver/bidirectional/bidi_api.ja.md b/website_and_docs/content/documentation/webdriver/bidirectional/bidi_api.ja.md deleted file mode 100644 index a27b57b7fd3c..000000000000 --- a/website_and_docs/content/documentation/webdriver/bidirectional/bidi_api.ja.md +++ /dev/null @@ -1,504 +0,0 @@ ---- -title: "BiDirectional API (CDP implementation)" -linkTitle: "BiDi API (CDP implementation)" -weight: 12 ---- - -{{% pageinfo color="warning" %}} -

- - Page being translated from - English to Japanese. Do you speak Japanese? Help us to translate - it by sending us pull requests! -

-{{% /pageinfo %}} - -The following list of APIs will be growing as the Selenium -project works through supporting real world use cases. If there -is additional functionality you'd like to see, please raise a -[feature request](https://github.com/SeleniumHQ/selenium/issues/new?assignees=&labels=&template=feature.md). - -## Register Basic Auth - -Some applications make use of browser authentication to secure pages. -With Selenium, you can automate the input of basic auth credentials whenever they arise. - -{{< tabpane langEqualsHeader=true >}} -{{< tab header="Java" >}} -{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/BidiApiTest.java/#L29-L32" >}} -{{< /tab >}} -{{< tab header="Python" text=true >}} -{{< badge-code >}} -{{< /tab >}} -{{< tab header="CSharp" text=true >}} -{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/BidiApiTest.cs#L13-L24" >}} -{{< /tab >}} -{{< tab header="Ruby" >}} -require 'selenium-webdriver' - -driver = Selenium::WebDriver.for :chrome - -begin - driver.devtools.new - driver.register(username: 'username', password: 'password') - driver.get '' -ensure - driver.quit -end -{{< /tab >}} -{{< tab header="JavaScript" >}} -const {Builder} = require('selenium-webdriver'); - -(async function example() { - try { - let driver = await new Builder() - .forBrowser('chrome') - .build(); - - const pageCdpConnection = await driver.createCDPConnection('page'); - await driver.register('username', 'password', pageCdpConnection); - await driver.get('https://the-internet.herokuapp.com/basic_auth'); - await driver.quit(); - }catch (e){ - console.log(e) - } -}()) -{{< /tab >}} -{{< tab header="Kotlin" >}} -val uriPredicate = Predicate { uri: URI -> - uri.host.contains("your-domain.com") - } -(driver as HasAuthentication).register(uriPredicate, UsernameAndPassword.of("admin", "password")) -driver.get("https://your-domain.com/login") -{{< /tab >}} -{{< /tabpane >}} - -## Mutation Observation - -Mutation Observation is the ability to capture events via -WebDriver BiDi when there are DOM mutations on a specific -element in the DOM. - -{{< tabpane langEqualsHeader=true >}} -{{< tab header="Java" >}} -{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/BidiApiTest.java/#L39-L50" >}} -{{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -from selenium.webdriver.common.by import By -from selenium.webdriver.support.wait import WebDriverWait - -driver = webdriver.Chrome() -async with driver.log.mutation_events() as event: - pages.load("dynamic.html") - driver.find_element(By.ID, "reveal").click() - WebDriverWait(driver, 5)\ - .until(EC.visibility_of(driver.find_element(By.ID, "revealed"))) - -assert event["attribute_name"] == "style" -assert event["current_value"] == "" -assert event["old_value"] == "display:none;" - - {{< /tab >}} - {{< tab header="CSharp" >}} -List attributeValueChanges = new List(); -DefaultWait> wait = new DefaultWait>(attributeValueChanges); -wait.Timeout = TimeSpan.FromSeconds(3); - -using IJavaScriptEngine monitor = new JavaScriptEngine(driver); -monitor.DomMutated += (sender, e) => -{ - attributeValueChanges.Add(e.AttributeData); -}; -await monitor.StartEventMonitoring(); - -driver.Navigate().GoToUrl("http://www.google.com"); -IWebElement span = driver.FindElement(By.CssSelector("span")); - -await monitor.EnableDomMutationMonitoring(); -((IJavaScriptExecutor) driver).ExecuteScript("arguments[0].setAttribute('cheese', 'gouda');", span); - -wait.Until((list) => list.Count > 0); -Console.WriteLine("Found {0} DOM mutation events", attributeValueChanges.Count); -foreach(var record in attributeValueChanges) -{ - Console.WriteLine("Attribute name: {0}", record.AttributeName); - Console.WriteLine("Attribute value: {0}", record.AttributeValue); -} - -await monitor.DisableDomMutationMonitoring(); - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :firefox -begin - driver.on_log_event(:mutation) { |mutation| mutations.push(mutation) } - driver.navigate.to url_for('dynamic.html') - driver.find_element(id: 'reveal').click - wait.until { mutations.any? } - mutation = mutations.first - expect(mutation.element).to eq(driver.find_element(id: 'revealed')) - expect(mutation.attribute_name).to eq('style') - expect(mutation.current_value).to eq('') - expect(mutation.old_value).to eq('display:none;') -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" >}} -const {Builder, until} = require('selenium-webdriver'); -const assert = require("assert"); - -(async function example() { - try { - let driver = await new Builder() - .forBrowser('chrome') - .build(); - - const cdpConnection = await driver.createCDPConnection('page'); - await driver.logMutationEvents(cdpConnection, event => { - assert.deepStrictEqual(event['attribute_name'], 'style'); - assert.deepStrictEqual(event['current_value'], ""); - assert.deepStrictEqual(event['old_value'], "display:none;"); - }); - - await driver.get('dynamic.html'); - await driver.findElement({id: 'reveal'}).click(); - let revealed = driver.findElement({id: 'revealed'}); - await driver.wait(until.elementIsVisible(revealed), 5000); - await driver.quit(); - }catch (e){ - console.log(e) - } -}()) - {{< /tab >}} - {{< tab header="Kotlin" text=true >}} -{{< badge-code >}} - {{< /tab >}} -{{< /tabpane >}} - -## Listen to `console.log` events - -Listen to the `console.log` events and register callbacks to process the event. - -{{< tabpane langEqualsHeader=true >}} -{{< tab header="Java" >}} -ChromeDriver driver = new ChromeDriver(); -DevTools devTools = driver.getDevTools(); -devTools.createSession(); -devTools.send(Log.enable()); -devTools.addListener(Log.entryAdded(), - logEntry -> { - System.out.println("log: "+logEntry.getText()); - System.out.println("level: "+logEntry.getLevel()); - }); -driver.get("http://the-internet.herokuapp.com/broken_images"); -// Check the terminal output for the browser console messages. -driver.quit(); -{{< /tab >}} -{{< tab header="Python" >}} -import trio -from selenium import webdriver -from selenium.webdriver.common.log import Log - -async def printConsoleLogs(): - chrome_options = webdriver.ChromeOptions() - driver = webdriver.Chrome() - driver.get("http://www.google.com") - - async with driver.bidi_connection() as session: - log = Log(driver, session) - from selenium.webdriver.common.bidi.console import Console - async with log.add_listener(Console.ALL) as messages: - driver.execute_script("console.log('I love cheese')") - print(messages["message"]) - - driver.quit() - -trio.run(printConsoleLogs) -{{< /tab >}} -{{< tab header="CSharp" >}} -using IJavaScriptEngine monitor = new JavaScriptEngine(driver); -List consoleMessages = new List(); -monitor.JavaScriptConsoleApiCalled += (sender, e) => -{ - Console.WriteLine("Log: {0}", e.MessageContent); -}; -await monitor.StartEventMonitoring(); -{{< /tab >}} -{{< tab header="Ruby" >}} -require 'selenium-webdriver' - -driver = Selenium::WebDriver.for :chrome -begin - driver.get 'http://www.google.com' - logs = [] - driver.on_log_event(:console) do |event| - logs.push(event) - puts logs.length - end - - driver.execute_script('console.log("here")') - -ensure - driver.quit -end -{{< /tab >}} -{{< tab header="JavaScript" >}} -const {Builder} = require('selenium-webdriver'); -(async () => { - try { - let driver = new Builder() - .forBrowser('chrome') - .build(); - - const cdpConnection = await driver.createCDPConnection('page'); - await driver.onLogEvent(cdpConnection, function (event) { - console.log(event['args'][0]['value']); - }); - await driver.executeScript('console.log("here")'); - await driver.quit(); - }catch (e){ - console.log(e); - } -})() -{{< /tab >}} -{{< tab header="Kotlin" >}} -fun kotlinConsoleLogExample() { - val driver = ChromeDriver() - val devTools = driver.devTools - devTools.createSession() - - val logConsole = { c: ConsoleEvent -> print("Console log message is: " + c.messages)} - devTools.domains.events().addConsoleListener(logConsole) - - driver.get("https://www.google.com") - - val executor = driver as JavascriptExecutor - executor.executeScript("console.log('Hello World')") - - val input = driver.findElement(By.name("q")) - input.sendKeys("Selenium 4") - input.sendKeys(Keys.RETURN) - driver.quit() -} -{{< /tab >}} -{{< /tabpane >}} - -## Listen to JS Exceptions - -Listen to the JS Exceptions -and register callbacks to process the exception details. - -{{< tabpane langEqualsHeader=true >}} -{{< tab header="Java" >}} -import org.openqa.selenium.*; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.devtools.DevTools; - -public void jsExceptionsExample() { - ChromeDriver driver = new ChromeDriver(); - DevTools devTools = driver.getDevTools(); - devTools.createSession(); - - List jsExceptionsList = new ArrayList<>(); - Consumer addEntry = jsExceptionsList::add; - devTools.getDomains().events().addJavascriptExceptionListener(addEntry); - - driver.get(""); - - WebElement link2click = driver.findElement(By.linkText("")); - ((JavascriptExecutor) driver).executeScript("arguments[0].setAttribute(arguments[1], arguments[2]);", - link2click, "onclick", "throw new Error('Hello, world!')"); - link2click.click(); - - for (JavascriptException jsException : jsExceptionsList) { - System.out.println("JS exception message: " + jsException.getMessage()); - System.out.println("JS exception system information: " + jsException.getSystemInformation()); - jsException.printStackTrace(); - } -} -{{< /tab >}} -{{< tab header="Python" >}} -async def catchJSException(): - chrome_options = webdriver.ChromeOptions() - driver = webdriver.Chrome() - - async with driver.bidi_connection() as session: - driver.get("") - log = Log(driver, session) - async with log.add_js_error_listener() as messages: - # Operation on the website that throws an JS error - print(messages) - - driver.quit() -{{< /tab >}} -{{< tab header="CSharp" >}} -List exceptionMessages = new List(); -using IJavaScriptEngine monitor = new JavaScriptEngine(driver); -monitor.JavaScriptExceptionThrown += (sender, e) => -{ - exceptionMessages.Add(e.Message); -}; - -await monitor.StartEventMonitoring(); - -driver.Navigate.GoToUrl(""); - -IWebElement link2click = driver.FindElement(By.LinkText("")); -((IJavaScriptExecutor) driver).ExecuteScript("arguments[0].setAttribute(arguments[1], arguments[2]);", - link2click, "onclick", "throw new Error('Hello, world!')"); -link2click.Click(); - -foreach (string message in exceptionMessages) -{ - Console.WriteLine("JS exception message: {0}", message); -} -{{< /tab >}} -{{< tab header="Ruby" >}} -require 'selenium-webdriver' - -driver = Selenium::WebDriver.for :chrome -begin - driver.get '' - exceptions = [] - driver.on_log_event(:exception) do |event| - exceptions.push(event) - puts exceptions.length - end - - #Actions causing JS exceptions - -ensure - driver.quit -end -{{< /tab >}} -{{< tab header="JavaScript" >}} -const {Builder, By} = require('selenium-webdriver'); -(async () => { - try { - let driver = new Builder() - .forBrowser('chrome') - .build(); - - const cdpConnection = await driver.createCDPConnection('page') - await driver.onLogException(cdpConnection, function (event) { - console.log(event['exceptionDetails']); - }) - await driver.get('https://the-internet.herokuapp.com'); - const link = await driver.findElement(By.linkText('Checkboxes')); - await driver.executeScript("arguments[0].setAttribute(arguments[1], arguments[2]);", link, "onclick","throw new Error('Hello, world!')"); - await link.click(); - await driver.quit(); - }catch (e){ - console.log(e); - } -})() -{{< /tab >}} -{{< tab header="Kotlin" >}} -fun kotlinJsErrorListener() { - val driver = ChromeDriver() - val devTools = driver.devTools - devTools.createSession() - - val logJsError = { j: JavascriptException -> print("Javascript error: '" + j.localizedMessage + "'.") } - devTools.domains.events().addJavascriptExceptionListener(logJsError) - - driver.get("https://www.google.com") - - val link2click = driver.findElement(By.name("q")) - (driver as JavascriptExecutor).executeScript( - "arguments[0].setAttribute(arguments[1], arguments[2]);", - link2click, "onclick", "throw new Error('Hello, world!')" - ) - link2click.click() - - driver.quit() -} -{{< /tab >}} -{{< /tabpane >}} - -## Network Interception - -If you want to capture network events coming into the browser and you want manipulate them you are able to do -it with the following examples. - -### Intercept Responses - -{{< tabpane langEqualsHeader=true >}} -{{< tab header="Java" >}} -{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/BidiApiTest.java#L59-L66" >}} -{{< /tab >}} -{{< tab header="Python" >}} -Currently unavailable in python due the inability to mix certain async and sync commands -{{< /tab >}} -{{< tab header="CSharp" text=true >}} -{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/BidiApiTest.cs#L33-L48" >}} -{{< /tab >}} -{{< tab header="Ruby" >}} -require 'selenium-webdriver' - -driver = Selenium::WebDriver.for :chrome -driver.intercept do |request, &continue| - uri = URI(request.url) - if uri.path.end_with?('one.js') - uri.path = '/devtools_request_interception_test/two.js' - request.url = uri.to_s - end - continue.call(request) -end -driver.navigate.to url_for('devToolsRequestInterceptionTest.html') -driver.find_element(tag_name: 'button').click -expect(driver.find_element(id: 'result').text).to eq('two') -{{< /tab >}} - -{{< tab header="JavaScript" >}} -const connection = await driver.createCDPConnection('page') -let url = fileServer.whereIs("/cheese") -let httpResponse = new HttpResponse(url) -httpResponse.addHeaders("Content-Type", "UTF-8") -httpResponse.body = "sausages" -await driver.onIntercept(connection, httpResponse, async function () { - let body = await driver.getPageSource() - assert.strictEqual(body.includes("sausages"), true, `Body contains: ${body}`) -}) -driver.get(url) -{{< /tab >}} -{{< tab header="Kotlin" >}} -val driver = ChromeDriver() -val interceptor = new NetworkInterceptor( - driver, - Route.matching(req -> true) - .to(() -> req -> new HttpResponse() - .setStatus(200) - .addHeader("Content-Type", MediaType.HTML_UTF_8.toString()) - .setContent(utf8String("Creamy, delicious cheese!")))) - - driver.get(appServer.whereIs("/cheese")) - - String source = driver.getPageSource() -{{< /tab >}} -{{< /tabpane >}} - -### Intercept Requests - -{{< tabpane text=true langEqualsHeader=true >}} -{{< tab header="Java" >}} -{{< badge-code >}} -{{< /tab >}} -{{< tab header="Python" >}} -{{< badge-code >}} -{{< /tab >}} -{{< tab header="CSharp" >}} -{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/BidiApiTest.cs#L56-L71" >}} -{{< /tab >}} -{{< tab header="Ruby" >}} -{{< badge-code >}} -{{< /tab >}} -{{< tab header="JavaScript" >}} -{{< badge-code >}} -{{< /tab >}} -{{< tab header="Kotlin" >}} -{{< badge-code >}} -{{< /tab >}} -{{< /tabpane >}} diff --git a/website_and_docs/content/documentation/webdriver/bidirectional/bidi_api.pt-br.md b/website_and_docs/content/documentation/webdriver/bidirectional/bidi_api.pt-br.md deleted file mode 100644 index f1662060f143..000000000000 --- a/website_and_docs/content/documentation/webdriver/bidirectional/bidi_api.pt-br.md +++ /dev/null @@ -1,490 +0,0 @@ ---- -title: "API BiDirecional (CDP implementation)" -linkTitle: "BiDi API (CDP implementation)" -weight: 12 ---- - -A seguinte lista de APIs crescerá à medida que o projeto Selenium se prepara -para suportar casos de uso do mundo real. Se houver funcionalidades adicionais que você gostaria de ver, por favor, levante uma [solicitação de recurso](https://github.com/SeleniumHQ/selenium/issues/new?assignees=&labels=&template=feature.md). - -## Registrar autenticação básica - -Alguns aplicativos fazem o uso da autenticação do navegador para proteger suas páginas. Com o Selenium, você pode automatizar a entrada de credenciais básicas de autenticação sempre que for necessário. - -{{< tabpane langEqualsHeader=true >}} -{{< tab header="Java" >}} -{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/BidiApiTest.java/#L29-L32" >}} -{{< /tab >}} -{{< tab header="Python" text=true >}} -{{< badge-code >}} -{{< /tab >}} -{{< tab header="CSharp" text=true >}} -{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/BidiApiTest.cs#L13-L24" >}} -{{< /tab >}} -{{< tab header="Ruby" >}} -require 'selenium-webdriver' - -driver = Selenium::WebDriver.for :chrome - -begin - driver.devtools.new - driver.register(username: 'username', password: 'password') - driver.get '' -ensure - driver.quit -end -{{< /tab >}} -{{< tab header="JavaScript" >}} -const {Builder} = require('selenium-webdriver'); - -(async function example() { - try { - let driver = await new Builder() - .forBrowser('chrome') - .build(); - - const pageCdpConnection = await driver.createCDPConnection('page'); - await driver.register('username', 'password', pageCdpConnection); - await driver.get('https://the-internet.herokuapp.com/basic_auth'); - await driver.quit(); - }catch (e){ - console.log(e) - } -}()) -{{< /tab >}} -{{< tab header="Kotlin" >}} -val uriPredicate = Predicate { uri: URI -> - uri.host.contains("your-domain.com") - } -(driver as HasAuthentication).register(uriPredicate, UsernameAndPassword.of("admin", "password")) -driver.get("https://your-domain.com/login") -{{< /tab >}} -{{< /tabpane >}} - -## Mutation Observation - -Mutation Observation(Observação de Mutação) é a capacidade de capturar eventos via WebDriver BiDi quando há mutações DOM em um elemento específico no DOM. - -{{< tabpane langEqualsHeader=true >}} -{{< tab header="Java" >}} -{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/BidiApiTest.java/#L39-L50" >}} -{{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -from selenium.webdriver.common.by import By -from selenium.webdriver.support.wait import WebDriverWait - -driver = webdriver.Chrome() -async with driver.log.mutation_events() as event: - pages.load("dynamic.html") - driver.find_element(By.ID, "reveal").click() - WebDriverWait(driver, 5)\ - .until(EC.visibility_of(driver.find_element(By.ID, "revealed"))) - -assert event["attribute_name"] == "style" -assert event["current_value"] == "" -assert event["old_value"] == "display:none;" - - {{< /tab >}} - {{< tab header="CSharp" >}} -List attributeValueChanges = new List(); -DefaultWait> wait = new DefaultWait>(attributeValueChanges); -wait.Timeout = TimeSpan.FromSeconds(3); - -using IJavaScriptEngine monitor = new JavaScriptEngine(driver); -monitor.DomMutated += (sender, e) => -{ - attributeValueChanges.Add(e.AttributeData); -}; -await monitor.StartEventMonitoring(); - -driver.Navigate().GoToUrl("http://www.google.com"); -IWebElement span = driver.FindElement(By.CssSelector("span")); - -await monitor.EnableDomMutationMonitoring(); -((IJavaScriptExecutor) driver).ExecuteScript("arguments[0].setAttribute('cheese', 'gouda');", span); - -wait.Until((list) => list.Count > 0); -Console.WriteLine("Found {0} DOM mutation events", attributeValueChanges.Count); -foreach(var record in attributeValueChanges) -{ - Console.WriteLine("Attribute name: {0}", record.AttributeName); - Console.WriteLine("Attribute value: {0}", record.AttributeValue); -} - -await monitor.DisableDomMutationMonitoring(); - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :firefox -begin - driver.on_log_event(:mutation) { |mutation| mutations.push(mutation) } - driver.navigate.to url_for('dynamic.html') - driver.find_element(id: 'reveal').click - wait.until { mutations.any? } - mutation = mutations.first - expect(mutation.element).to eq(driver.find_element(id: 'revealed')) - expect(mutation.attribute_name).to eq('style') - expect(mutation.current_value).to eq('') - expect(mutation.old_value).to eq('display:none;') -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" >}} -const {Builder, until} = require('selenium-webdriver'); -const assert = require("assert"); - -(async function example() { - try { - let driver = await new Builder() - .forBrowser('chrome') - .build(); - - const cdpConnection = await driver.createCDPConnection('page'); - await driver.logMutationEvents(cdpConnection, event => { - assert.deepStrictEqual(event['attribute_name'], 'style'); - assert.deepStrictEqual(event['current_value'], ""); - assert.deepStrictEqual(event['old_value'], "display:none;"); - }); - - await driver.get('dynamic.html'); - await driver.findElement({id: 'reveal'}).click(); - let revealed = driver.findElement({id: 'revealed'}); - await driver.wait(until.elementIsVisible(revealed), 5000); - await driver.quit(); - }catch (e){ - console.log(e) - } -}()) - {{< /tab >}} - {{< tab header="Kotlin" text=true >}} -{{< badge-code >}} - {{< /tab >}} -{{< /tabpane >}} - -## Vigie eventos `console.log` -Vigie os eventos `console.log` e registre os callbacks(retornos de chamada) para processar o evento. - -{{< tabpane langEqualsHeader=true >}} -{{< tab header="Java" >}} -ChromeDriver driver = new ChromeDriver(); -DevTools devTools = driver.getDevTools(); -devTools.createSession(); -devTools.send(Log.enable()); -devTools.addListener(Log.entryAdded(), - logEntry -> { - System.out.println("log: "+logEntry.getText()); - System.out.println("level: "+logEntry.getLevel()); - }); -driver.get("http://the-internet.herokuapp.com/broken_images"); -// Check the terminal output for the browser console messages. -driver.quit(); -{{< /tab >}} -{{< tab header="Python" >}} -import trio -from selenium import webdriver -from selenium.webdriver.common.log import Log - -async def printConsoleLogs(): - chrome_options = webdriver.ChromeOptions() - driver = webdriver.Chrome() - driver.get("http://www.google.com") - - async with driver.bidi_connection() as session: - log = Log(driver, session) - from selenium.webdriver.common.bidi.console import Console - async with log.add_listener(Console.ALL) as messages: - driver.execute_script("console.log('I love cheese')") - print(messages["message"]) - - driver.quit() - -trio.run(printConsoleLogs) -{{< /tab >}} -{{< tab header="CSharp" >}} -using IJavaScriptEngine monitor = new JavaScriptEngine(driver); -List consoleMessages = new List(); -monitor.JavaScriptConsoleApiCalled += (sender, e) => -{ - Console.WriteLine("Log: {0}", e.MessageContent); -}; -await monitor.StartEventMonitoring(); -{{< /tab >}} -{{< tab header="Ruby" >}} -require 'selenium-webdriver' - -driver = Selenium::WebDriver.for :chrome -begin - driver.get 'http://www.google.com' - logs = [] - driver.on_log_event(:console) do |event| - logs.push(event) - puts logs.length - end - - driver.execute_script('console.log("here")') - -ensure - driver.quit -end -{{< /tab >}} -{{< tab header="JavaScript" >}} -const {Builder} = require('selenium-webdriver'); -(async () => { - try { - let driver = new Builder() - .forBrowser('chrome') - .build(); - - const cdpConnection = await driver.createCDPConnection('page'); - await driver.onLogEvent(cdpConnection, function (event) { - console.log(event['args'][0]['value']); - }); - await driver.executeScript('console.log("here")'); - await driver.quit(); - }catch (e){ - console.log(e); - } -})() -{{< /tab >}} -{{< tab header="Kotlin" >}} -fun kotlinConsoleLogExample() { - val driver = ChromeDriver() - val devTools = driver.devTools - devTools.createSession() - - val logConsole = { c: ConsoleEvent -> print("Console log message is: " + c.messages)} - devTools.domains.events().addConsoleListener(logConsole) - - driver.get("https://www.google.com") - - val executor = driver as JavascriptExecutor - executor.executeScript("console.log('Hello World')") - - val input = driver.findElement(By.name("q")) - input.sendKeys("Selenium 4") - input.sendKeys(Keys.RETURN) - driver.quit() -} -{{< /tab >}} -{{< /tabpane >}} - -## Vigie exceções JS - -Vigie as exceções JS -e registre callbacks(retornos de chamada) para processar os detalhes da exceção. - -{{< tabpane langEqualsHeader=true >}} -{{< tab header="Java" >}} -import org.openqa.selenium.*; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.devtools.DevTools; - -public void jsExceptionsExample() { - ChromeDriver driver = new ChromeDriver(); - DevTools devTools = driver.getDevTools(); - devTools.createSession(); - - List jsExceptionsList = new ArrayList<>(); - Consumer addEntry = jsExceptionsList::add; - devTools.getDomains().events().addJavascriptExceptionListener(addEntry); - - driver.get(""); - - WebElement link2click = driver.findElement(By.linkText("")); - ((JavascriptExecutor) driver).executeScript("arguments[0].setAttribute(arguments[1], arguments[2]);", - link2click, "onclick", "throw new Error('Hello, world!')"); - link2click.click(); - - for (JavascriptException jsException : jsExceptionsList) { - System.out.println("JS exception message: " + jsException.getMessage()); - System.out.println("JS exception system information: " + jsException.getSystemInformation()); - jsException.printStackTrace(); - } -} -{{< /tab >}} -{{< tab header="Python" >}} -async def catchJSException(): - chrome_options = webdriver.ChromeOptions() - driver = webdriver.Chrome() - - async with driver.bidi_connection() as session: - driver.get("") - log = Log(driver, session) - async with log.add_js_error_listener() as messages: - # Operation on the website that throws an JS error - print(messages) - - driver.quit() -{{< /tab >}} -{{< tab header="CSharp" >}} -List exceptionMessages = new List(); -using IJavaScriptEngine monitor = new JavaScriptEngine(driver); -monitor.JavaScriptExceptionThrown += (sender, e) => -{ - exceptionMessages.Add(e.Message); -}; - -await monitor.StartEventMonitoring(); - -driver.Navigate.GoToUrl(""); - -IWebElement link2click = driver.FindElement(By.LinkText("")); -((IJavaScriptExecutor) driver).ExecuteScript("arguments[0].setAttribute(arguments[1], arguments[2]);", - link2click, "onclick", "throw new Error('Hello, world!')"); -link2click.Click(); - -foreach (string message in exceptionMessages) -{ - Console.WriteLine("JS exception message: {0}", message); -} -{{< /tab >}} -{{< tab header="Ruby" >}} -require 'selenium-webdriver' - -driver = Selenium::WebDriver.for :chrome -begin - driver.get '' - exceptions = [] - driver.on_log_event(:exception) do |event| - exceptions.push(event) - puts exceptions.length - end - - #Ações que causam exceções JS - -ensure - driver.quit -end -{{< /tab >}} -{{< tab header="JavaScript" >}} -const {Builder, By} = require('selenium-webdriver'); -(async () => { - try { - let driver = new Builder() - .forBrowser('chrome') - .build(); - - const cdpConnection = await driver.createCDPConnection('page') - await driver.onLogException(cdpConnection, function (event) { - console.log(event['exceptionDetails']); - }) - await driver.get('https://the-internet.herokuapp.com'); - const link = await driver.findElement(By.linkText('Checkboxes')); - await driver.executeScript("arguments[0].setAttribute(arguments[1], arguments[2]);", link, "onclick","throw new Error('Hello, world!')"); - await link.click(); - await driver.quit(); - }catch (e){ - console.log(e); - } -})() -{{< /tab >}} -{{< tab header="Kotlin" >}} -fun kotlinJsErrorListener() { - val driver = ChromeDriver() - val devTools = driver.devTools - devTools.createSession() - - val logJsError = { j: JavascriptException -> print("Javascript error: '" + j.localizedMessage + "'.") } - devTools.domains.events().addJavascriptExceptionListener(logJsError) - - driver.get("https://www.google.com") - - val link2click = driver.findElement(By.name("q")) - (driver as JavascriptExecutor).executeScript( - "arguments[0].setAttribute(arguments[1], arguments[2]);", - link2click, "onclick", "throw new Error('Hello, world!')" - ) - link2click.click() - - driver.quit() -} -{{< /tab >}} -{{< /tabpane >}} - -## Interceptação de Rede - -Se você quer capturar eventos de rede que chegam ao navegador e deseja manipulá-los, você pode fazer -com os exemplos a seguir. - -### Intercept Responses - -{{< tabpane langEqualsHeader=true >}} -{{< tab header="Java" >}} -{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/BidiApiTest.java#L59-L66" >}} -{{< /tab >}} -{{< tab header="Python" >}} -Currently unavailable in python due the inability to mix certain async and sync commands -{{< /tab >}} -{{< tab header="CSharp" text=true >}} -{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/BidiApiTest.cs#L33-L48" >}} -{{< /tab >}} -{{< tab header="Ruby" >}} -require 'selenium-webdriver' - -driver = Selenium::WebDriver.for :chrome -driver.intercept do |request, &continue| - uri = URI(request.url) - if uri.path.end_with?('one.js') - uri.path = '/devtools_request_interception_test/two.js' - request.url = uri.to_s - end - continue.call(request) -end -driver.navigate.to url_for('devToolsRequestInterceptionTest.html') -driver.find_element(tag_name: 'button').click -expect(driver.find_element(id: 'result').text).to eq('two') -{{< /tab >}} - -{{< tab header="JavaScript" >}} -const connection = await driver.createCDPConnection('page') -let url = fileServer.whereIs("/cheese") -let httpResponse = new HttpResponse(url) -httpResponse.addHeaders("Content-Type", "UTF-8") -httpResponse.body = "sausages" -await driver.onIntercept(connection, httpResponse, async function () { - let body = await driver.getPageSource() - assert.strictEqual(body.includes("sausages"), true, `Body contains: ${body}`) -}) -driver.get(url) -{{< /tab >}} -{{< tab header="Kotlin" >}} -val driver = ChromeDriver() -val interceptor = new NetworkInterceptor( - driver, - Route.matching(req -> true) - .to(() -> req -> new HttpResponse() - .setStatus(200) - .addHeader("Content-Type", MediaType.HTML_UTF_8.toString()) - .setContent(utf8String("Creamy, delicious cheese!")))) - - driver.get(appServer.whereIs("/cheese")) - - String source = driver.getPageSource() -{{< /tab >}} -{{< /tabpane >}} - - -### Intercept Requests - -{{< tabpane text=true langEqualsHeader=true >}} -{{< tab header="Java" >}} -{{< badge-code >}} -{{< /tab >}} -{{< tab header="Python" >}} -{{< badge-code >}} -{{< /tab >}} -{{< tab header="CSharp" >}} -{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/BidiApiTest.cs#L56-L71" >}} -{{< /tab >}} -{{< tab header="Ruby" >}} -{{< badge-code >}} -{{< /tab >}} -{{< tab header="JavaScript" >}} -{{< badge-code >}} -{{< /tab >}} -{{< tab header="Kotlin" >}} -{{< badge-code >}} -{{< /tab >}} -{{< /tabpane >}} diff --git a/website_and_docs/content/documentation/webdriver/bidirectional/bidi_api.zh-cn.md b/website_and_docs/content/documentation/webdriver/bidirectional/bidi_api.zh-cn.md deleted file mode 100644 index 718fac97c124..000000000000 --- a/website_and_docs/content/documentation/webdriver/bidirectional/bidi_api.zh-cn.md +++ /dev/null @@ -1,507 +0,0 @@ ---- -title: "BiDirectional API (CDP implementation)" -linkTitle: "BiDi API (CDP implementation)" -weight: 12 - ---- - -{{% pageinfo color="warning" %}} -

- - Page being translated from - English to Chinese. Do you speak Chinese? Help us to translate - it by sending us pull requests! -

-{{% /pageinfo %}} - - -The following list of APIs will be growing as the Selenium -project works through supporting real world use cases. If there -is additional functionality you'd like to see, please raise a -[feature request](https://github.com/SeleniumHQ/selenium/issues/new?assignees=&labels=&template=feature.md). - -## Register Basic Auth - -Some applications make use of browser authentication to secure pages. -With Selenium, you can automate the input of basic auth credentials whenever they arise. - -{{< tabpane langEqualsHeader=true >}} -{{< tab header="Java" >}} -{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/BidiApiTest.java/#L29-L32" >}} -{{< /tab >}} -{{< tab header="Python" text=true >}} -{{< badge-code >}} -{{< /tab >}} -{{< tab header="CSharp" text=true >}} -{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/BidiApiTest.cs#L13-L24" >}} -{{< /tab >}} -{{< tab header="Ruby" >}} -require 'selenium-webdriver' - -driver = Selenium::WebDriver.for :chrome - -begin - driver.devtools.new - driver.register(username: 'username', password: 'password') - driver.get '' -ensure - driver.quit -end -{{< /tab >}} -{{< tab header="JavaScript" >}} -const {Builder} = require('selenium-webdriver'); - -(async function example() { - try { - let driver = await new Builder() - .forBrowser('chrome') - .build(); - - const pageCdpConnection = await driver.createCDPConnection('page'); - await driver.register('username', 'password', pageCdpConnection); - await driver.get('https://the-internet.herokuapp.com/basic_auth'); - await driver.quit(); - }catch (e){ - console.log(e) - } -}()) -{{< /tab >}} -{{< tab header="Kotlin" >}} -val uriPredicate = Predicate { uri: URI -> - uri.host.contains("your-domain.com") - } -(driver as HasAuthentication).register(uriPredicate, UsernameAndPassword.of("admin", "password")) -driver.get("https://your-domain.com/login") -{{< /tab >}} -{{< /tabpane >}} - -## Mutation Observation - -Mutation Observation is the ability to capture events via -WebDriver BiDi when there are DOM mutations on a specific -element in the DOM. - -{{< tabpane langEqualsHeader=true >}} -{{< tab header="Java" >}} -{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/BidiApiTest.java/#L39-L50" >}} -{{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -from selenium.webdriver.common.by import By -from selenium.webdriver.support.wait import WebDriverWait - -driver = webdriver.Chrome() -async with driver.log.mutation_events() as event: - pages.load("dynamic.html") - driver.find_element(By.ID, "reveal").click() - WebDriverWait(driver, 5)\ - .until(EC.visibility_of(driver.find_element(By.ID, "revealed"))) - -assert event["attribute_name"] == "style" -assert event["current_value"] == "" -assert event["old_value"] == "display:none;" - - {{< /tab >}} - {{< tab header="CSharp" >}} -List attributeValueChanges = new List(); -DefaultWait> wait = new DefaultWait>(attributeValueChanges); -wait.Timeout = TimeSpan.FromSeconds(3); - -using IJavaScriptEngine monitor = new JavaScriptEngine(driver); -monitor.DomMutated += (sender, e) => -{ - attributeValueChanges.Add(e.AttributeData); -}; -await monitor.StartEventMonitoring(); - -driver.Navigate().GoToUrl("http://www.google.com"); -IWebElement span = driver.FindElement(By.CssSelector("span")); - -await monitor.EnableDomMutationMonitoring(); -((IJavaScriptExecutor) driver).ExecuteScript("arguments[0].setAttribute('cheese', 'gouda');", span); - -wait.Until((list) => list.Count > 0); -Console.WriteLine("Found {0} DOM mutation events", attributeValueChanges.Count); -foreach(var record in attributeValueChanges) -{ - Console.WriteLine("Attribute name: {0}", record.AttributeName); - Console.WriteLine("Attribute value: {0}", record.AttributeValue); -} - -await monitor.DisableDomMutationMonitoring(); - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' -driver = Selenium::WebDriver.for :firefox -begin - driver.on_log_event(:mutation) { |mutation| mutations.push(mutation) } - driver.navigate.to url_for('dynamic.html') - driver.find_element(id: 'reveal').click - wait.until { mutations.any? } - mutation = mutations.first - expect(mutation.element).to eq(driver.find_element(id: 'revealed')) - expect(mutation.attribute_name).to eq('style') - expect(mutation.current_value).to eq('') - expect(mutation.old_value).to eq('display:none;') -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" >}} -const {Builder, until} = require('selenium-webdriver'); -const assert = require("assert"); - -(async function example() { - try { - let driver = await new Builder() - .forBrowser('chrome') - .build(); - - const cdpConnection = await driver.createCDPConnection('page'); - await driver.logMutationEvents(cdpConnection, event => { - assert.deepStrictEqual(event['attribute_name'], 'style'); - assert.deepStrictEqual(event['current_value'], ""); - assert.deepStrictEqual(event['old_value'], "display:none;"); - }); - - await driver.get('dynamic.html'); - await driver.findElement({id: 'reveal'}).click(); - let revealed = driver.findElement({id: 'revealed'}); - await driver.wait(until.elementIsVisible(revealed), 5000); - await driver.quit(); - }catch (e){ - console.log(e) - } -}()) - {{< /tab >}} - {{< tab header="Kotlin" text=true >}} -{{< badge-code >}} - {{< /tab >}} -{{< /tabpane >}} - -## Listen to `console.log` events - -Listen to the `console.log` events and register callbacks to process the event. - -{{< tabpane langEqualsHeader=true >}} -{{< tab header="Java" >}} -ChromeDriver driver = new ChromeDriver(); -DevTools devTools = driver.getDevTools(); -devTools.createSession(); -devTools.send(Log.enable()); -devTools.addListener(Log.entryAdded(), - logEntry -> { - System.out.println("log: "+logEntry.getText()); - System.out.println("level: "+logEntry.getLevel()); - }); -driver.get("http://the-internet.herokuapp.com/broken_images"); -// Check the terminal output for the browser console messages. -driver.quit(); -{{< /tab >}} -{{< tab header="Python" >}} -import trio -from selenium import webdriver -from selenium.webdriver.common.log import Log - -async def printConsoleLogs(): - chrome_options = webdriver.ChromeOptions() - driver = webdriver.Chrome() - driver.get("http://www.google.com") - - async with driver.bidi_connection() as session: - log = Log(driver, session) - from selenium.webdriver.common.bidi.console import Console - async with log.add_listener(Console.ALL) as messages: - driver.execute_script("console.log('I love cheese')") - print(messages["message"]) - - driver.quit() - -trio.run(printConsoleLogs) -{{< /tab >}} -{{< tab header="CSharp" >}} -using IJavaScriptEngine monitor = new JavaScriptEngine(driver); -List consoleMessages = new List(); -monitor.JavaScriptConsoleApiCalled += (sender, e) => -{ - Console.WriteLine("Log: {0}", e.MessageContent); -}; -await monitor.StartEventMonitoring(); -{{< /tab >}} -{{< tab header="Ruby" >}} -require 'selenium-webdriver' - -driver = Selenium::WebDriver.for :chrome -begin - driver.get 'http://www.google.com' - logs = [] - driver.on_log_event(:console) do |event| - logs.push(event) - puts logs.length - end - - driver.execute_script('console.log("here")') - -ensure - driver.quit -end -{{< /tab >}} -{{< tab header="JavaScript" >}} -const {Builder} = require('selenium-webdriver'); -(async () => { - try { - let driver = new Builder() - .forBrowser('chrome') - .build(); - - const cdpConnection = await driver.createCDPConnection('page'); - await driver.onLogEvent(cdpConnection, function (event) { - console.log(event['args'][0]['value']); - }); - await driver.executeScript('console.log("here")'); - await driver.quit(); - }catch (e){ - console.log(e); - } -})() -{{< /tab >}} -{{< tab header="Kotlin" >}} -fun kotlinConsoleLogExample() { - val driver = ChromeDriver() - val devTools = driver.devTools - devTools.createSession() - - val logConsole = { c: ConsoleEvent -> print("Console log message is: " + c.messages)} - devTools.domains.events().addConsoleListener(logConsole) - - driver.get("https://www.google.com") - - val executor = driver as JavascriptExecutor - executor.executeScript("console.log('Hello World')") - - val input = driver.findElement(By.name("q")) - input.sendKeys("Selenium 4") - input.sendKeys(Keys.RETURN) - driver.quit() -} -{{< /tab >}} -{{< /tabpane >}} - -## Listen to JS Exceptions - -Listen to the JS Exceptions -and register callbacks to process the exception details. - -{{< tabpane langEqualsHeader=true >}} -{{< tab header="Java" >}} -import org.openqa.selenium.*; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.devtools.DevTools; - -public void jsExceptionsExample() { - ChromeDriver driver = new ChromeDriver(); - DevTools devTools = driver.getDevTools(); - devTools.createSession(); - - List jsExceptionsList = new ArrayList<>(); - Consumer addEntry = jsExceptionsList::add; - devTools.getDomains().events().addJavascriptExceptionListener(addEntry); - - driver.get(""); - - WebElement link2click = driver.findElement(By.linkText("")); - ((JavascriptExecutor) driver).executeScript("arguments[0].setAttribute(arguments[1], arguments[2]);", - link2click, "onclick", "throw new Error('Hello, world!')"); - link2click.click(); - - for (JavascriptException jsException : jsExceptionsList) { - System.out.println("JS exception message: " + jsException.getMessage()); - System.out.println("JS exception system information: " + jsException.getSystemInformation()); - jsException.printStackTrace(); - } -} -{{< /tab >}} -{{< tab header="Python" >}} -async def catchJSException(): - chrome_options = webdriver.ChromeOptions() - driver = webdriver.Chrome() - - async with driver.bidi_connection() as session: - driver.get("") - log = Log(driver, session) - async with log.add_js_error_listener() as messages: - # Operation on the website that throws an JS error - print(messages) - - driver.quit() -{{< /tab >}} -{{< tab header="CSharp" >}} -List exceptionMessages = new List(); -using IJavaScriptEngine monitor = new JavaScriptEngine(driver); -monitor.JavaScriptExceptionThrown += (sender, e) => -{ - exceptionMessages.Add(e.Message); -}; - -await monitor.StartEventMonitoring(); - -driver.Navigate.GoToUrl(""); - -IWebElement link2click = driver.FindElement(By.LinkText("")); -((IJavaScriptExecutor) driver).ExecuteScript("arguments[0].setAttribute(arguments[1], arguments[2]);", - link2click, "onclick", "throw new Error('Hello, world!')"); -link2click.Click(); - -foreach (string message in exceptionMessages) -{ - Console.WriteLine("JS exception message: {0}", message); -} -{{< /tab >}} -{{< tab header="Ruby" >}} -require 'selenium-webdriver' - -driver = Selenium::WebDriver.for :chrome -begin - driver.get '' - exceptions = [] - driver.on_log_event(:exception) do |event| - exceptions.push(event) - puts exceptions.length - end - - #Actions causing JS exceptions - -ensure - driver.quit -end -{{< /tab >}} -{{< tab header="JavaScript" >}} -const {Builder, By} = require('selenium-webdriver'); -(async () => { - try { - let driver = new Builder() - .forBrowser('chrome') - .build(); - - const cdpConnection = await driver.createCDPConnection('page') - await driver.onLogException(cdpConnection, function (event) { - console.log(event['exceptionDetails']); - }) - await driver.get('https://the-internet.herokuapp.com'); - const link = await driver.findElement(By.linkText('Checkboxes')); - await driver.executeScript("arguments[0].setAttribute(arguments[1], arguments[2]);", link, "onclick","throw new Error('Hello, world!')"); - await link.click(); - await driver.quit(); - }catch (e){ - console.log(e); - } -})() -{{< /tab >}} -{{< tab header="Kotlin" >}} -fun kotlinJsErrorListener() { - val driver = ChromeDriver() - val devTools = driver.devTools - devTools.createSession() - - val logJsError = { j: JavascriptException -> print("Javascript error: '" + j.localizedMessage + "'.") } - devTools.domains.events().addJavascriptExceptionListener(logJsError) - - driver.get("https://www.google.com") - - val link2click = driver.findElement(By.name("q")) - (driver as JavascriptExecutor).executeScript( - "arguments[0].setAttribute(arguments[1], arguments[2]);", - link2click, "onclick", "throw new Error('Hello, world!')" - ) - link2click.click() - - driver.quit() -} -{{< /tab >}} -{{< /tabpane >}} - -## Network Interception - -If you want to capture network events coming into the browser and you want manipulate them you are able to do -it with the following examples. - -### Intercept Responses - -{{< tabpane langEqualsHeader=true >}} -{{< tab header="Java" >}} -{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/BidiApiTest.java#L59-L66" >}} -{{< /tab >}} -{{< tab header="Python" >}} -Currently unavailable in python due the inability to mix certain async and sync commands -{{< /tab >}} -{{< tab header="CSharp" text=true >}} -{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/BidiApiTest.cs#L33-L48" >}} -{{< /tab >}} -{{< tab header="Ruby" >}} -require 'selenium-webdriver' - -driver = Selenium::WebDriver.for :chrome -driver.intercept do |request, &continue| - uri = URI(request.url) - if uri.path.end_with?('one.js') - uri.path = '/devtools_request_interception_test/two.js' - request.url = uri.to_s - end - continue.call(request) -end -driver.navigate.to url_for('devToolsRequestInterceptionTest.html') -driver.find_element(tag_name: 'button').click -expect(driver.find_element(id: 'result').text).to eq('two') -{{< /tab >}} - -{{< tab header="JavaScript" >}} -const connection = await driver.createCDPConnection('page') -let url = fileServer.whereIs("/cheese") -let httpResponse = new HttpResponse(url) -httpResponse.addHeaders("Content-Type", "UTF-8") -httpResponse.body = "sausages" -await driver.onIntercept(connection, httpResponse, async function () { - let body = await driver.getPageSource() - assert.strictEqual(body.includes("sausages"), true, `Body contains: ${body}`) -}) -driver.get(url) -{{< /tab >}} -{{< tab header="Kotlin" >}} -val driver = ChromeDriver() -val interceptor = new NetworkInterceptor( - driver, - Route.matching(req -> true) - .to(() -> req -> new HttpResponse() - .setStatus(200) - .addHeader("Content-Type", MediaType.HTML_UTF_8.toString()) - .setContent(utf8String("Creamy, delicious cheese!")))) - - driver.get(appServer.whereIs("/cheese")) - - String source = driver.getPageSource() -{{< /tab >}} -{{< /tabpane >}} - - -### Intercept Requests - -{{< tabpane text=true langEqualsHeader=true >}} -{{< tab header="Java" >}} -{{< badge-code >}} -{{< /tab >}} -{{< tab header="Python" >}} -{{< badge-code >}} -{{< /tab >}} -{{< tab header="CSharp" >}} -{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/BidiApiTest.cs#L56-L71" >}} -{{< /tab >}} -{{< tab header="Ruby" >}} -{{< badge-code >}} -{{< /tab >}} -{{< tab header="JavaScript" >}} -{{< badge-code >}} -{{< /tab >}} -{{< tab header="Kotlin" >}} -{{< badge-code >}} -{{< /tab >}} -{{< /tabpane >}} diff --git a/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools.en.md b/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools.en.md deleted file mode 100644 index 623e4338c995..000000000000 --- a/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools.en.md +++ /dev/null @@ -1,537 +0,0 @@ ---- -title: "Chrome DevTools" -linkTitle: "Chrome DevTools" -weight: 2 -aliases: [ -"/documentation/en/support_packages/chrome_devtools/", -"/documentation/support_packages/chrome_devtools/" -] ---- - -{{% pageinfo color="warning" %}} -While Selenium 4 provides direct access to the Chrome DevTools Protocol (CDP), it is -highly encouraged that you use the [WebDriver Bidi APIs]({{< ref "bidi_api.md" >}}) instead. -{{% /pageinfo %}} - -Many browsers provide "DevTools" -- a set of tools that are integrated with the browser that -developers can use to debug web apps and explore the performance of their pages. Google Chrome's -DevTools make use of a protocol called the Chrome DevTools Protocol (or "CDP" for short). -As the name suggests, this is not designed for testing, nor to have a stable API, so functionality -is highly dependent on the version of the browser. - -WebDriver Bidi is the next generation of the W3C WebDriver protocol and aims to provide a stable API -implemented by all browsers, but it's not yet complete. Until it is, Selenium provides access to -the CDP for those browsers that implement it (such as Google Chrome, or Microsoft Edge, and -Firefox), allowing you to enhance your tests in interesting ways. Some examples of what you can -do with it are given below. - -## Emulate Geo Location - -Some applications have different features and functionalities across different -locations. Automating such applications is difficult because it is hard to emulate -the geo-locations in the browser using Selenium. But with the help of Devtools, -we can easily emulate them. Below code snippet demonstrates that. - -{{< tabpane langEqualsHeader=true >}} -{{< badge-examples >}} - {{< tab header="Java" >}} -ChromeDriver driver = new ChromeDriver(); -DevTools devTools = driver.getDevTools(); -devTools.createSession(); -devTools.send(Emulation.setGeolocationOverride(Optional.of(52.5043), - Optional.of(13.4501), - Optional.of(1))); -driver.get("https://my-location.org/"); -driver.quit(); - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -from selenium.webdriver.chrome.service import Service - -def geoLocationTest(): - driver = webdriver.Chrome() - Map_coordinates = dict({ - "latitude": 41.8781, - "longitude": -87.6298, - "accuracy": 100 - }) - driver.execute_cdp_cmd("Emulation.setGeolocationOverride", Map_coordinates) - driver.get("") - {{< /tab >}} - {{< tab header="CSharp" >}} -using System.Threading.Tasks; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.DevTools; -// Replace the version to match the Chrome version -using OpenQA.Selenium.DevTools.V87.Emulation; - -namespace dotnet_test { - class Program { - public static void Main(string[] args) { - GeoLocation().GetAwaiter().GetResult(); - } - - public static async Task GeoLocation() { - ChromeDriver driver = new ChromeDriver(); - DevToolsSession devToolsSession = driver.CreateDevToolsSession(); - var geoLocationOverrideCommandSettings = new SetGeolocationOverrideCommandSettings(); - - geoLocationOverrideCommandSettings.Latitude = 51.507351; - geoLocationOverrideCommandSettings.Longitude = -0.127758; - geoLocationOverrideCommandSettings.Accuracy = 1; - - await devToolsSession - .GetVersionSpecificDomains() - .Emulation - .SetGeolocationOverride(geoLocationOverrideCommandSettings); - - driver.Url = ""; - } - } -} - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' - -driver = Selenium::WebDriver.for :chrome - -begin - # Latitude and longitude of Tokyo, Japan - coordinates = { latitude: 35.689487, - longitude: 139.691706, - accuracy: 100 } - driver.execute_cdp('Emulation.setGeolocationOverride', coordinates) - driver.get 'https://www.google.com/search?q=selenium' -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" text=true >}} -{{< gh-codeblock path="/examples/javascript/test/bidirectional/emulateGeoLocation.spec.js">}} - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.devtools.DevTools - -fun main() { - val driver = ChromeDriver() - val coordinates : HashMap = HashMap () - coordinates.put("latitude", 50.2334) - coordinates.put("longitude", 0.2334) - coordinates.put("accuracy", 1) - driver.executeCdpCommand("Emulation.setGeolocationOverride", coordinates) - driver.get("https://www.google.com") -} - {{< /tab >}} -{{< /tabpane >}} - -## Emulate Geo Location with the Remote WebDriver: - -{{< tabpane langEqualsHeader=true >}} -{{< badge-examples >}} - {{< tab header="Java" >}} -ChromeOptions chromeOptions = new ChromeOptions(); -WebDriver driver = new RemoteWebDriver(new URL(""), chromeOptions); -driver = new Augmenter().augment(driver); - -DevTools devTools = ((HasDevTools) driver).getDevTools(); -devTools.createSession(); - -devTools.send(Emulation.setGeolocationOverride(Optional.of(52.5043), - Optional.of(13.4501), - Optional.of(1))); - -driver.get("https://my-location.org/"); -driver.quit(); - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -#Replace the version to match the Chrome version -import selenium.webdriver.common.devtools.v93 as devtools - -async def geoLocationTest(): - chrome_options = webdriver.ChromeOptions() - driver = webdriver.Remote( - command_executor='', - options=chrome_options - ) - - async with driver.bidi_connection() as session: - cdpSession = session.session - await cdpSession.execute(devtools.emulation.set_geolocation_override(latitude=41.8781,longitude=-87.6298,accuracy=100)) - driver.get("https://my-location.org/") - driver.quit() - {{< /tab >}} - {{< tab header="CSharp" >}} -using System.Threading.Tasks; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.DevTools; -// Replace the version to match the Chrome version -using OpenQA.Selenium.DevTools.V87.Emulation; - -namespace dotnet_test { - class Program { - public static void Main(string[] args) { - GeoLocation().GetAwaiter().GetResult(); - } - - public static async Task GeoLocation() { - ChromeOptions chromeOptions = new ChromeOptions(); - RemoteWebDriver driver = new RemoteWebDriver(new Uri(""), chromeOptions); - DevToolsSession devToolsSession = driver.CreateDevToolsSession(); - var geoLocationOverrideCommandSettings = new SetGeolocationOverrideCommandSettings(); - - geoLocationOverrideCommandSettings.Latitude = 51.507351; - geoLocationOverrideCommandSettings.Longitude = -0.127758; - geoLocationOverrideCommandSettings.Accuracy = 1; - - await devToolsSession - .GetVersionSpecificDomains() - .Emulation - .SetGeolocationOverride(geoLocationOverrideCommandSettings); - - driver.Url = "https://my-location.org/"; - } - } -} - {{< /tab >}} - {{< tab header="Ruby" >}} - -driver = Selenium::WebDriver.for( -:remote, -:url => "", -:capabilities => :chrome) - -begin - # Latitude and longitude of Tokyo, Japan - coordinates = { latitude: 35.689487, - longitude: 139.691706, - accuracy: 100 } - devToolsSession = driver.devtools - devToolsSession.send_cmd('Emulation.setGeolocationOverride', coordinates) - driver.get 'https://my-location.org/' - puts res -ensure - driver.quit -end - - {{< /tab >}} - {{< tab header="JavaScript" >}} -const webdriver = require('selenium-webdriver'); -const BROWSER_NAME = webdriver.Browser.CHROME; - -async function getDriver() { - return new webdriver.Builder() - .usingServer('') - .forBrowser(BROWSER_NAME) - .build(); -} - -async function executeCDPCommands () { - let driver = await getDriver(); - - await driver.get(""); - - const cdpConnection = await driver.createCDPConnection('page'); - //Latitude and longitude of Tokyo, Japan - const coordinates = { - latitude: 35.689487, - longitude: 139.691706, - accuracy: 100, - }; - await cdpConnection.execute( - "Emulation.setGeolocationOverride", - coordinates - ); - await driver.quit(); -} - -executeCDPCommands(); - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.WebDriver -import org.openqa.selenium.chrome.ChromeOptions -import org.openqa.selenium.devtools.HasDevTools -// Replace the version to match the Chrome version -import org.openqa.selenium.devtools.v91.emulation.Emulation -import org.openqa.selenium.remote.Augmenter -import org.openqa.selenium.remote.RemoteWebDriver -import java.net.URL -import java.util.Optional - -fun main() { - val chromeOptions = ChromeOptions() - var driver: WebDriver = RemoteWebDriver(URL(""), chromeOptions) - driver = Augmenter().augment(driver) - - val devTools = (driver as HasDevTools).devTools - devTools.createSession() - - devTools.send( - Emulation.setGeolocationOverride( - Optional.of(52.5043), - Optional.of(13.4501), - Optional.of(1) - ) - ) - - driver["https://my-location.org/"] - driver.quit() -} - - {{< /tab >}} -{{< /tabpane >}} - -## Override Device Mode - -Using Selenium's integration with CDP, one can override the current device -mode and simulate a new mode. Width, height, mobile, and deviceScaleFactor -are required parameters. Optional parameters include scale, screenWidth, -screenHeight, positionX, positionY, dontSetVisible, screenOrientation, viewport, and displayFeature. - -{{< tabpane langEqualsHeader=true >}} -{{< badge-examples >}} -{{< tab header="Java" >}} -ChromeDriver driver = new ChromeDriver(); -DevTools devTools = driver.getDevTools(); -devTools.createSession(); -// iPhone 11 Pro dimensions -devTools.send(Emulation.setDeviceMetricsOverride(375, - 812, - 50, - true, - Optional.empty(), - Optional.empty(), - Optional.empty(), - Optional.empty(), - Optional.empty(), - Optional.empty(), - Optional.empty(), - Optional.empty(), - Optional.empty())); -driver.get("https://selenium.dev/"); -driver.quit(); -{{< /tab >}} -{{< tab header="Python" >}} - from selenium import webdriver - - driver = webdriver.Chrome() - // iPhone 11 Pro dimensions - set_device_metrics_override = dict({ - "width": 375, - "height": 812, - "deviceScaleFactor": 50, - "mobile": True - }) - driver.execute_cdp_cmd('Emulation.setDeviceMetricsOverride', set_device_metrics_override) - driver.get("") -{{< /tab >}} -{{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.DevTools; -using System.Threading.Tasks; -using OpenQA.Selenium.DevTools.V91.Emulation; -using DevToolsSessionDomains = OpenQA.Selenium.DevTools.V91.DevToolsSessionDomains; - -namespace Selenium4Sample { -public class ExampleDevice { - - protected IDevToolsSession session; - protected IWebDriver driver; - protected DevToolsSessionDomains devToolsSession; - - public async Task DeviceModeTest() { - ChromeOptions chromeOptions = new ChromeOptions(); - //Set ChromeDriver - driver = new ChromeDriver(); - //Get DevTools - IDevTools devTools = driver as IDevTools; - //DevTools Session - session = devTools.GetDevToolsSession(); - - var deviceModeSetting = new SetDeviceMetricsOverrideCommandSettings(); - deviceModeSetting.Width = 600; - deviceModeSetting.Height = 1000; - deviceModeSetting.Mobile = true; - deviceModeSetting.DeviceScaleFactor = 50; - - await session - .GetVersionSpecificDomains < OpenQA.Selenium.DevTools.V91.DevToolsSessionDomains > () - .Emulation - .SetDeviceMetricsOverride(deviceModeSetting); - - driver.Url = ""; - } -} -} -{{< /tab >}} -{{< tab header="Ruby" >}} -require 'selenium-webdriver' - -driver = Selenium::WebDriver.for :chrome - -begin - metrics = { width: 300, - height: 200, - mobile: true, - deviceScaleFactor: 50 } - driver.execute_cdp('Emulation.setDeviceMetricsOverride', metrics) - driver.get 'https://www.google.com' -ensure - driver.quit -end -{{< /tab >}} -{{< tab header="JavaScript" >}} -const {Builder} = require('selenium-webdriver'); -const firefox = require('selenium-webdriver/firefox'); -const options = new firefox.Options(); -// enable debugger for CDP -options.enableDebugger(); - -(async function example() { - try { - let driver = await new Builder().forBrowser('firefox').setFirefoxOptions(options).build(); - const pageCdpConnection = await driver.createCDPConnection('page'); - const metrics = { - width: 300, - height: 200, - deviceScaleFactor: 50, - mobile: true, - }; - await pageCdpConnection.execute( - "Emulation.setDeviceMetricsOverride", - metrics - ); - await driver.get("https://www.google.com"); - await driver.quit(); - } catch (e) { - console.log(e); - } -})(); -{{< /tab >}} -{{< tab header="Kotlin" >}} -fun kotlinOverridDeviceMode() { - val driver = ChromeDriver() - - val deviceMetrics: Map = object : HashMap() { - init { - put("width", 600) - put("height", 1000) - put("mobile", true) - put("deviceScaleFactor", 50) - } - } - - driver.executeCdpCommand("Emulation.setDeviceMetricsOverride", deviceMetrics) - driver.get("https://www.google.com") - driver.quit() -} -{{< /tab >}} -{{< /tabpane >}} - -## Collect Performance Metrics - -Collect various performance metrics while navigating the application. - -{{< tabpane langEqualsHeader=true >}} -{{< badge-examples >}} -{{< tab header="Java" >}} -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.devtools.DevTools; - -public void performanceMetricsExample() { - ChromeDriver driver = new ChromeDriver(); - DevTools devTools = driver.getDevTools(); - devTools.createSession(); - devTools.send(Performance.enable(Optional.empty())); - List metricList = devTools.send(Performance.getMetrics()); - - driver.get("https://google.com"); - driver.quit(); - - for(Metric m : metricList) { - System.out.println(m.getName() + " = " + m.getValue()); - } -} -{{< /tab >}} -{{< tab header="Python" >}} -from selenium import webdriver - -driver = webdriver.Chrome() - -driver.get('https://www.duckduckgo.com') -driver.execute_cdp_cmd('Performance.enable', {}) -t = driver.execute_cdp_cmd('Performance.getMetrics', {}) -print(t) -driver.quit() -{{< /tab >}} -{{< tab header="CSharp" >}} -// File must contain the following using statements -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.DevTools; - -// We must use a version-specific set of domains -using OpenQA.Selenium.DevTools.V94.Performance; - -public async Task PerformanceMetricsExample() -{ - IWebDriver driver = new ChromeDriver(); - IDevTools devTools = driver as IDevTools; - DevToolsSession session = devTools.GetDevToolsSession(); - await session.SendCommand(new EnableCommandSettings()); - var metricsResponse = - await session.SendCommand( - new GetMetricsCommandSettings()); - - driver.Navigate().GoToUrl("http://www.google.com"); - driver.Quit(); - - var metrics = metricsResponse.Metrics; - foreach (Metric metric in metrics) - { - Console.WriteLine("{0} = {1}", metric.Name, metric.Value); - } -} -{{< /tab >}} -{{< tab header="Ruby" >}} -require 'selenium-webdriver' - -driver = Selenium::WebDriver.for :chrome - -begin - driver.get 'https://www.duckduckgo.com' - driver.execute_cdp('Performance.enable', {}) - metrics = driver.execute_cdp('Performance.getMetrics', {}) - puts metrics -ensure - driver.quit -end -{{< /tab >}} -{{< tab header="JavaScript" >}} -await driver.get("https://www.duckduckgo.com"); - -await driver.sendAndGetDevToolsCommand('Performance.enable') - -let result = await driver.sendAndGetDevToolsCommand('Performance.getMetrics') -console.log(result) - -await driver.quit(); -{{< /tab >}} -{{< tab header="Kotlin" >}} -val driver = ChromeDriver() -val devTools = driver.devTools -devTools.createSession() -devTools.send(Performance.enable(Optional.empty())) -val metricList: List = devTools.send(Performance.getMetrics()) - -driver["https://google.com"] -driver.quit() - -for (m in metricList) { - println(m.name.toString() + " = " + m.value) -} -{{< /tab >}} -{{< /tabpane >}} - diff --git a/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools.ja.md b/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools.ja.md deleted file mode 100644 index 9b4aaacc881d..000000000000 --- a/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools.ja.md +++ /dev/null @@ -1,542 +0,0 @@ ---- -title: "Chrome DevTools Protocol" -linkTitle: "Chrome DevTools Protocol" -weight: 5 -aliases: [ -"/documentation/ja/support_packages/chrome_devtools/", -"/ja/documentation/support_packages/chrome_devtools/" -] ---- - -{{% pageinfo color="warning" %}} -

- - Page being translated from English to Japanese. - Do you speak Japanese? Help us to translate - it by sending us pull requests! -

-{{% /pageinfo %}} - -{{% pageinfo color="warning" %}} -While Selenium 4 provides direct access to the Chrome DevTools Protocol (CDP), it is -highly encouraged that you use the [WebDriver Bidi APIs]({{< ref "bidi_api.md" >}}) instead. -{{% /pageinfo %}} - -Many browsers provide "DevTools" -- a set of tools that are integrated with the browser that -developers can use to debug web apps and explore the performance of their pages. Google Chrome's -DevTools make use of a protocol called the Chrome DevTools Protocol (or "CDP" for short). -As the name suggests, this is not designed for testing, nor to have a stable API, so functionality -is highly dependent on the version of the browser. - -WebDriver Bidi is the next generation of the W3C WebDriver protocol and aims to provide a stable API -implemented by all browsers, but it's not yet complete. Until it is, Selenium provides access to -the CDP for those browsers that implement it (such as Google Chrome, or Microsoft Edge, and -Firefox), allowing you to enhance your tests in interesting ways. Some examples of what you can -do with it are given below. - -## Emulate Geo Location - -Some applications have different features and functionalities across different -locations. Automating such applications is difficult because it is hard to emulate -the geo-locations in the browser using Selenium. But with the help of Devtools, -we can easily emulate them. Below code snippet demonstrates that. - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -ChromeDriver driver = new ChromeDriver(); -DevTools devTools = driver.getDevTools(); -devTools.createSession(); -devTools.send(Emulation.setGeolocationOverride(Optional.of(52.5043), - Optional.of(13.4501), - Optional.of(1))); -driver.get("https://my-location.org/"); -driver.quit(); - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -from selenium.webdriver.chrome.service import Service - -def geoLocationTest(): - driver = webdriver.Chrome() - Map_coordinates = dict({ - "latitude": 41.8781, - "longitude": -87.6298, - "accuracy": 100 - }) - driver.execute_cdp_cmd("Emulation.setGeolocationOverride", Map_coordinates) - driver.get("") - {{< /tab >}} - {{< tab header="CSharp" >}} -using System.Threading.Tasks; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.DevTools; -// Replace the version to match the Chrome version -using OpenQA.Selenium.DevTools.V87.Emulation; - -namespace dotnet_test { - class Program { - public static void Main(string[] args) { - GeoLocation().GetAwaiter().GetResult(); - } - - public static async Task GeoLocation() { - ChromeDriver driver = new ChromeDriver(); - DevToolsSession devToolsSession = driver.CreateDevToolsSession(); - var geoLocationOverrideCommandSettings = new SetGeolocationOverrideCommandSettings(); - - geoLocationOverrideCommandSettings.Latitude = 51.507351; - geoLocationOverrideCommandSettings.Longitude = -0.127758; - geoLocationOverrideCommandSettings.Accuracy = 1; - - await devToolsSession - .GetVersionSpecificDomains() - .Emulation - .SetGeolocationOverride(geoLocationOverrideCommandSettings); - - driver.Url = ""; - } - } -} - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' - -driver = Selenium::WebDriver.for :chrome - -begin - # Latitude and longitude of Tokyo, Japan - coordinates = { latitude: 35.689487, - longitude: 139.691706, - accuracy: 100 } - driver.execute_cdp('Emulation.setGeolocationOverride', coordinates) - driver.get 'https://www.google.com/search?q=selenium' -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" text=true >}} -{{< gh-codeblock path="/examples/javascript/test/bidirectional/emulateGeoLocation.spec.js">}} - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.devtools.DevTools - -fun main() { - val driver = ChromeDriver() - val coordinates : HashMap = HashMap () - coordinates.put("latitude", 50.2334) - coordinates.put("longitude", 0.2334) - coordinates.put("accuracy", 1) - driver.executeCdpCommand("Emulation.setGeolocationOverride", coordinates) - driver.get("https://www.google.com") -} - {{< /tab >}} -{{< /tabpane >}} - -## Emulate Geo Location with the Remote WebDriver: - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -ChromeOptions chromeOptions = new ChromeOptions(); -WebDriver driver = new RemoteWebDriver(new URL(""), chromeOptions); -driver = new Augmenter().augment(driver); - -DevTools devTools = ((HasDevTools) driver).getDevTools(); -devTools.createSession(); - -devTools.send(Emulation.setGeolocationOverride(Optional.of(52.5043), - Optional.of(13.4501), - Optional.of(1))); - -driver.get("https://my-location.org/"); -driver.quit(); - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -#Replace the version to match the Chrome version -import selenium.webdriver.common.devtools.v93 as devtools - -async def geoLocationTest(): - chrome_options = webdriver.ChromeOptions() - driver = webdriver.Remote( - command_executor='', - options=chrome_options - ) - - async with driver.bidi_connection() as session: - cdpSession = session.session - await cdpSession.execute(devtools.emulation.set_geolocation_override(latitude=41.8781,longitude=-87.6298,accuracy=100)) - driver.get("https://my-location.org/") - driver.quit() - {{< /tab >}} - {{< tab header="CSharp" >}} -using System.Threading.Tasks; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.DevTools; -// Replace the version to match the Chrome version -using OpenQA.Selenium.DevTools.V87.Emulation; - -namespace dotnet_test { - class Program { - public static void Main(string[] args) { - GeoLocation().GetAwaiter().GetResult(); - } - - public static async Task GeoLocation() { - ChromeOptions chromeOptions = new ChromeOptions(); - RemoteWebDriver driver = new RemoteWebDriver(new Uri(""), chromeOptions); - DevToolsSession devToolsSession = driver.CreateDevToolsSession(); - var geoLocationOverrideCommandSettings = new SetGeolocationOverrideCommandSettings(); - - geoLocationOverrideCommandSettings.Latitude = 51.507351; - geoLocationOverrideCommandSettings.Longitude = -0.127758; - geoLocationOverrideCommandSettings.Accuracy = 1; - - await devToolsSession - .GetVersionSpecificDomains() - .Emulation - .SetGeolocationOverride(geoLocationOverrideCommandSettings); - - driver.Url = "https://my-location.org/"; - } - } -} - {{< /tab >}} - {{< tab header="Ruby" >}} - -driver = Selenium::WebDriver.for( -:remote, -:url => "", -:capabilities => :chrome) - -begin - # Latitude and longitude of Tokyo, Japan - coordinates = { latitude: 35.689487, - longitude: 139.691706, - accuracy: 100 } - devToolsSession = driver.devtools - devToolsSession.send_cmd('Emulation.setGeolocationOverride', coordinates) - driver.get 'https://my-location.org/' - puts res -ensure - driver.quit -end - - {{< /tab >}} - {{< tab header="JavaScript" >}} -const webdriver = require('selenium-webdriver'); -const BROWSER_NAME = webdriver.Browser.CHROME; - -async function getDriver() { - return new webdriver.Builder() - .usingServer('') - .forBrowser(BROWSER_NAME) - .build(); -} - -async function executeCDPCommands () { - let driver = await getDriver(); - - await driver.get(""); - - const cdpConnection = await driver.createCDPConnection('page'); - //Latitude and longitude of Tokyo, Japan - const coordinates = { - latitude: 35.689487, - longitude: 139.691706, - accuracy: 100, - }; - await cdpConnection.execute( - "Emulation.setGeolocationOverride", - coordinates - ); - await driver.quit(); -} - -executeCDPCommands(); - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.WebDriver -import org.openqa.selenium.chrome.ChromeOptions -import org.openqa.selenium.devtools.HasDevTools -// Replace the version to match the Chrome version -import org.openqa.selenium.devtools.v91.emulation.Emulation -import org.openqa.selenium.remote.Augmenter -import org.openqa.selenium.remote.RemoteWebDriver -import java.net.URL -import java.util.Optional - -fun main() { - val chromeOptions = ChromeOptions() - var driver: WebDriver = RemoteWebDriver(URL(""), chromeOptions) - driver = Augmenter().augment(driver) - - val devTools = (driver as HasDevTools).devTools - devTools.createSession() - - devTools.send( - Emulation.setGeolocationOverride( - Optional.of(52.5043), - Optional.of(13.4501), - Optional.of(1) - ) - ) - - driver["https://my-location.org/"] - driver.quit() -} - - {{< /tab >}} -{{< /tabpane >}} - -## Override Device Mode - -Using Selenium's integration with CDP, one can override the current device -mode and simulate a new mode. Width, height, mobile, and deviceScaleFactor -are required parameters. Optional parameters include scale, screenWidth, -screenHeight, positionX, positionY, dontSetVisible, screenOrientation, viewport, and displayFeature. - -{{< tabpane langEqualsHeader=true >}} -{{< tab header="Java" >}} -ChromeDriver driver = new ChromeDriver(); -DevTools devTools = driver.getDevTools(); -devTools.createSession(); -// iPhone 11 Pro dimensions -devTools.send(Emulation.setDeviceMetricsOverride(375, - 812, - 50, - true, - Optional.empty(), - Optional.empty(), - Optional.empty(), - Optional.empty(), - Optional.empty(), - Optional.empty(), - Optional.empty(), - Optional.empty(), - Optional.empty())); -driver.get("https://selenium.dev/"); -driver.quit(); -{{< /tab >}} -{{< tab header="Python" >}} -from selenium import webdriver - -driver = webdriver.Chrome() -// iPhone 11 Pro dimensions -set_device_metrics_override = dict({ -"width": 375, -"height": 812, -"deviceScaleFactor": 50, -"mobile": True -}) -driver.execute_cdp_cmd('Emulation.setDeviceMetricsOverride', set_device_metrics_override) -driver.get("") -{{< /tab >}} -{{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.DevTools; -using System.Threading.Tasks; -using OpenQA.Selenium.DevTools.V91.Emulation; -using DevToolsSessionDomains = OpenQA.Selenium.DevTools.V91.DevToolsSessionDomains; - -namespace Selenium4Sample { -public class ExampleDevice { - - protected IDevToolsSession session; - protected IWebDriver driver; - protected DevToolsSessionDomains devToolsSession; - - public async Task DeviceModeTest() { - ChromeOptions chromeOptions = new ChromeOptions(); - //Set ChromeDriver - driver = new ChromeDriver(); - //Get DevTools - IDevTools devTools = driver as IDevTools; - //DevTools Session - session = devTools.GetDevToolsSession(); - - var deviceModeSetting = new SetDeviceMetricsOverrideCommandSettings(); - deviceModeSetting.Width = 600; - deviceModeSetting.Height = 1000; - deviceModeSetting.Mobile = true; - deviceModeSetting.DeviceScaleFactor = 50; - - await session - .GetVersionSpecificDomains < OpenQA.Selenium.DevTools.V91.DevToolsSessionDomains > () - .Emulation - .SetDeviceMetricsOverride(deviceModeSetting); - - driver.Url = ""; - } -} -} -{{< /tab >}} -{{< tab header="Ruby" >}} -require 'selenium-webdriver' - -driver = Selenium::WebDriver.for :chrome - -begin - metrics = { width: 300, - height: 200, - mobile: true, - deviceScaleFactor: 50 } - driver.execute_cdp('Emulation.setDeviceMetricsOverride', metrics) - driver.get 'https://www.google.com' -ensure - driver.quit -end -{{< /tab >}} -{{< tab header="JavaScript" >}} -const {Builder} = require('selenium-webdriver'); -const firefox = require('selenium-webdriver/firefox'); -const options = new firefox.Options(); -// enable debugger for CDP -options.enableDebugger(); - -(async function example() { - try { - let driver = await new Builder().forBrowser('firefox').setFirefoxOptions(options).build(); - const pageCdpConnection = await driver.createCDPConnection('page'); - const metrics = { - width: 300, - height: 200, - deviceScaleFactor: 50, - mobile: true, - }; - await pageCdpConnection.execute( - "Emulation.setDeviceMetricsOverride", - metrics - ); - await driver.get("https://www.google.com"); - await driver.quit(); - } catch (e) { - console.log(e); - } -})(); -{{< /tab >}} -{{< tab header="Kotlin" >}} -fun kotlinOverridDeviceMode() { - val driver = ChromeDriver() - - val deviceMetrics: Map = object : HashMap() { - init { - put("width", 600) - put("height", 1000) - put("mobile", true) - put("deviceScaleFactor", 50) - } - } - - driver.executeCdpCommand("Emulation.setDeviceMetricsOverride", deviceMetrics) - driver.get("https://www.google.com") - driver.quit() -} -{{< /tab >}} -{{< /tabpane >}} - -## Collect Performance Metrics - -Collect various performance metrics while navigating the application. - -{{< tabpane langEqualsHeader=true >}} -{{< tab header="Java" >}} -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.devtools.DevTools; - -public void performanceMetricsExample() { - ChromeDriver driver = new ChromeDriver(); - DevTools devTools = driver.getDevTools(); - devTools.createSession(); - devTools.send(Performance.enable(Optional.empty())); - List metricList = devTools.send(Performance.getMetrics()); - - driver.get("https://google.com"); - driver.quit(); - - for(Metric m : metricList) { - System.out.println(m.getName() + " = " + m.getValue()); - } -} -{{< /tab >}} -{{< tab header="Python" >}} -from selenium import webdriver - -driver = webdriver.Chrome() - -driver.get('https://www.duckduckgo.com') -driver.execute_cdp_cmd('Performance.enable', {}) -t = driver.execute_cdp_cmd('Performance.getMetrics', {}) -print(t) -driver.quit() -{{< /tab >}} -{{< tab header="CSharp" >}} -// File must contain the following using statements -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.DevTools; - -// We must use a version-specific set of domains -using OpenQA.Selenium.DevTools.V94.Performance; - -public async Task PerformanceMetricsExample() -{ - IWebDriver driver = new ChromeDriver(); - IDevTools devTools = driver as IDevTools; - DevToolsSession session = devTools.GetDevToolsSession(); - await session.SendCommand(new EnableCommandSettings()); - var metricsResponse = - await session.SendCommand( - new GetMetricsCommandSettings()); - - driver.Navigate().GoToUrl("http://www.google.com"); - driver.Quit(); - - var metrics = metricsResponse.Metrics; - foreach (Metric metric in metrics) - { - Console.WriteLine("{0} = {1}", metric.Name, metric.Value); - } -} -{{< /tab >}} -{{< tab header="Ruby" >}} -require 'selenium-webdriver' - -driver = Selenium::WebDriver.for :chrome - -begin - driver.get 'https://www.duckduckgo.com' - driver.execute_cdp('Performance.enable', {}) - metrics = driver.execute_cdp('Performance.getMetrics', {}) - puts metrics -ensure - driver.quit -end -{{< /tab >}} -{{< tab header="JavaScript" >}} -await driver.get("https://www.duckduckgo.com"); - -await driver.sendAndGetDevToolsCommand('Performance.enable') - -let result = await driver.sendAndGetDevToolsCommand('Performance.getMetrics') -console.log(result) - -await driver.quit(); -{{< /tab >}} -{{< tab header="Kotlin" >}} -val driver = ChromeDriver() -val devTools = driver.devTools -devTools.createSession() -devTools.send(Performance.enable(Optional.empty())) -val metricList: List = devTools.send(Performance.getMetrics()) - -driver["https://google.com"] -driver.quit() - -for (m in metricList) { - println(m.name.toString() + " = " + m.value) -} -{{< /tab >}} -{{< /tabpane >}} - diff --git a/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools.pt-br.md b/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools.pt-br.md deleted file mode 100644 index 1a918e44aa19..000000000000 --- a/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools.pt-br.md +++ /dev/null @@ -1,528 +0,0 @@ ---- -title: "Chrome DevTools" -linkTitle: "Chrome DevTools" -weight: 5 -aliases: [ -"/documentation/pt-br/support_packages/chrome_devtools/", -"/pt-br/documentation/support_packages/chrome_devtools/" -] ---- - -{{% pageinfo color="warning" %}} -Apesar do Selenium 4 providenciar acesso direto ao Protocolo Chrome DevTools (CDP), é altamente recomendável que você use o [WebDriver Bidi APIs]({{< ref "bidi_api.md" >}}) ao invés do acesso direto. -{{% /pageinfo %}} - -Muitos navegadores fornecem o "DevTools", um conjunto de ferramentas integradas ao navegador, que -desenvolvedores podem usar para depurar web apps analisar o desempenho de suas páginas. O DevTools do Google Chrome faz o uso de um protocolo chamado Protocolo Chrome DevTools (abreviado como "CDP"). -Como o nome sugere, ele não foi projetado para testes, ou tem uma API estável, portanto, sua funcionalidade depende muito da versão do navegador de internet. - -WebDriver Bidi é a próxima geração do protocolo W3C WebDriver e visa fornecer uma API estável -implementado por todos os navegadores, mas ele ainda não está completo. Até que seja, o Selenium fornece acesso ao -CDP para os navegadores que o implementam (como Google Chrome ou Microsoft Edge e -Firefox), permitindo que você aprimore seus testes de maneiras interessantes. Alguns exemplos do que você pode -fazer com ele são dadas abaixo. - -## Emular Geo Localização - -Alguns aplicativos têm recursos e funcionalidades diferentes em diferentes -locations. Automatizar esses tipos de aplicativos é complicado porque é difícil emular -as geolocalizações no navegador usando o Selenium. Mas com a ajuda do Devtools, -podemos facilmente as emular. O trecho do código abaixo demonstra isso. - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -ChromeDriver driver = new ChromeDriver(); -DevTools devTools = driver.getDevTools(); -devTools.createSession(); -devTools.send(Emulation.setGeolocationOverride(Optional.of(52.5043), - Optional.of(13.4501), - Optional.of(1))); -driver.get("https://my-location.org/"); -driver.quit(); - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -from selenium.webdriver.chrome.service import Service - -def geoLocationTest(): - driver = webdriver.Chrome() - Map_coordinates = dict({ - "latitude": 41.8781, - "longitude": -87.6298, - "accuracy": 100 - }) - driver.execute_cdp_cmd("Emulation.setGeolocationOverride", Map_coordinates) - driver.get("") - {{< /tab >}} - {{< tab header="CSharp" >}} -using System.Threading.Tasks; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.DevTools; -// Replace the version to match the Chrome version -using OpenQA.Selenium.DevTools.V87.Emulation; - -namespace dotnet_test { - class Program { - public static void Main(string[] args) { - GeoLocation().GetAwaiter().GetResult(); - } - - public static async Task GeoLocation() { - ChromeDriver driver = new ChromeDriver(); - DevToolsSession devToolsSession = driver.CreateDevToolsSession(); - var geoLocationOverrideCommandSettings = new SetGeolocationOverrideCommandSettings(); - - geoLocationOverrideCommandSettings.Latitude = 51.507351; - geoLocationOverrideCommandSettings.Longitude = -0.127758; - geoLocationOverrideCommandSettings.Accuracy = 1; - - await devToolsSession - .GetVersionSpecificDomains() - .Emulation - .SetGeolocationOverride(geoLocationOverrideCommandSettings); - - driver.Url = ""; - } - } -} - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' - -driver = Selenium::WebDriver.for :chrome - -begin - # Latitude e longitude de Tóquio, Japão - coordinates = { latitude: 35.689487, - longitude: 139.691706, - accuracy: 100 } - driver.execute_cdp('Emulation.setGeolocationOverride', coordinates) - driver.get 'https://www.google.com/search?q=selenium' -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" text=true >}} -{{< gh-codeblock path="/examples/javascript/test/bidirectional/emulateGeoLocation.spec.js">}} - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.devtools.DevTools - -fun main() { - val driver = ChromeDriver() - val coordinates : HashMap = HashMap () - coordinates.put("latitude", 50.2334) - coordinates.put("longitude", 0.2334) - coordinates.put("accuracy", 1) - driver.executeCdpCommand("Emulation.setGeolocationOverride", coordinates) - driver.get("https://www.google.com") -} - {{< /tab >}} -{{< /tabpane >}} - -## Emular localização geográfica com o Remote WebDriver: - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -ChromeOptions chromeOptions = new ChromeOptions(); -WebDriver driver = new RemoteWebDriver(new URL(""), chromeOptions); -driver = new Augmenter().augment(driver); - -DevTools devTools = ((HasDevTools) driver).getDevTools(); -devTools.createSession(); - -devTools.send(Emulation.setGeolocationOverride(Optional.of(52.5043), - Optional.of(13.4501), - Optional.of(1))); - -driver.get("https://my-location.org/"); -driver.quit(); - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -#Replace the version to match the Chrome version -import selenium.webdriver.common.devtools.v93 as devtools - -async def geoLocationTest(): - chrome_options = webdriver.ChromeOptions() - driver = webdriver.Remote( - command_executor='', - options=chrome_options - ) - - async with driver.bidi_connection() as session: - cdpSession = session.session - await cdpSession.execute(devtools.emulation.set_geolocation_override(latitude=41.8781,longitude=-87.6298,accuracy=100)) - driver.get("https://my-location.org/") - driver.quit() - {{< /tab >}} - {{< tab header="CSharp" >}} -using System.Threading.Tasks; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.DevTools; -// Replace the version to match the Chrome version -using OpenQA.Selenium.DevTools.V87.Emulation; - -namespace dotnet_test { - class Program { - public static void Main(string[] args) { - GeoLocation().GetAwaiter().GetResult(); - } - - public static async Task GeoLocation() { - ChromeOptions chromeOptions = new ChromeOptions(); - RemoteWebDriver driver = new RemoteWebDriver(new Uri(""), chromeOptions); - DevToolsSession devToolsSession = driver.CreateDevToolsSession(); - var geoLocationOverrideCommandSettings = new SetGeolocationOverrideCommandSettings(); - - geoLocationOverrideCommandSettings.Latitude = 51.507351; - geoLocationOverrideCommandSettings.Longitude = -0.127758; - geoLocationOverrideCommandSettings.Accuracy = 1; - - await devToolsSession - .GetVersionSpecificDomains() - .Emulation - .SetGeolocationOverride(geoLocationOverrideCommandSettings); - - driver.Url = "https://my-location.org/"; - } - } -} - {{< /tab >}} - {{< tab header="Ruby" >}} - -driver = Selenium::WebDriver.for( -:remote, -:url => "", -:capabilities => :chrome) - -begin - # Latitude e longitude de Tóquio, Japão - coordinates = { latitude: 35.689487, - longitude: 139.691706, - accuracy: 100 } - devToolsSession = driver.devtools - devToolsSession.send_cmd('Emulation.setGeolocationOverride', coordinates) - driver.get 'https://my-location.org/' - puts res -ensure - driver.quit -end - - {{< /tab >}} - {{< tab header="JavaScript" >}} -const webdriver = require('selenium-webdriver'); -const BROWSER_NAME = webdriver.Browser.CHROME; - -async function getDriver() { - return new webdriver.Builder() - .usingServer('') - .forBrowser(BROWSER_NAME) - .build(); -} - -async function executeCDPCommands () { - let driver = await getDriver(); - - await driver.get(""); - - const cdpConnection = await driver.createCDPConnection('page'); - //Latitude and longitude of Tokyo, Japan - const coordinates = { - latitude: 35.689487, - longitude: 139.691706, - accuracy: 100, - }; - await cdpConnection.execute( - "Emulation.setGeolocationOverride", - coordinates - ); - await driver.quit(); -} - -executeCDPCommands(); - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.WebDriver -import org.openqa.selenium.chrome.ChromeOptions -import org.openqa.selenium.devtools.HasDevTools -// Replace the version to match the Chrome version -import org.openqa.selenium.devtools.v91.emulation.Emulation -import org.openqa.selenium.remote.Augmenter -import org.openqa.selenium.remote.RemoteWebDriver -import java.net.URL -import java.util.Optional - -fun main() { - val chromeOptions = ChromeOptions() - var driver: WebDriver = RemoteWebDriver(URL(""), chromeOptions) - driver = Augmenter().augment(driver) - - val devTools = (driver as HasDevTools).devTools - devTools.createSession() - - devTools.send( - Emulation.setGeolocationOverride( - Optional.of(52.5043), - Optional.of(13.4501), - Optional.of(1) - ) - ) - - driver["https://my-location.org/"] - driver.quit() -} - - {{< /tab >}} -{{< /tabpane >}} - -## Modo de Dispositivo Override - -Usando a integração do Selenium com o CDP, pode-se substituir o modo do dispositivo atual e simular um novo modo. Width(largura), Height(altura), mobile(mobilidade) e deviceScaleFactor são parâmetros obrigatórios. Parâmetros opcionais incluem scale(escala), screenWidth(largura da tela), -screenHeight(altura da tela), positionX, positionY, dontSetVisible(não setar como visível), screenOrientation(orientação da tela), viewport e displayFeature. - -{{< tabpane langEqualsHeader=true >}} -{{< tab header="Java" >}} -ChromeDriver driver = new ChromeDriver(); -DevTools devTools = driver.getDevTools(); -devTools.createSession(); -// iPhone 11 Pro dimensions -devTools.send(Emulation.setDeviceMetricsOverride(375, - 812, - 50, - true, - Optional.empty(), - Optional.empty(), - Optional.empty(), - Optional.empty(), - Optional.empty(), - Optional.empty(), - Optional.empty(), - Optional.empty(), - Optional.empty())); -driver.get("https://selenium.dev/"); -driver.quit(); -{{< /tab >}} -{{< tab header="Python" >}} -from selenium import webdriver - -driver = webdriver.Chrome() -// iPhone 11 Pro dimensions -set_device_metrics_override = dict({ -"width": 375, -"height": 812, -"deviceScaleFactor": 50, -"mobile": True -}) -driver.execute_cdp_cmd('Emulation.setDeviceMetricsOverride', set_device_metrics_override) -driver.get("") -{{< /tab >}} -{{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.DevTools; -using System.Threading.Tasks; -using OpenQA.Selenium.DevTools.V91.Emulation; -using DevToolsSessionDomains = OpenQA.Selenium.DevTools.V91.DevToolsSessionDomains; - -namespace Selenium4Sample { -public class ExampleDevice { - - protected IDevToolsSession session; - protected IWebDriver driver; - protected DevToolsSessionDomains devToolsSession; - - public async Task DeviceModeTest() { - ChromeOptions chromeOptions = new ChromeOptions(); - //Set ChromeDriver - driver = new ChromeDriver(); - //Get DevTools - IDevTools devTools = driver as IDevTools; - //DevTools Session - session = devTools.GetDevToolsSession(); - - var deviceModeSetting = new SetDeviceMetricsOverrideCommandSettings(); - deviceModeSetting.Width = 600; - deviceModeSetting.Height = 1000; - deviceModeSetting.Mobile = true; - deviceModeSetting.DeviceScaleFactor = 50; - - await session - .GetVersionSpecificDomains < OpenQA.Selenium.DevTools.V91.DevToolsSessionDomains > () - .Emulation - .SetDeviceMetricsOverride(deviceModeSetting); - - driver.Url = ""; - } -} -} -{{< /tab >}} -{{< tab header="Ruby" >}} -require 'selenium-webdriver' - -driver = Selenium::WebDriver.for :chrome - -begin - metrics = { width: 300, - height: 200, - mobile: true, - deviceScaleFactor: 50 } - driver.execute_cdp('Emulation.setDeviceMetricsOverride', metrics) - driver.get 'https://www.google.com' -ensure - driver.quit -end -{{< /tab >}} -{{< tab header="JavaScript" >}} -const {Builder} = require('selenium-webdriver'); -const firefox = require('selenium-webdriver/firefox'); -const options = new firefox.Options(); -// enable debugger for CDP -options.enableDebugger(); - -(async function example() { - try { - let driver = await new Builder().forBrowser('firefox').setFirefoxOptions(options).build(); - const pageCdpConnection = await driver.createCDPConnection('page'); - const metrics = { - width: 300, - height: 200, - deviceScaleFactor: 50, - mobile: true, - }; - await pageCdpConnection.execute( - "Emulation.setDeviceMetricsOverride", - metrics - ); - await driver.get("https://www.google.com"); - await driver.quit(); - } catch (e) { - console.log(e); - } -})(); -{{< /tab >}} -{{< tab header="Kotlin" >}} -fun kotlinOverridDeviceMode() { - val driver = ChromeDriver() - - val deviceMetrics: Map = object : HashMap() { - init { - put("width", 600) - put("height", 1000) - put("mobile", true) - put("deviceScaleFactor", 50) - } - } - - driver.executeCdpCommand("Emulation.setDeviceMetricsOverride", deviceMetrics) - driver.get("https://www.google.com") - driver.quit() -} -{{< /tab >}} -{{< /tabpane >}} - -## Coletando Métricas de Desempenho - -Colete várias métricas de desempenho enquanto navega no aplicativo. - -{{< tabpane langEqualsHeader=true >}} -{{< tab header="Java" >}} -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.devtools.DevTools; - -public void performanceMetricsExample() { - ChromeDriver driver = new ChromeDriver(); - DevTools devTools = driver.getDevTools(); - devTools.createSession(); - devTools.send(Performance.enable(Optional.empty())); - List metricList = devTools.send(Performance.getMetrics()); - - driver.get("https://google.com"); - driver.quit(); - - for(Metric m : metricList) { - System.out.println(m.getName() + " = " + m.getValue()); - } -} -{{< /tab >}} -{{< tab header="Python" >}} -from selenium import webdriver - -driver = webdriver.Chrome() - -driver.get('https://www.duckduckgo.com') -driver.execute_cdp_cmd('Performance.enable', {}) -t = driver.execute_cdp_cmd('Performance.getMetrics', {}) -print(t) -driver.quit() -{{< /tab >}} -{{< tab header="CSharp" >}} -// File must contain the following using statements -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.DevTools; - -// We must use a version-specific set of domains -using OpenQA.Selenium.DevTools.V94.Performance; - -public async Task PerformanceMetricsExample() -{ - IWebDriver driver = new ChromeDriver(); - IDevTools devTools = driver as IDevTools; - DevToolsSession session = devTools.GetDevToolsSession(); - await session.SendCommand(new EnableCommandSettings()); - var metricsResponse = - await session.SendCommand( - new GetMetricsCommandSettings()); - - driver.Navigate().GoToUrl("http://www.google.com"); - driver.Quit(); - - var metrics = metricsResponse.Metrics; - foreach (Metric metric in metrics) - { - Console.WriteLine("{0} = {1}", metric.Name, metric.Value); - } -} -{{< /tab >}} -{{< tab header="Ruby" >}} -require 'selenium-webdriver' - -driver = Selenium::WebDriver.for :chrome - -begin - driver.get 'https://www.duckduckgo.com' - driver.execute_cdp('Performance.enable', {}) - metrics = driver.execute_cdp('Performance.getMetrics', {}) - puts metrics -ensure - driver.quit -end -{{< /tab >}} -{{< tab header="JavaScript" >}} -await driver.get("https://www.duckduckgo.com"); - -await driver.sendAndGetDevToolsCommand('Performance.enable') - -let result = await driver.sendAndGetDevToolsCommand('Performance.getMetrics') -console.log(result) - -await driver.quit(); -{{< /tab >}} -{{< tab header="Kotlin" >}} -val driver = ChromeDriver() -val devTools = driver.devTools -devTools.createSession() -devTools.send(Performance.enable(Optional.empty())) -val metricList: List = devTools.send(Performance.getMetrics()) - -driver["https://google.com"] -driver.quit() - -for (m in metricList) { - println(m.name.toString() + " = " + m.value) -} -{{< /tab >}} -{{< /tabpane >}} - diff --git a/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools.zh-cn.md b/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools.zh-cn.md deleted file mode 100644 index 7ad07572fa26..000000000000 --- a/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools.zh-cn.md +++ /dev/null @@ -1,542 +0,0 @@ ---- -title: "Chrome开发工具协议" -linkTitle: "Chrome开发工具" -weight: 5 -aliases: [ -"/documentation/zh-cn/support_packages/chrome_devtools/", -"/zh-cn/documentation/support_packages/chrome_devtools/" -] ---- - -{{% pageinfo color="warning" %}} -虽然Selenium 4提供了对Chrome DevTools Protocol (CDP) 的直接访问, -但是仍非常鼓励您使用 -[WebDriver Bidi APIs]({{< ref "bidi_api.md" >}}) -代替. -{{% /pageinfo %}} - -许多浏览器都提供"开发工具" -- 一组与浏览器集成的工具, -开发人员可以用其调试web应用程序并探索其页面的性能. -谷歌浏览器开发工具 -使用一种称为Chrome DevTools Protocol (简称"CDP") 的协议. -顾名思义, 这不是为测试而设计的, -而并没有一个稳定的API, -所以它的功能高度依赖于浏览器的版本. - -WebDriver Bidi是W3C WebDriver的下一代协议, -旨在提供由所有浏览器实现稳定的API, 但尚未完成. -在此之前, Selenium提供了通过CDP实现的方式 -(诸如Google Chrome或Microsoft Edge, 以及Firefox), -允许您以有趣的方式增强测试. -下面给出了实际使用的例子. - -## 模拟地理位置 - -一些应用程序在不同的位置具有不同的特性和功能. -自动化此类应用程序很难, -因为很难使用Selenium在浏览器中模拟地理位置. -但是在Devtools的帮助下, -我们可以轻易模拟他们. -下面的代码片段演示了这一点. - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -ChromeDriver driver = new ChromeDriver(); -DevTools devTools = driver.getDevTools(); -devTools.createSession(); -devTools.send(Emulation.setGeolocationOverride(Optional.of(52.5043), - Optional.of(13.4501), - Optional.of(1))); -driver.get("https://my-location.org/"); -driver.quit(); - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -from selenium.webdriver.chrome.service import Service - -def geoLocationTest(): - driver = webdriver.Chrome() - Map_coordinates = dict({ - "latitude": 41.8781, - "longitude": -87.6298, - "accuracy": 100 - }) - driver.execute_cdp_cmd("Emulation.setGeolocationOverride", Map_coordinates) - driver.get("") - {{< /tab >}} - {{< tab header="CSharp" >}} -using System.Threading.Tasks; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.DevTools; -// Replace the version to match the Chrome version -using OpenQA.Selenium.DevTools.V87.Emulation; - -namespace dotnet_test { - class Program { - public static void Main(string[] args) { - GeoLocation().GetAwaiter().GetResult(); - } - - public static async Task GeoLocation() { - ChromeDriver driver = new ChromeDriver(); - DevToolsSession devToolsSession = driver.CreateDevToolsSession(); - var geoLocationOverrideCommandSettings = new SetGeolocationOverrideCommandSettings(); - - geoLocationOverrideCommandSettings.Latitude = 51.507351; - geoLocationOverrideCommandSettings.Longitude = -0.127758; - geoLocationOverrideCommandSettings.Accuracy = 1; - - await devToolsSession - .GetVersionSpecificDomains() - .Emulation - .SetGeolocationOverride(geoLocationOverrideCommandSettings); - - driver.Url = ""; - } - } -} - {{< /tab >}} - {{< tab header="Ruby" >}} -require 'selenium-webdriver' - -driver = Selenium::WebDriver.for :chrome - -begin - # Latitude and longitude of Tokyo, Japan - coordinates = { latitude: 35.689487, - longitude: 139.691706, - accuracy: 100 } - driver.execute_cdp('Emulation.setGeolocationOverride', coordinates) - driver.get 'https://www.google.com/search?q=selenium' -ensure - driver.quit -end - {{< /tab >}} - {{< tab header="JavaScript" text=true >}} -{{< gh-codeblock path="/examples/javascript/test/bidirectional/emulateGeoLocation.spec.js">}} - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.chrome.ChromeDriver -import org.openqa.selenium.devtools.DevTools - -fun main() { - val driver = ChromeDriver() - val coordinates : HashMap = HashMap () - coordinates.put("latitude", 50.2334) - coordinates.put("longitude", 0.2334) - coordinates.put("accuracy", 1) - driver.executeCdpCommand("Emulation.setGeolocationOverride", coordinates) - driver.get("https://www.google.com") -} - {{< /tab >}} -{{< /tabpane >}} - -## 通过远程WebDriver模拟地理位置 - -{{< tabpane langEqualsHeader=true >}} - {{< tab header="Java" >}} -ChromeOptions chromeOptions = new ChromeOptions(); -WebDriver driver = new RemoteWebDriver(new URL(""), chromeOptions); -driver = new Augmenter().augment(driver); - -DevTools devTools = ((HasDevTools) driver).getDevTools(); -devTools.createSession(); - -devTools.send(Emulation.setGeolocationOverride(Optional.of(52.5043), - Optional.of(13.4501), - Optional.of(1))); - -driver.get("https://my-location.org/"); -driver.quit(); - {{< /tab >}} - {{< tab header="Python" >}} -from selenium import webdriver -#Replace the version to match the Chrome version -import selenium.webdriver.common.devtools.v93 as devtools - -async def geoLocationTest(): - chrome_options = webdriver.ChromeOptions() - driver = webdriver.Remote( - command_executor='', - options=chrome_options - ) - - async with driver.bidi_connection() as session: - cdpSession = session.session - await cdpSession.execute(devtools.emulation.set_geolocation_override(latitude=41.8781,longitude=-87.6298,accuracy=100)) - driver.get("https://my-location.org/") - driver.quit() - {{< /tab >}} - {{< tab header="CSharp" >}} -using System.Threading.Tasks; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.DevTools; -// Replace the version to match the Chrome version -using OpenQA.Selenium.DevTools.V87.Emulation; - -namespace dotnet_test { - class Program { - public static void Main(string[] args) { - GeoLocation().GetAwaiter().GetResult(); - } - - public static async Task GeoLocation() { - ChromeOptions chromeOptions = new ChromeOptions(); - RemoteWebDriver driver = new RemoteWebDriver(new Uri(""), chromeOptions); - DevToolsSession devToolsSession = driver.CreateDevToolsSession(); - var geoLocationOverrideCommandSettings = new SetGeolocationOverrideCommandSettings(); - - geoLocationOverrideCommandSettings.Latitude = 51.507351; - geoLocationOverrideCommandSettings.Longitude = -0.127758; - geoLocationOverrideCommandSettings.Accuracy = 1; - - await devToolsSession - .GetVersionSpecificDomains() - .Emulation - .SetGeolocationOverride(geoLocationOverrideCommandSettings); - - driver.Url = "https://my-location.org/"; - } - } -} - {{< /tab >}} - {{< tab header="Ruby" >}} - -driver = Selenium::WebDriver.for( -:remote, -:url => "", -:capabilities => :chrome) - -begin - # Latitude and longitude of Tokyo, Japan - coordinates = { latitude: 35.689487, - longitude: 139.691706, - accuracy: 100 } - devToolsSession = driver.devtools - devToolsSession.send_cmd('Emulation.setGeolocationOverride', coordinates) - driver.get 'https://my-location.org/' - puts res -ensure - driver.quit -end - - {{< /tab >}} - {{< tab header="JavaScript" >}} -const webdriver = require('selenium-webdriver'); -const BROWSER_NAME = webdriver.Browser.CHROME; - -async function getDriver() { - return new webdriver.Builder() - .usingServer('') - .forBrowser(BROWSER_NAME) - .build(); -} - -async function executeCDPCommands () { - let driver = await getDriver(); - - await driver.get(""); - - const cdpConnection = await driver.createCDPConnection('page'); - //Latitude and longitude of Tokyo, Japan - const coordinates = { - latitude: 35.689487, - longitude: 139.691706, - accuracy: 100, - }; - await cdpConnection.execute( - "Emulation.setGeolocationOverride", - coordinates - ); - await driver.quit(); -} - -executeCDPCommands(); - {{< /tab >}} - {{< tab header="Kotlin" >}} -import org.openqa.selenium.WebDriver -import org.openqa.selenium.chrome.ChromeOptions -import org.openqa.selenium.devtools.HasDevTools -// Replace the version to match the Chrome version -import org.openqa.selenium.devtools.v91.emulation.Emulation -import org.openqa.selenium.remote.Augmenter -import org.openqa.selenium.remote.RemoteWebDriver -import java.net.URL -import java.util.Optional - -fun main() { - val chromeOptions = ChromeOptions() - var driver: WebDriver = RemoteWebDriver(URL(""), chromeOptions) - driver = Augmenter().augment(driver) - - val devTools = (driver as HasDevTools).devTools - devTools.createSession() - - devTools.send( - Emulation.setGeolocationOverride( - Optional.of(52.5043), - Optional.of(13.4501), - Optional.of(1) - ) - ) - - driver["https://my-location.org/"] - driver.quit() -} - - {{< /tab >}} -{{< /tabpane >}} - -## 覆盖设备模式 - -使用Selenium与CDP的集成, -可以覆盖当前设备模式并模拟新模式. -Width, height, mobile和deviceScaleFactor是必需的参数. -可选参数包括scale, screenWidth, -screenHeight, positionX, positionY, -dontSetVisible, screenOrientation, viewport和displayFeature. - -{{< tabpane langEqualsHeader=true >}} -{{< tab header="Java" >}} -ChromeDriver driver = new ChromeDriver(); -DevTools devTools = driver.getDevTools(); -devTools.createSession(); -// iPhone 11 Pro dimensions -devTools.send(Emulation.setDeviceMetricsOverride(375, - 812, - 50, - true, - Optional.empty(), - Optional.empty(), - Optional.empty(), - Optional.empty(), - Optional.empty(), - Optional.empty(), - Optional.empty(), - Optional.empty(), - Optional.empty())); -driver.get("https://selenium.dev/"); -driver.quit(); -{{< /tab >}} -{{< tab header="Python" >}} -from selenium import webdriver - -driver = webdriver.Chrome() -// iPhone 11 Pro dimensions -set_device_metrics_override = dict({ -"width": 375, -"height": 812, -"deviceScaleFactor": 50, -"mobile": True -}) -driver.execute_cdp_cmd('Emulation.setDeviceMetricsOverride', set_device_metrics_override) -driver.get("") -{{< /tab >}} -{{< tab header="CSharp" >}} -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.DevTools; -using System.Threading.Tasks; -using OpenQA.Selenium.DevTools.V91.Emulation; -using DevToolsSessionDomains = OpenQA.Selenium.DevTools.V91.DevToolsSessionDomains; - -namespace Selenium4Sample { -public class ExampleDevice { - - protected IDevToolsSession session; - protected IWebDriver driver; - protected DevToolsSessionDomains devToolsSession; - - public async Task DeviceModeTest() { - ChromeOptions chromeOptions = new ChromeOptions(); - //Set ChromeDriver - driver = new ChromeDriver(); - //Get DevTools - IDevTools devTools = driver as IDevTools; - //DevTools Session - session = devTools.GetDevToolsSession(); - - var deviceModeSetting = new SetDeviceMetricsOverrideCommandSettings(); - deviceModeSetting.Width = 600; - deviceModeSetting.Height = 1000; - deviceModeSetting.Mobile = true; - deviceModeSetting.DeviceScaleFactor = 50; - - await session - .GetVersionSpecificDomains < OpenQA.Selenium.DevTools.V91.DevToolsSessionDomains > () - .Emulation - .SetDeviceMetricsOverride(deviceModeSetting); - - driver.Url = ""; - } -} -} -{{< /tab >}} -{{< tab header="Ruby" >}} -require 'selenium-webdriver' - -driver = Selenium::WebDriver.for :chrome - -begin - metrics = { width: 300, - height: 200, - mobile: true, - deviceScaleFactor: 50 } - driver.execute_cdp('Emulation.setDeviceMetricsOverride', metrics) - driver.get 'https://www.google.com' -ensure - driver.quit -end -{{< /tab >}} -{{< tab header="JavaScript" >}} -const {Builder} = require('selenium-webdriver'); -const firefox = require('selenium-webdriver/firefox'); -const options = new firefox.Options(); -// enable debugger for CDP -options.enableDebugger(); - -(async function example() { - try { - let driver = await new Builder().forBrowser('firefox').setFirefoxOptions(options).build(); - const pageCdpConnection = await driver.createCDPConnection('page'); - const metrics = { - width: 300, - height: 200, - deviceScaleFactor: 50, - mobile: true, - }; - await pageCdpConnection.execute( - "Emulation.setDeviceMetricsOverride", - metrics - ); - await driver.get("https://www.google.com"); - await driver.quit(); - } catch (e) { - console.log(e); - } -})(); -{{< /tab >}} -{{< tab header="Kotlin" >}} -fun kotlinOverridDeviceMode() { - val driver = ChromeDriver() - - val deviceMetrics: Map = object : HashMap() { - init { - put("width", 600) - put("height", 1000) - put("mobile", true) - put("deviceScaleFactor", 50) - } - } - - driver.executeCdpCommand("Emulation.setDeviceMetricsOverride", deviceMetrics) - driver.get("https://www.google.com") - driver.quit() -} -{{< /tab >}} -{{< /tabpane >}} - -## Collect Performance Metrics - -Collect various performance metrics while navigating the application. - -{{< tabpane langEqualsHeader=true >}} -{{< tab header="Java" >}} -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.devtools.DevTools; - -public void performanceMetricsExample() { - ChromeDriver driver = new ChromeDriver(); - DevTools devTools = driver.getDevTools(); - devTools.createSession(); - devTools.send(Performance.enable(Optional.empty())); - List metricList = devTools.send(Performance.getMetrics()); - - driver.get("https://google.com"); - driver.quit(); - - for(Metric m : metricList) { - System.out.println(m.getName() + " = " + m.getValue()); - } -} -{{< /tab >}} -{{< tab header="Python" >}} -from selenium import webdriver - -driver = webdriver.Chrome() - -driver.get('https://www.duckduckgo.com') -driver.execute_cdp_cmd('Performance.enable', {}) -t = driver.execute_cdp_cmd('Performance.getMetrics', {}) -print(t) -driver.quit() -{{< /tab >}} -{{< tab header="CSharp" >}} -// File must contain the following using statements -using OpenQA.Selenium; -using OpenQA.Selenium.Chrome; -using OpenQA.Selenium.DevTools; - -// We must use a version-specific set of domains -using OpenQA.Selenium.DevTools.V94.Performance; - -public async Task PerformanceMetricsExample() -{ - IWebDriver driver = new ChromeDriver(); - IDevTools devTools = driver as IDevTools; - DevToolsSession session = devTools.GetDevToolsSession(); - await session.SendCommand(new EnableCommandSettings()); - var metricsResponse = - await session.SendCommand( - new GetMetricsCommandSettings()); - - driver.Navigate().GoToUrl("http://www.google.com"); - driver.Quit(); - - var metrics = metricsResponse.Metrics; - foreach (Metric metric in metrics) - { - Console.WriteLine("{0} = {1}", metric.Name, metric.Value); - } -} -{{< /tab >}} -{{< tab header="Ruby" >}} -require 'selenium-webdriver' - -driver = Selenium::WebDriver.for :chrome - -begin - driver.get 'https://www.duckduckgo.com' - driver.execute_cdp('Performance.enable', {}) - metrics = driver.execute_cdp('Performance.getMetrics', {}) - puts metrics -ensure - driver.quit -end -{{< /tab >}} -{{< tab header="JavaScript" >}} -await driver.get("https://www.duckduckgo.com"); - -await driver.sendAndGetDevToolsCommand('Performance.enable') - -let result = await driver.sendAndGetDevToolsCommand('Performance.getMetrics') -console.log(result) - -await driver.quit(); -{{< /tab >}} -{{< tab header="Kotlin" >}} -val driver = ChromeDriver() -val devTools = driver.devTools -devTools.createSession() -devTools.send(Performance.enable(Optional.empty())) -val metricList: List = devTools.send(Performance.getMetrics()) - -driver["https://google.com"] -driver.quit() - -for (m in metricList) { - println(m.name.toString() + " = " + m.value) -} -{{< /tab >}} -{{< /tabpane >}} - diff --git a/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/_index.en.md b/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/_index.en.md new file mode 100644 index 000000000000..6965c884fc70 --- /dev/null +++ b/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/_index.en.md @@ -0,0 +1,47 @@ +--- +title: "Chrome DevTools" +linkTitle: "Chrome DevTools" +weight: 2 +aliases: [ +"/documentation/en/support_packages/chrome_devtools/", +"/documentation/support_packages/chrome_devtools/" +] +--- + +Many browsers provide "DevTools" -- a set of tools that are integrated with the browser that +developers can use to debug web apps and explore the performance of their pages. Google Chrome's +DevTools make use of a protocol called the Chrome DevTools Protocol (or "CDP" for short). +As the name suggests, this is not designed for testing, nor to have a stable API, so functionality +is highly dependent on the version of the browser. + +The [WebDriver BiDirectional Protocol](https://w3c.github.io/webdriver-bidi/) is the next generation of the +W3C WebDriver protocol and aims to provide a stable API implemented by all browsers, but it's not yet complete. +Until it is, Selenium provides access to +the CDP for those browsers that implement it (such as Google Chrome, or Microsoft Edge, and +Firefox), allowing you to enhance your tests in interesting ways. Some examples of what you can +do with it are given below. + +### Ways to Use Chrome DevTools With Selenium +There are three different ways to access Chrome DevTools in Selenium. If you look for other examples online, +you will likely see each of these mixed and matched. + +* The [CDP Endpoint]({{< ref "cdp_endpoint.md" >}}) was the first option available to users. +It only works for the most simple things (setting state, getting basic information), and you +have to know the "magic strings" for the domain and methods and key value pairs. +For basic requirements, this might be simpler than the other options. These methods are only temporarily supported. +* The [CDP API]({{< ref "cdp_api.md" >}}) is an improvement on just using the endpoint because you can set +do things asynchronously. Instead of a String and a Map, you can access the supported classes, +methods and parameters in the code. These methods are also only temporarily supported. +* The [BiDi API]({{< ref "bidi_api.md" >}}) option should be used whenever possible because it +abstracts away the implementation details entirely and will work with either CDP or WebDriver-BiDi +when Selenium moves away from CDP. + +### Examples With Limited Value + +There are a number of commonly cited examples for using CDP that are of limited practical value. +* **Geo Location** — almost all sites use the IP address to determine physical location, +so setting an emulated geolocation rarely has the desired effect. +* **Overriding Device Metrics** — Chrome provides a great API for setting [Mobile Emulation](https://chromedriver.chromium.org/mobile-emulation) +in the Options classes, which is generally superior to attempting to do this with CDP. + +Check out the examples in these documents for ways to do additional useful things: diff --git a/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/_index.ja.md b/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/_index.ja.md new file mode 100644 index 000000000000..17b043d19b0f --- /dev/null +++ b/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/_index.ja.md @@ -0,0 +1,47 @@ +--- +title: "Chrome DevTools" +linkTitle: "Chrome DevTools" +weight: 2 +aliases: [ +"/documentation/ja/support_packages/chrome_devtools/", +"/ja/documentation/support_packages/chrome_devtools/" +] +--- + +Many browsers provide "DevTools" -- a set of tools that are integrated with the browser that +developers can use to debug web apps and explore the performance of their pages. Google Chrome's +DevTools make use of a protocol called the Chrome DevTools Protocol (or "CDP" for short). +As the name suggests, this is not designed for testing, nor to have a stable API, so functionality +is highly dependent on the version of the browser. + +The [WebDriver BiDirectional Protocol](https://w3c.github.io/webdriver-bidi/) is the next generation of the +W3C WebDriver protocol and aims to provide a stable API implemented by all browsers, but it's not yet complete. +Until it is, Selenium provides access to +the CDP for those browsers that implement it (such as Google Chrome, or Microsoft Edge, and +Firefox), allowing you to enhance your tests in interesting ways. Some examples of what you can +do with it are given below. + +### Ways to Use Chrome DevTools With Selenium +There are three different ways to access Chrome DevTools in Selenium. If you look for other examples online, +you will likely see each of these mixed and matched. + +* The [CDP Endpoint]({{< ref "cdp_endpoint.md" >}}) was the first option available to users. +It only works for the most simple things (setting state, getting basic information), and you +have to know the "magic strings" for the domain and methods and key value pairs. +For basic requirements, this might be simpler than the other options. These methods are only temporarily supported. +* The [CDP API]({{< ref "cdp_api.md" >}}) is an improvement on just using the endpoint because you can set +do things asynchronously. Instead of a String and a Map, you can access the supported classes, +methods and parameters in the code. These methods are also only temporarily supported. +* The [BiDi API]({{< ref "bidi_api.md" >}}) option should be used whenever possible because it +abstracts away the implementation details entirely and will work with either CDP or WebDriver-BiDi +when Selenium moves away from CDP. + +### Examples With Limited Value + +There are a number of commonly cited examples for using CDP that are of limited practical value. +* **Geo Location** — almost all sites use the IP address to determine physical location, +so setting an emulated geolocation rarely has the desired effect. +* **Overriding Device Metrics** — Chrome provides a great API for setting [Mobile Emulation](https://chromedriver.chromium.org/mobile-emulation) +in the Options classes, which is generally superior to attempting to do this with CDP. + +Check out the examples in these documents for ways to do additional useful things: diff --git a/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/_index.pt-br.md b/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/_index.pt-br.md new file mode 100644 index 000000000000..d9256c366fe6 --- /dev/null +++ b/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/_index.pt-br.md @@ -0,0 +1,47 @@ +--- +title: "Chrome DevTools" +linkTitle: "Chrome DevTools" +weight: 2 +aliases: [ +"/documentation/pt-br/support_packages/chrome_devtools/", +"/pt-br/documentation/support_packages/chrome_devtools/" +] +--- + +Many browsers provide "DevTools" -- a set of tools that are integrated with the browser that +developers can use to debug web apps and explore the performance of their pages. Google Chrome's +DevTools make use of a protocol called the Chrome DevTools Protocol (or "CDP" for short). +As the name suggests, this is not designed for testing, nor to have a stable API, so functionality +is highly dependent on the version of the browser. + +The [WebDriver BiDirectional Protocol](https://w3c.github.io/webdriver-bidi/) is the next generation of the +W3C WebDriver protocol and aims to provide a stable API implemented by all browsers, but it's not yet complete. +Until it is, Selenium provides access to +the CDP for those browsers that implement it (such as Google Chrome, or Microsoft Edge, and +Firefox), allowing you to enhance your tests in interesting ways. Some examples of what you can +do with it are given below. + +### Ways to Use Chrome DevTools With Selenium +There are three different ways to access Chrome DevTools in Selenium. If you look for other examples online, +you will likely see each of these mixed and matched. + +* The [CDP Endpoint]({{< ref "cdp_endpoint.md" >}}) was the first option available to users. +It only works for the most simple things (setting state, getting basic information), and you +have to know the "magic strings" for the domain and methods and key value pairs. +For basic requirements, this might be simpler than the other options. These methods are only temporarily supported. +* The [CDP API]({{< ref "cdp_api.md" >}}) is an improvement on just using the endpoint because you can set +do things asynchronously. Instead of a String and a Map, you can access the supported classes, +methods and parameters in the code. These methods are also only temporarily supported. +* The [BiDi API]({{< ref "bidi_api.md" >}}) option should be used whenever possible because it +abstracts away the implementation details entirely and will work with either CDP or WebDriver-BiDi +when Selenium moves away from CDP. + +### Examples With Limited Value + +There are a number of commonly cited examples for using CDP that are of limited practical value. +* **Geo Location** — almost all sites use the IP address to determine physical location, +so setting an emulated geolocation rarely has the desired effect. +* **Overriding Device Metrics** — Chrome provides a great API for setting [Mobile Emulation](https://chromedriver.chromium.org/mobile-emulation) +in the Options classes, which is generally superior to attempting to do this with CDP. + +Check out the examples in these documents for ways to do additional useful things: diff --git a/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/_index.zh-cn.md b/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/_index.zh-cn.md new file mode 100644 index 000000000000..0ad7b3c715f7 --- /dev/null +++ b/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/_index.zh-cn.md @@ -0,0 +1,47 @@ +--- +title: "Chrome DevTools" +linkTitle: "Chrome DevTools" +weight: 2 +aliases: [ +"/documentation/zh-cn/support_packages/chrome_devtools/", +"/zh-cn/documentation/support_packages/chrome_devtools/" +] +--- + +Many browsers provide "DevTools" -- a set of tools that are integrated with the browser that +developers can use to debug web apps and explore the performance of their pages. Google Chrome's +DevTools make use of a protocol called the Chrome DevTools Protocol (or "CDP" for short). +As the name suggests, this is not designed for testing, nor to have a stable API, so functionality +is highly dependent on the version of the browser. + +The [WebDriver BiDirectional Protocol](https://w3c.github.io/webdriver-bidi/) is the next generation of the +W3C WebDriver protocol and aims to provide a stable API implemented by all browsers, but it's not yet complete. +Until it is, Selenium provides access to +the CDP for those browsers that implement it (such as Google Chrome, or Microsoft Edge, and +Firefox), allowing you to enhance your tests in interesting ways. Some examples of what you can +do with it are given below. + +### Ways to Use Chrome DevTools With Selenium +There are three different ways to access Chrome DevTools in Selenium. If you look for other examples online, +you will likely see each of these mixed and matched. + +* The [CDP Endpoint]({{< ref "cdp_endpoint.md" >}}) was the first option available to users. +It only works for the most simple things (setting state, getting basic information), and you +have to know the "magic strings" for the domain and methods and key value pairs. +For basic requirements, this might be simpler than the other options. These methods are only temporarily supported. +* The [CDP API]({{< ref "cdp_api.md" >}}) is an improvement on just using the endpoint because you can set +do things asynchronously. Instead of a String and a Map, you can access the supported classes, +methods and parameters in the code. These methods are also only temporarily supported. +* The [BiDi API]({{< ref "bidi_api.md" >}}) option should be used whenever possible because it +abstracts away the implementation details entirely and will work with either CDP or WebDriver-BiDi +when Selenium moves away from CDP. + +### Examples With Limited Value + +There are a number of commonly cited examples for using CDP that are of limited practical value. +* **Geo Location** — almost all sites use the IP address to determine physical location, +so setting an emulated geolocation rarely has the desired effect. +* **Overriding Device Metrics** — Chrome provides a great API for setting [Mobile Emulation](https://chromedriver.chromium.org/mobile-emulation) +in the Options classes, which is generally superior to attempting to do this with CDP. + +Check out the examples in these documents for ways to do additional useful things: diff --git a/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/bidi_api.en.md b/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/bidi_api.en.md new file mode 100644 index 000000000000..c30c98d12f4c --- /dev/null +++ b/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/bidi_api.en.md @@ -0,0 +1,359 @@ +--- +title: "Chrome Devtools Protocol with BiDi API" +linkTitle: "BiDi API" +weight: 6 +description: > + These examples are currently implemented with CDP, but the same code should work when the functionality + is re-implemented with WebDriver-BiDi. +--- + +## Usage + +The following list of APIs will be growing as the Selenium +project works through supporting real world use cases. If there +is additional functionality you'd like to see, please raise a +[feature request](https://github.com/SeleniumHQ/selenium/issues/new?assignees=&labels=&template=feature.md). + +As these examples are re-implemented with the [WebDriver-Bidi](https://w3c.github.io/webdriver-bidi) protocol, they will +be moved to the [WebDriver Bidi]({{< ref "../webdriver_bidi/" >}}) pages. + +## Examples + +### Basic authentication + +Some applications make use of browser authentication to secure pages. +It used to be common to handle them in the URL, but browser stopped supporting this. +With BiDi, you can now provide the credentials when necessary + +Alternate implementations can be found at +[CDP Endpoint Basic Authentication]({{< ref "cdp_endpoint#basic-authentication" >}}) +and [CDP API Basic Authentication]({{< ref "cdp_api#basic-authentication" >}}) + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/BidiApiTest.java#L35-L38" >}} +{{% /tab %}} +{{% tab header="Python" %}} +An alternate implementation may be found at +[CDP Endpoint Basic Authentication]({{< ref "cdp_endpoint#basic-authentication" >}}) +{{< badge-implementation >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/BidiApiTest.cs#L18-L27" >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/bidi_api_spec.rb#L9-L11" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-examples >}} +```js +const {Builder} = require('selenium-webdriver'); + +(async function example() { + try { + let driver = await new Builder() + .forBrowser('chrome') + .build(); + + const pageCdpConnection = await driver.createCDPConnection('page'); + await driver.register('username', 'password', pageCdpConnection); + await driver.get('https://the-internet.herokuapp.com/basic_auth'); + await driver.quit(); + }catch (e){ + console.log(e) + } +}()) +``` +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-examples >}} +```java +val uriPredicate = Predicate { uri: URI -> + uri.host.contains("your-domain.com") + } +(driver as HasAuthentication).register(uriPredicate, UsernameAndPassword.of("admin", "password")) +driver.get("https://your-domain.com/login") +``` +{{% /tab %}} +{{< /tabpane >}} + + +### Pin scripts + +This can be especially useful when executing on a remote server. For example, +whenever you check the visibility of an element, or whenever you use +the classic get attribute method, Selenium is sending the contents of a js file +to the script execution endpoint. These files are each about 50kB, which adds up. + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +{{< badge-implementation >}} +{{% /tab %}} +{{% tab header="Python" %}} +{{< badge-implementation >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/BidiApiTest.cs#L41-L43" >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/bidi_api_spec.rb#L22-L23" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-implementation >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} + + +### Mutation observation + +Mutation Observation is the ability to capture events via +WebDriver BiDi when there are DOM mutations on a specific +element in the DOM. + +{{< tabpane text=true langEqualsHeader=true >}} + {{% tab text=true header="Java" %}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/BidiApiTest.java#L64-L65" >}} + {{% /tab %}} + {{% tab header="Python" %}} +{{< gh-codeblock path="/examples/python/tests/bidirectional/chrome_devtools/test_bidi_api.py#L9-L11" >}} + {{% /tab %}} + {{% tab header="CSharp" %}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/BidiApiTest.cs#L59-L68" >}} + {{% /tab %}} + {{< tab header="Ruby" >}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/bidi_api_spec.rb#L31-L32" >}} + {{< /tab >}} + {{% tab header="JavaScript" %}} + {{< badge-examples >}} +```js +const {Builder, until} = require('selenium-webdriver'); +const assert = require("assert"); + +(async function example() { + try { + let driver = await new Builder() + .forBrowser('chrome') + .build(); + + const cdpConnection = await driver.createCDPConnection('page'); + await driver.logMutationEvents(cdpConnection, event => { + assert.deepStrictEqual(event['attribute_name'], 'style'); + assert.deepStrictEqual(event['current_value'], ""); + assert.deepStrictEqual(event['old_value'], "display:none;"); + }); + + await driver.get('dynamic.html'); + await driver.findElement({id: 'reveal'}).click(); + let revealed = driver.findElement({id: 'revealed'}); + await driver.wait(until.elementIsVisible(revealed), 5000); + await driver.quit(); + }catch (e){ + console.log(e) + } +}()) +``` +{{% /tab %}} + {{< tab header="Kotlin" text=true >}} +{{< badge-code >}} + {{< /tab >}} +{{< /tabpane >}} + + +### Console logs and errors + +Listen to the `console.log` events and register callbacks to process the event. + +[CDP API Console logs]({{< ref "cdp_api#console-logs-and-errors" >}}) +and [WebDriver BiDi Console logs]({{< ref "../webdriver_bidi/log#console-logs" >}}) + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +Use the [WebDriver BiDi Console logs]({{< ref "../webdriver_bidi/log#console-logs" >}}) implementation. `HasLogEvents` +will likely end up deprecated because it does not implement `Closeable`. +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/BidiApiTest.java#L77-L78" >}} +{{% /tab %}} +{{% tab header="Python" %}} +{{< gh-codeblock path="/examples/python/tests/bidirectional/chrome_devtools/test_bidi_api.py#L23-L26" >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/BidiApiTest.cs#L85-L92" >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/bidi_api_spec.rb#L43-L44" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-examples >}} +```js +const {Builder} = require('selenium-webdriver'); +(async () => { + try { + let driver = new Builder() + .forBrowser('chrome') + .build(); + + const cdpConnection = await driver.createCDPConnection('page'); + await driver.onLogEvent(cdpConnection, function (event) { + console.log(event['args'][0]['value']); + }); + await driver.executeScript('console.log("here")'); + await driver.quit(); + }catch (e){ + console.log(e); + } +})() +``` +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-examples >}} +```java +fun kotlinConsoleLogExample() { + val driver = ChromeDriver() + val devTools = driver.devTools + devTools.createSession() + + val logConsole = { c: ConsoleEvent -> print("Console log message is: " + c.messages)} + devTools.domains.events().addConsoleListener(logConsole) + + driver.get("https://www.google.com") + + val executor = driver as JavascriptExecutor + executor.executeScript("console.log('Hello World')") + + val input = driver.findElement(By.name("q")) + input.sendKeys("Selenium 4") + input.sendKeys(Keys.RETURN) + driver.quit() +} +``` +{{% /tab %}} +{{< /tabpane >}} + + +### JavaScript exceptions + +Listen to the JS Exceptions +and register callbacks to process the exception details. + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +Use the [WebDriver BiDi JavaScript exceptions]({{< ref "../webdriver_bidi/log#javascript-exceptions" >}}) implementation +{{% /tab %}} +{{% tab header="Python" %}} +{{< gh-codeblock path="/examples/python/tests/bidirectional/chrome_devtools/test_bidi_api.py#L36-L39" >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/BidiApiTest.cs#L107-L114" >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/bidi_api_spec.rb#L57-L58" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-implementation >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} + + +### Network Interception + +Both requests and responses can be recorded or transformed. + +#### Response information + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/BidiApiTest.java#L90-L101" >}} +{{% /tab %}} +{{% tab header="Python" %}} +{{< badge-implementation >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/BidiApiTest.cs#L125-L133" >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/bidi_api_spec.rb#L67-L72" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-implementation >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} + +#### Response transformation + +{{< tabpane text=true langEqualsHeader=true >}} +{{< tab header="Java" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/BidiApiTest.java#L111-L121" >}} +{{< /tab >}} +{{< tab header="Python" >}} +{{< badge-implementation >}} +{{< /tab >}} +{{< tab header="CSharp" text=true >}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/BidiApiTest.cs#L143-L156" >}} +{{< /tab >}} +{{< tab header="Ruby" >}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/bidi_api_spec.rb#L79-L83" >}} +{{< /tab >}} +{{% tab header="JavaScript" %}} +{{< badge-examples >}} +```js +const connection = await driver.createCDPConnection('page') +let url = fileServer.whereIs("/cheese") +let httpResponse = new HttpResponse(url) +httpResponse.addHeaders("Content-Type", "UTF-8") +httpResponse.body = "sausages" +await driver.onIntercept(connection, httpResponse, async function () { + let body = await driver.getPageSource() + assert.strictEqual(body.includes("sausages"), true, `Body contains: ${body}`) +}) +driver.get(url) +``` +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-examples >}} +```java +val driver = ChromeDriver() +val interceptor = new NetworkInterceptor( + driver, + Route.matching(req -> true) + .to(() -> req -> new HttpResponse() + .setStatus(200) + .addHeader("Content-Type", MediaType.HTML_UTF_8.toString()) + .setContent(utf8String("Creamy, delicious cheese!")))) + + driver.get(appServer.whereIs("/cheese")) + + String source = driver.getPageSource() +``` +{{% /tab %}} +{{< /tabpane >}} + +#### Request interception + +{{< tabpane text=true langEqualsHeader=true >}} +{{< tab header="Java" >}} +{{< badge-implementation >}} +{{< /tab >}} +{{< tab header="Python" >}} +{{< badge-implementation >}} +{{< /tab >}} +{{< tab header="CSharp" >}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/BidiApiTest.cs#L167-L181" >}} +{{< /tab >}} +{{< tab header="Ruby" >}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/bidi_api_spec.rb#L90-L94" >}} +{{< /tab >}} +{{< tab header="JavaScript" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="Kotlin" >}} +{{< badge-code >}} +{{< /tab >}} +{{< /tabpane >}} diff --git a/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/bidi_api.ja.md b/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/bidi_api.ja.md new file mode 100644 index 000000000000..90bcd55f8f74 --- /dev/null +++ b/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/bidi_api.ja.md @@ -0,0 +1,361 @@ +--- +title: "Chrome Devtools Protocol with BiDi API" +linkTitle: "BiDi API" +weight: 6 +description: > + These examples are currently implemented with CDP, but the same code should work when the functionality + is re-implemented with WebDriver-BiDi. +--- + +## Usage + +The following list of APIs will be growing as the Selenium +project works through supporting real world use cases. If there +is additional functionality you'd like to see, please raise a +[feature request](https://github.com/SeleniumHQ/selenium/issues/new?assignees=&labels=&template=feature.md). + +As these examples are re-implemented with the [WebDriver-Bidi](https://w3c.github.io/webdriver-bidi) protocol, they will +be moved to the [WebDriver Bidi]({{< ref "../webdriver_bidi/" >}}) pages. + +## Examples + +### Basic authentication + +Some applications make use of browser authentication to secure pages. +It used to be common to handle them in the URL, but browser stopped supporting this. +With BiDi, you can now provide the credentials when necessary + +Alternate implementations can be found at +[CDP Endpoint Basic Authentication]({{< ref "cdp_endpoint#basic-authentication" >}}) +and [CDP API Basic Authentication]({{< ref "cdp_api#basic-authentication" >}}) + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/BidiApiTest.java#L35-L38" >}} +{{% /tab %}} +{{% tab header="Python" %}} +An alternate implementation may be found at +[CDP Endpoint Basic Authentication]({{< ref "cdp_endpoint#basic-authentication" >}}) +{{< badge-implementation >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/BidiApiTest.cs#L18-L27" >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/bidi_api_spec.rb#L9-L11" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-examples >}} + +```js +const {Builder} = require('selenium-webdriver'); + +(async function example() { + try { + let driver = await new Builder() + .forBrowser('chrome') + .build(); + + const pageCdpConnection = await driver.createCDPConnection('page'); + await driver.register('username', 'password', pageCdpConnection); + await driver.get('https://the-internet.herokuapp.com/basic_auth'); + await driver.quit(); + }catch (e){ + console.log(e) + } +}()) +``` +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-examples >}} + +```java +val uriPredicate = Predicate { uri: URI -> + uri.host.contains("your-domain.com") + } +(driver as HasAuthentication).register(uriPredicate, UsernameAndPassword.of("admin", "password")) +driver.get("https://your-domain.com/login") +``` +{{% /tab %}} +{{< /tabpane >}} + + +### Pin scripts + +This can be especially useful when executing on a remote server. For example, +whenever you check the visibility of an element, or whenever you use +the classic get attribute method, Selenium is sending the contents of a js file +to the script execution endpoint. These files are each about 50kB, which adds up. + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +{{< badge-implementation >}} +{{% /tab %}} +{{% tab header="Python" %}} +{{< badge-implementation >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/BidiApiTest.cs#L41-L43" >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/bidi_api_spec.rb#L22-L23" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-implementation >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} + + +### Mutation observation + +Mutation Observation is the ability to capture events via +WebDriver BiDi when there are DOM mutations on a specific +element in the DOM. + +{{< tabpane text=true langEqualsHeader=true >}} + {{% tab text=true header="Java" %}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/BidiApiTest.java#L64-L65" >}} + {{% /tab %}} + {{% tab header="Python" %}} +{{< gh-codeblock path="/examples/python/tests/bidirectional/chrome_devtools/test_bidi_api.py#L9-L11" >}} + {{% /tab %}} + {{% tab header="CSharp" %}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/BidiApiTest.cs#L59-L68" >}} + {{% /tab %}} + {{< tab header="Ruby" >}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/bidi_api_spec.rb#L31-L32" >}} + {{< /tab >}} + {{% tab header="JavaScript" %}} + {{< badge-examples >}} +```js +const {Builder, until} = require('selenium-webdriver'); +const assert = require("assert"); + +(async function example() { + try { + let driver = await new Builder() + .forBrowser('chrome') + .build(); + + const cdpConnection = await driver.createCDPConnection('page'); + await driver.logMutationEvents(cdpConnection, event => { + assert.deepStrictEqual(event['attribute_name'], 'style'); + assert.deepStrictEqual(event['current_value'], ""); + assert.deepStrictEqual(event['old_value'], "display:none;"); + }); + + await driver.get('dynamic.html'); + await driver.findElement({id: 'reveal'}).click(); + let revealed = driver.findElement({id: 'revealed'}); + await driver.wait(until.elementIsVisible(revealed), 5000); + await driver.quit(); + }catch (e){ + console.log(e) + } +}()) +``` +{{% /tab %}} + {{< tab header="Kotlin" text=true >}} +{{< badge-code >}} + {{< /tab >}} +{{< /tabpane >}} + + +### Console logs and errors + +Listen to the `console.log` events and register callbacks to process the event. + +[CDP API Console logs]({{< ref "cdp_api#console-logs-and-errors" >}}) +and [WebDriver BiDi Console logs]({{< ref "../webdriver_bidi/log#console-logs" >}}) + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +Use the [WebDriver BiDi Console logs]({{< ref "../webdriver_bidi/log#console-logs" >}}) implementation. `HasLogEvents` +will likely end up deprecated because it does not implement `Closeable`. +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/BidiApiTest.java#L77-L78" >}} +{{% /tab %}} +{{% tab header="Python" %}} +{{< gh-codeblock path="/examples/python/tests/bidirectional/chrome_devtools/test_bidi_api.py#L23-L26" >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/BidiApiTest.cs#L85-L92" >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/bidi_api_spec.rb#L43-L44" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-examples >}} +```js +const {Builder} = require('selenium-webdriver'); +(async () => { + try { + let driver = new Builder() + .forBrowser('chrome') + .build(); + + const cdpConnection = await driver.createCDPConnection('page'); + await driver.onLogEvent(cdpConnection, function (event) { + console.log(event['args'][0]['value']); + }); + await driver.executeScript('console.log("here")'); + await driver.quit(); + }catch (e){ + console.log(e); + } +})() +``` +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-examples >}} +```java +fun kotlinConsoleLogExample() { + val driver = ChromeDriver() + val devTools = driver.devTools + devTools.createSession() + + val logConsole = { c: ConsoleEvent -> print("Console log message is: " + c.messages)} + devTools.domains.events().addConsoleListener(logConsole) + + driver.get("https://www.google.com") + + val executor = driver as JavascriptExecutor + executor.executeScript("console.log('Hello World')") + + val input = driver.findElement(By.name("q")) + input.sendKeys("Selenium 4") + input.sendKeys(Keys.RETURN) + driver.quit() +} +``` +{{% /tab %}} +{{< /tabpane >}} + + +### JavaScript exceptions + +Listen to the JS Exceptions +and register callbacks to process the exception details. + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +Use the [WebDriver BiDi JavaScript exceptions]({{< ref "../webdriver_bidi/log#javascript-exceptions" >}}) implementation +{{% /tab %}} +{{% tab header="Python" %}} +{{< gh-codeblock path="/examples/python/tests/bidirectional/chrome_devtools/test_bidi_api.py#L36-L39" >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/BidiApiTest.cs#L107-L114" >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/bidi_api_spec.rb#L57-L58" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-implementation >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} + + +### Network Interception + +Both requests and responses can be recorded or transformed. + +#### Response information + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/BidiApiTest.java#L90-L101" >}} +{{% /tab %}} +{{% tab header="Python" %}} +{{< badge-implementation >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/BidiApiTest.cs#L125-L133" >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/bidi_api_spec.rb#L67-L72" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-implementation >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} + +#### Response transformation + +{{< tabpane text=true langEqualsHeader=true >}} +{{< tab header="Java" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/BidiApiTest.java#L111-L121" >}} +{{< /tab >}} +{{< tab header="Python" >}} +{{< badge-implementation >}} +{{< /tab >}} +{{< tab header="CSharp" text=true >}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/BidiApiTest.cs#L143-L156" >}} +{{< /tab >}} +{{< tab header="Ruby" >}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/bidi_api_spec.rb#L79-L83" >}} +{{< /tab >}} +{{% tab header="JavaScript" %}} +{{< badge-examples >}} +```js +const connection = await driver.createCDPConnection('page') +let url = fileServer.whereIs("/cheese") +let httpResponse = new HttpResponse(url) +httpResponse.addHeaders("Content-Type", "UTF-8") +httpResponse.body = "sausages" +await driver.onIntercept(connection, httpResponse, async function () { + let body = await driver.getPageSource() + assert.strictEqual(body.includes("sausages"), true, `Body contains: ${body}`) +}) +driver.get(url) +``` +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-examples >}} +```java +val driver = ChromeDriver() +val interceptor = new NetworkInterceptor( + driver, + Route.matching(req -> true) + .to(() -> req -> new HttpResponse() + .setStatus(200) + .addHeader("Content-Type", MediaType.HTML_UTF_8.toString()) + .setContent(utf8String("Creamy, delicious cheese!")))) + + driver.get(appServer.whereIs("/cheese")) + + String source = driver.getPageSource() +``` +{{% /tab %}} +{{< /tabpane >}} + +#### Request interception + +{{< tabpane text=true langEqualsHeader=true >}} +{{< tab header="Java" >}} +{{< badge-implementation >}} +{{< /tab >}} +{{< tab header="Python" >}} +{{< badge-implementation >}} +{{< /tab >}} +{{< tab header="CSharp" >}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/BidiApiTest.cs#L167-L181" >}} +{{< /tab >}} +{{< tab header="Ruby" >}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/bidi_api_spec.rb#L90-L94" >}} +{{< /tab >}} +{{< tab header="JavaScript" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="Kotlin" >}} +{{< badge-code >}} +{{< /tab >}} +{{< /tabpane >}} diff --git a/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/bidi_api.pt-br.md b/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/bidi_api.pt-br.md new file mode 100644 index 000000000000..48531e6a3fc5 --- /dev/null +++ b/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/bidi_api.pt-br.md @@ -0,0 +1,350 @@ +--- +title: "Chrome Devtools Protocol with BiDi API" +linkTitle: "BiDi API" +weight: 6 +description: > + These examples are currently implemented with CDP, but the same code should work when the functionality + is re-implemented with WebDriver-BiDi. +--- + +## Usage + +A seguinte lista de APIs crescerá à medida que o projeto Selenium se prepara +para suportar casos de uso do mundo real. Se houver funcionalidades adicionais que você gostaria de ver, por favor, levante uma [solicitação de recurso](https://github.com/SeleniumHQ/selenium/issues/new?assignees=&labels=&template=feature.md). + +As these examples are re-implemented with the [WebDriver-Bidi](https://w3c.github.io/webdriver-bidi) protocol, they will +be moved to the [WebDriver Bidi]({{< ref "../webdriver_bidi/" >}}) pages. + +## Examples + +### Basic authentication + +Alguns aplicativos fazem o uso da autenticação do navegador para proteger suas páginas. Com o Selenium, você pode automatizar a entrada de credenciais básicas de autenticação sempre que for necessário. + +Alternate implementations can be found at +[CDP Endpoint Basic Authentication]({{< ref "cdp_endpoint#basic-authentication" >}}) +and [CDP API Basic Authentication]({{< ref "cdp_api#basic-authentication" >}}) + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/BidiApiTest.java#L35-L38" >}} +{{% /tab %}} +{{% tab header="Python" %}} +An alternate implementation may be found at +[CDP Endpoint Basic Authentication]({{< ref "cdp_endpoint#basic-authentication" >}}) +{{< badge-implementation >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/BidiApiTest.cs#L18-L27" >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/bidi_api_spec.rb#L9-L11" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-examples >}} +```js +const {Builder} = require('selenium-webdriver'); + +(async function example() { + try { + let driver = await new Builder() + .forBrowser('chrome') + .build(); + + const pageCdpConnection = await driver.createCDPConnection('page'); + await driver.register('username', 'password', pageCdpConnection); + await driver.get('https://the-internet.herokuapp.com/basic_auth'); + await driver.quit(); + }catch (e){ + console.log(e) + } +}()) +``` +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-examples >}} +```java +val uriPredicate = Predicate { uri: URI -> + uri.host.contains("your-domain.com") + } +(driver as HasAuthentication).register(uriPredicate, UsernameAndPassword.of("admin", "password")) +driver.get("https://your-domain.com/login") +``` +{{% /tab %}} +{{< /tabpane >}} + + +### Pin scripts +This can be especially useful when executing on a remote server. For example, +whenever you check the visibility of an element, or whenever you use +the classic get attribute method, Selenium is sending the contents of a js file +to the script execution endpoint. These files are each about 50kB, which adds up. + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +{{< badge-implementation >}} +{{% /tab %}} +{{% tab header="Python" %}} +{{< badge-implementation >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/BidiApiTest.cs#L41-L43" >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/bidi_api_spec.rb#L22-L23" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-implementation >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} + + +### Mutation observation + +Mutation Observation(Observação de Mutação) é a capacidade de capturar eventos via WebDriver BiDi quando há mutações DOM em um elemento específico no DOM. + +{{< tabpane text=true langEqualsHeader=true >}} + {{% tab text=true header="Java" %}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/BidiApiTest.java#L64-L65" >}} + {{% /tab %}} + {{% tab header="Python" %}} +{{< gh-codeblock path="/examples/python/tests/bidirectional/chrome_devtools/test_bidi_api.py#L9-L11" >}} + {{% /tab %}} + {{% tab header="CSharp" %}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/BidiApiTest.cs#L59-L68" >}} + {{% /tab %}} + {{< tab header="Ruby" >}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/bidi_api_spec.rb#L31-L32" >}} + {{< /tab >}} + {{% tab header="JavaScript" %}} + {{< badge-examples >}} +```js +const {Builder, until} = require('selenium-webdriver'); +const assert = require("assert"); + +(async function example() { + try { + let driver = await new Builder() + .forBrowser('chrome') + .build(); + + const cdpConnection = await driver.createCDPConnection('page'); + await driver.logMutationEvents(cdpConnection, event => { + assert.deepStrictEqual(event['attribute_name'], 'style'); + assert.deepStrictEqual(event['current_value'], ""); + assert.deepStrictEqual(event['old_value'], "display:none;"); + }); + + await driver.get('dynamic.html'); + await driver.findElement({id: 'reveal'}).click(); + let revealed = driver.findElement({id: 'revealed'}); + await driver.wait(until.elementIsVisible(revealed), 5000); + await driver.quit(); + }catch (e){ + console.log(e) + } +}()) +``` +{{% /tab %}} + {{< tab header="Kotlin" text=true >}} +{{< badge-code >}} + {{< /tab >}} +{{< /tabpane >}} + + +### Console logs and errors +Vigie os eventos `console.log` e registre os callbacks(retornos de chamada) para processar o evento. + +[CDP API Console logs]({{< ref "cdp_api#console-logs-and-errors" >}}) +and [WebDriver BiDi Console logs]({{< ref "../webdriver_bidi/log#console-logs" >}}) + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +Use the [WebDriver BiDi Console logs]({{< ref "../webdriver_bidi/log#console-logs" >}}) implementation. `HasLogEvents` +will likely end up deprecated because it does not implement `Closeable`. +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/BidiApiTest.java#L77-L78" >}} +{{% /tab %}} +{{% tab header="Python" %}} +{{< gh-codeblock path="/examples/python/tests/bidirectional/chrome_devtools/test_bidi_api.py#L23-L26" >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/BidiApiTest.cs#L85-L92" >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/bidi_api_spec.rb#L43-L44" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-examples >}} +```js +const {Builder} = require('selenium-webdriver'); +(async () => { + try { + let driver = new Builder() + .forBrowser('chrome') + .build(); + + const cdpConnection = await driver.createCDPConnection('page'); + await driver.onLogEvent(cdpConnection, function (event) { + console.log(event['args'][0]['value']); + }); + await driver.executeScript('console.log("here")'); + await driver.quit(); + }catch (e){ + console.log(e); + } +})() +``` +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-examples >}} +```java +fun kotlinConsoleLogExample() { + val driver = ChromeDriver() + val devTools = driver.devTools + devTools.createSession() + + val logConsole = { c: ConsoleEvent -> print("Console log message is: " + c.messages)} + devTools.domains.events().addConsoleListener(logConsole) + + driver.get("https://www.google.com") + + val executor = driver as JavascriptExecutor + executor.executeScript("console.log('Hello World')") + + val input = driver.findElement(By.name("q")) + input.sendKeys("Selenium 4") + input.sendKeys(Keys.RETURN) + driver.quit() +} +``` +{{% /tab %}} +{{< /tabpane >}} + +### JavaScript exceptions + +Vigie as exceções JS +e registre callbacks(retornos de chamada) para processar os detalhes da exceção. + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +Use the [WebDriver BiDi JavaScript exceptions]({{< ref "../webdriver_bidi/log#javascript-exceptions" >}}) implementation +{{% /tab %}} +{{% tab header="Python" %}} +{{< gh-codeblock path="/examples/python/tests/bidirectional/chrome_devtools/test_bidi_api.py#L36-L39" >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/BidiApiTest.cs#L107-L114" >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/bidi_api_spec.rb#L57-L58" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-implementation >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} + + +### Interceptação de Rede + +Both requests and responses can be recorded or transformed. + +#### Response information + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/BidiApiTest.java#L90-L101" >}} +{{% /tab %}} +{{% tab header="Python" %}} +{{< badge-implementation >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/BidiApiTest.cs#L125-L133" >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/bidi_api_spec.rb#L67-L72" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-implementation >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} + +#### Response transformation + +{{< tabpane text=true langEqualsHeader=true >}} +{{< tab header="Java" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/BidiApiTest.java#L111-L121" >}} +{{< /tab >}} +{{< tab header="Python" >}} +{{< badge-implementation >}} +{{< /tab >}} +{{< tab header="CSharp" text=true >}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/BidiApiTest.cs#L143-L156" >}} +{{< /tab >}} +{{< tab header="Ruby" >}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/bidi_api_spec.rb#L79-L83" >}} +{{< /tab >}} +{{% tab header="JavaScript" %}} +{{< badge-examples >}} +```js +const connection = await driver.createCDPConnection('page') +let url = fileServer.whereIs("/cheese") +let httpResponse = new HttpResponse(url) +httpResponse.addHeaders("Content-Type", "UTF-8") +httpResponse.body = "sausages" +await driver.onIntercept(connection, httpResponse, async function () { + let body = await driver.getPageSource() + assert.strictEqual(body.includes("sausages"), true, `Body contains: ${body}`) +}) +driver.get(url) +``` +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-examples >}} +```java +val driver = ChromeDriver() +val interceptor = new NetworkInterceptor( + driver, + Route.matching(req -> true) + .to(() -> req -> new HttpResponse() + .setStatus(200) + .addHeader("Content-Type", MediaType.HTML_UTF_8.toString()) + .setContent(utf8String("Creamy, delicious cheese!")))) + + driver.get(appServer.whereIs("/cheese")) + + String source = driver.getPageSource() +``` +{{% /tab %}} +{{< /tabpane >}} + +#### Request interception + +{{< tabpane text=true langEqualsHeader=true >}} +{{< tab header="Java" >}} +{{< badge-implementation >}} +{{< /tab >}} +{{< tab header="Python" >}} +{{< badge-implementation >}} +{{< /tab >}} +{{< tab header="CSharp" >}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/BidiApiTest.cs#L167-L181" >}} +{{< /tab >}} +{{< tab header="Ruby" >}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/bidi_api_spec.rb#L90-L94" >}} +{{< /tab >}} +{{< tab header="JavaScript" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="Kotlin" >}} +{{< badge-code >}} +{{< /tab >}} +{{< /tabpane >}} diff --git a/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/bidi_api.zh-cn.md b/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/bidi_api.zh-cn.md new file mode 100644 index 000000000000..c30c98d12f4c --- /dev/null +++ b/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/bidi_api.zh-cn.md @@ -0,0 +1,359 @@ +--- +title: "Chrome Devtools Protocol with BiDi API" +linkTitle: "BiDi API" +weight: 6 +description: > + These examples are currently implemented with CDP, but the same code should work when the functionality + is re-implemented with WebDriver-BiDi. +--- + +## Usage + +The following list of APIs will be growing as the Selenium +project works through supporting real world use cases. If there +is additional functionality you'd like to see, please raise a +[feature request](https://github.com/SeleniumHQ/selenium/issues/new?assignees=&labels=&template=feature.md). + +As these examples are re-implemented with the [WebDriver-Bidi](https://w3c.github.io/webdriver-bidi) protocol, they will +be moved to the [WebDriver Bidi]({{< ref "../webdriver_bidi/" >}}) pages. + +## Examples + +### Basic authentication + +Some applications make use of browser authentication to secure pages. +It used to be common to handle them in the URL, but browser stopped supporting this. +With BiDi, you can now provide the credentials when necessary + +Alternate implementations can be found at +[CDP Endpoint Basic Authentication]({{< ref "cdp_endpoint#basic-authentication" >}}) +and [CDP API Basic Authentication]({{< ref "cdp_api#basic-authentication" >}}) + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/BidiApiTest.java#L35-L38" >}} +{{% /tab %}} +{{% tab header="Python" %}} +An alternate implementation may be found at +[CDP Endpoint Basic Authentication]({{< ref "cdp_endpoint#basic-authentication" >}}) +{{< badge-implementation >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/BidiApiTest.cs#L18-L27" >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/bidi_api_spec.rb#L9-L11" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-examples >}} +```js +const {Builder} = require('selenium-webdriver'); + +(async function example() { + try { + let driver = await new Builder() + .forBrowser('chrome') + .build(); + + const pageCdpConnection = await driver.createCDPConnection('page'); + await driver.register('username', 'password', pageCdpConnection); + await driver.get('https://the-internet.herokuapp.com/basic_auth'); + await driver.quit(); + }catch (e){ + console.log(e) + } +}()) +``` +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-examples >}} +```java +val uriPredicate = Predicate { uri: URI -> + uri.host.contains("your-domain.com") + } +(driver as HasAuthentication).register(uriPredicate, UsernameAndPassword.of("admin", "password")) +driver.get("https://your-domain.com/login") +``` +{{% /tab %}} +{{< /tabpane >}} + + +### Pin scripts + +This can be especially useful when executing on a remote server. For example, +whenever you check the visibility of an element, or whenever you use +the classic get attribute method, Selenium is sending the contents of a js file +to the script execution endpoint. These files are each about 50kB, which adds up. + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +{{< badge-implementation >}} +{{% /tab %}} +{{% tab header="Python" %}} +{{< badge-implementation >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/BidiApiTest.cs#L41-L43" >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/bidi_api_spec.rb#L22-L23" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-implementation >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} + + +### Mutation observation + +Mutation Observation is the ability to capture events via +WebDriver BiDi when there are DOM mutations on a specific +element in the DOM. + +{{< tabpane text=true langEqualsHeader=true >}} + {{% tab text=true header="Java" %}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/BidiApiTest.java#L64-L65" >}} + {{% /tab %}} + {{% tab header="Python" %}} +{{< gh-codeblock path="/examples/python/tests/bidirectional/chrome_devtools/test_bidi_api.py#L9-L11" >}} + {{% /tab %}} + {{% tab header="CSharp" %}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/BidiApiTest.cs#L59-L68" >}} + {{% /tab %}} + {{< tab header="Ruby" >}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/bidi_api_spec.rb#L31-L32" >}} + {{< /tab >}} + {{% tab header="JavaScript" %}} + {{< badge-examples >}} +```js +const {Builder, until} = require('selenium-webdriver'); +const assert = require("assert"); + +(async function example() { + try { + let driver = await new Builder() + .forBrowser('chrome') + .build(); + + const cdpConnection = await driver.createCDPConnection('page'); + await driver.logMutationEvents(cdpConnection, event => { + assert.deepStrictEqual(event['attribute_name'], 'style'); + assert.deepStrictEqual(event['current_value'], ""); + assert.deepStrictEqual(event['old_value'], "display:none;"); + }); + + await driver.get('dynamic.html'); + await driver.findElement({id: 'reveal'}).click(); + let revealed = driver.findElement({id: 'revealed'}); + await driver.wait(until.elementIsVisible(revealed), 5000); + await driver.quit(); + }catch (e){ + console.log(e) + } +}()) +``` +{{% /tab %}} + {{< tab header="Kotlin" text=true >}} +{{< badge-code >}} + {{< /tab >}} +{{< /tabpane >}} + + +### Console logs and errors + +Listen to the `console.log` events and register callbacks to process the event. + +[CDP API Console logs]({{< ref "cdp_api#console-logs-and-errors" >}}) +and [WebDriver BiDi Console logs]({{< ref "../webdriver_bidi/log#console-logs" >}}) + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +Use the [WebDriver BiDi Console logs]({{< ref "../webdriver_bidi/log#console-logs" >}}) implementation. `HasLogEvents` +will likely end up deprecated because it does not implement `Closeable`. +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/BidiApiTest.java#L77-L78" >}} +{{% /tab %}} +{{% tab header="Python" %}} +{{< gh-codeblock path="/examples/python/tests/bidirectional/chrome_devtools/test_bidi_api.py#L23-L26" >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/BidiApiTest.cs#L85-L92" >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/bidi_api_spec.rb#L43-L44" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-examples >}} +```js +const {Builder} = require('selenium-webdriver'); +(async () => { + try { + let driver = new Builder() + .forBrowser('chrome') + .build(); + + const cdpConnection = await driver.createCDPConnection('page'); + await driver.onLogEvent(cdpConnection, function (event) { + console.log(event['args'][0]['value']); + }); + await driver.executeScript('console.log("here")'); + await driver.quit(); + }catch (e){ + console.log(e); + } +})() +``` +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-examples >}} +```java +fun kotlinConsoleLogExample() { + val driver = ChromeDriver() + val devTools = driver.devTools + devTools.createSession() + + val logConsole = { c: ConsoleEvent -> print("Console log message is: " + c.messages)} + devTools.domains.events().addConsoleListener(logConsole) + + driver.get("https://www.google.com") + + val executor = driver as JavascriptExecutor + executor.executeScript("console.log('Hello World')") + + val input = driver.findElement(By.name("q")) + input.sendKeys("Selenium 4") + input.sendKeys(Keys.RETURN) + driver.quit() +} +``` +{{% /tab %}} +{{< /tabpane >}} + + +### JavaScript exceptions + +Listen to the JS Exceptions +and register callbacks to process the exception details. + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +Use the [WebDriver BiDi JavaScript exceptions]({{< ref "../webdriver_bidi/log#javascript-exceptions" >}}) implementation +{{% /tab %}} +{{% tab header="Python" %}} +{{< gh-codeblock path="/examples/python/tests/bidirectional/chrome_devtools/test_bidi_api.py#L36-L39" >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/BidiApiTest.cs#L107-L114" >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/bidi_api_spec.rb#L57-L58" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-implementation >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} + + +### Network Interception + +Both requests and responses can be recorded or transformed. + +#### Response information + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/BidiApiTest.java#L90-L101" >}} +{{% /tab %}} +{{% tab header="Python" %}} +{{< badge-implementation >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/BidiApiTest.cs#L125-L133" >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/bidi_api_spec.rb#L67-L72" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-implementation >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} + +#### Response transformation + +{{< tabpane text=true langEqualsHeader=true >}} +{{< tab header="Java" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/BidiApiTest.java#L111-L121" >}} +{{< /tab >}} +{{< tab header="Python" >}} +{{< badge-implementation >}} +{{< /tab >}} +{{< tab header="CSharp" text=true >}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/BidiApiTest.cs#L143-L156" >}} +{{< /tab >}} +{{< tab header="Ruby" >}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/bidi_api_spec.rb#L79-L83" >}} +{{< /tab >}} +{{% tab header="JavaScript" %}} +{{< badge-examples >}} +```js +const connection = await driver.createCDPConnection('page') +let url = fileServer.whereIs("/cheese") +let httpResponse = new HttpResponse(url) +httpResponse.addHeaders("Content-Type", "UTF-8") +httpResponse.body = "sausages" +await driver.onIntercept(connection, httpResponse, async function () { + let body = await driver.getPageSource() + assert.strictEqual(body.includes("sausages"), true, `Body contains: ${body}`) +}) +driver.get(url) +``` +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-examples >}} +```java +val driver = ChromeDriver() +val interceptor = new NetworkInterceptor( + driver, + Route.matching(req -> true) + .to(() -> req -> new HttpResponse() + .setStatus(200) + .addHeader("Content-Type", MediaType.HTML_UTF_8.toString()) + .setContent(utf8String("Creamy, delicious cheese!")))) + + driver.get(appServer.whereIs("/cheese")) + + String source = driver.getPageSource() +``` +{{% /tab %}} +{{< /tabpane >}} + +#### Request interception + +{{< tabpane text=true langEqualsHeader=true >}} +{{< tab header="Java" >}} +{{< badge-implementation >}} +{{< /tab >}} +{{< tab header="Python" >}} +{{< badge-implementation >}} +{{< /tab >}} +{{< tab header="CSharp" >}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/BidiApiTest.cs#L167-L181" >}} +{{< /tab >}} +{{< tab header="Ruby" >}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/bidi_api_spec.rb#L90-L94" >}} +{{< /tab >}} +{{< tab header="JavaScript" >}} +{{< badge-code >}} +{{< /tab >}} +{{< tab header="Kotlin" >}} +{{< badge-code >}} +{{< /tab >}} +{{< /tabpane >}} diff --git a/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/cdp_api.en.md b/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/cdp_api.en.md new file mode 100644 index 000000000000..b8e85ed12d53 --- /dev/null +++ b/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/cdp_api.en.md @@ -0,0 +1,208 @@ +--- +title: "Chrome DevTools Protocol API" +linkTitle: "CDP API" +weight: 4 +description: > + Each of the Selenium bindings dynamically generates classes and methods for the various CDP domains and features; + these are tied to specific versions of Chrome. +--- + +{{% pageinfo color="warning" %}} +While Selenium 4 provides direct access to the Chrome DevTools Protocol (CDP), these +methods will eventually be removed. It is recommended to use the [WebDriver Bidi APIs]({{< ref "bidi_api.md" >}}) +methods where possible to ensure future compatibility. +{{% /pageinfo %}} + +## Usage + +If your use case has been implemented by [WebDriver Bidi]({{< ref "../webdriver_bidi/" >}}) or +the [BiDi API]({{< ref "bidi_api.md" >}}), you should use those implementations instead of this one. +Generally you should prefer this approach over executing with the [CDP Endpoint]({{< ref "cdp_endpoint.md" >}}), +especially in Ruby. + + +## Examples + +### Set Cookie + +An alternate implementation can be found at [CDP Endpoint Set Cookie]({{< ref "cdp_endpoint#set-cookie" >}}) + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +Because Java requires using all the parameters example, the Map approach used in +[CDP Endpoint Set Cookie]({{< ref "cdp_endpoint#set-cookie" >}}) might be more simple. +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/CdpApiTest.java#L39-L57" >}} +{{% /tab %}} +{{% tab header="Python" %}} +Because Python requires using async methods for this example, the synchronous approach found in +[CDP Endpoint Set Cookie]({{< ref "cdp_endpoint#set-cookie" >}}) might be easier. +{{< gh-codeblock path="/examples/python/tests/bidirectional/chrome_devtools/test_cdp_api.py#L10-L18" >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +Due to the added complexity in .NET of obtaining the domains and executing with awaits, the +[CDP Endpoint Set Cookie]({{< ref "cdp_endpoint#set-cookie" >}}) might be easier. +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/CdpApiTest.cs#L25-L37" >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/cdp_api_spec.rb#L9-L12" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} + +### Performance Metrics + +An alternate implementation can be found at [CDP Endpoint Performance Metrics]({{< ref "cdp_endpoint#performance-metrics" >}}) + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/CdpApiTest.java#L68-L72" >}} +{{% /tab %}} +{{% tab header="Python" %}} +Because Python requires using async methods for this example, the synchronous approach found in +[CDP Endpoint Performance Metrics]({{< ref "cdp_endpoint#performance-metrics" >}}) might be easier. +{{< gh-codeblock path="/examples/python/tests/bidirectional/chrome_devtools/test_cdp_api.py#L30-L33" >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +Due to the added complexity in .NET of obtaining the domains and executing with awaits, the +[CDP Endpoint Performance Metrics]({{< ref "cdp_endpoint#performance-metrics" >}}) might be easier. +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/CdpApiTest.cs#L49-L56" >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/cdp_api_spec.rb#L23-L25" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} + +### Basic authentication + +Alternate implementations can be found at +[CDP Endpoint Basic Authentication]({{< ref "cdp_endpoint#basic-authentication" >}}) +and [BiDi API Basic Authentication]({{< ref "bidi_api#basic-authentication" >}}) + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +The [BiDi API Basic Authentication]({{< ref "bidi_api#basic-authentication" >}}) implementation should be preferred +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/CdpApiTest.java#L85-L92" >}} +{{% /tab %}} +{{% tab header="Python" %}} +Because Python requires using async methods for this example, the synchronous approach found in +[CDP Endpoint Basic Authentication]({{< ref "cdp_endpoint#basic-authentication" >}}) might be easier. +{{< gh-codeblock path="/examples/python/tests/bidirectional/chrome_devtools/test_cdp_api.py#L43-L49" >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +Due to the added complexity in .NET of obtaining the domains and executing with awaits, the +[CDP Endpoint Basic Authentication]({{< ref "cdp_endpoint#basic-authentication" >}}) might be easier. +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/CdpApiTest.cs#L70-L83" >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +The [BiDi API Basic Authentication]({{< ref "bidi_api#basic-authentication" >}}) implementation should be preferred +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/cdp_api_spec.rb#L36-L40" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} + +### Console logs + +Because reading console logs requires setting an event listener, +this cannot be done with a CDP Endpoint implementation +Alternate implementations can be found at +[BiDi API Console logs and errors]({{< ref "bidi_api#console-logs-and-errors" >}}) +and [WebDriver BiDi Console logs]({{< ref "../webdriver_bidi/log#console-logs" >}}) + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +Use the [WebDriver BiDi Console logs]({{< ref "../webdriver_bidi/log#console-logs" >}}) implementation +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/CdpApiTest.java#L105-L112" >}} +{{% /tab %}} +{{% tab header="Python" %}} +Use the [BiDi API Console logs and errors]({{< ref "bidi_api#console-logs-and-errors" >}}) implementation +{{< badge-code >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +Use the [BiDi API Console logs and errors]({{< ref "bidi_api#console-logs-and-errors" >}}) implementation +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +The [BiDi API Console logs and errors]({{< ref "bidi_api#console-logs-and-errors" >}}) implementation should be preferred +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/cdp_api_spec.rb#L50-L55" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} + +### JavaScript exceptions + +Similar to console logs, but this listens for actual javascript exceptions not just logged errors +Alternate implementations can be found at +[BiDi API JavaScript exceptions]({{< ref "bidi_api#javascript-exceptions" >}}) +and [WebDriver BiDi JavaScript exceptions]({{< ref "../webdriver_bidi/log#javascript-exceptions" >}}) + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +Use the [WebDriver BiDi JavaScript exceptions]({{< ref "../webdriver_bidi/log#javascript-exceptions" >}}) implementation +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/CdpApiTest.java#L125-L130" >}} +{{% /tab %}} +{{% tab header="Python" %}} +Use the [BiDi API JavaScript exceptions]({{< ref "bidi_api#javascript-exceptions" >}}) implementation +{{< badge-code >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +Use the [BiDi API JavaScript exceptions]({{< ref "bidi_api#javascript-exceptions" >}}) implementation +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +Use the [BiDi API JavaScript exceptions]({{< ref "bidi_api#javascript-exceptions" >}}) implementation +{{< badge-code >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} + +### Download complete + +Wait for a download to finish before continuing. +Because getting download status requires setting a listener, this cannot be done with a CDP Endpoint implementation. + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/CdpApiTest.java#L142-L154" >}} +{{% /tab %}} +{{% tab header="Python" %}} +{{< badge-code >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/cdp_api_spec.rb#L66-L72" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} diff --git a/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/cdp_api.ja.md b/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/cdp_api.ja.md new file mode 100644 index 000000000000..b8e85ed12d53 --- /dev/null +++ b/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/cdp_api.ja.md @@ -0,0 +1,208 @@ +--- +title: "Chrome DevTools Protocol API" +linkTitle: "CDP API" +weight: 4 +description: > + Each of the Selenium bindings dynamically generates classes and methods for the various CDP domains and features; + these are tied to specific versions of Chrome. +--- + +{{% pageinfo color="warning" %}} +While Selenium 4 provides direct access to the Chrome DevTools Protocol (CDP), these +methods will eventually be removed. It is recommended to use the [WebDriver Bidi APIs]({{< ref "bidi_api.md" >}}) +methods where possible to ensure future compatibility. +{{% /pageinfo %}} + +## Usage + +If your use case has been implemented by [WebDriver Bidi]({{< ref "../webdriver_bidi/" >}}) or +the [BiDi API]({{< ref "bidi_api.md" >}}), you should use those implementations instead of this one. +Generally you should prefer this approach over executing with the [CDP Endpoint]({{< ref "cdp_endpoint.md" >}}), +especially in Ruby. + + +## Examples + +### Set Cookie + +An alternate implementation can be found at [CDP Endpoint Set Cookie]({{< ref "cdp_endpoint#set-cookie" >}}) + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +Because Java requires using all the parameters example, the Map approach used in +[CDP Endpoint Set Cookie]({{< ref "cdp_endpoint#set-cookie" >}}) might be more simple. +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/CdpApiTest.java#L39-L57" >}} +{{% /tab %}} +{{% tab header="Python" %}} +Because Python requires using async methods for this example, the synchronous approach found in +[CDP Endpoint Set Cookie]({{< ref "cdp_endpoint#set-cookie" >}}) might be easier. +{{< gh-codeblock path="/examples/python/tests/bidirectional/chrome_devtools/test_cdp_api.py#L10-L18" >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +Due to the added complexity in .NET of obtaining the domains and executing with awaits, the +[CDP Endpoint Set Cookie]({{< ref "cdp_endpoint#set-cookie" >}}) might be easier. +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/CdpApiTest.cs#L25-L37" >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/cdp_api_spec.rb#L9-L12" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} + +### Performance Metrics + +An alternate implementation can be found at [CDP Endpoint Performance Metrics]({{< ref "cdp_endpoint#performance-metrics" >}}) + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/CdpApiTest.java#L68-L72" >}} +{{% /tab %}} +{{% tab header="Python" %}} +Because Python requires using async methods for this example, the synchronous approach found in +[CDP Endpoint Performance Metrics]({{< ref "cdp_endpoint#performance-metrics" >}}) might be easier. +{{< gh-codeblock path="/examples/python/tests/bidirectional/chrome_devtools/test_cdp_api.py#L30-L33" >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +Due to the added complexity in .NET of obtaining the domains and executing with awaits, the +[CDP Endpoint Performance Metrics]({{< ref "cdp_endpoint#performance-metrics" >}}) might be easier. +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/CdpApiTest.cs#L49-L56" >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/cdp_api_spec.rb#L23-L25" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} + +### Basic authentication + +Alternate implementations can be found at +[CDP Endpoint Basic Authentication]({{< ref "cdp_endpoint#basic-authentication" >}}) +and [BiDi API Basic Authentication]({{< ref "bidi_api#basic-authentication" >}}) + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +The [BiDi API Basic Authentication]({{< ref "bidi_api#basic-authentication" >}}) implementation should be preferred +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/CdpApiTest.java#L85-L92" >}} +{{% /tab %}} +{{% tab header="Python" %}} +Because Python requires using async methods for this example, the synchronous approach found in +[CDP Endpoint Basic Authentication]({{< ref "cdp_endpoint#basic-authentication" >}}) might be easier. +{{< gh-codeblock path="/examples/python/tests/bidirectional/chrome_devtools/test_cdp_api.py#L43-L49" >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +Due to the added complexity in .NET of obtaining the domains and executing with awaits, the +[CDP Endpoint Basic Authentication]({{< ref "cdp_endpoint#basic-authentication" >}}) might be easier. +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/CdpApiTest.cs#L70-L83" >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +The [BiDi API Basic Authentication]({{< ref "bidi_api#basic-authentication" >}}) implementation should be preferred +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/cdp_api_spec.rb#L36-L40" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} + +### Console logs + +Because reading console logs requires setting an event listener, +this cannot be done with a CDP Endpoint implementation +Alternate implementations can be found at +[BiDi API Console logs and errors]({{< ref "bidi_api#console-logs-and-errors" >}}) +and [WebDriver BiDi Console logs]({{< ref "../webdriver_bidi/log#console-logs" >}}) + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +Use the [WebDriver BiDi Console logs]({{< ref "../webdriver_bidi/log#console-logs" >}}) implementation +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/CdpApiTest.java#L105-L112" >}} +{{% /tab %}} +{{% tab header="Python" %}} +Use the [BiDi API Console logs and errors]({{< ref "bidi_api#console-logs-and-errors" >}}) implementation +{{< badge-code >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +Use the [BiDi API Console logs and errors]({{< ref "bidi_api#console-logs-and-errors" >}}) implementation +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +The [BiDi API Console logs and errors]({{< ref "bidi_api#console-logs-and-errors" >}}) implementation should be preferred +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/cdp_api_spec.rb#L50-L55" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} + +### JavaScript exceptions + +Similar to console logs, but this listens for actual javascript exceptions not just logged errors +Alternate implementations can be found at +[BiDi API JavaScript exceptions]({{< ref "bidi_api#javascript-exceptions" >}}) +and [WebDriver BiDi JavaScript exceptions]({{< ref "../webdriver_bidi/log#javascript-exceptions" >}}) + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +Use the [WebDriver BiDi JavaScript exceptions]({{< ref "../webdriver_bidi/log#javascript-exceptions" >}}) implementation +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/CdpApiTest.java#L125-L130" >}} +{{% /tab %}} +{{% tab header="Python" %}} +Use the [BiDi API JavaScript exceptions]({{< ref "bidi_api#javascript-exceptions" >}}) implementation +{{< badge-code >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +Use the [BiDi API JavaScript exceptions]({{< ref "bidi_api#javascript-exceptions" >}}) implementation +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +Use the [BiDi API JavaScript exceptions]({{< ref "bidi_api#javascript-exceptions" >}}) implementation +{{< badge-code >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} + +### Download complete + +Wait for a download to finish before continuing. +Because getting download status requires setting a listener, this cannot be done with a CDP Endpoint implementation. + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/CdpApiTest.java#L142-L154" >}} +{{% /tab %}} +{{% tab header="Python" %}} +{{< badge-code >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/cdp_api_spec.rb#L66-L72" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} diff --git a/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/cdp_api.pt-br.md b/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/cdp_api.pt-br.md new file mode 100644 index 000000000000..b8e85ed12d53 --- /dev/null +++ b/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/cdp_api.pt-br.md @@ -0,0 +1,208 @@ +--- +title: "Chrome DevTools Protocol API" +linkTitle: "CDP API" +weight: 4 +description: > + Each of the Selenium bindings dynamically generates classes and methods for the various CDP domains and features; + these are tied to specific versions of Chrome. +--- + +{{% pageinfo color="warning" %}} +While Selenium 4 provides direct access to the Chrome DevTools Protocol (CDP), these +methods will eventually be removed. It is recommended to use the [WebDriver Bidi APIs]({{< ref "bidi_api.md" >}}) +methods where possible to ensure future compatibility. +{{% /pageinfo %}} + +## Usage + +If your use case has been implemented by [WebDriver Bidi]({{< ref "../webdriver_bidi/" >}}) or +the [BiDi API]({{< ref "bidi_api.md" >}}), you should use those implementations instead of this one. +Generally you should prefer this approach over executing with the [CDP Endpoint]({{< ref "cdp_endpoint.md" >}}), +especially in Ruby. + + +## Examples + +### Set Cookie + +An alternate implementation can be found at [CDP Endpoint Set Cookie]({{< ref "cdp_endpoint#set-cookie" >}}) + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +Because Java requires using all the parameters example, the Map approach used in +[CDP Endpoint Set Cookie]({{< ref "cdp_endpoint#set-cookie" >}}) might be more simple. +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/CdpApiTest.java#L39-L57" >}} +{{% /tab %}} +{{% tab header="Python" %}} +Because Python requires using async methods for this example, the synchronous approach found in +[CDP Endpoint Set Cookie]({{< ref "cdp_endpoint#set-cookie" >}}) might be easier. +{{< gh-codeblock path="/examples/python/tests/bidirectional/chrome_devtools/test_cdp_api.py#L10-L18" >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +Due to the added complexity in .NET of obtaining the domains and executing with awaits, the +[CDP Endpoint Set Cookie]({{< ref "cdp_endpoint#set-cookie" >}}) might be easier. +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/CdpApiTest.cs#L25-L37" >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/cdp_api_spec.rb#L9-L12" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} + +### Performance Metrics + +An alternate implementation can be found at [CDP Endpoint Performance Metrics]({{< ref "cdp_endpoint#performance-metrics" >}}) + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/CdpApiTest.java#L68-L72" >}} +{{% /tab %}} +{{% tab header="Python" %}} +Because Python requires using async methods for this example, the synchronous approach found in +[CDP Endpoint Performance Metrics]({{< ref "cdp_endpoint#performance-metrics" >}}) might be easier. +{{< gh-codeblock path="/examples/python/tests/bidirectional/chrome_devtools/test_cdp_api.py#L30-L33" >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +Due to the added complexity in .NET of obtaining the domains and executing with awaits, the +[CDP Endpoint Performance Metrics]({{< ref "cdp_endpoint#performance-metrics" >}}) might be easier. +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/CdpApiTest.cs#L49-L56" >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/cdp_api_spec.rb#L23-L25" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} + +### Basic authentication + +Alternate implementations can be found at +[CDP Endpoint Basic Authentication]({{< ref "cdp_endpoint#basic-authentication" >}}) +and [BiDi API Basic Authentication]({{< ref "bidi_api#basic-authentication" >}}) + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +The [BiDi API Basic Authentication]({{< ref "bidi_api#basic-authentication" >}}) implementation should be preferred +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/CdpApiTest.java#L85-L92" >}} +{{% /tab %}} +{{% tab header="Python" %}} +Because Python requires using async methods for this example, the synchronous approach found in +[CDP Endpoint Basic Authentication]({{< ref "cdp_endpoint#basic-authentication" >}}) might be easier. +{{< gh-codeblock path="/examples/python/tests/bidirectional/chrome_devtools/test_cdp_api.py#L43-L49" >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +Due to the added complexity in .NET of obtaining the domains and executing with awaits, the +[CDP Endpoint Basic Authentication]({{< ref "cdp_endpoint#basic-authentication" >}}) might be easier. +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/CdpApiTest.cs#L70-L83" >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +The [BiDi API Basic Authentication]({{< ref "bidi_api#basic-authentication" >}}) implementation should be preferred +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/cdp_api_spec.rb#L36-L40" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} + +### Console logs + +Because reading console logs requires setting an event listener, +this cannot be done with a CDP Endpoint implementation +Alternate implementations can be found at +[BiDi API Console logs and errors]({{< ref "bidi_api#console-logs-and-errors" >}}) +and [WebDriver BiDi Console logs]({{< ref "../webdriver_bidi/log#console-logs" >}}) + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +Use the [WebDriver BiDi Console logs]({{< ref "../webdriver_bidi/log#console-logs" >}}) implementation +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/CdpApiTest.java#L105-L112" >}} +{{% /tab %}} +{{% tab header="Python" %}} +Use the [BiDi API Console logs and errors]({{< ref "bidi_api#console-logs-and-errors" >}}) implementation +{{< badge-code >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +Use the [BiDi API Console logs and errors]({{< ref "bidi_api#console-logs-and-errors" >}}) implementation +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +The [BiDi API Console logs and errors]({{< ref "bidi_api#console-logs-and-errors" >}}) implementation should be preferred +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/cdp_api_spec.rb#L50-L55" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} + +### JavaScript exceptions + +Similar to console logs, but this listens for actual javascript exceptions not just logged errors +Alternate implementations can be found at +[BiDi API JavaScript exceptions]({{< ref "bidi_api#javascript-exceptions" >}}) +and [WebDriver BiDi JavaScript exceptions]({{< ref "../webdriver_bidi/log#javascript-exceptions" >}}) + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +Use the [WebDriver BiDi JavaScript exceptions]({{< ref "../webdriver_bidi/log#javascript-exceptions" >}}) implementation +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/CdpApiTest.java#L125-L130" >}} +{{% /tab %}} +{{% tab header="Python" %}} +Use the [BiDi API JavaScript exceptions]({{< ref "bidi_api#javascript-exceptions" >}}) implementation +{{< badge-code >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +Use the [BiDi API JavaScript exceptions]({{< ref "bidi_api#javascript-exceptions" >}}) implementation +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +Use the [BiDi API JavaScript exceptions]({{< ref "bidi_api#javascript-exceptions" >}}) implementation +{{< badge-code >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} + +### Download complete + +Wait for a download to finish before continuing. +Because getting download status requires setting a listener, this cannot be done with a CDP Endpoint implementation. + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/CdpApiTest.java#L142-L154" >}} +{{% /tab %}} +{{% tab header="Python" %}} +{{< badge-code >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/cdp_api_spec.rb#L66-L72" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} diff --git a/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/cdp_api.zh-cn.md b/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/cdp_api.zh-cn.md new file mode 100644 index 000000000000..b8e85ed12d53 --- /dev/null +++ b/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/cdp_api.zh-cn.md @@ -0,0 +1,208 @@ +--- +title: "Chrome DevTools Protocol API" +linkTitle: "CDP API" +weight: 4 +description: > + Each of the Selenium bindings dynamically generates classes and methods for the various CDP domains and features; + these are tied to specific versions of Chrome. +--- + +{{% pageinfo color="warning" %}} +While Selenium 4 provides direct access to the Chrome DevTools Protocol (CDP), these +methods will eventually be removed. It is recommended to use the [WebDriver Bidi APIs]({{< ref "bidi_api.md" >}}) +methods where possible to ensure future compatibility. +{{% /pageinfo %}} + +## Usage + +If your use case has been implemented by [WebDriver Bidi]({{< ref "../webdriver_bidi/" >}}) or +the [BiDi API]({{< ref "bidi_api.md" >}}), you should use those implementations instead of this one. +Generally you should prefer this approach over executing with the [CDP Endpoint]({{< ref "cdp_endpoint.md" >}}), +especially in Ruby. + + +## Examples + +### Set Cookie + +An alternate implementation can be found at [CDP Endpoint Set Cookie]({{< ref "cdp_endpoint#set-cookie" >}}) + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +Because Java requires using all the parameters example, the Map approach used in +[CDP Endpoint Set Cookie]({{< ref "cdp_endpoint#set-cookie" >}}) might be more simple. +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/CdpApiTest.java#L39-L57" >}} +{{% /tab %}} +{{% tab header="Python" %}} +Because Python requires using async methods for this example, the synchronous approach found in +[CDP Endpoint Set Cookie]({{< ref "cdp_endpoint#set-cookie" >}}) might be easier. +{{< gh-codeblock path="/examples/python/tests/bidirectional/chrome_devtools/test_cdp_api.py#L10-L18" >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +Due to the added complexity in .NET of obtaining the domains and executing with awaits, the +[CDP Endpoint Set Cookie]({{< ref "cdp_endpoint#set-cookie" >}}) might be easier. +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/CdpApiTest.cs#L25-L37" >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/cdp_api_spec.rb#L9-L12" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} + +### Performance Metrics + +An alternate implementation can be found at [CDP Endpoint Performance Metrics]({{< ref "cdp_endpoint#performance-metrics" >}}) + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/CdpApiTest.java#L68-L72" >}} +{{% /tab %}} +{{% tab header="Python" %}} +Because Python requires using async methods for this example, the synchronous approach found in +[CDP Endpoint Performance Metrics]({{< ref "cdp_endpoint#performance-metrics" >}}) might be easier. +{{< gh-codeblock path="/examples/python/tests/bidirectional/chrome_devtools/test_cdp_api.py#L30-L33" >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +Due to the added complexity in .NET of obtaining the domains and executing with awaits, the +[CDP Endpoint Performance Metrics]({{< ref "cdp_endpoint#performance-metrics" >}}) might be easier. +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/CdpApiTest.cs#L49-L56" >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/cdp_api_spec.rb#L23-L25" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} + +### Basic authentication + +Alternate implementations can be found at +[CDP Endpoint Basic Authentication]({{< ref "cdp_endpoint#basic-authentication" >}}) +and [BiDi API Basic Authentication]({{< ref "bidi_api#basic-authentication" >}}) + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +The [BiDi API Basic Authentication]({{< ref "bidi_api#basic-authentication" >}}) implementation should be preferred +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/CdpApiTest.java#L85-L92" >}} +{{% /tab %}} +{{% tab header="Python" %}} +Because Python requires using async methods for this example, the synchronous approach found in +[CDP Endpoint Basic Authentication]({{< ref "cdp_endpoint#basic-authentication" >}}) might be easier. +{{< gh-codeblock path="/examples/python/tests/bidirectional/chrome_devtools/test_cdp_api.py#L43-L49" >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +Due to the added complexity in .NET of obtaining the domains and executing with awaits, the +[CDP Endpoint Basic Authentication]({{< ref "cdp_endpoint#basic-authentication" >}}) might be easier. +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/CdpApiTest.cs#L70-L83" >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +The [BiDi API Basic Authentication]({{< ref "bidi_api#basic-authentication" >}}) implementation should be preferred +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/cdp_api_spec.rb#L36-L40" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} + +### Console logs + +Because reading console logs requires setting an event listener, +this cannot be done with a CDP Endpoint implementation +Alternate implementations can be found at +[BiDi API Console logs and errors]({{< ref "bidi_api#console-logs-and-errors" >}}) +and [WebDriver BiDi Console logs]({{< ref "../webdriver_bidi/log#console-logs" >}}) + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +Use the [WebDriver BiDi Console logs]({{< ref "../webdriver_bidi/log#console-logs" >}}) implementation +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/CdpApiTest.java#L105-L112" >}} +{{% /tab %}} +{{% tab header="Python" %}} +Use the [BiDi API Console logs and errors]({{< ref "bidi_api#console-logs-and-errors" >}}) implementation +{{< badge-code >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +Use the [BiDi API Console logs and errors]({{< ref "bidi_api#console-logs-and-errors" >}}) implementation +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +The [BiDi API Console logs and errors]({{< ref "bidi_api#console-logs-and-errors" >}}) implementation should be preferred +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/cdp_api_spec.rb#L50-L55" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} + +### JavaScript exceptions + +Similar to console logs, but this listens for actual javascript exceptions not just logged errors +Alternate implementations can be found at +[BiDi API JavaScript exceptions]({{< ref "bidi_api#javascript-exceptions" >}}) +and [WebDriver BiDi JavaScript exceptions]({{< ref "../webdriver_bidi/log#javascript-exceptions" >}}) + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +Use the [WebDriver BiDi JavaScript exceptions]({{< ref "../webdriver_bidi/log#javascript-exceptions" >}}) implementation +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/CdpApiTest.java#L125-L130" >}} +{{% /tab %}} +{{% tab header="Python" %}} +Use the [BiDi API JavaScript exceptions]({{< ref "bidi_api#javascript-exceptions" >}}) implementation +{{< badge-code >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +Use the [BiDi API JavaScript exceptions]({{< ref "bidi_api#javascript-exceptions" >}}) implementation +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +Use the [BiDi API JavaScript exceptions]({{< ref "bidi_api#javascript-exceptions" >}}) implementation +{{< badge-code >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} + +### Download complete + +Wait for a download to finish before continuing. +Because getting download status requires setting a listener, this cannot be done with a CDP Endpoint implementation. + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/CdpApiTest.java#L142-L154" >}} +{{% /tab %}} +{{% tab header="Python" %}} +{{< badge-code >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/cdp_api_spec.rb#L66-L72" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} diff --git a/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/cdp_endpoint.en.md b/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/cdp_endpoint.en.md new file mode 100644 index 000000000000..4952fae2e0dd --- /dev/null +++ b/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/cdp_endpoint.en.md @@ -0,0 +1,108 @@ +--- +title: "Chrome DevTools Protocol Endpoint" +linkTitle: "CDP Endpoint" +weight: 2 +description: > + Google provides a `/cdp/execute` endpoint that can be accessed directly. Each Selenium binding provides a method that + allows you to pass the CDP domain as a String, and the required parameters as a simple Map. +--- + +{{% pageinfo color="warning" %}} +These methods will eventually be removed. It is recommended to use the [WebDriver-BiDi]({{< ref "../webdriver_bidi/" >}}) or [WebDriver Bidi APIs]({{< ref "bidi_api.md" >}}) +methods where possible to ensure future compatibility. +{{% /pageinfo %}} + + +## Usage + +Generally you should prefer the use of the [CDP API]({{< ref "cdp_api.md" >}}) over this approach, +but sometimes the syntax is cleaner or significantly more simple. + +Limitations include: +* It only works for use cases that are limited to setting or getting information; +any actual asynchronous interactions require another implementation +* You have to know the exactly correct "magic strings" for domains and keys +* It is possible that an update to Chrome will change the required parameters + +## Examples + +### Set Cookie + +An alternate implementation can be found at [CDP API Set Cookie]({{< ref "cdp_api#set-cookie" >}}) + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/CdpEndpointTest.java#L26-32" >}} +{{% /tab %}} +{{% tab header="Python" %}} +{{< gh-codeblock path="/examples/python/tests/bidirectional/chrome_devtools/test_cdp_endpoint.py#L7-L12" >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/CdpEndpointTest.cs#L25-L33" >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +The [CDP API Set Cookie]({{< ref "cdp_api#set-cookie" >}}) implementation should be preferred +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/cdp_endpoint_spec.rb#L9-L14" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} + +### Performance Metrics + +An alternate implementation can be found at [CDP API Performance Metrics]({{< ref "cdp_api#performance-metrics" >}}) + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +The [CDP API Performance Metrics]({{< ref "cdp_api#performance-metrics" >}}) implementation should be preferred +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/CdpEndpointTest.java#L43-L46" >}} +{{% /tab %}} +{{% tab header="Python" %}} +{{< gh-codeblock path="/examples/python/tests/bidirectional/chrome_devtools/test_cdp_endpoint.py#L23-L25" >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/CdpEndpointTest.cs#L46-L49" >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +The [CDP API Performance Metrics]({{< ref "cdp_api#performance-metrics" >}}) implementation should be preferred +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/cdp_endpoint_spec.rb#L25-L27" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} + +### Basic authentication + +Alternate implementations can be found at [CDP API Basic Authentication]({{< ref "cdp_api#basic-authentication" >}}) +and [BiDi API Basic Authentication]({{< ref "bidi_api#basic-authentication" >}}) + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +The [BiDi API Basic Authentication]({{< ref "bidi_api#basic-authentication" >}}) implementation should be preferred +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/CdpEndpointTest.java#L60-L66" >}} +{{% /tab %}} +{{% tab header="Python" %}} +{{< gh-codeblock path="/examples/python/tests/bidirectional/chrome_devtools/test_cdp_endpoint.py#L34-L39" >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/CdpEndpointTest.cs#L65-L73" >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +The [BiDi API Basic Authentication]({{< ref "bidi_api#basic-authentication" >}}) implementation should be preferred +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/cdp_endpoint_spec.rb#L38-L43" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} diff --git a/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/cdp_endpoint.ja.md b/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/cdp_endpoint.ja.md new file mode 100644 index 000000000000..4952fae2e0dd --- /dev/null +++ b/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/cdp_endpoint.ja.md @@ -0,0 +1,108 @@ +--- +title: "Chrome DevTools Protocol Endpoint" +linkTitle: "CDP Endpoint" +weight: 2 +description: > + Google provides a `/cdp/execute` endpoint that can be accessed directly. Each Selenium binding provides a method that + allows you to pass the CDP domain as a String, and the required parameters as a simple Map. +--- + +{{% pageinfo color="warning" %}} +These methods will eventually be removed. It is recommended to use the [WebDriver-BiDi]({{< ref "../webdriver_bidi/" >}}) or [WebDriver Bidi APIs]({{< ref "bidi_api.md" >}}) +methods where possible to ensure future compatibility. +{{% /pageinfo %}} + + +## Usage + +Generally you should prefer the use of the [CDP API]({{< ref "cdp_api.md" >}}) over this approach, +but sometimes the syntax is cleaner or significantly more simple. + +Limitations include: +* It only works for use cases that are limited to setting or getting information; +any actual asynchronous interactions require another implementation +* You have to know the exactly correct "magic strings" for domains and keys +* It is possible that an update to Chrome will change the required parameters + +## Examples + +### Set Cookie + +An alternate implementation can be found at [CDP API Set Cookie]({{< ref "cdp_api#set-cookie" >}}) + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/CdpEndpointTest.java#L26-32" >}} +{{% /tab %}} +{{% tab header="Python" %}} +{{< gh-codeblock path="/examples/python/tests/bidirectional/chrome_devtools/test_cdp_endpoint.py#L7-L12" >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/CdpEndpointTest.cs#L25-L33" >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +The [CDP API Set Cookie]({{< ref "cdp_api#set-cookie" >}}) implementation should be preferred +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/cdp_endpoint_spec.rb#L9-L14" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} + +### Performance Metrics + +An alternate implementation can be found at [CDP API Performance Metrics]({{< ref "cdp_api#performance-metrics" >}}) + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +The [CDP API Performance Metrics]({{< ref "cdp_api#performance-metrics" >}}) implementation should be preferred +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/CdpEndpointTest.java#L43-L46" >}} +{{% /tab %}} +{{% tab header="Python" %}} +{{< gh-codeblock path="/examples/python/tests/bidirectional/chrome_devtools/test_cdp_endpoint.py#L23-L25" >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/CdpEndpointTest.cs#L46-L49" >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +The [CDP API Performance Metrics]({{< ref "cdp_api#performance-metrics" >}}) implementation should be preferred +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/cdp_endpoint_spec.rb#L25-L27" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} + +### Basic authentication + +Alternate implementations can be found at [CDP API Basic Authentication]({{< ref "cdp_api#basic-authentication" >}}) +and [BiDi API Basic Authentication]({{< ref "bidi_api#basic-authentication" >}}) + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +The [BiDi API Basic Authentication]({{< ref "bidi_api#basic-authentication" >}}) implementation should be preferred +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/CdpEndpointTest.java#L60-L66" >}} +{{% /tab %}} +{{% tab header="Python" %}} +{{< gh-codeblock path="/examples/python/tests/bidirectional/chrome_devtools/test_cdp_endpoint.py#L34-L39" >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/CdpEndpointTest.cs#L65-L73" >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +The [BiDi API Basic Authentication]({{< ref "bidi_api#basic-authentication" >}}) implementation should be preferred +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/cdp_endpoint_spec.rb#L38-L43" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} diff --git a/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/cdp_endpoint.pt-br.md b/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/cdp_endpoint.pt-br.md new file mode 100644 index 000000000000..4952fae2e0dd --- /dev/null +++ b/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/cdp_endpoint.pt-br.md @@ -0,0 +1,108 @@ +--- +title: "Chrome DevTools Protocol Endpoint" +linkTitle: "CDP Endpoint" +weight: 2 +description: > + Google provides a `/cdp/execute` endpoint that can be accessed directly. Each Selenium binding provides a method that + allows you to pass the CDP domain as a String, and the required parameters as a simple Map. +--- + +{{% pageinfo color="warning" %}} +These methods will eventually be removed. It is recommended to use the [WebDriver-BiDi]({{< ref "../webdriver_bidi/" >}}) or [WebDriver Bidi APIs]({{< ref "bidi_api.md" >}}) +methods where possible to ensure future compatibility. +{{% /pageinfo %}} + + +## Usage + +Generally you should prefer the use of the [CDP API]({{< ref "cdp_api.md" >}}) over this approach, +but sometimes the syntax is cleaner or significantly more simple. + +Limitations include: +* It only works for use cases that are limited to setting or getting information; +any actual asynchronous interactions require another implementation +* You have to know the exactly correct "magic strings" for domains and keys +* It is possible that an update to Chrome will change the required parameters + +## Examples + +### Set Cookie + +An alternate implementation can be found at [CDP API Set Cookie]({{< ref "cdp_api#set-cookie" >}}) + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/CdpEndpointTest.java#L26-32" >}} +{{% /tab %}} +{{% tab header="Python" %}} +{{< gh-codeblock path="/examples/python/tests/bidirectional/chrome_devtools/test_cdp_endpoint.py#L7-L12" >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/CdpEndpointTest.cs#L25-L33" >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +The [CDP API Set Cookie]({{< ref "cdp_api#set-cookie" >}}) implementation should be preferred +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/cdp_endpoint_spec.rb#L9-L14" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} + +### Performance Metrics + +An alternate implementation can be found at [CDP API Performance Metrics]({{< ref "cdp_api#performance-metrics" >}}) + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +The [CDP API Performance Metrics]({{< ref "cdp_api#performance-metrics" >}}) implementation should be preferred +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/CdpEndpointTest.java#L43-L46" >}} +{{% /tab %}} +{{% tab header="Python" %}} +{{< gh-codeblock path="/examples/python/tests/bidirectional/chrome_devtools/test_cdp_endpoint.py#L23-L25" >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/CdpEndpointTest.cs#L46-L49" >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +The [CDP API Performance Metrics]({{< ref "cdp_api#performance-metrics" >}}) implementation should be preferred +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/cdp_endpoint_spec.rb#L25-L27" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} + +### Basic authentication + +Alternate implementations can be found at [CDP API Basic Authentication]({{< ref "cdp_api#basic-authentication" >}}) +and [BiDi API Basic Authentication]({{< ref "bidi_api#basic-authentication" >}}) + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +The [BiDi API Basic Authentication]({{< ref "bidi_api#basic-authentication" >}}) implementation should be preferred +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/CdpEndpointTest.java#L60-L66" >}} +{{% /tab %}} +{{% tab header="Python" %}} +{{< gh-codeblock path="/examples/python/tests/bidirectional/chrome_devtools/test_cdp_endpoint.py#L34-L39" >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/CdpEndpointTest.cs#L65-L73" >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +The [BiDi API Basic Authentication]({{< ref "bidi_api#basic-authentication" >}}) implementation should be preferred +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/cdp_endpoint_spec.rb#L38-L43" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} diff --git a/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/cdp_endpoint.zh-cn.md b/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/cdp_endpoint.zh-cn.md new file mode 100644 index 000000000000..4952fae2e0dd --- /dev/null +++ b/website_and_docs/content/documentation/webdriver/bidirectional/chrome_devtools/cdp_endpoint.zh-cn.md @@ -0,0 +1,108 @@ +--- +title: "Chrome DevTools Protocol Endpoint" +linkTitle: "CDP Endpoint" +weight: 2 +description: > + Google provides a `/cdp/execute` endpoint that can be accessed directly. Each Selenium binding provides a method that + allows you to pass the CDP domain as a String, and the required parameters as a simple Map. +--- + +{{% pageinfo color="warning" %}} +These methods will eventually be removed. It is recommended to use the [WebDriver-BiDi]({{< ref "../webdriver_bidi/" >}}) or [WebDriver Bidi APIs]({{< ref "bidi_api.md" >}}) +methods where possible to ensure future compatibility. +{{% /pageinfo %}} + + +## Usage + +Generally you should prefer the use of the [CDP API]({{< ref "cdp_api.md" >}}) over this approach, +but sometimes the syntax is cleaner or significantly more simple. + +Limitations include: +* It only works for use cases that are limited to setting or getting information; +any actual asynchronous interactions require another implementation +* You have to know the exactly correct "magic strings" for domains and keys +* It is possible that an update to Chrome will change the required parameters + +## Examples + +### Set Cookie + +An alternate implementation can be found at [CDP API Set Cookie]({{< ref "cdp_api#set-cookie" >}}) + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/CdpEndpointTest.java#L26-32" >}} +{{% /tab %}} +{{% tab header="Python" %}} +{{< gh-codeblock path="/examples/python/tests/bidirectional/chrome_devtools/test_cdp_endpoint.py#L7-L12" >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/CdpEndpointTest.cs#L25-L33" >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +The [CDP API Set Cookie]({{< ref "cdp_api#set-cookie" >}}) implementation should be preferred +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/cdp_endpoint_spec.rb#L9-L14" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} + +### Performance Metrics + +An alternate implementation can be found at [CDP API Performance Metrics]({{< ref "cdp_api#performance-metrics" >}}) + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +The [CDP API Performance Metrics]({{< ref "cdp_api#performance-metrics" >}}) implementation should be preferred +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/CdpEndpointTest.java#L43-L46" >}} +{{% /tab %}} +{{% tab header="Python" %}} +{{< gh-codeblock path="/examples/python/tests/bidirectional/chrome_devtools/test_cdp_endpoint.py#L23-L25" >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/CdpEndpointTest.cs#L46-L49" >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +The [CDP API Performance Metrics]({{< ref "cdp_api#performance-metrics" >}}) implementation should be preferred +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/cdp_endpoint_spec.rb#L25-L27" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} + +### Basic authentication + +Alternate implementations can be found at [CDP API Basic Authentication]({{< ref "cdp_api#basic-authentication" >}}) +and [BiDi API Basic Authentication]({{< ref "bidi_api#basic-authentication" >}}) + +{{< tabpane text=true langEqualsHeader=true >}} +{{% tab header="Java" %}} +The [BiDi API Basic Authentication]({{< ref "bidi_api#basic-authentication" >}}) implementation should be preferred +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/CdpEndpointTest.java#L60-L66" >}} +{{% /tab %}} +{{% tab header="Python" %}} +{{< gh-codeblock path="/examples/python/tests/bidirectional/chrome_devtools/test_cdp_endpoint.py#L34-L39" >}} +{{% /tab %}} +{{% tab header="CSharp" %}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/CdpEndpointTest.cs#L65-L73" >}} +{{% /tab %}} +{{% tab header="Ruby" %}} +The [BiDi API Basic Authentication]({{< ref "bidi_api#basic-authentication" >}}) implementation should be preferred +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/cdp_endpoint_spec.rb#L38-L43" >}} +{{% /tab %}} +{{% tab header="JavaScript" %}} +{{< badge-code >}} +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-code >}} +{{% /tab %}} +{{< /tabpane >}} diff --git a/website_and_docs/content/documentation/webdriver/bidirectional/bidirectional_w3c/_index.en.md b/website_and_docs/content/documentation/webdriver/bidirectional/webdriver_bidi/_index.en.md similarity index 87% rename from website_and_docs/content/documentation/webdriver/bidirectional/bidirectional_w3c/_index.en.md rename to website_and_docs/content/documentation/webdriver/bidirectional/webdriver_bidi/_index.en.md index 8369c9f93c92..09f9e815d024 100644 --- a/website_and_docs/content/documentation/webdriver/bidirectional/bidirectional_w3c/_index.en.md +++ b/website_and_docs/content/documentation/webdriver/bidirectional/webdriver_bidi/_index.en.md @@ -1,8 +1,9 @@ --- title: "BiDirectional API (W3C compliant)" -linkTitle: "BiDi API (W3C compliant)" +linkTitle: "WebDriver-BiDi" weight: 16 aliases: [ +"/documentation/en/webdriver/bidirectional/bidirectional_w3c", "/documentation/en/webdriver/bidi_apis/bidi_w3c", "/documentation/webdriver/bidi_apis/bidi_w3c" ] diff --git a/website_and_docs/content/documentation/webdriver/bidirectional/bidirectional_w3c/_index.ja.md b/website_and_docs/content/documentation/webdriver/bidirectional/webdriver_bidi/_index.ja.md similarity index 100% rename from website_and_docs/content/documentation/webdriver/bidirectional/bidirectional_w3c/_index.ja.md rename to website_and_docs/content/documentation/webdriver/bidirectional/webdriver_bidi/_index.ja.md diff --git a/website_and_docs/content/documentation/webdriver/bidirectional/bidirectional_w3c/_index.pt-br.md b/website_and_docs/content/documentation/webdriver/bidirectional/webdriver_bidi/_index.pt-br.md similarity index 100% rename from website_and_docs/content/documentation/webdriver/bidirectional/bidirectional_w3c/_index.pt-br.md rename to website_and_docs/content/documentation/webdriver/bidirectional/webdriver_bidi/_index.pt-br.md diff --git a/website_and_docs/content/documentation/webdriver/bidirectional/bidirectional_w3c/_index.zh-cn.md b/website_and_docs/content/documentation/webdriver/bidirectional/webdriver_bidi/_index.zh-cn.md similarity index 100% rename from website_and_docs/content/documentation/webdriver/bidirectional/bidirectional_w3c/_index.zh-cn.md rename to website_and_docs/content/documentation/webdriver/bidirectional/webdriver_bidi/_index.zh-cn.md diff --git a/website_and_docs/content/documentation/webdriver/bidirectional/bidirectional_w3c/browsing_context.en.md b/website_and_docs/content/documentation/webdriver/bidirectional/webdriver_bidi/browsing_context.en.md similarity index 77% rename from website_and_docs/content/documentation/webdriver/bidirectional/bidirectional_w3c/browsing_context.en.md rename to website_and_docs/content/documentation/webdriver/bidirectional/webdriver_bidi/browsing_context.en.md index 17fbbc965af3..1b3b8c4580fb 100644 --- a/website_and_docs/content/documentation/webdriver/bidirectional/bidirectional_w3c/browsing_context.en.md +++ b/website_and_docs/content/documentation/webdriver/bidirectional/webdriver_bidi/browsing_context.en.md @@ -2,6 +2,9 @@ title: "Browsing Context" linkTitle: "Browsing Context" weight: 1 +aliases: [ + "/documentation/en/webdriver/bidirectional/bidirectional_w3c/browsing_context", +] --- This section contains the APIs related to browsing context commands. @@ -13,7 +16,7 @@ Creates a new browsing context in a new window. {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java#L35" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java#L35" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} @@ -33,7 +36,7 @@ Creates a new browsing context in a new tab. {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java#L49" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java#L49" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} @@ -53,7 +56,7 @@ Creates a browsing context for the existing tab/window to run commands. {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java#L28-L29" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java#L28-L29" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} @@ -74,7 +77,7 @@ The API allows to pass the reference browsing context, which is used to create a {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java#L41-L43" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java#L41-L43" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} @@ -94,7 +97,7 @@ The API allows to pass the reference browsing context, which is used to create a {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java#L55-L57" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java#L55-L57" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} @@ -112,7 +115,7 @@ The API allows to pass the reference browsing context, which is used to create a {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java#L63-L65" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java#L63-L65" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} @@ -130,7 +133,7 @@ The API allows to pass the reference browsing context, which is used to create a {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java#L74-L77" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java#L74-L77" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} @@ -150,7 +153,7 @@ Provides a tree of all browsing contexts descending from the parent browsing con {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java#L86-L91" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java#L86-L91" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} @@ -170,7 +173,7 @@ Provides a tree of all browsing contexts descending from the parent browsing con {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java#L102-L105" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java#L102-L105" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} @@ -188,7 +191,7 @@ Provides a tree of all browsing contexts descending from the parent browsing con {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java#L117-L120" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java#L117-L120" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} @@ -206,7 +209,7 @@ Provides a tree of all browsing contexts descending from the parent browsing con {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java#L127-L130" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java#L127-L130" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} diff --git a/website_and_docs/content/documentation/webdriver/bidirectional/bidirectional_w3c/browsing_context.ja.md b/website_and_docs/content/documentation/webdriver/bidirectional/webdriver_bidi/browsing_context.ja.md similarity index 78% rename from website_and_docs/content/documentation/webdriver/bidirectional/bidirectional_w3c/browsing_context.ja.md rename to website_and_docs/content/documentation/webdriver/bidirectional/webdriver_bidi/browsing_context.ja.md index b548b77a30dc..3e0bdb0fcc8a 100644 --- a/website_and_docs/content/documentation/webdriver/bidirectional/bidirectional_w3c/browsing_context.ja.md +++ b/website_and_docs/content/documentation/webdriver/bidirectional/webdriver_bidi/browsing_context.ja.md @@ -22,7 +22,7 @@ Creates a new browsing context in a new window. {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java#L35" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java#L35" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} @@ -42,7 +42,7 @@ Creates a new browsing context in a new tab. {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java#L49" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java#L49" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} @@ -62,7 +62,7 @@ Creates a browsing context for the existing tab/window to run commands. {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java#L28-L29" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java#L28-L29" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} @@ -83,7 +83,7 @@ The API allows to pass the reference browsing context, which is used to create a {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java#L41-L43" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java#L41-L43" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} @@ -103,7 +103,7 @@ The API allows to pass the reference browsing context, which is used to create a {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java#L55-L57" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java#L55-L57" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} @@ -121,7 +121,7 @@ The API allows to pass the reference browsing context, which is used to create a {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java#L63-L65" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java#L63-L65" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} @@ -139,7 +139,7 @@ The API allows to pass the reference browsing context, which is used to create a {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java#L74-L77" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java#L74-L77" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} @@ -159,7 +159,7 @@ Provides a tree of all browsing contexts descending from the parent browsing con {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java#L86-L91" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java#L86-L91" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} @@ -179,7 +179,7 @@ Provides a tree of all browsing contexts descending from the parent browsing con {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java#L102-L105" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java#L102-L105" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} @@ -197,7 +197,7 @@ Provides a tree of all browsing contexts descending from the parent browsing con {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java#L117-L120" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java#L117-L120" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} @@ -215,7 +215,7 @@ Provides a tree of all browsing contexts descending from the parent browsing con {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java#L127-L130" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java#L127-L130" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} diff --git a/website_and_docs/content/documentation/webdriver/bidirectional/bidirectional_w3c/browsing_context.pt-br.md b/website_and_docs/content/documentation/webdriver/bidirectional/webdriver_bidi/browsing_context.pt-br.md similarity index 78% rename from website_and_docs/content/documentation/webdriver/bidirectional/bidirectional_w3c/browsing_context.pt-br.md rename to website_and_docs/content/documentation/webdriver/bidirectional/webdriver_bidi/browsing_context.pt-br.md index 522d94bc4fb5..9aa20689b947 100644 --- a/website_and_docs/content/documentation/webdriver/bidirectional/bidirectional_w3c/browsing_context.pt-br.md +++ b/website_and_docs/content/documentation/webdriver/bidirectional/webdriver_bidi/browsing_context.pt-br.md @@ -22,7 +22,7 @@ Creates a new browsing context in a new window. {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java#L35" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java#L35" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} @@ -42,7 +42,7 @@ Creates a new browsing context in a new tab. {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java#L49" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java#L49" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} @@ -62,7 +62,7 @@ Creates a browsing context for the existing tab/window to run commands. {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java#L28-L29" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java#L28-L29" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} @@ -83,7 +83,7 @@ The API allows to pass the reference browsing context, which is used to create a {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java#L41-L43" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java#L41-L43" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} @@ -103,7 +103,7 @@ The API allows to pass the reference browsing context, which is used to create a {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java#L55-L57" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java#L55-L57" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} @@ -121,7 +121,7 @@ The API allows to pass the reference browsing context, which is used to create a {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java#L63-L65" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java#L63-L65" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} @@ -139,7 +139,7 @@ The API allows to pass the reference browsing context, which is used to create a {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java#L74-L77" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java#L74-L77" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} @@ -159,7 +159,7 @@ Provides a tree of all browsing contexts descending from the parent browsing con {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java#L86-L91" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java#L86-L91" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} @@ -179,7 +179,7 @@ Provides a tree of all browsing contexts descending from the parent browsing con {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java#L102-L105" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java#L102-L105" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} @@ -197,7 +197,7 @@ Provides a tree of all browsing contexts descending from the parent browsing con {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java#L117-L120" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java#L117-L120" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} @@ -215,7 +215,7 @@ Provides a tree of all browsing contexts descending from the parent browsing con {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java#L127-L130" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java#L127-L130" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} diff --git a/website_and_docs/content/documentation/webdriver/bidirectional/bidirectional_w3c/browsing_context.zh-cn.md b/website_and_docs/content/documentation/webdriver/bidirectional/webdriver_bidi/browsing_context.zh-cn.md similarity index 78% rename from website_and_docs/content/documentation/webdriver/bidirectional/bidirectional_w3c/browsing_context.zh-cn.md rename to website_and_docs/content/documentation/webdriver/bidirectional/webdriver_bidi/browsing_context.zh-cn.md index cdf92257152c..52448465862e 100644 --- a/website_and_docs/content/documentation/webdriver/bidirectional/bidirectional_w3c/browsing_context.zh-cn.md +++ b/website_and_docs/content/documentation/webdriver/bidirectional/webdriver_bidi/browsing_context.zh-cn.md @@ -22,7 +22,7 @@ Creates a new browsing context in a new window. {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java#L35" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java#L35" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} @@ -42,7 +42,7 @@ Creates a new browsing context in a new tab. {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java#L49" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java#L49" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} @@ -62,7 +62,7 @@ Creates a browsing context for the existing tab/window to run commands. {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java#L28-L29" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java#L28-L29" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} @@ -83,7 +83,7 @@ The API allows to pass the reference browsing context, which is used to create a {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java#L41-L43" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java#L41-L43" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} @@ -103,7 +103,7 @@ The API allows to pass the reference browsing context, which is used to create a {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java#L55-L57" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java#L55-L57" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} @@ -121,7 +121,7 @@ The API allows to pass the reference browsing context, which is used to create a {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java#L63-L65" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java#L63-L65" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} @@ -139,7 +139,7 @@ The API allows to pass the reference browsing context, which is used to create a {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java#L74-L77" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java#L74-L77" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} @@ -159,7 +159,7 @@ Provides a tree of all browsing contexts descending from the parent browsing con {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java#L86-L91" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java#L86-L91" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} @@ -179,7 +179,7 @@ Provides a tree of all browsing contexts descending from the parent browsing con {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java#L102-L105" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java#L102-L105" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} @@ -197,7 +197,7 @@ Provides a tree of all browsing contexts descending from the parent browsing con {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java#L117-L120" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java#L117-L120" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} @@ -215,7 +215,7 @@ Provides a tree of all browsing contexts descending from the parent browsing con {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/BrowsingContextTest.java#L127-L130" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/BrowsingContextTest.java#L127-L130" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} diff --git a/website_and_docs/content/documentation/webdriver/bidirectional/bidirectional_w3c/log.en.md b/website_and_docs/content/documentation/webdriver/bidirectional/webdriver_bidi/log.en.md similarity index 65% rename from website_and_docs/content/documentation/webdriver/bidirectional/bidirectional_w3c/log.en.md rename to website_and_docs/content/documentation/webdriver/bidirectional/webdriver_bidi/log.en.md index b07963b17eb8..767681068e03 100644 --- a/website_and_docs/content/documentation/webdriver/bidirectional/bidirectional_w3c/log.en.md +++ b/website_and_docs/content/documentation/webdriver/bidirectional/webdriver_bidi/log.en.md @@ -2,44 +2,47 @@ title: "Log" linkTitle: "Log" weight: 1 +aliases: [ + "/documentation/en/webdriver/bidirectional/bidirectional_w3c/log", +] --- This section contains the APIs related to logging. -## Listen to `console.log` events +## Console logs Listen to the `console.log` events and register callbacks to process the event. {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/LogTest.java#L31-L38" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/LogTest.java#L31-L38" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} {{< /tab >}} {{< tab header="JavaScript" >}} -{{< gh-codeblock path="examples/javascript/test/bidirectional/logInspector.spec.js#L23-37" >}} +{{< gh-codeblock path="/examples/javascript/test/bidirectional/logInspector.spec.js#L23-37" >}} {{< /tab >}} {{< tab header="Kotlin" >}} {{< badge-code >}} {{< /tab >}} {{< /tabpane >}} -## Listen to JS Exceptions +## JavaScript exceptions Listen to the JS Exceptions and register callbacks to process the exception details. {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/LogTest.java#L70-L77" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/LogTest.java#L70-L77" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} {{< /tab >}} {{< tab header="JavaScript" >}} -{{< gh-codeblock path="examples/javascript/test/bidirectional/logInspector.spec.js#L44-54" >}} +{{< gh-codeblock path="/examples/javascript/test/bidirectional/logInspector.spec.js#L44-54" >}} {{< /tab >}} {{< tab header="Kotlin" >}} {{< badge-code >}} @@ -53,7 +56,7 @@ Listen to all JS logs at all levels and register callbacks to process the log. {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/LogTest.java#L52-L59" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/LogTest.java#L52-L59" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} diff --git a/website_and_docs/content/documentation/webdriver/bidirectional/bidirectional_w3c/log.ja.md b/website_and_docs/content/documentation/webdriver/bidirectional/webdriver_bidi/log.ja.md similarity index 71% rename from website_and_docs/content/documentation/webdriver/bidirectional/bidirectional_w3c/log.ja.md rename to website_and_docs/content/documentation/webdriver/bidirectional/webdriver_bidi/log.ja.md index fe9e95007b8f..93feb58faa4b 100644 --- a/website_and_docs/content/documentation/webdriver/bidirectional/bidirectional_w3c/log.ja.md +++ b/website_and_docs/content/documentation/webdriver/bidirectional/webdriver_bidi/log.ja.md @@ -15,40 +15,40 @@ weight: 12 This section contains the APIs related to logging. -## Listen to `console.log` events +## Console logs Listen to the `console.log` events and register callbacks to process the event. {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/LogTest.java#L31-L38" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/LogTest.java#L31-L38" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} {{< /tab >}} {{< tab header="JavaScript" >}} -{{< gh-codeblock path="examples/javascript/test/bidirectional/logInspector.spec.js#L23-37" >}} +{{< gh-codeblock path="/examples/javascript/test/bidirectional/logInspector.spec.js#L23-37" >}} {{< /tab >}} {{< tab header="Kotlin" >}} {{< badge-code >}} {{< /tab >}} {{< /tabpane >}} -## Listen to JS Exceptions +## JavaScript exceptions Listen to the JS Exceptions and register callbacks to process the exception details. {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/LogTest.java#L70-L77" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/LogTest.java#L70-L77" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} {{< /tab >}} {{< tab header="JavaScript" >}} -{{< gh-codeblock path="examples/javascript/test/bidirectional/logInspector.spec.js#L44-54" >}} +{{< gh-codeblock path="/examples/javascript/test/bidirectional/logInspector.spec.js#L44-54" >}} {{< /tab >}} {{< tab header="Kotlin" >}} {{< badge-code >}} @@ -62,7 +62,7 @@ Listen to all JS logs at all levels and register callbacks to process the log. {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/LogTest.java#L52-L59" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/LogTest.java#L52-L59" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} diff --git a/website_and_docs/content/documentation/webdriver/bidirectional/bidirectional_w3c/log.pt-br.md b/website_and_docs/content/documentation/webdriver/bidirectional/webdriver_bidi/log.pt-br.md similarity index 71% rename from website_and_docs/content/documentation/webdriver/bidirectional/bidirectional_w3c/log.pt-br.md rename to website_and_docs/content/documentation/webdriver/bidirectional/webdriver_bidi/log.pt-br.md index 1e3c0b026062..7e969d4aab8f 100644 --- a/website_and_docs/content/documentation/webdriver/bidirectional/bidirectional_w3c/log.pt-br.md +++ b/website_and_docs/content/documentation/webdriver/bidirectional/webdriver_bidi/log.pt-br.md @@ -15,40 +15,40 @@ weight: 12 This section contains the APIs related to logging. -## Listen to `console.log` events +## Console logs Listen to the `console.log` events and register callbacks to process the event. {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/LogTest.java#L31-L38" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/LogTest.java#L31-L38" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} {{< /tab >}} {{< tab header="JavaScript" >}} -{{< gh-codeblock path="examples/javascript/test/bidirectional/logInspector.spec.js#L23-37" >}} +{{< gh-codeblock path="/examples/javascript/test/bidirectional/logInspector.spec.js#L23-37" >}} {{< /tab >}} {{< tab header="Kotlin" >}} {{< badge-code >}} {{< /tab >}} {{< /tabpane >}} -## Listen to JS Exceptions +## JavaScript exceptions Listen to the JS Exceptions and register callbacks to process the exception details. {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/LogTest.java#L70-L77" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/LogTest.java#L70-L77" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} {{< /tab >}} {{< tab header="JavaScript" >}} -{{< gh-codeblock path="examples/javascript/test/bidirectional/logInspector.spec.js#L44-54" >}} +{{< gh-codeblock path="/examples/javascript/test/bidirectional/logInspector.spec.js#L44-54" >}} {{< /tab >}} {{< tab header="Kotlin" >}} {{< badge-code >}} @@ -62,7 +62,7 @@ Listen to all JS logs at all levels and register callbacks to process the log. {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/LogTest.java#L52-L59" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/LogTest.java#L52-L59" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} diff --git a/website_and_docs/content/documentation/webdriver/bidirectional/bidirectional_w3c/log.zh-cn.md b/website_and_docs/content/documentation/webdriver/bidirectional/webdriver_bidi/log.zh-cn.md similarity index 71% rename from website_and_docs/content/documentation/webdriver/bidirectional/bidirectional_w3c/log.zh-cn.md rename to website_and_docs/content/documentation/webdriver/bidirectional/webdriver_bidi/log.zh-cn.md index 6edb28a1ff08..572311545f0c 100644 --- a/website_and_docs/content/documentation/webdriver/bidirectional/bidirectional_w3c/log.zh-cn.md +++ b/website_and_docs/content/documentation/webdriver/bidirectional/webdriver_bidi/log.zh-cn.md @@ -16,41 +16,41 @@ weight: 12 This section contains the APIs related to logging. -## Listen to `console.log` events +## Console logs Listen to the `console.log` events and register callbacks to process the event. {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/LogTest.java#L31-L38" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/LogTest.java#L31-L38" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} {{< /tab >}} {{< tab header="JavaScript" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/javascript/test/bidirectional/logInspector.spec.js#L23-37" >}} +{{< gh-codeblock path="/examples/javascript/test/bidirectional/logInspector.spec.js#L23-37" >}} {{< /tab >}} {{< tab header="Kotlin" >}} {{< badge-code >}} {{< /tab >}} {{< /tabpane >}} -## Listen to JS Exceptions +## JavaScript exceptions Listen to the JS Exceptions and register callbacks to process the exception details. {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/LogTest.java#L70-L77" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/LogTest.java#L70-L77" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} {{< /tab >}} {{< tab header="JavaScript" >}} {{< badge-version version="4.8" >}} -{{< gh-codeblock path="examples/javascript/test/bidirectional/logInspector.spec.js#L44-54" >}} +{{< gh-codeblock path="/examples/javascript/test/bidirectional/logInspector.spec.js#L44-54" >}} {{< /tab >}} {{< tab header="Kotlin" >}} {{< badge-code >}} @@ -63,7 +63,7 @@ Listen to all JS logs at all levels and register callbacks to process the log. {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} -{{< gh-codeblock path="examples/java/src/test/java/dev/selenium/bidirectional/bidirectional_w3c/LogTest.java#L52-L59" >}} +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/webdriver_bidi/LogTest.java#L52-L59" >}} {{< /tab >}} {{< tab header="Ruby" >}} {{< badge-code >}} diff --git a/website_and_docs/content/documentation/webdriver/browsers/chrome.en.md b/website_and_docs/content/documentation/webdriver/browsers/chrome.en.md index 0ed37a7149ff..5ac15048e47a 100644 --- a/website_and_docs/content/documentation/webdriver/browsers/chrome.en.md +++ b/website_and_docs/content/documentation/webdriver/browsers/chrome.en.md @@ -463,4 +463,4 @@ You can simulate various network conditions. ### DevTools -See the [Chrome DevTools]({{< ref "../bidirectional/chrome_devtools.md" >}}) section for more information about using Chrome DevTools +See the [Chrome DevTools]({{< ref "../bidirectional/chrome_devtools/cdp_api.md" >}}) section for more information about using Chrome DevTools diff --git a/website_and_docs/content/documentation/webdriver/browsers/chrome.ja.md b/website_and_docs/content/documentation/webdriver/browsers/chrome.ja.md index 3fc435a1a130..f3a7389d136e 100644 --- a/website_and_docs/content/documentation/webdriver/browsers/chrome.ja.md +++ b/website_and_docs/content/documentation/webdriver/browsers/chrome.ja.md @@ -469,4 +469,4 @@ please refer to the ### デベロッパー ツール -Chromeデベロッパーツールの使用に関する詳細については、[Chromeデベロッパー ツール]({{< ref "../bidirectional/chrome_devtools.md" >}})セクションを参照してください。 +Chromeデベロッパーツールの使用に関する詳細については、[Chromeデベロッパー ツール]({{< ref "../bidirectional/chrome_devtools/cdp_api.md" >}})セクションを参照してください。 diff --git a/website_and_docs/content/documentation/webdriver/browsers/chrome.pt-br.md b/website_and_docs/content/documentation/webdriver/browsers/chrome.pt-br.md index 402e06decda6..826e5a78d044 100644 --- a/website_and_docs/content/documentation/webdriver/browsers/chrome.pt-br.md +++ b/website_and_docs/content/documentation/webdriver/browsers/chrome.pt-br.md @@ -466,4 +466,4 @@ please refer to the ### DevTools -Veja a secção [Chrome DevTools]({{< ref "../bidirectional/chrome_devtools.md" >}}) para mais informação em como usar Chrome DevTools +Veja a secção [Chrome DevTools]({{< ref "../bidirectional/chrome_devtools/cdp_api.md" >}}) para mais informação em como usar Chrome DevTools diff --git a/website_and_docs/content/documentation/webdriver/browsers/chrome.zh-cn.md b/website_and_docs/content/documentation/webdriver/browsers/chrome.zh-cn.md index 2b7c44f8004c..80f5b615a39c 100644 --- a/website_and_docs/content/documentation/webdriver/browsers/chrome.zh-cn.md +++ b/website_and_docs/content/documentation/webdriver/browsers/chrome.zh-cn.md @@ -465,4 +465,4 @@ please refer to the ### DevTools -See the [Chrome DevTools]({{< ref "../bidirectional/chrome_devtools.md" >}}) section for more information about using Chrome DevTools +See the [Chrome DevTools]({{< ref "../bidirectional/chrome_devtools/cdp_api.md" >}}) section for more information about using Chrome DevTools diff --git a/website_and_docs/content/documentation/webdriver/browsers/edge.en.md b/website_and_docs/content/documentation/webdriver/browsers/edge.en.md index 5d11127ebe2f..c6b70ea7c1be 100644 --- a/website_and_docs/content/documentation/webdriver/browsers/edge.en.md +++ b/website_and_docs/content/documentation/webdriver/browsers/edge.en.md @@ -463,4 +463,4 @@ You can simulate various network conditions. ### DevTools -See the [Chrome DevTools]({{< ref "../bidirectional/chrome_devtools.md" >}}) section for more information about using DevTools in Edge +See the [Chrome DevTools]({{< ref "../bidirectional/chrome_devtools/cdp_api.md" >}}) section for more information about using DevTools in Edge diff --git a/website_and_docs/content/documentation/webdriver/browsers/edge.ja.md b/website_and_docs/content/documentation/webdriver/browsers/edge.ja.md index db9ebe9d967f..9537b1aa37a9 100644 --- a/website_and_docs/content/documentation/webdriver/browsers/edge.ja.md +++ b/website_and_docs/content/documentation/webdriver/browsers/edge.ja.md @@ -465,4 +465,4 @@ You can simulate various network conditions. ### DevTools -See the [Chrome DevTools]({{< ref "../bidirectional/chrome_devtools.md" >}}) section for more information about using DevTools in Edge +See the [Chrome DevTools]({{< ref "../bidirectional/chrome_devtools/cdp_api.md" >}}) section for more information about using DevTools in Edge diff --git a/website_and_docs/content/documentation/webdriver/browsers/edge.pt-br.md b/website_and_docs/content/documentation/webdriver/browsers/edge.pt-br.md index 8418db1f6b9f..d5f276b76011 100644 --- a/website_and_docs/content/documentation/webdriver/browsers/edge.pt-br.md +++ b/website_and_docs/content/documentation/webdriver/browsers/edge.pt-br.md @@ -465,4 +465,4 @@ You can simulate various network conditions. ### DevTools -See the [Chrome DevTools]({{< ref "../bidirectional/chrome_devtools.md" >}}) section for more information about using DevTools in Edge +See the [Chrome DevTools]({{< ref "../bidirectional/chrome_devtools/cdp_api.md" >}}) section for more information about using DevTools in Edge diff --git a/website_and_docs/content/documentation/webdriver/browsers/edge.zh-cn.md b/website_and_docs/content/documentation/webdriver/browsers/edge.zh-cn.md index 92e919e545d8..c7c03f2b0e8b 100644 --- a/website_and_docs/content/documentation/webdriver/browsers/edge.zh-cn.md +++ b/website_and_docs/content/documentation/webdriver/browsers/edge.zh-cn.md @@ -465,4 +465,4 @@ You can simulate various network conditions. ### DevTools -See the [Chrome DevTools]({{< ref "../bidirectional/chrome_devtools.md" >}}) section for more information about using DevTools in Edge +See the [Chrome DevTools]({{< ref "../bidirectional/chrome_devtools/cdp_api.md" >}}) section for more information about using DevTools in Edge