Skip to content

Commit 499b734

Browse files
committed
Split up unit test files
1 parent cc714f6 commit 499b734

7 files changed

+1110
-1058
lines changed

test/autotrackMemoize.spec.ts

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
import { createSelectorCreator, autotrackMemoize } from 'reselect'
2+
3+
// Construct 1E6 states for perf test outside of the perf test so as to not change the execute time of the test function
4+
const numOfStates = 1000000
5+
interface StateA {
6+
a: number
7+
}
8+
9+
interface StateAB {
10+
a: number
11+
b: number
12+
}
13+
14+
interface StateSub {
15+
sub: {
16+
a: number
17+
}
18+
}
19+
20+
const states: StateAB[] = []
21+
22+
for (let i = 0; i < numOfStates; i++) {
23+
states.push({ a: 1, b: 2 })
24+
}
25+
26+
describe('Basic selector behavior with autotrack', () => {
27+
const createSelector = createSelectorCreator(autotrackMemoize)
28+
29+
test('basic selector', () => {
30+
// console.log('Selector test')
31+
const selector = createSelector(
32+
(state: StateA) => state.a,
33+
a => a
34+
)
35+
const firstState = { a: 1 }
36+
const firstStateNewPointer = { a: 1 }
37+
const secondState = { a: 2 }
38+
39+
expect(selector(firstState)).toBe(1)
40+
expect(selector(firstState)).toBe(1)
41+
expect(selector.recomputations()).toBe(1)
42+
expect(selector(firstStateNewPointer)).toBe(1)
43+
expect(selector.recomputations()).toBe(1)
44+
expect(selector(secondState)).toBe(2)
45+
expect(selector.recomputations()).toBe(2)
46+
})
47+
48+
test("don't pass extra parameters to inputSelector when only called with the state", () => {
49+
const selector = createSelector(
50+
(...params: any[]) => params.length,
51+
a => a
52+
)
53+
expect(selector({})).toBe(1)
54+
})
55+
56+
test('basic selector multiple keys', () => {
57+
const selector = createSelector(
58+
(state: StateAB) => state.a,
59+
(state: StateAB) => state.b,
60+
(a, b) => a + b
61+
)
62+
const state1 = { a: 1, b: 2 }
63+
expect(selector(state1)).toBe(3)
64+
expect(selector(state1)).toBe(3)
65+
expect(selector.recomputations()).toBe(1)
66+
const state2 = { a: 3, b: 2 }
67+
expect(selector(state2)).toBe(5)
68+
expect(selector(state2)).toBe(5)
69+
expect(selector.recomputations()).toBe(2)
70+
})
71+
72+
test('basic selector invalid input selector', () => {
73+
expect(() =>
74+
createSelector(
75+
// @ts-ignore
76+
(state: StateAB) => state.a,
77+
function input2(state: StateAB) {
78+
return state.b
79+
},
80+
'not a function',
81+
(a: any, b: any) => a + b
82+
)
83+
).toThrow(
84+
'createSelector expects all input-selectors to be functions, but received the following types: [function unnamed(), function input2(), string]'
85+
)
86+
87+
expect(() =>
88+
// @ts-ignore
89+
createSelector((state: StateAB) => state.a, 'not a function')
90+
).toThrow(
91+
'createSelector expects an output function after the inputs, but received: [string]'
92+
)
93+
})
94+
95+
test('basic selector cache hit performance', () => {
96+
if (process.env.COVERAGE) {
97+
return // don't run performance tests for coverage
98+
}
99+
100+
const selector = createSelector(
101+
(state: StateAB) => state.a,
102+
(state: StateAB) => state.b,
103+
(a, b) => a + b
104+
)
105+
const state1 = { a: 1, b: 2 }
106+
107+
const start = performance.now()
108+
for (let i = 0; i < 1000000; i++) {
109+
selector(state1)
110+
}
111+
const totalTime = performance.now() - start
112+
113+
expect(selector(state1)).toBe(3)
114+
expect(selector.recomputations()).toBe(1)
115+
// Expected a million calls to a selector with the same arguments to take less than 1 second
116+
expect(totalTime).toBeLessThan(1000)
117+
})
118+
119+
test('basic selector cache hit performance for state changes but shallowly equal selector args', () => {
120+
if (process.env.COVERAGE) {
121+
return // don't run performance tests for coverage
122+
}
123+
124+
const selector = createSelector(
125+
(state: StateAB) => state.a,
126+
(state: StateAB) => state.b,
127+
(a, b) => a + b
128+
)
129+
130+
const start = performance.now()
131+
for (let i = 0; i < 1000000; i++) {
132+
selector(states[i])
133+
}
134+
const totalTime = performance.now() - start
135+
136+
expect(selector(states[0])).toBe(3)
137+
expect(selector.recomputations()).toBe(1)
138+
139+
// Expected a million calls to a selector with the same arguments to take less than 1 second
140+
expect(totalTime).toBeLessThan(1000)
141+
})
142+
143+
test('memoized composite arguments', () => {
144+
const selector = createSelector(
145+
(state: StateSub) => state.sub,
146+
sub => sub.a
147+
)
148+
const state1 = { sub: { a: 1 } }
149+
expect(selector(state1)).toEqual(1)
150+
expect(selector(state1)).toEqual(1)
151+
expect(selector.recomputations()).toBe(1)
152+
const state2 = { sub: { a: 2 } }
153+
expect(selector(state2)).toEqual(2)
154+
expect(selector.recomputations()).toBe(2)
155+
})
156+
157+
test('first argument can be an array', () => {
158+
const selector = createSelector(
159+
[state => state.a, state => state.b],
160+
(a, b) => {
161+
return a + b
162+
}
163+
)
164+
expect(selector({ a: 1, b: 2 })).toBe(3)
165+
expect(selector({ a: 1, b: 2 })).toBe(3)
166+
expect(selector.recomputations()).toBe(1)
167+
expect(selector({ a: 3, b: 2 })).toBe(5)
168+
expect(selector.recomputations()).toBe(2)
169+
})
170+
171+
test('can accept props', () => {
172+
let called = 0
173+
const selector = createSelector(
174+
(state: StateAB) => state.a,
175+
(state: StateAB) => state.b,
176+
(state: StateAB, props: { c: number }) => props.c,
177+
(a, b, c) => {
178+
called++
179+
return a + b + c
180+
}
181+
)
182+
expect(selector({ a: 1, b: 2 }, { c: 100 })).toBe(103)
183+
})
184+
185+
test('recomputes result after exception', () => {
186+
let called = 0
187+
const selector = createSelector(
188+
(state: StateA) => state.a,
189+
() => {
190+
called++
191+
throw Error('test error')
192+
}
193+
)
194+
expect(() => selector({ a: 1 })).toThrow('test error')
195+
expect(() => selector({ a: 1 })).toThrow('test error')
196+
expect(called).toBe(2)
197+
})
198+
199+
test('memoizes previous result before exception', () => {
200+
let called = 0
201+
const selector = createSelector(
202+
(state: StateA) => state.a,
203+
a => {
204+
called++
205+
if (a > 1) throw Error('test error')
206+
return a
207+
}
208+
)
209+
const state1 = { a: 1 }
210+
const state2 = { a: 2 }
211+
expect(selector(state1)).toBe(1)
212+
expect(() => selector(state2)).toThrow('test error')
213+
expect(selector(state1)).toBe(1)
214+
expect(called).toBe(2)
215+
})
216+
})

