-
-
Notifications
You must be signed in to change notification settings - Fork 130
Add endpoint that receives a webdriver script for batch command execution #328
Conversation
This is very nice direction for remote device testing and distributed device testing. Having a way to optimize performance critical sections like "find and act" while running a full script on the client has not been possible with Appium. A couple questions:
Also I think it would be useful to pass the script language with the script, so that cloud providers can choose to optionally support transpilation of other languages to javascript. |
a note after reading https://github.com/appium/appium-base-driver/pull/328/files#diff-aa816d90f6389bb3ff7a3fc331643232R287 ... an idea of how to pass valid JS commands to the server. (To reduce mistake/work load in client side) like Selenium, we'll prepare some JS commands as atom commands. Each client gets, reads and sends it to server like https://github.com/SeleniumHQ/selenium/blob/2abd80f236d1a7459ef638e96af8c4efd86b4abd/rb/lib/selenium/webdriver/atoms.rb#L30 (we can fix the JS file to fix some issues instead o updating all clients. This is a behefit of shared code.) If sending command is complicated, this method does not work. Users should write JS (or will we implement each languages->JS converter?). |
@KazuCocoa I'm not totally sure I'm following you. Are you saying that it's a bad idea to give clients the ability to write full-on javascript? And instead we implement client methods that simply generate correct javascript? I think that's a good idea, but I don't see them as mutually exclusive. You could either write something like this: await driver.executeDriverScript(`
const el = await driver.$("~foo");
await el.click();
`); or, you could write this (if the client supports it, let's say we're using python: with driver.batch() as batch:
el = batch.find_element_by_accessibility_id("foo")
el.click() And then the python client would, as part of interpreting the context manager there, turn that into valid webdriverio code underneath the hood, and call Is that what you're proposing? If so I agree that'd be awesome, and then it's just up to the clients to implement this "safe" way of using executeScript. In practice though, I'm not sure how easy it would be to do this translation. What about this script? with driver.batch() as batch:
els = batch.find_elements_by_accessibility_id("foo")
for el in els:
el.click() How do you translate the |
thanks for the questions, @xcolwell!
Same as with any other error
Right now they are not (and running inside a pure JS VM, there's no such thing as stdout/stderr per se), but we could make some log object available to the script, which could then be used to put the output in the appium log as well as return it as part of the return value of the function.
Yes, the script can return any simple javascript object at any level of complexity, and JSON is the transport method.
No, I'm not sure if it's possible to attach a watchdog to a VM, but this could presumably be done of Appium as a whole. I'm assuming actions in the VM get counted on a system resource level are counted as happening within the appium process
There could be! We'd just need to decide what we want to make available to the user. In this PR it's just the driver object. But we mentioned above maybe a log object also makes sense. What else makes sense? Within the constraints of security.
I agree. |
@imurchie any objections to this approach? |
ok @mykola-mokhnach |
Alright, I've made all the downstream changes so once we merge all of these, the whole codebase should be using the new security model. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This features needs a separate documentation page
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎉 promising
will work on docs in another PR in the main repo |
OK, docs added in appium/appium#12807 |
const W3C_ELEMENT_KEY = 'element-6066-11e4-a52e-4f735466cecf'; | ||
const MJSONWP_ELEMENT_KEY = 'ELEMENT'; | ||
|
||
async function runScript (driverOpts, script, timeout) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should timeout have a default value?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it does, in the important place where the request from the user is handled (in execute-child.js
) but i'll add a check to make sure it's included
Also just realized that to support this feature, |
I've run some functional tests with @KazuCocoa 's python client changes, and they work (though I ran into a bug with webdriverio sendkeys, seems like these lines are causing the problem--cc @christian-bromann ) |
I will look into it. |
will wait a bit to see what @christian-bromann says before merging, in case a code change is required on this end. otherwise i think this is good to go, and will merge/publish all the dependent PRs once this one is merged. |
ok, with the new version of webdriverio, i've confirmed this works, so will merge now! |
published in 3.17.0 |
The batch command proposal has been under discussion for some time. To summarize, the original proposal was for a new API that would essentially allow encoding of any Appium command in JSON format, including the use of magic values like
{{<element}}
to refer to an element found in a previous command. This original proposal had several drawbacks:This PR takes a much more radical approach. Basically, it asks that the user send in not a formatted list of commands, but rather a script (written in a supported library, in this case webdriverio). This script is run in a NodeJS VM with access to a driver object representing the current session. This proposal has a number of advantages:
The main disadvantages of this new proposal are:
require
function. I'm having trouble thinking how a malicious user could abuse this feature, but it's possible I suppose.I think this is pretty sweet, what do you all think?