diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /testing/geckodriver/doc | |
parent | Initial commit. (diff) | |
download | thunderbird-upstream.tar.xz thunderbird-upstream.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | testing/geckodriver/doc/ARM.md | 50 | ||||
-rw-r--r-- | testing/geckodriver/doc/Bugs.md | 45 | ||||
-rw-r--r-- | testing/geckodriver/doc/Building.md | 46 | ||||
-rw-r--r-- | testing/geckodriver/doc/Capabilities.md | 98 | ||||
-rw-r--r-- | testing/geckodriver/doc/CrashReports.md | 67 | ||||
-rw-r--r-- | testing/geckodriver/doc/Flags.md | 216 | ||||
-rw-r--r-- | testing/geckodriver/doc/Notarization.md | 44 | ||||
-rw-r--r-- | testing/geckodriver/doc/Patches.md | 31 | ||||
-rw-r--r-- | testing/geckodriver/doc/Profiles.md | 103 | ||||
-rw-r--r-- | testing/geckodriver/doc/Releasing.md | 292 | ||||
-rw-r--r-- | testing/geckodriver/doc/Support.md | 183 | ||||
-rw-r--r-- | testing/geckodriver/doc/Testing.md | 69 | ||||
-rw-r--r-- | testing/geckodriver/doc/TraceLogs.md | 206 | ||||
-rw-r--r-- | testing/geckodriver/doc/Usage.md | 143 | ||||
-rw-r--r-- | testing/geckodriver/doc/index.rst | 55 |
15 files changed, 1648 insertions, 0 deletions
diff --git a/testing/geckodriver/doc/ARM.md b/testing/geckodriver/doc/ARM.md new file mode 100644 index 0000000000..8ae9afae58 --- /dev/null +++ b/testing/geckodriver/doc/ARM.md @@ -0,0 +1,50 @@ +# Self-serving an ARM build + +Mozilla announced the intent to deprecate ARMv7 HF builds of +geckodriver in September 2018. This does not mean you can no longer +use geckodriver on ARM systems, and this document explains how you +can self-service a build for ARMv7 HF. + +Assuming you have already checked out [central], the steps to +cross-compile ARMv7 from a Linux host system is as follows: + + 1. If you don’t have Rust installed: + + ```shell + % curl https://sh.rustup.rs -sSf | sh + ``` + + 2. Install cross-compiler toolchain: + + ```shell + % apt install gcc-arm-linux-gnueabihf libc6-armhf-cross libc6-dev-armhf-cross + ``` + + 3. Create a new shell, or to reuse the existing shell: + + ```shell + % source $HOME/.cargo/env + ``` + + 4. Install rustc target toolchain: + + ```shell + % rustup target install armv7-unknown-linux-gnueabihf + ``` + + 5. Put this in [testing/geckodriver/.cargo/config]: + + ```rust + [target.armv7-unknown-linux-gnueabihf] + linker = "arm-linux-gnueabihf-gcc" + ``` + + 6. Build geckodriver from testing/geckodriver: + + ```shell + % cd testing/geckodriver + % cargo build --release --target armv7-unknown-linux-gnueabihf + ``` + +[central]: https://hg.mozilla.org/mozilla-central/ +[testing/geckodriver/.cargo/config]: https://searchfox.org/mozilla-central/source/testing/geckodriver/.cargo/config diff --git a/testing/geckodriver/doc/Bugs.md b/testing/geckodriver/doc/Bugs.md new file mode 100644 index 0000000000..b561bd41b5 --- /dev/null +++ b/testing/geckodriver/doc/Bugs.md @@ -0,0 +1,45 @@ +# Reporting bugs + +When opening a new issue or commenting on existing issues, please +make sure discussions are related to concrete technical issues +with geckodriver or Marionette. Questions or discussions are more +appropriate for the [mailing list]. + +For issue reports to be actionable, it must be clear exactly +what the observed and expected behaviours are, and how to set up +the state required to observe the erroneous behaviour. The most +useful thing to provide is a minimal HTML document which permits +the problem to be reproduced along with a [trace-level log] from +geckodriver showing the exact wire protocol calls made. + +Because of the wide variety and different charateristics of clients +used with geckodriver, their stacktraces, logs, and code examples are +typically not very useful as they distract from the actual underlying +cause. **For this reason, we cannot overstate the importance of +always providing the [trace-level log] from geckodriver.** Bugs +relating to a specific client should be filed with that project. + +We welcome you to file issues in the [GitHub issue tracker] once you are +confident it has not already been reported. The [ISSUE_TEMPLATE.md] +contains a helpful checklist for things we will want to know about +the affected system, reproduction steps, and logs. + +geckodriver development follows a rolling release model as +we don’t release patches for older versions. It is therefore +useful to use the tip-of-tree geckodriver binary, or failing this, +the latest release when verifying the problem. geckodriver is only +compatible with the current release channel versions of Firefox, and +it consequently does not help to report bugs that affect outdated +and unsupported Firefoxen. Please always try to verify the issue +in the latest Firefox Nightly before you file your bug. + +Once we are satisfied the issue raised is of sufficiently actionable +character, we will continue with triaging it and file a bug where it +is appropriate. Bugs specific to geckodriver will be filed in the +[`Testing :: geckodriver`] component in Bugzilla. + +[mailing list]: index.rst/#communication +[trace-level log]: TraceLogs.md +[GitHub issue tracker]: https://github.com/mozilla/geckodriver/issues +[ISSUE_TEMPLATE.md]: https://raw.githubusercontent.com/mozilla/geckodriver/master/ISSUE_TEMPLATE.md +[`Testing :: geckodriver`]: https://bugzilla.mozilla.org/buglist.cgi?component=geckodriver diff --git a/testing/geckodriver/doc/Building.md b/testing/geckodriver/doc/Building.md new file mode 100644 index 0000000000..49a5a51200 --- /dev/null +++ b/testing/geckodriver/doc/Building.md @@ -0,0 +1,46 @@ +# Building geckodriver + +geckodriver is written in [Rust], a systems programming language +from Mozilla. Crucially, it relies on the [webdriver crate] to +provide the HTTPD and do most of the heavy lifting of marshalling +the WebDriver protocol. geckodriver translates WebDriver [commands], +[responses], and [errors] to the [Marionette protocol], and acts +as a proxy between [WebDriver] and [Marionette]. + +To build geckodriver: + +```shell +% ./mach build testing/geckodriver +``` + +If you use artifact builds you may build geckodriver using cargo, +since mach in this case does not have a compile environment: + +```shell +% cd testing/geckodriver +% cargo build +… +Compiling geckodriver v0.21.0 (file:///code/gecko/testing/geckodriver) +… +Finished dev [optimized + debuginfo] target(s) in 7.83s +``` + +Because all Rust code in central shares the same cargo workspace, +the binary will be put in the `$(topsrcdir)/target` directory. + +You can run your freshly built geckodriver this way: + +```shell +% ./mach geckodriver -- --other --flags +``` + +See [Testing](Testing.md) for how to run tests. + +[Rust]: https://www.rust-lang.org/ +[webdriver crate]: https://crates.io/crates/webdriver +[commands]: https://docs.rs/webdriver/newest/webdriver/command/ +[responses]: https://docs.rs/webdriver/newest/webdriver/response/ +[errors]: https://docs.rs/webdriver/newest/webdriver/error/enum.ErrorStatus.html +[Marionette protocol]: /testing/marionette/Protocol.md +[WebDriver]: https://w3c.github.io/webdriver/ +[Marionette]: /testing/marionette/index.rst diff --git a/testing/geckodriver/doc/Capabilities.md b/testing/geckodriver/doc/Capabilities.md new file mode 100644 index 0000000000..c9eb7a5f97 --- /dev/null +++ b/testing/geckodriver/doc/Capabilities.md @@ -0,0 +1,98 @@ +# Firefox capabilities + +geckodriver has a few capabilities that are specific to Firefox. +Most of these [are documented on MDN](https://developer.mozilla.org/en-US/docs/Web/WebDriver/Capabilities/firefoxOptions). + +We additionally have some capabilities that largely are implementation +concerns that normal users should not care about: + +## `moz:debuggerAddress` + +A boolean value to indicate if Firefox has to be started with the +[Remote Protocol] enabled, which is a low-level debugging interface that +implements a subset of the [Chrome DevTools Protocol] (CDP). + +When enabled the returned `moz:debuggerAddress` capability of the `New Session` +command is the `host:port` combination of a server that supports the following +HTTP endpoints: + +### GET /json/version + +The browser version metadata: + +```json +{ + "Browser": "Firefox/84.0a1", + "Protocol-Version": "1.0", + "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:84.0) Gecko/20100101 Firefox/84.0", + "V8-Version": "1.0", + "WebKit-Version": "1.0", + "webSocketDebuggerUrl": "ws://localhost:9222/devtools/browser/fe507083-2960-a442-bbd7-7dfe1f111c05" +} +``` + +### GET /json/list + +A list of all available websocket targets: + +```json +[ { + "description": "", + "devtoolsFrontendUrl": null, + "faviconUrl": "", + "id": "ecbf9028-676a-1b40-8596-a5edc0e2875b", + "type": "page", + "url": "https://www.mozilla.org/en-US/", + "browsingContextId": 29, + "webSocketDebuggerUrl": "ws://localhost:9222/devtools/page/ecbf9028-676a-1b40-8596-a5edc0e2875b" +} ] +``` + +The contained `webSocketDebuggerUrl` entries can be used to connect to the +websocket and interact with the browser by using the CDP protocol. + +[Remote Protocol]: /remote/index.rst +[Chrome DevTools Protocol]: https://chromedevtools.github.io/devtools-protocol/ + +## `moz:useNonSpecCompliantPointerOrigin` + +A boolean value to indicate how the pointer origin for an action +command will be calculated. + +With Firefox 59 the calculation will be based on the requirements +by the [WebDriver] specification. This means that the pointer origin +is no longer computed based on the top and left position of the +referenced element, but on the in-view center point. + +To temporarily disable the WebDriver conformant behavior use `false` +as value for this capability. + +Please note that this capability exists only temporarily, and that +it will be removed once all Selenium bindings can handle the new +behavior. + +## `moz:webdriverClick` + +A boolean value to indicate which kind of interactability checks +to run when performing a click or sending keys to an elements. For +Firefoxen prior to version 58.0 some legacy code as imported from +an older version of FirefoxDriver was in use. + +With Firefox 58 the interactability checks as required by the +[WebDriver] specification are enabled by default. This means +geckodriver will additionally check if an element is obscured by +another when clicking, and if an element is focusable for sending +keys. + +Because of this change in behaviour, we are aware that some extra +errors could be returned. In most cases the test in question might +have to be updated so it's conform with the new checks. But if the +problem is located in geckodriver, then please raise an issue in +the [issue tracker]. + +To temporarily disable the WebDriver conformant checks use `false` +as value for this capability. + +Please note that this capability exists only temporarily, and that +it will be removed once the interactability checks have been +stabilized. diff --git a/testing/geckodriver/doc/CrashReports.md b/testing/geckodriver/doc/CrashReports.md new file mode 100644 index 0000000000..576bdda7a9 --- /dev/null +++ b/testing/geckodriver/doc/CrashReports.md @@ -0,0 +1,67 @@ +# Analyzing crash data of Firefox + +It's not uncommon that under some special platform configurations and while +running automated tests via Selenium and geckodriver Firefox could crash. In +those cases it is very helpful to retrieve the generated crash data aka +minidump files, and report these to us. + +## Retrieve the crash data + +Because geckodriver creates a temporary user profile for Firefox, it also +automatically removes all its folders once the tests have been finished. That +also means that if Firefox crashed the created minidump files are lost. To +prevent that a custom profile has to be used instead. The following code +shows an example by using the Python Selenium bindings on Mac OS: + +```python +import tempfile + +from selenium import webdriver +from selenium.webdriver.firefox.options import Options + +# Custom profile folder to keep the minidump files +profile = tempfile.mkdtemp(".selenium") +print("*** Using profile: {}".format(profile)) + +# Use the above folder as custom profile +opts = Options() +opts.add_argument("-profile") +opts.add_argument(profile) +opts.binary = "/Applications/Firefox.app/Contents/MacOS/firefox" + +driver = webdriver.Firefox( + options=opts, + # hard-code the Marionette port so geckodriver can connect + service_args=["--marionette-port", "2828"] +) + +# Your test code which crashes Firefox +``` + +Executing the test with Selenium now, which triggers the crash of Firefox +will leave all the files from the user profile around in the above path. + +To retrieve the minidump files navigate to that folder and look for a sub +folder with the name `minidumps`. It should contain at least one series of +files. One file with the `.dmp` extension and another one with `.extra`. +Both of those files are needed. If more crash files are present grab them all. + +Attach the files as best archived as zip file to the created [geckodriver issue] +on Github. + +[geckodriver issue]: https://github.com/mozilla/geckodriver/issues/new + +## Getting details of the crash + +More advanced users can upload the generated minidump files themselves and +receive details information about the crash. Therefore find the [crash reporter] +folder and copy all the generated minidump files into the `pending` sub directory. +Make sure that both the `.dmp` and `.extra` files are present. + +Once done you can also [view the crash reports]. + +If you submitted a crash please do not forget to also add the link of the +crash report to the geckodriver issue. + +[crash reporter]: https://support.mozilla.org/kb/mozillacrashreporter#w_viewing-reports-outside-of-firefox +[view the crash reports]: https://support.mozilla.orgkb/mozillacrashreporter#w_viewing-crash-reports diff --git a/testing/geckodriver/doc/Flags.md b/testing/geckodriver/doc/Flags.md new file mode 100644 index 0000000000..3db6e27c06 --- /dev/null +++ b/testing/geckodriver/doc/Flags.md @@ -0,0 +1,216 @@ +<!-- markdownlint-disable MD033 --> +# Flags + +## <code>-\\-allow-hosts <var>ALLOW_HOSTS</var>...</code> + +Values of the `Host` header to allow for incoming requests. + +By default the value of <var>HOST</var> is allowed. If `--allow-hosts` +is provided, exactly the given values will be permitted. For example +`--allow-host geckodriver.test webdriver.local` will allow requests +with `Host` set to `geckodriver.test` or `webdriver.local`. + +Requests with `Host` set to an IP address are always allowed. + +## <code>-\\-allow-origins <var>ALLOW_ORIGINS</var>...</code> + +Values of the `Origin` header to allow for incoming requests. + +`Origin` is set by web browsers for all `POST` requests, and most +other cross-origin requests. By default any request with an `Origin` +header is rejected to protect against malicious websites trying to +access geckodriver running on the local machine. + +If `--allow-origins` is provided, web services running on the given +origin will be able to make requests to geckodriver. For example +`--allow-origins https://webdriver.test:8080` will allow a web-based +service on the origin with scheme `https`, hostname `webdriver.test`, +and port `8080` to access the geckodriver instance. + +## <code>-\\-android-storage <var>ANDROID_STORAGE</var></code> + +**Deprecation warning**: This argument is deprecated and planned to be removed +with the 0.31.0 release of geckodriver. As such it shouldn't be used with version +0.30.0 or later anymore. By default the automatic detection will now use the +external storage location, which is always readable and writeable. + +Selects the test data location on the Android device, eg. the Firefox profile. +By default `auto` is used. + +<style type="text/css"> + table { width: 100%; margin-bottom: 2em; } + table, th, td { border: solid gray 1px; } + td, th { padding: 10px; text-align: left; vertical-align: middle; } + td:nth-child(1), th:nth-child(1) { width: 10em; text-align: center; } +</style> + +<table> + <thead> + <tr> + <th>Value + <th>Description + </tr> + </thead> + + <tr> + <td>auto + <td>Best suitable location based on whether the device is rooted.<br/> + If the device is rooted `internal` is used, otherwise `app`. + <tr> + <td>app + <td><p>Location: `/data/data/%androidPackage%/test_root`</p> + Based on the `androidPackage` capability that is passed as part of + `moz:firefoxOptions` when creating a new session. Commands that + change data in the app's directory are executed using run-as. This requires + that the installed app is debuggable. + <tr> + <td>internal + <td><p>Location: `/data/local/tmp/test_root`</p> + The device must be rooted since when the app runs, files that are created + in the profile, which is owned by the app user, cannot be changed by the + shell user. Commands will be executed via `su`. + <tr> + <td>sdcard + <td><p>Location: `$EXTERNAL_STORAGE/Android/data/%androidPackage%/files/test_root`</p> + This location is supported by all versions of Android whether if the device + is rooted or not. +</table> + +## <code>-b <var>BINARY</var></code> / <code>-\\-binary <var>BINARY</var></code> + +Path to the Firefox binary to use. By default geckodriver tries to +find and use the system installation of Firefox, but that behaviour +can be changed by using this option. Note that the `binary` +capability of the `moz:firefoxOptions` object that is passed when +[creating a new session] will override this option. + +On Linux systems it will use the first _firefox_ binary found +by searching the `PATH` environmental variable, which is roughly +equivalent to calling [whereis(1)] and extracting the second column: + +```shell +% whereis firefox +firefox: /usr/bin/firefox /usr/local/firefox +``` + +On macOS, the binary is found by looking for the first _firefox-bin_ +binary in the same fashion as on Linux systems. This means it is +possible to also use `PATH` to control where geckodriver should +find Firefox on macOS. It will then look for _/Applications/Firefox.app_. + +On Windows systems, geckodriver looks for the system Firefox by +scanning the Windows registry. + +[creating a new session]: https://w3c.github.io/webdriver/#new-session +[whereis(1)]: http://www.manpagez.com/man/1/whereis/ + +## <code>-\\-connect-existing</code> + +Connect geckodriver to an existing Firefox instance. This means +geckodriver will abstain from the default of starting a new Firefox +session. + +The existing Firefox instance must have [Marionette] enabled. +To enable the remote protocol in Firefox, you can pass the +`--marionette` flag. Unless the `marionette.port` preference +has been user-set, Marionette will listen on port 2828. So when +using `--connect-existing` it is likely you will also have to use +`--marionette-port` to set the correct port. + +## <code>-\\-host <var>HOST</var></code> + +Host to use for the WebDriver server. Defaults to 127.0.0.1. + +## <code>-\\-jsdebugger</code> + +Attach [browser toolbox] debugger when Firefox starts. This is +useful for debugging [Marionette] internals. + +To be prompted at the start of the test run or between tests, +you can set the `marionette.debugging.clicktostart` preference to +`true`. + +For reference, below is the list of preferences that enables the +chrome debugger. These are all set implicitly when the +argument is passed to geckodriver. + +* `devtools.browsertoolbox.panel` -> `jsdebugger` + + Selects the Debugger panel by default. + +* `devtools.chrome.enabled` → true + + Enables debugging of chrome code. + +* `devtools.debugger.prompt-connection` → false + + Controls the remote connection prompt. Note that this will + automatically expose your Firefox instance to localhost. + +* `devtools.debugger.remote-enabled` → true + + Allows a remote debugger to connect, which is necessary for + debugging chrome code. + +[browser toolbox]: https://developer.mozilla.org/en-US/docs/Tools/Browser_Toolbox + +## <code>-\\-log <var>LEVEL</var></code> + +Set the Gecko and geckodriver log level. Possible values are `fatal`, +`error`, `warn`, `info`, `config`, `debug`, and `trace`. + +## <code>-\\-log-no-truncate</code> + +Disables truncation of long log lines. + +## <code>-\\-marionette-host <var>HOST</var></code> + +Selects the host for geckodriver’s connection to the [Marionette] +remote protocol. Defaults to 127.0.0.1. + +## <code>-\\-marionette-port <var>PORT</var></code> + +Selects the port for geckodriver’s connection to the [Marionette] +remote protocol. + +In the default mode where geckodriver starts and manages the Firefox +process, it will pick a free port assigned by the system and set the +`marionette.port` preference in the profile. + +When `--connect-existing` is used and the Firefox process is not +under geckodriver’s control, it will simply connect to <var>PORT</var>. + +`--connect-existing`: #connect-existing + +## <code>-p <var>PORT</var></code> / <code>-\\-port <var>PORT</var></code> + +Port to use for the WebDriver server. Defaults to 4444. + +A helpful trick is that it is possible to bind to 0 to get the +system to atomically assign a free port. + +## <code>-\\-profile-root <var>PROFILE_ROOT</var></code> + +Path to the directory to use when creating temporary profiles. By +default this is the system temporary directory. Both geckodriver and +Firefox must have read-write access to this path. + +This setting can be useful when Firefox is sandboxed from the host +filesystem such that it doesn't share the same system temporary +directory as geckodriver (e.g. when running Firefox inside a container +or packaged as a snap). + +## <code>-v[v]</code> + +Increases the logging verbosity by to debug level when passing +a single `-v`, or to trace level if `-vv` is passed. This is +analogous to passing `--log debug` and `--log trace`, respectively. + +## <code>-\\-websocket-port<var>PORT</var></code> + +Port to use to connect to WebDriver BiDi. Defaults to 9222. + +A helpful trick is that it is possible to bind to 0 to get the +system to atomically assign a free port. + +[Marionette]: /testing/marionette/index.rst diff --git a/testing/geckodriver/doc/Notarization.md b/testing/geckodriver/doc/Notarization.md new file mode 100644 index 0000000000..ba1ba08d64 --- /dev/null +++ b/testing/geckodriver/doc/Notarization.md @@ -0,0 +1,44 @@ +# MacOS notarization + +With the introduction of macOS 10.15 “Catalina” Apple introduced +[new notarization requirements] that all software must be signed +and notarized centrally. + +Whilst the geckodriver binary is technically both signed and notarized, the +actual validation can only be performed by MacOS if the machine that starts +the geckodriver binary for the very first time is online. Offline validation +would require shipping geckodriver as a DMG/PKG. You can track the relevant +progress in [bug 1783943]. + +Note: geckodriver releases between 0.26.0 and 0.31.0 don't have the +notarization applied and always require the manual steps below to +bypass the notarization requirement of the binary during the very first start. + +[new notarization requirements]: https://developer.apple.com/news/?id=04102019a +[bug 1783943]: https://bugzilla.mozilla.org/show_bug.cgi?id=1783943 + +## Offline mode + +There are some mitigating circumstances: + +* Verification problems only occur when other notarized programs, + such as a web browser, downloads the software from the internet. + +* Arbitrary software downloaded through other means, such as + curl(1) is _not_ affected by this change. + +In other words, if your method for fetching geckodriver on macOS +is through the GitHub web UI using a web browser, the program will +not be able to run unless you manually disable the quarantine check +(explained below). If downloading geckodriver via other means +than a macOS notarized program, you should not be affected. + +To bypass the notarization requirement on macOS if you have downloaded +the geckodriver .tar.gz via a web browser, you can run the following +command in a terminal: + + % xattr -r -d com.apple.quarantine geckodriver + +A problem with notarization will manifest itself through a security +dialogue appearing, explaining that the source of the program is +not trusted. diff --git a/testing/geckodriver/doc/Patches.md b/testing/geckodriver/doc/Patches.md new file mode 100644 index 0000000000..e559da075d --- /dev/null +++ b/testing/geckodriver/doc/Patches.md @@ -0,0 +1,31 @@ +# Submitting patches + +You can submit patches by using [Phabricator]. Walk through its documentation +in how to set it up, and uploading patches for review. Don't worry about which +person to select for reviewing your code. It will be done automatically. + +Please also make sure to follow the [commit creation guidelines]. + +Once you have contributed a couple of patches, we are happy to sponsor you in +[becoming a Mozilla committer]. When you have been granted commit access +level 1, you will have permission to use the [Firefox CI] to trigger your own +“try runs” to test your changes. You can use the following [try preset] to run +the most relevant tests: + +```shell +% ./mach try --preset geckodriver +``` + +This preset will schedule geckodriver-related tests on various platforms. You can +reduce the number of tasks by filtering on platforms (e.g. linux) or build type +(e.g. opt): + +```shell +% ./mach try --preset geckodriver -xq "'linux 'opt" +``` + +[Phabricator]: https://moz-conduit.readthedocs.io/en/latest/phabricator-user.html +[commit creation guidelines]: https://mozilla-version-control-tools.readthedocs.io/en/latest/devguide/contributing.html?highlight=phabricator#submitting-patches-for-review +[becoming a Mozilla committer]: https://www.mozilla.org/en-US/about/governance/policies/commit/ +[Firefox CI]: https://treeherder.mozilla.org/ +[try preset]: https://firefox-source-docs.mozilla.org/tools/try/presets.html diff --git a/testing/geckodriver/doc/Profiles.md b/testing/geckodriver/doc/Profiles.md new file mode 100644 index 0000000000..abad9af730 --- /dev/null +++ b/testing/geckodriver/doc/Profiles.md @@ -0,0 +1,103 @@ +# Profiles + +geckodriver uses [profiles] to instrument Firefox’ behaviour. The +user will usually rely on geckodriver to generate a temporary, +throwaway profile. These profiles are deleted when the WebDriver +session expires. + +In cases where the user needs to use custom, prepared profiles, +geckodriver will make modifications to the profile that ensures +correct behaviour. See [_Automation preferences_] below on the +precedence of user-defined preferences in this case. + +Custom profiles can be provided two different ways: + + 1. by appending `--profile /some/location` to the [`args` capability], + which will instruct geckodriver to use the profile _in-place_; + + 2. or by setting the [`profile` capability] to a Base64-encoded + ZIP of the profile directory. + +Note that geckodriver has a [known bug concerning `--profile`] that +prevents the randomised Marionette port from being passed to +geckodriver. To circumvent this issue, make sure you specify the +port manually using `--marionette-port <port>`. + +The second way is compatible with shipping Firefox profiles across +a network, when for example the geckodriver instance is running on +a remote system. This is the case when using Selenium’s `RemoteWebDriver` +concept, where the WebDriver client and the server are running on +two distinct systems. + +[profiles]: https://support.mozilla.org/en-US/kb/profiles-where-firefox-stores-user-data +[_Automation preferences_]: #automation-preferences +[`args` capability]: https://developer.mozilla.org/en-US/docs/Web/WebDriver/Capabilities/firefoxOptions#args_array_of_strings +[`profile` capability]: https://developer.mozilla.org/en-US/docs/Web/WebDriver/Capabilities/firefoxOptions#profile_string +[known bug concerning `--profile`]: https://github.com/mozilla/geckodriver/issues/1058 + +## Default locations for temporary profiles + +When a custom user profile is not provided with the `-profile` +command-line argument geckodriver generates a temporary, throwaway +profile. This is written to the default system temporary folder +and subsequently removed when the WebDriver session expires. + +The default location for temporary profiles depends on the system. +On Unix systems it uses /tmp, and on Windows it uses the Windows +directory. + +The default location can be overridden. On Unix you set the `TMPDIR` +environment variable. On Windows, the following environment variables +are respected, in order: + + 1. `TMP` + 2. `TEMP` + 3. `USERPROFILE` + +It is not necessary to change the temporary directory system-wide. +All you have to do is make sure it gets set for the environment of +the geckodriver process: + + TMPDIR=/some/location ./geckodriver + +## Automation preferences + +As indicated in the introduction, geckodriver configures Firefox +so it is well-behaved in automation environments. It uses a +combination of preferences written to the profile prior to launching +Firefox (1), and a set of recommended preferences set on startup (2). + +These can be perused here: + + 1. [testing/geckodriver/src/prefs.rs](https://searchfox.org/mozilla-central/source/testing/geckodriver/src/prefs.rs) + 2. [remote/components/marionette.js](https://searchfox.org/mozilla-central/source/remote/components/marionette.js) + +As mentioned, these are _recommended_ preferences, and any user-defined +preferences in the [user.js file] or as part of the [`prefs` capability] +take precedence. This means for example that the user can tweak +`browser.startup.page` to override the recommended preference for +starting the browser with a blank page. + +The recommended preferences set at runtime (see 2 above) may also +be disabled entirely by setting `remote.prefs.recommended` starting with Firefox +91. For older versions of Firefox, the preference to use was +`marionette.prefs.recommended`. +This may however cause geckodriver to not behave correctly according +to the WebDriver standard, so it should be used with caution. + +Users should take note that the `marionette.port` preference is +special, and will always be overridden when using geckodriver unless +the `--marionette-port <port>` flag is used specifically to instruct +the Marionette server in Firefox which port to use. + +[user.js file]: http://kb.mozillazine.org/User.js_file +[`prefs` capability]: https://developer.mozilla.org/en-US/docs/Web/WebDriver/Capabilities/firefoxOptions#prefs_preferences_object + +## Temporary profiles not being removed + +It is a known bug that geckodriver in some instances fails to remove +the temporary profile, particularly when the session is not explicitly +deleted or the process gets interrupted. See [geckodriver issue +299] for more information. + +[geckodriver issue 299]: https://github.com/mozilla/geckodriver/issues/299 diff --git a/testing/geckodriver/doc/Releasing.md b/testing/geckodriver/doc/Releasing.md new file mode 100644 index 0000000000..79574f8a0e --- /dev/null +++ b/testing/geckodriver/doc/Releasing.md @@ -0,0 +1,292 @@ +# Releasing geckodriver + +Releasing geckodriver is not as easy as it once used to be when the +project’s canonical home was on GitHub. Today geckodriver is hosted +in [mozilla-central], and whilst we do want to make future releases +from [Mozilla’s CI infrastructure], we are currently in between two +worlds: development happens in m-c, but releases continue to be made +from GitHub. + +In any case, the steps to release geckodriver are as follows: + +[mozilla-central]: https://hg.mozilla.org/mozilla-central/ +[Mozilla’s CI infrastructure]: https://treeherder.mozilla.org/ + +## Update in-tree dependency crates + +geckodriver depends on a number of Rust crates that also live in +central by using relative paths. Here an excerpt from its `Cargo.toml`: + +```ini +[dependencies] +… +marionette = { path = "./marionette" } +… +mozdevice = { path = "../mozbase/rust/mozdevice" } +mozprofile = { path = "../mozbase/rust/mozprofile" } +mozrunner = { path = "../mozbase/rust/mozrunner" } +mozversion = { path = "../mozbase/rust/mozversion" } +… +webdriver = { path = "../webdriver" } +``` + +Because we need to export the geckodriver source code to the old +GitHub repository when we release, we first need to publish these +crates in the specified order if they have had any changes in the +interim since the last release. If they have received no changes, +you can skip them: + +- `testing/mozbase/rust/mozdevice` +- `testing/mozbase/rust/mozprofile` +- `testing/mozbase/rust/mozrunner` +- `testing/mozbase/rust/mozversion` +- `testing/webdriver` +- `testing/geckodriver/marionette` + +For each crate: + +1. Change into the crates folder. +2. Bump the version number in `Cargo.toml` based on [semantic versioning rules], + and also update the version dependency for other in-tree crates using the + currently modified crate. Note that running `cargo update` will fail if you + missed updating a crate's dependency. + +3. Use the [cargo-semver-checks] command to validate the version change: + + ```shell + % cargo semver-checks check-release + ``` + +4. Update the crate: + + ```shell + % cargo update -p <crate name> + ``` + +5. We also publish audit information for the crates based on Mozilla's + [audit criteria]. Because we use [wildcard audit entries] make sure that the + latest day of publication is still within the `end` date. The related entry + of the crate can be found at the top of [audits.toml]. If the date is over, + then update its value to at most 1 year in the future. + +6. Commit the changes for the modified [Cargo.toml] files, [Cargo.lock] and + [audits.toml]. + + ```shell + % git add Cargo.toml Cargo.lock audits.toml testing + % git commit -m "Bug XYZ - [rust-<name>] Release version <version>" + ``` + +[semantic versioning rules]: https://semver.org/ +[cargo-semver-checks]: https://crates.io/crates/cargo-semver-checks +[audit criteria]: https://mozilla.github.io/cargo-vet/audit-criteria.html +[wildcard audit entries]: https://mozilla.github.io/cargo-vet/wildcard-audit-entries.html +[Cargo.toml]: https://searchfox.org/mozilla-central/source/testing/geckodriver/Cargo.toml +[Cargo.lock]: https://searchfox.org/mozilla-central/source/Cargo.lock +[audits.toml]: https://searchfox.org/mozilla-central/source/supply-chain/audits.toml + +## Update the change log + +Notable changes to geckodriver are mentioned in [CHANGES.md]. Many +users rely on this, so it’s important that you make it **relevant +to end-users**. For example, we only mention changes that are visible +to users. The change log is not a complete anthology of commits, +as these often will not convey the essence of a change to end-users. +If a feature was added but removed before release, there is no reason +to list it as a change. + +It is good practice to also include relevant information from the +[webdriver], [marionette], [rust-mozrunner], and [rust-mozdevice] crates, +since these are the most important dependencies of geckodriver and a lot +of its functionality is implemented there. + +To get a list of all the changes for one of the above crates one of the following +commands can be used: + +```shell +% hg log -M -r <revision>::central --template "{node|short}\t{desc|firstline}\n" <path> +% git log --reverse $(git cinnabar hg2git <revision>)..HEAD --pretty="%s" <path> +``` + +where `<revision>` is the changeset of the last geckodriver release and `<path>` +the location of the crate in the repository. + +Add the list of changes to the related release bug on Bugzilla, and also check the +dependency list of the bug for other fixes that are worth mentioning. + +We follow the writing style of the existing change log, with +one section per version (with a release date), with subsections +‘Added’, ‘Changed’, 'Fixed' and ‘Removed’. If the targeted +Firefox or Selenium versions have changed, it is good to make a +mention of this. Lines are optimally formatted at roughly 72 columns +to make the file readable in a text editor as well as rendered HTML. +fmt(1) does a splendid job at text formatting. + +[CHANGES.md]: https://searchfox.org/mozilla-central/source/testing/geckodriver/CHANGES.md +[webdriver]: https://searchfox.org/mozilla-central/source/testing/webdriver +[marionette]: https://searchfox.org/mozilla-central/source/testing/geckodriver/marionette +[rust-mozrunner]: https://searchfox.org/mozilla-central/source/testing/mozbase/rust/mozrunner +[rust-mozdevice]: https://searchfox.org/mozilla-central/source/testing/mozbase/rust/mozdevice + +## Bump the version number and update the support page + +Bump the version number in [Cargo.toml] to the next version. +geckodriver follows [semantic versioning] so it’s a good idea to +familiarise yourself with that before deciding on the version number. + +After you’ve changed the version number, run + +```shell +% ./mach build testing/geckodriver +``` + +again to update [Cargo.lock]. + +Now update the [support page] by adding a new row to the versions table, +including the required versions of Selenium, and Firefox. + +Finally commit all those changes. + +[semantic versioning]: http://semver.org/ +[support page]: https://searchfox.org/mozilla-central/source/testing/geckodriver/doc/Support.md + +## Add the changeset id + +To easily allow a release build of geckodriver after cloning the +repository, the changeset id for the release has to be added to the +change log. Therefore add a final place-holder commit to the patch +series, to already get review for. + +Once all previous revisions of the patch series have been landed, and got merged +to `mozilla-central`, the changeset id from the merge commit has to picked for +finalizing the change log. This specific id is needed because Taskcluster creates +the final signed builds based on that merge. + +## Release new in-tree dependency crates + +Make sure to wait until the complete patch series from above has been +merged to mozilla-central. Then continue with the following steps. + +Before releasing geckodriver all dependency crates as +[updated earlier](#update-in-tree-dependency-crates) have to be +released first. + +Therefore change into each of the directories for crates with an update +and run the following command to publish the crate: + +```shell +% cargo publish +``` + +Note that if a crate has an in-tree dependency make sure to first +change the dependency information. + +Do not release the geckodriver crate yet! + +Once all crates have been published observe the `/target/package/` folder under +the root of the mozilla-central repository and remove all the folders related +to the above published packages (it will save ~1GB disk space). + +## Export to GitHub + +The canonical GitHub repository is <https://github.com/mozilla/geckodriver.git> +so make sure you have a local clone of that. It has three branches: +_master_ which only contains the [README.md]; _old_ which was the +state of the project when it was exported to mozilla-central; and +_release_, from where releases are made. + +Before we copy the code over to the GitHub repository we need to +check out the [release commit that bumped the version number](#add-the-changeset-id) +on mozilla-central: + +```shell +% hg update $RELEASE_REVISION +``` + +Or: + +```shell +% git checkout $(git cinnabar hg2git $RELEASE_REVISION) +``` + +We will now export the contents of [testing/geckodriver] to a new branch that +is based on the _release_ branch, which will be used to create a pull request: + +```shell +% cd $SRC/geckodriver +% git checkout release +% git pull +% git checkout -b do_release_X.Y.Z +% git rm -rf . +% git clean -fxd +% cp -rt $SRC/gecko/testing/geckodriver . +``` + +Now verify that geckodriver builds correctly by running: + +```shell +% cargo build +``` + +[README.md]: https://searchfox.org/mozilla-central/source/testing/geckodriver/README.md +[testing/geckodriver]: https://searchfox.org/mozilla-central/source/testing/geckodriver + +## Commit local changes + +Now commit all the changes you have made locally to the _release_ branch. +It is recommended to setup a [GPG key] for signing the commit, so +that the release commit is marked as `verified`. + +```shell +% git add . -- ':!mach_commands.py :!moz.build :!target/*' +% git commit -S -am "Import of vX.Y.Z" (signed) +``` + +or if you cannot use signing use: + +```shell +% git add . -- ':!mach_commands.py :!moz.build :!target/*' +% git commit -am "Import of vX.Y.Z" (unsigned) +``` + +Then push the changes, and create a pull request: + +```shell +% git push origin do_release_X.Y.Z +``` + +As indicated above, the changes you make to this branch will not +be upstreamed back into mozilla-central. It is merely used as a +place for external consumers to build their own version of geckodriver. + +[GPG key]: https://help.github.com/articles/signing-commits/ + +## Make the release + +geckodriver needs to be manually released on github.com. Therefore start to +[draft a new release], and make the following changes: + +1. Specify the "Tag version", and select "Release" as target. + +2. Leave the release title empty + +3. Paste the raw Markdown source from [CHANGES.md] into the description field. + This will highlight for end-users what changes were made in that particular + package when they visit the GitHub downloads section. Make sure to check that + all references can be resolved, and if not make sure to add those too. + +4. Find the signed geckodriver archives in the [taskcluster index] by + replacing %changeset% with the full release changeset id. Rename the + individual files so the basename looks like 'geckodriver-v%version%-%platform%'. + Upload them all, including the checksum files for the Linux platforms. + +5. Before announcing the release on GitHub publish the geckodriver crate as well + on crates.io by running `cargo publish` from the release branch. + +6. Send the release announcement to the [dev-webdriver] mailing list. + +[draft a new release]: https://github.com/mozilla/geckodriver/releases/new +[taskcluster index]: https://firefox-ci-tc.services.mozilla.com/tasks/index/gecko.v2.mozilla-central.revision.%changeset%.geckodriver +[dev-webdriver]: https://groups.google.com/a/mozilla.org/g/dev-webdriver + +Congratulations! You’ve released geckodriver! diff --git a/testing/geckodriver/doc/Support.md b/testing/geckodriver/doc/Support.md new file mode 100644 index 0000000000..0c06ee1bc0 --- /dev/null +++ b/testing/geckodriver/doc/Support.md @@ -0,0 +1,183 @@ +<!-- markdownlint-disable MD033 --> +# Supported platforms + +The following table shows a mapping between [geckodriver releases], +and required versions of Selenium and Firefox: + +<style type="text/css"> + table { width: 100%; margin-bottom: 2em; } + table, th, td { border: solid gray 1px; } + td, th { padding: 5px 10px; text-align: center; } +</style> + +<table> + <thead> + <tr> + <th rowspan="2">geckodriver + <th rowspan="2">Selenium + <th colspan="2">Firefox + </tr> + <tr> + <th>min + <th>max + </tr> + </thead> + </thead> + <tr> + <td>0.33.0 + <td>≥ 3.11 (3.14 Python) + <td>102 ESR + <td>n/a + <tr> + <td>0.32.2 + <td>≥ 3.11 (3.14 Python) + <td>102 ESR + <td>n/a + <tr> + <td>0.32.1 + <td>≥ 3.11 (3.14 Python) + <td>102 ESR + <td>n/a + <tr> + <td>0.32.0 + <td>≥ 3.11 (3.14 Python) + <td>102 ESR + <td>n/a + <tr> + <td>0.31.0 + <td>≥ 3.11 (3.14 Python) + <td>91 ESR + <td>n/a + <tr> + <tr> + <td>0.30.0 + <td>≥ 3.11 (3.14 Python) + <td>78 ESR + <td>90 + <tr> + <td>0.29.1 + <td>≥ 3.11 (3.14 Python) + <td>60 + <td>90 + <tr> + <td>0.29.0 + <td>≥ 3.11 (3.14 Python) + <td>60 + <td>90 + <tr> + <td>0.28.0 + <td>≥ 3.11 (3.14 Python) + <td>60 + <td>90 + <tr> + <td>0.27.0 + <td>≥ 3.11 (3.14 Python) + <td>60 + <td>90 + <tr> + <td>0.26.0 + <td>≥ 3.11 (3.14 Python) + <td>60 + <td>90 + <tr> + <td>0.25.0 + <td>≥ 3.11 (3.14 Python) + <td>57 + <td>90 + <tr> + <td>0.24.0 + <td>≥ 3.11 (3.14 Python) + <td>57 + <td>79 + <tr> + <td>0.23.0 + <td>≥ 3.11 (3.14 Python) + <td>57 + <td>79 + <tr> + <td>0.22.0 + <td>≥ 3.11 (3.14 Python) + <td>57 + <td>79 + <tr> + <td>0.21.0 + <td>≥ 3.11 (3.14 Python) + <td>57 + <td>79 + <tr> + <td>0.20.1 + <td>≥ 3.5 + <td>55 + <td>62 + <tr> + <td>0.20.0 + <td>≥ 3.5 + <td>55 + <td>62 + <tr> + <td>0.19.1 + <td>≥ 3.5 + <td>55 + <td>62 + <tr> + <td>0.19.0 + <td>≥ 3.5 + <td>55 + <td>62 + <tr> + <td>0.18.0 + <td>≥ 3.4 + <td>53 + <td>62 + <tr> + <td>0.17.0 + <td>≥ 3.4 + <td>52 + <td>62 +</table> + +## Clients + +[Selenium] users must update to version 3.11 or later to use geckodriver. +Other clients that follow the [W3C WebDriver specification][WebDriver] +are also supported. + +## Firefoxen + +geckodriver is not yet feature complete. This means that it does +not yet offer full conformance with the [WebDriver] standard +or complete compatibility with [Selenium]. You can track the +[implementation status] of the latest [Firefox Nightly] on MDN. +We also keep track of known [Selenium], [remote protocol], and +[specification] problems in our [issue tracker]. + +Support is best in Firefox 57 and greater, although generally the more +recent the Firefox version, the better the experience as they have +more bug fixes and features. Some features will only be available +in the most recent Firefox versions, and we strongly advise using the +latest [Firefox Nightly] with geckodriver. Since Windows XP support +in Firefox was dropped with Firefox 53, we do not support this platform. + +## Android + +Starting with the 0.26.0 release geckodriver is able to connect +to Android devices, and to control packages which are based on [GeckoView] +(eg. [Firefox Preview] aka Fenix, or [Firefox Reality]). But it also still +supports versions of Fennec up to 68 ESR, which is the last officially +supported release from Mozilla. + +To run tests on Android specific capabilities under `moz:firefoxOptions` +have to be set when requesting a new session. See the Android section under +[Firefox Capabilities](Capabilities.md#android) for more details. + +[geckodriver releases]: https://github.com/mozilla/geckodriver/releases +[Selenium]: https://github.com/seleniumhq/selenium +[WebDriver]: https://w3c.github.io/webdriver/ +[implementation status]: https://bugzilla.mozilla.org/showdependencytree.cgi?id=721859&hide_resolved=1 +[remote protocol]: https://github.com/mozilla/geckodriver/issues?q=is%3Aissue+is%3Aopen+label%3Amarionette +[specification]: https://github.com/mozilla/geckodriver/issues?q=is%3Aissue+is%3Aopen+label%3Aspec +[issue tracker]: https://github.com/mozilla/geckodriver/issues +[Firefox Nightly]: https://nightly.mozilla.org/ +[GeckoView]: https://wiki.mozilla.org/Mobile/GeckoView +[Firefox Preview]: https://play.google.com/store/apps/details?id=org.mozilla.fenix +[Firefox Reality]: https://play.google.com/store/apps/details?id=org.mozilla.vrbrowser diff --git a/testing/geckodriver/doc/Testing.md b/testing/geckodriver/doc/Testing.md new file mode 100644 index 0000000000..2f8f5c9ef6 --- /dev/null +++ b/testing/geckodriver/doc/Testing.md @@ -0,0 +1,69 @@ +# Testing geckodriver + +We verify and test geckodriver in a couple of different ways. +Since it is an implementation of the WebDriver web standard, we share +a set of conformance tests with other browser vendors through the +[Web Platform Tests] (WPT) initiative. This lets us ensure web +compatibility between _different_ WebDriver implementations for +different browsers. + +In addition to the WPT tests, geckodriver and webdriver have +unit tests. These are written in Rust, but you must explicitly +tell mach to build these by adding the following line to your [mozconfig]: + +```make +ac_add_options --enable-rust-tests +``` + +Tests can then be run by using the `test` sub command for [cargo] in the +specific source folder: + +```shell +% cd testing/geckodriver/src +% cargo test +``` + +To run the more extensive WPT tests you can use mach, but first +make sure you have built Firefox: + +```shell +% ./mach build +% ./mach wpt testing/web-platform/tests/webdriver +``` + +As these are functional integration tests and pop up Firefox windows +sporadically, a helpful tip is to suppress the window whilst you +are running them by using Firefox’ [headless mode]: + +```shell +% ./mach wpt --headless testing/web-platform/tests/webdriver +``` + +The `--headless` flag is equivalent to setting the `MOZ_HEADLESS` +output variable. In addition to `MOZ_HEADLESS` there is also +`MOZ_HEADLESS_WIDTH` and `MOZ_HEADLESS_HEIGHT` for controlling the +dimensions of the no-op virtual display. This is similar to using +Xvfb(1) which you may know from the X windowing system, but has +the additional benefit of also working on macOS and Windows. + +As you get in to development of geckodriver and Marionette you will +increasingly grow to understand our love for [trace-level logs]. +They provide us with the input—the HTTP requests—from the client +(in WPT’s case from the tests’ use of a custom WebDriver client), +the translation geckodriver makes to the [Marionette protocol], +the log output from Marionette, its responses back to geckodriver, +and finally the output—or the HTTP response—back to the client. + +The [trace-level logs] can be surfaced by passing on the `-vv` +flag to geckodriver through WPT: + +```shell +% ./mach wpt --webdriver-arg=-vv testing/web-platform/tests/webdriver +``` + +[Web Platform Tests]: http://web-platform-tests.org/ +[cargo]: http://doc.crates.io/guide.html +[headless mode]: https://developer.mozilla.org/en-US/Firefox/Headless_mode +[mozconfig]: https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/Build_Instructions/Configuring_Build_Options +[trace-level logs]: TraceLogs.md +[Marionette protocol]: /testing/marionette/Protocol.md diff --git a/testing/geckodriver/doc/TraceLogs.md b/testing/geckodriver/doc/TraceLogs.md new file mode 100644 index 0000000000..fb4e298c44 --- /dev/null +++ b/testing/geckodriver/doc/TraceLogs.md @@ -0,0 +1,206 @@ +# Enabling trace logs + +geckodriver provides different bands of logs for different audiences. +The most important log entries are shown to everyone by default, +and these include which port geckodriver provides the WebDriver +API on, as well as informative warnings, errors, and fatal exceptions. + +The different log bands are, in ascending bandwidth: + +1. `fatal` is reserved for exceptional circumstances when geckodriver + or Firefox cannot recover. This usually entails that either + one or both of the processes will exit. + +2. `error` messages are mistakes in the program code which it is + possible to recover from. + +3. `warn` shows warnings of more informative nature that are not + necessarily problems in geckodriver. This could for example happen + if you use the legacy `desiredCapabilities`/`requiredCapabilities` + objects instead of the new `alwaysMatch`/`firstMatch` structures. + +4. `info` (default) contains information about which port geckodriver + binds to, but also all messages from the lower-bandwidth levels + listed above. + +5. `config` additionally shows the negotiated capabilities after + matching the `alwaysMatch` capabilities with the sequence of + `firstMatch` capabilities. + +6. `debug` is reserved for information that is useful when programming. + +7. `trace`, where in addition to itself, all previous levels + are included. The trace level shows all HTTP requests received + by geckodriver, packets sent to and from the remote protocol in + Firefox, and responses sent back to your client. + +In other words this means that the configured level will coalesce +entries from all lower bands including itself. If you set the log +level to `error`, you will get log entries for both `fatal` and `error`. +Similarly for `trace`, you will get all the logs that are offered. + +To help debug a problem with geckodriver or Firefox, the trace-level +output is vital to understand what is going on. This is why we ask +that trace logs are included when filing bugs gainst geckodriver. +It is only under very special circumstances that a trace log is +not needed, so you will normally find that our first action when +triaging your issue will be to ask you to include one. Do yourself +and us a favour and provide a trace-level log right away. + +To silence geckodriver altogether you may for example either redirect +all output to append to some log files: + +```shell +% geckodriver >>geckodriver.log 2>>geckodriver.err.log +``` + +Or a black hole somewhere: + +```shell +% geckodriver >/dev/null 2>&1 +``` + +The log level set for geckodriver is propagated to the Marionette +logger in Firefox. Marionette is the remote protocol that geckodriver +uses to implement WebDriver. This means enabling trace logs for +geckodriver will also implicitly enable them for Marionette. + +The log level is set in different ways. Either by using the +`--log <LEVEL>` option, where `LEVEL` is one of the log levels +from the list above, or by using the `-v` (for debug) or `-vv` +(for trace) shorthands. For example, the following command will +enable trace logs for both geckodriver and Marionette: + +```shell +% geckodriver -vv +``` + +The second way of setting the log level is through capabilities. +geckodriver accepts a Mozilla-specific configuration object +in [`moz:firefoxOptions`]. This JSON Object, which is further +described in the [README] can hold Firefox-specific configuration, +such as which Firefox binary to use, additional preferences to set, +and of course which log level to use. + +[`moz:firefoxOptions`]: https://searchfox.org/mozilla-central/source/testing/geckodriver/README.md#firefox-capabilities +[README]: https://searchfox.org/mozilla-central/source/testing/geckodriver/README.md + +Each client has its own way of specifying capabilities, and some clients +include “helpers” for providing browser-specific configuration. +It is often advisable to use these helpers instead of encoding the +JSON Object yourself because it can be difficult to get the exact +details right, but if you choose to, it should look like this: + +```json +{"moz:firefoxOptions": {"log": {"level": "trace"}}} +``` + +Note that most known WebDriver clients, such as those provided by +the Selenium project, do not expose a way to actually _see_ the logs +unless you redirect the log output to a particular file (using the +method shown above) or let the client “inherit” geckodriver’s +output, for example by redirecting the stdout and stderr streams to +its own. The notable exceptions are the Python and Ruby bindings, +which surface geckodriver logs in a remarkable easy and efficient way. + +See the client-specific documentation below for the most idiomatic +way to enable trace logs in your language. We want to expand this +documentation to cover all the best known clients people use with +geckodriver. If you find your language missing, please consider +[submitting a patch]. + +[submitting a patch]: Patches.md + +## C-Sharp + +The Selenium [C# client] comes with a [`FirefoxOptions`] helper for +constructing the [`moz:firefoxOptions`] capabilities object: + +```csharp +FirefoxOptions options = new FirefoxOptions(); +options.LogLevel = FirefoxDriverLogLevel.Trace; +IWebDriver driver = new FirefoxDriver(options); +``` + +The log output is directed to stdout. + +[C# client]: https://seleniumhq.github.io/selenium/docs/api/dotnet/ +[`FirefoxOptions`]: https://seleniumhq.github.io/selenium/docs/api/dotnet/html/T_OpenQA_Selenium_Firefox_FirefoxOptions.htm + +## Java + +The Selenium [Java client] also comes with +a [`org.openqa.selenium.firefox.FirefoxOptions`] helper for +constructing the [`moz:firefoxOptions`] capabilities object: + +```java +FirefoxOptions options = new FirefoxOptions(); +options.setLogLevel(FirefoxDriverLogLevel.TRACE); +WebDriver driver = new FirefoxDriver(options); +``` + +The log output is directed to stdout. + +[Java client]: https://seleniumhq.github.io/selenium/docs/api/java/ +[`org.openqa.selenium.firefox.FirefoxOptions`]: https://seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/firefox/FirefoxOptions.html + +## Javascript (webdriver.io) + +With the Selenium [JavaScript client] the capabilities object can directly be +constructed: + +```javascript +import WebDriver from 'webdriver' + +const driver = await WebDriver.newSession({ + capabilities: { + browserName: 'firefox', + 'moz:firefoxOptions': { + log: { level: 'trace' }, + } + } +}) +``` + +The log output is directed to stdout, or if geckodriver runs as a wdio plugin +then the generated logs are part of the wdio log system. + +[JavaScript client]: https://webdriver.io/ + +## Python + +The Selenium [Python client] comes with a +[`selenium.webdriver.firefox.options.Options`] helper that can +be used programmatically to construct the [`moz:firefoxOptions`] +capabilities object: + +```python +from selenium.webdriver import Firefox +from selenium.webdriver.firefox.options import Options + +opts = Options() +opts.log.level = "trace" +driver = Firefox(options=opts) +``` + +The log output is stored in a file called _geckodriver.log_ in your +script’s current working directory. + +[Python client]: https://selenium-python.readthedocs.io/ +[`selenium.webdriver.firefox.options.Options`]: https://github.com/SeleniumHQ/selenium/blob/master/py/selenium/webdriver/firefox/options.py + +## Ruby + +The Selenium [Ruby client] comes with an [`Options`] helper to +generate the correct [`moz:firefoxOptions`] capabilities object: + +```ruby +Selenium::WebDriver.logger.level = :debug +opts = Selenium::WebDriver::Firefox::Options.new(log_level: :trace) +driver = Selenium::WebDriver.for :firefox, options: opts +``` + +The log output is directed to stdout. + +[Ruby client]: https://seleniumhq.github.io/selenium/docs/api/rb/ +[`Options`]: https://seleniumhq.github.io/selenium/docs/api/rb/Selenium/WebDriver/Firefox/Options.html diff --git a/testing/geckodriver/doc/Usage.md b/testing/geckodriver/doc/Usage.md new file mode 100644 index 0000000000..ee4ab86f8d --- /dev/null +++ b/testing/geckodriver/doc/Usage.md @@ -0,0 +1,143 @@ +# Usage + +geckodriver is an implementation of WebDriver, and WebDriver can +be used for widely different purposes. How you invoke geckodriver +largely depends on your use case. + +## Running Firefox in a container-based package + +When Firefox is packaged inside a container (e.g. [Snap], [Flatpak]), it may +see a different filesystem to the host. This can affect access to the generated +profile directory, which may result in a hang when starting Firefox. + +This is known to affect launching the default Firefox shipped with Ubuntu 22.04+. + +There are several workarounds available for this problem: + +- Do not use container-packaged Firefox builds with geckodriver. Instead +download a Firefox release from <https://download.mozilla.org/?product=firefox-latest&os=linux> +and a geckodriver release from <https://github.com/mozilla/geckodriver/releases>. + +- Use a geckodriver that runs in the same container filesystem as the Firefox +package. For example on Ubuntu `/snap/bin/geckodriver` will work with the +default Firefox. + +- Set the `--profile-root` command line option to write the profile to a +directory accessible to both Firefox and geckodriver, for example a non-hidden +directory under `$HOME`. + +[Flatpak]: https://flatpak.org/ +[Snap]: https://ubuntu.com/core/services/guide/snaps-intro + +## Selenium + +If you are using geckodriver through [Selenium], you must ensure that +you have version 3.11 or greater. Because geckodriver implements the +[W3C WebDriver standard][WebDriver] and not the same Selenium wire +protocol older drivers are using, you may experience incompatibilities +and migration problems when making the switch from FirefoxDriver to +geckodriver. + +Generally speaking, Selenium 3 enabled geckodriver as the default +WebDriver implementation for Firefox. With the release of Firefox 47, +FirefoxDriver had to be discontinued for its lack of support for the +[new multi-processing architecture in Gecko][e10s]. + +Selenium client bindings will pick up the _geckodriver_ binary executable +from your [system’s `PATH` environmental variable][PATH] unless you +override it by setting the `webdriver.gecko.driver` [Java VM system +property]: + +```java +System.setProperty("webdriver.gecko.driver", "/home/user/bin"); +``` + +Or by passing it as a flag to the [java(1)] launcher: + +```shell +% java -Dwebdriver.gecko.driver=/home/user/bin YourApplication +``` + +Your mileage with this approach may vary based on which programming +language bindings you are using. It is in any case generally the case +that geckodriver will be picked up if it is available on the system path. +In a bash compatible shell, you can make other programs aware of its +location by exporting or setting the `PATH` variable: + +```shell +% export PATH=$PATH:/home/user/bin +% whereis geckodriver +geckodriver: /home/user/bin/geckodriver +``` + +On Window systems you can change the system path by right-clicking **My +Computer** and choosing **Properties**. In the dialogue that appears, +navigate **Advanced** → **Environmental Variables** → **Path**. + +Or in the Windows console window: + +```shell +% set PATH=%PATH%;C:\bin\geckodriver +``` + +## Standalone + +Since geckodriver is a separate HTTP server that is a complete remote end +implementation of [WebDriver], it is possible to avoid using the Selenium +remote server if you have no requirements to distribute processes across +a matrix of systems. + +Given a W3C WebDriver conforming client library (or _local end_) you +may interact with the geckodriver HTTP server as if you were speaking +to any Selenium server. + +Using [curl(1)]: + +```shell +% geckodriver & +[1] 16010 +% 1491834109194 geckodriver INFO Listening on 127.0.0.1:4444 +% curl -H 'Content-Type: application/json' -d '{"capabilities": {"alwaysMatch": {"acceptInsecureCerts": true}}}' http://localhost:4444/session +{"value":{"sessionId":"d4605710-5a4e-4d64-a52a-778bb0c31e00","capabilities":{"acceptInsecureCerts":true,[...]}}} +% curl -H 'Content-Type: application/json' -d '{"url": "https://mozilla.org"}' http://localhost:4444/session/d4605710-5a4e-4d64-a52a-778bb0c31e00/url +{} +% curl http://localhost:4444/session/d4605710-5a4e-4d64-a52a-778bb0c31e00/url +{"value":"https://www.mozilla.org/en-US/" +% curl -X DELETE http://localhost:4444/session/d4605710-5a4e-4d64-a52a-778bb0c31e00 +{} +% fg +geckodriver +^C +``` + +Using the Python [wdclient] library: + +```python +import webdriver + +with webdriver.Session("127.0.0.1", 4444) as session: + session.url = "https://mozilla.org" + print "The current URL is %s" % session.url +``` + +And to run: + +```shell +% geckodriver & +[1] 16054 +% python example.py +1491835308354 geckodriver INFO Listening on 127.0.0.1:4444 +The current URL is https://www.mozilla.org/en-US/ +% fg +geckodriver +^C +``` + +[Selenium]: http://seleniumhq.org/ +[e10s]: https://developer.mozilla.org/en-US/Firefox/Multiprocess_Firefox +[PATH]: https://en.wikipedia.org/wiki/PATH_(variable) +[Java VM system property]: http://docs.oracle.com/javase/tutorial/essential/environment/sysprop.html +[java(1)]: http://www.manpagez.com/man/1/java/ +[WebDriver]: https://w3c.github.io/webdriver/ +[curl(1)]: http://www.manpagez.com/man/1/curl/ +[wdclient]: https://github.com/web-platform-tests/wpt/tree/master/tools/webdriver diff --git a/testing/geckodriver/doc/index.rst b/testing/geckodriver/doc/index.rst new file mode 100644 index 0000000000..863c05810c --- /dev/null +++ b/testing/geckodriver/doc/index.rst @@ -0,0 +1,55 @@ +=========== +geckodriver +=========== + +Proxy for using W3C WebDriver-compatible clients to interact with +Gecko-based browsers. + +This program provides the HTTP API described by the `WebDriver protocol`_. +to communicate with Gecko browsers, such as Firefox. It translates calls +into the :ref:`Firefox remote protocol <Protocol>` by acting as a proxy between the local- +and remote ends. + +You can consult the `change log`_ for a record of all notable changes +to the program. Releases_ are made available on GitHub. + +.. _WebDriver protocol: https://w3c.github.io/webdriver/#protocol +.. _change log: https://github.com/mozilla/geckodriver/releases +.. _Releases: https://github.com/mozilla/geckodriver/releases + + +.. toctree:: + :maxdepth: 1 + + Support.md + WebDriver capabilities <https://developer.mozilla.org/en-US/docs/Web/WebDriver/Capabilities> + Capabilities.md + Usage.md + Flags.md + Profiles.md + Bugs.md + TraceLogs.md + CrashReports.md + Notarization.md + + +For developers +============== +.. toctree:: + :maxdepth: 1 + + Building.md + Testing.md + Patches.md + Releasing.md + ARM.md + + +Communication +============= + +The mailing list for geckodriver discussion is +https://groups.google.com/a/mozilla.org/g/dev-webdriver. + +If you prefer real-time chat, ask your questions +on `#webdriver:mozilla.org <https://chat.mozilla.org/#/room/#webdriver:mozilla.org>`__. |