Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

chore: enable cucumber, rewrite existing tests #513

Merged
merged 15 commits into from Oct 23, 2019
Merged

Conversation

Mohammer5
Copy link
Contributor

@Mohammer5 Mohammer5 commented Oct 16, 2019

This PR covers several topics

Cucumber

I've added the cypress-cucumber-preprocessor npm module.
This allows us to write .feature files in the cypress/integration folder.

I've set "nonGlobalStepDefinitions": true in the package.json to enable us to place the step definitions in folders with the same name as the .feature file

Rewrite existing tests

I've rewritten the previously existing tests for the AlertBar.
There are now two feature files in cypress/integration:

  • AlertBar/Autohiding.feature
    Step definitions in ``cypress/integration/AlertBar/Autohiding/`
  • AlertBar/ClearOnAction.feature
    Step definitions in ``cypress/integration/AlertBar/ClearOnAction/`

Add scripts

I've added 5 scripts to the package.json of which 2 are of importance to us:

  • cypress:open
  • cypress:run

These will both run the storybook and then cyrpress.
What to check here:
(When running yarn cypress:run, make sure your BROWSER env var contains the path to either chrome or chromium: BROWSER=$(which chrome) yarn cypress:run)

  1. Correct behavior
    • yarn cypress:open should simply open the cypress interface
    • yarn cypress:run should run the tests inside the terminal
      I've tested it on a different tty to ensure it's working properly because in ttys with a window manager, it still opens a real browser
    • When either of the two scripts are terminated or cypress:open process is terminated manually:
      There should be no running process of the storybook or cypress
    • cypress:run should exit with code 0 if all tests pass
  2. Error management
    • the storybook port is already in use
      The script should exit with code 1
    • the tests did not pass successfully
      The cypress:run script should exit with code 1

@Mohammer5 Mohammer5 requested review from varl and a team as code owners October 16, 2019 08:42
@netlify
Copy link

netlify bot commented Oct 16, 2019

Deploy preview for dhis2-ui-core ready!

Built with commit 4ad0a56

https://deploy-preview-513--dhis2-ui-core.netlify.com

@Mohammer5
Copy link
Contributor Author

Lacks docs and proper PR description.
Will add them for better understanding

Copy link
Contributor

@HendrikThePendric HendrikThePendric left a comment

Choose a reason for hiding this comment

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

I can't really comment on the quality of this setup, because I don't know much about Gherkin at all. I have some generic comments:

Some file have some complex looking logic in them, i.e. cypress/assets/unfetch.umd.js and possibly this is something we'd need to copy into every repo that uses Gherkin. Perhaps we can use some form of package to take care of this? Or perhaps keep all these scripts in a central location (@dhis2/cli or sth)?

I've tested the cypress:open and cypress:run commands. The open command works fine, but the run command failed consistently (I've tried the built in terminal, iTerm, and the VSCode integrated terminal and they all had the same problem, quite likely this all boils down to the same thing as the all just use bash). Here's the output:

