Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
seleniumhq
GitHub Repository: seleniumhq/selenium
Path: blob/trunk/javascript/selenium-webdriver/lib/script.js
2884 views
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 logInspector = require('../bidi/logInspector')
19
const scriptManager = require('../bidi//scriptManager')
20
const { LocalValue, ChannelValue } = require('../bidi/protocolValue')
21
const fs = require('node:fs')
22
const path = require('node:path')
23
const by = require('./by')
24
25
class Script {
26
#driver
27
#logInspector
28
#script
29
30
constructor(driver) {
31
this.#driver = driver
32
}
33
34
// This should be done in the constructor.
35
// But since it needs to call async methods we cannot do that in the constructor.
36
// We can have a separate async method that initialises the Script instance.
37
// However, that pattern does not allow chaining the methods as we would like the user to use it.
38
// Since it involves awaiting to get the instance and then another await to call the method.
39
// Using this allows the user to do this "await driver.script().addJavaScriptErrorHandler(callback)"
40
async #init() {
41
if (this.#logInspector !== undefined) {
42
return
43
}
44
this.#logInspector = await logInspector(this.#driver)
45
}
46
47
async #initScript() {
48
if (this.#script !== undefined) {
49
return
50
}
51
this.#script = await scriptManager([], this.#driver)
52
}
53
54
async addJavaScriptErrorHandler(callback) {
55
await this.#init()
56
return await this.#logInspector.onJavascriptException(callback)
57
}
58
59
async removeJavaScriptErrorHandler(id) {
60
await this.#init()
61
await this.#logInspector.removeCallback(id)
62
}
63
64
async addConsoleMessageHandler(callback) {
65
await this.#init()
66
return this.#logInspector.onConsoleEntry(callback)
67
}
68
69
async removeConsoleMessageHandler(id) {
70
await this.#init()
71
72
await this.#logInspector.removeCallback(id)
73
}
74
75
async addDomMutationHandler(callback) {
76
await this.#initScript()
77
78
let argumentValues = []
79
let value = LocalValue.createChannelValue(new ChannelValue('channel_name'))
80
argumentValues.push(value)
81
82
const filePath = path.join(__dirname, 'atoms', 'bidi-mutation-listener.js')
83
84
let mutationListener = fs.readFileSync(filePath, 'utf-8').toString()
85
await this.#script.addPreloadScript(mutationListener, argumentValues)
86
87
let id = await this.#script.onMessage(async (message) => {
88
let payload = JSON.parse(message['data']['value'])
89
let elements = await this.#driver.findElements({
90
css: '*[data-__webdriver_id=' + by.escapeCss(payload['target']) + ']',
91
})
92
93
if (elements.length === 0) {
94
return
95
}
96
97
let event = {
98
element: elements[0],
99
attribute_name: payload['name'],
100
current_value: payload['value'],
101
old_value: payload['oldValue'],
102
}
103
callback(event)
104
})
105
106
return id
107
}
108
109
async removeDomMutationHandler(id) {
110
await this.#initScript()
111
112
await this.#script.removeCallback(id)
113
}
114
115
async pin(script) {
116
await this.#initScript()
117
return await this.#script.addPreloadScript(script)
118
}
119
120
async unpin(id) {
121
await this.#initScript()
122
await this.#script.removePreloadScript(id)
123
}
124
125
async execute(script, ...args) {
126
await this.#initScript()
127
128
const browsingContextId = await this.#driver.getWindowHandle()
129
130
const argumentList = []
131
132
args.forEach((arg) => {
133
argumentList.push(LocalValue.getArgument(arg))
134
})
135
136
const response = await this.#script.callFunctionInBrowsingContext(browsingContextId, script, true, argumentList)
137
138
return response.result
139
}
140
}
141
142
module.exports = Script
143
144