Skip to content

Commit 56cb21f

Browse files
03byronMikeRyanDev
authored andcommitted
feat(createSelector): Expose projector function on selectors to improve testability
Closes #290
1 parent d20ebf1 commit 56cb21f

File tree

2 files changed

+19
-4
lines changed

2 files changed

+19
-4
lines changed

modules/store/spec/selector.spec.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,17 @@ describe('Selectors', () => {
4141
expect(projectFn).toHaveBeenCalledWith(countOne, countTwo);
4242
});
4343

44+
it('should be possible to test a projector fn independent from the selectors it is composed of', () => {
45+
const projectFn = jasmine.createSpy('projectionFn');
46+
const selector = createSelector(incrementOne, incrementTwo, projectFn);
47+
48+
selector.projector('', '');
49+
50+
expect(incrementOne).not.toHaveBeenCalled();
51+
expect(incrementTwo).not.toHaveBeenCalled();
52+
expect(projectFn).toHaveBeenCalledWith('', '');
53+
});
54+
4455
it('should call the projector function only when the value of a dependent selector change', () => {
4556
const firstState = { first: 'state', unchanged: 'state' };
4657
const secondState = { second: 'state', unchanged: 'state' };

modules/store/src/selector.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import { Selector } from './models';
22

3+
export type AnyFn = (...args: any[]) => any;
4+
35
export interface MemoizedSelector<State, Result>
46
extends Selector<State, Result> {
57
release(): void;
8+
projector: AnyFn;
69
}
710

8-
export type AnyFn = (...args: any[]) => any;
9-
1011
export function memoize(t: AnyFn): { memoized: AnyFn; reset: () => void } {
1112
let lastArguments: null | IArguments = null;
1213
let lastResult: any = null;
@@ -132,7 +133,10 @@ export function createSelector(...args: any[]): Selector<any, any> {
132133
memoizedSelectors.forEach(selector => selector.release());
133134
}
134135

135-
return Object.assign(memoizedState.memoized, { release });
136+
return Object.assign(memoizedState.memoized, {
137+
release,
138+
projector: memoizedProjector.memoized,
139+
});
136140
}
137141

138142
export function createFeatureSelector<T>(
@@ -142,5 +146,5 @@ export function createFeatureSelector<T>(
142146
return state[featureName];
143147
});
144148

145-
return Object.assign(memoized, { release: reset });
149+
return Object.assign(memoized, { release: reset, projector: memoized });
146150
}

0 commit comments

Comments
 (0)