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

feat: Add support for optional env key to browser launch options #23624

Merged
merged 12 commits into from
Sep 22, 2022

Conversation

ryanjduffy
Copy link
Contributor

@ryanjduffy ryanjduffy commented Aug 30, 2022

User facing changelog

n/a

Additional details

Related PR: #22250

In building out support to integrate replay with cypress, I discovered there isn't a way to set environment variables for the browser without putting the onus on the end user. Further, since the browser launch seems to happen in a different process than the plugin, I couldn't inject those values into process.env and have them picked up by the existing logic.

This adds support for an optional env key on the launch options passed to before:browser:launch which is then merged with the defaultBrowserEnv and process.env. I placed it between those two so the default browser family config (defaultBrowserEnv) would be overwritten by browser instance config (browser.env) which would be overwritten by the current process.env.

Steps to test

  • Create a new cypress project
  • Add a before:browser:launch handler in setupNodeEvents to add an env variable
  • Verify that the browser receives that env variable. I added a debug entry to log the environment which is probably sufficient for testing this change.

How has the user experience changed?

PR Tasks

@cypress-bot
Copy link
Contributor

cypress-bot bot commented Aug 30, 2022

Thanks for taking the time to open a PR!

@ryanjduffy
Copy link
Contributor Author

@emilyrohrbough - Finally got back to this! Let me know what y'all think when you get to it. It'll go a long way to improve the DX for replay.io users integrating with cypress.io!

@emilyrohrbough
Copy link
Member

@ryanjduffy Thank you so much! I will add this to my list to review and get back to you shortly. Hopefully by end of day today, if not by EOD tomorrow!

