From f14d3ea1af1301a8ba5d12badea05092f863f2f6 Mon Sep 17 00:00:00 2001 From: jerolan Date: Tue, 25 Jun 2019 17:45:38 -0500 Subject: [PATCH 01/12] Base test --- package.json | 4 +- src/__tests__/App.js | 10 +++++ src/components/TriviaResultScreen/App.test.js | 9 ---- yarn.lock | 43 ++++++++++++++++++- 4 files changed, 54 insertions(+), 12 deletions(-) create mode 100644 src/__tests__/App.js delete mode 100644 src/components/TriviaResultScreen/App.test.js diff --git a/package.json b/package.json index d6a0a9e..d3461dd 100644 --- a/package.json +++ b/package.json @@ -11,9 +11,11 @@ "react-scripts": "3.0.1" }, "devDependencies": { + "@testing-library/react": "^8.0.4", "husky": ">=1", "lint-staged": ">=8", - "prettier": "1.17.1" + "prettier": "1.17.1", + "react-test-renderer": "^16.8.6" }, "scripts": { "start": "react-scripts start", diff --git a/src/__tests__/App.js b/src/__tests__/App.js new file mode 100644 index 0000000..9b363a1 --- /dev/null +++ b/src/__tests__/App.js @@ -0,0 +1,10 @@ +import React from 'react'; +import App from '../App'; + +import renderer from 'react-test-renderer'; + +describe('', () => { + it('renders correctly', () => { + renderer.create(); + }); +}); diff --git a/src/components/TriviaResultScreen/App.test.js b/src/components/TriviaResultScreen/App.test.js deleted file mode 100644 index a754b20..0000000 --- a/src/components/TriviaResultScreen/App.test.js +++ /dev/null @@ -1,9 +0,0 @@ -import React from 'react'; -import ReactDOM from 'react-dom'; -import App from './App'; - -it('renders without crashing', () => { - const div = document.createElement('div'); - ReactDOM.render(, div); - ReactDOM.unmountComponentAtNode(div); -}); diff --git a/yarn.lock b/yarn.lock index 1b8f88b..dfd4730 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1205,6 +1205,11 @@ dependencies: any-observable "^0.3.0" +"@sheerun/mutationobserver-shim@^0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@sheerun/mutationobserver-shim/-/mutationobserver-shim-0.3.2.tgz#8013f2af54a2b7d735f71560ff360d3a8176a87b" + integrity sha512-vTCdPp/T/Q3oSqwHmZ5Kpa9oI7iLtGl3RQaA/NyLHikvcrPxACkkKVr/XzkSPJWXHRhKGzVvb0urJsbMlRxi1Q== + "@svgr/babel-plugin-add-jsx-attribute@^4.2.0": version "4.2.0" resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-4.2.0.tgz#dadcb6218503532d6884b210e7f3c502caaa44b1" @@ -1310,6 +1315,25 @@ "@svgr/plugin-svgo" "^4.0.3" loader-utils "^1.1.0" +"@testing-library/dom@^5.0.0": + version "5.4.0" + resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-5.4.0.tgz#49f41c99473286a4102721242bc47571fb7efef0" + integrity sha512-0OQsquNYfbxgqqoGf9RZ9lglXEYgKlhSe+W9UFQGDAvT554Y9PG6hGe0RHYggAXe/GoNPccSsl65nn+qq0cFKw== + dependencies: + "@babel/runtime" "^7.4.5" + "@sheerun/mutationobserver-shim" "^0.3.2" + aria-query "3.0.0" + pretty-format "^24.8.0" + wait-for-expect "^1.2.0" + +"@testing-library/react@^8.0.4": + version "8.0.4" + resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-8.0.4.tgz#6ed405ba88b625ec53d7cfa78c038a950bafc1fa" + integrity sha512-omm4D00Z0aMaWfPRRP4X6zIaOVb0Kf1Yc1H5VE4id9D0pQRiBcTtmjbN0kZgT8rQGxHhVAuv1NuwFwMTwKzFqg== + dependencies: + "@babel/runtime" "^7.4.5" + "@testing-library/dom" "^5.0.0" + "@types/babel__core@^7.1.0": version "7.1.1" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.1.tgz#ce9a9e5d92b7031421e1d0d74ae59f572ba48be6" @@ -1774,7 +1798,7 @@ argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" -aria-query@^3.0.0: +aria-query@3.0.0, aria-query@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-3.0.0.tgz#65b3fcc1ca1155a8c9ae64d6eee297f15d5133cc" integrity sha1-ZbP8wcoRVajJrmTW7uKX8V1RM8w= @@ -8471,7 +8495,7 @@ react-event-listener@^0.6.6: prop-types "^15.6.0" warning "^4.0.1" -react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.0, react-is@^16.8.1, react-is@^16.8.4: +react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.0, react-is@^16.8.1, react-is@^16.8.4, react-is@^16.8.6: version "16.8.6" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.6.tgz#5bbc1e2d29141c9fbdfed456343fe2bc430a6a16" integrity sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA== @@ -8565,6 +8589,16 @@ react-scripts@3.0.1: optionalDependencies: fsevents "2.0.6" +react-test-renderer@^16.8.6: + version "16.8.6" + resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.8.6.tgz#188d8029b8c39c786f998aa3efd3ffe7642d5ba1" + integrity sha512-H2srzU5IWYT6cZXof6AhUcx/wEyJddQ8l7cLM/F7gDXYyPr4oq+vCIxJYXVGhId1J706sqziAjuOEjyNkfgoEw== + dependencies: + object-assign "^4.1.1" + prop-types "^15.6.2" + react-is "^16.8.6" + scheduler "^0.13.6" + react@^16.8.6: version "16.8.6" resolved "https://registry.yarnpkg.com/react/-/react-16.8.6.tgz#ad6c3a9614fd3a4e9ef51117f54d888da01f2bbe" @@ -10254,6 +10288,11 @@ w3c-xmlserializer@^1.1.2: webidl-conversions "^4.0.2" xml-name-validator "^3.0.0" +wait-for-expect@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/wait-for-expect/-/wait-for-expect-1.2.0.tgz#fdab6a26e87d2039101db88bff3d8158e5c3e13f" + integrity sha512-EJhKpA+5UHixduMBEGhTFuLuVgQBKWxkFbefOdj2bbk2/OpA5Opsc4aUTGmF+qJ+v3kTGxDRNYwKaT4j6g5n8Q== + walker@^1.0.7, walker@~1.0.5: version "1.0.7" resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb" From eb20a0869a1253121cb9a779d879c76e54924029 Mon Sep 17 00:00:00 2001 From: jerolan Date: Tue, 25 Jun 2019 18:49:28 -0500 Subject: [PATCH 02/12] Update test cases --- package.json | 17 +++++- src/__tests__/{App.js => App-test.js} | 0 src/api/__tests__/api-test.js | 18 ++++++ src/components/HomeScreen/HomeScreen.js | 2 +- .../HomeScreen/__tests__/HomeScreen-test.js | 13 ++++ .../__snapshots__/HomeScreen-test.js.snap | 48 +++++++++++++++ .../__tests__/TriviaResultScreen-test.js | 61 +++++++++++++++++++ .../__tests__/TriviaScreen-test.js | 32 ++++++++++ .../__tests__/AnswerOptionsList-test.js | 24 ++++++++ .../__tests__/AnswerResultTitle-test.js | 22 +++++++ src/jest/ReactRouter.js | 13 ++++ src/setupTests.js | 6 ++ yarn.lock | 55 +++++++++++++++-- 13 files changed, 304 insertions(+), 7 deletions(-) rename src/__tests__/{App.js => App-test.js} (100%) create mode 100644 src/api/__tests__/api-test.js create mode 100644 src/components/HomeScreen/__tests__/HomeScreen-test.js create mode 100644 src/components/HomeScreen/__tests__/__snapshots__/HomeScreen-test.js.snap create mode 100644 src/components/TriviaResultScreen/__tests__/TriviaResultScreen-test.js create mode 100644 src/components/TriviaScreen/__tests__/TriviaScreen-test.js create mode 100644 src/components/TriviaScreen/components/AnswerOptionList/__tests__/AnswerOptionsList-test.js create mode 100644 src/components/TriviaScreen/components/AnswerResultTitle/__tests__/AnswerResultTitle-test.js create mode 100644 src/jest/ReactRouter.js create mode 100644 src/setupTests.js diff --git a/package.json b/package.json index d3461dd..a6409ff 100644 --- a/package.json +++ b/package.json @@ -5,10 +5,12 @@ "dependencies": { "@material-ui/core": "^4.1.2", "@material-ui/icons": "^4.2.1", + "jest-dom": "^3.5.0", "react": "^16.8.6", "react-dom": "^16.8.6", "react-router-dom": "^5.0.1", - "react-scripts": "3.0.1" + "react-scripts": "3.0.1", + "react-testing-library": "^8.0.1" }, "devDependencies": { "@testing-library/react": "^8.0.4", @@ -20,7 +22,8 @@ "scripts": { "start": "react-scripts start", "build": "react-scripts build", - "test": "react-scripts test" + "test": "react-scripts test", + "coverage": "npm test -- --coverage" }, "eslintConfig": { "extends": "react-app" @@ -37,6 +40,16 @@ "last 1 safari version" ] }, + "jest": { + "coverageThreshold": { + "global": { + "statements": 80, + "branches": 80, + "functions": 80, + "lines": 80 + } + } + }, "husky": { "hooks": { "pre-commit": "lint-staged" diff --git a/src/__tests__/App.js b/src/__tests__/App-test.js similarity index 100% rename from src/__tests__/App.js rename to src/__tests__/App-test.js diff --git a/src/api/__tests__/api-test.js b/src/api/__tests__/api-test.js new file mode 100644 index 0000000..e6600be --- /dev/null +++ b/src/api/__tests__/api-test.js @@ -0,0 +1,18 @@ +import api, { LIMIT } from '../index'; + +describe('api', () => { + it('initialices trivia', () => { + const triviaSource = api(); + expect(triviaSource).toBeDefined(); + + for (let i = 0; i < LIMIT; i++) { + const question = triviaSource.next(); + expect(question.value._id).toBeDefined(); + expect(question.done).toBe(false); + } + + const emptyQuestion = triviaSource.next(); + expect(emptyQuestion.value).toBeUndefined(); + expect(emptyQuestion.done).toBe(true); + }); +}); diff --git a/src/components/HomeScreen/HomeScreen.js b/src/components/HomeScreen/HomeScreen.js index 0fb18bb..12629a2 100644 --- a/src/components/HomeScreen/HomeScreen.js +++ b/src/components/HomeScreen/HomeScreen.js @@ -6,7 +6,7 @@ import Page from '../Page'; import { TitleLogo } from './components'; import Styles from './HomeScreen.module.css'; -export default function HomeScreen({ navigation }) { +export default function HomeScreen() { return (
diff --git a/src/components/HomeScreen/__tests__/HomeScreen-test.js b/src/components/HomeScreen/__tests__/HomeScreen-test.js new file mode 100644 index 0000000..14e1600 --- /dev/null +++ b/src/components/HomeScreen/__tests__/HomeScreen-test.js @@ -0,0 +1,13 @@ +import React from 'react'; +import { Link } from 'react-router-dom'; + +import HomeScreen from '../HomeScreen'; + +import renderer from 'react-test-renderer'; + +describe('', () => { + it('starts trivia', () => { + const component = renderer.create(); + expect(component).toMatchSnapshot(); + }); +}); diff --git a/src/components/HomeScreen/__tests__/__snapshots__/HomeScreen-test.js.snap b/src/components/HomeScreen/__tests__/__snapshots__/HomeScreen-test.js.snap new file mode 100644 index 0000000..9019471 --- /dev/null +++ b/src/components/HomeScreen/__tests__/__snapshots__/HomeScreen-test.js.snap @@ -0,0 +1,48 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` starts trivia 1`] = ` +
+
+
+ App logo + + +
+
+
+`; diff --git a/src/components/TriviaResultScreen/__tests__/TriviaResultScreen-test.js b/src/components/TriviaResultScreen/__tests__/TriviaResultScreen-test.js new file mode 100644 index 0000000..2ff3c56 --- /dev/null +++ b/src/components/TriviaResultScreen/__tests__/TriviaResultScreen-test.js @@ -0,0 +1,61 @@ +import React from 'react'; +import Button from '@material-ui/core/Button'; +import Typography from '@material-ui/core/Typography'; +import renderer from 'react-test-renderer'; + +import TriviaResultScreen from '../TriviaResultScreen'; + +describe('', () => { + it('display as winner', () => { + const location = { + state: { + isWinner: true, + }, + }; + + const component = renderer.create( + + ); + + const textTree = component.root.findByType(Typography); + expect(textTree.props.children).toBe('Soy intelectual muy inteligente!'); + }); + + it('display as looser', () => { + const location = { + state: { + isWinner: false, + }, + }; + + const component = renderer.create( + + ); + + const textTree = component.root.findByType(Typography); + expect(textTree.props.children).toBe( + 'Eres tonto como una piedra y feo como una blasfemia' + ); + }); + + it('restarts the trivia', () => { + const history = { + push: jest.fn(), + }; + + const location = { + state: { + isWinner: true, + }, + }; + + const component = renderer.create( + + ); + + const buttonTree = component.root.findByType(Button); + + buttonTree.props.onClick(); + expect(history.push).toBeCalledWith('/'); + }); +}); diff --git a/src/components/TriviaScreen/__tests__/TriviaScreen-test.js b/src/components/TriviaScreen/__tests__/TriviaScreen-test.js new file mode 100644 index 0000000..6ab0d3d --- /dev/null +++ b/src/components/TriviaScreen/__tests__/TriviaScreen-test.js @@ -0,0 +1,32 @@ +import React from 'react'; +import renderer from 'react-test-renderer'; + +import TriviaScreen from '../TriviaScreen'; +import { AnswerOptionList } from '../components'; +import { LIMIT } from '../../../api'; + +describe('', () => { + it('render list and answer questions', () => { + jest.useFakeTimers(); + + const history = { + push: jest.fn(), + }; + + let component; + + renderer.act(() => { + component = renderer.create(); + }); + + const answerOptionList = component.root.findByType(AnswerOptionList); + + for (let i = 0; i < LIMIT; i++) { + renderer.act(() => { + const option = answerOptionList.props.options[0]; + answerOptionList.props.onOptionPress(option); + jest.runAllTimers(); + }); + } + }); +}); diff --git a/src/components/TriviaScreen/components/AnswerOptionList/__tests__/AnswerOptionsList-test.js b/src/components/TriviaScreen/components/AnswerOptionList/__tests__/AnswerOptionsList-test.js new file mode 100644 index 0000000..23881e9 --- /dev/null +++ b/src/components/TriviaScreen/components/AnswerOptionList/__tests__/AnswerOptionsList-test.js @@ -0,0 +1,24 @@ +import React from 'react'; +import Button from '@material-ui/core/Button'; +import renderer from 'react-test-renderer'; + +import AnswerOptionList from '../AnswerOptionsList'; + +describe('', () => { + it('handle option press', () => { + const onOptionPress = jest.fn(); + const options = [ + { + number: 1, + text: 'test', + }, + ]; + + const component = renderer.create( + + ); + + const buttonTree = component.root.findByType(Button); + buttonTree.props.onClick(); + }); +}); diff --git a/src/components/TriviaScreen/components/AnswerResultTitle/__tests__/AnswerResultTitle-test.js b/src/components/TriviaScreen/components/AnswerResultTitle/__tests__/AnswerResultTitle-test.js new file mode 100644 index 0000000..081901a --- /dev/null +++ b/src/components/TriviaScreen/components/AnswerResultTitle/__tests__/AnswerResultTitle-test.js @@ -0,0 +1,22 @@ +import React from 'react'; +import renderer from 'react-test-renderer'; + +import AnswerResultTitle from '../AnswerResultTitle'; + +describe('', () => { + it('renders CORRECTO!', () => { + const component = renderer.create(); + const tree = component.toJSON(); + const text = tree.children[0]; + expect(text).toBe('CORRECTO!'); + expect(tree.props.style.color).toBe('green'); + }); + + it('renders FALLASTE!', () => { + const component = renderer.create(); + const tree = component.toJSON(); + const text = tree.children[0]; + expect(text).toBe('FALLASTE!'); + expect(tree.props.style.color).toBe('red'); + }); +}); diff --git a/src/jest/ReactRouter.js b/src/jest/ReactRouter.js new file mode 100644 index 0000000..f2b40a1 --- /dev/null +++ b/src/jest/ReactRouter.js @@ -0,0 +1,13 @@ +import React from 'react'; + +jest.mock('react-router-dom', () => { + function Link({ to, ...props }) { + return diff --git a/src/components/TriviaResultScreen/TriviaResultScreen.js b/src/components/TriviaResultScreen/TriviaResultScreen.js index 1b950e0..e0c6d9d 100644 --- a/src/components/TriviaResultScreen/TriviaResultScreen.js +++ b/src/components/TriviaResultScreen/TriviaResultScreen.js @@ -11,7 +11,7 @@ export default function TriviaResultScreen({ history, location }) { }; return ( - +
{location.state.isWinner @@ -19,7 +19,12 @@ export default function TriviaResultScreen({ history, location }) { : 'Eres tonto como una piedra y feo como una blasfemia'} -
diff --git a/src/components/TriviaScreen/TriviaScreen.js b/src/components/TriviaScreen/TriviaScreen.js index 611a30a..d319413 100644 --- a/src/components/TriviaScreen/TriviaScreen.js +++ b/src/components/TriviaScreen/TriviaScreen.js @@ -43,7 +43,7 @@ export default function TriviaScreen({ history }) { }; return ( - + {currentQuestion.text} diff --git a/src/components/TriviaScreen/components/AnswerOptionList/AnswerOptionsList.js b/src/components/TriviaScreen/components/AnswerOptionList/AnswerOptionsList.js index 9dd16d2..60ad24c 100644 --- a/src/components/TriviaScreen/components/AnswerOptionList/AnswerOptionsList.js +++ b/src/components/TriviaScreen/components/AnswerOptionList/AnswerOptionsList.js @@ -8,6 +8,7 @@ export default function AnswerOptionList({ options, onOptionPress }) { return options.map(option => (