Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4,568 changes: 2,548 additions & 2,020 deletions examples/todomvc/package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions examples/todomvc/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"react-redux": "^5.0.5",
"react-test-renderer": "^15.5.4",
"redux": "^3.5.2",
"reselect": "^3.0.1",
"todomvc-app-css": "^2.1.0"
},
"scripts": {
Expand Down
3 changes: 2 additions & 1 deletion examples/todomvc/src/actions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ export const addTodo = text => ({ type: types.ADD_TODO, text })
export const deleteTodo = id => ({ type: types.DELETE_TODO, id })
export const editTodo = (id, text) => ({ type: types.EDIT_TODO, id, text })
export const completeTodo = id => ({ type: types.COMPLETE_TODO, id })
export const completeAll = () => ({ type: types.COMPLETE_ALL })
export const completeAllTodos = () => ({ type: types.COMPLETE_ALL_TODOS })
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the rename? Seems like the context is obvious here regardless.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it is obvious. I just feel having Todos attached to the completeAll will make it much more explicit and consistent with the others.

export const clearCompleted = () => ({ type: types.CLEAR_COMPLETED })
export const setVisibilityFilter = filter => ({ type: types.SET_VISIBILITY_FILTER, filter})
4 changes: 2 additions & 2 deletions examples/todomvc/src/actions/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ describe('todo actions', () => {
})

it('completeAll should create COMPLETE_ALL action', () => {
expect(actions.completeAll()).toEqual({
type: types.COMPLETE_ALL
expect(actions.completeAllTodos()).toEqual({
type: types.COMPLETE_ALL_TODOS
})
})

Expand Down
12 changes: 12 additions & 0 deletions examples/todomvc/src/components/App.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from 'react'
import Header from '../containers/Header'
import MainSection from '../containers/MainSection'

const App = () => (
<div>
<Header />
<MainSection />
</div>
)

export default App
31 changes: 31 additions & 0 deletions examples/todomvc/src/components/App.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React from 'react'
import { createRenderer } from 'react-test-renderer/shallow'
import App from './App'
import Header from '../containers/Header'
import MainSection from '../containers/MainSection'


const setup = propOverrides => {
const renderer = createRenderer()
renderer.render(<App />)
const output = renderer.getRenderOutput()
return output
}

describe('components', () => {
describe('Header', () => {
it('should render', () => {
const output = setup()
const [ header ] = output.props.children
expect(header.type).toBe(Header)
})
})

describe('Mainsection', () => {
it('should render', () => {
const output = setup()
const [ , mainSection ] = output.props.children
expect(mainSection.type).toBe(MainSection)
})
})
})
91 changes: 33 additions & 58 deletions examples/todomvc/src/components/Footer.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { Component } from 'react'
import React from 'react'
import PropTypes from 'prop-types'
import classnames from 'classnames'
import FilterLink from '../containers/FilterLink'
import { SHOW_ALL, SHOW_COMPLETED, SHOW_ACTIVE } from '../constants/TodoFilters'

const FILTER_TITLES = {
Expand All @@ -9,64 +9,39 @@ const FILTER_TITLES = {
[SHOW_COMPLETED]: 'Completed'
}

export default class Footer extends Component {
static propTypes = {
completedCount: PropTypes.number.isRequired,
activeCount: PropTypes.number.isRequired,
filter: PropTypes.string.isRequired,
onClearCompleted: PropTypes.func.isRequired,
onShow: PropTypes.func.isRequired
}

renderTodoCount() {
const { activeCount } = this.props
const itemWord = activeCount === 1 ? 'item' : 'items'

return (
const Footer = (props) => {
const { activeCount, completedCount, onClearCompleted } = props
const itemWord = activeCount === 1 ? 'item' : 'items'
return (
<footer className="footer">
<span className="todo-count">
<strong>{activeCount || 'No'}</strong> {itemWord} left
</span>
)
}

renderFilterLink(filter) {
const title = FILTER_TITLES[filter]
const { filter: selectedFilter, onShow } = this.props

return (
<a className={classnames({ selected: filter === selectedFilter })}
style={{ cursor: 'pointer' }}
onClick={() => onShow(filter)}>
{title}
</a>
)
}

renderClearButton() {
const { completedCount, onClearCompleted } = this.props
if (completedCount > 0) {
return (
<button className="clear-completed"
onClick={onClearCompleted} >
Clear completed
</button>
)
}
}
<ul className="filters">
{Object.keys(FILTER_TITLES).map(filter =>
<li key={filter}>
<FilterLink filter={filter}>
{FILTER_TITLES[filter]}
</FilterLink>
</li>
)}
</ul>
{
!!completedCount &&
<button
className="clear-completed"
onClick={onClearCompleted}
>Clear completed</button>

}
</footer>
)
}

render() {
return (
<footer className="footer">
{this.renderTodoCount()}
<ul className="filters">
{[ SHOW_ALL, SHOW_ACTIVE, SHOW_COMPLETED ].map(filter =>
<li key={filter}>
{this.renderFilterLink(filter)}
</li>
)}
</ul>
{this.renderClearButton()}
</footer>
)
}
Footer.propTypes = {
completedCount: PropTypes.number.isRequired,
activeCount: PropTypes.number.isRequired,
onClearCompleted: PropTypes.func.isRequired,
}

export default Footer
27 changes: 9 additions & 18 deletions examples/todomvc/src/components/Footer.spec.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import React from 'react'
import { createRenderer } from 'react-test-renderer/shallow';
import Footer from './Footer'
import { SHOW_ALL, SHOW_ACTIVE } from '../constants/TodoFilters'
import FilterLink from '../containers/FilterLink'
import { SHOW_ALL, SHOW_ACTIVE, SHOW_COMPLETED } from '../constants/TodoFilters'

const setup = propOverrides => {
const props = Object.assign({
completedCount: 0,
activeCount: 0,
filter: SHOW_ALL,
onClearCompleted: jest.fn(),
onShow: jest.fn()
}, propOverrides)

const renderer = createRenderer()
Expand Down Expand Up @@ -54,6 +53,8 @@ describe('components', () => {
})

it('should render filters', () => {
const todoFilters = [SHOW_ALL, SHOW_ACTIVE, SHOW_COMPLETED]
const filterTitles = ['All', 'Active', 'Completed']
const { output } = setup()
const [ , filters ] = output.props.children
expect(filters.type).toBe('ul')
Expand All @@ -62,33 +63,23 @@ describe('components', () => {
filters.props.children.forEach(function checkFilter(filter, i) {
expect(filter.type).toBe('li')
const a = filter.props.children
expect(a.props.className).toBe(i === 0 ? 'selected' : '')
expect(a.props.children).toBe({
0: 'All',
1: 'Active',
2: 'Completed'
}[i])
expect(a.type).toBe(FilterLink)
expect(a.props.filter).toBe(todoFilters[i])
expect(a.props.children).toBe(filterTitles[i])
})
})

it('should call onShow when a filter is clicked', () => {
const { output, props } = setup()
const [ , filters ] = output.props.children
const filterLink = filters.props.children[1].props.children
filterLink.props.onClick({})
expect(props.onShow).toBeCalledWith(SHOW_ACTIVE)
})

it('shouldnt show clear button when no completed todos', () => {
const { output } = setup({ completedCount: 0 })
const [ , , clear ] = output.props.children
expect(clear).toBe(undefined)
expect(clear).toBe(false)
})

it('should render clear button when completed todos', () => {
const { output } = setup({ completedCount: 1 })
const [ , , clear ] = output.props.children
expect(clear.type).toBe('button')
expect(clear.props.className).toBe('clear-completed')
expect(clear.props.children).toBe('Clear completed')
})

Expand Down
26 changes: 0 additions & 26 deletions examples/todomvc/src/components/Header.js

This file was deleted.

23 changes: 23 additions & 0 deletions examples/todomvc/src/components/Link.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from 'react'
import PropTypes from 'prop-types'
import classnames from 'classnames'

const Link = ({ active, children, setFilter }) =>
(
<a
className={classnames({ selected: active })}
style={{ cursor: 'pointer' }}
onClick={() => setFilter()}
>
{children}
</a>
)


Link.propTypes = {
active: PropTypes.bool.isRequired,
children: PropTypes.node.isRequired,
setFilter: PropTypes.func.isRequired
}

export default Link
42 changes: 42 additions & 0 deletions examples/todomvc/src/components/Link.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React from 'react'
import { createRenderer } from 'react-test-renderer/shallow';
import Link from './Link'

const setup = (propOverrides) => {
const props = Object.assign({
active: false,
children: 'All',
setFilter: jest.fn()
}, propOverrides)

const renderer = createRenderer();
renderer.render(<Link {...props} />)
const output = renderer.getRenderOutput()

return {
props: props,
output: output,
}
}

describe('component', () => {
describe('Link', () => {
it('should render correctly', () => {
const { output } = setup()
expect(output.type).toBe('a')
expect(output.props.style.cursor).toBe('pointer')
expect(output.props.children).toBe('All')
})

it('should have class selected if active', () => {
const { output } = setup({ active: true })
expect(output.props.className).toBe('selected')
})

it('should call setFilter on click', () => {
const { output, props } = setup()
output.props.onClick()
expect(props.setFilter).toBeCalled()
})
})
})
Loading