diff options
author | Daniel Calviño Sánchez <danxuliu@gmail.com> | 2022-06-19 20:38:05 +0200 |
---|---|---|
committer | Daniel Calviño Sánchez <danxuliu@gmail.com> | 2022-06-20 18:38:03 +0200 |
commit | 04d3ad5962f65c634e89cc9bf9fea9cfe81fa3cd (patch) | |
tree | 81951e9ef41038f2760e305d739a900ea4c17db6 /docs | |
parent | da03ec77adbe34aedfc0b19433d1fab33498aa7c (diff) |
Add explicit method to run asynchronous code
Executing "await someFunctionCall()" as synchronous code works as
expected in Chromium (the execution will not return until the awaited
function ended). However, it does not when explicit Promises are used
(it returns as soon as the main code finished, without waiting for the
Promise to be fulfilled).
WebDriver provides an explicit way to execute asynchronous functions and
signal when they finished to return, so this is used now for all
asynchronous code.
This will also make possible to add support for Firefox, as in Firefox
asynchronous functions executed as synchronous return immediately, so
they need to be explicitly executed as asynchronous.
Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
Diffstat (limited to 'docs')
-rw-r--r-- | docs/Talkbuchet-cli.py | 47 |
1 files changed, 44 insertions, 3 deletions
diff --git a/docs/Talkbuchet-cli.py b/docs/Talkbuchet-cli.py index 64d52006f..229e1d36d 100644 --- a/docs/Talkbuchet-cli.py +++ b/docs/Talkbuchet-cli.py @@ -203,12 +203,53 @@ class SeleniumHelper: def execute(self, script): """ Executes the given script. + + If the script contains asynchronous code "executeAsync()" should be used + instead to properly wait until the asynchronous code finished before + returning. + + Technically Chrome works as expected with something like + "execute('await someFunctionCall(); await anotherFunctionCall()'", but + "executeAsync" has to be used instead for something like + "someFunctionReturningAPromise().then(() => { more code })"). """ self.driver.execute_script(script) self.printLogs() + def executeAsync(self, script): + """ + Executes the given script asynchronously. + + This function should be used to execute JavaScript code that needs to + wait for a promise to be fulfilled, either explicitly or through "await" + calls. + + The script needs to explicitly signal that the execution has finished by + including the special text "{RETURN}" (without quotes). If "{RETURN}" is + not included the function will automatically return once all the root + statements of the script were executed (which works as expected if using + "await" calls, but not if the script includes something like + "someFunctionReturningAPromise().then(() => { more code })"; in that + case the script should be written as + "someFunctionReturningAPromise().then(() => { more code {RETURN} })"). + """ + + # Add an explicit return point at the end of the script if none is + # given. + if script.find('{RETURN}') == -1: + script += '{RETURN}' + + # Asynchronous scripts need to explicitly signal that they are finished + # by invoking the callback injected as the last argument. + # https://www.selenium.dev/documentation/legacy/json_wire_protocol/#sessionsessionidexecute_async + script = script.replace('{RETURN}', '; arguments[arguments.length - 1]()') + + self.driver.execute_async_script(script) + + self.printLogs() + class Talkbuchet: """ @@ -267,7 +308,7 @@ class Talkbuchet: # Clear previous logs self.seleniumHelper.clearLogs() - self.seleniumHelper.execute(talkbuchet) + self.seleniumHelper.executeAsync(talkbuchet) def setAudioEnabled(self, audioEnabled): """ @@ -348,7 +389,7 @@ class Talkbuchet: :param video: True to start video, False otherwise """ - self.seleniumHelper.execute('await startMedia(' + ('true' if audio else 'false') + ', ' + ('true' if video else 'false') + ')') + self.seleniumHelper.executeAsync('await startMedia(' + ('true' if audio else 'false') + ', ' + ('true' if video else 'false') + ')') def closeConnections(self): """ @@ -419,7 +460,7 @@ class Talkbuchet: if scriptTimeout > savedScriptTimeout: self.seleniumHelper.driver.set_script_timeout(scriptTimeout) - self.seleniumHelper.execute('await siege()') + self.seleniumHelper.executeAsync('await siege()') self.seleniumHelper.driver.set_script_timeout(savedScriptTimeout) |