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

[docs] Add unit testing guide #6678

Merged
merged 20 commits into from
Aug 16, 2018
Merged

[docs] Add unit testing guide #6678

merged 20 commits into from
Aug 16, 2018

Conversation

ascorbic
Copy link
Contributor

Add a unit testing doc

@KyleAMathews
Copy link
Contributor

KyleAMathews commented Jul 23, 2018

Deploy preview for using-postcss-sass failed.

Built with commit 01898bb

https://app.netlify.com/sites/using-postcss-sass/deploys/5b69625702ed8362a8bbd799

@gatsbybot
Copy link
Collaborator

gatsbybot commented Jul 23, 2018

Deploy preview for using-drupal ready!

Built with commit 01898bb

https://deploy-preview-6678--using-drupal.netlify.com

@gatsbybot
Copy link
Collaborator

gatsbybot commented Jul 23, 2018

Deploy preview for gatsbygram ready!

Built with commit 01898bb

https://deploy-preview-6678--gatsbygram.netlify.com

@LekoArts
Copy link
Contributor

LekoArts commented Jul 23, 2018

Well done! Really like it 👍 You described the setup I currently also have.

I could write about:

  • react-testing-library
  • emotion (or any CSS-in-JS)
  • cypress

We'd need to figure out how to structure this. I'd propose a section on the Guides with the title Testing. We then would have your Unit testing.
I could add End-to-End testing showing how to use cypress.

How could we group/add the other two bulletpoints there?

I'll try to understand the testing on Gatsby's GraphQL etc. with @kkemple help. That could also go into your Unit testing then.

@ascorbic
Copy link
Contributor Author

Great. Yes, I agree a new testing section would be best, and end-to-end testing would be really useful. Something on CI might be good too. We need to work out where to best draw the line, as this obviously isn't meant to be a general guide to React testing, but rather a Gatsby-specific guide.

I'd like to do a guide on Storybooks, as they're really useful and need some particular Gatsby setup.

@LekoArts
Copy link
Contributor

Something on CI might be good too. We need to work out where to best draw the line, as this obviously isn't meant to be a general guide to React testing, but rather a Gatsby-specific guide.

Agree!
Jest really seemed the worst to setup.

The guides on Styling could be a good reference for the rest as there's also only really little to setup (but it still is getting explained). So for Cypress it would be more of an explanation of something like:

"test:e2e:dev": "start-server-and-test dev http://localhost:8000 cy:open",
"test:e2e:run": "start-server-and-test develop http://localhost:8000 cy:run",

react-testing-library and emotion don't have any Gatsby specific problems but I'll guess a short explanation on what to do would be cool.

@ascorbic
Copy link
Contributor Author

I've not tried testing components that include graphql. You may need to add babel-plugin-remove-graphql-queries to the preprocessor.

@pieh
Copy link
Contributor

pieh commented Jul 24, 2018

Woah, this is great!

I wonder if we can add something to gatsby-link with process.env.NODE_ENV === `test` to avoid need of MemoryRouter trick

We'd need to figure out how to structure this. I'd propose a section on the Guides with the title Testing. We then would have your Unit testing.

/cc @shannonbux for input on structuring docs

@S-unya
Copy link

S-unya commented Jul 24, 2018

@pieh that would be really useful. We are onboarding a number of developers into Gatsby and every single one has hit that wall.

install Babel 7 as it's required by Jest.

