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

Example for react-app-rewired #35

Closed
StallionV opened this issue Jun 1, 2020 · 17 comments
Closed

Example for react-app-rewired #35

StallionV opened this issue Jun 1, 2020 · 17 comments
Labels
enhancement New feature or request

Comments

@StallionV
Copy link

We created our App using CRA V3 and use Ant design along with it.
Ant design needs a custom version react-app-rewired to run on top of react-scripts.

We did not have Typescript to start with but added later on.

Cypress runs just fine but the code coverage won't run.
Our current start script looks like
"start": "PORT=7000 react-app-rewired start"
and when we change it to
"start": "PORT=7000 react-scripts -r @cypress/instrument-cra start" it won't work

Can you share an example of

  • CRA
  • Using react-app-rewired
  • With Typescript installed
@bahmutov
Copy link
Owner

bahmutov commented Jun 1, 2020 via email

@StallionV
Copy link
Author

StallionV commented Jun 2, 2020

@bahmutov
Copy link
Owner

bahmutov commented Jun 2, 2020

I have forked the repo to https://github.com/bahmutov/cypress-cra-ts-antd-react-app-rewired and added https://github.com/cypress-io/instrument-cra

Starting the app with "start": "PORT=7000 react-app-rewired -r @cypress/instrument-cra start" I see the following

Screen Shot 2020-06-01 at 8 23 52 PM

  • there is window.__coverage__ object, so instrumentation and coverage is there
  • the Layout that comes from antd is missing - is this the error you are seeing? @StallionV

@bahmutov bahmutov added the enhancement New feature or request label Jun 2, 2020
@bahmutov
Copy link
Owner

bahmutov commented Jun 2, 2020

Hmm, I tried an alternative approach - add this plugin via config-overrides.js

