Skip to content

Commit 0e0022a

Browse files
committed
add test for listener
1 parent 346fd48 commit 0e0022a

File tree

2 files changed

+364
-0
lines changed

2 files changed

+364
-0
lines changed
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
import { TestScheduler } from 'rxjs/testing'
2+
import { Controller, Listener } from '../../src'
3+
import { getByTestId, render } 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+
callback: (state: number) => void
45+
listenWhen?: (prev: number, curr: number) => boolean
46+
stateComp?: (prev: number, curr: number) => boolean
47+
}
48+
const DisplayRendered = ({ source, callback, listenWhen, stateComp }: DisplayRenderedProps) => {
49+
return (
50+
<Listener source={source} listener={callback} listenWhen={listenWhen} stateCompare={stateComp}>
51+
<h1 data-testid='text'>Rendered</h1>
52+
</Listener>
53+
)
54+
}
55+
56+
it('listenWhen respected', (done) => {
57+
const callbackFn = jest.fn((state) => state)
58+
const listenWhenFn = jest.fn((prev, curr) => prev === curr)
59+
const instance = new TestController()
60+
const { container } = render(<DisplayRendered source={instance} callback={callbackFn} listenWhen={listenWhenFn} />)
61+
const rendered = getByTestId(container, 'text')
62+
const renderedText = rendered.textContent
63+
const expectedText = 'Rendered'
64+
expect(renderedText).toBe(expectedText)
65+
instance.inc()
66+
instance.inc()
67+
instance.inc()
68+
instance.inc()
69+
instance.inc()
70+
expect(callbackFn).toHaveBeenCalledTimes(0)
71+
expect(listenWhenFn).toHaveBeenCalledTimes(5)
72+
expect(listenWhenFn.mock.calls[0][0]).toBe(0)
73+
expect(listenWhenFn.mock.calls[0][1]).toBe(1)
74+
expect(listenWhenFn.mock.calls[1][0]).toBe(1)
75+
expect(listenWhenFn.mock.calls[1][1]).toBe(2)
76+
expect(listenWhenFn.mock.calls[2][0]).toBe(2)
77+
expect(listenWhenFn.mock.calls[2][1]).toBe(3)
78+
expect(listenWhenFn.mock.calls[3][0]).toBe(3)
79+
expect(listenWhenFn.mock.calls[3][1]).toBe(4)
80+
expect(listenWhenFn.mock.calls[4][0]).toBe(4)
81+
expect(listenWhenFn.mock.calls[4][1]).toBe(5)
82+
done()
83+
})
84+
85+
it('listener called', (done) => {
86+
const callbackFn = jest.fn((x: number) => x)
87+
const instance = new TestController()
88+
const { container } = render(<DisplayRendered source={instance} callback={callbackFn} />)
89+
const rendered = getByTestId(container, 'text')
90+
const renderedText = rendered.textContent
91+
const expectedText = 'Rendered'
92+
expect(renderedText).toBe(expectedText)
93+
instance.inc()
94+
instance.inc()
95+
instance.inc()
96+
instance.inc()
97+
instance.inc()
98+
expect(callbackFn).toHaveBeenCalledTimes(5)
99+
expect(callbackFn.mock.calls[0][0]).toBe(1)
100+
expect(callbackFn.mock.calls[1][0]).toBe(2)
101+
expect(callbackFn.mock.calls[2][0]).toBe(3)
102+
expect(callbackFn.mock.calls[3][0]).toBe(4)
103+
expect(callbackFn.mock.calls[4][0]).toBe(5)
104+
done()
105+
})
106+
107+
it('default state compare respected', (done) => {
108+
const callbackFn = jest.fn((x: number) => x)
109+
const instance = new TestController()
110+
const { container } = render(<DisplayRendered source={instance} callback={callbackFn} />)
111+
const rendered = getByTestId(container, 'text')
112+
const renderedText = rendered.textContent
113+
const expectedText = 'Rendered'
114+
expect(renderedText).toBe(expectedText)
115+
instance.inc()
116+
instance.reEmit()
117+
instance.reEmit()
118+
instance.reEmit()
119+
instance.reEmit()
120+
instance.reEmit()
121+
expect(callbackFn).toHaveBeenCalledTimes(1)
122+
expect(callbackFn.mock.calls[0][0]).toBe(1)
123+
done()
124+
})
125+
126+
it('specified state compare respected', (done) => {
127+
const callbackFn = jest.fn((x: number) => x)
128+
const instance = new TestController()
129+
const { container } = render(
130+
<DisplayRendered source={instance} callback={callbackFn} listenWhen={() => true} stateComp={() => false} />,
131+
)
132+
const rendered = getByTestId(container, 'text')
133+
const renderedText = rendered.textContent
134+
const expectedText = 'Rendered'
135+
expect(renderedText).toBe(expectedText)
136+
instance.inc()
137+
instance.reEmit()
138+
instance.reEmit()
139+
instance.reEmit()
140+
instance.reEmit()
141+
instance.reEmit()
142+
expect(callbackFn).toHaveBeenCalledTimes(6)
143+
expect(callbackFn.mock.calls[0][0]).toBe(1)
144+
expect(callbackFn.mock.calls[0][0]).toBe(1)
145+
expect(callbackFn.mock.calls[1][0]).toBe(1)
146+
expect(callbackFn.mock.calls[2][0]).toBe(1)
147+
expect(callbackFn.mock.calls[3][0]).toBe(1)
148+
expect(callbackFn.mock.calls[4][0]).toBe(1)
149+
done()
150+
})
151+
152+
type DisplayRenderedProvidedProps = {
153+
source: TestController
154+
}
155+
156+
const DisplayRenderedProvided = ({ source }: DisplayRenderedProvidedProps) => {
157+
return (
158+
<Listener source={source} listener={() => {}}>
159+
<h1 data-testid='text'>Rendered: {source.state}</h1>
160+
</Listener>
161+
)
162+
}
163+
164+
it('ctor useListener return controller', () => {
165+
const instance = new TestController(5)
166+
const { container } = render(<DisplayRenderedProvided source={instance} />)
167+
const rendered = getByTestId(container, 'text')
168+
const renderedText = rendered.textContent
169+
const expectedText = 'Rendered: 5'
170+
expect(renderedText).toBe(expectedText)
171+
})