```sh
yarn add -D jest babel-jest react-test-renderer 'babel-core@^7.0.0-0' @babel/core identity-obj-proxy @babel/plugin-proposal-class-properties @babel/plugin-proposal-optional-chaining
Copy link
Contributor

Choose a reason for hiding this comment

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

You should change yarn to npm as that's what is used all through the docs.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Right you are

@KyleAMathews
Copy link
Contributor

KyleAMathews commented Jul 24, 2018

Deploy preview for gatsbyjs failed.

Built with commit 01898bb

https://app.netlify.com/sites/gatsbyjs/deploys/5b69625602ed8362a8bbd78d

For this guide, you will be starting with `gatsby-starter-blog`, but the
concepts should be the same or very similar for your site.

First you need to install Jest and some more required packages. You need to
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this actually necessary with v2 since Gatsby is using Babel 7 already? Seems you would only need to install the presets and plugins? Also, looks like presets are missing from install step unless they are already present for Gatsby itself.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point: the presets are missing, and do need installing. I'll add them. Even though, as you say, Babel 7 is installed by Gatsby, it seems that unless it is added as a dependency of the project, the wrong version is picked-up. Likewise plugins are not found unless specifically included. All my testing was done on the latest beta.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As for your point about whether this is required: yes, it is, as jest doesn't know that it needs to use babel, as there's no .babelrc. You could add one, but of course that is then also used in the Gatsby build. Using a Jest preprocessor seems to be the best way (and is the way used in the Gatsby codebase). I tried to stick as close as possible to the way it's done in the Gatsby site itself.

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh yeah, using preprocessor for sure! I meant having to install babel 7 since it's already used by gatsby, but seems that it is in fact needed!

m-allanson
m-allanson previously approved these changes Jul 25, 2018
Copy link
Contributor

@m-allanson m-allanson left a comment

Choose a reason for hiding this comment

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

Great stuff! Thanks @ascorbic 👍

I think we can merge this now, and then link it up to the docs once we know the best place to put it?

As suggested above, Guides -> Testing -> Unit Testing seems like a sensible place.

matching.

If you make changes that mean you need to update the snapshot, you can do this
by running `npm test -- -u`.
Copy link
Contributor

Choose a reason for hiding this comment

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

I believe with npm version > 5 the -- is unnecessary for passing additional args

Copy link
Contributor

Choose a reason for hiding this comment

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

Let's stick with -- here, as Gatsby supports Node v6 which ships with npm v3.

Copy link
Contributor

Choose a reason for hiding this comment

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

Makes sense!


```js
import React from "react"

Copy link
Contributor

Choose a reason for hiding this comment

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

Spacing here should be consistent with the code further down. L230. No new line between package imports

extension `.test.js` or `.spec.js`. You are telling Jest to ignore any tests in
the `node_modules` or `.cache` directories.

The `moduleNameMapper` section works a bit like webpack rules, and tells Jest
Copy link
Contributor

Choose a reason for hiding this comment

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

Webpack

Copy link
Contributor

Choose a reason for hiding this comment

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

I just changed this in my last review :) webpack is officially written as 'webpack' rather than 'Webpack'. Awkward, I know! See usage on https://webpack.js.org/

Copy link
Contributor

Choose a reason for hiding this comment

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

oh wut. TIL. Thanks!

how to handle imports. You are mainly concerned here with mocking static file
imports, which Jest can't handle. A mock is a dummy module that is used instead
of the real module inside tests. It is good when you have something that you
can't or don't want to test. You have two types that you mock: stylesheets, and
Copy link
Contributor

Choose a reason for hiding this comment

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

Why not just

