Skip to content

Commit 6237dbc

Browse files
authored
Unit tests for issue #149 (#153)
* fix(select): Chained actions and Injectables * fix #149 - chained actions should not get stale state, changed to create an observable from redux since redux 3.4x supports an observable shim * fix #138 - ability to use select decorators in service Changing to use redux's observable, had to change how we created the initial observable. Use switchMap to switch streams once the store observable becomes available * fix(ngRedux): Add filter operator * Add linting back * Remove commented out code
1 parent 5e6c75c commit 6237dbc

File tree

12 files changed

+426
-32
lines changed

12 files changed

+426
-32
lines changed
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { NgRedux } from 'ng2-redux';
2+
3+
export const SEARCH_ACTIONS = {
4+
SEARCH: 'SEARCH',
5+
SEARCH_RESULT: 'SEARCH_RESULT',
6+
TERMINATE: 'TERMINATE',
7+
SEARCH_NEXT: 'SEARCH_NEXT',
8+
SEARCH_PREVIOUS: 'SEARCH_PREVIOUS'
9+
};
10+
11+
import { Injectable } from '@angular/core';
12+
@Injectable()
13+
export class SearchActions {
14+
constructor(private ngRedux: NgRedux<any>) {}
15+
16+
searchDispatch(keyword: string) {
17+
this.ngRedux.dispatch(this.search(keyword));
18+
}
19+
20+
fetchResultDispatch(total: number) {
21+
this.ngRedux.dispatch(this.fetchResult(total));
22+
}
23+
24+
private search(keyword: string) {
25+
return {
26+
type: SEARCH_ACTIONS.SEARCH,
27+
payload: keyword
28+
};
29+
}
30+
31+
private fetchResult(total: number) {
32+
return {
33+
type: SEARCH_ACTIONS.SEARCH_RESULT,
34+
payload: {
35+
total: total
36+
}
37+
};
38+
}
39+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { Component, Input } from '@angular/core';
2+
import { Observable } from 'rxjs/Observable';
3+
import { NgRedux } from 'ng2-redux';
4+
import 'rxjs/add/operator/combineLatest';
5+
import { SearchActions } from '../actions/search-actions';
6+
7+
@Component({
8+
selector: 'search-info',
9+
providers: [SearchActions],
10+
template: `
11+
<ul>
12+
<li>{{ search$ | async | json}}</li>
13+
</ul>
14+
`
15+
})
16+
export class SearchInfo {
17+
18+
private search$: Observable<any>;
19+
private test;
20+
21+
constructor(private ngRedux: NgRedux<any>, private actions: SearchActions) { }
22+
23+
ngOnInit() {
24+
this.search$ = this.ngRedux.select(state => state.searchReducer.keyword);
25+
this.search$.subscribe((keyword) => {
26+
if (keyword != '') {
27+
this.actions.fetchResultDispatch(keyword.length)
28+
}
29+
});
30+
}
31+
ngAfterViewInit() {
32+
33+
34+
}
35+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { Component } from '@angular/core';
2+
import { NgRedux, select } from 'ng2-redux';
3+
import { SearchActions } from '../actions/search-actions';
4+
import { Observable } from 'rxjs/Rx';
5+
6+
@Component({
7+
selector: 'search',
8+
providers: [SearchActions],
9+
template: `
10+
<p>
11+
Counter: {{ counter }} <br/>
12+
Counter$ Async: {{ counter$ | async }} <br/>
13+
<input id='search-input' type="text" class="search"
14+
[(ngModel)]="keyword" (ngModelChange)="searchKeyword()"/>
15+
</p>
16+
`
17+
})
18+
export class Search {
19+
counter$: Observable<any>;
20+
search$: Observable<any>;
21+
counter;
22+
keyword: string;
23+
24+
constructor(private actions: SearchActions, private ngRedux: NgRedux<any>) { }
25+
26+
ngOnInit() {
27+
this.counter$ = this.ngRedux.select(state => state.searchReducer.total);
28+
this.search$ = this.ngRedux.select(state => state.searchReducer.keyword);
29+
30+
31+
32+
this.search$.subscribe((keyword) => {
33+
if (keyword != '') {
34+
this.actions.fetchResultDispatch(keyword.length)
35+
}
36+
});
37+
38+
this.counter$.subscribe(state => {
39+
40+
this.counter = state;
41+
});
42+
43+
44+
45+
46+
47+
}
48+
49+
private searchKeyword() {
50+
this.actions.searchDispatch(this.keyword);
51+
}
52+
}

examples/counter/containers/App.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,26 @@ import { NgRedux, DevToolsExtension } from 'ng2-redux';
44

55
import { Counter } from '../components/Counter';
66
import { CounterInfo } from '../components/CounterInfo';
7+
import { Search } from '../components/search.component';
8+
import { SearchInfo } from '../components/search-info.component';
79
import { RootState, enhancers } from '../store';
810

911
import reducer from '../reducers/index';
1012
const createLogger = require('redux-logger');
1113

1214
@Component({
1315
selector: 'root',
14-
directives: [Counter, CounterInfo],
16+
directives: [Counter, CounterInfo, Search, SearchInfo],
1517
pipes: [AsyncPipe],
16-
template: `
17-
<counter></counter>
18-
<counter-info></counter-info>
19-
`,
20-
providers: [ DevToolsExtension ]
18+
providers: [ DevToolsExtension ],
19+
template: `
20+
<br/>
21+
<counter></counter>
22+
<counter-info></counter-info>
23+
<search-info></search-info>
24+
<search></search>
25+
`
26+
2127
})
2228
export class App {
2329
constructor(

examples/counter/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { bootstrap } from '@angular/platform-browser-dynamic';
22
import { App } from './containers/App';
33
import { NgRedux } from 'ng2-redux';
4+
import { SearchActions } from './actions/search-actions';
45

5-
bootstrap(App, [ NgRedux ]);
6+
bootstrap(App, [ NgRedux, SearchActions]);

examples/counter/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"scripts": {
77
"postinstall": "typings install",
88
"start": "webpack-dev-server -d --inline --progress --no-info --config webpack.config.js",
9-
"dev": "webpack-dev-server -d --inline --progress --no-info --config webpack.dev.config.js"
9+
"dev": "webpack-dev-server -d --inline --progress --no-info --config webpack.dev.config.js --host 127.0.0.1"
1010
},
1111
"repository": {
1212
"type": "git",

examples/counter/reducers/index.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@ const { combineReducers } = Redux;
33
import { RootState } from '../store';
44
import counter from './counter';
55
import pathDemo from './path-demo';
6-
6+
import searchReducer from './search';
77
const rootReducer = combineReducers<RootState>({
88
counter,
9-
pathDemo
9+
pathDemo,
10+
searchReducer
1011
});
1112

1213
export default rootReducer;

examples/counter/reducers/search.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { SEARCH_ACTIONS } from '../actions/search-actions';
2+
3+
export interface SearchState {
4+
onSearch: boolean;
5+
keyword: string;
6+
total: number;
7+
}
8+
9+
const searchInitState: SearchState = {
10+
onSearch: false,
11+
keyword: '',
12+
total: -1
13+
};
14+
15+
export default function searchReducer(state = searchInitState, action):
16+
SearchState {
17+
switch (action.type) {
18+
case SEARCH_ACTIONS.SEARCH:
19+
return Object.assign({}, state, {
20+
onSearch: true,
21+
keyword: action.payload,
22+
total: state.total
23+
});
24+
case SEARCH_ACTIONS.SEARCH_RESULT:
25+
let total = action.payload.total;
26+
return Object.assign({}, state, {
27+
onSearch: state.onSearch,
28+
keyword: state.keyword,
29+
total
30+
});
31+
default:
32+
return state;
33+
}
34+
}

examples/counter/store/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@ export const enhancers = [
77
export interface RootState {
88
counter: number;
99
pathDemo: Object;
10-
}
10+
};

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
{
22
"name": "ng2-redux",
3-
"version": "3.2.0",
3+
"version": "3.2.1-beta.1",
44
"description": "Angular 2 bindings for Redux",
55
"main": "./lib/index.js",
66
"scripts": {
77
"build": "npm run typings && rimraf ./lib; tsc; rimraf ./lib/___tests___",
8-
"test": "npm run typings && npm run lint && npm run mocha",
8+
"test": "npm run typings && npm run lint && npm run mocha",
99
"typings": "rimraf ./typings && typings install",
1010
"mocha": "ts-node ./node_modules/mocha/bin/_mocha --opts ./src/___tests___/mocha.opts",
1111
"lint": "tslint 'src/**/*.ts' 'examples/counter/**.ts --exclude 'examples/counter/node_modules"
@@ -58,6 +58,7 @@
5858
"rxjs": "5.0.0-beta.6",
5959
"sinon": "^1.16.1",
6060
"sinon-chai": "^2.8.0",
61+
"symbol-observable": "^1.0.1",
6162
"ts-loader": "^0.8.1",
6263
"ts-node": "^0.5.5",
6364
"tslint": "^3.11.0",

0 commit comments

Comments
 (0)