henkbookpro:ui hendrik$ yarn cypress:run
yarn run v1.17.3
$ node scripts/cypress_run.js
$ STORYBOOK_INCLUDE_TESTING=1 yarn start --ci
$ yarn start-storybook --ci
$ start-storybook --port 5000 -s ./stories/info --ci
webpack built c3b580e33c67785ba278 in 5527ms
╭────────────────────────────────────────────────────╮
│                                                    │
│   Storybook 5.2.4 started                          │
│   6.44 s for manager and 6.06 s for preview        │
│                                                    │
│   Local:            http://localhost:5000/         │
│   On your network:  http://192.168.87.189:5000/    │
│                                                    │
╰────────────────────────────────────────────────────╯
$ NO_COLOR=1 cypress run -b $BROWSER --config video=false
Path must be a string. Received true
TypeError: Path must be a string. Received true
    at assertPath (path.js:28:11)
    at Object.basename (path.js:1395:5)
    at isValidPathToBrowser (/Users/hendrik/Library/Caches/Cypress/3.4.1/Cypress.app/Contents/Resources/app/packages/server/lib/browsers/index.js:52:17)
    at /Users/hendrik/Library/Caches/Cypress/3.4.1/Cypress.app/Contents/Resources/app/packages/server/lib/browsers/index.js:73:11
    at tryCatcher (/Users/hendrik/Library/Caches/Cypress/3.4.1/Cypress.app/Contents/Resources/app/packages/launcher/node_modules/bluebird/js/release/util.js:16:23)
    at Promise._settlePromiseFromHandler (/Users/hendrik/Library/Caches/Cypress/3.4.1/Cypress.app/Contents/Resources/app/packages/launcher/node_modules/bluebird/js/release/promise.js:512:31)
    at Promise._settlePromise (/Users/hendrik/Library/Caches/Cypress/3.4.1/Cypress.app/Contents/Resources/app/packages/launcher/node_modules/bluebird/js/release/promise.js:569:18)
    at Promise._settlePromise0 (/Users/hendrik/Library/Caches/Cypress/3.4.1/Cypress.app/Contents/Resources/app/packages/launcher/node_modules/bluebird/js/release/promise.js:614:10)
    at Promise._settlePromises (/Users/hendrik/Library/Caches/Cypress/3.4.1/Cypress.app/Contents/Resources/app/packages/launcher/node_modules/bluebird/js/release/promise.js:694:18)
    at _drainQueueStep (/Users/hendrik/Library/Caches/Cypress/3.4.1/Cypress.app/Contents/Resources/app/packages/launcher/node_modules/bluebird/js/release/async.js:138:12)
    at _drainQueue (/Users/hendrik/Library/Caches/Cypress/3.4.1/Cypress.app/Contents/Resources/app/packages/launcher/node_modules/bluebird/js/release/async.js:131:9)
    at Async._drainQueues (/Users/hendrik/Library/Caches/Cypress/3.4.1/Cypress.app/Contents/Resources/app/packages/launcher/node_modules/bluebird/js/release/async.js:147:5)
    at Immediate.Async.drainQueues (/Users/hendrik/Library/Caches/Cypress/3.4.1/Cypress.app/Contents/Resources/app/packages/launcher/node_modules/bluebird/js/release/async.js:17:14)
    at runCallback (timers.js:789:20)
    at tryOnImmediate (timers.js:751:5)
    at processImmediate [as _immediateCallback] (timers.js:722:5)

info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

@Mohammer5
Copy link
Contributor Author

Some file have some complex looking logic in them, i.e. cypress/assets/unfetch.umd.js and possibly this is something we'd need to copy into every repo that uses Gherkin. Perhaps we can use some form of package to take care of this? Or perhaps keep all these scripts in a central location (@dhis2/cli or sth)?

Unfetch is only temporarily needed until cypress supports hooking into fetch.
@amcgee and I will create a wrapper library that will take care of installing and setting up all of this in app platform apps (I've added a PR for setup script in @dhis2/cli but we both prefer an isolated library that will also mange the cypress and cucumber version)

@amcgee
Copy link
Member

amcgee commented Oct 17, 2019

@Mohammer5 why do we need unfetch here? I don't think ui-core components should be doing fetches?

In cypress tests for applications we should be able to simply delete window.fetch (I did this in maps app) and then rely on the app's polyfill to stub it back in, I think.... am I missing something here?

@Mohammer5
Copy link
Contributor Author

@Mohammer5 why do we need unfetch here? I don't think ui-core components should be doing fetches?

In cypress tests for applications we should be able to simply delete window.fetch (I did this in maps app)and then rely on the app's polyfill to stub it out, I think.... am I missing something here?

You're right, we don't need it in ui-core at all..
ui-widgets does need it though as there's no polyfill in the storybook (that's where I copied it from).

I'll remove it from this PR

@amcgee
Copy link
Member

amcgee commented Oct 17, 2019

Nice!

I think it also shouldn't be necessary in ui-widgets though right? Because the ui-widgets storybook uses a CustomDataProvider which intercepts all data requests, so they shouldn't turn into fetches either.

