This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

BiDirectional API (W3C compliant)

Examples of working with Chrome DevTools Protocol in Selenium. CDP support is temporary until WebDriver BiDi has been implemented.

The following list of APIs will be growing as the WebDriver BiDirectional Protocol grows and browser vendors implement the same. Additionally, Selenium will try to support real-world use cases that internally use a combination of W3C BiDi protocol APIs.

If there is additional functionality you’d like to see, please raise a feature request.

1 - Browsing Context

Commands

This section contains the APIs related to browsing context commands.

Open a new window

Creates a new browsing context in a new window.

Selenium v4.8

        Assertions.assertEquals(id, browsingContext.getId());
    }

    @Test

Selenium v4.8

  it 'creates a window' do
    browsing_context = Selenium::WebDriver::BiDi::BrowsingContext.new(
      driver, type_hint: :window
    )
    expect(browsing_context.id).not_to be_nil

Selenium v4.8

    const browsingContext = await BrowsingContext(driver, {
      type: 'window',
    })

Selenium v4.8

def test_create_window(driver):
    browsing_context = (
        driver.bidi_connection.bidi_session.browsing_context.create(
            type_hint=WindowTypes.WINDOW
        )
    )
    assert browsing_context is not None

Open a new tab

Creates a new browsing context in a new tab.

Selenium v4.8


    @Test
    void testNavigateToAUrl() {
        BrowsingContext browsingContext = new BrowsingContext(driver, WindowType.TAB);

Selenium v4.8

  it 'creates a tab' do
    browsing_context = Selenium::WebDriver::BiDi::BrowsingContext.new(
      driver, type_hint: :tab
    )
    expect(browsing_context.id).not_to be_nil

Selenium v4.8

    const browsingContext = await BrowsingContext(driver, {
      type: 'tab',
    })

Selenium v4.8

def test_create_tab(driver):
    browsing_context = (
        driver.bidi_connection.bidi_session.browsing_context.create(
            type_hint=WindowTypes.TAB
        )
    )
    assert browsing_context is not None

Use existing window handle

Creates a browsing context for the existing tab/window to run commands.

Selenium v4.8

        wait = new WebDriverWait(driver, Duration.ofSeconds(10));
    }

    @Test
    void testCreateABrowsingContextForGivenId() {

Selenium v4.8

  it 'creates browsing context for given id' do
    id = driver.window_handle
    browsing_context = Selenium::WebDriver::BiDi::BrowsingContext.new(
      driver, context_id: id
    )
    expect(browsing_context.id).to eq(id)

Selenium v4.8

    const id = await driver.getWindowHandle()
    const browsingContext = await BrowsingContext(driver, {
      browsingContextId: id,
    })

Selenium v4.8

def test_create_browsing_context_for_given_id(driver):
    id = driver.current_window_handle
    browsing_context = (
        driver.bidi_connection.bidi_session.browsing_context.create(
            context_id=id
        )
    )
    assert browsing_context == id

Open a window with a reference browsing context

A reference browsing context is a top-level browsing context. The API allows to pass the reference browsing context, which is used to create a new window. The implementation is operating system specific.

Selenium v4.8

        Assertions.assertNotNull(browsingContext.getId());
    }

    @Test
    void testCreateATab() {
        BrowsingContext browsingContext = new BrowsingContext(driver, WindowType.TAB);

Selenium v4.8

    const browsingContext = await BrowsingContext(driver, {
      type: 'window',
      referenceContext: await driver.getWindowHandle(),
    })

Open a tab with a reference browsing context

A reference browsing context is a top-level browsing context. The API allows to pass the reference browsing context, which is used to create a new tab. The implementation is operating system specific.

Selenium v4.8


        Assertions.assertNotNull(browsingContext.getId());
        Assertions.assertNotNull(info.getNavigationId());
        Assertions.assertTrue(info.getUrl().contains("/bidi/logEntryAdded.html"));
    }

Selenium v4.8

    const browsingContext = await BrowsingContext(driver, {
      type: 'tab',
      referenceContext: await driver.getWindowHandle(),
    })

Selenium v4.8

        BrowsingContext browsingContext = new BrowsingContext(driver, WindowType.TAB);

        NavigationResult info = browsingContext.navigate("https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html",
                ReadinessState.COMPLETE);

        Assertions.assertNotNull(browsingContext.getId());
        Assertions.assertNotNull(info.getNavigationId());
        Assertions.assertTrue(info.getUrl().contains("/bidi/logEntryAdded.html"));
    }

Selenium v4.8

  it 'navigates to a url' do
    browsing_context = Selenium::WebDriver::BiDi::BrowsingContext.new(
      driver, type_hint: :tab
    )

    navigation_info = browsing_context.navigate(
      'https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html'
    )

    expect(browsing_context.id).not_to be_nil
    expect(navigation_info['navigation_id']).not_to be_nil
    expect(navigation_info['url']).to include('/bidi/logEntryAdded.html')

Selenium v4.8

    let info = await browsingContext.navigate('https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html')

Selenium v4.8

def test_navigate_to_url(driver):
    browsing_context = (
        driver.bidi_connection.bidi_session.browsing_context.create(
            type_hint=WindowTypes.TAB
        )
    )

    navigation_info = (
        driver.bidi_connection.bidi_session.browsing_context.navigate(
            context=browsing_context,
            url="https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html"
        )
    )

    assert browsing_context is not None
    assert navigation_info.get('navigation_id') is not None
    assert "/bidi/logEntryAdded.html" in navigation_info.get('url', '')