You can mock anything

}
```

This means you can now run tests by typing `npm test`. If you want you could
Copy link
Contributor

Choose a reason for hiding this comment

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

npm run test for verboseness

also add a script that runs `jest --watchAll` to watch files and run tests when
they are changed.

Now, run `npm test` and you should immediately get an error like this:
Copy link
Contributor

Choose a reason for hiding this comment

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

npm run test

the snapshot being written. This is created in a `__snapshots__` directory next
to your tests. If you take a look at it, you will see that it is a JSON
representation of the `<Bio />` component. You should check your snapshot files
into your SCM repository so that anyone can see if the tests have stopped
Copy link
Contributor

Choose a reason for hiding this comment

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

Wording.

so that any changes are tracked in history

Copy link
Contributor

Choose a reason for hiding this comment

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

And that tests can run by CI solutions like travis (which could have it's own guide that could be linked in the future)

wuweiweiwu
wuweiweiwu previously approved these changes Jul 26, 2018
Copy link
Contributor

@wuweiweiwu wuweiweiwu left a comment

Choose a reason for hiding this comment

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

Minor comments 👍

"use strict"
import React from "react"
const gatsby = jest.genMockFromModule("gatsby")
gatsby.Link = ({ to, ...props }) => <a href={to} {...props} />
Copy link
Contributor

@LekoArts LekoArts Aug 1, 2018

Choose a reason for hiding this comment

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

I encountered this issue because my NavItem component uses activeClassName on Link:

Warning: React does not recognize the `activeClassName` prop on a DOM element. If you intentionally want i
t to appear in the DOM as a custom attribute, spell it as lowercase `activeclassname` instead. If you accident
ally passed it from a parent component, remove it from the DOM element.

So we should write something like?

gatsby.Link = ({ to, activeClassName, activeStyle, ...props }) => (
  <a href={to} className={activeClassName} style={activeStyle} {...props} />
);

Copy link
Contributor

@LekoArts LekoArts Aug 1, 2018

Choose a reason for hiding this comment

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

It also changes the emotion snapshots. It removes the styling of the activeClassName content. I think it doesn't recognize in my test that it now should display the active style because the to prop is the same as the current location.

Copy link
Contributor

Choose a reason for hiding this comment

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

Removing the mocking for gatsby.Link just caused more errors :/

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, it will change snapshots because it's replacing a component with a mock. That's expected.

Copy link
Contributor

Choose a reason for hiding this comment

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

Sorry, wasn't clear enough. It changes the snapshot of my styles (via jest-emotion). The removed styles are the ones from activeClassNames.

 FAIL  src/elements/__tests__/NavItem.js
  ● NavItem › renders with active style

    expect(value).toMatchSnapshot()

    Received value does not match stored snapshot "NavItem renders with active style 1".

    - Snapshot
    + Received

    @@ -60,37 +60,12 @@
          margin: 1.5rem 0.25rem;
          padding: 6px 16px;
        }
      }

    - .emotion-1 {
    -   color: #765e31;
    -   background: rgba(238,205,81,0.2);
    - }
    -
    - .emotion-1:focus {
    -   color: #765e31;
    - }
    -
    - @media (max-width:800px) {
    -   .emotion-1 {
    -     color: white !important;
    -     background: none;
    -     margin-bottom: 0;
    -     padding-bottom: 0.5rem;
    -   }
    -
    -   .emotion-1:after {
    -     -webkit-transform: translateY(0px);
    -     -ms-transform: translateY(0px);
    -     transform: translateY(0px);
    -   }
    - }
    -
      <a
    -   aria-current="page"
    -   class="emotion-0 emotion-1"
    +   class="emotion-0"
        data-testid="navitem-bilbo"
        href="/"
      >
        Brand
      </a>

      27 |     );
      28 |
    > 29 |     expect(container.firstChild).toMatchSnapshot();
         |                                  ^
      30 |   });
      31 |
      32 |   test('renders with correct attributes', () => {

      at Object.<anonymous> (src/elements/__tests__/NavItem.js:29:34)

@LekoArts
Copy link
Contributor

LekoArts commented Aug 1, 2018

Same snapshot error like in #6678 (review) described occurs

@ascorbic
Copy link
Contributor Author

ascorbic commented Aug 1, 2018

You can't expect the snapshots to match, as they're being generated in different ways. The important things is whether they change in future when your code changes.

@ascorbic
Copy link
Contributor Author

ascorbic commented Aug 1, 2018

The specific issue here is that the mock doesn't have the logic to know if it's the active link or not.

@LekoArts
Copy link
Contributor

LekoArts commented Aug 2, 2018

Alright, I understand that. Just wished that I still could test that (with the mock — the „old“ MemoryRouter way still works of course).

Then I‘d add one or two sentences about the fact that this way you can’t test the active state.

Copy link
Contributor

@shannonbux shannonbux left a comment

Choose a reason for hiding this comment

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

@ascorbic looks great! just left one comment

@pieh It seems like Testing ought to be a new category now. I'll do that and put these docs there.

@S-unya, have you chatted with anyone at Gatsby about your experience onboarding devs to Gatsby? It'd be super valuable to hear what major roadblocks you've noticed calendly.com/shannon-soper <--sign up there (others are welcome to, too!)


Here is the example:

```js
Copy link
Contributor

Choose a reason for hiding this comment

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

What kind of file should someone use this code example for? Maybe readers will just know, but wanted to make sure if it's supposed to go in a specific type of file or you have a suggestion, make it clear here as you did for other code examples!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As in where they'd be using StaticQuery rather than a page query? No problem.

@ascorbic
Copy link
Contributor Author

ascorbic commented Aug 3, 2018

@shannonbux That's great. Yes, I definitely think testing needs a category. I have more to come! Storybooks I think might be next, and CI/CD would be a good one. I've learnt stuff just from seeing the setup you have here in the gatsby repo, tbh.

Regarding onboarding, @S-unya and I are colleagues, and we've been running workshops for the rest of our team. A lot of these docs have come out of our experiences with this. It would be great to chat about that at some point.

@KyleAMathews
Copy link
Contributor

Deploy preview for using-styled-components failed.

Built with commit 17b86d2

https://app.netlify.com/sites/using-styled-components/deploys/5b64140e3813f06148ecae01

@KyleAMathews
Copy link
Contributor

Deploy preview for using-contentful failed.

Built with commit 17b86d2

https://app.netlify.com/sites/using-contentful/deploys/5b64140e3813f06148ecae04

@shannonbux
Copy link
Contributor

shannonbux commented Aug 3, 2018 via email

@Mathspy
Copy link

