Skip to content

Commit b44c1b9

Browse files
committed
Split up core and integration tests, refactor preact tests for X.
1 parent a84fc5c commit b44c1b9

File tree

4 files changed

+314
-347
lines changed

4 files changed

+314
-347
lines changed

test/preact/preact.test.js

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
import { h, render } from 'preact';
2+
import createStore from '../../src';
3+
import { Provider, connect } from '../../src/integrations/preact';
4+
5+
const sleep = ms => new Promise( r => setTimeout(r, ms) );
6+
7+
describe('integrations/preact', () => {
8+
describe('<Provider>', () => {
9+
afterEach(() => {
10+
render(null, document.body);
11+
});
12+
13+
it('should provide props into context', () => {
14+
const Child = jest.fn();
15+
16+
render(
17+
<Provider store="a">
18+
<Child />
19+
</Provider>,
20+
document.body
21+
);
22+
expect(Child).toHaveBeenCalledWith(expect.anything(), { store: 'a' });
23+
24+
render(null, document.body);
25+
26+
let store = { name: 'obj' };
27+
render(
28+
<Provider store={store}>
29+
<Child />
30+
</Provider>,
31+
document.body
32+
);
33+
expect(Child).toHaveBeenCalledWith(expect.anything(), { store });
34+
});
35+
});
36+
37+
describe('connect()', () => {
38+
afterEach(async () => {
39+
render(null, document.body);
40+
await sleep(1);
41+
});
42+
43+
it('should pass mapped state as props', () => {
44+
let state = { a: 'b' };
45+
const store = { subscribe: jest.fn(), unsubscribe: jest.fn(), getState: () => state };
46+
const Child = jest.fn();
47+
const ConnectedChild = connect(Object)(Child);
48+
render(
49+
<Provider store={store}>
50+
<ConnectedChild />
51+
</Provider>,
52+
document.body
53+
);
54+
expect(Child).toHaveBeenCalledWith(
55+
{ a: 'b', store },
56+
expect.anything()
57+
);
58+
expect(store.subscribe).toBeCalled();
59+
});
60+
61+
it('should transform string selector', () => {
62+
let state = { a: 'b', b: 'c', c: 'd' };
63+
const store = { subscribe: jest.fn(), unsubscribe: jest.fn(), getState: () => state };
64+
const Child = jest.fn();
65+
const ConnectedChild = connect('a, b')(Child);
66+
render(
67+
<Provider store={store}>
68+
<ConnectedChild />
69+
</Provider>,
70+
document.body
71+
);
72+
expect(Child).toHaveBeenCalledWith(
73+
{ a: 'b', b: 'c', store },
74+
expect.anything()
75+
);
76+
expect(store.subscribe).toBeCalled();
77+
});
78+
79+
it('should subscribe to store on mount', async () => {
80+
const store = { subscribe: jest.fn(), unsubscribe: jest.fn(), getState: () => ({}) };
81+
jest.spyOn(store, 'subscribe');
82+
const ConnectedChild = connect(Object)(() => null);
83+
84+
render(
85+
<Provider store={store}>
86+
<ConnectedChild />
87+
</Provider>,
88+
document.body
89+
);
90+
91+
expect(store.subscribe).toBeCalledWith(expect.any(Function));
92+
});
93+
94+
it('should unsubscribe from store when unmounted', async () => {
95+
const store = createStore();
96+
jest.spyOn(store, 'unsubscribe');
97+
const ConnectedChild = connect(Object)(() => null);
98+
render(
99+
<Provider store={store}>
100+
<ConnectedChild />
101+
</Provider>,
102+
document.body
103+
);
104+
await sleep(1);
105+
render(null, document.body);
106+
expect(store.unsubscribe).toBeCalled();
107+
});
108+
109+
it('should subscribe to store', async () => {
110+
const store = createStore();
111+
const Child = jest.fn();
112+
jest.spyOn(store, 'subscribe');
113+
jest.spyOn(store, 'unsubscribe');
114+
const ConnectedChild = connect(Object)(Child);
115+
116+
render(
117+
<Provider store={store}>
118+
<ConnectedChild />
119+
</Provider>,
120+
document.body
121+
);
122+
123+
expect(store.subscribe).toBeCalledWith(expect.any(Function));
124+
expect(Child).toHaveBeenCalledWith(
125+
{ store },
126+
expect.anything()
127+
);
128+
129+
Child.mockClear();
130+
131+
store.setState({ a: 'b' });
132+
await sleep(1);
133+
expect(Child).toHaveBeenCalledWith(
134+
{ a: 'b', store },
135+
expect.anything()
136+
);
137+
138+
render(null, document.body);
139+
expect(store.unsubscribe).toBeCalled();
140+
141+
Child.mockClear();
142+
143+
store.setState({ c: 'd' });
144+
await sleep(1);
145+
expect(Child).not.toHaveBeenCalled();
146+
});
147+
148+
it('should run mapStateToProps and update when outer props change', async () => {
149+
let state = {};
150+
const store = { subscribe: jest.fn(), unsubscribe: () => {}, getState: () => state };
151+
const Child = jest.fn().mockName('<Child>').mockReturnValue(42);
152+
let mappings = 0;
153+
154+
// Jest mock return values are broken :(
155+
const mapStateToProps = jest.fn((state, props) => ({
156+
mappings: ++mappings,
157+
...props
158+
}));
159+
160+
const ConnectedChild = connect(mapStateToProps)(Child);
161+
const ref = {};
162+
render(
163+
<Provider store={store}>
164+
<ConnectedChild ref={ref} />
165+
</Provider>,
166+
document.body
167+
);
168+
let c = ref.current;
169+
170+
expect(mapStateToProps).toHaveBeenCalledTimes(1);
171+
expect(mapStateToProps).toHaveBeenCalledWith({}, { });
172+
// first render calls mapStateToProps
173+
expect(Child).toHaveBeenCalledWith(
174+
{ mappings: 1, store },
175+
expect.anything()
176+
);
177+
178+
mapStateToProps.mockClear();
179+
Child.mockClear();
180+
181+
render(
182+
<Provider store={store}>
183+
<ConnectedChild a="b" />
184+
</Provider>,
185+
document.body
186+
);
187+
188+
expect(mapStateToProps).toHaveBeenCalledTimes(1);
189+
expect(mapStateToProps).toHaveBeenCalledWith({ }, { a: 'b' });
190+
// outer props were changed
191+
expect(Child).toHaveBeenCalledWith(
192+
{ mappings: 2, a: 'b', store },
193+
expect.anything()
194+
);
195+
196+
mapStateToProps.mockClear();
197+
Child.mockClear();
198+
199+
render(
200+
<Provider store={store}>
201+
<ConnectedChild a="b" />
202+
</Provider>,
203+
document.body
204+
);
205+
206+
expect(mapStateToProps).toHaveBeenCalledTimes(1);
207+
expect(mapStateToProps).toHaveBeenCalledWith({ }, { a: 'b' });
208+
209+
// re-rendered, but outer props were not changed
210+
expect(Child).toHaveBeenCalledWith(
211+
{ mappings: 3, a: 'b', store },
212+
expect.anything()
213+
);
214+
});
215+
});
216+
});

0 commit comments

Comments
 (0)