const { override, fixBabelImports, addLessLoader, addBabelPlugin } = require('customize-cra')
module.exports = override(
  addBabelPlugin('babel-plugin-istanbul'),
...

But I get the same error - something goes terribly wrong during instrumentation, hmm

@bahmutov
Copy link
Owner

bahmutov commented Jun 2, 2020

Looking at the code.

1st workaround - use require like this

import React from 'react'
// import { Layout, Menu, Breadcrumb } from 'antd'
import './App.less'
const { Layout, Menu, Breadcrumb } = require('antd')
const { Header, Content, Footer } = Layout

Screen Shot 2020-06-01 at 8 41 27 PM

2nd workaround - following umijs/babel-plugin-import#204

import { Layout, Menu, Breadcrumb } from 'antd/lib'

also works

For both, instrument the app either using react-app-rewired -r @cypress/instrument-cra start or config-overrides.js

const { override, fixBabelImports, addLessLoader, addBabelPlugin } = require('customize-cra')
module.exports = override(
  addBabelPlugin('babel-plugin-istanbul'),
  ...

I prefer using addBabelPlugin method (and just adding babel-plugin-istanbul dependency)

@StallionV
Copy link
Author

StallionV commented Jun 2, 2020

Yes this is the same error. Basically react-app-rewired was added to customize web pack.
Reference Ant design v3: https://3x.ant.design/docs/react/use-with-create-react-app#Advanced-Guides
Interestingly they switched to Craco recently with v4: https://ant.design/docs/react/use-with-create-react-app#Advanced-Guides

But yes it is complaining that it is not able to get any Ant modules and the app crashes.
If you revert the line it goes back to working fine

@StallionV
Copy link
Author

2nd workaround - following ant-design/babel-plugin-import#204

also works

For both, instrument the app either using react-app-rewired -r @cypress/instrument-cra start or config-overrides.js

const { override, fixBabelImports, addLessLoader, addBabelPlugin } = require('customize-cra')
module.exports = override(
  addBabelPlugin('babel-plugin-istanbul'),
  ...

I prefer using addBabelPlugin method (and just adding babel-plugin-istanbul dependency)

Thanks let me give this a shot.
The problem with this is changes all over the app, since I have a huge app.
Any other way instead of the require or changing ant to and/lib

Also do i then still follow the same steps as in https://github.com/bahmutov/cra-ts-code-coverage-example right?

@bahmutov
Copy link
Owner

bahmutov commented Jun 2, 2020 via email

@StallionV
Copy link
Author

Thanks I will give it a shot and update here. Very much appreciate your quick input.
The code coverage videos were great as well.
You guys are awesome !!

@StallionV
Copy link
Author

Thanks @bahmutov so I did get it to work using the 2nd approach but am confused about the code coverage
Screen Shot 2020-06-01 at 9 07 26 PM
Here it is giving me 80% coverage stating 4 of the 5 lines are covered even though the whole JSX element in return is not covered. Can you explain ?

@bahmutov
Copy link
Owner

bahmutov commented Jun 2, 2020

I have recorded this short video explaining the above report https://youtu.be/yVvCYtsmkZU

@StallionV
Copy link
Author

Thanks Gleb , a follow up question which I also left in the comments in the video link.
I totally get what you said. But then isn't the coverage kind of superficial? I know it cannot be covered completely due to code transpilers. I would also like to test the fact that e.g. from the JSX I expect 3 menu items, and if one is missing it is a broken test case. I know I can do this using Cypress, but the fact that it will have 0 impact on my code coverage gives an uneasy feeling. How to we cover this gray area? Unit test ? I really believe Cypress can be a one wholesome solution for testing but would like to cover these real world scenarios as well.

@StallionV
Copy link
Author

Yeah, not sure about changing the imports all over the place, understand this is a hassle, but who knows why these things don't play nicely together. After that you should just use the @cypress/code-coverage plugin to report results I think Gleb

I did end up doing a replace all from 'ant' to from 'ant/lib' and it was not that bad. The reports do show up for the complete app. Just wanted to confirm that this really worked.

@bahmutov
Copy link
Owner

bahmutov commented Jun 2, 2020

:) I don't think you want to cover every line of JSX markup. The important thing is what the users gets. Let's say the most important part for you is that there are 3 items, right. Then you write an assertion to confirm it

import App from './App'
mount(<App />) // or cy.visit('/')
// assuming MenuItem renders something with class="menu-item"
cy.get('.menu-item').should('have.length', 3)

Ok, but maybe you are not sure or had regression about the text in the middle item

import App from './App'
mount(<App />)
// assuming MenuItem renders something with class="menu-item"
cy.get('.menu-item').eq(1).should('contain', 'nav 2')
// or any item contains "nav 2"
cy.contains('.menu-item', 'nav 2')

going even further, maybe you want to confirm the markup produced, then you can bring a snapshot plugin from https://on.cypress.io/plugins and confirm entire HTML

import App from './App'
mount(<App />)
cy.get('.layout').invoke('html').toMatchSnapshot()

I don't like HTML snapshots - they are brittle and had to understand. Instead, I recommend setting up a visual testing https://on.cypress.io/visual-testing plugin. Then you can confirm the entire application works and looks as expected

cy.visit('/')
// confirm the page has rendered
cy.get('.menu-item').should('have.length', 3)
cy.get('.layout').visualSnapshot()

You can find multiple examples of image snapshot testing in our visual testing guide, and even see long list of videos using the open-source plugin at https://github.com/bahmutov/sudoku

Functional tests plus visual snapshots should give you full confidence in the application working. Code coverage is more like a map of remaining features to test, as I talk about in https://www.youtube.com/watch?v=JL3QKQO80fs presentation

@StallionV
Copy link
Author

Thanks that is pretty awesome. Will explore it, that may help bridge the gap !!

@bahmutov
Copy link
Owner

bahmutov commented Jun 4, 2020

ok, seems to be resolved

@bahmutov bahmutov closed this as completed Jun 4, 2020
@gonzalofergar13
Copy link

@bahmutov I'm having a problem with Cypress code coverage. My application has react code in different modules but Cypress is only installed in one of them. When executing Cypress with code coverage, only the react scripts located in the module where Cypress is installed are instrumented and appear in the report. Is there a way to instrument and collect coverage of every module?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants