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

ci(travis): run cypress e2e tests on build #5431

Merged
merged 5 commits into from
Apr 21, 2020
Merged

Conversation

IanLondon
Copy link
Contributor

@IanLondon IanLondon commented Apr 14, 2020

overview

Run cypress tests in Travis! Build will fail if any e2e tests fail. Closes #5318

This is dependent on #5424 - after it is merged, I'll rebase this PR and change if (global.Cypress) in that PR to if (process.env.CYPRESS === '1').

changelog

review requests

Sanity check!

  • One weird thing I encountered was that labware library tests failed in Travis because GTM_ID env var was set, which somehow caused an error to be thrown about Intercom being undefined. So I set GTM_ID='' and also just to be safe I cut out the GTM tag from the Handlebars HTML template if GTM_ID is falsey.
  • I'm using wait-until to make sure that the dev server is running before trying to start Cypress
  • Cypress by default saves videos. I don't think they're useful to us, so I turned them off. We can always enable them and upload them to S3 if we decide that's good, but otherwise it just slows down the build.
  • I didn't add any Make commands for running Cypress while you're writing tests. I kind of don't want to, I'd rather do cd protocol-designer; yarn cypress open (whatever args) rather than going thru Make.

risk assessment

Significant risk to our workflow, but easy to roll back. If this causes builds to fail intermittently, or go too slowly, we'll have to change it back. Worst case scenario is removing make test-e2e from Travis yml to stop running the tests until we fix whatever problem we might have.

@codecov
Copy link

codecov bot commented Apr 14, 2020

Codecov Report

Merging #5431 into edge will not change coverage.
The diff coverage is 100.00%.

Impacted file tree graph

@@           Coverage Diff           @@
##             edge    #5431   +/-   ##
=======================================
  Coverage   65.64%   65.64%           
=======================================
  Files        1084     1084           
  Lines       30905    30905           
=======================================
  Hits        20287    20287           
  Misses      10618    10618           
Impacted Files Coverage Δ
...designer/src/components/FileSidebar/FileSidebar.js 77.77% <100.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update b45af1e...42a5716. Read the comment docs.

@@ -43,7 +43,7 @@ const saveFile = (downloadData: $PropertyType<Props, 'downloadData'>) => {
const blob = new Blob([JSON.stringify(downloadData.fileData)], {
type: 'application/json',
})
if (global.Cypress) {
if (process.env.CYPRESS === '1') {
Copy link
Contributor

Choose a reason for hiding this comment

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

This will also have to be changed to an env var in your other PR #5424, right?

@mcous mcous added the robot-svcs Falls under the purview of the Robot Services squad (formerly CPX, Core Platform Experience). label Apr 15, 2020
Copy link
Contributor

@mcous mcous left a comment

Choose a reason for hiding this comment

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

If possible, I would love these e2e tests to be parallel rather than balloon out the existing JS test job

.travis.yml Outdated
@@ -84,13 +84,14 @@ jobs:

# test, build, and upload for JavaScript projects
- stage: test
name: 'JS unit tests; build Protocol Designer, Labware Library, Components Library'
name: 'JS unit & E2E tests; build Protocol Designer, Labware Library, Components Library'
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it's a better idea to put E2E tests in their own parallel job in the test stage rather than blowing this job out even further.

If the reason it was placed in this stage was to prevent deploy of PD if the e2e tests don't pass, then I have two thoughts while we're still on Travis:

  1. We could move PD deploy to a job in the "deploy" stage
    • This gates PD deploy on API tests passing
  2. We could continue to put PD artifacts in S3 regardless of what the e2e tests say
    • PD "deploy" uploads artifacts in S3; it does not actually deploy anything
    • I don't think preventing artifact uploads on e2e failures is necessarily worth the effort (not that it's a bad idea or anything)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

don't think preventing artifact uploads on e2e failures is necessarily worth the effort (not that it's a bad idea or anything)

👍

"$(MAKE) dev" \
"cypress run --browser chrome"
concurrently --no-color --kill-others --success first --names "labware-library-server,labware-library-tests" \
"$(MAKE) dev CYPRESS=1 GTM_ID=''" \
Copy link
Contributor

Choose a reason for hiding this comment

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

Why are we defining a new environment variable? We already have NODE_ENV=test, I feel like it might be a little more straightforward to do NODE_ENV=cypress or e2e or something similar

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 looks like we only ever set NODE_ENV to 'production' or 'development', I don't see test?

I was worried that since we're just using 2 states of NODE_ENV, we'd find places in our code with an assumption "if NODE_ENV isn't production then it must be development". But now going through uses of NODE_ENV the only time I see something like that is const DEV_MODE = process.env.NODE_ENV !== 'production' in app-shell which isn't going to cause an issue.

However, it's easy to do if (NODE_ENV === 'development ) {/* dev stuff */} else {/* prod stuff, but oops this also happens when NODE_ENV is cypress */} and IMO this is more complicated to think about than using a new env var.

Also any use of process.env.CYPRESS env var in the app code is an easy-to-search-for indicator that we had to do something gross to get Cypress to do something that it's not able to do, like looking at saved files

Copy link
Member

Choose a reason for hiding this comment

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

agree re:

easy-to-search-for indicator

But I think we should be in the habit of explicitly checking strings rather than relying on an else

Copy link
Contributor

Choose a reason for hiding this comment

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

It looks like we only ever set NODE_ENV to 'production' or 'development', I don't see test?