Selenium v4.8

    void testGetTreeWithAChild() {
        String referenceContextId = driver.getWindowHandle();
        BrowsingContext parentWindow = new BrowsingContext(driver, referenceContextId);

        parentWindow.navigate("https://www.selenium.dev/selenium/web/iframes.html", ReadinessState.COMPLETE);

        List<BrowsingContextInfo> contextInfoList = parentWindow.getTree();

        Assertions.assertEquals(1, contextInfoList.size());
        BrowsingContextInfo info = contextInfoList.get(0);

Selenium v4.8

    const info = await browsingContext.navigate(
      'https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html',
      'complete'
    )

Get browsing context tree

Provides a tree of all browsing contexts descending from the parent browsing context, including the parent browsing context.

Selenium v4.8

        Assertions.assertTrue(info.getChildren().get(0).getUrl().contains("formPage.html"));
    }

    @Test
    void testGetTreeWithDepth() {
        String referenceContextId = driver.getWindowHandle();
        BrowsingContext parentWindow = new BrowsingContext(driver, referenceContextId);

        parentWindow.navigate("https://www.selenium.dev/selenium/web/iframes.html", ReadinessState.COMPLETE);

        List<BrowsingContextInfo> contextInfoList = parentWindow.getTree(0);

        Assertions.assertEquals(1, contextInfoList.size());
        BrowsingContextInfo info = contextInfoList.get(0);

Selenium v4.8

  it 'gets tree with children' do
    reference_context_id = driver.window_handle
    browsing_context = Selenium::WebDriver::BiDi::BrowsingContext.new(
      driver, context_id: reference_context_id
    )

    browsing_context.navigate('https://www.selenium.dev/selenium/web/iframes.html')
    tree = browsing_context.get_tree

    expect(tree).not_to be_empty
    expect(tree.first['context']).to eq(reference_context_id)
    expect(tree.first['children']).not_to be_empty

Selenium v4.8

    const browsingContextId = await driver.getWindowHandle()
    const parentWindow = await BrowsingContext(driver, {
      browsingContextId: browsingContextId,
    })
    await parentWindow.navigate('https://www.selenium.dev/selenium/web/iframes.html', 'complete')

    const contextInfo = await parentWindow.getTree()

Selenium v4.8

def test_get_tree(driver):
    reference_context_id = driver.current_window_handle

    driver.get("https://www.selenium.dev/selenium/web/iframes.html")
    tree = (
        driver.bidi_connection.bidi_session.browsing_context.get_tree(
            root=reference_context_id
        )
    )

    assert tree is not None
    assert len(tree) > 0
    assert tree[0].get('context') == reference_context_id

Get browsing context tree with depth

Provides a tree of all browsing contexts descending from the parent browsing context, including the parent browsing context upto the depth value passed.

Selenium v4.8

    }

    @Test
    void testGetAllTopLevelContexts() {
        BrowsingContext window1 = new BrowsingContext(driver, driver.getWindowHandle());
        BrowsingContext window2 = new BrowsingContext(driver, WindowType.WINDOW);

        List<BrowsingContextInfo> contextInfoList = window1.getTopLevelContexts();

        Assertions.assertEquals(2, contextInfoList.size());
    }

    @Test

Selenium v4.8

    const browsingContextId = await driver.getWindowHandle()
    const parentWindow = await BrowsingContext(driver, {
      browsingContextId: browsingContextId,
    })
    await parentWindow.navigate('https://www.selenium.dev/selenium/web/iframes.html', 'complete')

    const contextInfo = await parentWindow.getTree(0)

Get All Top level browsing contexts

Selenium v4.8

        BrowsingContext window2 = new BrowsingContext(driver, WindowType.WINDOW);

        window2.close();

        Assertions.assertThrows(BiDiException.class, window2::getTree);
    }

    @Test

Selenium v4.20.0

    const id = await driver.getWindowHandle()
    const window1 = await BrowsingContext(driver, {
      browsingContextId: id,
    })
    await BrowsingContext(driver, { type: 'window' })
    const res = await window1.getTopLevelContexts()

Close a tab/window

Selenium v4.8

        BrowsingContext tab2 = new BrowsingContext(driver, WindowType.TAB);

        tab2.close();

        Assertions.assertThrows(BiDiException.class, tab2::getTree);
    }

    @Test
    void testActivateABrowsingContext() {
        BrowsingContext window1 = new BrowsingContext(driver, driver.getWindowHandle());
        BrowsingContext window2 = new BrowsingContext(driver, WindowType.WINDOW);

        window1.activate();

        boolean isFocused = (boolean) ((JavascriptExecutor) driver).executeScript("return document.hasFocus();");

        Assertions.assertTrue(isFocused);
    }

Selenium v4.8

  it 'closes a window' do
    browsing_context = Selenium::WebDriver::BiDi::BrowsingContext.new(
      driver, type_hint: :window
    )

    expect { browsing_context.close }.not_to raise_error
  end

  it 'closes a tab' do
    browsing_context = Selenium::WebDriver::BiDi::BrowsingContext.new(
      driver, type_hint: :tab
    )

    expect { browsing_context.close }.not_to raise_error

Selenium v4.8

    const window1 = await BrowsingContext(driver, {type: 'window'})
    const window2 = await BrowsingContext(driver, {type: 'window'})

    await window2.close()

Selenium v4.8

def test_close_window(driver):
    browsing_context = (
        driver.bidi_connection.bidi_session.browsing_context.create(
            type_hint=WindowTypes.WINDOW
        )
    )

    driver.bidi_connection.bidi_session.browsing_context.close(
        context=browsing_context
    )
    # If no exception is raised, the close was successful

Activate a browsing context

Selenium v4.14.1

        BrowsingContext browsingContext = new BrowsingContext(driver, WindowType.TAB);

        browsingContext.navigate("https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html", ReadinessState.COMPLETE);

        NavigationResult reloadInfo = browsingContext.reload(ReadinessState.INTERACTIVE);

Selenium v4.14.1

  it 'activates a browsing context' do
    browsing_context = Selenium::WebDriver::BiDi::BrowsingContext.new(
      driver, type_hint: :tab
    )

    expect { browsing_context.activate }.not_to raise_error

Selenium v4.15

    const window1 = await BrowsingContext(driver, {
      browsingContextId: id,
    })
    await window1.activate()

Selenium v4.14.1

