Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Testing React.js Applications
Search
Max Stoiber
January 15, 2016
Technology
740
4
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Testing React.js Applications
Max Stoiber
January 15, 2016
More Decks by Max Stoiber
See All by Max Stoiber
Testing React Applications
mxstbr
3
360
Styling Intro
mxstbr
3
400
Introduction to React.js
mxstbr
1
170
Styling React Applications
mxstbr
2
730
Scaling React.js Applications (short version)
mxstbr
2
440
Scaling React.js Applications
mxstbr
0
440
Offline is the new Black
mxstbr
3
1.1k
Exploring ES6
mxstbr
1
340
Other Decks in Technology
See All in Technology
ハーレムエンジニアリング
kazuma777777
0
150
Master Dataグループ紹介資料
sansan33
PRO
1
4.8k
ブラウザ研修 2026
recruitengineers
PRO
6
990
Forza Horizon 6 のテレメトリ機能で 自動運転に使えそうな学習データを集める話
henjin0
0
170
AWS ネットワーク構築でハマった(ハマりかけた) 5選とそこから得た教訓
nagisa53
4
210
生成 AI の基礎 〜 サンプル実装で学ぶ基本原理
enakai00
7
4.4k
【CEDEC2026】『Relink』を拡張せよ - 『GRANBLUE FANTASY: Relink - Endless Ragnarok』の開発速度と品質を守るCI運用
cygames
PRO
0
170
Flutterをカメラで動かしたかった話
sony
1
140
Sansan Engineering Unit 紹介資料
sansan33
PRO
1
4.9k
第3回しろおびセキュリティスポンサーセッション
log0417
0
180
【AG-UI × A2UI × MCP Apps】Generative UIをやさしく解説する
nrinetcom
PRO
1
120
私がブラウザを自作したくなった理由
supurazako
1
230
Featured
See All Featured
The Director’s Chair: Orchestrating AI for Truly Effective Learning
tmiket
1
270
Building Experiences: Design Systems, User Experience, and Full Site Editing
marktimemedia
0
570
Measuring & Analyzing Core Web Vitals
bluesmoon
9
950
What the history of the web can teach us about the future of AI
inesmontani
PRO
1
650
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
31
3.3k
Paper Plane (Part 1)
katiecoart
PRO
1
10k
Why You Should Never Use an ORM
jnunemaker
PRO
61
10k
Raft: Consensus for Rubyists
vanstee
141
7.6k
Bridging the Design Gap: How Collaborative Modelling removes blockers to flow between stakeholders and teams @FastFlow conf
baasie
0
640
Everyday Curiosity
cassininazir
0
280
SERP Conf. Vienna - Web Accessibility: Optimizing for Inclusivity and SEO
sarafernandez
2
1.5k
Building Better People: How to give real-time feedback that sticks.
wjessup
370
20k
Transcript
Testing React.js Applications Max Stoiber - @mxstbr
Max Stoiber Max Stoiber – @mxstbr – mxstbr.com Freelance Front-End
Developer @mxstbr
Max Stoiber – @mxstbr – mxstbr.com
TYPES Max Stoiber – @mxstbr – mxstbr.com
SYSTEM TESTING Max Stoiber – @mxstbr – mxstbr.com STRESS TESTING
PERFORMANCE TESTING USABILITY TESTING UNIT TESTING
Max Stoiber – @mxstbr – mxstbr.com UNIT TESTING UNIT TESTING
SYSTEM TESTING STRESS TESTING PERFORMANCE TESTING USABILITY TESTING
Max Stoiber – @mxstbr – mxstbr.com UNIT
Max Stoiber – @mxstbr – mxstbr.com FUNCTION COMPONENT ACTIONS STORES
WHY? Max Stoiber – @mxstbr – mxstbr.com
CATCH BUGS BEFORE THEY HAPPEN Max Stoiber – @mxstbr –
mxstbr.com
EXECUTABLE DOCUMENTATION Max Stoiber – @mxstbr – mxstbr.com
SAVE TIME Max Stoiber – @mxstbr – mxstbr.com
WRITE BETTER CODE Max Stoiber – @mxstbr – mxstbr.com
HOW? Max Stoiber – @mxstbr – mxstbr.com
MOCHA Max Stoiber – @mxstbr – mxstbr.com
Max Stoiber – @mxstbr – mxstbr.com
MJACKSON/EXPECT Max Stoiber – @mxstbr – mxstbr.com
Max Stoiber – @mxstbr – mxstbr.com
Max Stoiber – @mxstbr – mxstbr.com // add.js export function
add(x, y) { return x + y; }
Max Stoiber – @mxstbr – mxstbr.com // add.test.js import {
add } from './add.js'; import expect from 'expect'; describe('add()', () => { it('adds two numbers', () => { expect(add(2, 3)).toEqual(5); }); it('doesnt add the third number', () => { expect(add(2, 3, 5)).toEqual(add(2, 3)); }); });
Max Stoiber – @mxstbr – mxstbr.com describe('add()', () => {
it('adds two numbers', () => { expect(add(2, 3)).toEqual(5); }); it('doesnt add the third number', () => { expect(add(2, 3, 5)).toEqual(add(2, 3)); }); });
Max Stoiber – @mxstbr – mxstbr.com describe('add()', () => {
it('adds two numbers', () => { expect(add(2, 3)).toEqual(5); }); it('doesnt add the third number', () => { expect(add(2, 3, 5)).toEqual(add(2, 3)); }); });
Max Stoiber – @mxstbr – mxstbr.com describe('add()', () => {
it('adds two numbers', () => { expect(add(2, 3)).toEqual(5); }); it('doesnt add the third number', () => { expect(add(2, 3, 5)).toEqual(add(2, 3)); }); });
Max Stoiber – @mxstbr – mxstbr.com describe('add()', () => {
it('adds two numbers', () => { expect(add(2, 3)).toEqual(5); }); it('doesnt add the third number', () => { expect(add(2, 3, 5)).toEqual(add(2, 3)); }); });
Max Stoiber – @mxstbr – mxstbr.com describe('add()', () => {
it('adds two numbers', () => { expect(add(2, 3)).toEqual(5); }); it('doesnt add the third number', () => { expect(add(2, 3, 5)).toEqual(add(2, 3)); }); });
Max Stoiber – @mxstbr – mxstbr.com
Max Stoiber – @mxstbr – mxstbr.com // add.js export function
add(x, y) { return x + y; }
Max Stoiber – @mxstbr – mxstbr.com // add.js export function
add(x, y) { return x + y; x * y; }
Max Stoiber – @mxstbr – mxstbr.com
Max Stoiber – @mxstbr – mxstbr.com
REDUX Max Stoiber – @mxstbr – mxstbr.com
NavBar ├── NavBar.react.js # React component │ ├── NavBar.actions.js #
Actions ├── NavBar.constants.js # Constants ├── NavBar.reducer.js # Reducer │ ├── NavBar.actions.test.js # Actions tests └── NavBar.reducer.test.js # Reducer tests Max Stoiber – @mxstbr – mxstbr.com
ACTIONS Max Stoiber – @mxstbr – mxstbr.com
Max Stoiber – @mxstbr – mxstbr.com // NavBar.actions.js import {
TOGGLE_NAV } from './NavBar.constants.js'; export function toggleNav() { return { type: TOGGLE_NAV }; }
Max Stoiber – @mxstbr – mxstbr.com // NavBar.actions.test.js import {
toggleNav } from './NavBar.actions'; import { TOGGLE_NAV } from './NavBar.constants'; import expect from ‘expect'; describe('NavBar actions', () => { });
Max Stoiber – @mxstbr – mxstbr.com describe('NavBar actions', () =>
{ describe('toggleNav', () => { it('should return the correct constant', () => { expect(toggleNav()).toEqual({ type: TOGGLE_NAV }); }); }); });
Max Stoiber – @mxstbr – mxstbr.com describe('NavBar actions', () =>
{ describe('toggleNav', () => { it('should return the correct constant', () => { expect(toggleNav()).toEqual({ type: TOGGLE_NAV }); }); }); });
Max Stoiber – @mxstbr – mxstbr.com describe('NavBar actions', () =>
{ describe('toggleNav', () => { it('should return the correct constant', () => { expect(toggleNav()).toEqual({ type: TOGGLE_NAV }); }); }); });
Max Stoiber – @mxstbr – mxstbr.com describe('NavBar actions', () =>
{ describe('toggleNav', () => { it('should return the correct constant', () => { expect(toggleNav()).toEqual({ type: TOGGLE_NAV }); }); }); });
Max Stoiber – @mxstbr – mxstbr.com describe('NavBar actions', () =>
{ describe('toggleNav', () => { it('should return the correct constant', () => { expect(toggleNav()).toEqual({ type: TOGGLE_NAV }); }); }); });
Max Stoiber – @mxstbr – mxstbr.com
REDUCER Max Stoiber – @mxstbr – mxstbr.com
Max Stoiber – @mxstbr – mxstbr.com // NavBar.reducer.js import {
TOGGLE_NAV } from ‘./NavBar.constants.js'; const initialState = { open: false }; export default function NavBarReducer(state = initialState, action) { switch (action.type) { case TOGGLE_NAV: return Object.assign({}, state, { open: !state.open }); default: return state; } }
Max Stoiber – @mxstbr – mxstbr.com // NavBar.reducer.test.js import expect
from 'expect'; import NavBarReducer from './NavBar.reducer'; import { TOGGLE_NAV } from './NavBar.constants'; import { toggleNav } from './NavBar.actions'; describe('NavBarReducer', () => { it('returns the initial state', () => {}); it('handles the toggleNav action', () => {}); });
Max Stoiber – @mxstbr – mxstbr.com describe('NavBarReducer', () => {
it('returns the initial state', () => { expect(NavBarReducer(undefined, {})).toEqual({ open: false }); }); it('handles the toggleNav action', () => { expect(NavBarReducer(undefined, toggleNav())).toEqual({ open: true }); }); });
Max Stoiber – @mxstbr – mxstbr.com describe('NavBarReducer', () => {
it('returns the initial state', () => { expect(NavBarReducer(undefined, {})).toEqual({ open: false }); }); it('handles the toggleNav action', () => { expect(NavBarReducer(undefined, toggleNav())).toEqual({ open: true }); }); });
Max Stoiber – @mxstbr – mxstbr.com describe('NavBarReducer', () => {
it('returns the initial state', () => { expect(NavBarReducer(undefined, {})).toEqual({ open: false }); }); it('handles the toggleNav action', () => { expect(NavBarReducer(undefined, toggleNav())).toEqual({ open: true }); }); });
Max Stoiber – @mxstbr – mxstbr.com describe('NavBarReducer', () => {
it('returns the initial state', () => { expect(NavBarReducer(undefined, {})).toEqual({ open: false }); }); it('handles the toggleNav action', () => { expect(NavBarReducer(undefined, toggleNav())).toEqual({ open: true }); }); });
Max Stoiber – @mxstbr – mxstbr.com describe('NavBarReducer', () => {
it('returns the initial state', () => { expect(NavBarReducer(undefined, {})).toEqual({ open: false }); }); it('handles the toggleNav action', () => { expect(NavBarReducer(undefined, toggleNav())).toEqual({ open: true }); }); });
Max Stoiber – @mxstbr – mxstbr.com describe('NavBarReducer', () => {
it('returns the initial state', () => { expect(NavBarReducer(undefined, {})).toEqual({ open: false }); }); it('handles the toggleNav action', () => { expect(NavBarReducer(undefined, toggleNav())).toEqual({ open: true }); }); });
Max Stoiber – @mxstbr – mxstbr.com describe('NavBarReducer', () => {
it('returns the initial state', () => { expect(NavBarReducer(undefined, {})).toEqual({ open: false }); }); it('handles the toggleNav action', () => { expect(NavBarReducer(undefined, toggleNav())).toEqual({ open: true }); }); });
Max Stoiber – @mxstbr – mxstbr.com
Max Stoiber – @mxstbr – mxstbr.com
AIRBNB/ENZYME Max Stoiber – @mxstbr – mxstbr.com
AIRBNB/ENZYME Max Stoiber – @mxstbr – mxstbr.com
Max Stoiber – @mxstbr – mxstbr.com // Button.react.js import React
from 'react'; class Button extends React.Component { render() { return ( <button className="btn" onClick={this.props.onClick}> { this.props.children } </button> ); } } export default Button;
Max Stoiber – @mxstbr – mxstbr.com <Button onClick={this._click}>Click me!</Button>
Max Stoiber – @mxstbr – mxstbr.com <button>Click me!</button>
Max Stoiber – @mxstbr – mxstbr.com // Button.test.js import Button
from './Button.react'; import expect from 'expect'; import { shallow } from 'enzyme'; import React from 'react'; describe('<Button />', () => { it('renders a <button>', () => {}); it('renders text', () => {}); it('handles clicks', () => {}); });
Max Stoiber – @mxstbr – mxstbr.com // Button.test.js import Button
from './Button.react'; import expect from 'expect'; import { shallow } from 'enzyme'; import React from 'react'; describe('<Button />', () => { it('renders a <button>', () => {}); it('renders text', () => {}); it('handles clicks', () => {}); });
SHALLOW RENDERING Max Stoiber – @mxstbr – mxstbr.com
ONE LEVEL DEEP Max Stoiber – @mxstbr – mxstbr.com
Max Stoiber – @mxstbr – mxstbr.com <div> <span className=“heading">Title</span> <Subcomponent
/> </div>
Max Stoiber – @mxstbr – mxstbr.com <div> <span class=“heading">Title</span> <div></div>
</div> NORMAL RENDERING
Max Stoiber – @mxstbr – mxstbr.com <div> <span class=“heading">Title</span> <Subcomponent
/> </div> SHALLOW RENDERING
Max Stoiber – @mxstbr – mxstbr.com // Button.test.js import Button
from './Button.react'; import expect from 'expect'; import { shallow } from 'enzyme'; import React from 'react'; describe('<Button />', () => { it('renders a <button>', () => {}); it('renders text', () => {}); it('handles clicks', () => {}); });
Max Stoiber – @mxstbr – mxstbr.com describe('<Button />', () =>
{ it('renders a <button>', () => { const renderedComponent = shallow( <Button></Button> ); expect( renderedComponent.find("button").node ).toExist(); }); });
Max Stoiber – @mxstbr – mxstbr.com describe('<Button />', () =>
{ it('renders a <button>', () => { const renderedComponent = shallow( <Button></Button> ); expect( renderedComponent.find("button").node ).toExist(); }); });
Max Stoiber – @mxstbr – mxstbr.com describe('<Button />', () =>
{ it('renders a <button>', () => { const renderedComponent = shallow( <Button></Button> ); expect( renderedComponent.find("button").node ).toExist(); }); });
Max Stoiber – @mxstbr – mxstbr.com describe('<Button />', () =>
{ it('renders a <button>', () => { const renderedComponent = shallow( <Button></Button> ); expect( renderedComponent.find("button").node ).toExist(); }); });
Max Stoiber – @mxstbr – mxstbr.com describe('<Button />', () =>
{ it('renders text', () => { const text = "Click me!"; const renderedComponent = shallow( <Button>{ text }</Button> ); expect( renderedComponent.contains(text) ).toEqual(true); }); });
Max Stoiber – @mxstbr – mxstbr.com describe('<Button />', () =>
{ it('renders text', () => { const text = "Click me!"; const renderedComponent = shallow( <Button>{ text }</Button> ); expect( renderedComponent.contains(text) ).toEqual(true); }); });
Max Stoiber – @mxstbr – mxstbr.com describe('<Button />', () =>
{ it('renders text', () => { const text = "Click me!"; const renderedComponent = shallow( <Button>{ text }</Button> ); expect( renderedComponent.contains(text) ).toEqual(true); }); });
Max Stoiber – @mxstbr – mxstbr.com describe('<Button />', () =>
{ it('renders text', () => { const text = "Click me!"; const renderedComponent = shallow( <Button>{ text }</Button> ); expect( renderedComponent.contains(text) ).toEqual(true); }); });
Max Stoiber – @mxstbr – mxstbr.com describe('<Button />', () =>
{ it('renders text', () => { const text = "Click me!"; const renderedComponent = shallow( <Button>{ text }</Button> ); expect( renderedComponent.contains(text) ).toEqual(true); }); });
Max Stoiber – @mxstbr – mxstbr.com describe('<Button />', () =>
{ it('handles clicks', () => { const onClickSpy = expect.createSpy(); const renderedComponent = shallow( <Button onClick={onClickSpy} /> ); renderedComponent.find('button').simulate('click'); expect(onClickSpy).toHaveBeenCalled(); }); });
Max Stoiber – @mxstbr – mxstbr.com describe('<Button />', () =>
{ it('handles clicks', () => { const onClickSpy = expect.createSpy(); const renderedComponent = shallow( <Button onClick={onClickSpy} /> ); renderedComponent.find('button').simulate('click'); expect(onClickSpy).toHaveBeenCalled(); }); });
Max Stoiber – @mxstbr – mxstbr.com describe('<Button />', () =>
{ it('handles clicks', () => { const onClickSpy = expect.createSpy(); const renderedComponent = shallow( <Button onClick={onClickSpy} /> ); renderedComponent.find('button').simulate('click'); expect(onClickSpy).toHaveBeenCalled(); }); });
Max Stoiber – @mxstbr – mxstbr.com describe('<Button />', () =>
{ it('handles clicks', () => { const onClickSpy = expect.createSpy(); const renderedComponent = shallow( <Button onClick={onClickSpy} /> ); renderedComponent.find('button').simulate('click'); expect(onClickSpy).toHaveBeenCalled(); }); });
Max Stoiber – @mxstbr – mxstbr.com describe('<Button />', () =>
{ it('handles clicks', () => { const onClickSpy = expect.createSpy(); const renderedComponent = shallow( <Button onClick={onClickSpy} /> ); renderedComponent.find('button').simulate('click'); expect(onClickSpy).toHaveBeenCalled(); }); });
Max Stoiber – @mxstbr – mxstbr.com
@mxstbr Max Stoiber – @mxstbr – mxstbr.com HTTPS://GITHUB.COM/MXSTBR/REACT-TESTING