test/createStructuredSelector.spec.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import {
2+
createSelectorCreator,
3+
defaultMemoize,
4+
createStructuredSelector
5+
} from 'reselect'
6+
7+
interface StateAB {
8+
a: number
9+
b: number
10+
}
11+
12+
describe('createStructureSelector', () => {
13+
test('structured selector', () => {
14+
const selector = createStructuredSelector({
15+
x: (state: StateAB) => state.a,
16+
y: (state: StateAB) => state.b
17+
})
18+
const firstResult = selector({ a: 1, b: 2 })
19+
expect(firstResult).toEqual({ x: 1, y: 2 })
20+
expect(selector({ a: 1, b: 2 })).toBe(firstResult)
21+
const secondResult = selector({ a: 2, b: 2 })
22+
expect(secondResult).toEqual({ x: 2, y: 2 })
23+
expect(selector({ a: 2, b: 2 })).toBe(secondResult)
24+
})
25+
26+
test('structured selector with invalid arguments', () => {
27+
expect(() =>
28+
// @ts-expect-error
29+
createStructuredSelector(
30+
(state: StateAB) => state.a,
31+
(state: StateAB) => state.b
32+
)
33+
).toThrow(/expects first argument to be an object.*function/)
34+
expect(() =>
35+
createStructuredSelector({
36+
a: state => state.b,
37+
// @ts-expect-error
38+
c: 'd'
39+
})
40+
).toThrow(
41+
'createSelector expects all input-selectors to be functions, but received the following types: [function a(), string]'
42+
)
43+
})
44+
45+
test('structured selector with custom selector creator', () => {
46+
const customSelectorCreator = createSelectorCreator(
47+
defaultMemoize,
48+
(a, b) => a === b
49+
)
50+
const selector = createStructuredSelector(
51+
{
52+
x: (state: StateAB) => state.a,
53+
y: (state: StateAB) => state.b
54+
},
55+
customSelectorCreator
56+
)
57+
const firstResult = selector({ a: 1, b: 2 })
58+
expect(firstResult).toEqual({ x: 1, y: 2 })
59+
expect(selector({ a: 1, b: 2 })).toBe(firstResult)
60+
expect(selector({ a: 2, b: 2 })).toEqual({ x: 2, y: 2 })
61+
})
62+
})

0 commit comments

Comments
 (0)