def test_activate_browsing_context(driver):
    browsing_context = (
        driver.bidi_connection.bidi_session.browsing_context.create(
            type_hint=WindowTypes.TAB
        )
    )

    driver.bidi_connection.bidi_session.browsing_context.activate(
        context=browsing_context
    )
    # If no exception is raised, the activate was successful

Reload a browsing context

Selenium v4.13.0

        BrowsingContext browsingContext = new BrowsingContext(driver, driver.getWindowHandle());

        driver.get("https://www.selenium.dev/selenium/web/alerts.html");

        driver.findElement(By.id("alert")).click();

Selenium v4.13.0

  it 'reloads a browsing context' do
    browsing_context = Selenium::WebDriver::BiDi::BrowsingContext.new(
      driver, type_hint: :tab
    )

    browsing_context.navigate('https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html')

    navigation_info = browsing_context.reload

    expect(navigation_info).not_to be_nil

Selenium v4.15

    await browsingContext.reload(undefined, 'complete')

Selenium v4.13.0

def test_reload_browsing_context(driver):
    browsing_context = (
        driver.bidi_connection.bidi_session.browsing_context.create(
            type_hint=WindowTypes.TAB
        )
    )
    driver.bidi_connection.bidi_session.browsing_context.navigate(
        context=browsing_context,
        url="https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html"
    )

    navigation_info = (
        driver.bidi_connection.bidi_session.browsing_context.reload(
            context=browsing_context
        )
    )

Handle user prompt

Selenium v4.13.0

    @Test
    void testDismissUserPromptWithText() {
        BrowsingContext browsingContext = new BrowsingContext(driver, driver.getWindowHandle());

        driver.get("https://www.selenium.dev/selenium/web/alerts.html");

        driver.findElement(By.id("prompt-with-default")).click();

        String userText = "Selenium automates browsers";

Selenium v4.15

    await browsingContext.handleUserPrompt(true, userText)

Capture Screenshot

Selenium v4.13.0


        driver.get("https://www.selenium.dev/selenium/web/coordinates_tests/simple_page.html");

        WebElement element = driver.findElement(By.id("box"));
        Rectangle elementRectangle = element.getRect();

Selenium v4.15

    const response = await browsingContext.captureScreenshot()

Capture Viewport Screenshot

Selenium v4.14.0

    }

    @Test
    void textCaptureElementScreenshot() {
        BrowsingContext browsingContext = new BrowsingContext(driver, driver.getWindowHandle());

        driver.get("https://www.selenium.dev/selenium/web/formPage.html");
        WebElement element = driver.findElement(By.id("checky"));

        String screenshot = browsingContext.captureElementScreenshot(((RemoteWebElement) element).getId());

Selenium v4.15

    const browsingContext = await BrowsingContext(driver, {
      browsingContextId: id,
    })

    const response = await browsingContext.captureBoxScreenshot(5, 5, 10, 10)

Capture Element Screenshot

Selenium v4.14.0

        BrowsingContext browsingContext = new BrowsingContext(driver, driver.getWindowHandle());
        driver.get("https://www.selenium.dev/selenium/web/formPage.html");

        browsingContext.setViewport(250, 300);

        List<Long> newViewportSize =

Selenium v4.15

    const response = await browsingContext.captureElementScreenshot(elementId)

Set Viewport

Selenium v4.14.1

        BrowsingContext browsingContext = new BrowsingContext(driver, driver.getWindowHandle());

        driver.get("https://www.selenium.dev/selenium/web/formPage.html");
        PrintOptions printOptions = new PrintOptions();

Selenium v4.15

    await browsingContext.setViewport(250, 300)

Selenium v4.14.1

        browsingContext.navigate("https://www.selenium.dev/selenium/web/formPage.html", ReadinessState.COMPLETE);

        wait.until(visibilityOfElementLocated(By.id("imageButton"))).submit();
        wait.until(titleIs("We Arrive Here"));

        browsingContext.back();

Selenium v4.10

    const result = await browsingContext.printPage({
      orientation: 'landscape',
      scale: 1,
      background: true,
      width: 30,
      height: 30,
      top: 1,
      bottom: 1,
      left: 1,
      right: 1,
      shrinkToFit: true,
      pageRanges: ['1-2'],
    })

Selenium v4.16.0


        wait.until(visibilityOfElementLocated(By.id("imageButton"))).submit();
        wait.until(titleIs("We Arrive Here"));

        browsingContext.back();
        Assertions.assertTrue(driver.getPageSource().contains("We Leave From Here"));

Selenium v4.17

    await browsingContext.back()

Selenium v4.16.0

    void canTraverseBrowserHistory() {
        BrowsingContext browsingContext = new BrowsingContext(driver, driver.getWindowHandle());
        browsingContext.navigate("https://www.selenium.dev/selenium/web/formPage.html", ReadinessState.COMPLETE);

        wait.until(visibilityOfElementLocated(By.id("imageButton"))).submit();
        wait.until(titleIs("We Arrive Here"));

        browsingContext.traverseHistory(-1);
        Assertions.assertTrue(driver.getPageSource().contains("We Leave From Here"));
    }
}

Selenium v4.17

    await browsingContext.forward()

Traverse history

Selenium v4.16.0

Selenium v4.17

    await browsingContext.traverseHistory(-1)

Events

This section contains the APIs related to browsing context events.

Browsing Context Created Event

Selenium v4.10

    try (BrowsingContextInspector inspector = new BrowsingContextInspector(driver)) {
        CompletableFuture<BrowsingContextInfo> future = new CompletableFuture<>();

        inspector.onBrowsingContextCreated(future::complete);

        String windowHandle = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle();

        BrowsingContextInfo browsingContextInfo = future.get(5, TimeUnit.SECONDS);

Selenium v4.9.2

    const browsingContextInspector = await BrowsingContextInspector(driver)
    await browsingContextInspector.onBrowsingContextCreated((entry) => {
      contextInfo = entry
    })

    await driver.switchTo().newWindow('window')

Dom Content loaded Event

Selenium v4.10

            String windowHandle = driver.switchTo().newWindow(WindowType.TAB).getWindowHandle();

            BrowsingContextInfo browsingContextInfo = future.get(5, TimeUnit.SECONDS);

            Assertions.assertEquals(windowHandle, browsingContextInfo.getId());
        }
    }

    @Test
    void canListenToDomContentLoadedEvent()

