Skip to content

Commit e81416a

Browse files
committed
add pushsubscription test
1 parent 19d6365 commit e81416a

File tree

2 files changed

+287
-0
lines changed

2 files changed

+287
-0
lines changed

test/mock_channel.dart

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ class OneSignalMockChannelController {
2020
const MethodChannel('OneSignal#liveactivities');
2121
final MethodChannel _notificationsChannel =
2222
const MethodChannel('OneSignal#notifications');
23+
final MethodChannel _pushSubscriptionChannel =
24+
const MethodChannel('OneSignal#pushsubscription');
2325

2426
late OneSignalState state;
2527

@@ -38,12 +40,26 @@ class OneSignalMockChannelController {
3840
.setMockMethodCallHandler(_liveActivitiesChannel, _handleMethod);
3941
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
4042
.setMockMethodCallHandler(_notificationsChannel, _handleMethod);
43+
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
44+
.setMockMethodCallHandler(_pushSubscriptionChannel, _handleMethod);
4145
}
4246

4347
void resetState() {
4448
state = OneSignalState();
4549
}
4650

51+
// Helper method to simulate push subscription changes from native
52+
void simulatePushSubscriptionChange(Map<String, dynamic> changeData) {
53+
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
54+
.handlePlatformMessage(
55+
_pushSubscriptionChannel.name,
56+
_pushSubscriptionChannel.codec.encodeMethodCall(
57+
MethodCall('OneSignal#onPushSubscriptionChange', changeData),
58+
),
59+
(ByteData? data) {},
60+
);
61+
}
62+
4763
Future<dynamic> _handleMethod(MethodCall call) async {
4864
switch (call.method) {
4965
case "OneSignal#setAppId":
@@ -209,6 +225,20 @@ class OneSignalMockChannelController {
209225
case "OneSignal#proceedWithWillDisplay":
210226
state.proceedWithWillDisplayCalled = true;
211227
break;
228+
case "OneSignal#pushSubscriptionToken":
229+
return state.pushSubscriptionToken;
230+
case "OneSignal#pushSubscriptionId":
231+
return state.pushSubscriptionId;
232+
case "OneSignal#pushSubscriptionOptedIn":
233+
return state.pushSubscriptionOptedIn;
234+
case "OneSignal#optIn":
235+
state.pushSubscriptionOptInCalled = true;
236+
state.pushSubscriptionOptInCallCount++;
237+
break;
238+
case "OneSignal#optOut":
239+
state.pushSubscriptionOptOutCalled = true;
240+
state.pushSubscriptionOptOutCallCount++;
241+
break;
212242
}
213243
}
214244
}
@@ -283,6 +313,15 @@ class OneSignalState {
283313
int nativeClickListenerAddedCount = 0;
284314
bool? proceedWithWillDisplayCalled;
285315

316+
// push subscription
317+
String? pushSubscriptionId;
318+
String? pushSubscriptionToken;
319+
bool? pushSubscriptionOptedIn;
320+
bool pushSubscriptionOptInCalled = false;
321+
bool pushSubscriptionOptOutCalled = false;
322+
int pushSubscriptionOptInCallCount = 0;
323+
int pushSubscriptionOptOutCallCount = 0;
324+
286325
/*
287326
All of the following functions parse the MethodCall
288327
parameters, and sets properties on the object itself

test/pushsubscription_test.dart

Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
import 'package:flutter_test/flutter_test.dart';
2+
import 'package:onesignal_flutter/src/pushsubscription.dart';
3+
import 'package:onesignal_flutter/src/subscription.dart';
4+
5+
import 'mock_channel.dart';
6+
7+
void main() {
8+
TestWidgetsFlutterBinding.ensureInitialized();
9+
10+
group('OneSignalPushSubscription', () {
11+
late OneSignalPushSubscription pushSubscription;
12+
late OneSignalMockChannelController channelController;
13+
14+
setUp(() {
15+
channelController = OneSignalMockChannelController();
16+
channelController.resetState();
17+
pushSubscription = OneSignalPushSubscription();
18+
});
19+
20+
group('initial state', () {
21+
test('id, token, and optedIn are null initially', () {
22+
expect(pushSubscription.id, isNull);
23+
expect(pushSubscription.token, isNull);
24+
expect(pushSubscription.optedIn, isNull);
25+
});
26+
});
27+
28+
group('lifecycleInit', () {
29+
test('fetches and sets id, token, and optedIn', () async {
30+
channelController.state.pushSubscriptionId = 'test-id-123';
31+
channelController.state.pushSubscriptionToken = 'test-token-456';
32+
channelController.state.pushSubscriptionOptedIn = true;
33+
34+
await pushSubscription.lifecycleInit();
35+
36+
expect(pushSubscription.id, 'test-id-123');
37+
expect(pushSubscription.token, 'test-token-456');
38+
expect(pushSubscription.optedIn, true);
39+
expect(channelController.state.lifecycleInitCalled, true);
40+
});
41+
42+
test('handles null values from native', () async {
43+
channelController.state.pushSubscriptionId = null;
44+
channelController.state.pushSubscriptionToken = null;
45+
channelController.state.pushSubscriptionOptedIn = false;
46+
47+
await pushSubscription.lifecycleInit();
48+
49+
expect(pushSubscription.id, isNull);
50+
expect(pushSubscription.token, isNull);
51+
expect(pushSubscription.optedIn, false);
52+
});
53+
54+
test('updates state when values change', () async {
55+
channelController.state.pushSubscriptionId = 'id-1';
56+
channelController.state.pushSubscriptionToken = 'token-1';
57+
channelController.state.pushSubscriptionOptedIn = false;
58+
59+
await pushSubscription.lifecycleInit();
60+
61+
expect(pushSubscription.id, 'id-1');
62+
expect(pushSubscription.token, 'token-1');
63+
expect(pushSubscription.optedIn, false);
64+
65+
// Change mock state
66+
channelController.state.pushSubscriptionId = 'id-2';
67+
channelController.state.pushSubscriptionToken = 'token-2';
68+
channelController.state.pushSubscriptionOptedIn = true;
69+
70+
await pushSubscription.lifecycleInit();
71+
72+
expect(pushSubscription.id, 'id-2');
73+
expect(pushSubscription.token, 'token-2');
74+
expect(pushSubscription.optedIn, true);
75+
});
76+
});
77+
78+
group('optIn', () {
79+
test('calls native optIn method', () async {
80+
await pushSubscription.optIn();
81+
82+
expect(channelController.state.pushSubscriptionOptInCalled, true);
83+
});
84+
85+
test('can be called multiple times', () async {
86+
await pushSubscription.optIn();
87+
await pushSubscription.optIn();
88+
await pushSubscription.optIn();
89+
90+
expect(channelController.state.pushSubscriptionOptInCallCount, 3);
91+
});
92+
});
93+
94+
group('optOut', () {
95+
test('calls native optOut method', () async {
96+
await pushSubscription.optOut();
97+
98+
expect(channelController.state.pushSubscriptionOptOutCalled, true);
99+
});
100+
101+
test('can be called multiple times', () async {
102+
await pushSubscription.optOut();
103+
await pushSubscription.optOut();
104+
105+
expect(channelController.state.pushSubscriptionOptOutCallCount, 2);
106+
});
107+
});
108+
109+
group('observers', () {
110+
test('can add observer', () {
111+
bool observerCalled = false;
112+
113+
pushSubscription.addObserver((stateChanges) {
114+
observerCalled = true;
115+
});
116+
117+
// Trigger a change via mock channel
118+
final changeData = {
119+
'current': {'id': 'new-id', 'token': 'new-token', 'optedIn': true},
120+
'previous': {'id': 'old-id', 'token': 'old-token', 'optedIn': false},
121+
};
122+
123+
channelController.simulatePushSubscriptionChange(changeData);
124+
125+
expect(observerCalled, true);
126+
});
127+
128+
test('can add multiple observers', () {
129+
int observer1CallCount = 0;
130+
int observer2CallCount = 0;
131+
132+
pushSubscription.addObserver((stateChanges) {
133+
observer1CallCount++;
134+
});
135+
136+
pushSubscription.addObserver((stateChanges) {
137+
observer2CallCount++;
138+
});
139+
140+
final changeData = {
141+
'current': {'id': 'id', 'token': 'token', 'optedIn': true},
142+
'previous': {'id': 'id', 'token': 'token', 'optedIn': false},
143+
};
144+
145+
channelController.simulatePushSubscriptionChange(changeData);
146+
147+
expect(observer1CallCount, 1);
148+
expect(observer2CallCount, 1);
149+
});
150+
151+
test('can remove observer', () {
152+
int callCount = 0;
153+
154+
void observer(OSPushSubscriptionChangedState stateChanges) {
155+
callCount++;
156+
}
157+
158+
pushSubscription.addObserver(observer);
159+
pushSubscription.removeObserver(observer);
160+
161+
final changeData = {
162+
'current': {'id': 'id', 'token': 'token', 'optedIn': true},
163+
'previous': {'id': 'id', 'token': 'token', 'optedIn': false},
164+
};
165+
166+
channelController.simulatePushSubscriptionChange(changeData);
167+
168+
expect(callCount, 0);
169+
});
170+
171+
test('observer receives correct state changes', () {
172+
OSPushSubscriptionChangedState? receivedState;
173+
174+
pushSubscription.addObserver((stateChanges) {
175+
receivedState = stateChanges;
176+
});
177+
178+
final changeData = {
179+
'current': {'id': 'new-id', 'token': 'new-token', 'optedIn': true},
180+
'previous': {'id': 'old-id', 'token': 'old-token', 'optedIn': false},
181+
};
182+
183+
channelController.simulatePushSubscriptionChange(changeData);
184+
185+
expect(receivedState, isNotNull);
186+
expect(receivedState!.current.id, 'new-id');
187+
expect(receivedState!.current.token, 'new-token');
188+
expect(receivedState!.current.optedIn, true);
189+
expect(receivedState!.previous.id, 'old-id');
190+
expect(receivedState!.previous.token, 'old-token');
191+
expect(receivedState!.previous.optedIn, false);
192+
});
193+
});
194+
195+
group('onPushSubscriptionChange', () {
196+
test('updates internal state when subscription changes', () async {
197+
channelController.state.pushSubscriptionId = 'initial-id';
198+
channelController.state.pushSubscriptionToken = 'initial-token';
199+
channelController.state.pushSubscriptionOptedIn = false;
200+
201+
await pushSubscription.lifecycleInit();
202+
203+
expect(pushSubscription.id, 'initial-id');
204+
expect(pushSubscription.token, 'initial-token');
205+
expect(pushSubscription.optedIn, false);
206+
207+
// Simulate a subscription change
208+
final changeData = {
209+
'current': {
210+
'id': 'updated-id',
211+
'token': 'updated-token',
212+
'optedIn': true
213+
},
214+
'previous': {
215+
'id': 'initial-id',
216+
'token': 'initial-token',
217+
'optedIn': false
218+
},
219+
};
220+
221+
channelController.simulatePushSubscriptionChange(changeData);
222+
223+
expect(pushSubscription.id, 'updated-id');
224+
expect(pushSubscription.token, 'updated-token');
225+
expect(pushSubscription.optedIn, true);
226+
});
227+
228+
test('handles null values in state changes', () async {
229+
channelController.state.pushSubscriptionId = 'id';
230+
channelController.state.pushSubscriptionToken = 'token';
231+
channelController.state.pushSubscriptionOptedIn = true;
232+
233+
await pushSubscription.lifecycleInit();
234+
235+
final changeData = {
236+
'current': {'id': null, 'token': null, 'optedIn': false},
237+
'previous': {'id': 'id', 'token': 'token', 'optedIn': true},
238+
};
239+
240+
channelController.simulatePushSubscriptionChange(changeData);
241+
242+
expect(pushSubscription.id, isNull);
243+
expect(pushSubscription.token, isNull);
244+
expect(pushSubscription.optedIn, false);
245+
});
246+
});
247+
});
248+
}

0 commit comments

Comments
 (0)