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

misc: replace marionette-client with geckodriver as b2g marionette client is no longer supported #30250

Merged
merged 18 commits into from
Sep 30, 2024

Conversation

AtofStryker
Copy link
Contributor

@AtofStryker AtofStryker commented Sep 17, 2024

Additional details

As a precursor to supporting WebDriver BiDi, Cypress needs to replace the older marionette-client with geckodriver. This is the current recommendation from the Mozilla team as marionette-client is no longer supported (see Cypress migration bugzilla ticket).

Currently, the responsibilities of the current geckodriver implementation and the older marionette-client:

This is outlined in the added README in this PR as well as some other useful information. This information will be updated as we implement BiDi.

NOTE: right now, the WebDriver Classic methods are implementing the spec through HTTP instead of using a package or a client. This was chosen to keep the package change minimal in this PR and we will likely be moving to some type of client to reduce the overhead needed to maintain WebDriver. This will be either an OSS package like webdriverio/webdriver or we implement our own (work for either scoped to #30219)

It is worth noting that we patch the geckodriver package to coincide with our debug logs in order to not print extraneous messages to the console that could disrupt end user experience as well as impact our system tests. We also need to patch top-level awaits to correctly build the app and feed in process args that are needed (such as the MOZ_ prefix variables) when spawning firefox.

To consume GeckoDriver, this code installs the geckodriver package, a lightweight wrapper around the geckodriver binary, to connect to the Firefox browser. geckodriver will be downloaded automatically to the user's tmp directory if not already downloaded, and will be started and managed by the Cypress server.

Bugfixes found while testing

  • Windows machines not killing the Firefox browser process when user triggers SIGINT from ctrl+c in the terminal (fixed in 192204d)
  • Browser no longer maximized in headed mode by default since xulstore.json no longer has the same effect since geckodriver is creating a full profile (fixed in ae36a24). this will only take effect when headed and if the user does NOT supply a width or height to the browser

Steps to test

Unit tests have been updated to reflect the replaced client, as well as tests added for our geckodriver wrapper.

The system-tests and integration tests serve as a regression suite to help guarantee this change works.

Manual testing should also be completed on linux, mac, and windows in open/run mode permutations to verify the code and client changes work universally. The app team will be participating in a small bughunt to identify issues we may have not already found.

How has the user experience changed?

Ideally, this change should NOT impact the end user. This is an internal swap of a client used to automate the browser and should not affect the end user in any way.

PR Tasks

  • Have tests been added/updated?
  • Has a PR for user-facing changes been opened in cypress-documentation?
  • Have API changes been updated in the type definitions?
  • is the bughunt completed?
  • are the v8 snapshots up to date?

@AtofStryker AtofStryker force-pushed the misc/remove_marionette_for_geckodriver branch 2 times, most recently from 161ebbf to 7a1dc85 Compare September 17, 2024 23:05
@AtofStryker AtofStryker self-assigned this Sep 17, 2024
Copy link

cypress bot commented Sep 17, 2024

cypress    Run #57409

Run Properties:  status check failed Failed #57409  •  git commit 721100a489: address comments from code review
Project cypress
Branch Review misc/remove_marionette_for_geckodriver
Run status status check failed Failed #57409
Run duration 15m 55s
Commit git commit 721100a489: address comments from code review
Committer AtofStryker
View all properties for this run ↗︎

Test results
Tests that failed  Failures 17
Tests that were flaky  Flaky 1
Tests that did not run due to a developer annotating a test with .skip  Pending 12
Tests that did not run due to a failure in a mocha hook  Skipped 0
Tests that passed  Passing 474
View all changes introduced in this branch ↗︎

Warning

Partial Report: The results for the Application Quality reports may be incomplete.

UI Coverage  54.41%
  Untested elements 29  
  Tested elements 37  
Accessibility  96.09%
  Failed rules  0 critical   7 serious   3 moderate   0 minor
  Failed elements 190  

Tests for review

Failed  cypress\e2e\runner\reporter-ct-vite.errors.cy.ts • 17 failed tests • app-e2e

View Output

Test Artifacts
Vite - errors ui > assertion failures Test Replay Screenshots
Vite - errors ui > assertion failures - no preferred IDE Test Replay Screenshots
Vite - errors ui > hooks Test Replay Screenshots
Vite - errors ui > commands Test Replay Screenshots
Vite - errors ui > cy.then Test Replay Screenshots
Vite - errors ui > cy.should Test Replay Screenshots
Vite - errors ui > cy.each Test Replay Screenshots
Vite - errors ui > cy.spread Test Replay Screenshots
Vite - errors ui > cy.within Test Replay Screenshots
Vite - errors ui > cy.wrap Test Replay Screenshots
The first 10 failed tests are shown, see all 17 tests in Cypress Cloud.
Failed  cypress\e2e\cypress-in-cypress.cy.ts • 0 failed tests • app-e2e

View Output

Test Artifacts
Failed  cypress\e2e\runner\reporter.command_errors.cy.ts • 0 failed tests • app-e2e

View Output

Test Artifacts
Failed  cypress\e2e\settings.cy.ts • 0 failed tests • app-e2e

View Output

Test Artifacts
Failed  cypress\e2e\cypress-in-cypress-e2e.cy.ts • 0 failed tests • app-e2e

View Output

Test Artifacts

The first 5 failed specs are shown, see all 48 specs in Cypress Cloud.

Flakiness  cypress\e2e\scaffold-component-testing.cy.ts • 1 flaky test • launchpad-e2e

View Output

Test Artifacts
scaffolding component testing > react-vite-ts-unconfigured > scaffolds component testing for React and Vite Test Replay Screenshots

@AtofStryker AtofStryker force-pushed the misc/remove_marionette_for_geckodriver branch 20 times, most recently from cac7939 to 192204d Compare September 25, 2024 00:52
@AtofStryker AtofStryker requested review from ryanthemanuel and cacieprins and removed request for ryanthemanuel and cacieprins September 25, 2024 20:34
@AtofStryker AtofStryker force-pushed the misc/remove_marionette_for_geckodriver branch from 3488c1c to fb54eaa Compare September 26, 2024 22:11
Copy link

@whimboo whimboo left a comment

Choose a reason for hiding this comment

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

Hi @AtofStryker. It's great to see the progress you've made over the past days. I hope it's fine when I just added a couple of minor comments and suggestions. You can find those all inline. I'm kinda looking forward to see it working, and especially the removal of the Marionette JS client usage.

packages/launcher/lib/browsers.ts Outdated Show resolved Hide resolved
MOZ_HEADLESS_WIDTH: '1280',
MOZ_HEADLESS_HEIGHT: '721',
MOZ_HEADLESS_HEIGHT: '806',
Copy link

Choose a reason for hiding this comment

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

Above you mention a total offset of 86px but this change is 85px only. Not sure if that matters but wanted to just mention.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's 85 plus whatever the height for the shrunken url bar, which is the 1 px already aded to the 721 here

host: '127.0.0.1',
port: geckoDriverPort,
marionetteHost: '127.0.0.1',
marionettePort,
Copy link

Choose a reason for hiding this comment

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

I assume this can be defined by the user? Please note that if set to 0 Firefox will automatically select a free port on the system.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

we define this on their behalf. We just find an available port on the machine to run it

packages/server/lib/browsers/geckodriver/README.md Outdated Show resolved Hide resolved
## Debugging

To help debug `geckodriver` and `firefox`, the `DEBUG=cypress-verbose:server:browsers:geckodriver` can be used when launching `cypress`. This will
* Enable full `stdout` and `stderr` for `geckodriver` (including startup time) and the `firefox` process. The logs will **NOT** be truncated so they may get quite long.
Copy link

Choose a reason for hiding this comment

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

Please note that geckodriver also accepts a -vv argument which will enable trace level logs for Firefox as well. This is pretty helpful in case you see some broken behavior or misbehavior by our implementation which needs to be investigated.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

does this have the same effect as setting --log=trace?

Copy link

Choose a reason for hiding this comment

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

Yes, one provides a string while for easier use we added the -v[v] argument.

await Bluebird.resolve(waitPort({
port: opts.port,
// add 1 second to the timeout so the timeout throws first if the limit is reached
timeout: timeout + 1000,
Copy link

Choose a reason for hiding this comment

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

I assume this is waiting for a connection? Geckodriver itself waits up to 60s internally after Firefox is launched for the socket to Marionette and then fails & kills the browser process. Not sure if that would help you if you have a shorter timeout. There is no command line argument for that yet.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

correct. This is just waiting for geckodriver to be running before we proceed. If we reach the timeout threshold, we will the process if once exists, which ultimately just results in the app process tree being killed

Copy link

Choose a reason for hiding this comment

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

Just to be sure it's waiting for geckodriver running and allowing connections on its HTTP port, right? Thanks.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes that is correct to the best of my knowledge. wait-port should wait for the http endpoint on the port to response as well as the record to be available in the DNS.

Copy link

Choose a reason for hiding this comment

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

Thanks.

@AtofStryker
Copy link
Contributor Author

Hi @AtofStryker. It's great to see the progress you've made over the past days. I hope it's fine when I just added a couple of minor comments and suggestions. You can find those all inline. I'm kinda looking forward to see it working, and especially the removal of the Marionette JS client usage.

Thank you for the review @whimboo! Once we get this in, I should have more updates to post on the bugzilla thread as far as progress / next steps.

Copy link

@whimboo whimboo left a comment

Choose a reason for hiding this comment

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

As an outsider who doesn't know the code I cannot give a real code review, but the changes look fine to me from the geckodriver usage perspective.

Thanks again for working on it!

// For whatever reason, we NEED to bind to stderr/stdout in order
// for the geckodriver process not to hang, even though the event effectively
// isn't doing anything without debug logs enabled.
geckoDriverChildProcess.stdout?.on('data', (buf) => {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@whimboo do you have any idea why the above comment would happen? @mschile and I tried gating the stdout/stderr behind an if statement and it looks to cause the process to almost freeze (is still running but appears stuck). We tested this on Firefox 125/130 with geckodriver 0.35.0. Is it possible the driver is timing out or something like that?

Copy link

Choose a reason for hiding this comment

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

No I don't know why that happens. If you may have the time and could create a minimal stand-alone testcase to reproduce this behavior it would be great. We haven't heard about it yet.

One thing which could happen is if a pipe was setup for stdout/stderr but nothing is read from it. That means that geckodriver will run into an overflow slowing down massively first. We had something similar in the past for Puppeteer when logging was enabled but the pipe was not read. It was fixed via puppeteer/puppeteer#7644.

@cypress-bot
Copy link
Contributor

cypress-bot bot commented Oct 24, 2024

Released in 13.15.1.

This comment thread has been locked. If you are still experiencing this issue after upgrading to
Cypress v13.15.1, please open a new issue.

@cypress-bot cypress-bot bot locked as resolved and limited conversation to collaborators Oct 24, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

misc: Remove Firefox marionette-client in favor of Geckodriver
6 participants