Mathspy commented Aug 5, 2018

Thank you very much for this write-up! Would have been lost without it in my new project that I based on both Storybook and Jest (and what a weird time to start a project like that with Babel moving to v7, Storybook moving to v4 and Gatsby moving to v2)

After the hours spent getting everything working few days ago I decided to save anyone trying this in the future the hassle and made a Storybook/Jest starter

On that note, I would be very interested in helping writing up future test documentations whether for jest or storybook or otherwise as testing is an enthusiasm of mine

And truly kudos to Gatsby, Storybook, Jest, Babel, Enzyme and all other open-source projects for your continuous and commendable work ❤️

@kkemple
Copy link
Contributor

kkemple commented Aug 6, 2018

@Mathspy thanks for making this a starter! It was on my list of things to do once we figured out the best approach for testing. So awesome! 🙌👏

TypeError: Cannot read property 'history' of undefined
```

This is an error in `gatsby-link`, although `react-router-dom` would complain
Copy link
Contributor

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.

OK, done. It simplifies it quite a bit, as @reach/router's Link is a lot happier running in a test environment without a Router than react-router was.

],
"globals": {
"__PATH_PREFIX__": ""
},
Copy link
Contributor

Choose a reason for hiding this comment

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

I received the following error:
jestjs/jest#6766

testURL: 'http://localhost' solves this issue 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good spot. Added, along with explanation.

@LekoArts
Copy link
Contributor

LekoArts commented Aug 7, 2018

FYI, switching to @reach/router solved the issue with the snapshot tests for the activeClassName 👍
Snapshots also include that now (following your instructions of mocking gatsby-link)

```js
// loadershim.js

global.___loader = {
Copy link
Contributor

Choose a reason for hiding this comment

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

what's ___loader? and what is enqueue? Where do they come from originally?

Copy link
Contributor

Choose a reason for hiding this comment

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

They're part of Gatsby's runtime. They were exposed as globals for some reason or another a while ago and need refactored to a normal module interface.

Copy link
Contributor

@calcsam calcsam left a comment

Choose a reason for hiding this comment

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

Looks great! Everyone's given the 👍 so I'm going to merge this in!

@calcsam
Copy link
Contributor

calcsam commented Aug 16, 2018

@shannonbux let's get these into the link structure ASAP :)

@calcsam calcsam merged commit 260e25f into gatsbyjs:master Aug 16, 2018
calcsam pushed a commit that referenced this pull request Aug 16, 2018
* Add unit testing guide

* Typo fixes

* Proofreading

* Add info on testing gatsby-link

* Updates for style

* Switch yarn to npm

* Add babel presets to npm install

* Small edits

* Small edits from review

* Add loader shim and __PATH_PREFIX__ global

* Add testing graphql doc

* Rename

* Mock Gatsby rather than removing graphql and using MemoryRouter

* Add filename for gatsby mock

* Update LInk mock so all props can be displayed

* Details on why you might not want to mock Link

* Add not on use of StaticQuery, and a little on component purity

* Update for @reach/router

* Add testURL to Jest config
Because of jestjs/jest#6766
calcsam added a commit that referenced this pull request Aug 16, 2018
* Add unit testing guide

* Typo fixes

* Proofreading

* Add info on testing gatsby-link

* Updates for style

* Switch yarn to npm

* Add babel presets to npm install

* Small edits

* Small edits from review

* Add loader shim and __PATH_PREFIX__ global

* Add testing graphql doc

* Rename

* Mock Gatsby rather than removing graphql and using MemoryRouter

* Add filename for gatsby mock

* Update LInk mock so all props can be displayed

* Details on why you might not want to mock Link

* Add not on use of StaticQuery, and a little on component purity

* Update for @reach/router

* Add testURL to Jest config
Because of jestjs/jest#6766
porfirioribeiro pushed a commit to porfirioribeiro/gatsby that referenced this pull request Aug 22, 2018
* Add unit testing guide

* Typo fixes

* Proofreading

* Add info on testing gatsby-link

* Updates for style

* Switch yarn to npm

* Add babel presets to npm install

* Small edits

* Small edits from review

* Add loader shim and __PATH_PREFIX__ global

* Add testing graphql doc

* Rename

* Mock Gatsby rather than removing graphql and using MemoryRouter

* Add filename for gatsby mock

* Update LInk mock so all props can be displayed

* Details on why you might not want to mock Link

* Add not on use of StaticQuery, and a little on component purity

* Update for @reach/router

* Add testURL to Jest config
Because of jestjs/jest#6766
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.