Selenium v4.9.2

    const browsingContextInspector = await BrowsingContextInspector(driver)
    let navigationInfo = null
    await browsingContextInspector.onDomContentLoaded((entry) => {
      navigationInfo = entry
    })

    const browsingContext = await BrowsingContext(driver, {
      browsingContextId: await driver.getWindowHandle(),
    })
    await browsingContext.navigate('https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html', 'complete')

Browsing Context Loaded Event

Selenium v4.10

        try (BrowsingContextInspector inspector = new BrowsingContextInspector(driver)) {
            CompletableFuture<NavigationInfo> future = new CompletableFuture<>();
            inspector.onBrowsingContextLoaded(future::complete);

            BrowsingContext context = new BrowsingContext(driver, driver.getWindowHandle());
            context.navigate("https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html", ReadinessState.COMPLETE);

            NavigationInfo navigationInfo = future.get(5, TimeUnit.SECONDS);

Selenium v4.9.2

    const browsingContextInspector = await BrowsingContextInspector(driver)

    await browsingContextInspector.onBrowsingContextLoaded((entry) => {
      navigationInfo = entry
    })
    const browsingContext = await BrowsingContext(driver, {
      browsingContextId: await driver.getWindowHandle(),
    })
    await browsingContext.navigate('https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html', 'complete')

Selenium v4.15

        try (BrowsingContextInspector inspector = new BrowsingContextInspector(driver)) {
            CompletableFuture<NavigationInfo> future = new CompletableFuture<>();
            inspector.onNavigationStarted(future::complete);

            BrowsingContext context = new BrowsingContext(driver, driver.getWindowHandle());
            context.navigate("https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html", ReadinessState.COMPLETE);

            NavigationInfo navigationInfo = future.get(5, TimeUnit.SECONDS);

Fragment Navigated Event

Selenium v4.15

        try (BrowsingContextInspector inspector = new BrowsingContextInspector(driver)) {
            CompletableFuture<NavigationInfo> future = new CompletableFuture<>();

            BrowsingContext context = new BrowsingContext(driver, driver.getWindowHandle());
            context.navigate("https://www.selenium.dev/selenium/web/linked_image.html", ReadinessState.COMPLETE);

            inspector.onFragmentNavigated(future::complete);

            context.navigate("https://www.selenium.dev/selenium/web/linked_image.html#linkToAnchorOnThisPage", ReadinessState.COMPLETE);

            NavigationInfo navigationInfo = future.get(5, TimeUnit.SECONDS);

Selenium v4.15.0

    const browsingContextInspector = await BrowsingContextInspector(driver)

    const browsingContext = await BrowsingContext(driver, {
      browsingContextId: await driver.getWindowHandle(),
    })
    await browsingContext.navigate('https://www.selenium.dev/selenium/web/linked_image.html', 'complete')

    await browsingContextInspector.onFragmentNavigated((entry) => {
      navigationInfo = entry
    })

    await browsingContext.navigate('https://www.selenium.dev/selenium/web/linked_image.html#linkToAnchorOnThisPage', 'complete')

User Prompt Opened Event

Selenium v4.15

        try (BrowsingContextInspector inspector = new BrowsingContextInspector(driver)) {
            CompletableFuture<NavigationInfo> future = new CompletableFuture<>();

            BrowsingContext context = new BrowsingContext(driver, driver.getWindowHandle());
            context.navigate("https://www.selenium.dev/selenium/web/linked_image.html", ReadinessState.COMPLETE);

            inspector.onFragmentNavigated(future::complete);

            context.navigate("https://www.selenium.dev/selenium/web/linked_image.html#linkToAnchorOnThisPage", ReadinessState.COMPLETE);

            NavigationInfo navigationInfo = future.get(5, TimeUnit.SECONDS);

User Prompt Closed Event

Selenium v4.15

        try (BrowsingContextInspector inspector = new BrowsingContextInspector(driver)) {
            CompletableFuture<UserPromptClosed> future = new CompletableFuture<>();

            BrowsingContext context = new BrowsingContext(driver, driver.getWindowHandle());
            inspector.onUserPromptClosed(future::complete);

            driver.get("https://www.selenium.dev/selenium/web/alerts.html");

            driver.findElement(By.id("prompt")).click();

            context.handleUserPrompt(true, "selenium");

            UserPromptClosed userPromptClosed = future.get(5, TimeUnit.SECONDS);
            Assertions.assertEquals(context.getId(), userPromptClosed.getBrowsingContextId());

Browsing Context Destroyed Event

Selenium v4.18

        try (BrowsingContextInspector inspector = new BrowsingContextInspector(driver)) {
            CompletableFuture<BrowsingContextInfo> future = new CompletableFuture<>();

            inspector.onBrowsingContextDestroyed(future::complete);

            String windowHandle = driver.switchTo().newWindow(WindowType.WINDOW).getWindowHandle();

            driver.close();

            BrowsingContextInfo browsingContextInfo = future.get(5, TimeUnit.SECONDS);

            Assertions.assertEquals(windowHandle, browsingContextInfo.getId());

Selenium v4.18.0

    const browsingContextInspector = await BrowsingContextInspector(driver)
    await browsingContextInspector.onBrowsingContextDestroyed((entry) => {
      contextInfo = entry
    })

    await driver.switchTo().newWindow('window')

    const windowHandle = await driver.getWindowHandle()
    await driver.close()

2 - Input

This section contains the APIs related to input commands.

Perform Actions

Selenium v4.17

        Actions selectThreeOptions =
                actions.click(options.get(1)).keyDown(Keys.SHIFT).click(options.get(3)).keyUp(Keys.SHIFT);

        input.perform(windowHandle, selectThreeOptions.getSequences());

Selenium v4.17

  it 'sends keyboard input' do
    driver.navigate.to 'https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html'

    input_field = driver.find_element(id: 'textInput')
    input_field.send_keys('Hello World')

    expect(input_field.attribute('value')).to eq('Hello World')
  end

Selenium v4.17

    const actions = driver.actions().click(options[1]).keyDown(Key.SHIFT).click(options[3]).keyUp(Key.SHIFT).getSequences()

    await input.perform(browsingContextId, actions)

Selenium v4.17

    driver.get("https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html")

    input_field = driver.find_element(id="textInput")
    input_field.send_keys("Hello World")

    assert input_field.get_attribute("value") == "Hello World"


@pytest.mark.driver_type("bidi")
def test_input_mouse_click(driver):
    driver.get("https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html")

    button = driver.find_element(id="consoleLog")
    button.click()

    # Verify click occurred
    assert button is not None

Release Actions

Selenium v4.17

        Actions sendLowercase =
                new Actions(driver).keyDown(inputTextBox, "a").keyDown(inputTextBox, "b");

        input.perform(windowHandle, sendLowercase.getSequences());
        ((JavascriptExecutor) driver).executeScript("resetEvents()");

        input.release(windowHandle);

Selenium v4.17


    input_field = driver.find_element(id: 'textInput')
    input_field.send_keys('a')

    expect(input_field.attribute('value')).to include('a')
  end

  it 'clicks element' do
    driver.navigate.to 'https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html'

    button = driver.find_element(id: 'consoleLog')
    button.click

Selenium v4.17

    await input.release(browsingContextId)

Selenium v4.17


@pytest.mark.driver_type("bidi")
def test_dispatch_keyboard_events(driver):
    driver.get("https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html")

    driver.execute_script("""
        document.addEventListener('keydown', function(e) {
            console.log('Key pressed: ' + e.key);
        });
    """)

    body = driver.find_element(tag_name="body")
    body.send_keys("a")


@pytest.mark.driver_type("bidi")
def test_dispatch_mouse_events(driver):
    driver.get("https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html")

3 - Log

This section contains the APIs related to logging.

Console logs

Listen to the console.log events and register callbacks to process the event.

Selenium v4.8

            CompletableFuture<ConsoleLogEntry> future = new CompletableFuture<>();
            logInspector.onConsoleEntry(future::complete);

            driver.get("https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html");
            driver.findElement(By.id("consoleLog")).click();

            ConsoleLogEntry logEntry = future.get(5, TimeUnit.SECONDS);
    const inspector = await LogInspector(driver)
    await inspector.onConsoleEntry(function (log) {
      logEntry = log
    })

    await driver.get('https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html')
    await driver.findElement({id: 'consoleLog'}).click()

    assert.equal(logEntry.text, 'Hello, world!')
    assert.equal(logEntry.realm, null)
    assert.equal(logEntry.type, 'console')
    assert.equal(logEntry.level, 'info')
    assert.equal(logEntry.method, 'log')
    assert.equal(logEntry.stackTrace, null)
    assert.equal(logEntry.args.length, 1)

JavaScript exceptions

Listen to the JS Exceptions and register callbacks to process the exception details.

            logInspector.onJavaScriptException(future::complete);

            driver.get("https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html");
            driver.findElement(By.id("jsException")).click();

            JavascriptLogEntry logEntry = future.get(5, TimeUnit.SECONDS);
    const inspector = await LogInspector(driver)
    await inspector.onJavascriptException(function (log) {
      logEntry = log
    })

    await driver.get('https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html')
    await driver.findElement({id: 'jsException'}).click()

    assert.equal(logEntry.text, 'Error: Not working')
    assert.equal(logEntry.type, 'javascript')
    assert.equal(logEntry.level, 'error')

Listen to JS Logs

Listen to all JS logs at all levels and register callbacks to process the log.

Selenium v4.8

            logInspector.onJavaScriptLog(future::complete);

            driver.get("https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html");
            driver.findElement(By.id("jsException")).click();

            JavascriptLogEntry logEntry = future.get(5, TimeUnit.SECONDS);

4 - Network

Commands

This section contains the APIs related to network commands.

Add network intercept

Selenium v4.18

            String intercept =
                    network.addIntercept(new AddInterceptParameters(InterceptPhase.BEFORE_REQUEST_SENT));
            Assertions.assertNotNull(intercept);

Selenium v4.18

  it 'intercepts network requests' do
    request_events = []
    
    driver.bidi_connection.add_network_request_listener do |event|
      request_events << event

Selenium v4.18

    assert.notEqual(intercept, null)

Selenium v4.18

def test_intercept_network_requests(driver):
    request_events = []

    def on_request(event):
        request_events.append(event)

    driver.bidi_connection.add_network_request_listener(on_request)

    driver.get("https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html")

    wait = WebDriverWait(driver, 5)
    wait.until(lambda _: len(request_events) > 0)

    assert len(request_events) > 0

Remove network intercept

Selenium v4.18

                    network.addIntercept(new AddInterceptParameters(InterceptPhase.BEFORE_REQUEST_SENT));
            Assertions.assertNotNull(intercept);
            network.removeIntercept(intercept);
        }
    }

Selenium v4.18

    const intercept = await network.addIntercept(new AddInterceptParameters(InterceptPhase.BEFORE_REQUEST_SENT))
    assert.notEqual(intercept, null)

Continue request blocked at authRequired phase with credentials

Selenium v4.18

                    responseDetails ->
                            network.continueWithAuth(
                                    responseDetails.getRequest().getRequestId(),
                                    new UsernameAndPassword("admin", "admin")));
            driver.get("https://the-internet.herokuapp.com/basic_auth");
            String successMessage = "Congratulations! You must have the proper credentials.";
            WebElement elementMessage = driver.findElement(By.tagName("p"));
            Assertions.assertEquals(successMessage, elementMessage.getText());

Selenium v4.18


    await network.authRequired(async (event) => {
      await network.continueWithAuth(event.request.request, 'admin','admin')
    })
    await driver.get('https://the-internet.herokuapp.com/basic_auth')

Continue request blocked at authRequired phase without credentials

Selenium v4.18

                            // Does not handle the alert
                            network.continueWithAuthNoCredentials(responseDetails.getRequest().getRequestId()));
            driver.get("https://the-internet.herokuapp.com/basic_auth");
            Alert alert = wait.until(ExpectedConditions.alertIsPresent());
            alert.dismiss();
            Assertions.assertTrue(driver.getPageSource().contains("Not authorized"));
        }

Selenium v4.18


    await network.authRequired(async (event) => {
      await network.continueWithAuthNoCredentials(event.request.request)
    })

Cancel request blocked at authRequired phase

Selenium v4.18

                            network.cancelAuth(responseDetails.getRequest().getRequestId()));
            driver.get("https://the-internet.herokuapp.com/basic_auth");
            Assertions.assertTrue(driver.getPageSource().contains("Not authorized"));
        }
    }

    @Test

