selenium-webdriver 4.15.0 → 4.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGES.md +29 -0
- package/LICENSE +1 -1
- package/NOTICE +1 -1
- package/bidi/browsingContext.js +23 -1
- package/bidi/input.js +100 -0
- package/bidi/networkInspector.js +4 -0
- package/bidi/protocolType.js +1 -0
- package/bidi/protocolValue.js +56 -6
- package/bidi/realmInfo.js +1 -0
- package/bidi/scriptManager.js +52 -1
- package/bidi/scriptTypes.js +58 -0
- package/bin/linux/selenium-manager +0 -0
- package/bin/macos/selenium-manager +0 -0
- package/bin/windows/selenium-manager.exe +0 -0
- package/chrome.js +1 -6
- package/chromium.js +1 -34
- package/common/seleniumManager.js +7 -5
- package/devtools/CDPConnection.js +1 -1
- package/example/headless.js +2 -2
- package/firefox.js +54 -74
- package/index.js +3 -3
- package/lib/atoms/find-elements.js +3 -2
- package/lib/atoms/get-attribute.js +6 -100
- package/lib/atoms/is-displayed.js +2 -1
- package/lib/capabilities.js +7 -0
- package/lib/command.js +4 -0
- package/lib/http.js +5 -1
- package/lib/input.js +12 -0
- package/lib/webdriver.js +57 -1
- package/package.json +1 -1
- package/example/firefox_channels.js +0 -84
package/CHANGES.md
CHANGED
|
@@ -1,3 +1,32 @@
|
|
|
1
|
+
## 4.17.0
|
|
2
|
+
|
|
3
|
+
* Add javascript to Selenium Manager input for tracking (see #13288)
|
|
4
|
+
* remove deprecated headless methods and associated references
|
|
5
|
+
* Add script message event (#13153)
|
|
6
|
+
* Update channel name from Aurora to Dev
|
|
7
|
+
* Remove firefox_channels.js example as Channels is deprecated
|
|
8
|
+
* Add Input module command (#13360)
|
|
9
|
+
* remove all references to firefox-bin
|
|
10
|
+
* download files from remote server (#13102)
|
|
11
|
+
* Add auth required event
|
|
12
|
+
* Add traverse history command
|
|
13
|
+
* Add test to get iframe's browsing context
|
|
14
|
+
* Add Input module JS command
|
|
15
|
+
* Add test for node properties in
|
|
16
|
+
* Add CDP for Chrome 121 and remove 118
|
|
17
|
+
|
|
18
|
+
## 4.16.0
|
|
19
|
+
|
|
20
|
+
#### :bug: Bug fix
|
|
21
|
+
|
|
22
|
+
* Fix logging levels in http.js and webdriver.js (#13098)
|
|
23
|
+
* Remove unused targets from the JS tree (#13129)
|
|
24
|
+
|
|
25
|
+
* #### :nail_care: Polish
|
|
26
|
+
|
|
27
|
+
* Add CDP v120 and remove v117
|
|
28
|
+
|
|
29
|
+
|
|
1
30
|
## 4.15.0
|
|
2
31
|
|
|
3
32
|
#### :bug: Bug fix
|
package/LICENSE
CHANGED
|
@@ -187,7 +187,7 @@
|
|
|
187
187
|
same "printed page" as the copyright notice for easier
|
|
188
188
|
identification within third-party archives.
|
|
189
189
|
|
|
190
|
-
Copyright
|
|
190
|
+
Copyright 2024 Software Freedom Conservancy (SFC)
|
|
191
191
|
|
|
192
192
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
193
193
|
you may not use this file except in compliance with the License.
|
package/NOTICE
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
Copyright 2011-
|
|
1
|
+
Copyright 2011-2024 Software Freedom Conservancy
|
|
2
2
|
Copyright 2004-2011 Selenium committers
|
package/bidi/browsingContext.js
CHANGED
|
@@ -186,7 +186,7 @@ class BrowsingContext {
|
|
|
186
186
|
params: {
|
|
187
187
|
context: this._id,
|
|
188
188
|
clip: {
|
|
189
|
-
type: '
|
|
189
|
+
type: 'box',
|
|
190
190
|
x: x,
|
|
191
191
|
y: y,
|
|
192
192
|
width: width,
|
|
@@ -195,7 +195,10 @@ class BrowsingContext {
|
|
|
195
195
|
},
|
|
196
196
|
}
|
|
197
197
|
|
|
198
|
+
console.log(JSON.stringify(params))
|
|
199
|
+
|
|
198
200
|
const response = await this.bidi.send(params)
|
|
201
|
+
console.log(JSON.stringify(response))
|
|
199
202
|
this.checkErrorInScreenshot(response)
|
|
200
203
|
return response['result']['data']
|
|
201
204
|
}
|
|
@@ -309,6 +312,25 @@ class BrowsingContext {
|
|
|
309
312
|
throw Error(result['error'])
|
|
310
313
|
}
|
|
311
314
|
}
|
|
315
|
+
|
|
316
|
+
async traverseHistory(delta) {
|
|
317
|
+
const params = {
|
|
318
|
+
method: 'browsingContext.traverseHistory',
|
|
319
|
+
params: {
|
|
320
|
+
context: this._id,
|
|
321
|
+
delta: delta,
|
|
322
|
+
},
|
|
323
|
+
}
|
|
324
|
+
await this.bidi.send(params)
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
async forward() {
|
|
328
|
+
await this.traverseHistory(1)
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
async back() {
|
|
332
|
+
await this.traverseHistory(-1)
|
|
333
|
+
}
|
|
312
334
|
}
|
|
313
335
|
|
|
314
336
|
class NavigateResult {
|
package/bidi/input.js
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
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
|
+
// type: module added to package.json
|
|
19
|
+
// import { WebElement } from '../lib/webdriver'
|
|
20
|
+
const { WebElement } = require('../lib/webdriver')
|
|
21
|
+
|
|
22
|
+
class Input {
|
|
23
|
+
constructor(driver) {
|
|
24
|
+
this._driver = driver
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async init() {
|
|
28
|
+
if (!(await this._driver.getCapabilities()).get('webSocketUrl')) {
|
|
29
|
+
throw Error('WebDriver instance must support BiDi protocol')
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
this.bidi = await this._driver.getBidi()
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async perform(browsingContextId, actions) {
|
|
36
|
+
const _actions = await updateActions(actions)
|
|
37
|
+
|
|
38
|
+
const command = {
|
|
39
|
+
method: 'input.performActions',
|
|
40
|
+
params: {
|
|
41
|
+
context: browsingContextId,
|
|
42
|
+
actions: _actions,
|
|
43
|
+
},
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
let response = await this.bidi.send(command)
|
|
47
|
+
|
|
48
|
+
return response
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async release(browsingContextId) {
|
|
52
|
+
const command = {
|
|
53
|
+
method: 'input.releaseActions',
|
|
54
|
+
params: {
|
|
55
|
+
context: browsingContextId,
|
|
56
|
+
},
|
|
57
|
+
}
|
|
58
|
+
return await this.bidi.send(command)
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async function updateActions(actions) {
|
|
63
|
+
const _actions = []
|
|
64
|
+
for (const action of actions) {
|
|
65
|
+
const sequenceList = action.actions
|
|
66
|
+
let updatedSequenceList = []
|
|
67
|
+
|
|
68
|
+
if (action.type === 'pointer' || action.type === 'wheel') {
|
|
69
|
+
for (const sequence of sequenceList) {
|
|
70
|
+
if (
|
|
71
|
+
(sequence.type === 'pointerMove' || sequence.type === 'scroll') &&
|
|
72
|
+
sequence.origin instanceof WebElement
|
|
73
|
+
) {
|
|
74
|
+
const element = sequence.origin
|
|
75
|
+
const elementId = await element.getId()
|
|
76
|
+
sequence.origin = {
|
|
77
|
+
type: 'element',
|
|
78
|
+
element: { sharedId: elementId },
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
updatedSequenceList.push(sequence)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const updatedAction = { ...action, actions: updatedSequenceList }
|
|
85
|
+
_actions.push(updatedAction)
|
|
86
|
+
} else {
|
|
87
|
+
_actions.push(action)
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return _actions
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async function getInputInstance(driver) {
|
|
95
|
+
let instance = new Input(driver)
|
|
96
|
+
await instance.init()
|
|
97
|
+
return instance
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
module.exports = getInputInstance
|
package/bidi/networkInspector.js
CHANGED
|
@@ -39,6 +39,10 @@ class NetworkInspector {
|
|
|
39
39
|
await this.subscribeAndHandleEvent('network.responseCompleted', callback)
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
async authRequired(callback) {
|
|
43
|
+
await this.subscribeAndHandleEvent('network.authRequired', callback)
|
|
44
|
+
}
|
|
45
|
+
|
|
42
46
|
async subscribeAndHandleEvent(eventType, callback) {
|
|
43
47
|
if (this._browsingContextIds != null) {
|
|
44
48
|
await this.bidi.subscribe(eventType, this._browsingContextIds)
|
package/bidi/protocolType.js
CHANGED
package/bidi/protocolValue.js
CHANGED
|
@@ -25,7 +25,7 @@ const TYPE_CONSTANT = 'type'
|
|
|
25
25
|
const VALUE_CONSTANT = 'value'
|
|
26
26
|
const RemoteReferenceType = {
|
|
27
27
|
HANDLE: 'handle',
|
|
28
|
-
SHARED_ID: '
|
|
28
|
+
SHARED_ID: 'sharedId',
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
class LocalValue {
|
|
@@ -98,6 +98,10 @@ class LocalValue {
|
|
|
98
98
|
return new LocalValue(NonPrimitiveType.SET, value)
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
+
static createChannelValue(value) {
|
|
102
|
+
return new LocalValue(NonPrimitiveType.CHANNEL, value)
|
|
103
|
+
}
|
|
104
|
+
|
|
101
105
|
toJson() {
|
|
102
106
|
let toReturn = {}
|
|
103
107
|
toReturn[TYPE_CONSTANT] = this.type
|
|
@@ -165,12 +169,12 @@ class RemoteValue {
|
|
|
165
169
|
}
|
|
166
170
|
|
|
167
171
|
class ReferenceValue {
|
|
168
|
-
constructor(handle,
|
|
172
|
+
constructor(handle, sharedId) {
|
|
169
173
|
if (handle === RemoteReferenceType.HANDLE) {
|
|
170
|
-
this.handle =
|
|
174
|
+
this.handle = sharedId
|
|
171
175
|
} else {
|
|
172
176
|
this.handle = handle
|
|
173
|
-
this.
|
|
177
|
+
this.sharedId = sharedId
|
|
174
178
|
}
|
|
175
179
|
}
|
|
176
180
|
|
|
@@ -180,8 +184,8 @@ class ReferenceValue {
|
|
|
180
184
|
toReturn[RemoteReferenceType.HANDLE] = this.handle
|
|
181
185
|
}
|
|
182
186
|
|
|
183
|
-
if (this.
|
|
184
|
-
toReturn[RemoteReferenceType.SHARED_ID] = this.
|
|
187
|
+
if (this.sharedId != null) {
|
|
188
|
+
toReturn[RemoteReferenceType.SHARED_ID] = this.sharedId
|
|
185
189
|
}
|
|
186
190
|
|
|
187
191
|
return toReturn
|
|
@@ -195,10 +199,56 @@ class RegExpValue {
|
|
|
195
199
|
}
|
|
196
200
|
}
|
|
197
201
|
|
|
202
|
+
class SerializationOptions {
|
|
203
|
+
constructor(
|
|
204
|
+
maxDomDepth = 0,
|
|
205
|
+
maxObjectDepth = null,
|
|
206
|
+
includeShadowTree = 'none'
|
|
207
|
+
) {
|
|
208
|
+
this._maxDomDepth = maxDomDepth
|
|
209
|
+
this._maxObjectDepth = maxObjectDepth
|
|
210
|
+
|
|
211
|
+
if (['none', 'open', 'all'].includes(includeShadowTree)) {
|
|
212
|
+
throw Error(
|
|
213
|
+
`Valid types are 'none', 'open', and 'all'. Received: ${includeShadowTree}`
|
|
214
|
+
)
|
|
215
|
+
}
|
|
216
|
+
this._includeShadowTree = includeShadowTree
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
class ChannelValue {
|
|
221
|
+
constructor(channel, options = undefined, resultOwnership = undefined) {
|
|
222
|
+
this.channel = channel
|
|
223
|
+
|
|
224
|
+
if (options !== undefined) {
|
|
225
|
+
if (options instanceof SerializationOptions) {
|
|
226
|
+
this.options = options
|
|
227
|
+
} else {
|
|
228
|
+
throw Error(
|
|
229
|
+
`Pass in SerializationOptions object. Received: ${options} `
|
|
230
|
+
)
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if (resultOwnership != undefined) {
|
|
235
|
+
if (['root', 'none'].includes(resultOwnership)) {
|
|
236
|
+
this.resultOwnership = resultOwnership
|
|
237
|
+
} else {
|
|
238
|
+
throw Error(
|
|
239
|
+
`Valid types are 'root' and 'none. Received: ${resultOwnership}`
|
|
240
|
+
)
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
198
246
|
module.exports = {
|
|
247
|
+
ChannelValue,
|
|
199
248
|
LocalValue,
|
|
200
249
|
RemoteValue,
|
|
201
250
|
ReferenceValue,
|
|
202
251
|
RemoteReferenceType,
|
|
203
252
|
RegExpValue,
|
|
253
|
+
SerializationOptions,
|
|
204
254
|
}
|
package/bidi/realmInfo.js
CHANGED
package/bidi/scriptManager.js
CHANGED
|
@@ -21,8 +21,10 @@ const {
|
|
|
21
21
|
EvaluateResultException,
|
|
22
22
|
ExceptionDetails,
|
|
23
23
|
} = require('./evaluateResult')
|
|
24
|
-
const {
|
|
24
|
+
const { Message } = require('./scriptTypes')
|
|
25
|
+
const { RealmInfo, RealmType, WindowRealmInfo } = require('./realmInfo')
|
|
25
26
|
const { RemoteValue } = require('./protocolValue')
|
|
27
|
+
const { Source } = require('./scriptTypes')
|
|
26
28
|
const { WebDriverError } = require('../lib/error')
|
|
27
29
|
|
|
28
30
|
class ScriptManager {
|
|
@@ -348,6 +350,55 @@ class ScriptManager {
|
|
|
348
350
|
let response = await this.bidi.send(command)
|
|
349
351
|
return this.realmInfoMapper(response.result.realms)
|
|
350
352
|
}
|
|
353
|
+
|
|
354
|
+
async onMessage(callback) {
|
|
355
|
+
await this.subscribeAndHandleEvent('script.message', callback)
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
async onRealmCreated(callback) {
|
|
359
|
+
await this.subscribeAndHandleEvent('script.realmCreated', callback)
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
async subscribeAndHandleEvent(eventType, callback) {
|
|
363
|
+
if (this._browsingContextIds != null) {
|
|
364
|
+
await this.bidi.subscribe(eventType, this._browsingContextIds)
|
|
365
|
+
} else {
|
|
366
|
+
await this.bidi.subscribe(eventType)
|
|
367
|
+
}
|
|
368
|
+
await this._on(callback)
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
async _on(callback) {
|
|
372
|
+
this.ws = await this.bidi.socket
|
|
373
|
+
this.ws.on('message', (event) => {
|
|
374
|
+
const { params } = JSON.parse(Buffer.from(event.toString()))
|
|
375
|
+
if (params) {
|
|
376
|
+
let response = null
|
|
377
|
+
if ('channel' in params) {
|
|
378
|
+
response = new Message(
|
|
379
|
+
params.channel,
|
|
380
|
+
new RemoteValue(params.data),
|
|
381
|
+
new Source(params.source)
|
|
382
|
+
)
|
|
383
|
+
} else if ('realm' in params) {
|
|
384
|
+
if (params.type === RealmType.WINDOW) {
|
|
385
|
+
response = new WindowRealmInfo(
|
|
386
|
+
params.realm,
|
|
387
|
+
params.origin,
|
|
388
|
+
params.type,
|
|
389
|
+
params.context,
|
|
390
|
+
params.sandbox
|
|
391
|
+
)
|
|
392
|
+
} else if (params.realm !== null && params.type !== null) {
|
|
393
|
+
response = new RealmInfo(params.realm, params.origin, params.type)
|
|
394
|
+
} else if (params.realm !== null) {
|
|
395
|
+
response = params.realm
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
callback(response)
|
|
399
|
+
}
|
|
400
|
+
})
|
|
401
|
+
}
|
|
351
402
|
}
|
|
352
403
|
|
|
353
404
|
async function getScriptManagerInstance(browsingContextId, driver) {
|
|
@@ -0,0 +1,58 @@
|
|
|
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 Message {
|
|
19
|
+
constructor(channel, data, source) {
|
|
20
|
+
this._channel = channel
|
|
21
|
+
this._data = data
|
|
22
|
+
this._source = source
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
get channel() {
|
|
26
|
+
return this._channel
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
get data() {
|
|
30
|
+
return this._data
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
get source() {
|
|
34
|
+
return this._source
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
class Source {
|
|
39
|
+
constructor(source) {
|
|
40
|
+
this._browsingContextId = null
|
|
41
|
+
this._realmId = source.realm
|
|
42
|
+
|
|
43
|
+
// Browsing context is returned as an optional parameter
|
|
44
|
+
if ('context' in source) {
|
|
45
|
+
this._browsingContextId = source.context
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
get browsingContextId() {
|
|
50
|
+
return this._browsingContextId
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
get realmId() {
|
|
54
|
+
return this._realmId
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
module.exports = { Message, Source }
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/chrome.js
CHANGED
|
@@ -36,17 +36,12 @@
|
|
|
36
36
|
* a unique browser session with a clean user profile (unless otherwise
|
|
37
37
|
* configured through the {@link Options} class).
|
|
38
38
|
*
|
|
39
|
-
* __Headless Chrome__ <a id="headless"></a>
|
|
40
|
-
*
|
|
41
|
-
* To start Chrome in headless mode, simply call
|
|
42
|
-
* {@linkplain Options#headless Options.headless()}.
|
|
43
|
-
*
|
|
44
39
|
* let chrome = require('selenium-webdriver/chrome');
|
|
45
40
|
* let {Builder} = require('selenium-webdriver');
|
|
46
41
|
*
|
|
47
42
|
* let driver = new Builder()
|
|
48
43
|
* .forBrowser('chrome')
|
|
49
|
-
* .setChromeOptions(new chrome.Options()
|
|
44
|
+
* .setChromeOptions(new chrome.Options())
|
|
50
45
|
* .build();
|
|
51
46
|
*
|
|
52
47
|
* __Customizing the ChromeDriver Server__ <a id="custom-server"></a>
|
package/chromium.js
CHANGED
|
@@ -36,17 +36,12 @@
|
|
|
36
36
|
* a unique browser session with a clean user profile (unless otherwise
|
|
37
37
|
* configured through the {@link Options} class).
|
|
38
38
|
*
|
|
39
|
-
* __Headless Chromium__ <a id="headless"></a>
|
|
40
|
-
*
|
|
41
|
-
* To start the browser in headless mode, simply call
|
|
42
|
-
* {@linkplain Options#headless Options.headless()}.
|
|
43
|
-
*
|
|
44
39
|
* let chrome = require('selenium-webdriver/chrome');
|
|
45
40
|
* let {Builder} = require('selenium-webdriver');
|
|
46
41
|
*
|
|
47
42
|
* let driver = new Builder()
|
|
48
43
|
* .forBrowser('chrome')
|
|
49
|
-
* .setChromeOptions(new chrome.Options()
|
|
44
|
+
* .setChromeOptions(new chrome.Options())
|
|
50
45
|
* .build();
|
|
51
46
|
*
|
|
52
47
|
* __Customizing the Chromium WebDriver Server__ <a id="custom-server"></a>
|
|
@@ -310,34 +305,6 @@ class Options extends Capabilities {
|
|
|
310
305
|
return this
|
|
311
306
|
}
|
|
312
307
|
|
|
313
|
-
/**
|
|
314
|
-
* @deprecated Use {@link Options#addArguments} instead.
|
|
315
|
-
* @example
|
|
316
|
-
* options.addArguments('--headless=chrome'); (or)
|
|
317
|
-
* options.addArguments('--headless');
|
|
318
|
-
* @example
|
|
319
|
-
*
|
|
320
|
-
* Recommended to use '--headless=chrome' as argument for browsers v94-108.
|
|
321
|
-
* Recommended to use '--headless=new' as argument for browsers v109+.
|
|
322
|
-
*
|
|
323
|
-
* Configures the driver to start the browser in headless mode.
|
|
324
|
-
*
|
|
325
|
-
* > __NOTE:__ Resizing the browser window in headless mode is only supported
|
|
326
|
-
* > in Chromium 60+. Users are encouraged to set an initial window size with
|
|
327
|
-
* > the {@link #windowSize windowSize({width, height})} option.
|
|
328
|
-
*
|
|
329
|
-
* > __NOTE__: For security, Chromium disables downloads by default when
|
|
330
|
-
* > in headless mode (to prevent sites from silently downloading files to
|
|
331
|
-
* > your machine). After creating a session, you may call
|
|
332
|
-
* > {@link ./chrome.Driver#setDownloadPath setDownloadPath} to re-enable
|
|
333
|
-
* > downloads, saving files in the specified directory.
|
|
334
|
-
*
|
|
335
|
-
* @return {!Options} A self reference.
|
|
336
|
-
*/
|
|
337
|
-
headless() {
|
|
338
|
-
return this.addArguments('headless')
|
|
339
|
-
}
|
|
340
|
-
|
|
341
308
|
/**
|
|
342
309
|
* Sets the initial window size.
|
|
343
310
|
*
|
|
@@ -35,7 +35,7 @@ let debugMessagePrinted = false
|
|
|
35
35
|
* Determines the path of the correct Selenium Manager binary
|
|
36
36
|
* @returns {string}
|
|
37
37
|
*/
|
|
38
|
-
function getBinary() {
|
|
38
|
+
function getBinary () {
|
|
39
39
|
const directory = {
|
|
40
40
|
darwin: 'macos',
|
|
41
41
|
win32: 'windows',
|
|
@@ -48,7 +48,8 @@ function getBinary() {
|
|
|
48
48
|
|
|
49
49
|
let seleniumManagerBasePath = path.join(__dirname, '..', '/bin')
|
|
50
50
|
|
|
51
|
-
const filePath = process.env.SE_MANAGER_PATH || path.join(
|
|
51
|
+
const filePath = process.env.SE_MANAGER_PATH || path.join(
|
|
52
|
+
seleniumManagerBasePath, directory, file)
|
|
52
53
|
|
|
53
54
|
if (!fs.existsSync(filePath)) {
|
|
54
55
|
throw new Error(`Unable to obtain Selenium Manager at ${filePath}`)
|
|
@@ -69,8 +70,9 @@ function getBinary() {
|
|
|
69
70
|
* browser location
|
|
70
71
|
*/
|
|
71
72
|
|
|
72
|
-
function driverLocation(options) {
|
|
73
|
-
let args = ['--browser', options.getBrowserName(), '--
|
|
73
|
+
function driverLocation (options) {
|
|
74
|
+
let args = ['--browser', options.getBrowserName(), '--language-binding',
|
|
75
|
+
'javascript', '--output', 'json']
|
|
74
76
|
|
|
75
77
|
if (options.getBrowserVersion() && options.getBrowserVersion() !== '') {
|
|
76
78
|
args.push('--browser-version', options.getBrowserVersion())
|
|
@@ -139,7 +141,7 @@ function driverLocation(options) {
|
|
|
139
141
|
}
|
|
140
142
|
}
|
|
141
143
|
|
|
142
|
-
function logOutput(output) {
|
|
144
|
+
function logOutput (output) {
|
|
143
145
|
for (const key in output.logs) {
|
|
144
146
|
if (output.logs[key].level === 'WARN') {
|
|
145
147
|
log_.warning(`${output.logs[key].message}`)
|
package/example/headless.js
CHANGED
|
@@ -41,10 +41,10 @@ const height = 480
|
|
|
41
41
|
let driver = new Builder()
|
|
42
42
|
.forBrowser('chrome')
|
|
43
43
|
.setChromeOptions(
|
|
44
|
-
new chrome.Options().headless
|
|
44
|
+
new chrome.Options().addArguments('-headless').windowSize({ width, height })
|
|
45
45
|
)
|
|
46
46
|
.setFirefoxOptions(
|
|
47
|
-
new firefox.Options().headless
|
|
47
|
+
new firefox.Options().addArguments('-headless').windowSize({ width, height })
|
|
48
48
|
)
|
|
49
49
|
.build()
|
|
50
50
|
|