Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add test automation support via Web Driver #170

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
187 changes: 187 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -1472,6 +1472,193 @@ <h2>
feature/default allowlist=] is [=default allowlist/'self'=].
</p>
</section>
<section data-cite="webdriver WebDriver-BiDi">
<h2>
Automation
</h2>
<p>
For the purposes of user-agent automation and application testing, this
document defines extensions to the [[[WebDriver]]] and
[[[WebDriver-BiDi]]] specifications. It is OPTIONAL for a user agent to
support them.
</p>
<pre class="idl">
dictionary GeolocationMockCoordinates {
double accuracy = 1;
required double latitude;
required double longitude;
double? altitude = null;
double? altitudeAccuracy = null;
double? heading = null;
double? speed = null;
};
</pre>
<p>
To <dfn>set the system coordinates</dfn> given an optional
{{GeolocationMockCoordinates}}
|coordinates:GeolocationMockCoordinates|, and an optional [=user
agent=] |agent|:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still working on understanding the WebDriver BiDi architecture but in the old WebDriver specification requests have a session from which you can derive the browsing contexts to which a command will apply. Rather than applying to the entire user agent this allows automation to control only the specific context the developer is targeting.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, something like that could work... I'll see how this looks in the implementation and hopefully can base it off that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned in #146, Chromium already implements this in the Chrome DevTools Protocol and it is scoped to a particular browsing context. This interface is used by Chrome DevTools to provide a UI for setting a mock position. It would be weird if a change made while inspecting one page affected other pages as well. Supporting both page-level and browser-level location overrides would introduce a lot of complexity to the implementation.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree... that would be weird.

</p>
<ol class="algorithm">
<li>Let |targets| be a list containing all [=environment settings
object=] which belong to the |agent| if provided, or all [=user
agents=] otherwise.
</li>
<li>Let |tasks| be an [=list/empty=] [=list=].
</li>
<li>For each |target| in |targets|:
<ol>
<li>Queue a task |task| on the [=geolocation task source=] of
|target|'s [=relevant settings object=]'s [=global object=]'s
[=Window/browsing context=] to:
<ol>
<li>If |coordinates| is not given, clear the system location
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should define "system location" in a way that ties into the "acquire a position" algorithm.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought about this as I was specifying this, but I think we might want keep them separate.

I initially tried to hook into "acquire a position"... but I think it might be best to keep them separate: this algorithm just sets the coordinates for the entire user agent*, then the actual API methods "acquire a position".

*at least initially... let's start simple and then see if we need to set it per origin. That adds a lot of complexity thought, so we probably don't want to do that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's as easy as saying, "a top-level traversable has a mock position which is initially unset". This algorithm sets the mock position and the "acquire a position" algorithm checks if the mock position is set in step 5.3.3.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, yeah, I like that the mock position to take precedence over the system one... and it doesn't imply that it's touching the system one at all (it's just something that works with automation and that's it).

and thus make the position unavailable.
</li>
<li>Otherwise, set the system coordinates to match the values
of |coordinates|.
</li>
</ol>
</li>
<li>Append |task| to |tasks|.
</li>
</ol>
</li>
<li>Wait for all |tasks| to finish and return.
</li>
</ol>
<h3>
Set System Coordinates Web Driver Extension
</h3>
<table class="data simple">
<thead>
<tr>
<th>
HTTP Method
</th>
<th>
[=Extension command URI template|URI template=]
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
POST
</td>
<td>
/session/{session id}/geolocation
</td>
</tr>
</tbody>
</table>
<p>
The <dfn class="export" data-for="extension command">set system
coordinates</dfn> [=extension command=] [=remote end steps=] are:
</p>
<ol class="algorithm">
<li>If the |parameters| argument is the empty string:
<ol>
<li>[=Set the system coordinates=].
</li>
<li>Return |success| with data `null`.
</li>
</ol>
</li>
<li>Let |coordinates| be the |parameters| argument [=converted to IDL
value=] of type {{GeolocationMockCoordinates}}.
</li>
<li>If the conversion [=exception/throws=], return an [=invalid
argument=] [=error=].
</li>
<li>[=Set the system coordinates=] to |coordinates|.
</li>
<li>Return |success| with data `null`.
</li>
</ol>
<h3>
The `geolocation` Web Driver BiDi Module
</h3>
<p>
This section defines the `geolocation` [=extension module=] for the
[[WebDriver-BiDi]] specification.
</p>
<p>
The `geolocation` module contains commands for setting the system's
geolocation coordinates and associated types.
</p>
<h4>
`GeolocationCommand` definition
</h4>
<p>
The `GeolocationCommand` [=remote end definition=] is as follows:
</p>
<pre class="cddl">
GeolocationCommand = (
geolocation.setSystemCoordinates
)
</pre>
<h4>
The `Coordinates` type
</h4>
<p>
The `Coordinates` of the geolocation module is defined as follows:
</p>
<pre class="cddl">
geolocation.Coordinates = {
accuracy: float .default 1.0,
latitude: float,
longitude: float,
altitude: float / null .default null,
altitudeAccuracy: float / null .default null,
heading: float / null .default null,
speed: float / null .default null
}
</pre>
<h4>
The `geolocation.setSystemCoordinates` command
</h4>
<pre class="cddl">
geolocation.setCoordinates = (
method: "geolocation.setCoordinates",
params: geolocation.SetCoordinates
)

geolocation.SetCoordinates = {
coordinates: geolocation.Coordinates,
? userContext: text,
}
</pre>
<p>
The [=remote end steps=] with |session| and |command parameters| are:
</p>
<ol>
<li>Let |user context id| be the value of |command
parameters|["userContext"], if present, and default otherwise.
</li>
<li>Let |agent| be the [=user agent=] that represents the user context
with the id |user context id|.
</li>
<li>If the "coordinates" field of |command parameters| is missing:
<ol>
<li>[=Set the system coordinates=] to undefined and |agent|.
</li>
<li>Return [=success=] with data `null`.
</li>
</ol>
</li>
<li>Let |coordinates| be the |command parameters| argument [=converted
to IDL value=] of type {{GeolocationMockCoordinates}}.
</li>
<li>If the conversion [=exception/throws=], return an [=error=] with
[=error code=] [=invalid argument=].
</li>
<li>[=Set the system coordinates=] to |coordinates| and |agent|.
</li>
<li>Return [=success=] with data `null`.
</li>
</ol>
</section>
<section id="conformance"></section>
<section id="idl-index" class="appendix">
<!-- All the Web IDL will magically appear here -->
Expand Down
Loading