Skip to content

Commit 6a64167

Browse files
committed
more tests
1 parent dbd3b59 commit 6a64167

File tree

3 files changed

+157
-5
lines changed

3 files changed

+157
-5
lines changed
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
import { vi, describe, it, expect, beforeEach } from 'vitest';
2+
3+
const mockNetInfo = vi.hoisted(() => {
4+
const netInfo = {
5+
listeners: [],
6+
unsubs: [],
7+
addEventListener(fn: any) {
8+
this.listeners.push(fn);
9+
const unsub = vi.fn();
10+
this.unsubs.push(unsub);
11+
return unsub;
12+
},
13+
pushState(state: boolean) {
14+
for (const listener of this.listeners) {
15+
listener({ isInternetReachable: state });
16+
}
17+
},
18+
clear() {
19+
this.listeners = [];
20+
this.unsubs = [];
21+
}
22+
};
23+
return netInfo;
24+
});
25+
26+
vi.mock('@react-native-community/netinfo', () => {
27+
return {
28+
addEventListener: mockNetInfo.addEventListener.bind(mockNetInfo),
29+
};
30+
});
31+
32+
import { ReactNativeNetInfoEventProcessor } from './batch_event_processor.react_native';
33+
import { getMockLogger } from '../tests/mock/mock_logger';
34+
import { getMockRepeater } from '../tests/mock/mock_repeater';
35+
import { getMockAsyncCache } from '../tests/mock/mock_cache';
36+
import { createImpressionEvent } from '../tests/mock/create_event';
37+
import { EventWithId } from './batch_event_processor';
38+
import { formatEvents, ProcessableEvent } from '.';
39+
40+
const getMockDispatcher = () => {
41+
return {
42+
dispatchEvent: vi.fn(),
43+
};
44+
};
45+
46+
const exhaustMicrotasks = async (loop = 100) => {
47+
for(let i = 0; i < loop; i++) {
48+
await Promise.resolve();
49+
}
50+
}
51+
52+
53+
describe('ReactNativeNetInfoEventProcessor', () => {
54+
beforeEach(() => {
55+
mockNetInfo.clear();
56+
});
57+
58+
it('should not retry failed events when reachable state does not change', async () => {
59+
const eventDispatcher = getMockDispatcher();
60+
const dispatchRepeater = getMockRepeater();
61+
const failedEventRepeater = getMockRepeater();
62+
63+
const cache = getMockAsyncCache<EventWithId>();
64+
const events: ProcessableEvent[] = [];
65+
66+
for(let i = 0; i < 5; i++) {
67+
const id = `id-${i}`;
68+
const event = createImpressionEvent(id);
69+
events.push(event);
70+
await cache.set(id, { id, event });
71+
}
72+
73+
const processor = new ReactNativeNetInfoEventProcessor({
74+
eventDispatcher,
75+
dispatchRepeater,
76+
failedEventRepeater,
77+
batchSize: 1000,
78+
eventStore: cache,
79+
});
80+
81+
processor.start();
82+
await processor.onRunning();
83+
84+
mockNetInfo.pushState(true);
85+
expect(eventDispatcher.dispatchEvent).not.toHaveBeenCalled();
86+
87+
mockNetInfo.pushState(true);
88+
expect(eventDispatcher.dispatchEvent).not.toHaveBeenCalled();
89+
});
90+
91+
it('should retry failed events when network becomes reachable', async () => {
92+
const eventDispatcher = getMockDispatcher();
93+
const dispatchRepeater = getMockRepeater();
94+
const failedEventRepeater = getMockRepeater();
95+
96+
const cache = getMockAsyncCache<EventWithId>();
97+
const events: ProcessableEvent[] = [];
98+
99+
for(let i = 0; i < 5; i++) {
100+
const id = `id-${i}`;
101+
const event = createImpressionEvent(id);
102+
events.push(event);
103+
await cache.set(id, { id, event });
104+
}
105+
106+
const processor = new ReactNativeNetInfoEventProcessor({
107+
eventDispatcher,
108+
dispatchRepeater,
109+
failedEventRepeater,
110+
batchSize: 1000,
111+
eventStore: cache,
112+
});
113+
114+
processor.start();
115+
await processor.onRunning();
116+
117+
mockNetInfo.pushState(false);
118+
expect(eventDispatcher.dispatchEvent).not.toHaveBeenCalled();
119+
120+
mockNetInfo.pushState(true);
121+
122+
await exhaustMicrotasks();
123+
124+
expect(eventDispatcher.dispatchEvent).toHaveBeenCalledWith(formatEvents(events));
125+
});
126+
127+
it('should unsubscribe from netinfo listener when stopped', async () => {
128+
const eventDispatcher = getMockDispatcher();
129+
const dispatchRepeater = getMockRepeater();
130+
const failedEventRepeater = getMockRepeater();
131+
132+
const cache = getMockAsyncCache<EventWithId>();
133+
134+
const processor = new ReactNativeNetInfoEventProcessor({
135+
eventDispatcher,
136+
dispatchRepeater,
137+
failedEventRepeater,
138+
batchSize: 1000,
139+
eventStore: cache,
140+
});
141+
142+
processor.start();
143+
await processor.onRunning();
144+
145+
mockNetInfo.pushState(false);
146+
147+
processor.stop();
148+
await processor.onTerminated();
149+
150+
expect(mockNetInfo.unsubs[0]).toHaveBeenCalled();
151+
});
152+
});

lib/event_processor/batch_event_processor.react_native.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import {
22
NetInfoState,
33
addEventListener as addConnectionListener,
4-
} from "@react-native-community/netinfo"
4+
} from '@react-native-community/netinfo';
55

6-
import { BatchEventProcessor, BatchEventProcessorConfig } from "./batch_event_processor";
7-
import { Fn } from "../utils/type";
6+
import { BatchEventProcessor, BatchEventProcessorConfig } from './batch_event_processor';
7+
import { Fn } from '../utils/type';
88

9-
class ReactNativeNetInfoEventProcessor extends BatchEventProcessor {
9+
export class ReactNativeNetInfoEventProcessor extends BatchEventProcessor {
1010
private isInternetReachable = true;
1111
private unsubscribeNetInfo?: Fn;
1212

vitest.config.mts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export default defineConfig({
2020
test: {
2121
onConsoleLog: () => true,
2222
environment: 'happy-dom',
23-
include: ['**/batch_event_processor.spec.ts'],
23+
include: ['**/batch_event_processor.react_native.spec.ts'],
2424
typecheck: {
2525
tsconfig: 'tsconfig.spec.json',
2626
},

0 commit comments

Comments
 (0)