Skip to content

Commit e3b1928

Browse files
committed
add builder test
1 parent c8c31b8 commit e3b1928

File tree

2 files changed

+333
-0
lines changed

2 files changed

+333
-0
lines changed
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
import { TestScheduler } from 'rxjs/testing'
2+
import { Controller, ControllerProvider, Builder } from '../../src'
3+
import { act, getByTestId, render, waitFor } from '@testing-library/react'
4+
import { tap } from 'rxjs'
5+
6+
class TestController extends Controller<number> {
7+
constructor(initialValue?: number) {
8+
super(initialValue ?? 0)
9+
}
10+
inc() {
11+
this.emit(this.state + 1)
12+
}
13+
protected compareState(): boolean {
14+
return false
15+
}
16+
reEmit() {
17+
this.emit(this.state)
18+
}
19+
}
20+
21+
it('emit object values every reEmit', () => {
22+
const testScheduler = new TestScheduler((actual, expected) => {
23+
return expect(actual).toEqual(expected)
24+
})
25+
const testController = new TestController()
26+
const triggerMarbles = '-aaaa'
27+
const triggerValues = {
28+
a: () => testController.reEmit(),
29+
}
30+
31+
const expectedMarbles = '-aaaa'
32+
const expectedValues = {
33+
a: 0,
34+
}
35+
const eventObservable = testController.observable.pipe()
36+
testScheduler.run(({ expectObservable, cold }) => {
37+
expectObservable(eventObservable).toBe(expectedMarbles, expectedValues)
38+
expectObservable(cold(triggerMarbles, triggerValues).pipe(tap((fn) => fn())))
39+
})
40+
})
41+
42+
type DisplayRenderedProps = {
43+
source: TestController
44+
buildWhen?: (prev: number, curr: number) => boolean
45+
stateComp?: (prev: number, curr: number) => boolean
46+
}
47+
const DisplayRendered = ({ source, buildWhen, stateComp }: DisplayRenderedProps) => {
48+
return (
49+
<Builder source={source} buildWhen={buildWhen} stateCompare={stateComp}>
50+
{(state) => {
51+
return (
52+
<>
53+
<h1 data-testid='text'>{state}</h1>
54+
<h1 data-testid='controller'>{source.constructor.name}</h1>
55+
</>
56+
)
57+
}}
58+
</Builder>
59+
)
60+
}
61+
62+
it('buildWhen respected', (done) => {
63+
const buildWhenFn = jest.fn((prev, curr) => prev === curr)
64+
const instance = new TestController()
65+
const { container } = render(
66+
<ControllerProvider ctor={TestController} source={instance}>
67+
<DisplayRendered source={instance} buildWhen={buildWhenFn} />
68+
</ControllerProvider>,
69+
)
70+
instance.inc()
71+
instance.inc()
72+
instance.inc()
73+
instance.inc()
74+
instance.inc()
75+
expect(buildWhenFn).toHaveBeenCalledTimes(5)
76+
expect(buildWhenFn.mock.calls[0][0]).toBe(0)
77+
expect(buildWhenFn.mock.calls[0][1]).toBe(1)
78+
expect(buildWhenFn.mock.calls[1][0]).toBe(1)
79+
expect(buildWhenFn.mock.calls[1][1]).toBe(2)
80+
expect(buildWhenFn.mock.calls[2][0]).toBe(2)
81+
expect(buildWhenFn.mock.calls[2][1]).toBe(3)
82+
expect(buildWhenFn.mock.calls[3][0]).toBe(3)
83+
expect(buildWhenFn.mock.calls[3][1]).toBe(4)
84+
expect(buildWhenFn.mock.calls[4][0]).toBe(4)
85+
expect(buildWhenFn.mock.calls[4][1]).toBe(5)
86+
const rendered = getByTestId(container, 'text')
87+
const renderedText = rendered.textContent
88+
const expectedText = '0'
89+
expect(renderedText).toBe(expectedText)
90+
done()
91+
})
92+
93+
it('rerender on state changed', async () => {
94+
const instance = new TestController()
95+
const { container } = render(
96+
<ControllerProvider ctor={TestController} source={instance}>
97+
<DisplayRendered source={instance} />
98+
</ControllerProvider>,
99+
)
100+
const rendered = getByTestId(container, 'text')
101+
const renderedText = rendered.textContent
102+
const expectedText = '0'
103+
expect(renderedText).toBe(expectedText)
104+
act(() => {
105+
instance.inc()
106+
instance.inc()
107+
instance.inc()
108+
instance.inc()
109+
instance.inc()
110+
})
111+
await waitFor(() => {
112+
const rendered = getByTestId(container, 'text')
113+
const renderedText = rendered.textContent
114+
const expectedText = '5'
115+
expect(renderedText).toBe(expectedText)
116+
})
117+
})
118+
119+
it('specified state compare respected', async () => {
120+
const stateCompareFn = jest.fn((prev, curr) => prev !== curr)
121+
const instance = new TestController()
122+
const { container } = render(
123+
<ControllerProvider ctor={TestController} source={instance}>
124+
<DisplayRendered source={instance} stateComp={stateCompareFn} />
125+
</ControllerProvider>,
126+
)
127+
const rendered = getByTestId(container, 'text')
128+
const renderedText = rendered.textContent
129+
const expectedText = '0'
130+
expect(renderedText).toBe(expectedText)
131+
132+
act(() => {
133+
instance.inc()
134+
instance.inc()
135+
instance.inc()
136+
instance.inc()
137+
})
138+
await waitFor(() => {
139+
expect(stateCompareFn).toHaveBeenCalledTimes(4)
140+
expect(stateCompareFn.mock.calls[0][0]).toBe(0)
141+
expect(stateCompareFn.mock.calls[0][1]).toBe(1)
142+
expect(stateCompareFn.mock.calls[1][0]).toBe(0)
143+
expect(stateCompareFn.mock.calls[1][1]).toBe(2)
144+
expect(stateCompareFn.mock.calls[2][0]).toBe(0)
145+
expect(stateCompareFn.mock.calls[2][1]).toBe(3)
146+
expect(stateCompareFn.mock.calls[3][0]).toBe(0)
147+
expect(stateCompareFn.mock.calls[3][1]).toBe(4)
148+
const rendered = getByTestId(container, 'text')
149+
const renderedText = rendered.textContent
150+
const expectedText = '0'
151+
expect(renderedText).toBe(expectedText)
152+
})
153+
})

