Skip to content

Commit 3c783f7

Browse files
authored
[bidi] Add provide response command (#13708)
1 parent 30fbca1 commit 3c783f7

File tree

6 files changed

+248
-0
lines changed

6 files changed

+248
-0
lines changed

java/src/org/openqa/selenium/bidi/module/Network.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import org.openqa.selenium.bidi.network.ContinueRequestParameters;
3434
import org.openqa.selenium.bidi.network.ContinueResponseParameters;
3535
import org.openqa.selenium.bidi.network.FetchError;
36+
import org.openqa.selenium.bidi.network.ProvideResponseParameters;
3637
import org.openqa.selenium.bidi.network.ResponseDetails;
3738
import org.openqa.selenium.internal.Require;
3839

@@ -132,6 +133,10 @@ public void continueResponse(ContinueResponseParameters parameters) {
132133
this.bidi.send(new Command<>("network.continueResponse", parameters.toMap()));
133134
}
134135

136+
public void provideResponse(ProvideResponseParameters parameters) {
137+
this.bidi.send(new Command<>("network.provideResponse", parameters.toMap()));
138+
}
139+
135140
public void onBeforeRequestSent(Consumer<BeforeRequestSent> consumer) {
136141
if (browsingContextIds.isEmpty()) {
137142
this.bidi.addListener(beforeRequestSentEvent, consumer);
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// Licensed to the Software Freedom Conservancy (SFC) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The SFC licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
package org.openqa.selenium.bidi.network;
19+
20+
import java.util.HashMap;
21+
import java.util.List;
22+
import java.util.Map;
23+
import java.util.stream.Collectors;
24+
25+
public class ProvideResponseParameters {
26+
private final Map<String, Object> map = new HashMap<>();
27+
28+
public ProvideResponseParameters(String request) {
29+
map.put("request", request);
30+
}
31+
32+
public ProvideResponseParameters body(BytesValue value) {
33+
map.put("body", value.toMap());
34+
return this;
35+
}
36+
37+
public ProvideResponseParameters cookies(List<SetCookieHeader> cookieHeaders) {
38+
List<Map<String, Object>> cookies =
39+
cookieHeaders.stream().map(SetCookieHeader::toMap).collect(Collectors.toList());
40+
map.put("cookies", cookies);
41+
return this;
42+
}
43+
44+
public ProvideResponseParameters headers(List<Header> headers) {
45+
List<Map<String, Object>> headerList =
46+
headers.stream().map(Header::toMap).collect(Collectors.toList());
47+
map.put("headers", headerList);
48+
return this;
49+
}
50+
51+
public ProvideResponseParameters reasonPhrase(String reasonPhrase) {
52+
map.put("reasonPhrase", reasonPhrase);
53+
return this;
54+
}
55+
56+
public ProvideResponseParameters statusCode(int statusCode) {
57+
map.put("statusCode", statusCode);
58+
return this;
59+
}
60+
61+
public Map<String, Object> toMap() {
62+
return map;
63+
}
64+
}

java/test/org/openqa/selenium/bidi/network/NetworkCommandsTest.java

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import java.util.concurrent.TimeUnit;
3232
import org.junit.jupiter.api.AfterEach;
3333
import org.junit.jupiter.api.BeforeEach;
34+
import org.junit.jupiter.api.Disabled;
3435
import org.junit.jupiter.api.Test;
3536
import org.openqa.selenium.Alert;
3637
import org.openqa.selenium.By;
@@ -132,6 +133,71 @@ void canContinueResponse() throws InterruptedException {
132133
}
133134
}
134135

136+
@Test
137+
@NotYetImplemented(SAFARI)
138+
@NotYetImplemented(IE)
139+
@NotYetImplemented(EDGE)
140+
@NotYetImplemented(FIREFOX)
141+
void canProvideResponse() throws InterruptedException {
142+
try (Network network = new Network(driver)) {
143+
String intercept =
144+
network.addIntercept(new AddInterceptParameters(InterceptPhase.BEFORE_REQUEST_SENT));
145+
146+
CountDownLatch latch = new CountDownLatch(1);
147+
148+
network.onBeforeRequestSent(
149+
beforeRequestSent -> {
150+
network.provideResponse(
151+
new ProvideResponseParameters(beforeRequestSent.getRequest().getRequestId()));
152+
153+
latch.countDown();
154+
});
155+
156+
assertThat(intercept).isNotNull();
157+
158+
driver.get(server.whereIs("/bidi/logEntryAdded.html"));
159+
160+
boolean countdown = latch.await(5, TimeUnit.SECONDS);
161+
assertThat(countdown).isTrue();
162+
}
163+
}
164+
165+
@Disabled
166+
@NotYetImplemented(SAFARI)
167+
@NotYetImplemented(IE)
168+
@NotYetImplemented(EDGE)
169+
@NotYetImplemented(FIREFOX)
170+
// TODO: Browsers are yet to implement all parameters. Once implemented, add exhaustive tests.
171+
void canProvideResponseWithAllParameters() throws InterruptedException {
172+
try (Network network = new Network(driver)) {
173+
String intercept =
174+
network.addIntercept(new AddInterceptParameters(InterceptPhase.RESPONSE_STARTED));
175+
176+
CountDownLatch latch = new CountDownLatch(1);
177+
178+
network.onResponseStarted(
179+
responseDetails -> {
180+
network.provideResponse(
181+
new ProvideResponseParameters(responseDetails.getRequest().getRequestId())
182+
.body(
183+
new BytesValue(
184+
BytesValue.Type.STRING,
185+
"<html><head><title>Hello," + " World!</title></head><body/></html>")));
186+
187+
latch.countDown();
188+
});
189+
190+
assertThat(intercept).isNotNull();
191+
192+
driver.get(server.whereIs("/bidi/logEntryAdded.html"));
193+
194+
boolean countdown = latch.await(5, TimeUnit.SECONDS);
195+
assertThat(countdown).isTrue();
196+
197+
assertThat(driver.getPageSource()).contains("Hello");
198+
}
199+
}
200+
135201
@Test
136202
@NotYetImplemented(SAFARI)
137203
@NotYetImplemented(IE)

javascript/node/selenium-webdriver/bidi/network.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ const { BeforeRequestSent, ResponseStarted, FetchError } = require('./networkTyp
1919
const { AddInterceptParameters } = require('./addInterceptParameters')
2020
const { ContinueResponseParameters } = require('./continueResponseParameters')
2121
const { ContinueRequestParameters } = require('./continueRequestParameters')
22+
const { ProvideResponseParameters } = require('./provideResponseParameters')
2223

2324
class Network {
2425
constructor(driver, browsingContextIds) {
@@ -196,6 +197,19 @@ class Network {
196197
await this.bidi.send(command)
197198
}
198199

200+
async provideResponse(params) {
201+
if (!(params instanceof ProvideResponseParameters)) {
202+
throw new Error(`Params must be an instance of ProvideResponseParameters. Received:'${params}'`)
203+
}
204+
205+
const command = {
206+
method: 'network.provideResponse',
207+
params: Object.fromEntries(params.asMap()),
208+
}
209+
210+
await this.bidi.send(command)
211+
}
212+
199213
async close() {
200214
await this.bidi.unsubscribe(
201215
'network.beforeRequestSent',
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// Licensed to the Software Freedom Conservancy (SFC) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The SFC licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
const { BytesValue, Header } = require('./networkTypes')
19+
20+
class ProvideResponseParameters {
21+
#map = new Map()
22+
23+
constructor(request) {
24+
this.#map.set('request', request)
25+
}
26+
27+
body(value) {
28+
if (!(value instanceof BytesValue)) {
29+
throw new Error(`Value must be an instance of BytesValue. Received: ${typeof value} with value: ${value}`)
30+
}
31+
this.#map.set('body', Object.fromEntries(value.asMap()))
32+
return this
33+
}
34+
35+
cookies(cookieHeaders) {
36+
const cookies = []
37+
cookieHeaders.forEach((header) => {
38+
if (!(header instanceof Header)) {
39+
throw new Error(`CookieHeader must be an instance of Header. Received:'${header}'`)
40+
}
41+
cookies.push(Object.fromEntries(header.asMap()))
42+
})
43+
44+
this.#map.set('cookies', cookies)
45+
return this
46+
}
47+
48+
headers(headers) {
49+
const headerList = []
50+
headers.forEach((header) => {
51+
if (!(header instanceof Header)) {
52+
throw new Error(`Header must be an instance of Header. Received:'${header}'`)
53+
}
54+
headerList.push(Object.fromEntries(header.asMap()))
55+
})
56+
57+
this.#map.set('headers', headerList)
58+
return this
59+
}
60+
61+
reasonPhrase(reasonPhrase) {
62+
if (typeof reasonPhrase !== 'string') {
63+
throw new Error(`Reason phrase must be a string. Received: '${reasonPhrase})'`)
64+
}
65+
this.#map.set('reasonPhrase', reasonPhrase)
66+
return this
67+
}
68+
69+
statusCode(statusCode) {
70+
if (!Number.isInteger(statusCode)) {
71+
throw new Error(`Status must be an integer. Received:'${statusCode}'`)
72+
}
73+
74+
this.#map.set('statusCode', statusCode)
75+
return this
76+
}
77+
78+
asMap() {
79+
return this.#map
80+
}
81+
}
82+
83+
module.exports = { ProvideResponseParameters }

javascript/node/selenium-webdriver/test/bidi/network_commands_test.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ const { InterceptPhase } = require('../../bidi/interceptPhase')
2727
const { until } = require('../../index')
2828
const { ContinueRequestParameters } = require('../../bidi/continueRequestParameters')
2929
const { ContinueResponseParameters } = require('../../bidi/continueResponseParameters')
30+
const { ProvideResponseParameters } = require('../../bidi/provideResponseParameters')
3031

3132
suite(
3233
function (env) {
@@ -147,6 +148,21 @@ suite(
147148

148149
assert.strictEqual(counter, 1)
149150
})
151+
152+
xit('can provide response', async function () {
153+
await network.addIntercept(new AddInterceptParameters(InterceptPhase.BEFORE_REQUEST_SENT))
154+
155+
let counter = 0
156+
157+
await network.beforeRequestSent(async (event) => {
158+
await network.provideResponse(new ProvideResponseParameters(event.request.request))
159+
counter = counter + 1
160+
})
161+
162+
await driver.get(Pages.logEntryAdded)
163+
164+
assert.strictEqual(counter, 1)
165+
})
150166
})
151167
},
152168
{ browsers: [Browser.FIREFOX] },

0 commit comments

Comments
 (0)