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.ja.md b/website_and_docs/content/documentation/webdriver/bidirectional/bidi_api.ja.md deleted file mode 100644 index 759221d8fe07..000000000000 --- a/website_and_docs/content/documentation/webdriver/bidirectional/bidi_api.ja.md +++ /dev/null @@ -1,545 +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" >}} -Predicate uriPredicate = uri -> uri.getHost().contains("your-domain.com"); - -((HasAuthentication) driver).register(uriPredicate, UsernameAndPassword.of("admin", "password")); -driver.get("https://your-domain.com/login"); -{{< /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" >}} -ChromeDriver driver = new ChromeDriver(); - -AtomicReference seen = new AtomicReference<>(); -CountDownLatch latch = new CountDownLatch(1); -((HasLogEvents) driver).onLogEvent(domMutation(mutation -> { - seen.set(mutation); - latch.countDown(); -})); - -driver.get("https://www.google.com"); -WebElement span = driver.findElement(By.cssSelector("span")); - -((JavascriptExecutor) driver).executeScript("arguments[0].setAttribute('cheese', 'gouda');", span); - -assertThat(latch.await(10, SECONDS), is(true)); -assertThat(seen.get().getAttributeName(), is("cheese")); -assertThat(seen.get().getCurrentValue(), is("gouda")); - -driver.quit(); - {{< /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" >}} - import org.openqa.selenium.WebDriver; - import org.openqa.selenium.devtools.HasDevTools; - import org.openqa.selenium.devtools.NetworkInterceptor; - import org.openqa.selenium.remote.http.Contents; - import org.openqa.selenium.remote.http.Filter; - import org.openqa.selenium.remote.http.HttpResponse; - import org.openqa.selenium.remote.http.Route; - - 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://example-sausages-site.com"); - - String source = driver.getPageSource(); - - assertThat(source).contains("delicious cheese!"); -{{< /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 857658531740..000000000000 --- a/website_and_docs/content/documentation/webdriver/bidirectional/bidi_api.pt-br.md +++ /dev/null @@ -1,531 +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" >}} -Predicate uriPredicate = uri -> uri.getHost().contains("your-domain.com"); - -((HasAuthentication) driver).register(uriPredicate, UsernameAndPassword.of("admin", "password")); -driver.get("https://your-domain.com/login"); -{{< /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" >}} -ChromeDriver driver = new ChromeDriver(); - -AtomicReference seen = new AtomicReference<>(); -CountDownLatch latch = new CountDownLatch(1); -((HasLogEvents) driver).onLogEvent(domMutation(mutation -> { - seen.set(mutation); - latch.countDown(); -})); - -driver.get("https://www.google.com"); -WebElement span = driver.findElement(By.cssSelector("span")); - -((JavascriptExecutor) driver).executeScript("arguments[0].setAttribute('cheese', 'gouda');", span); - -assertThat(latch.await(10, SECONDS), is(true)); -assertThat(seen.get().getAttributeName(), is("cheese")); -assertThat(seen.get().getCurrentValue(), is("gouda")); - -driver.quit(); - {{< /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" >}} - import org.openqa.selenium.WebDriver; - import org.openqa.selenium.devtools.HasDevTools; - import org.openqa.selenium.devtools.NetworkInterceptor; - import org.openqa.selenium.remote.http.Contents; - import org.openqa.selenium.remote.http.Filter; - import org.openqa.selenium.remote.http.HttpResponse; - import org.openqa.selenium.remote.http.Route; - - 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://example-sausages-site.com"); - - String source = driver.getPageSource(); - - assertThat(source).contains("delicious cheese!"); -{{< /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 dec54576ed2e..000000000000 --- a/website_and_docs/content/documentation/webdriver/bidirectional/bidi_api.zh-cn.md +++ /dev/null @@ -1,548 +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" >}} -Predicate uriPredicate = uri -> uri.getHost().contains("your-domain.com"); - -((HasAuthentication) driver).register(uriPredicate, UsernameAndPassword.of("admin", "password")); -driver.get("https://your-domain.com/login"); -{{< /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" >}} -ChromeDriver driver = new ChromeDriver(); - -AtomicReference seen = new AtomicReference<>(); -CountDownLatch latch = new CountDownLatch(1); -((HasLogEvents) driver).onLogEvent(domMutation(mutation -> { - seen.set(mutation); - latch.countDown(); -})); - -driver.get("https://www.google.com"); -WebElement span = driver.findElement(By.cssSelector("span")); - -((JavascriptExecutor) driver).executeScript("arguments[0].setAttribute('cheese', 'gouda');", span); - -assertThat(latch.await(10, SECONDS), is(true)); -assertThat(seen.get().getAttributeName(), is("cheese")); -assertThat(seen.get().getCurrentValue(), is("gouda")); - -driver.quit(); - {{< /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" >}} - import org.openqa.selenium.WebDriver; - import org.openqa.selenium.devtools.HasDevTools; - import org.openqa.selenium.devtools.NetworkInterceptor; - import org.openqa.selenium.remote.http.Contents; - import org.openqa.selenium.remote.http.Filter; - import org.openqa.selenium.remote.http.HttpResponse; - import org.openqa.selenium.remote.http.Route; - - 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://example-sausages-site.com"); - - String source = driver.getPageSource(); - - assertThat(source).contains("delicious cheese!"); -{{< /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.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 index da2aaa9abaa8..6965c884fc70 100644 --- 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 @@ -25,18 +25,23 @@ do with it are given below. 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. -* If your use case has an example in the [BiDi API]({{< ref "bidi_api.md" >}}), you should definitely use it, -as it should remain future-compatible. -* You might prefer [CDP API]({{< ref "cdp_api.md" >}}) to avoid learning all the magic strings; it ensures -your code is compatible with the latest version of Chrome. These methods will be removed at some point. -* You might prefer [CDP Endpoint]({{< ref "cdp_endpoint.md" >}}) to avoid managing Chrome versions; or if your use -case is simple and the CDP API is too complicated. These methods will be removed at some point. +* 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 doing this with CDP. +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 index bdadbaeab8a9..c30c98d12f4c 100644 --- 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 @@ -7,6 +7,8 @@ description: > 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 @@ -15,28 +17,35 @@ is additional functionality you'd like to see, please raise a 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. -## Register Basic Auth +## 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/BidiApiTest.java#L34-L36" >}} +{{< 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/BidiApiTest.cs#L16-L24" >}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/BidiApiTest.cs#L18-L27" >}} {{% /tab %}} {{% tab header="Ruby" %}} -{{< gh-codeblock path="/examples/ruby/spec/bidirectional/bidi_api_spec.rb#L9-L11" >}} +{{< 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'); @@ -58,7 +67,6 @@ const {Builder} = require('selenium-webdriver'); {{% /tab %}} {{% tab header="Kotlin" %}} {{< badge-examples >}} - ```java val uriPredicate = Predicate { uri: URI -> uri.host.contains("your-domain.com") @@ -70,7 +78,8 @@ driver.get("https://your-domain.com/login") {{< /tabpane >}} -## Pin Scripts +### 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 @@ -78,16 +87,16 @@ to the script execution endpoint. These files are each about 50kB, which adds up {{< tabpane text=true langEqualsHeader=true >}} {{% tab header="Java" %}} -{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/BidiApiTest.java#L54-L61" >}} +{{< badge-implementation >}} {{% /tab %}} {{% tab header="Python" %}} {{< badge-implementation >}} {{% /tab %}} {{% tab header="CSharp" %}} -{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/BidiApiTest.cs#L16-L24" >}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/BidiApiTest.cs#L41-L43" >}} {{% /tab %}} {{% tab header="Ruby" %}} -{{< gh-codeblock path="/examples/ruby/spec/bidirectional/bidi_api_spec.rb#L38-L45" >}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/bidi_api_spec.rb#L22-L23" >}} {{% /tab %}} {{% tab header="JavaScript" %}} {{< badge-implementation >}} @@ -98,98 +107,28 @@ to the script execution endpoint. These files are each about 50kB, which adds up {{< /tabpane >}} -## Mutation Observation +### 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" >}} -ChromeDriver driver = new ChromeDriver(); - -AtomicReference seen = new AtomicReference<>(); -CountDownLatch latch = new CountDownLatch(1); -((HasLogEvents) driver).onLogEvent(domMutation(mutation -> { - seen.set(mutation); - latch.countDown(); -})); - -driver.get("https://www.google.com"); -WebElement span = driver.findElement(By.cssSelector("span")); - -((JavascriptExecutor) driver).executeScript("arguments[0].setAttribute('cheese', 'gouda');", span); - -assertThat(latch.await(10, SECONDS), is(true)); -assertThat(seen.get().getAttributeName(), is("cheese")); -assertThat(seen.get().getCurrentValue(), is("gouda")); - -driver.quit(); - {{< /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 >}} +{{< 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" >}} -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 +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/bidi_api_spec.rb#L31-L32" >}} {{< /tab >}} - {{< tab header="JavaScript" >}} + {{% tab header="JavaScript" %}} + {{< badge-examples >}} +```js const {Builder, until} = require('selenium-webdriver'); const assert = require("assert"); @@ -215,81 +154,39 @@ const assert = require("assert"); console.log(e) } }()) - {{< /tab >}} +``` +{{% /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") +### Console logs and errors - 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"]) +Listen to the `console.log` events and register callbacks to process the event. - driver.quit() +[CDP API Console logs]({{< ref "cdp_api#console-logs-and-errors" >}}) +and [WebDriver BiDi Console logs]({{< ref "../webdriver_bidi/log#console-logs" >}}) -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" >}} +{{< 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 { @@ -307,8 +204,11 @@ const {Builder} = require('selenium-webdriver'); console.log(e); } })() -{{< /tab >}} -{{< tab header="Kotlin" >}} +``` +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-examples >}} +```java fun kotlinConsoleLogExample() { val driver = ChromeDriver() val devTools = driver.devTools @@ -327,199 +227,83 @@ fun kotlinConsoleLogExample() { input.sendKeys(Keys.RETURN) driver.quit() } -{{< /tab >}} +``` +{{% /tab %}} {{< /tabpane >}} -## Listen to JS Exceptions + +### JavaScript 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(); +{{< 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 >}} - 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) +### Network Interception - driver.get("https://www.google.com") +Both requests and responses can be recorded or transformed. - 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() +#### Response information - driver.quit() -} -{{< /tab >}} +{{< 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 >}} -## 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. +#### Response transformation -### Intercept Responses - -{{< tabpane langEqualsHeader=true >}} -{{< badge-examples >}} +{{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} - import org.openqa.selenium.WebDriver; - import org.openqa.selenium.devtools.HasDevTools; - import org.openqa.selenium.devtools.NetworkInterceptor; - import org.openqa.selenium.remote.http.Contents; - import org.openqa.selenium.remote.http.Filter; - import org.openqa.selenium.remote.http.HttpResponse; - import org.openqa.selenium.remote.http.Route; - - 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://example-sausages-site.com"); - - String source = driver.getPageSource(); - - assertThat(source).contains("delicious cheese!"); +{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/chrome_devtools/BidiApiTest.java#L111-L121" >}} {{< /tab >}} {{< tab header="Python" >}} -Currently unavailable in python due the inability to mix certain async and sync commands +{{< badge-implementation >}} {{< /tab >}} {{< tab header="CSharp" text=true >}} -{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/BidiApiTest.cs#L33-L48" >}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/BidiApiTest.cs#L143-L156" >}} {{< /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') +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/bidi_api_spec.rb#L79-L83" >}} {{< /tab >}} - -{{< tab header="JavaScript" >}} +{{% tab header="JavaScript" %}} +{{< badge-examples >}} +```js const connection = await driver.createCDPConnection('page') let url = fileServer.whereIs("/cheese") let httpResponse = new HttpResponse(url) @@ -530,8 +314,11 @@ await driver.onIntercept(connection, httpResponse, async function () { assert.strictEqual(body.includes("sausages"), true, `Body contains: ${body}`) }) driver.get(url) -{{< /tab >}} -{{< tab header="Kotlin" >}} +``` +{{% /tab %}} +{{% tab header="Kotlin" %}} +{{< badge-examples >}} +```java val driver = ChromeDriver() val interceptor = new NetworkInterceptor( driver, @@ -544,23 +331,24 @@ val interceptor = new NetworkInterceptor( driver.get(appServer.whereIs("/cheese")) String source = driver.getPageSource() -{{< /tab >}} +``` +{{% /tab %}} {{< /tabpane >}} -### Intercept Requests +#### Request interception {{< tabpane text=true langEqualsHeader=true >}} {{< tab header="Java" >}} -{{< badge-code >}} +{{< badge-implementation >}} {{< /tab >}} {{< tab header="Python" >}} -{{< badge-code >}} +{{< badge-implementation >}} {{< /tab >}} {{< tab header="CSharp" >}} -{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/BidiApiTest.cs#L56-L71" >}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/BidiApiTest.cs#L167-L181" >}} {{< /tab >}} {{< tab header="Ruby" >}} -{{< badge-code >}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/bidi_api_spec.rb#L90-L94" >}} {{< /tab >}} {{< tab header="JavaScript" >}} {{< badge-code >}} 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 index 80c891ac1dad..b8e85ed12d53 100644 --- 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 @@ -3,7 +3,8 @@ title: "Chrome DevTools Protocol API" linkTitle: "CDP API" weight: 4 description: > - Each Selenium binding dynamically creates the classes and generates the methods for each new version of Chrome. + 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" %}} @@ -30,20 +31,20 @@ An alternate implementation can be found at [CDP Endpoint Set Cookie]({{< ref "c {{% 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/CdpApiTest.java#L39-L57" >}} +{{< 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/test_cdp_api.py#L10-L17" >}} +{{< 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/CdpApiTest.cs#L25-L39" >}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/CdpApiTest.cs#L25-L37" >}} {{% /tab %}} {{% tab header="Ruby" %}} -{{< gh-codeblock path="/examples/ruby/spec/bidirectional/cdp_api_spec.rb#L9-L12" >}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/cdp_api_spec.rb#L9-L12" >}} {{% /tab %}} {{% tab header="JavaScript" %}} {{< badge-code >}} @@ -59,20 +60,20 @@ An alternate implementation can be found at [CDP Endpoint Performance Metrics]({ {{< tabpane text=true langEqualsHeader=true >}} {{% tab header="Java" %}} -{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/CdpApiTest.java#L68-L73" >}} +{{< 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/test_cdp_api.py#L29-L32" >}} +{{< 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/CdpApiTest.cs#L51-L60" >}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/CdpApiTest.cs#L49-L56" >}} {{% /tab %}} {{% tab header="Ruby" %}} -{{< gh-codeblock path="/examples/ruby/spec/bidirectional/cdp_api_spec.rb#L23-L24" >}} +{{< gh-codeblock path="/examples/ruby/spec/bidirectional/chrome_devtools/cdp_api_spec.rb#L23-L25" >}} {{% /tab %}} {{% tab header="JavaScript" %}} {{< badge-code >}} @@ -82,27 +83,30 @@ Due to the added complexity in .NET of obtaining the domains and executing with {{% /tab %}} {{< /tabpane >}} -### Basic Authentication +### Basic authentication -An alternate implementation can be found at -[CDP Endpoint Basic Authentication]({{< ref "cdp_endpoint#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" %}} -{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/CdpApiTest.java#L86-L94" >}} +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/test_cdp_api.py#L42-L46" >}} +{{< 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/CdpApiTest.cs#L73-L87" >}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/CdpApiTest.cs#L70-L83" >}} {{% /tab %}} {{% tab header="Ruby" %}} -{{< gh-codeblock path="/examples/ruby/spec/bidirectional/cdp_endpoint_spec.rb#L35-L38" >}} +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 >}} @@ -112,23 +116,88 @@ Due to the added complexity in .NET of obtaining the domains and executing with {{% /tab %}} {{< /tabpane >}} -### Console Logs +### 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" %}} -{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/CdpApiTest.java#L107-L118" >}} +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" %}} -{{< gh-codeblock path="/examples/ruby/spec/bidirectional/cdp_endpoint_spec.rb#L46-L51" >}} +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 >}} 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 index 82f88f2d8f5b..4952fae2e0dd 100644 --- 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 @@ -8,7 +8,7 @@ description: > --- {{% pageinfo color="warning" %}} -These methods will eventually be removed. It is recommended to use the [WebDriver-BiDi]({{< ref "../webdriver_bidi/" >}}) [WebDriver Bidi APIs]({{< ref "bidi_api.md" >}}) +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 %}} @@ -19,7 +19,7 @@ Generally you should prefer the use of the [CDP API]({{< ref "cdp_api.md" >}}) o but sometimes the syntax is cleaner or significantly more simple. Limitations include: -* It only works for use cases that only require setting or getting information; +* 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 @@ -32,16 +32,17 @@ An alternate implementation can be found at [CDP API Set Cookie]({{< ref "cdp_ap {{< tabpane text=true langEqualsHeader=true >}} {{% tab header="Java" %}} -{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/CdpEndpointTest.java#L26-L34" >}} +{{< 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/test_cdp_endpoint.py#L7-L11" >}} +{{< 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/CdpEndpointTest.cs#L25-L33" >}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/CdpEndpointTest.cs#L25-L33" >}} {{% /tab %}} {{% tab header="Ruby" %}} -{{< gh-codeblock path="/examples/ruby/spec/bidirectional/cdp_endpoint_spec.rb#L9-L13" >}} +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 >}} @@ -57,16 +58,18 @@ An alternate implementation can be found at [CDP API Performance Metrics]({{< re {{< tabpane text=true langEqualsHeader=true >}} {{% tab header="Java" %}} -{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/CdpEndpointTest.java#L45-L49" >}} +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/test_cdp_endpoint.py#L22-L23" >}} +{{< 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/CdpEndpointTest.cs#L46-L49" >}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/CdpEndpointTest.cs#L46-L49" >}} {{% /tab %}} {{% tab header="Ruby" %}} -{{< gh-codeblock path="/examples/ruby/spec/bidirectional/cdp_endpoint_spec.rb#L24-L25" >}} +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 >}} @@ -76,22 +79,25 @@ An alternate implementation can be found at [CDP API Performance Metrics]({{< re {{% /tab %}} {{< /tabpane >}} -### Basic Authentication +### Basic authentication -An alternate implementation can be found at [CDP API Basic Authentication]({{< ref "cdp_api#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" %}} -{{< gh-codeblock path="/examples/java/src/test/java/dev/selenium/bidirectional/CdpEndpointTest.java#L63-L70" >}} +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/test_cdp_endpoint.py#L32-L36" >}} +{{< 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/CdpEndpointTest.cs#L66-L74" >}} +{{< gh-codeblock path="/examples/dotnet/SeleniumDocs/Bidirectional/ChromeDevtools/CdpEndpointTest.cs#L65-L73" >}} {{% /tab %}} {{% tab header="Ruby" %}} -{{< gh-codeblock path="/examples/ruby/spec/bidirectional/cdp_endpoint_spec.rb#L36-L40" >}} +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 >}} 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.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.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 3b8e2215d699..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/webdriver_bidi/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/webdriver_bidi/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/webdriver_bidi/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/webdriver_bidi/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/webdriver_bidi/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/webdriver_bidi/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/webdriver_bidi/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/webdriver_bidi/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/webdriver_bidi/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/webdriver_bidi/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/webdriver_bidi/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 5054eb2ed7d8..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/webdriver_bidi/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/webdriver_bidi/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/webdriver_bidi/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/webdriver_bidi/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/webdriver_bidi/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/webdriver_bidi/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/webdriver_bidi/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/webdriver_bidi/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/webdriver_bidi/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/webdriver_bidi/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/webdriver_bidi/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 05e8c0b51268..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/webdriver_bidi/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/webdriver_bidi/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/webdriver_bidi/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/webdriver_bidi/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/webdriver_bidi/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/webdriver_bidi/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/webdriver_bidi/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/webdriver_bidi/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/webdriver_bidi/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/webdriver_bidi/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/webdriver_bidi/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/webdriver_bidi/log.en.md b/website_and_docs/content/documentation/webdriver/bidirectional/webdriver_bidi/log.en.md index 70703e1b061d..767681068e03 100644 --- a/website_and_docs/content/documentation/webdriver/bidirectional/webdriver_bidi/log.en.md +++ b/website_and_docs/content/documentation/webdriver/bidirectional/webdriver_bidi/log.en.md @@ -9,7 +9,7 @@ aliases: [ 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. @@ -29,7 +29,7 @@ Listen to the `console.log` events and register callbacks to process the event. {{< /tab >}} {{< /tabpane >}} -## Listen to JS Exceptions +## JavaScript exceptions Listen to the JS Exceptions and register callbacks to process the exception details. 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 72% 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 907a40c6a4e2..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/webdriver_bidi/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/webdriver_bidi/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/webdriver_bidi/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 72% 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 02f532c24cfa..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/webdriver_bidi/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/webdriver_bidi/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/webdriver_bidi/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 b99722875856..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/webdriver_bidi/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/webdriver_bidi/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/webdriver_bidi/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.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.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