Skip to content

Improving api #13

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

Merged
merged 15 commits into from
Mar 28, 2018
Merged
10 changes: 10 additions & 0 deletions .all-contributorsrc
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,16 @@
"doc",
"test"
]
},
{
"login": "antoaravinth",
"name": "Anto Aravinth",
"avatar_url": "https://avatars1.githubusercontent.com/u/1241511?s=460&v=4",
"profile": "https://github.com/antoaravinth",
"contributions": [
"code",
"test"
]
}
]
}
8 changes: 3 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
[![downloads][downloads-badge]][npmtrends]
[![MIT License][license-badge]][license]

[![All Contributors](https://img.shields.io/badge/all_contributors-6-orange.svg?style=flat-square)](#contributors)
[![All Contributors](https://img.shields.io/badge/all_contributors-7-orange.svg?style=flat-square)](#contributors)
[![PRs Welcome][prs-badge]][prs]
[![Code of Conduct][coc-badge]][coc]

Expand Down Expand Up @@ -382,11 +382,9 @@ light-weight, simple, and understandable.
Thanks goes to these people ([emoji key][emojis]):

<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->

<!-- prettier-ignore -->
| [<img src="https://avatars.githubusercontent.com/u/1500684?v=3" width="100px;"/><br /><sub><b>Kent C. Dodds</b></sub>](https://kentcdodds.com)<br />[💻](https://github.com/kentcdodds/react-testing-library/commits?author=kentcdodds "Code") [📖](https://github.com/kentcdodds/react-testing-library/commits?author=kentcdodds "Documentation") [🚇](#infra-kentcdodds "Infrastructure (Hosting, Build-Tools, etc)") [⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=kentcdodds "Tests") | [<img src="https://avatars1.githubusercontent.com/u/2430381?v=4" width="100px;"/><br /><sub><b>Ryan Castner</b></sub>](http://audiolion.github.io)<br />[📖](https://github.com/kentcdodds/react-testing-library/commits?author=audiolion "Documentation") | [<img src="https://avatars0.githubusercontent.com/u/8008023?v=4" width="100px;"/><br /><sub><b>Daniel Sandiego</b></sub>](https://www.dnlsandiego.com)<br />[💻](https://github.com/kentcdodds/react-testing-library/commits?author=dnlsandiego "Code") | [<img src="https://avatars2.githubusercontent.com/u/12592677?v=4" width="100px;"/><br /><sub><b>Paweł Mikołajczyk</b></sub>](https://github.com/Miklet)<br />[💻](https://github.com/kentcdodds/react-testing-library/commits?author=Miklet "Code") | [<img src="https://avatars3.githubusercontent.com/u/464978?v=4" width="100px;"/><br /><sub><b>Alejandro Ñáñez Ortiz</b></sub>](http://co.linkedin.com/in/alejandronanez/)<br />[📖](https://github.com/kentcdodds/react-testing-library/commits?author=alejandronanez "Documentation") | [<img src="https://avatars0.githubusercontent.com/u/1402095?v=4" width="100px;"/><br /><sub><b>Matt Parrish</b></sub>](https://github.com/pbomb)<br />[🐛](https://github.com/kentcdodds/react-testing-library/issues?q=author%3Apbomb "Bug reports") [💻](https://github.com/kentcdodds/react-testing-library/commits?author=pbomb "Code") [📖](https://github.com/kentcdodds/react-testing-library/commits?author=pbomb "Documentation") [⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=pbomb "Tests") |
| :---: | :---: | :---: | :---: | :---: | :---: |

| [<img src="https://avatars.githubusercontent.com/u/1500684?v=3" width="100px;"/><br /><sub><b>Kent C. Dodds</b></sub>](https://kentcdodds.com)<br />[💻](https://github.com/kentcdodds/react-testing-library/commits?author=kentcdodds "Code") [📖](https://github.com/kentcdodds/react-testing-library/commits?author=kentcdodds "Documentation") [🚇](#infra-kentcdodds "Infrastructure (Hosting, Build-Tools, etc)") [⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=kentcdodds "Tests") | [<img src="https://avatars1.githubusercontent.com/u/2430381?v=4" width="100px;"/><br /><sub><b>Ryan Castner</b></sub>](http://audiolion.github.io)<br />[📖](https://github.com/kentcdodds/react-testing-library/commits?author=audiolion "Documentation") | [<img src="https://avatars0.githubusercontent.com/u/8008023?v=4" width="100px;"/><br /><sub><b>Daniel Sandiego</b></sub>](https://www.dnlsandiego.com)<br />[💻](https://github.com/kentcdodds/react-testing-library/commits?author=dnlsandiego "Code") | [<img src="https://avatars2.githubusercontent.com/u/12592677?v=4" width="100px;"/><br /><sub><b>Paweł Mikołajczyk</b></sub>](https://github.com/Miklet)<br />[💻](https://github.com/kentcdodds/react-testing-library/commits?author=Miklet "Code") | [<img src="https://avatars3.githubusercontent.com/u/464978?v=4" width="100px;"/><br /><sub><b>Alejandro Ñáñez Ortiz</b></sub>](http://co.linkedin.com/in/alejandronanez/)<br />[📖](https://github.com/kentcdodds/react-testing-library/commits?author=alejandronanez "Documentation") | [<img src="https://avatars0.githubusercontent.com/u/1402095?v=4" width="100px;"/><br /><sub><b>Matt Parrish</b></sub>](https://github.com/pbomb)<br />[🐛](https://github.com/kentcdodds/react-testing-library/issues?q=author%3Apbomb "Bug reports") [💻](https://github.com/kentcdodds/react-testing-library/commits?author=pbomb "Code") [📖](https://github.com/kentcdodds/react-testing-library/commits?author=pbomb "Documentation") [⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=pbomb "Tests") | [<img src="https://avatars1.githubusercontent.com/u/1241511?s=460&v=4" width="100px;"/><br /><sub><b>Anto Aravinth</b></sub>](https://github.com/antoaravinth)<br />[💻](https://github.com/kentcdodds/react-testing-library/commits?author=antoaravinth "Code") [⚠️](https://github.com/kentcdodds/react-testing-library/commits?author=antoaravinth "Tests") |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: |
<!-- ALL-CONTRIBUTORS-LIST:END -->

This project follows the [all-contributors][all-contributors] specification.
Expand Down
7 changes: 7 additions & 0 deletions extend-expect.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const expect = require('expect') //eslint-disable-line import/no-extraneous-dependencies
const extensions = require('./dist/jest-extensions')

const {toBeInTheDOM, toHaveTextContent, toSatisfyDOM} = extensions.default
expect.extend({toBeInTheDOM, toHaveTextContent, toSatisfyDOM})

module.exports = expect
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
},
"files": [
"dist",
"typings"
"typings",
"extend-expect.js"
],
"keywords": [],
"author": "Kent C. Dodds <kent@doddsfamily.us> (http://kentcdodds.com/)",
Expand Down
12 changes: 11 additions & 1 deletion src/__tests__/fetch.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react'
import axiosMock from 'axios'
import {render, Simulate, flushPromises} from '../'
import '../../extend-expect' //eslint-disable-line import/no-unassigned-import
Copy link
Member

Choose a reason for hiding this comment

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

Let's just disable this rule globally. It really annoys me and I should remove it from my base config eventually...

In the package.json, update the eslintConfig to have a rules property that disables this rule 👍


// instead of importing it, we'll define it inline here
// import Fetch from '../fetch'
Expand Down Expand Up @@ -37,14 +38,23 @@ test('Fetch makes an API call and displays the greeting when load-greeting is cl
}),
)
const url = '/greeting'
const {getByTestId, container} = render(<Fetch url={url} />)
const {getByTestId, container, queryByTestId} = render(<Fetch url={url} />)

// Act
Simulate.click(getByTestId('load-greeting'))

await flushPromises()

// Assert
expect(queryByTestId('foo')).not.toBeInTheDOM()
Copy link
Member

Choose a reason for hiding this comment

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

I think people will look to these tests as an example of how to test their components with good practices.

With that in mind, let's do one of the following:

  1. Add a comment suggesting: "Here are a few assertions you could use, but you don't need all of them."
  2. Move these to a separate testing file that's intended to show off the different kinds of assertions.

I don't really care which we do.

expect(queryByTestId('greeting-text')).toBeInTheDOM()
expect(queryByTestId('greeting-text')).toHaveTextContent('hello there')
expect(getByTestId('greeting-text')).toSatisfyDOM(
el => el.textContent === 'hello there',
)
expect(queryByTestId('greeting-text')).not.toHaveTextContent(
'you are not there',
)
expect(axiosMock.get).toHaveBeenCalledTimes(1)
expect(axiosMock.get).toHaveBeenCalledWith(url)
expect(getByTestId('greeting-text').textContent).toBe('hello there')
Expand Down
48 changes: 48 additions & 0 deletions src/jest-extensions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
const extensions = {
toBeInTheDOM(received) {
if (received) {
return {
message: () => 'expected the dom to be present',
Copy link
Member

Choose a reason for hiding this comment

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

Rather than calling it "dom" call it "element." The received is an element, not "dom" 👍

Same below.

pass: true,
}
} else {
return {
message: () => 'expected the dom not to be present',
pass: false,
}
}
},

toHaveTextContent(htmlElement, checkWith) {
const textContent = htmlElement.textContent
Copy link
Member

Choose a reason for hiding this comment

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

Could we add an extra check here that htmlElement is actually instanceof HTMLElement? If not we can:

throw new Error(`The given subject is a ${getDisplayName(htmlElement)}, not an HTMLElement`)

Or return an object, but this should probably fail regardless of whether people use .not.

The getDisplayName function could be something like this:

function getDisplayName(subject) {
  if (subject && subject.constructor) {
    return subject.constructor.name
  } else {
    return typeof subject
  }
}

Or, maybe there's a better thing for this available on npm...

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I guess the code that you had mentioned getDisplayName is enough. npm packages are there, but they offer many functionalities which we won't need at this time.

const pass = textContent === checkWith
Copy link
Member

Choose a reason for hiding this comment

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

Could we extend this to use the matcher function that's in the queries.js file? Perhaps we should move that matcher function to a utils file.

Using the matcher function would allow the toHaveTextContent to use a regex/case insensitive substring/function which I think would make this more powerful.

Copy link
Collaborator Author

@antsmartian antsmartian Mar 27, 2018

Choose a reason for hiding this comment

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

Yes, thats a good idea. Can take care of that, will move matcher to utils folder. Import matcher in queries.js and jest-extension.js files to use them. So fundamentally the call would be:

const pass =  matches(textContent,htmlElement,checkWith)

if (pass) {
return {
message: () => `expected ${textContent} not equals to ${checkWith}`,
Copy link
Member

Choose a reason for hiding this comment

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

Let's use jest-matcher-utils here so it's colored properly.

pass: true,
}
} else {
return {
message: () => `expected ${textContent} equals to ${checkWith}`,
Copy link
Member

Choose a reason for hiding this comment

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

Let's use jest-matcher-utils here so it's colored properly.

pass: false,
}
}
},

toSatisfyDOM(element, fn) {
const pass = fn(element)
Copy link
Member

Choose a reason for hiding this comment

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

I think this should be more like this: https://github.com/jest-community/jest-extended/blob/master/src/matchers/toSatisfy/index.js

In fact, it looks like we should probably be changing everything in this file to use jest-matcher-utils so it's colored properly etc. Unfortunately it looks like there are no docs, but here's the source.

if (pass) {
return {
message: () => 'expected condition not equals to true',
pass: true,
}
} else {
return {
message: () => 'expected condition equals to true',
pass: false,
}
}
},
}

export default extensions