tests/Listener/listener_ctor.test.tsx

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
import { TestScheduler } from 'rxjs/testing'
2+
import { Controller, ControllerProvider, ResourcesNotProvidedError, Listener } from '../../src'
3+
import { 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+
callback: (state: number) => void
44+
listenWhen?: (prev: number, curr: number) => boolean
45+
stateComp?: (prev: number, curr: number) => boolean
46+
}
47+
const DisplayRendered = ({ callback, listenWhen, stateComp }: DisplayRenderedProps) => {
48+
return (
49+
<Listener source={TestController} listener={callback} listenWhen={listenWhen} stateCompare={stateComp}>
50+
<h1 data-testid='text'>Rendered</h1>
51+
</Listener>
52+
)
53+
}
54+
it('listenWhen respected', (done) => {
55+
const callbackFn = jest.fn((state) => state)
56+
const listenWhenFn = jest.fn((prev, curr) => prev === curr)
57+
const instance = new TestController()
58+
const { container } = render(
59+
<ControllerProvider ctor={TestController} source={instance}>
60+
<DisplayRendered callback={callbackFn} listenWhen={listenWhenFn} />
61+
</ControllerProvider>,
62+
)
63+
const rendered = getByTestId(container, 'text')
64+
const renderedText = rendered.textContent
65+
const expectedText = 'Rendered'
66+
expect(renderedText).toBe(expectedText)
67+
instance.inc()
68+
instance.inc()
69+
instance.inc()
70+
instance.inc()
71+
instance.inc()
72+
expect(callbackFn).toHaveBeenCalledTimes(0)
73+
expect(listenWhenFn).toHaveBeenCalledTimes(5)
74+
expect(listenWhenFn.mock.calls[0][0]).toBe(0)
75+
expect(listenWhenFn.mock.calls[0][1]).toBe(1)
76+
expect(listenWhenFn.mock.calls[1][0]).toBe(1)
77+
expect(listenWhenFn.mock.calls[1][1]).toBe(2)
78+
expect(listenWhenFn.mock.calls[2][0]).toBe(2)
79+
expect(listenWhenFn.mock.calls[2][1]).toBe(3)
80+
expect(listenWhenFn.mock.calls[3][0]).toBe(3)
81+
expect(listenWhenFn.mock.calls[3][1]).toBe(4)
82+
expect(listenWhenFn.mock.calls[4][0]).toBe(4)
83+
expect(listenWhenFn.mock.calls[4][1]).toBe(5)
84+
done()
85+
})
86+
87+
it('listener called', (done) => {
88+
const callbackFn = jest.fn((x: number) => x)
89+
const instance = new TestController()
90+
const { container } = render(
91+
<ControllerProvider ctor={TestController} source={instance}>
92+
<DisplayRendered callback={callbackFn} />
93+
</ControllerProvider>,
94+
)
95+
const rendered = getByTestId(container, 'text')
96+
const renderedText = rendered.textContent
97+
const expectedText = 'Rendered'
98+
expect(renderedText).toBe(expectedText)
99+
instance.inc()
100+
instance.inc()
101+
instance.inc()
102+
instance.inc()
103+
instance.inc()
104+
expect(callbackFn).toHaveBeenCalledTimes(5)
105+
expect(callbackFn.mock.calls[0][0]).toBe(1)
106+
expect(callbackFn.mock.calls[1][0]).toBe(2)
107+
expect(callbackFn.mock.calls[2][0]).toBe(3)
108+
expect(callbackFn.mock.calls[3][0]).toBe(4)
109+
expect(callbackFn.mock.calls[4][0]).toBe(5)
110+
done()
111+
})
112+
113+
it('default state compare respected', (done) => {
114+
const callbackFn = jest.fn((x: number) => x)
115+
const instance = new TestController()
116+
const { container } = render(
117+
<ControllerProvider ctor={TestController} source={instance}>
118+
<DisplayRendered callback={callbackFn} />
119+
</ControllerProvider>,
120+
)
121+
const rendered = getByTestId(container, 'text')
122+
const renderedText = rendered.textContent
123+
const expectedText = 'Rendered'
124+
expect(renderedText).toBe(expectedText)
125+
instance.inc()
126+
instance.reEmit()
127+
instance.reEmit()
128+
instance.reEmit()
129+
instance.reEmit()
130+
instance.reEmit()
131+
expect(callbackFn).toHaveBeenCalledTimes(1)
132+
expect(callbackFn.mock.calls[0][0]).toBe(1)
133+
done()
134+
})
135+
136+
it('specified state compare respected', (done) => {
137+
const callbackFn = jest.fn((x: number) => x)
138+
const instance = new TestController()
139+
const { container } = render(
140+
<ControllerProvider ctor={TestController} source={instance}>
141+
<DisplayRendered callback={callbackFn} listenWhen={() => true} stateComp={() => false} />
142+
</ControllerProvider>,
143+
)
144+
const rendered = getByTestId(container, 'text')
145+
const renderedText = rendered.textContent
146+
const expectedText = 'Rendered'
147+
expect(renderedText).toBe(expectedText)
148+
instance.inc()
149+
instance.reEmit()
150+
instance.reEmit()
151+
instance.reEmit()
152+
instance.reEmit()
153+
instance.reEmit()
154+
expect(callbackFn).toHaveBeenCalledTimes(6)
155+
expect(callbackFn.mock.calls[0][0]).toBe(1)
156+
expect(callbackFn.mock.calls[0][0]).toBe(1)
157+
expect(callbackFn.mock.calls[1][0]).toBe(1)
158+
expect(callbackFn.mock.calls[2][0]).toBe(1)
159+
expect(callbackFn.mock.calls[3][0]).toBe(1)
160+
expect(callbackFn.mock.calls[4][0]).toBe(1)
161+
done()
162+
})
163+
164+
const DisplayRenderedProvided = () => {
165+
return (
166+
<Listener source={TestController} listener={() => {}}>
167+
<h1 data-testid='text'>Rendered</h1>
168+
</Listener>
169+
)
170+
}
171+
172+
it('ctor useListener return controller', () => {
173+
const instance = new TestController(5)
174+
const { container } = render(
175+
<ControllerProvider ctor={TestController} source={instance}>
176+
<DisplayRenderedProvided />
177+
</ControllerProvider>,
178+
)
179+
const rendered = getByTestId(container, 'text')
180+
const renderedText = rendered.textContent
181+
const expectedText = 'Rendered'
182+
expect(renderedText).toBe(expectedText)
183+
})
184+
185+
it('throw error when not provided ctor', async () => {
186+
jest.spyOn(console, 'error').mockImplementation(() => jest.fn())
187+
188+
const renderer = () => {
189+
render(<DisplayRenderedProvided />)
190+
}
191+
await waitFor(() => expect(renderer).toThrow(ResourcesNotProvidedError))
192+
jest.restoreAllMocks()
193+
})

0 commit comments

Comments
 (0)