tests/Builder/builder_ctor.test.tsx

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
import { TestScheduler } from 'rxjs/testing'
2+
import { Controller, ControllerProvider, ResourcesNotProvidedError, Builder } from '../../src'
3+
import { act, getByTestId, render, waitFor } from '@testing-library/react'
4+
import { tap } from 'rxjs'
5+
6+
class TestController extends Controller<number> {
7+
constructor(initialValue?: number) {
8+
super(initialValue ?? 0)
9+
}
10+
inc() {
11+
this.emit(this.state + 1)
12+
}
13+
protected compareState(): boolean {
14+
return false
15+
}
16+
reEmit() {
17+
this.emit(this.state)
18+
}
19+
}
20+
21+
it('emit object values every reEmit', () => {
22+
const testScheduler = new TestScheduler((actual, expected) => {
23+
return expect(actual).toEqual(expected)
24+
})
25+
const testController = new TestController()
26+
const triggerMarbles = '-aaaa'
27+
const triggerValues = {
28+
a: () => testController.reEmit(),
29+
}
30+
31+
const expectedMarbles = '-aaaa'
32+
const expectedValues = {
33+
a: 0,
34+
}
35+
const eventObservable = testController.observable.pipe()
36+
testScheduler.run(({ expectObservable, cold }) => {
37+
expectObservable(eventObservable).toBe(expectedMarbles, expectedValues)
38+
expectObservable(cold(triggerMarbles, triggerValues).pipe(tap((fn) => fn())))
39+
})
40+
})
41+
42+
type DisplayRenderedProps = {
43+
buildWhen?: (prev: number, curr: number) => boolean
44+
stateComp?: (prev: number, curr: number) => boolean
45+
}
46+
const DisplayRendered = ({ buildWhen, stateComp }: DisplayRenderedProps) => {
47+
return (
48+
<Builder source={TestController} buildWhen={buildWhen} stateCompare={stateComp}>
49+
{(state, controller) => {
50+
return (
51+
<>
52+
<h1 data-testid='text'>{state}</h1>
53+
<h1 data-testid='controller'>{controller.constructor.name}</h1>
54+
</>
55+
)
56+
}}
57+
</Builder>
58+
)
59+
}
60+
61+
it('buildWhen respected', (done) => {
62+
const buildWhenFn = jest.fn((prev, curr) => prev === curr)
63+
const instance = new TestController()
64+
const { container } = render(
65+
<ControllerProvider ctor={TestController} source={instance}>
66+
<DisplayRendered buildWhen={buildWhenFn} />
67+
</ControllerProvider>,
68+
)
69+
instance.inc()
70+
instance.inc()
71+
instance.inc()
72+
instance.inc()
73+
instance.inc()
74+
expect(buildWhenFn).toHaveBeenCalledTimes(5)
75+
expect(buildWhenFn.mock.calls[0][0]).toBe(0)
76+
expect(buildWhenFn.mock.calls[0][1]).toBe(1)
77+
expect(buildWhenFn.mock.calls[1][0]).toBe(1)
78+
expect(buildWhenFn.mock.calls[1][1]).toBe(2)
79+
expect(buildWhenFn.mock.calls[2][0]).toBe(2)
80+
expect(buildWhenFn.mock.calls[2][1]).toBe(3)
81+
expect(buildWhenFn.mock.calls[3][0]).toBe(3)
82+
expect(buildWhenFn.mock.calls[3][1]).toBe(4)
83+
expect(buildWhenFn.mock.calls[4][0]).toBe(4)
84+
expect(buildWhenFn.mock.calls[4][1]).toBe(5)
85+
const rendered = getByTestId(container, 'text')
86+
const renderedText = rendered.textContent
87+
const expectedText = '0'
88+
expect(renderedText).toBe(expectedText)
89+
done()
90+
})
91+
92+
it('rerender on state changed', async () => {
93+
const instance = new TestController()
94+
const { container } = render(
95+
<ControllerProvider ctor={TestController} source={instance}>
96+
<DisplayRendered />
97+
</ControllerProvider>,
98+
)
99+
const rendered = getByTestId(container, 'text')
100+
const renderedText = rendered.textContent
101+
const expectedText = '0'
102+
expect(renderedText).toBe(expectedText)
103+
act(() => {
104+
instance.inc()
105+
instance.inc()
106+
instance.inc()
107+
instance.inc()
108+
instance.inc()
109+
})
110+
await waitFor(() => {
111+
const rendered = getByTestId(container, 'text')
112+
const renderedText = rendered.textContent
113+
const expectedText = '5'
114+
expect(renderedText).toBe(expectedText)
115+
})
116+
})
117+
118+
it('specified state compare respected', async () => {
119+
const stateCompareFn = jest.fn((prev, curr) => prev !== curr)
120+
const instance = new TestController()
121+
const { container } = render(
122+
<ControllerProvider ctor={TestController} source={instance}>
123+
<DisplayRendered stateComp={stateCompareFn} />
124+
</ControllerProvider>,
125+
)
126+
const rendered = getByTestId(container, 'text')
127+
const renderedText = rendered.textContent
128+
const expectedText = '0'
129+
expect(renderedText).toBe(expectedText)
130+
131+
act(() => {
132+
instance.inc()
133+
instance.inc()
134+
instance.inc()
135+
instance.inc()
136+
})
137+
await waitFor(() => {
138+
expect(stateCompareFn).toHaveBeenCalledTimes(4)
139+
expect(stateCompareFn.mock.calls[0][0]).toBe(0)
140+
expect(stateCompareFn.mock.calls[0][1]).toBe(1)
141+
expect(stateCompareFn.mock.calls[1][0]).toBe(0)
142+
expect(stateCompareFn.mock.calls[1][1]).toBe(2)
143+
expect(stateCompareFn.mock.calls[2][0]).toBe(0)
144+
expect(stateCompareFn.mock.calls[2][1]).toBe(3)
145+
expect(stateCompareFn.mock.calls[3][0]).toBe(0)
146+
expect(stateCompareFn.mock.calls[3][1]).toBe(4)
147+
const rendered = getByTestId(container, 'text')
148+
const renderedText = rendered.textContent
149+
const expectedText = '0'
150+
expect(renderedText).toBe(expectedText)
151+
})
152+
})
153+
154+
it('useBuilder cto return [state, controller]', () => {
155+
const instance = new TestController(5)
156+
const { container } = render(
157+
<ControllerProvider ctor={TestController} source={instance}>
158+
<DisplayRendered />
159+
</ControllerProvider>,
160+
)
161+
const renderedCount = getByTestId(container, 'text')
162+
const renderedText = renderedCount.textContent
163+
const expectedText = '5'
164+
expect(renderedText).toBe(expectedText)
165+
166+
const renderedController = getByTestId(container, 'controller')
167+
const renderedControllerText = renderedController.textContent
168+
const expectedControllerText = 'TestController'
169+
expect(renderedControllerText).toBe(expectedControllerText)
170+
})
171+
172+
it('throw error when not provided ctor', async () => {
173+
jest.spyOn(console, 'error').mockImplementation(() => jest.fn())
174+
175+
const renderer = () => {
176+
render(<DisplayRendered />)
177+
}
178+
await waitFor(() => expect(renderer).toThrow(ResourcesNotProvidedError))
179+
jest.restoreAllMocks()
180+
})

0 commit comments

Comments
 (0)