Lock in $30 Savings on PRO—Offer Ends Soon! ⏳
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
4
680
Testing React.js Applications
Max Stoiber
January 15, 2016
Tweet
Share
More Decks by Max Stoiber
See All by Max Stoiber
Testing React Applications
mxstbr
3
330
Styling Intro
mxstbr
3
380
Introduction to React.js
mxstbr
1
150
Styling React Applications
mxstbr
2
680
Scaling React.js Applications (short version)
mxstbr
2
420
Scaling React.js Applications
mxstbr
0
420
Offline is the new Black
mxstbr
3
1.1k
Exploring ES6
mxstbr
1
330
Other Decks in Technology
See All in Technology
AIで加速する次世代のBill Oneアーキテクチャ〜成長の先にある軌道修正〜
sansantech
PRO
1
150
IaC を使いたくないけどポリシー管理をどうにかしたい
kazzpapa3
1
180
メッセージ駆動が可能にする結合の最適化
j5ik2o
9
1.7k
不確実性に備える ABEMA の信頼性設計とオブザーバビリティ基盤
nagapad
5
9.4k
インフラ室事例集
mixi_engineers
PRO
2
110
生成AIシステムとAIエージェントに関する性能や安全性の評価
shibuiwilliam
2
270
経営から紐解くデータマネジメント
pacocat
8
1.7k
pmconf 2025 大阪「生成AI時代に未来を切り開くためのプロダクト戦略:圧倒的生産性を実現するためのプロダクトサイクロン」 / The Product Cyclone for Outstanding Productivity
yamamuteki
3
3k
『ソフトウェア』で『リアル』を動かす:クレーンゲームからデータ基盤までの統一アーキテクチャ / アーキテクチャConference 2025
genda
0
2k
命名から始めるSpec Driven
kuruwic
3
680
信頼性が求められる業務のAIAgentのアーキテクチャ設計の勘所と課題
miyatakoji
0
190
Flutter Thread Merge - Flutter Tokyo #11
itsmedreamwalker
1
110
Featured
See All Featured
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.2k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.5k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
249
1.3M
Being A Developer After 40
akosma
91
590k
KATA
mclloyd
PRO
32
15k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
508
140k
Git: the NoSQL Database
bkeepers
PRO
432
66k
Automating Front-end Workflow
addyosmani
1371
200k
A Tale of Four Properties
chriscoyier
162
23k
Testing 201, or: Great Expectations
jmmastey
46
7.8k
Bash Introduction
62gerente
615
210k
RailsConf 2023
tenderlove
30
1.3k
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