@@ -181,7 +182,9 @@ export function launch (

// allow setting default env vars such as MOZ_HEADLESS_WIDTH
// but only if it's not already set by the environment
const env = Object.assign({}, defaultBrowserEnv, process.env)
const env = Object.assign({}, defaultBrowserEnv, browser.env, launchOptionsEnv, process.env)
Copy link
Member

@emilyrohrbough emilyrohrbough Sep 1, 2022

Choose a reason for hiding this comment

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

@ryanjduffy It looks like this change is doing more than accepting env values form the launchOptions. I wouldn't expect envs set on the found browser to be used in the node process that starts the browser. In the previous PR you had opened, you had linked to a few code snipped in reply & you're plugin. Where are these ENV values actually getting applied on the browser obj?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not sure I follow but I'll share some context here in hopes that clarifies!

Here's the current code in our plugin. It's of course not setting env variables yet because it can't!

https://github.com/replayio/replay-cli/blob/c90c03f08d9ccfcb9bc9a4a6a7c07246ff1b07f5/packages/cypress/src/index.ts#L11-L14

The eventual implementation after this landed would be:

  on("before:browser:launch", (browser, launchOptions) => {
    selectedBrowser = browser.family;
    reporter.onTestSuiteBegin(undefined, "CYPRESS_REPLAY_METADATA");

    launchOptions.env = {
      RECORD_ALL_CONTENT: 1,
      RECORD_REPLAY_METADATA_FILE: '/path/to/file.json'
    };

    return launchOptions;
  });

The goal here being that we need to configure the replay browser with RECORD_ALL_CONTENT to instruct the firefox fork to record everything (unlike the desktop experience in which the user clicks the Rec button) and where to find metadata for the recording which is how we link up the recording with the test result.

This is all happening from the plugin because that's the point at which we have the test context to add the metadata. IIRC, I also didn't find another way to set an environment variables for the launcher node process beyond requiring the user to set them before invoking cypress.

Hope that helps! Happy to have a quick video call to chat if that's useful too.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Also, i'm in the cypress community discord as ryanjduffy if you want to chat there!

Copy link
Member

Choose a reason for hiding this comment

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

@ryanjduffy This is great insights! Thank you!

Copy link
Contributor

@lmiller1990 lmiller1990 Sep 8, 2022

Choose a reason for hiding this comment

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

Explanation makes sense for why we pass launchOptionsEnv (which will contain the REPLAY_ variables) but why did we add browser.env here, too?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Looks like browsers.env was just cruft from my prior impl. @emilyrohrbough 's suggestions to drop those two diffs should do the trick!

Copy link
Contributor

@lmiller1990 lmiller1990 left a comment

Choose a reason for hiding this comment

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

Is there a good way to test this manually? Eg - should we set up Replay locally? Considering this is a new feature, after all, I think we probably should do some testing on our end before we review + merge it.

@ryanjduffy ryanjduffy force-pushed the add-browser-env branch 3 times, most recently from a29d202 to 7b637df Compare September 8, 2022 19:16
@ryanjduffy
Copy link
Contributor Author

Force pushed a fresh commit to rebase on develop and match up code style.

@ryanjduffy
Copy link
Contributor Author

Is there a good way to test this manually? Eg - should we set up Replay locally? Considering this is a new feature, after all, I think we probably should do some testing on our end before we review + merge it.

Definitely! I'm walking through the steps myself now to verify it all one more time. Our Cypress instructions cover most of it. I can push an experimental version of our plugin that uses this feature so others can try it as well.

@ryanjduffy
Copy link
Contributor Author

Manual testing steps:

  1. Clone replayio/replayable and checkout demo-cypress-env. You could also follow the instructions and set up your own project for extra credit
    git clone git@github.com:replayio/replayable && cd replayable && git checkout demo-cypress-env && npm i && npm run dev
    
  2. From cypress, checkout this branch
    git fetch upstream +refs/pull/23624/merge && git checkout -qf FETCH_HEAD
    
  3. Run cypress in dev mode against the replayable repo
    yarn cypress:run --project /path/to/replayable --browser "Replay Firefox"
    
  4. Verify Replay made local recordings. There should be three entries.
    npx @replayio/replay ls
    

Copy link
Contributor

@flotwig flotwig left a comment

Choose a reason for hiding this comment

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

@@ -166,6 +166,7 @@ export function launch (
debuggingPort: number,
args: string[] = [],
defaultBrowserEnv = {},
launchOptionsEnv = {},
Copy link
Contributor

Choose a reason for hiding this comment

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

This is too many parameters for this function, can you either remove the need for this parameter or move the parameters for .launch into an options object?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍 I'll collapse the two env members into one.

@@ -5480,6 +5480,7 @@ declare namespace Cypress {
extensions: string[]
preferences: { [key: string]: any }
args: string[]
env: { [key: string]: any }
Copy link
Contributor

Choose a reason for hiding this comment

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

This is essentially a no-op in Electron, should we add an error or warning if someone sets .env with Electron?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍 I noticed that args seems to be the same so I've added a warning for both of those. Let me know if I've misread and args is used or if there's a different way that is preferred for warning.

@ryanjduffy
Copy link
Contributor Author

This needs a docs PR, this file should be edited: https://github.com/cypress-io/cypress-documentation/blob/master/content/api/plugins/browser-launch-api.md

Opened cypress-io/cypress-documentation#4723

@lmiller1990
Copy link
Contributor

@ryanjduffy works great for me, I followed the steps and got it:

ID                                    Status  Title                          Created At
790783cd-f2c1-4c02-891c-fef7e2223767  onDisk  cypress/e2e/view-issues.cy.js  2022-09-11T23:15:34.279Z
054c8d69-fb1b-4429-a9da-6de10c48d738  onDisk  cypress/e2e/navigation.cy.js   2022-09-11T23:15:27.215Z
0943eec6-b68f-440b-86c1-341e161c7b76  onDisk  Replay of localhost:3000       2022-09-11T23:15:11.757Z

Left a quick comment on the docs PR, I'll wait for @flotwig to loop back and approve this PR, but looks good to me.

Copy link
Contributor

@lmiller1990 lmiller1990 left a comment

Choose a reason for hiding this comment

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

Sorry for the delay, one last question!

if (launchOptions.args.length > 0) options.push('args')

if (options.length > 0) {
errors.warning('BROWSER_UNSUPPORTED_LAUNCH_OPTION', 'electron', options)
Copy link
Contributor

Choose a reason for hiding this comment

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

@ryanjduffy sorry last comment here before approval... how can I actually pass something to this? I want to verify this error actually shows up, but I couldn't figure out how.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Something like this should do it!

      on("before:browser:launch", (browser, launchOptions) => {
        launchOptions.env = {
          DEBUG: "whatever",
        };

        return launchOptions;
      });

image

Copy link
Contributor

@ZachJW34 ZachJW34 left a comment

Choose a reason for hiding this comment

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

Changes look good! I reran CI and we have a few build failures, lmk if you need help fixing those up. A few are snapshot related, but we did recently add webkit support so looks like we need to make some tweaks there.

@ryanjduffy
Copy link
Contributor Author

Changes look good! I reran CI and we have a few build failures, lmk if you need help fixing those up. A few are snapshot related, but we did recently add webkit support so looks like we need to make some tweaks there.

Looks like it. Fixing up now

Copy link
Contributor

@lmiller1990 lmiller1990 left a comment

Choose a reason for hiding this comment

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

Pushed a commit ensuring the warning shows up correctly 👍

62ad6d3

@lmiller1990
Copy link
Contributor

Seems I broke something when I pushed a commit, reverting + fixing...

@flotwig
Copy link
Contributor

flotwig commented Sep 21, 2022

Looks like the deprecated_spec snapshot needs to be updated, then this should be good to go:

cd system-tests
SNAPSHOT_UPDATE=1 yarn test deprecated_spec --browser electron

should do the trick.

@lmiller1990
Copy link
Contributor

Looks like a few more needed updating, I ran + pushed. 🤞

@ZachJW34
Copy link
Contributor

Looks like we need to tweak one more system-test using non-deprecated API - no warning. The snapshot needs to be browser specific, since args is not supported for Electron the snapshot will differ. Looks like the pattern is to add:

onRun: (exec, browser) => {
  if (browser === 'electron') {
    return exec({ originalTitle: `deprecated before:browser:launch args / using non-deprecated API - no warning - [electron]` })
  }

  return exec({ originalTitle: `deprecated before:browser:launch args / using non-deprecated API - no warning - [firefox,chromium]` })
},

I'd push but my local is a bit borked. Could you add those changes and run cd system-tests && SNAPSHOT_UPDATE=1 yarn test deprecated_spec

@ZachJW34
Copy link
Contributor

LGTM!

@ZachJW34 ZachJW34 merged commit acc1050 into cypress-io:develop Sep 22, 2022
@ryanjduffy ryanjduffy deleted the add-browser-env branch September 22, 2022 22:37
@cypress-bot
Copy link
Contributor

cypress-bot bot commented Sep 27, 2022

Released in 10.9.0.

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

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

Successfully merging this pull request may close these issues.

5 participants