Skip to content

Commit f6cc28a

Browse files
committed
Add tests for items effects
1 parent 1568365 commit f6cc28a

File tree

2 files changed

+99
-44
lines changed

2 files changed

+99
-44
lines changed

libs/common-data/src/lib/state/items/items.effects.spec.ts

Lines changed: 66 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,35 +2,91 @@ import { TestBed } from '@angular/core/testing';
22
import { provideMockActions } from '@ngrx/effects/testing';
33
import { StoreModule } from '@ngrx/store';
44
import { DataPersistence } from '@nrwl/nx';
5-
import { hot } from '@nrwl/nx/testing';
6-
import { Observable } from 'rxjs';
5+
import { cold, hot } from '@nrwl/nx/testing';
6+
import { Observable, of } from 'rxjs';
77

8-
import { ItemsLoaded, LoadItems } from './items.actions';
8+
import { AddItem, DeleteItem, ItemAdded, ItemDeleted, ItemsLoaded, ItemUpdated, LoadItems, UpdateItem } from './items.actions';
99
import { ItemsEffects } from './items.effects';
10+
import { Item, ItemsService } from '@workspace/common-data';
1011

11-
describe('ItemsEffects', () => {
12+
class ItemsServiceMock {
13+
all() {}
14+
create(item) {}
15+
update(item) {}
16+
delete(item) {}
17+
}
18+
19+
fdescribe('ItemsEffects', () => {
1220
let actions$: Observable<any>;
1321
let effects$: ItemsEffects;
22+
let itemsService: ItemsService;
1423

1524
beforeEach(() => {
1625
TestBed.configureTestingModule({
1726
imports: [StoreModule.forRoot({})],
1827
providers: [
1928
ItemsEffects,
2029
DataPersistence,
21-
provideMockActions(() => actions$)
30+
provideMockActions(() => actions$),
31+
{provide: ItemsService, useClass: ItemsServiceMock}
2232
]
2333
});
2434

2535
effects$ = TestBed.get(ItemsEffects);
36+
itemsService = TestBed.get(ItemsService);
2637
});
2738

28-
describe('someEffect', () => {
29-
it('should work', () => {
39+
describe('`loadItems$`', () => {
40+
it('should trigger `ItemsLoaded` action with data from `ItemsService.all`', () => {
41+
const items = [{id: 'csa-132', name: 'Test', description: 'Testing', price: 4313}];
42+
spyOn(itemsService, 'all').and.returnValue(of(items));
43+
3044
actions$ = hot('-a-|', { a: new LoadItems() });
31-
expect(effects$.loadItems$).toBeObservable(
32-
hot('-a-|', { a: new ItemsLoaded([]) })
33-
);
45+
const expected$ = cold('-a-|', { a: new ItemsLoaded(items) });
46+
47+
expect(effects$.loadItems$).toBeObservable(expected$);
48+
expect(itemsService.all).toHaveBeenCalled();
49+
});
50+
});
51+
52+
describe('`addItem$`', () => {
53+
it('should trigger `ItemAdded` action with data from `ItemsService.create`', () => {
54+
const item = {id: null, name: 'Test', description: 'Testing', price: 4313};
55+
const createdItem = {...item, id: 'jhh14-created'};
56+
spyOn(itemsService, 'create').and.returnValue(of(createdItem));
57+
58+
actions$ = hot('-a-|', { a: new AddItem(item) });
59+
const expected$ = cold('-a-|', { a: new ItemAdded(createdItem) });
60+
61+
expect(effects$.addItem$).toBeObservable(expected$);
62+
expect(itemsService.create).toHaveBeenCalledWith(item);
63+
});
64+
});
65+
66+
describe('`updateItem$`', () => {
67+
it('should trigger `ItemUpdated` action with data from `ItemsService.update`', () => {
68+
const item = {id: 'jhh14-updated', name: 'Test', description: 'Testing', price: 4313};
69+
const updatedItem = {...item, name: 'Updated', description: 'Different'};
70+
spyOn(itemsService, 'update').and.returnValue(of(updatedItem));
71+
72+
actions$ = hot('-a-|', { a: new UpdateItem(item) });
73+
const expected$ = cold('-a-|', { a: new ItemUpdated(updatedItem) });
74+
75+
expect(effects$.updateItem$).toBeObservable(expected$);
76+
expect(itemsService.update).toHaveBeenCalledWith(item);
77+
});
78+
});
79+
80+
describe('`deleteItem$`', () => {
81+
it('should trigger `ItemDeleted` action with data from `ItemsService.delete`', () => {
82+
const item = {id: 'jhh14-deleted', name: 'Test', description: 'Testing', price: 4313};
83+
spyOn(itemsService, 'delete').and.returnValue(of(item));
84+
85+
actions$ = hot('-a-|', { a: new DeleteItem(item) });
86+
const expected$ = cold('-a-|', { a: new ItemDeleted(item) });
87+
88+
expect(effects$.deleteItem$).toBeObservable(expected$);
89+
expect(itemsService.delete).toHaveBeenCalledWith(item);
3490
});
3591
});
3692
});

libs/common-data/src/lib/state/items/items.reducer.spec.ts

Lines changed: 33 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ import { Action } from '@ngrx/store';
44
import { Item } from '@workspace/common-data';
55
import { selectCurrentItem, selectCurrentItemId } from '../index';
66

7-
fdescribe('itemsReducer', () => {
7+
describe('itemsReducer', () => {
88
it('should return state with unknown action', () => {
99
const action = {type: 'DoesNotExist', payload: 'Sample'} as Action;
1010
const actual = itemsReducer(initialState, action as any);
1111
expect(actual).toEqual(initialState);
1212
});
1313

14-
it(`${ItemsActionTypes.ItemsLoaded} action`, () => {
14+
it(`${ItemsActionTypes.ItemsLoaded} action should replace state with payload`, () => {
1515
const exampleItems: Item[] = [{id: 'cb1234-sa', name: 'test', description: 'testing', price: 10}];
1616
const entities = {
1717
'cb1234-sa': exampleItems[0]
@@ -22,7 +22,7 @@ fdescribe('itemsReducer', () => {
2222
expect(state.entities).toEqual(entities);
2323
});
2424

25-
it(`${ItemsActionTypes.ItemAdded} action`, () => {
25+
it(`${ItemsActionTypes.ItemAdded} action should add item to state`, () => {
2626
const addedItem: Item = {id: 'added-item', name: 'added', description: 'added testing', price: 1001};
2727
const entities = {
2828
'added-item': addedItem
@@ -33,7 +33,7 @@ fdescribe('itemsReducer', () => {
3333
expect(state.entities).toEqual(entities);
3434
});
3535

36-
it(`${ItemsActionTypes.ItemUpdated} action`, () => {
36+
it(`${ItemsActionTypes.ItemUpdated} action should update item in state`, () => {
3737
const existingEntities = { 'existing-item': { id: 'existing-item', name: 'existing', description: 'existing testing', price: 1001 } };
3838
const existingState = {...initialState, entities: existingEntities};
3939

@@ -44,7 +44,7 @@ fdescribe('itemsReducer', () => {
4444
expect(state.entities['existing-item']).toEqual(updatedItem);
4545
});
4646

47-
it(`${ItemsActionTypes.ItemDeleted} action`, () => {
47+
it(`${ItemsActionTypes.ItemDeleted} action should remove item from state`, () => {
4848
const existingEntities = {
4949
'existing-item': { id: 'existing-item', name: 'existing', description: 'existing testing', price: 1001 },
5050
'another-item': { id: 'another-item', name: 'another', description: 'another testing', price: 5824 },
@@ -58,43 +58,42 @@ fdescribe('itemsReducer', () => {
5858
expect(state.entities['another-item']).not.toBeTruthy();
5959
});
6060

61-
it(`${ItemsActionTypes.ItemSelected} action`, () => {
61+
it(`${ItemsActionTypes.ItemSelected} action should set 'selectedItemId' in state`, () => {
6262
const selectedItem = 'item-id';
6363

6464
const action: ItemSelected = new ItemSelected(selectedItem);
6565
const state = itemsReducer(initialState, action);
6666
expect(state.selectedItemId).toBe(selectedItem);
6767
});
6868

69-
// -------------------------------------------------------------------
70-
// SELECTORS
71-
// -------------------------------------------------------------------
72-
it('`selectCurrentItemId` should get currently selected item ID', () => {
73-
const state = {items: {...initialState, selectedItemId: '123'}};
74-
expect(selectCurrentItemId(state)).toBe('123');
75-
});
76-
77-
describe('`selectCurrentItem`', () => {
78-
it('should get currently selected item', () => {
79-
const state = {
80-
items: {
81-
...initialState,
82-
selectedItemId: '123',
83-
entities: { '123': { id: '123', name: 'Test', description: 'Testing', price: 134 } }
84-
}
85-
};
86-
expect(selectCurrentItem(state)).toBe(state.items.entities['123']);
69+
describe('selectors', () => {
70+
it('`selectCurrentItemId` should get currently selected item ID', () => {
71+
const state = {items: {...initialState, selectedItemId: '123'}};
72+
expect(selectCurrentItemId(state)).toBe('123');
8773
});
8874

89-
it('should return an empty item if no selected item', () => {
90-
const state = {
91-
items: {
92-
...initialState,
93-
selectedItemId: null,
94-
entities: { '123': { id: '123', name: 'Test', description: 'Testing', price: 134 } }
95-
}
96-
};
97-
expect(selectCurrentItem(state)).toEqual({ id: null, name: '', price: 0, description: '' });
98-
});
75+
describe('`selectCurrentItem`', () => {
76+
it('should get currently selected item', () => {
77+
const state = {
78+
items: {
79+
...initialState,
80+
selectedItemId: '123',
81+
entities: { '123': { id: '123', name: 'Test', description: 'Testing', price: 134 } }
82+
}
83+
};
84+
expect(selectCurrentItem(state)).toBe(state.items.entities['123']);
85+
});
86+
87+
it('should return an empty item if no selected item', () => {
88+
const state = {
89+
items: {
90+
...initialState,
91+
selectedItemId: null,
92+
entities: { '123': { id: '123', name: 'Test', description: 'Testing', price: 134 } }
93+
}
94+
};
95+
expect(selectCurrentItem(state)).toEqual({ id: null, name: '', price: 0, description: '' });
96+
});
97+
})
9998
});
10099
});

0 commit comments

Comments
 (0)