Skip to content

Commit 081d163

Browse files
committed
Added test to examples/todomvc
1 parent 0fcd6ea commit 081d163

16 files changed

+3530
-60
lines changed

examples/todomvc/package.json

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
"version": "0.0.0",
44
"description": "dop TodoMVC example",
55
"scripts": {
6-
"start": "node src/server.js"
6+
"start": "node src/server.js",
7+
"test": "react-scripts test"
78
},
89
"repository": {
910
"type": "git",
@@ -17,9 +18,10 @@
1718
"dependencies": {
1819
"babel-polyfill": "^6.3.14",
1920
"classnames": "^2.1.2",
20-
"react": "^0.14.7",
21-
"react-dom": "^0.14.7",
22-
"dop": "^0.21.0"
21+
"dop": "^0.24.0",
22+
"react": "^15.6.1",
23+
"react-dom": "^15.6.1",
24+
"style-loader": "^0.18.2"
2325
},
2426
"devDependencies": {
2527
"babel-core": "^6.3.15",
@@ -28,16 +30,12 @@
2830
"babel-preset-react": "^6.3.13",
2931
"babel-preset-react-hmre": "^1.1.1",
3032
"babel-register": "^6.3.13",
31-
"cross-env": "^1.0.7",
32-
"enzyme": "^2.2.0",
33-
"expect": "^1.8.0",
33+
"enzyme": "^2.9.1",
3434
"express": "^4.13.3",
35-
"jsdom": "^5.6.1",
36-
"mocha": "^2.2.5",
37-
"node-libs-browser": "^0.5.2",
3835
"raw-loader": "^0.5.1",
39-
"react-addons-test-utils": "^0.14.7",
40-
"style-loader": "^0.12.3",
36+
"react-addons-test-utils": "^0.14.8",
37+
"react-scripts": "^1.0.10",
38+
"react-test-renderer": "^15.6.1",
4139
"todomvc-app-css": "^2.0.1",
4240
"webpack": "^1.9.11",
4341
"webpack-dev-middleware": "^1.2.0",

examples/todomvc/src/actions.js

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
import { collect } from 'dop';
2-
import state from './state';
2+
import store from './store';
33

44
export function changeTextNewTodo(text) {
5-
state.newTodoText = text;
5+
store.newTodoText = text;
66
}
77

88
let todoIdInc = 1;
99
export function addTodo(text) {
1010
if (text.length > 0) {
1111
const collector = collect()
1212
changeTextNewTodo('')
13-
state.todos.push({
13+
store.todos.push({
1414
text: text,
1515
completed: false,
1616
id: todoIdInc++,
@@ -21,17 +21,17 @@ export function addTodo(text) {
2121
}
2222

2323
export function deleteTodo(id) {
24-
const index = state.todos.findIndex(todo => todo.id === id);
24+
const index = store.todos.findIndex(todo => todo.id === id);
2525
const collector = collect();
26-
state.todos.splice(index, 1);
26+
store.todos.splice(index, 1);
2727
collector.emit();
2828
}
2929

3030
export function editTodo(id, text) {
3131
if (text.length === 0)
3232
deleteTodo(id);
3333
else {
34-
const todo = state.todos.filter(todo => todo.id === id)[0];
34+
const todo = store.todos.filter(todo => todo.id === id)[0];
3535
const collector = collect();
3636
if (text !== todo.text)
3737
todo.text = text;
@@ -40,33 +40,33 @@ export function editTodo(id, text) {
4040
}
4141

4242
export function completeTodo(id) {
43-
const todo = state.todos.filter(todo => todo.id === id)[0];
43+
const todo = store.todos.filter(todo => todo.id === id)[0];
4444
const collector = collect();
4545
todo.completed = !todo.completed;
4646
collector.emit();
4747
}
4848

4949
export function completeAll() {
5050
const collector = collect();
51-
const areAllMarked = state.todos.every(todo => todo.completed);
52-
state.todos.forEach(todo => (todo.completed = !areAllMarked));
51+
const areAllMarked = store.todos.every(todo => todo.completed);
52+
store.todos.forEach(todo => (todo.completed = !areAllMarked));
5353
collector.emit();
5454
}
5555

5656
export function changeFilter(filter) {
57-
state.selectedFilter = filter;
57+
store.selectedFilter = filter;
5858
}
5959

6060
export function clearCompleted() {
6161
const collector = collect();
62-
const completeds = state.todos
62+
const completeds = store.todos
6363
.filter(todo => todo.completed === true)
6464
.map(todo => todo.id)
6565
.forEach(deleteTodo);
6666
collector.emit();
6767
}
6868

6969
export function editingTodo(id) {
70-
const todo = state.todos.filter(todo => todo.id === id)[0];
70+
const todo = store.todos.filter(todo => todo.id === id)[0];
7171
todo.editing = !todo.editing;
7272
}

examples/todomvc/src/components/Footer.js

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React, { PropTypes, Component } from 'react';
22
import classnames from 'classnames';
33
import { createObserver } from 'dop';
4-
import state from '../state';
4+
import store from '../store';
55
import { clearCompleted, changeFilter } from '../actions';
66
import { SHOW_ALL, SHOW_COMPLETED, SHOW_ACTIVE } from '../constants';
77

@@ -13,12 +13,10 @@ const FILTER_TITLES = {
1313

1414
export default class Footer extends Component {
1515
componentWillMount() {
16-
const observer = createObserver(mutations => {
17-
this.forceUpdate();
18-
});
19-
observer.observe(state, 'itemsLeftCount');
20-
observer.observe(state, 'selectedFilter');
21-
observer.observe(state, 'completedCount');
16+
const observer = createObserver(m => this.forceUpdate());
17+
observer.observe(store, 'itemsLeftCount');
18+
observer.observe(store, 'selectedFilter');
19+
observer.observe(store, 'completedCount');
2220
}
2321

2422
shouldComponentUpdate() {
@@ -28,9 +26,9 @@ export default class Footer extends Component {
2826
render() {
2927
return (
3028
<FooterTemplate
31-
activeCount={state.itemsLeftCount}
32-
completedCount={state.completedCount}
33-
selectedFilter={state.selectedFilter}
29+
activeCount={store.itemsLeftCount}
30+
completedCount={store.completedCount}
31+
selectedFilter={store.selectedFilter}
3432
onChangeFilter={changeFilter}
3533
onClearCompleted={clearCompleted}
3634
/>
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import React from 'react'
2+
import renderer from 'react-test-renderer';
3+
import Footer from './Footer'
4+
import { addTodo, completeTodo } from '../actions'
5+
6+
let component
7+
test('Checking item lefts', () => {
8+
component = renderer.create(
9+
<Footer />
10+
);
11+
let tree = component.toJSON();
12+
expect(tree).toMatchSnapshot();
13+
14+
// No items left
15+
expect(tree.children[0].children[2]).toBe('items')
16+
expect(tree.children[0].children[0].children[0]).toBe('No')
17+
18+
// Adding todo manually
19+
const labelnewtodo = 'My new todo'
20+
addTodo(labelnewtodo)
21+
tree = component.toJSON();
22+
expect(tree).toMatchSnapshot();
23+
24+
// 1 item left
25+
expect(tree.children[0].children[2]).toBe('item')
26+
expect(tree.children[0].children[0].children[0]).toBe(1)
27+
28+
// Adding todo manually
29+
addTodo('My new todo 2')
30+
tree = component.toJSON();
31+
expect(tree).toMatchSnapshot();
32+
33+
// 2 item left
34+
expect(tree.children[0].children[2]).toBe('items')
35+
expect(tree.children[0].children[0].children[0]).toBe(2)
36+
37+
// Completing todo manually
38+
completeTodo(1)
39+
tree = component.toJSON();
40+
expect(tree).toMatchSnapshot();
41+
42+
// 1 item left
43+
expect(tree.children[0].children[2]).toBe('item')
44+
expect(tree.children[0].children[0].children[0]).toBe(1)
45+
});
46+

examples/todomvc/src/components/Header.js

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,15 @@
11
import React, { Component, PropTypes } from 'react';
22
import { createObserver } from 'dop';
3-
import state from '../state';
3+
import store from '../store';
44
import { changeTextNewTodo, addTodo, completeAll } from '../actions';
55

66

77
export default class Header extends Component {
88
componentWillMount() {
9-
const observer = createObserver(mutations => {
10-
this.forceUpdate();
11-
});
12-
observer.observe(state.todos, 'length');
13-
observer.observe(state, 'newTodoText');
14-
observer.observe(state, 'areAllItemsCompleted');
9+
const observer = createObserver(m => this.forceUpdate());
10+
observer.observe(store.todos, 'length');
11+
observer.observe(store, 'newTodoText');
12+
observer.observe(store, 'areAllItemsCompleted');
1513
}
1614

1715
shouldComponentUpdate() {
@@ -30,12 +28,12 @@ export default class Header extends Component {
3028
render() {
3129
return (
3230
<HeaderTemplate
33-
value={state.newTodoText}
34-
todosLength={state.todos.length}
31+
value={store.newTodoText}
32+
todosLength={store.todos.length}
3533
onChangeText={this.onChangeText}
3634
onSave={this.onSave}
3735
onCompleteAll={completeAll}
38-
areAllItemsCompleted={state.areAllItemsCompleted}
36+
areAllItemsCompleted={store.areAllItemsCompleted}
3937
/>
4038
);
4139
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import React from 'react'
2+
import renderer from 'react-test-renderer';
3+
import Header from './Header'
4+
5+
6+
test('Adding a new todo', () => {
7+
const component = renderer.create(
8+
<Header />
9+
);
10+
let tree = component.toJSON();
11+
expect(tree).toMatchSnapshot();
12+
13+
// manually changed input new todo
14+
let newtodotext = "New todo"
15+
tree.children[1].props.onChange({target:{value:newtodotext}})
16+
// re-rendering
17+
tree = component.toJSON();
18+
expect( tree.children[1].props.value).toBe(newtodotext)
19+
20+
// saving new todo manually
21+
tree.children[1].props.onKeyDown({which:13,target:{value:newtodotext}})
22+
// re-rendering
23+
tree = component.toJSON();
24+
expect(tree.children[1].props.value).toBe("")
25+
expect(tree).toMatchSnapshot();
26+
});
27+

examples/todomvc/src/components/TodoItem.js

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React, { Component, PropTypes } from 'react';
22
import classnames from 'classnames';
33
import { createObserver, getObjectPath } from 'dop';
4-
import state from '../state';
4+
import store from '../store';
55
import { editTodo, completeTodo, deleteTodo, editingTodo } from '../actions';
66

77
export default class TodoItem extends Component {
@@ -16,17 +16,15 @@ export default class TodoItem extends Component {
1616
}
1717

1818
componentWillMount() {
19-
this.todo = state.todos[this.props.index]
20-
this.observer = createObserver(() => {
21-
this.forceUpdate()
22-
});
19+
this.todo = store.todos[this.props.index]
20+
this.observer = createObserver(m => this.forceUpdate());
2321
this.unobserveTodo = this.observer.observe(this.todo)
2422
}
2523

2624
shouldComponentUpdate(nextProps) {
2725
if (nextProps.index !== this.props.index) {
2826
this.unobserveTodo()
29-
this.todo = state.todos[nextProps.index]
27+
this.todo = store.todos[nextProps.index]
3028
this.unobserveTodo = this.observer.observe(this.todo)
3129
}
3230
return false;
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import React from 'react'
2+
import renderer from 'react-test-renderer';
3+
import TodoItem from './TodoItem'
4+
import { addTodo, editTodo } from '../actions'
5+
import store from '../store'
6+
7+
let component
8+
let idtodo = 1
9+
let indextodo = 0
10+
test('Adding a new todo', () => {
11+
// Adding todo manually
12+
const labelnewtodo = 'My new todo'
13+
addTodo(labelnewtodo)
14+
15+
component = renderer.create(
16+
<TodoItem index={indextodo} />
17+
);
18+
let tree = component.toJSON();
19+
expect(tree).toMatchSnapshot();
20+
let labelcomponent = tree.children[0].children[1]
21+
expect(labelcomponent.type).toBe('label')
22+
expect(labelcomponent.children[0]).toBe(labelnewtodo)
23+
});
24+
25+
26+
test('Editing todo', () => {
27+
const labelnewtodo = 'Label changed'
28+
editTodo(idtodo, 'Label changed')
29+
let tree = component.toJSON();
30+
expect(tree).toMatchSnapshot();
31+
let labelcomponent = tree.children[0].children[1]
32+
expect(labelcomponent.children[0]).toBe(labelnewtodo)
33+
tree = component.toJSON();
34+
expect(tree).toMatchSnapshot();
35+
});

examples/todomvc/src/components/Todos.js

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React, { Component, PropTypes } from 'react';
22
import { createObserver } from 'dop';
3-
import state from '../state';
3+
import store from '../store';
44
import { completeAll } from '../actions';
55
import { SHOW_ALL, SHOW_COMPLETED, SHOW_ACTIVE } from '../constants';
66
import TodoItem from './TodoItem';
@@ -13,12 +13,10 @@ const TODO_FILTERS = {
1313

1414
export default class Todos extends Component {
1515
componentWillMount() {
16-
const observer = createObserver(mutations => {
17-
this.forceUpdate();
18-
});
19-
observer.observe(state.todos, 'length');
20-
observer.observe(state, 'selectedFilter');
21-
observer.observe(state, 'itemsLeftCount');
16+
const observer = createObserver(m => this.forceUpdate());
17+
observer.observe(store.todos, 'length');
18+
observer.observe(store, 'selectedFilter');
19+
observer.observe(store, 'itemsLeftCount');
2220
}
2321

2422
shouldComponentUpdate() {
@@ -28,8 +26,8 @@ export default class Todos extends Component {
2826
render() {
2927
return (
3028
<TodosTemplate
31-
todos={state.todos}
32-
selectedFilter={state.selectedFilter}
29+
todos={store.todos}
30+
selectedFilter={store.selectedFilter}
3331
todoFilters={TODO_FILTERS}
3432
onCompleteAll={completeAll}
3533
/>

0 commit comments

Comments
 (0)