-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test: Tests and cleanup for
with-reselect
package (#8)
* Rename constructors to be shorter * Add tests for dynamicSelectorFromReselect * Add tests for reselectSelectorFromDynamic
- Loading branch information
Showing
6 changed files
with
244 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,10 @@ | ||
import { DynamicSelectorArgsWithoutState, DynamicSelectorFn } from '@dynamic-selectors/core'; | ||
|
||
const createReselectSelectorFromDynamic = <StateType = any, ReturnType = any>( | ||
const reselectSelectorFromDynamic = <StateType = any, ReturnType = any>( | ||
dynamicSelectorFn: DynamicSelectorFn<ReturnType>, | ||
...paramsAndOtherArgs: DynamicSelectorArgsWithoutState | ||
) => { | ||
return (state: StateType) => dynamicSelectorFn(state, ...paramsAndOtherArgs); | ||
}; | ||
|
||
export { createReselectSelectorFromDynamic }; | ||
export { reselectSelectorFromDynamic }; |
This file was deleted.
Oops, something went wrong.
81 changes: 81 additions & 0 deletions
81
packages/with-reselect/tests/dynamicSelectorFromReselect.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import { createSelector } from 'reselect'; | ||
|
||
import { dynamicSelectorFromReselect } from '../src'; | ||
import DebugInfoCheckUtil from '../../core/tests/util/debugInfoCheckUtil'; | ||
|
||
describe('dynamicSelectorFromReselect', () => { | ||
test('handles simple selector functions', () => { | ||
const reselectSelector = (state: any) => state.a; | ||
const dynamicSelector = dynamicSelectorFromReselect(reselectSelector); | ||
const selectorCheck = new DebugInfoCheckUtil(dynamicSelector); | ||
|
||
let state = { a: 1 }; | ||
|
||
// Normal run | ||
expect(dynamicSelector(state)).toEqual(1); | ||
selectorCheck.expectInvoked('run'); | ||
|
||
// Now it's cached by state | ||
expect(dynamicSelector(state)).toEqual(1); | ||
selectorCheck.expectInvoked('skipped'); | ||
|
||
state = { a: 1 }; | ||
|
||
// It's a new state, so Reselect returns a new value, but after we run we realize we didn't need to | ||
expect(dynamicSelector(state)).toEqual(1); | ||
selectorCheck.expectInvoked('phantom'); | ||
|
||
// Now it's cached by state | ||
expect(dynamicSelector(state)).toEqual(1); | ||
selectorCheck.expectInvoked('skipped'); | ||
|
||
state = { a: 2 }; | ||
|
||
// A full run because the accessed state value is new | ||
expect(dynamicSelector(state)).toEqual(2); | ||
selectorCheck.expectInvoked('run'); | ||
|
||
// But then it's cached again | ||
expect(dynamicSelector(state)).toEqual(2); | ||
selectorCheck.expectInvoked('skipped'); | ||
}); | ||
|
||
test('handles normal selector functions', () => { | ||
const reselectorDependency = (state: any) => state.a; | ||
const reselectSelector = createSelector(reselectorDependency, (depResult) => depResult); | ||
const dynamicSelector = dynamicSelectorFromReselect(reselectSelector); | ||
|
||
const selectorCheck = new DebugInfoCheckUtil(dynamicSelector); | ||
|
||
let state = { a: 1 }; | ||
|
||
// Normal run | ||
expect(dynamicSelector(state)).toEqual(1); | ||
selectorCheck.expectInvoked('run'); | ||
|
||
// Now it's cached by state | ||
expect(dynamicSelector(state)).toEqual(1); | ||
selectorCheck.expectInvoked('skipped'); | ||
|
||
state = { a: 1 }; | ||
|
||
// It's a new state, so Reselect returns a new value, but after we run we realize we didn't need to | ||
expect(dynamicSelector(state)).toEqual(1); | ||
selectorCheck.expectInvoked('phantom'); | ||
|
||
// Cached again | ||
expect(dynamicSelector(state)).toEqual(1); | ||
selectorCheck.expectInvoked('skipped'); | ||
|
||
state = { a: 2 }; | ||
|
||
// Parent invokes child, child is DepChecked and found to be dirty, so parent runs (and invokes child again -- | ||
// but it's skipped now) | ||
expect(dynamicSelector(state)).toEqual(2); | ||
selectorCheck.expectInvoked('run'); | ||
|
||
// Cached again | ||
expect(dynamicSelector(state)).toEqual(2); | ||
selectorCheck.expectInvoked('skipped'); | ||
}); | ||
}); |
152 changes: 152 additions & 0 deletions
152
packages/with-reselect/tests/reselectSelectorFromDynamic.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
import { createSelector } from 'reselect'; | ||
import { createDynamicSelector } from '@dynamic-selectors/core'; | ||
|
||
import { reselectSelectorFromDynamic } from '../src'; | ||
import DebugInfoCheckUtil from '../../core/tests/util/debugInfoCheckUtil'; | ||
|
||
describe('reselectSelectorFromDynamic', () => { | ||
test('dynamic selector as a Reselect dependency', () => { | ||
const dynamicSelector = createDynamicSelector((getState) => { | ||
return getState('a'); | ||
}); | ||
const reselectSelector = createSelector(dynamicSelector, (depResult) => depResult); | ||
const selectorCheck = new DebugInfoCheckUtil(dynamicSelector); | ||
|
||
let state = { a: 1 }; | ||
|
||
// Normal run | ||
expect(reselectSelector(state)).toEqual(1); | ||
selectorCheck.expectInvoked('run'); | ||
expect(reselectSelector.recomputations()).toEqual(1); | ||
|
||
// Now it's cached by state | ||
expect(reselectSelector(state)).toEqual(1); | ||
selectorCheck.expectUntouched(); | ||
expect(reselectSelector.recomputations()).toEqual(1); | ||
|
||
state = { a: 1 }; | ||
|
||
// Reselect invokes dynamic, dynamic is DepChecked, then skipped | ||
expect(reselectSelector(state)).toEqual(1); | ||
selectorCheck.expectInvoked('skipped'); | ||
expect(reselectSelector.recomputations()).toEqual(1); | ||
|
||
// Cached again | ||
expect(reselectSelector(state)).toEqual(1); | ||
selectorCheck.expectUntouched(); | ||
expect(reselectSelector.recomputations()).toEqual(1); | ||
|
||
state = { a: 2 }; | ||
|
||
// Reselect invokes dynamic, dynamic is found to be dirty, so it returns the new value | ||
expect(reselectSelector(state)).toEqual(2); | ||
selectorCheck.expectInvoked('run'); | ||
expect(reselectSelector.recomputations()).toEqual(2); | ||
|
||
// Cached again | ||
expect(reselectSelector(state)).toEqual(2); | ||
selectorCheck.expectUntouched(); | ||
expect(reselectSelector.recomputations()).toEqual(2); | ||
}); | ||
|
||
test('dynamic selector with params as a Reselect dependency', () => { | ||
const dynamicSelector = createDynamicSelector((getState, path: string) => { | ||
return getState(path); | ||
}); | ||
const reselectSelectorA = createSelector( | ||
reselectSelectorFromDynamic(dynamicSelector, 'a'), | ||
(depResult) => depResult, | ||
); | ||
const reselectSelectorB = createSelector( | ||
reselectSelectorFromDynamic(dynamicSelector, 'b'), | ||
(depResult) => depResult, | ||
); | ||
const reselectSelectorC = createSelector( | ||
reselectSelectorFromDynamic(dynamicSelector, 'c'), | ||
(depResult) => depResult, | ||
); | ||
const dynamicSelectorCheckA = new DebugInfoCheckUtil(dynamicSelector, 'a'); | ||
const dynamicSelectorCheckB = new DebugInfoCheckUtil(dynamicSelector, 'b'); | ||
const dynamicSelectorCheckC = new DebugInfoCheckUtil(dynamicSelector, 'c'); | ||
|
||
let state = { a: 1, b: 1, c: 1 }; | ||
|
||
// Normal runs | ||
expect(reselectSelectorA(state)).toEqual(1); | ||
dynamicSelectorCheckA.expectInvoked('run'); | ||
dynamicSelectorCheckB.expectUntouched(); | ||
dynamicSelectorCheckC.expectUntouched(); | ||
expect(reselectSelectorB(state)).toEqual(1); | ||
dynamicSelectorCheckA.expectUntouched(); | ||
dynamicSelectorCheckB.expectInvoked('run'); | ||
dynamicSelectorCheckC.expectUntouched(); | ||
expect(reselectSelectorC(state)).toEqual(1); | ||
dynamicSelectorCheckA.expectUntouched(); | ||
dynamicSelectorCheckB.expectUntouched(); | ||
dynamicSelectorCheckC.expectInvoked('run'); | ||
|
||
expect(reselectSelectorA.recomputations()).toEqual(1); | ||
expect(reselectSelectorB.recomputations()).toEqual(1); | ||
expect(reselectSelectorC.recomputations()).toEqual(1); | ||
|
||
// Now all are cached by state | ||
expect(reselectSelectorA(state)).toEqual(1); | ||
dynamicSelectorCheckA.expectUntouched(); | ||
expect(reselectSelectorB(state)).toEqual(1); | ||
dynamicSelectorCheckB.expectUntouched(); | ||
expect(reselectSelectorC(state)).toEqual(1); | ||
dynamicSelectorCheckC.expectUntouched(); | ||
|
||
expect(reselectSelectorA.recomputations()).toEqual(1); | ||
expect(reselectSelectorB.recomputations()).toEqual(1); | ||
expect(reselectSelectorC.recomputations()).toEqual(1); | ||
|
||
state = { a: 1, b: 1, c: 2 }; | ||
|
||
// A and B are cached because the accessed state value didn't change; C re-ran | ||
expect(reselectSelectorA(state)).toEqual(1); | ||
dynamicSelectorCheckA.expectInvoked('skipped'); | ||
expect(reselectSelectorB(state)).toEqual(1); | ||
dynamicSelectorCheckB.expectInvoked('skipped'); | ||
expect(reselectSelectorC(state)).toEqual(2); | ||
dynamicSelectorCheckC.expectInvoked('run'); | ||
|
||
expect(reselectSelectorA.recomputations()).toEqual(1); | ||
expect(reselectSelectorB.recomputations()).toEqual(1); | ||
expect(reselectSelectorC.recomputations()).toEqual(2); | ||
|
||
// Now all are cached by state | ||
expect(reselectSelectorA(state)).toEqual(1); | ||
dynamicSelectorCheckA.expectUntouched(); | ||
expect(reselectSelectorB(state)).toEqual(1); | ||
dynamicSelectorCheckB.expectUntouched(); | ||
expect(reselectSelectorC(state)).toEqual(2); | ||
dynamicSelectorCheckC.expectUntouched(); | ||
|
||
expect(reselectSelectorA.recomputations()).toEqual(1); | ||
expect(reselectSelectorB.recomputations()).toEqual(1); | ||
expect(reselectSelectorC.recomputations()).toEqual(2); | ||
|
||
state = { a: 2, b: 2, c: 3 }; | ||
|
||
// Full runs because the accessed state value is new | ||
expect(reselectSelectorA(state)).toEqual(2); | ||
dynamicSelectorCheckA.expectInvoked('run'); | ||
expect(reselectSelectorB(state)).toEqual(2); | ||
dynamicSelectorCheckB.expectInvoked('run'); | ||
expect(reselectSelectorC(state)).toEqual(3); | ||
dynamicSelectorCheckC.expectInvoked('run'); | ||
|
||
expect(reselectSelectorA.recomputations()).toEqual(2); | ||
expect(reselectSelectorB.recomputations()).toEqual(2); | ||
expect(reselectSelectorC.recomputations()).toEqual(3); | ||
|
||
// But now everything is cached again | ||
expect(reselectSelectorA(state)).toEqual(2); | ||
dynamicSelectorCheckA.expectUntouched(); | ||
expect(reselectSelectorB(state)).toEqual(2); | ||
dynamicSelectorCheckB.expectUntouched(); | ||
expect(reselectSelectorC(state)).toEqual(3); | ||
dynamicSelectorCheckC.expectUntouched(); | ||
}); | ||
}); |