diff --git a/java/src/org/openqa/selenium/bidi/module/Network.java b/java/src/org/openqa/selenium/bidi/module/Network.java index 80b46b717f2a4..0f2f4436dbf9e 100644 --- a/java/src/org/openqa/selenium/bidi/module/Network.java +++ b/java/src/org/openqa/selenium/bidi/module/Network.java @@ -33,6 +33,7 @@ import org.openqa.selenium.bidi.network.ContinueRequestParameters; import org.openqa.selenium.bidi.network.ContinueResponseParameters; import org.openqa.selenium.bidi.network.FetchError; +import org.openqa.selenium.bidi.network.ProvideResponseParameters; import org.openqa.selenium.bidi.network.ResponseDetails; import org.openqa.selenium.internal.Require; @@ -132,6 +133,10 @@ public void continueResponse(ContinueResponseParameters parameters) { this.bidi.send(new Command<>("network.continueResponse", parameters.toMap())); } + public void provideResponse(ProvideResponseParameters parameters) { + this.bidi.send(new Command<>("network.provideResponse", parameters.toMap())); + } + public void onBeforeRequestSent(Consumer consumer) { if (browsingContextIds.isEmpty()) { this.bidi.addListener(beforeRequestSentEvent, consumer); diff --git a/java/src/org/openqa/selenium/bidi/network/ProvideResponseParameters.java b/java/src/org/openqa/selenium/bidi/network/ProvideResponseParameters.java new file mode 100644 index 0000000000000..d6a76b2c9e7fa --- /dev/null +++ b/java/src/org/openqa/selenium/bidi/network/ProvideResponseParameters.java @@ -0,0 +1,64 @@ +// 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.network; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class ProvideResponseParameters { + private final Map map = new HashMap<>(); + + public ProvideResponseParameters(String request) { + map.put("request", request); + } + + public ProvideResponseParameters body(BytesValue value) { + map.put("body", value.toMap()); + return this; + } + + public ProvideResponseParameters cookies(List cookieHeaders) { + List> cookies = + cookieHeaders.stream().map(SetCookieHeader::toMap).collect(Collectors.toList()); + map.put("cookies", cookies); + return this; + } + + public ProvideResponseParameters headers(List
headers) { + List> headerList = + headers.stream().map(Header::toMap).collect(Collectors.toList()); + map.put("headers", headerList); + return this; + } + + public ProvideResponseParameters reasonPhrase(String reasonPhrase) { + map.put("reasonPhrase", reasonPhrase); + return this; + } + + public ProvideResponseParameters statusCode(int statusCode) { + map.put("statusCode", statusCode); + return this; + } + + public Map toMap() { + return map; + } +} diff --git a/java/test/org/openqa/selenium/bidi/network/NetworkCommandsTest.java b/java/test/org/openqa/selenium/bidi/network/NetworkCommandsTest.java index 415b1e2319e2f..3a4a68796e346 100644 --- a/java/test/org/openqa/selenium/bidi/network/NetworkCommandsTest.java +++ b/java/test/org/openqa/selenium/bidi/network/NetworkCommandsTest.java @@ -31,6 +31,7 @@ import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.openqa.selenium.Alert; import org.openqa.selenium.By; @@ -132,6 +133,71 @@ void canContinueResponse() throws InterruptedException { } } + @Test + @NotYetImplemented(SAFARI) + @NotYetImplemented(IE) + @NotYetImplemented(EDGE) + @NotYetImplemented(FIREFOX) + void canProvideResponse() throws InterruptedException { + try (Network network = new Network(driver)) { + String intercept = + network.addIntercept(new AddInterceptParameters(InterceptPhase.BEFORE_REQUEST_SENT)); + + CountDownLatch latch = new CountDownLatch(1); + + network.onBeforeRequestSent( + beforeRequestSent -> { + network.provideResponse( + new ProvideResponseParameters(beforeRequestSent.getRequest().getRequestId())); + + latch.countDown(); + }); + + assertThat(intercept).isNotNull(); + + driver.get(server.whereIs("/bidi/logEntryAdded.html")); + + boolean countdown = latch.await(5, TimeUnit.SECONDS); + assertThat(countdown).isTrue(); + } + } + + @Disabled + @NotYetImplemented(SAFARI) + @NotYetImplemented(IE) + @NotYetImplemented(EDGE) + @NotYetImplemented(FIREFOX) + // TODO: Browsers are yet to implement all parameters. Once implemented, add exhaustive tests. + void canProvideResponseWithAllParameters() throws InterruptedException { + try (Network network = new Network(driver)) { + String intercept = + network.addIntercept(new AddInterceptParameters(InterceptPhase.RESPONSE_STARTED)); + + CountDownLatch latch = new CountDownLatch(1); + + network.onResponseStarted( + responseDetails -> { + network.provideResponse( + new ProvideResponseParameters(responseDetails.getRequest().getRequestId()) + .body( + new BytesValue( + BytesValue.Type.STRING, + "Hello," + " World!"))); + + latch.countDown(); + }); + + assertThat(intercept).isNotNull(); + + driver.get(server.whereIs("/bidi/logEntryAdded.html")); + + boolean countdown = latch.await(5, TimeUnit.SECONDS); + assertThat(countdown).isTrue(); + + assertThat(driver.getPageSource()).contains("Hello"); + } + } + @Test @NotYetImplemented(SAFARI) @NotYetImplemented(IE) diff --git a/javascript/node/selenium-webdriver/bidi/network.js b/javascript/node/selenium-webdriver/bidi/network.js index 9d7b3842b0f3f..5c7ae3ccb885d 100644 --- a/javascript/node/selenium-webdriver/bidi/network.js +++ b/javascript/node/selenium-webdriver/bidi/network.js @@ -19,6 +19,7 @@ const { BeforeRequestSent, ResponseStarted, FetchError } = require('./networkTyp const { AddInterceptParameters } = require('./addInterceptParameters') const { ContinueResponseParameters } = require('./continueResponseParameters') const { ContinueRequestParameters } = require('./continueRequestParameters') +const { ProvideResponseParameters } = require('./provideResponseParameters') class Network { constructor(driver, browsingContextIds) { @@ -196,6 +197,19 @@ class Network { await this.bidi.send(command) } + async provideResponse(params) { + if (!(params instanceof ProvideResponseParameters)) { + throw new Error(`Params must be an instance of ProvideResponseParameters. Received:'${params}'`) + } + + const command = { + method: 'network.provideResponse', + params: Object.fromEntries(params.asMap()), + } + + await this.bidi.send(command) + } + async close() { await this.bidi.unsubscribe( 'network.beforeRequestSent', diff --git a/javascript/node/selenium-webdriver/bidi/provideResponseParameters.js b/javascript/node/selenium-webdriver/bidi/provideResponseParameters.js new file mode 100644 index 0000000000000..08348379a239c --- /dev/null +++ b/javascript/node/selenium-webdriver/bidi/provideResponseParameters.js @@ -0,0 +1,83 @@ +// 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. + +const { BytesValue, Header } = require('./networkTypes') + +class ProvideResponseParameters { + #map = new Map() + + constructor(request) { + this.#map.set('request', request) + } + + body(value) { + if (!(value instanceof BytesValue)) { + throw new Error(`Value must be an instance of BytesValue. Received: ${typeof value} with value: ${value}`) + } + this.#map.set('body', Object.fromEntries(value.asMap())) + return this + } + + cookies(cookieHeaders) { + const cookies = [] + cookieHeaders.forEach((header) => { + if (!(header instanceof Header)) { + throw new Error(`CookieHeader must be an instance of Header. Received:'${header}'`) + } + cookies.push(Object.fromEntries(header.asMap())) + }) + + this.#map.set('cookies', cookies) + return this + } + + headers(headers) { + const headerList = [] + headers.forEach((header) => { + if (!(header instanceof Header)) { + throw new Error(`Header must be an instance of Header. Received:'${header}'`) + } + headerList.push(Object.fromEntries(header.asMap())) + }) + + this.#map.set('headers', headerList) + return this + } + + reasonPhrase(reasonPhrase) { + if (typeof reasonPhrase !== 'string') { + throw new Error(`Reason phrase must be a string. Received: '${reasonPhrase})'`) + } + this.#map.set('reasonPhrase', reasonPhrase) + return this + } + + statusCode(statusCode) { + if (!Number.isInteger(statusCode)) { + throw new Error(`Status must be an integer. Received:'${statusCode}'`) + } + + this.#map.set('statusCode', statusCode) + return this + } + + asMap() { + return this.#map + } +} + +module.exports = { ProvideResponseParameters } diff --git a/javascript/node/selenium-webdriver/test/bidi/network_commands_test.js b/javascript/node/selenium-webdriver/test/bidi/network_commands_test.js index 0e0c5d46cd9b7..8e8831ebf8294 100644 --- a/javascript/node/selenium-webdriver/test/bidi/network_commands_test.js +++ b/javascript/node/selenium-webdriver/test/bidi/network_commands_test.js @@ -27,6 +27,7 @@ const { InterceptPhase } = require('../../bidi/interceptPhase') const { until } = require('../../index') const { ContinueRequestParameters } = require('../../bidi/continueRequestParameters') const { ContinueResponseParameters } = require('../../bidi/continueResponseParameters') +const { ProvideResponseParameters } = require('../../bidi/provideResponseParameters') suite( function (env) { @@ -147,6 +148,21 @@ suite( assert.strictEqual(counter, 1) }) + + xit('can provide response', async function () { + await network.addIntercept(new AddInterceptParameters(InterceptPhase.BEFORE_REQUEST_SENT)) + + let counter = 0 + + await network.beforeRequestSent(async (event) => { + await network.provideResponse(new ProvideResponseParameters(event.request.request)) + counter = counter + 1 + }) + + await driver.get(Pages.logEntryAdded) + + assert.strictEqual(counter, 1) + }) }) }, { browsers: [Browser.FIREFOX] },