Skip to content

Commit 1adc1d3

Browse files
committed
step 4 working with tests
1 parent ebb0157 commit 1adc1d3

File tree

14 files changed

+148
-60
lines changed

14 files changed

+148
-60
lines changed

README.md

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ A [CodeRoad](https://coderoad.github.io) tutorial for learning Redux.
44

55
<!-- @import('01') -->
66
<!-- @import('02') -->
7-
<!-- @import('04') -->
7+
<!-- @import('03') -->
88
<!-- @import('05') -->
99
<!-- @import('06') -->
1010
<!-- @import('07') -->
@@ -28,23 +28,13 @@ CodeRoad is an open-sourced interactive tutorial platform for the Atom Editor. L
2828

2929
## Outline
3030

31-
##### Actions
31+
##### Reducer
3232

33-
Events that change the data.
33+
The data transformation
3434

35-
##### 1. Actions
3635
```js
37-
const action = { type: 'ACTION_NAME' };
38-
```
39-
40-
##### 2. Action Creators
41-
42-
```js
43-
const actionName = () => ({ type: 'ACTION_NAME' });
44-
```
45-
46-
##### 3. Action Types
47-
48-
```js
49-
const ACTION_NAME = 'ACTION_NAME'
36+
const reducer = (state) => {
37+
console.log(state);
38+
return state;
39+
};
5040
```

coderoad.json

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,63 @@
11
{
22
"info": {
33
"title": "CodeRoad Redux JS Tutorial",
4-
"description": "A [CodeRoad](https://coderoad.github.io) tutorial for learning Redux.\n\n<!-- @import('01') -->\n<!-- @import('02') -->\n<!-- @import('04') -->\n<!-- @import('05') -->\n<!-- @import('06') -->\n<!-- @import('07') -->\n<!-- @import('08') -->\n<!-- @import('09') -->"
4+
"description": "A [CodeRoad](https://coderoad.github.io) tutorial for learning Redux.\n\n<!-- @import('01') -->\n<!-- @import('02') -->\n<!-- @import('03') -->\n<!-- @import('05') -->\n<!-- @import('06') -->\n<!-- @import('07') -->\n<!-- @import('08') -->\n<!-- @import('09') -->"
55
},
66
"pages": [
77
{
8-
"title": "Actions",
9-
"description": "Events that change the data.\n\n##### 1. Actions\n```js\nconst action = { type: 'ACTION_NAME' };\n```\n\n##### 2. Action Creators\n\n```js\nconst actionName = () => ({ type: 'ACTION_NAME' });\n```\n\n##### 3. Action Types\n\n```js\nconst ACTION_NAME = 'ACTION_NAME'\n```",
8+
"title": "Reducer",
9+
"description": "The data transformation\n\n```js\nconst reducer = (state) => {\n console.log(state);\n return state;\n};\n```",
1010
"tasks": [
1111
{
12-
"description": "create an action called `voteUp`",
12+
"description": "Extract the `state => state` function in create store, and call in a new function called \"reducer\".",
1313
"tests": [
14-
"03/01"
14+
"04/01"
1515
],
1616
"actions": [
1717
"open('index.js')"
1818
]
1919
},
2020
{
21-
"description": "change `voteUp` into an action creator.",
21+
"description": "Log the state inside of your reducer. What does it look like?",
2222
"tests": [
23-
"03/02"
23+
"04/02"
2424
],
2525
"hints": [
26-
"wrap your output object in round brackets",
27-
"Try this: `const voteUp = () => ({ type: \"VOTE_UP\" });`"
26+
"Add a `console.log` statement inside of your reducer function",
27+
"Try this:```js\nconst reducer = (state) => {\n console.log(state);\n return state;\n};\n```"
2828
]
2929
},
3030
{
31-
"description": "add a param of `id` to your action creator",
31+
"description": "Pass an action as a second param to the reducer",
3232
"tests": [
33-
"03/03"
33+
"04/03"
3434
]
3535
},
3636
{
37-
"description": "create an action type for `voteUp`",
38-
"hints": [
39-
"const VOTE_UP = \"VOTE_UP\""
40-
],
37+
"description": "Dispatch two voteUp actions through the reducer: `store.dispatch(voteUp(2))`. Change your log statement inside of your reducer to look like this: `console.log('state: ', state, 'action: ', action)`",
4138
"tests": [
42-
"03/04"
39+
"04/04"
4340
]
4441
},
4542
{
46-
"description": "Use the action type inside your `voteUp` action creator. Notice how your editor may autocomplete the action type.",
43+
"description": "Create a `switch` statement and pass in `action.type`, the default return should return `state`",
4744
"tests": [
48-
"03/05"
49-
],
50-
"hints": [
51-
"change \"VOTE_UP\" to use the constant VOTE_UP",
52-
"Try this: `const voteUp = () => ({ type: VOTE_UP });`"
45+
"04/05"
46+
]
47+
},
48+
{
49+
"description": "The `switch` statement should have a `default` case that returns the state",
50+
"tests": [
51+
"04/06"
52+
]
53+
},
54+
{
55+
"description": "add a switch case for `VOTE_UP`. For now, just console.log the `id` of the action passed in and return the default state again.",
56+
"tests": [
57+
"04/07"
5358
]
5459
}
55-
],
56-
"onPageComplete": "Excellent! In the next unit we will look at how these actions can be used to transform data using a \"reducer\""
60+
]
5761
}
5862
]
5963
}

tutorial/03/01.js

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,4 @@
1-
var chai = require('chai');
2-
var spies = require('chai-spies');
3-
var expect = chai.expect;
4-
chai.use(spies);
5-
6-
var spy = chai.spy.on(console, 'log');
1+
const expect = require('chai').expect;
72

83
/// load('index.js')
94

