Skip to content

Commit 7e11db8

Browse files
[js] Implement network request interceptions
1 parent a45202d commit 7e11db8

File tree

3 files changed

+174
-14
lines changed

3 files changed

+174
-14
lines changed
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
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+
class HttpResponse {
19+
/**
20+
* Creates a HTTP Response that will be used to
21+
* mock out network interceptions.
22+
* @param {*} urlToIntercept
23+
*/
24+
constructor(urlToIntercept = "") {
25+
this.returnBody = ""
26+
this.returnHeaders = []
27+
this.returnMethod = "GET"
28+
this.returnStatus = 200
29+
this.urlToIntercept = urlToIntercept
30+
}
31+
32+
/**
33+
* Add headers that will be returned when we intercept
34+
* a HTTP Request
35+
* @param {*} header
36+
* @param {*} value
37+
*/
38+
addHeaders(header, value) {
39+
this.returnHeaders.push({ name: header, value: value })
40+
}
41+
42+
get headers() {
43+
return this.returnHeaders
44+
}
45+
46+
/**
47+
* Set the STATUS value of the returned HTTP Request
48+
* @param {*} value
49+
*/
50+
set status(value) {
51+
// Add in check that his should be a number
52+
this.returnStatus = value
53+
}
54+
55+
get status() {
56+
return this.returnStatus
57+
}
58+
59+
/**
60+
* Sets the value of the body of the HTTP Request that
61+
* will be returned.
62+
* @param {*} value
63+
*/
64+
set body(value) {
65+
this.returnBody = value
66+
}
67+
68+
get body() {
69+
let buff = Buffer.from(this.returnBody, "utf-8")
70+
return buff.toString("base64")
71+
}
72+
73+
/**
74+
* Sets the method of the HTTP Request
75+
* @param {*} value the method of the request.
76+
*/
77+
set method(value) {
78+
this.returnMethod = value
79+
}
80+
81+
/**
82+
* Returns the Method to be used in the intercept
83+
*/
84+
get method() {
85+
return this.returnMethod
86+
}
87+
88+
}
89+
exports.HttpResponse = HttpResponse

javascript/node/selenium-webdriver/lib/webdriver.js

Lines changed: 68 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1246,14 +1246,6 @@ class WebDriver {
12461246
* @param connection CDP Connection
12471247
*/
12481248
async register(username, password, connection) {
1249-
await connection.execute(
1250-
'Network.setCacheDisabled',
1251-
this.getRandomNumber(1, 10),
1252-
{
1253-
cacheDisabled: true,
1254-
},
1255-
null
1256-
)
12571249

12581250
this._wsConnection.on('message', (message) => {
12591251
const params = JSON.parse(message)
@@ -1292,21 +1284,77 @@ class WebDriver {
12921284
},
12931285
null
12941286
)
1287+
await connection.execute(
1288+
'Network.setCacheDisabled',
1289+
this.getRandomNumber(1, 10),
1290+
{
1291+
cacheDisabled: true,
1292+
},
1293+
null
1294+
)
12951295
}
12961296

1297+
/**
1298+
* Handle Network interception requests
1299+
* @param connection WebSocket connection to the browser
1300+
* @param httpResponse Object representing what we are intercepting
1301+
* as well as what should be returned.
1302+
* @param callback callback called when we intercept requests.
1303+
*/
1304+
async onIntercept(connection, httpResponse, callback) {
1305+
1306+
this._wsConnection.on('message', (message) => {
1307+
const params = JSON.parse(message)
1308+
if (params.method === 'Fetch.requestPaused') {
1309+
const requestPausedParams = params['params']
1310+
if (requestPausedParams.request.url == httpResponse.urlToIntercept) {
1311+
connection.execute(
1312+
'Fetch.continueRequest',
1313+
this.getRandomNumber(1, 10),
1314+
{
1315+
requestId: requestPausedParams['requestId'],
1316+
url: httpResponse.urlToIntercept,
1317+
method: httpResponse.method,
1318+
headers: httpResponse.headers,
1319+
postData: httpResponse.body
1320+
}
1321+
)
1322+
callback()
1323+
} else {
1324+
connection.execute(
1325+
'Fetch.continueRequest',
1326+
this.getRandomNumber(1, 10),
1327+
{
1328+
requestId: requestPausedParams['requestId'],
1329+
}
1330+
)
1331+
}
1332+
}
1333+
})
1334+
1335+
await connection.execute(
1336+
'Fetch.enable',
1337+
1,
1338+
{},
1339+
null
1340+
)
1341+
await connection.execute(
1342+
'Network.setCacheDisabled',
1343+
this.getRandomNumber(1, 10),
1344+
{
1345+
cacheDisabled: true,
1346+
},
1347+
null
1348+
)
1349+
}
12971350
/**
12981351
*
12991352
* @param connection
13001353
* @param callback
13011354
* @returns {Promise<void>}
13021355
*/
13031356
async onLogEvent(connection, callback) {
1304-
await connection.execute(
1305-
'Runtime.enable',
1306-
this.getRandomNumber(1, 10),
1307-
{},
1308-
null
1309-
)
1357+
13101358

13111359
this._wsConnection.on('message', (message) => {
13121360
const params = JSON.parse(message)
@@ -1322,6 +1370,12 @@ class WebDriver {
13221370
callback(event)
13231371
}
13241372
})
1373+
await connection.execute(
1374+
'Runtime.enable',
1375+
this.getRandomNumber(1, 10),
1376+
{},
1377+
null
1378+
)
13251379
}
13261380

13271381
/**

javascript/node/selenium-webdriver/test/devtools_test.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
const assert = require('assert')
2121
const { Browser, until } = require('..')
2222
const fileServer = require('../lib/test/fileserver')
23+
const { HttpResponse } = require('../devtools/networkontor')
2324
const { Pages, ignore, suite } = require('../lib/test')
2425

2526
suite(
@@ -123,6 +124,22 @@ suite(
123124
assert.strictEqual(source.includes('Access granted!'), true)
124125
})
125126
})
127+
128+
describe("Network Interception", function () {
129+
ignore(browsers(Browser.SAFARI, Browser.FIREFOX)).
130+
it('Allows network requests to be captured and mocked', async function () {
131+
const connection = await driver.createCDPConnection('page')
132+
let url = fileServer.whereIs("/cheese")
133+
let httpResponse = new HttpResponse(url)
134+
httpResponse.addHeaders("Content-Type", "UTF-8")
135+
httpResponse.body = "sausages"
136+
await driver.onIntercept(connection, httpResponse, async function () {
137+
let body = await driver.getPageSource()
138+
assert.strictEqual(body.includes("sausages"), true, `Body contains: ${body}`)
139+
})
140+
driver.get(url)
141+
})
142+
})
126143
},
127144
{ browsers: ['chrome', 'firefox'] }
128145
)

0 commit comments

Comments
 (0)