Selenium v4.18


    await network.authRequired(async (event) => {
      await network.cancelAuth(event.request.request)
    })

Fail request

Selenium v4.18

            }
    }
}

Events

This section contains the APIs related to network events.

Before Request Sent

Selenium v4.15

        try (Network network = new Network(driver)) {
            CompletableFuture<BeforeRequestSent> future = new CompletableFuture<>();
            network.onBeforeRequestSent(future::complete);
            driver.get("https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html");

            BeforeRequestSent requestSent = future.get(5, TimeUnit.SECONDS);

Selenium v4.15

  it 'intercepts network responses' do
    response_events = []
    
    driver.bidi_connection.add_network_response_listener do |event|
      response_events << event

Selenium v4.18

    let beforeRequestEvent = []
    const network = await Network(driver)
    await network.beforeRequestSent(function (event) {
      beforeRequestEvent.push(event)
    })

    await driver.get('https://www.selenium.dev/selenium/web/blank.html')

Selenium v4.15

def test_intercept_network_responses(driver):
    response_events = []

    def on_response(event):
        response_events.append(event)

    driver.bidi_connection.add_network_response_listener(on_response)

    driver.get("https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html")

    wait = WebDriverWait(driver, 5)
    wait.until(lambda _: len(response_events) > 0)

    assert len(response_events) > 0

Response Started

Selenium v4.15

        try (Network network = new Network(driver)) {
            CompletableFuture<ResponseDetails> future = new CompletableFuture<>();
            network.onResponseStarted(future::complete);
            driver.get("https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html");

            ResponseDetails response = future.get(5, TimeUnit.SECONDS);
            String windowHandle = driver.getWindowHandle();

Selenium v4.15

  it 'continues network request' do
    driver.navigate.to 'https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html'
    
    driver.bidi_connection.add_network_response_listener do |event|
      request_id = event['request']['request']
      driver.bidi_connection.bidi_session.network.continue_response(request: request_id)

Selenium v4.18

    let onResponseStarted = []
    const network = await Network(driver)
    await network.responseStarted(function (event) {
      onResponseStarted.push(event)
    })

    await driver.get('https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html')

Selenium v4.15

def test_continue_response(driver):
    # This test demonstrates intercepting and continuing responses
    driver.get("https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html")

    def on_response(event):
        request_id = event.get("request", {}).get("request")
        # Continue the response
        driver.bidi_connection.bidi_session.network.continue_response(
            request=request_id
        )

    driver.bidi_connection.add_network_response_listener(on_response)

    driver.get("https://www.selenium.dev/selenium/web/iframes.html")

Response Completed

Selenium v4.15

        try (Network network = new Network(driver)) {
            CompletableFuture<ResponseDetails> future = new CompletableFuture<>();
            network.onResponseCompleted(future::complete);
            driver.get("https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html");

            ResponseDetails response = future.get(5, TimeUnit.SECONDS);
            String windowHandle = driver.getWindowHandle();

Selenium v4.18

    let onResponseCompleted = []
    const network = await Network(driver)
    await network.responseCompleted(function (event) {
      onResponseCompleted.push(event)
    })

    await driver.get('https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html')

Auth Required

Selenium v4.17

        try (Network network = new Network(driver)) {
            CompletableFuture<ResponseDetails> future = new CompletableFuture<>();
            network.onAuthRequired(future::complete);
            driver.get("https://the-internet.herokuapp.com/basic_auth");

            ResponseDetails response = future.get(5, TimeUnit.SECONDS);

Selenium v4.17

  it 'intercepts network requests' do
    request_events = []
    
    driver.bidi_connection.add_network_request_listener do |event|
      request_events << event

Selenium v4.17

def test_intercept_network_auth_required(driver):
    auth_events = []

    def on_auth_required(event):
        auth_events.append(event)

    driver.bidi_connection.add_auth_required_listener(on_auth_required)

    # Navigate to a URL that requires authentication
    # This is a placeholder - actual auth required event would need
    # a protected resource
    driver.get("https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html")

5 - Script

Commands

This section contains the APIs related to script commands.

Call function in a browsing context

Selenium v4.15

        try (Script script = new Script(id, driver)) {
            List<LocalValue> arguments = new ArrayList<>();
            arguments.add(PrimitiveProtocolValue.numberValue(22));

            Map<Object, LocalValue> value = new HashMap<>();
            value.put("some_property", LocalValue.numberValue(42));
            LocalValue thisParameter = LocalValue.objectValue(value);

            arguments.add(thisParameter);

            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "function processWithPromise(argument) {\n"
                                    + "  return new Promise((resolve, reject) => {\n"
                                    + "    setTimeout(() => {\n"
                                    + "      resolve(argument + this.some_property);\n"
                                    + "    }, 1000)\n"
                                    + "  })\n"
                                    + "}",
                            true,
                            Optional.of(arguments),
                            Optional.of(thisParameter),
                            Optional.of(ResultOwnership.ROOT));

Selenium v4.15

  it 'calls a function' do
    driver.navigate.to 'https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html'

    result = driver.script.call_function(
      'function(a, b) { return a + b; }',
      args: [
        {type: 'number', value: 2},
        {type: 'number', value: 3}
      ]
    )

    expect(result['type']).to eq('number')
    expect(result['value']).to eq(5)

Selenium v4.9

    const manager = await ScriptManager(id, driver)

    let argumentValues = []
    let value = new ArgumentValue(LocalValue.createNumberValue(22))
    argumentValues.push(value)

    let mapValue = {some_property: LocalValue.createNumberValue(42)}
    let thisParameter = new ArgumentValue(LocalValue.createObjectValue(mapValue)).asMap()

    const result = await manager.callFunctionInBrowsingContext(
      id,
      'function processWithPromise(argument) {' +
      'return new Promise((resolve, reject) => {' +
      'setTimeout(() => {' +
      'resolve(argument + this.some_property);' +
      '}, 1000)' +
      '})' +
      '}',
      true,
      argumentValues,
      thisParameter,
      ResultOwnership.ROOT)

Selenium v4.15

def test_call_function(driver):
    driver.get("https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html")

    result = driver.script.call_function(
        "function(a, b) { return a + b; }",
        args=[{"type": "number", "value": 2}, {"type": "number", "value": 3}]
    )

    assert result.get("type") == "number"
    assert result.get("value") == 5

Call function in a sandbox

Selenium v4.15

        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.callFunctionInBrowsingContext(
                            id,
                            "sandbox",
                            "() => window.foo",
                            true,
                            Optional.empty(),
                            Optional.empty(),
                            Optional.empty());

Selenium v4.9

    const manager = await ScriptManager(id, driver)

    await manager.callFunctionInBrowsingContext(id, '() => { window.foo = 2; }', true, null, null, null, 'sandbox')

Call function in a realm

Selenium v4.15

        try (Script script = new Script(tab, driver)) {
            List<RealmInfo> realms = script.getAllRealms();
            String realmId = realms.get(0).getRealmId();

            EvaluateResult result = script.callFunctionInRealm(
                    realmId,
                    "() => { window.foo = 3; }",
                    true,
                    Optional.empty(),
                    Optional.empty(),
                    Optional.empty());

Selenium v4.15

  it 'gets realms' do
    driver.navigate.to 'https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html'

    realms = driver.script.get_realms

    expect(realms).not_to be_empty
    expect(realms.first).to have_key('realm')

Selenium v4.9

    const manager = await ScriptManager(firstTab, driver)

    const realms = await manager.getAllRealms()
    const realmId = realms[0].realmId

    await manager.callFunctionInRealm(realmId, '() => { window.foo = 3; }', true)

Selenium v4.15

def test_evaluate_with_realm(driver):
    driver.get("https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html")

    # Get realms
    realms = driver.script.get_realms()

    assert len(realms) > 0
    realm_id = realms[0].get("realm")

    # Evaluate in specific realm
    result = driver.script.evaluate("1 + 1", realm=realm_id)

    assert result.get("type") == "number"
    assert result.get("value") == 2

Evaluate script in a browsing context

Selenium v4.15

        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(id, "1 + 2", true, Optional.empty());

Selenium v4.15

  it 'evaluates a script' do
    driver.navigate.to 'https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html'

    result = driver.script.evaluate('2 + 2')

    expect(result['type']).to eq('number')
    expect(result['value']).to eq(4)

Selenium v4.9

    const manager = await ScriptManager(id, driver)

    const result = await manager.evaluateFunctionInBrowsingContext(id, '1 + 2', true)

Selenium v4.15

def test_evaluate_script(driver):
    driver.get("https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html")

    result = driver.script.evaluate("2 + 2")

    assert result.get("type") == "number"
    assert result.get("value") == 4

Evaluate script in a sandbox

Selenium v4.15

        try (Script script = new Script(id, driver)) {
            EvaluateResult result =
                    script.evaluateFunctionInBrowsingContext(
                            id, "sandbox", "window.foo", true, Optional.empty());

Selenium v4.9

    const manager = await ScriptManager(id, driver)

    await manager.evaluateFunctionInBrowsingContext(id, 'window.foo = 2', true, null, 'sandbox')

    const resultInSandbox = await manager.evaluateFunctionInBrowsingContext(id, 'window.foo', true, null, 'sandbox')

Evaluate script in a realm

Selenium v4.15

        try (Script script = new Script(tab, driver)) {
            List<RealmInfo> realms = script.getAllRealms();
            String realmId = realms.get(0).getRealmId();

            EvaluateResult result =
                    script.evaluateFunctionInRealm(
                            realmId, "window.foo", true, Optional.empty());

Selenium v4.15

  it 'evaluates in specific realm' do
    driver.navigate.to 'https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html'

    realms = driver.script.get_realms
    realm_id = realms.first['realm']

    result = driver.script.evaluate('1 + 1', realm: realm_id)

    expect(result['type']).to eq('number')
    expect(result['value']).to eq(2)

Selenium v4.9

    const manager = await ScriptManager(firstTab, driver)

    const realms = await manager.getAllRealms()
    const realmId = realms[0].realmId

    await manager.evaluateFunctionInRealm(realmId, 'window.foo = 3', true)

    const result = await manager.evaluateFunctionInRealm(realmId, 'window.foo', true)

Selenium v4.15

def test_evaluate_with_realm(driver):
    driver.get("https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html")

    # Get realms
    realms = driver.script.get_realms()

    assert len(realms) > 0
    realm_id = realms[0].get("realm")

    # Evaluate in specific realm
    result = driver.script.evaluate("1 + 1", realm=realm_id)

    assert result.get("type") == "number"
    assert result.get("value") == 2

Disown handles in a browsing context

Selenium v4.15

            script.disownBrowsingContextScript(

Selenium v4.15

  it 'disowns a value' do
    driver.navigate.to 'https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html'

    result = driver.script.evaluate('({x: 1})')
    handle = result['handle']

    expect { driver.script.disown(handles: [handle]) }.not_to raise_error

Selenium v4.9

    await manager.disownBrowsingContextScript(id, boxId)

Selenium v4.15

def test_disown_value(driver):
    driver.get("https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html")

    result = driver.script.evaluate("({x: 1})")
    handle = result.get("handle")

    # Disown the value
    driver.script.disown(handles=[handle])
    # If no exception is raised, disown was successful

Disown handles in a realm

Selenium v4.15

            script.disownRealmScript(realmId, List.of(boxId));

Selenium v4.9

    await manager.disownRealmScript(realmId, boxId)

Get all realms

Selenium v4.15

        try (Script script = new Script(firstWindow, driver)) {
            List<RealmInfo> realms = script.getAllRealms();

Selenium v4.9

    const manager = await ScriptManager(firstWindow, driver)

    const realms = await manager.getAllRealms()

Get realm by type

Selenium v4.15

        try (Script script = new Script(firstWindow, driver)) {
            List<RealmInfo> realms = script.getRealmsByType(RealmType.WINDOW);

Selenium v4.9

    const manager = await ScriptManager(firstWindow, driver)

    const realms = await manager.getRealmsByType(RealmType.WINDOW)

Get browsing context realms

Selenium v4.15

        try (Script script = new Script(windowId, driver)) {
            List<RealmInfo> realms = script.getRealmsInBrowsingContext(tabId);

Selenium v4.9

    const manager = await ScriptManager(windowId, driver)

    const realms = await manager.getRealmsInBrowsingContext(tabId)

Get browsing context realms by type

Selenium v4.15

            List<RealmInfo> windowRealms =
                    script.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW);

Selenium v4.9

    const realms = await manager.getRealmsInBrowsingContextByType(windowId, RealmType.WINDOW)

Preload a script

Selenium v4.15

            String id = script.addPreloadScript("() => { window.bar=2; }", "sandbox");

Selenium v4.10

    const manager = await ScriptManager(id, driver)

    const scriptId = await manager.addPreloadScript('() => {{ console.log(\'{preload_script_console_text}\') }}')

Remove a preloaded script

Selenium v4.15

                script.removePreloadScript(id);

Selenium v4.10

    await manager.removePreloadScript(scriptId)

Events

This section contains the APIs related to script events.

Message

Selenium v4.16

        try (Script script = new Script(driver)) {
            CompletableFuture<Message> future = new CompletableFuture<>();
            script.onMessage(future::complete);

            script.callFunctionInBrowsingContext(
                    driver.getWindowHandle(),
                    "(channel) => channel('foo')",
                    false,
                    Optional.of(List.of(LocalValue.channelValue("channel_name"))),
                    Optional.empty(),
                    Optional.empty());

            Message message = future.get(5, TimeUnit.SECONDS);
            Assertions.assertEquals("channel_name", message.getChannel());
        }

Selenium v4.16

  it 'calls function with element arguments' do
    driver.navigate.to 'https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html'

    element = driver.find_element(id: 'consoleLog')

    result = driver.script.call_function(
      'function(elem) { return elem.tagName; }',
      args: [
        {type: 'HTMLElement', handle: element}
      ]
    )

    expect(result['value']).to eq('BUTTON')

Selenium v4.18

    const manager = await ScriptManager(undefined, driver)

    let message = null

    await manager.onMessage((m) => {
      message = m
    })

    let argumentValues = []
    let value = new ArgumentValue(LocalValue.createChannelValue(new ChannelValue('channel_name')))
    argumentValues.push(value)

    const result = await manager.callFunctionInBrowsingContext(
      await driver.getWindowHandle(),
      '(channel) => channel("foo")',
      false,
      argumentValues,
    )

Selenium v4.16

def test_call_function_with_element_args(driver):
    driver.get("https://www.selenium.dev/selenium/web/bidi/logEntryAdded.html")

    element = driver.find_element(By.ID, "consoleLog")

    result = driver.script.call_function(
        "function(elem) { return elem.tagName; }",
        args=[{"type": "HTMLElement", "handle": element}]
    )

    assert result.get("value") == "BUTTON"

Realm Created

Selenium v4.16

        try (Script script = new Script(driver)) {
            CompletableFuture<RealmInfo> future = new CompletableFuture<>();
            script.onRealmCreated(future::complete);

            BrowsingContext context = new BrowsingContext(driver, driver.getWindowHandle());

            context.navigate("https://www.selenium.dev/selenium/blankPage");
            RealmInfo realmInfo = future.get(5, TimeUnit.SECONDS);
            Assertions.assertNotNull(realmInfo.getRealmId());
            Assertions.assertEquals(RealmType.WINDOW, realmInfo.getRealmType());
        }

Selenium v4.18

    const manager = await ScriptManager(undefined, driver)

    let realmInfo = null

    await manager.onRealmCreated((result) => {
      realmInfo = result
    })

    const id = await driver.getWindowHandle()
    const browsingContext = await BrowsingContext(driver, {
      browsingContextId: id,
    })

    await browsingContext.navigate('https://www.selenium.dev/selenium/web/blank', 'complete')

Realm Destroyed

Selenium v4.16

        try (Script script = new Script(driver)) {
            CompletableFuture<RealmInfo> future = new CompletableFuture<>();
            script.onRealmDestroyed(future::complete);

            BrowsingContext context = new BrowsingContext(driver, driver.getWindowHandle());

            context.close();
            RealmInfo realmInfo = future.get(5, TimeUnit.SECONDS);
            Assertions.assertNotNull(realmInfo.getRealmId());
            Assertions.assertEquals(RealmType.WINDOW, realmInfo.getRealmType());
        }

Selenium v4.19

    const manager = await ScriptManager(undefined, driver)

    let realmInfo = null

    await manager.onRealmDestroyed((result) => {
      realmInfo = result
    })

    const id = await driver.getWindowHandle()
    const browsingContext = await BrowsingContext(driver, {
      browsingContextId: id,
    })

    await browsingContext.close()