Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,11 @@ public BrowsingContext(WebDriver driver, WindowType type) {
this.id = this.create(type);
}

/*
* @deprecated
* Use {@link #BrowsingContext(WebDriver, CreateParameters)} instead.
*/
@Deprecated
public BrowsingContext(WebDriver driver, WindowType type, String referenceContextId) {
Require.nonNull("WebDriver", driver);
Require.nonNull("Reference browsing context id", referenceContextId);
Expand All @@ -117,7 +122,19 @@ public BrowsingContext(WebDriver driver, WindowType type, String referenceContex

this.driver = driver;
this.bidi = ((HasBiDi) driver).getBiDi();
this.id = this.create(type, referenceContextId);
this.id = this.create(new CreateContextParameters(type).referenceContext(referenceContextId));
}

public BrowsingContext(WebDriver driver, CreateContextParameters parameters) {
Require.nonNull("WebDriver", driver);

if (!(driver instanceof HasBiDi)) {
throw new IllegalArgumentException("WebDriver instance must support BiDi protocol");
}

this.driver = driver;
this.bidi = ((HasBiDi) driver).getBiDi();
this.id = this.create(parameters);
}

public String getId() {
Expand All @@ -130,12 +147,9 @@ private String create(WindowType type) {
"browsingContext.create", Map.of("type", type.toString()), browsingContextIdMapper));
}

private String create(WindowType type, String referenceContext) {
private String create(CreateContextParameters parameters) {
return this.bidi.send(
new Command<>(
"browsingContext.create",
Map.of("type", type.toString(), "referenceContext", referenceContext),
browsingContextIdMapper));
new Command<>("browsingContext.create", parameters.toMap(), browsingContextIdMapper));
}

public NavigationResult navigate(String url) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Licensed to the Software Freedom Conservancy (SFC) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The SFC licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

package org.openqa.selenium.bidi.browsingcontext;

import java.util.HashMap;
import java.util.Map;
import org.openqa.selenium.WindowType;

public class CreateContextParameters {
private final Map<String, Object> map = new HashMap<>();
private final WindowType windowType;

public CreateContextParameters(WindowType type) {
this.windowType = type;
}

public CreateContextParameters referenceContext(String id) {
map.put("referenceContext", id);
return this;
}

public CreateContextParameters background(boolean background) {
map.put("background", background);
return this;
}

public CreateContextParameters userContext(String userContext) {
map.put("userContext", userContext);
return this;
}

public Map<String, Object> toMap() {
map.put("type", windowType.toString());
return map;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import org.openqa.selenium.WebElement;
import org.openqa.selenium.WindowType;
import org.openqa.selenium.bidi.BiDiException;
import org.openqa.selenium.bidi.module.Browser;
import org.openqa.selenium.environment.webserver.AppServer;
import org.openqa.selenium.environment.webserver.NettyAppServer;
import org.openqa.selenium.environment.webserver.Page;
Expand Down Expand Up @@ -77,7 +78,10 @@ void canCreateAWindow() {
@NotYetImplemented(IE)
void canCreateAWindowWithAReferenceContext() {
BrowsingContext browsingContext =
new BrowsingContext(driver, WindowType.WINDOW, driver.getWindowHandle());
new BrowsingContext(
driver,
new CreateContextParameters(WindowType.WINDOW)
.referenceContext(driver.getWindowHandle()));
assertThat(browsingContext.getId()).isNotEmpty();
}

Expand All @@ -94,10 +98,30 @@ void canCreateATab() {
@NotYetImplemented(IE)
void canCreateATabWithAReferenceContext() {
BrowsingContext browsingContext =
new BrowsingContext(driver, WindowType.TAB, driver.getWindowHandle());
new BrowsingContext(
driver,
new CreateContextParameters(WindowType.TAB).referenceContext(driver.getWindowHandle()));
assertThat(browsingContext.getId()).isNotEmpty();
}

@Test
@NotYetImplemented(SAFARI)
@NotYetImplemented(IE)
void canCreateAContextWithAllParameters() {
Browser browser = new Browser(driver);
String userContextId = browser.createUserContext();

CreateContextParameters parameters = new CreateContextParameters(WindowType.WINDOW);
parameters
.referenceContext(driver.getWindowHandle())
.userContext(userContextId)
.background(true);

BrowsingContext browsingContext = new BrowsingContext(driver, parameters);
assertThat(browsingContext.getId()).isNotEmpty();
assertThat(browsingContext.getId()).isNotEqualTo(driver.getWindowHandle());
}

@Test
@NotYetImplemented(SAFARI)
@NotYetImplemented(IE)
Expand Down
47 changes: 35 additions & 12 deletions javascript/node/selenium-webdriver/bidi/browsingContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const { BrowsingContextInfo } = require('./browsingContextTypes')
const { SerializationOptions, ReferenceValue, RemoteValue } = require('./protocolValue')
const { WebElement } = require('../lib/webdriver')
const { CaptureScreenshotParameters } = require('./captureScreenshotParameters')
const { CreateContextParameters } = require('./createContextParameters')

/**
* Represents the locator to locate nodes in the browsing context.
Expand Down Expand Up @@ -110,34 +111,53 @@ class BrowsingContext {
return this._id
}

async init({ browsingContextId, type, referenceContext }) {
async init({ browsingContextId = undefined, type = undefined, createParameters = undefined }) {
if (!(await this._driver.getCapabilities()).get('webSocketUrl')) {
throw Error('WebDriver instance must support BiDi protocol')
}

if (browsingContextId === undefined && type === undefined && createParameters === undefined) {
throw Error('Either BrowsingContextId or Type or CreateParameters must be provided')
}

if (type === undefined && createParameters !== undefined) {
throw Error('Type must be provided with CreateParameters')
}

if (type !== undefined && !['window', 'tab'].includes(type)) {
throw Error(`Valid types are 'window' & 'tab'. Received: ${type}`)
}

this.bidi = await this._driver.getBidi()
this._id =
browsingContextId === undefined
? (await this.create(type, referenceContext))['result']['context']
? (await this.create(type, createParameters))['result']['context']
: browsingContextId
}

/**
* Creates a browsing context for the given type and referenceContext
* Creates a browsing context for the given type with the given parameters
*/
async create(type, referenceContext) {
async create(type, createParameters = undefined) {
if (createParameters !== undefined && (!createParameters) instanceof CreateContextParameters) {
throw Error(`Pass in the instance of CreateContextParameters. Received: ${createParameters}`)
}

let parameters = new Map()
parameters.set('type', type)

if (createParameters !== undefined) {
createParameters.asMap().forEach((value, key) => {
parameters.set(key, value)
})
}

const params = {
method: 'browsingContext.create',
params: {
type: type,
referenceContext: referenceContext,
},
params: Object.fromEntries(parameters),
}
return await this.bidi.send(params)
const res = await this.bidi.send(params)
return res
}

/**
Expand Down Expand Up @@ -635,12 +655,15 @@ class PrintResult {
* @param driver
* @param browsingContextId The browsing context of current window/tab
* @param type "window" or "tab"
* @param referenceContext To get a browsing context for this reference if passed
* @param createParameters The parameters for creating a new browsing context
* @returns {Promise<BrowsingContext>}
*/
async function getBrowsingContextInstance(driver, { browsingContextId, type, referenceContext }) {
async function getBrowsingContextInstance(
driver,
{ browsingContextId = undefined, type = undefined, createParameters = undefined },
) {
let instance = new BrowsingContext(driver)
await instance.init({ browsingContextId, type, referenceContext })
await instance.init({ browsingContextId, type, createParameters })
return instance
}

Expand Down
73 changes: 73 additions & 0 deletions javascript/node/selenium-webdriver/bidi/createContextParameters.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// Licensed to the Software Freedom Conservancy (SFC) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The SFC licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

/**
* Represents a set of parameters for creating a context.
* Described in https://w3c.github.io/webdriver-bidi/#command-browsingContext-create.
*/
class CreateContextParameters {
#map = new Map()

/**
* Sets the reference context.
* @param {string} id - The ID of the reference context.
* @returns {CreateContextParameters} - The updated instance of CreateContextParameters for chaining.
* @throws {Error} - If the provided ID is not a string.
*/
referenceContext(id) {
if (typeof id !== 'string') {
throw new Error(`ReferenceContext must be string. Received:'${id}'`)
}
this.#map.set('referenceContext', id)
return this
}

/**
* Sets the background parameter.
*
* @param {boolean} background - The background value to set.
* @returns {CreateContextParameters} - The updated instance of CreateContextParameters for chaining.
* @throws {Error} - If the background parameter is not a boolean.
*/
background(background) {
if (typeof background !== 'boolean') {
throw new Error(`Background must be boolean. Received:'${background}'`)
}
this.#map.set('background', background)
return this
}

/**
* Sets the user context.
* @param {string} userContext - The user context to set.
* @returns {CreateContextParameters} - The updated instance of CreateContextParameters for chaining.
* @throws {Error} - If the userContext parameter is not a string.
*/
userContext(userContext) {
if (typeof userContext !== 'string') {
throw new Error(`UserContext must be string. Received:'${userContext}'`)
}
this.#map.set('userContext', userContext)
return this
}

asMap() {
return this.#map
}
}

module.exports = { CreateContextParameters }
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ const BrowsingContext = require('../../bidi/browsingContext')
const until = require('../../lib/until')
const { Origin, CaptureScreenshotParameters } = require('../../bidi/captureScreenshotParameters')
const { BoxClipRectangle, ElementClipRectangle } = require('../../bidi/clipRectangle')
const { CreateContextParameters } = require('../../bidi/createContextParameters')
const BrowserBiDi = require('../../bidi/browser')

suite(
function (env) {
Expand Down Expand Up @@ -61,11 +63,25 @@ suite(
it('can create a window with a reference context', async function () {
const browsingContext = await BrowsingContext(driver, {
type: 'window',
referenceContext: await driver.getWindowHandle(),
createParameters: new CreateContextParameters().referenceContext(await driver.getWindowHandle()),
})
assert.notEqual(browsingContext.id, null)
})

it('can create a tab with all parameters', async function () {
const browser = await BrowserBiDi(driver)
const userContext = await browser.createUserContext()
const browsingContext = await BrowsingContext(driver, {
type: 'window',
createParameters: new CreateContextParameters()
.referenceContext(await driver.getWindowHandle())
.background(true)
.userContext(userContext),
})
assert.notEqual(browsingContext.id, null)
assert.notEqual(browsingContext.id, await driver.getWindowHandle())
})

it('can create a tab', async function () {
const browsingContext = await BrowsingContext(driver, {
type: 'tab',
Expand All @@ -76,7 +92,7 @@ suite(
it('can create a tab with a reference context', async function () {
const browsingContext = await BrowsingContext(driver, {
type: 'tab',
referenceContext: await driver.getWindowHandle(),
referenceContext: new CreateContextParameters().referenceContext(await driver.getWindowHandle()),
})
assert.notEqual(browsingContext.id, null)
})
Expand Down