├── .gitignore
├── src
├── __tests__
│ ├── mock.js
│ └── shallow.js
├── utils.js
└── list-github-repos.js
├── .babelrc
└── package.json
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/src/__tests__/mock.js:
--------------------------------------------------------------------------------
1 | test('works', () => {})
2 |
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["babel-preset-react", "babel-preset-env"],
3 | "plugins": ["babel-plugin-transform-class-properties"]
4 | }
5 |
--------------------------------------------------------------------------------
/src/__tests__/shallow.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import Enzyme, {shallow} from 'enzyme'
3 | import Adapter from 'enzyme-adapter-react-16'
4 | import {ListGitHubRepos} from '../list-github-repos'
5 |
6 | Enzyme.configure({adapter: new Adapter()})
7 |
8 | test('shallow', () => {
9 | const wrapper = shallow()
10 | console.log(wrapper.debug())
11 | })
12 |
--------------------------------------------------------------------------------
/src/utils.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 |
3 | function searchRepos(query) {
4 | return axios({
5 | url: 'https://api.github.com/graphql',
6 | method: 'post',
7 | data: {
8 | query: `{
9 | search(first: 10,type:REPOSITORY, query:"${query}") {
10 | nodes {
11 | ... on Repository {
12 | nameWithOwner
13 | homepageUrl
14 | url
15 | }
16 | }
17 | }
18 | }`
19 | },
20 | headers: {
21 | Authorization: `bearer 102307c997ceb0fd9a4bc6c3457473c91f2b0b6f`
22 | }
23 | }).then(response => {
24 | return response.data.data.search.nodes
25 | })
26 | }
27 |
28 | export {searchRepos}
29 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "never-use-shallow-rendering",
3 | "version": "1.0.0",
4 | "description": "Example of why you shouldn't use shallow rendering",
5 | "main": "index.js",
6 | "dependencies": {
7 | "axios": "^0.18.0",
8 | "react-dom": "^16.4.1",
9 | "react": "^16.4.1"
10 | },
11 | "devDependencies": {
12 | "babel-core": "^6.26.3",
13 | "babel-plugin-transform-class-properties": "^6.24.1",
14 | "babel-preset-env": "^1.7.0",
15 | "babel-preset-react": "^6.24.1",
16 | "enzyme": "^3.3.0",
17 | "enzyme-adapter-react-16": "^1.1.1",
18 | "jest": "^23.2.0",
19 | "react-testing-library": "^4.0.2"
20 | },
21 | "scripts": {
22 | "test": "jest"
23 | },
24 | "keywords": [],
25 | "author": "Kent C. Dodds (http://kentcdodds.com/)",
26 | "license": "GPLv3"
27 | }
28 |
--------------------------------------------------------------------------------
/src/list-github-repos.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {searchRepos} from './utils'
3 |
4 | const callAll = (...fns) => (...args) => fns.forEach(fn => fn && fn(...args))
5 |
6 | class SearchInput extends React.Component {
7 | static idCounter = 1
8 | id = `search-input-${SearchInput.idCounter++}`
9 | input = React.createRef()
10 | state = {error: null}
11 | handleChange = event => {
12 | clearTimeout(this.timeout)
13 | const {value} = event.target
14 | this.setState({error: null})
15 | // delay showing the error in case the user's still typing
16 | this.timeout = setTimeout(() => {
17 | this.setState({error: this.getError(value)})
18 | }, 400)
19 | }
20 | getError(value) {
21 | return value && value.length < 3 ? 'Must be 3 characters or longer' : null
22 | }
23 | componentWillUnmount() {
24 | clearTimeout(this.timeout)
25 | }
26 | render() {
27 | const {error} = this.state
28 | const {
29 | label,
30 | inputProps: {onChange, id = this.id, ...inputProps}
31 | } = this.props
32 | return (
33 |
34 |
35 |
36 |
{error}
37 |
38 | )
39 | }
40 | }
41 |
42 | class List extends React.Component {
43 | render() {
44 | const {list} = this.props
45 | return (
46 |
55 | )
56 | }
57 | }
58 |
59 | class Title extends React.Component {
60 | render() {
61 | return List of GitHub repos
62 | }
63 | }
64 |
65 | class SearchForm extends React.Component {
66 | handleSubmit = async event => {
67 | event.preventDefault()
68 | const query = event.target.elements.query.value
69 | const repos = await searchRepos(query)
70 | this.props.onSearchResult(repos)
71 | }
72 | render() {
73 | return (
74 |
78 | )
79 | }
80 | }
81 |
82 | class ListGitHubRepos extends React.Component {
83 | state = {list: []}
84 | handleSearchResult = repos => this.setState({list: repos})
85 | render() {
86 | const {list} = this.state
87 | return (
88 |
89 |
90 |
91 |
92 |
93 | )
94 | }
95 | }
96 |
97 | export {ListGitHubRepos}
98 |
--------------------------------------------------------------------------------