.eslintrc.js Outdated Show resolved Hide resolved
cypress.json Outdated Show resolved Hide resolved
@Mohammer5
Copy link
Contributor Author

Mohammer5 commented Oct 17, 2019

Nice!

I think it also shouldn't be necessary in ui-widgets though right? Because the ui-widgets storybook uses a CustomDataProvider which intercepts all data requests, so they shouldn't turn into fetches either.

I'm using that to test different scenarios, like checking what happens when there are messages and when there are no messages.
Alternatively we could add another scenario to the storybook instead if that's what should be preferred. I kinda liked the way how I was able to override certain responses though:

Setting the defaults
Overwriting the defaults

It works quite well with gherkin as well, as there'd be nothing to be done by the Given step definitions if it was done by the story already

@@ -0,0 +1,5 @@
{
Copy link
Member

Choose a reason for hiding this comment

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

Probably should remove this example fixture if we're not using it

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed

Copy link
Member

Choose a reason for hiding this comment

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

It looks like this file is still 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.

No idea what happened there.. It's gone now

Copy link
Contributor

@HendrikThePendric HendrikThePendric left a comment

Choose a reason for hiding this comment

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

Just to confirm, once I added a BROWSER env variable that pointed to my I was able to run cypress:run successfully.

Copy link
Member

@amcgee amcgee left a comment

Choose a reason for hiding this comment

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

Yay tests, good work @Mohammer5 !

I made some comments inline.

One question - what is the reasoning behind everything in scripts/cypress? It seems like this could mostly be achieved in the package.json scripts with concurrently and wait-on - see maps package.json and maps .travis.yml - we don't use concurrently there but I think we could/should instead of starting the background process (see usage in app-runtime and app-store.

I'm also not sure what cypress:ci is for, why isn't that just cypress:run?

@Mohammer5
Copy link
Contributor Author

Mohammer5 commented Oct 17, 2019

@amcgee Thanks for taking a look at this!

what is the reasoning behind everything in scripts/cypress

I've tried to use concurrently and wait-on. Unfortunately wait-on doesn't support waiting for a 200 response, so it'll continue earlier than when storybook is ready. (See "Goals")

The scripts also make sure that the script fails if the port used by both cypress and storybook is identical, it exits with 1 if the port is already in use. Storybook just starts with an incremented port if the specified one is already in use and there's no way to know about that except for analyzing the output.

I'm also not sure what cypress:ci is for, why isn't that just cypress:run?

cypress:ci is used internally by the script that's called from cypress:run:

  • cypress:run starts the ci process
  • cypress:ci is the process that expects the storybook to be available

I guess the naming is a bit odd here, I'd appreciate alternative names that are more descriptive!

@amcgee
Copy link
Member

amcgee commented Oct 17, 2019

I've tried to use concurrently and wait-on. Unfortunately wait-on doesn't support waiting for a 200 response, so it'll continue earlier than when storybook is ready. (See "Goals")

Do we need to wait for a 200 response or just a GET response? With webpack-dev-server this was solved by using wait-on http-get://...., but maybe storybook's server responds with non-200 to GET when it isn't ready? That would surprise me, but possible.

@Mohammer5
Copy link
Contributor Author

Do we need to wait for a 200 response or just a GET response? With webpack-dev-server this was solved by using wait-on http-get://...., but maybe storybook's server responds with non-200 to GET when it isn't ready? That would surprise me, but possible.

I haven't tried http-get protocol. Will do and see if that works

@amcgee
Copy link
Member

amcgee commented Oct 17, 2019

The scripts also make sure that the script fails if the port used by both cypress and storybook is identical, it exits with 1 if the port is already in use. Storybook just starts with an incremented port if the specified one is already in use and there's no way to know about that except for analyzing the output.

Just throwing out possibly-simpler solutions here, since I'm worried that adding a bunch of custom development scripts to a single repo (though I know we'll extract them into a wrapper lib eventually):

Could we use detect-port's CLI to either fail if the port isn't available or pass a random available port to Storybook and on to Cypress?

@amcgee
Copy link
Member

