Speedometer: Add a React + Redux TodoMVC implementation
[WebKit-https.git] / PerformanceTests / Speedometer / resources / todomvc / architecture-examples / react-redux / src / components / TodoItem.spec.js
1 import React from 'react'
2 import TestUtils from 'react-addons-test-utils'
3 import TodoItem from './TodoItem'
4 import TodoTextInput from './TodoTextInput'
5
6 const setup = ( editing = false ) => {
7   const props = {
8     todo: {
9       id: 0,
10       text: 'Use Redux',
11       completed: false
12     },
13     editTodo: jest.fn(),
14     deleteTodo: jest.fn(),
15     completeTodo: jest.fn()
16   }
17
18   const renderer = TestUtils.createRenderer()
19
20   renderer.render(
21     <TodoItem {...props} />
22   )
23
24   let output = renderer.getRenderOutput()
25
26   if (editing) {
27     const label = output.props.children.props.children[1]
28     label.props.onDoubleClick({})
29     output = renderer.getRenderOutput()
30   }
31
32   return {
33     props: props,
34     output: output,
35     renderer: renderer
36   }
37 }
38
39 describe('components', () => {
40   describe('TodoItem', () => {
41     it('initial render', () => {
42       const { output } = setup()
43
44       expect(output.type).toBe('li')
45       expect(output.props.className).toBe('')
46
47       const div = output.props.children
48
49       expect(div.type).toBe('div')
50       expect(div.props.className).toBe('view')
51
52       const [ input, label, button ] = div.props.children
53
54       expect(input.type).toBe('input')
55       expect(input.props.checked).toBe(false)
56
57       expect(label.type).toBe('label')
58       expect(label.props.children).toBe('Use Redux')
59
60       expect(button.type).toBe('button')
61       expect(button.props.className).toBe('destroy')
62     })
63
64     it('input onChange should call completeTodo', () => {
65       const { output, props } = setup()
66       const input = output.props.children.props.children[0]
67       input.props.onChange({})
68       expect(props.completeTodo).toBeCalledWith(0)
69     })
70
71     it('button onClick should call deleteTodo', () => {
72       const { output, props } = setup()
73       const button = output.props.children.props.children[2]
74       button.props.onClick({})
75       expect(props.deleteTodo).toBeCalledWith(0)
76     })
77
78     it('label onDoubleClick should put component in edit state', () => {
79       const { output, renderer } = setup()
80       const label = output.props.children.props.children[1]
81       label.props.onDoubleClick({})
82       const updated = renderer.getRenderOutput()
83       expect(updated.type).toBe('li')
84       expect(updated.props.className).toBe('editing')
85     })
86
87     it('edit state render', () => {
88       const { output } = setup(true)
89
90       expect(output.type).toBe('li')
91       expect(output.props.className).toBe('editing')
92
93       const input = output.props.children
94       expect(input.type).toBe(TodoTextInput)
95       expect(input.props.text).toBe('Use Redux')
96       expect(input.props.editing).toBe(true)
97     })
98
99     it('TodoTextInput onSave should call editTodo', () => {
100       const { output, props } = setup(true)
101       output.props.children.props.onSave('Use Redux')
102       expect(props.editTodo).toBeCalledWith(0, 'Use Redux')
103     })
104
105     it('TodoTextInput onSave should call deleteTodo if text is empty', () => {
106       const { output, props } = setup(true)
107       output.props.children.props.onSave('')
108       expect(props.deleteTodo).toBeCalledWith(0)
109     })
110
111     it('TodoTextInput onSave should exit component from edit state', () => {
112       const { output, renderer } = setup(true)
113       output.props.children.props.onSave('Use Redux')
114       const updated = renderer.getRenderOutput()
115       expect(updated.type).toBe('li')
116       expect(updated.props.className).toBe('')
117     })
118   })
119 })