I don't much care, but since Jest sets NODE_ENV to test during testing, (see https://jestjs.io/docs/en/getting-started#using-babel; expand the "Making your Babel config jest-aware" section) I suggested NODE_ENV="cypress" to match that behavior. You can see our usage of this in our babel config:

  env: {
    // Note(isk: 3/2/20): Must have babel-plugin-styled-components in each env,
    // see here for further details: s https://styled-components.com/docs/tooling#babel-plugin
    production: {
      plugins: ['babel-plugin-styled-components', 'babel-plugin-unassert'],
    },
    development: {
      plugins: ['babel-plugin-styled-components', 'react-hot-loader/babel'],
    },
    test: {
      plugins: [
        'babel-plugin-styled-components',
        '@babel/plugin-transform-modules-commonjs',
        'babel-plugin-dynamic-import-node',
      ],
    },
  },

However, it's easy to do if (NODE_ENV === 'development' ) {/* dev stuff /} else {/ prod stuff, but oops this also happens when NODE_ENV is cypress */} and IMO this is more complicated to think about than using a new env var.

In my experience, checking for production environment should always be checking that the env was explicitly set to production to avoid this exact issue.

@@ -43,7 +43,7 @@ const saveFile = (downloadData: $PropertyType<Props, 'downloadData'>) => {
const blob = new Blob([JSON.stringify(downloadData.fileData)], {
type: 'application/json',
})
if (global.Cypress) {
if (process.env.CYPRESS === '1') {
// HACK(IL, 2020-04-02): can't figure out a better way to do this yet
Copy link
Contributor

Choose a reason for hiding this comment

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

Rather than polluting the application code here, could you replace fileSaver using webpack or babel if the environment doesn't support it? See eligrey/FileSaver.js#501

Also, the app attached the Redux store to the window if the NODE_ENV isn't production, but that doesn't feel like the problem here

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 will save fine under Cypress, but Cypress has no way to locate the file. Sometimes the test will timeout if a file is saved because depending on browser settings it might make a native "Save File..." modal that never closes, but that doesn't have to do with fileSaver

Copy link
Contributor

@mcous mcous Apr 21, 2020

Choose a reason for hiding this comment

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

Yeah to be clear, I'm not suggesting we change this global.__lastSavedFile__ = downloadData.fileData behavior during Cypress runs. I'm saying that this override should happen using a mock for FileSaver that webpack (using the resolve) config or babel (using babel-plugin-module-resolver) shims in when the environment is Cypress rather than putting the override logic in application code

Regardless, certainly not a request for this PR, sorry for not making clear in the original post

Copy link
Contributor

@dozercodes dozercodes left a comment

Choose a reason for hiding this comment

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

🌲

Copy link
Contributor

@Kadee80 Kadee80 left a comment

Choose a reason for hiding this comment

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

🌵

Copy link
Member

@shlokamin shlokamin left a comment

Choose a reason for hiding this comment

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

Good stuff @IanLondon!

"$(MAKE) dev" \
"cypress run --browser chrome"
concurrently --no-color --kill-others --success first --names "labware-library-server,labware-library-tests" \
"$(MAKE) dev CYPRESS=1 GTM_ID=''" \
Copy link
Member

Choose a reason for hiding this comment

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

agree re:

easy-to-search-for indicator

But I think we should be in the habit of explicitly checking strings rather than relying on an else

Copy link
Contributor

@mcous mcous left a comment

Choose a reason for hiding this comment

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

Posted some clarifications but this LGTM. Looking over the Travis run is making me more convinced we should switch to GH actions and get even more parallelization going on

.travis.yml Outdated
@@ -84,7 +84,7 @@ jobs:

# test, build, and upload for JavaScript projects
- stage: test
name: 'JS unit tests; build Protocol Designer, Labware Library, Components Library'
name: 'JS unit; build Protocol Designer, Labware Library, Components Library'
Copy link
Contributor

Choose a reason for hiding this comment

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

Unintentional removal of "tests"?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

d'oh

@@ -43,7 +43,7 @@ const saveFile = (downloadData: $PropertyType<Props, 'downloadData'>) => {
const blob = new Blob([JSON.stringify(downloadData.fileData)], {
type: 'application/json',
})
if (global.Cypress) {
if (process.env.CYPRESS === '1') {
// HACK(IL, 2020-04-02): can't figure out a better way to do this yet
Copy link
Contributor

@mcous mcous Apr 21, 2020

Choose a reason for hiding this comment

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

Yeah to be clear, I'm not suggesting we change this global.__lastSavedFile__ = downloadData.fileData behavior during Cypress runs. I'm saying that this override should happen using a mock for FileSaver that webpack (using the resolve) config or babel (using babel-plugin-module-resolver) shims in when the environment is Cypress rather than putting the override logic in application code

Regardless, certainly not a request for this PR, sorry for not making clear in the original post

@IanLondon IanLondon merged commit a31331d into edge Apr 21, 2020
@IanLondon IanLondon deleted the ci_add-cypress-to-travis branch April 21, 2020 19:08
IanLondon added a commit that referenced this pull request Apr 22, 2020
* run cypress tests in new Travis job
* labware-library: do not add GTM script when E2E testing
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
infrastructure ops/ CI/ repo etc robot-svcs Falls under the purview of the Robot Services squad (formerly CPX, Core Platform Experience).
Projects
None yet
Development

Successfully merging this pull request may close these issues.

CI: Run Cypress E2E tests in CI build
5 participants