amcgee commented Oct 17, 2019

I haven't tried http-get protocol. Will do and see if that works

Found that after a lot of frustration and debugging with this same issue in maps, it's handy!

@Mohammer5
Copy link
Contributor Author

Thanks to @amcgee I was able to get rid of the scripts folder and do everything with concurrently and wait-on 👍.
Please review again!

@Mohammer5
Copy link
Contributor Author

@varl @amcgee I think this is ready for another review

@varl
Copy link
Contributor

varl commented Oct 21, 2019

LGTM.

As I mentioned in the other Cypress/Cucumber PR: I don't have experience setting it up so basing my review on how it looks and works. If there are any improvements to be made they can be done incrementally.

@varl varl requested a review from amcgee October 21, 2019 06:18
@varl
Copy link
Contributor

varl commented Oct 21, 2019

Would be great if you could take another look @amcgee.

Copy link
Member

@amcgee amcgee left a comment

Choose a reason for hiding this comment

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

LGTM (after removing the unused feature again, minor comments below)

I can't say I'm crazy about the sentence-length file/directory names (really easy to mis-match them, since they need to be identical), though I can live with that here.

Also not a deal-breaker, but here's a suggestion for script names that make them a little more descriptive -

cypress:run // starts the server and runs cypress:only:run
cypress:open // starts the server and runs cypress:only:open
cypress:only:run // cypress run
cypress:only:open // cypress open

Not sure I love these either, but at least it's easier to parse than the difference between cypress:open and cypress:browser.

We could make these CLI flags in the eventual wrapper library, so we wouldn't need ugly long script names.

@@ -0,0 +1,5 @@
{
Copy link
Member

Choose a reason for hiding this comment

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

It looks like this file is still here?

Copy link
Member

@amcgee amcgee left a comment

Choose a reason for hiding this comment

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

One more comment

},
"projectId": "65oh1u"
"testFiles": "**/*.feature",
"video": false,
Copy link
Member

Choose a reason for hiding this comment

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

Why are we setting video: false here? Seems like we want videos when doing recorded CI runs...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Same reason as for the screenshots: I think this should be explicitly turned on for CI. During development this won't be needed as we're probably debugging in the browser anyways.

These files will be git-ignored, so on the one hand devs won't necessarily notice these files have been created and on the other hand is the amount of disk space used by videos quite a bit.

Copy link
Member

Choose a reason for hiding this comment

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

Ah you're right, totally fair! I'd used the --video false flag for that, but putting it in the config file is definitely better if we can override it explicitly when running in CI. Nice.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok.. seems like right now that's not an option: kimmobrunfeldt/concurrently#33
So I'm inclined to remove these options from cypress.json until this 3.5 year old issue has been solved..... Do you agree?

Copy link
Member

Choose a reason for hiding this comment

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

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 a bit more complicated. We'd have to set the config with code, depending on an env var, and I wasn't successful in doing so (I didn't try extensively though).

I think for now it's ok to remove it from the config and do this on a new/another branch/PR

Copy link
Member

Choose a reason for hiding this comment

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

This works (with "video": false in cypress.json)

CYPRESS_VIDEO=true cypress run

I think you're right, it's better not to create screenshots or videos on a dev machine so let's default those to false in cypress.json (as you had done) and override them with the env vars in .travis.yml

Copy link
Member

Choose a reason for hiding this comment

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

(no configuration with code required)

Copy link
Member

Choose a reason for hiding this comment

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

^ @Mohammer5 (and yeah, not sure about the Semantic status check, think @varl might have changed the settings for this repo to require all commits to be semantic, since this is merge-rebased?)

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've added this functionality for taking screenshots manually as that didn't work.
Works for videos out of the box.

@Mohammer5 Mohammer5 changed the title test: enable cucumber, rewrite existing tests & add scripts chore: enable cucumber, rewrite existing tests Oct 22, 2019
@Mohammer5 Mohammer5 merged commit 04fcbec into master Oct 23, 2019
@Mohammer5 Mohammer5 deleted the Enable_cucumber branch October 23, 2019 02:41
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants