Skip to content

Commit

Permalink
[bidi] Update browsing context create method (#13766)
Browse files Browse the repository at this point in the history
  • Loading branch information
pujagani committed Apr 24, 2024
1 parent fee33dd commit 4a6c384
Show file tree
Hide file tree
Showing 6 changed files with 223 additions and 22 deletions.
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

0 comments on commit 4a6c384

Please sign in to comment.