tutorial/04/01.js

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,25 @@ var spies = require('chai-spies');
33
var expect = chai.expect;
44
chai.use(spies);
55

6-
var spy = chai.spy.on(console, 'log');
6+
var log = chai.spy.on(console, 'log');
77

88
/// load('index.js')
99

1010
describe('01 reducer', () => {
11+
12+
it('doesn\'t exist', () => {
13+
expect(reducer).to.be.defined;
14+
});
15+
1116
it('doesn\'t take a "state" param', () => {
12-
expect(reducer).to.have.length(1);
17+
const regex = /state/;
18+
const string = reducer.toString();
19+
expect(string).to.match(regex);
1320
});
1421

1522
it('doesn\'t return "state"', () => {
16-
expect(reducer({ a: 1 }).to.deep.equal({ a: 1 });
23+
expect(reducer('a', { type: 'ANY' })).to.equal('a');
24+
expect(reducer(1, { type: 'ANY' })).to.equal(1);
1725
});
18-
26+
1927
});

tutorial/04/02.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
11
describe('02 reducer', () => {
22

3+
it('doesn\'t have any console.log statements', () => {
4+
const regex = /console.log\(/;
5+
const string = reducer.toString();
6+
expect(string).to.match(regex);
7+
});
8+
39
});

tutorial/04/03.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
describe('03 reducer', () => {
2+
3+
it('has a second param', () => {
4+
expect(reducer).to.have.length(2);
5+
});
6+
7+
it('has a second param called "action"', () => {
8+
const regex = /action/;
9+
const string = reducer.toString();
10+
expect(string).to.match(regex);
11+
});
12+
13+
});

tutorial/04/04.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
describe('04 console.log', () => {
2+
3+
it('should be called with state and action as in the example', () => {
4+
const regex = / console.log\(\s?[\'\"]state:\s?[\'\"],\s?state,\s?[\'\"]action:\s?[\'\"],\s?action\s?\)/;
5+
const string = reducer.toString();
6+
expect(string).to.match(regex);
7+
});
8+
9+
it('should be called with the state and dispatched action twice', () => {
10+
expect(log).to.have.been.called.with('state: ', initialState, 'action: ', voteUp(2));
11+
});
12+
13+
});

tutorial/04/05.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
describe('05 reducer', () => {
2+
3+
it('should have a switch statement', () => {
4+
const regex = /switch/;
5+
const string = reducer.toString();
6+
expect(string).to.match(regex);
7+
});
8+
9+
it('should switch on a "action.type"', () => {
10+
const regex = /switch\s?\(\s?action.type\s?\)\s?\{/;
11+
const string = reducer.toString();
12+
expect(string).to.match(regex);
13+
});
14+
15+
});

tutorial/04/06.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
describe('06 reducer switch statement', () => {
2+
3+
it('should have a default case', () => {
4+
const regex = /default\:/;
5+
const string = reducer.toString();
6+
expect(string).to.match(regex);
7+
});
8+
9+
it('should return the original "default" state', () => {
10+
expect(reducer('a', { type: 'ANY' })).to.equal('a');
11+
});
12+
13+
});

tutorial/04/07.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
describe('07 reducer switch statement', () => {
2+
3+
it('should have a case for VOTE_UP', () => {
4+
const regex = /case VOTE_UP\:/;
5+
const string = reducer.toString();
6+
expect(string).to.match(regex);
7+
});
8+
9+
it('should log the dispatched id (action.payload.id)', () => {
10+
expect(log).to.be.called.with(2);
11+
});
12+
13+
});

tutorial/04/index.md

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,33 @@ const reducer = (state) => {
88
};
99
```
1010

11-
+ Create a reducer and call it as the first param in your `createStore`
11+
+ Extract the `state => state` function in create store, and call in a new function called "reducer".
1212
@test('04/01')
1313
@action(open('index.js'))
1414

15-
+ Change the state
15+
+ Log the state inside of your reducer. What does it look like?
1616
@test('04/02')
17+
@hint('Add a `console.log` statement inside of your reducer function')
18+
@hint('Try this:
19+
```js
20+
const reducer = (state) => {
21+
console.log(state);
22+
return state;
23+
};
24+
```
25+
')
1726

18-
+ Pass an action to the reducer
27+
+ Pass an action as a second param to the reducer
1928
@test('04/03')
2029

21-
+ Dispatch two voteUp actions through the reducer: `store.dispatch(voteUp(2))`
30+
+ Dispatch two voteUp actions through the reducer: `store.dispatch(voteUp(2))`. Change your log statement inside of your reducer to look like this: `console.log('state: ', state, 'action: ', action)`
2231
@test('04/04')
2332

2433
+ Create a `switch` statement and pass in `action.type`, the default return should return `state`
2534
@test('04/05')
2635

27-
+ add a switch case for `VOTE_UP`. Inside of it, console.log the `id` of the action passed in
36+
+ The `switch` statement should have a `default` case that returns the state
2837
@test('04/06')
38+
39+
+ add a switch case for `VOTE_UP`. For now, just console.log the `id` of the action passed in and return the default state again.
40+
@test('04/07')

tutorial/05/01.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
describe('01 pure function', () => {
2+
3+
});

tutorial/05/02.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
describe('02 pure function', () => {
2+
3+
});

tutorial/tutorial.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22

33
A [CodeRoad](https://coderoad.github.io) tutorial for learning Redux.
44

5-
@import('01')
6-
@import('02')
7-
@import('03')
8-
<!-- @import('04') -->
5+
<!-- @import('01') -->
6+
<!-- @import('02') -->
7+
<!-- @import('03') -->
8+
@import('04')
99
<!-- @import('05') -->
1010
<!-- @import('06') -->
1111
<!-- @import('07') -->

0 commit comments

Comments
 (0)