Skip to content

Commit d05cb03

Browse files
authored
test: add more test coverage (#1075)
1 parent 7769d47 commit d05cb03

File tree

8 files changed

+694
-8
lines changed

8 files changed

+694
-8
lines changed

.gitignore

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,13 @@ android/.idea
1212
flutter_export_environment.sh
1313
example/ios/Flutter/ephemeral/
1414

15+
# Coverage
16+
coverage/
17+
test/dlcov_references_test.dart
18+
dlcov.log
19+
1520
# IntelliJ related
1621
*.iml
1722
*.ipr
1823
*.iws
19-
.idea/
24+
.idea/

lib/src/inappmessage.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ class OSInAppMessageClickEvent extends JSONStringRepresentable {
1616

1717
String jsonRepresentation() {
1818
return convertToJsonString({
19-
'message': this.message,
20-
'result': this.result,
19+
'message': this.message.jsonRepresentation(),
20+
'result': this.result.jsonRepresentation(),
2121
});
2222
}
2323
}

lib/src/inappmessages.dart

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import 'dart:async';
2+
23
import 'package:flutter/services.dart';
34
import 'package:onesignal_flutter/onesignal_flutter.dart';
45
import 'package:onesignal_flutter/src/inappmessage.dart';
@@ -20,7 +21,7 @@ class OneSignalInAppMessages {
2021

2122
// constructor method
2223
OneSignalInAppMessages() {
23-
this._channel.setMethodCallHandler(_handleMethod);
24+
this._channel.setMethodCallHandler(handleMethod);
2425
}
2526

2627
List<OnClickInAppMessageListener> _clickListeners =
@@ -78,7 +79,8 @@ class OneSignalInAppMessages {
7879
}
7980

8081
// Private function that gets called by ObjC/Java
81-
Future<Null> _handleMethod(MethodCall call) async {
82+
// Exposed as public for testing purposes
83+
Future<Null> handleMethod(MethodCall call) async {
8284
if (call.method == 'OneSignal#onClickInAppMessage') {
8385
for (var listener in _clickListeners) {
8486
listener(

pubspec.yaml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ description: OneSignal is a free push notification service for mobile apps. This
33
version: 5.3.4
44
homepage: https://github.com/OneSignal/OneSignal-Flutter-SDK
55

6+
scripts:
7+
test: dlcov -c 80 --lcov-gen="flutter test --coverage" --include-untested-files=true
8+
69
flutter:
710
plugin:
811
platforms:
@@ -20,7 +23,9 @@ dev_dependencies:
2023
test: ^1.5.1
2124
flutter_test:
2225
sdk: flutter
26+
dlcov: ^4.2.1
27+
rps: ^0.9.1
2328

2429
environment:
25-
sdk: '>=2.12.0 <3.0.0'
26-
flutter: '>=1.10.0'
30+
sdk: ">=2.12.0 <3.0.0"
31+
flutter: ">=1.10.0"

test/debug_test.dart

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import 'package:flutter_test/flutter_test.dart';
2+
import 'package:onesignal_flutter/onesignal_flutter.dart';
3+
4+
import 'mock_channel.dart';
5+
6+
void main() {
7+
TestWidgetsFlutterBinding.ensureInitialized();
8+
9+
OneSignalMockChannelController channelController =
10+
OneSignalMockChannelController();
11+
12+
setUp(() {
13+
channelController.resetState();
14+
});
15+
16+
group('OneSignalDebug', () {
17+
group('setLogLevel', () {
18+
for (final logLevel in OSLogLevel.values) {
19+
test('sets log level to ${logLevel.toString().split('.').last}',
20+
() async {
21+
await OneSignal.Debug.setLogLevel(logLevel);
22+
expect(channelController.state.logLevel, logLevel);
23+
});
24+
}
25+
});
26+
27+
group('setAlertLevel', () {
28+
for (final logLevel in OSLogLevel.values) {
29+
test('sets alert level to ${logLevel.toString().split('.').last}',
30+
() async {
31+
await OneSignal.Debug.setAlertLevel(logLevel);
32+
expect(channelController.state.visualLevel, logLevel);
33+
});
34+
}
35+
});
36+
});
37+
}

test/inappmessage_test.dart

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
import 'package:flutter_test/flutter_test.dart';
2+
import 'package:onesignal_flutter/src/inappmessage.dart';
3+
import 'package:onesignal_flutter/src/utils.dart';
4+
5+
const validMessageJson = {
6+
'message_id': 'test-message-id-123',
7+
};
8+
9+
const validClickResultJson = {
10+
'action_id': 'action-123',
11+
'url': 'https://example.com',
12+
'closing_message': true,
13+
};
14+
15+
void _testMessageEvent<T extends JSONStringRepresentable>(
16+
String eventName,
17+
T Function(Map<String, dynamic>) constructor,
18+
) {
19+
group(eventName, () {
20+
test('creates from valid JSON with message', () {
21+
final json = {'message': validMessageJson};
22+
final event = constructor(json);
23+
expect(event, isNotNull);
24+
});
25+
26+
test('creates from JSON with null message_id', () {
27+
final json = {'message': <String, dynamic>{}};
28+
final event = constructor(json);
29+
expect(event, isNotNull);
30+
});
31+
32+
test('jsonRepresentation returns correct JSON string', () {
33+
final json = {'message': validMessageJson};
34+
final event = constructor(json);
35+
final jsonString = event.jsonRepresentation();
36+
expect(jsonString, contains('"message"'));
37+
});
38+
});
39+
}
40+
41+
void main() {
42+
group('OSInAppMessage', () {
43+
test('creates from valid JSON with message_id', () {
44+
final message = OSInAppMessage(validMessageJson);
45+
46+
expect(message.messageId, validMessageJson['message_id']);
47+
});
48+
49+
test('creates from JSON with null message_id', () {
50+
final json = <String, dynamic>{};
51+
final message = OSInAppMessage(json);
52+
53+
expect(message.messageId, isNull);
54+
});
55+
56+
test('jsonRepresentation returns correct JSON string', () {
57+
// Test with valid message_id
58+
final message1 = OSInAppMessage(validMessageJson);
59+
final jsonString1 = message1.jsonRepresentation();
60+
expect(jsonString1, contains('"message_id": "test-message-id-123"'));
61+
62+
// Test with null message_id
63+
final json = <String, dynamic>{};
64+
final message2 = OSInAppMessage(json);
65+
final jsonString2 = message2.jsonRepresentation();
66+
expect(jsonString2, contains('"message_id"'));
67+
expect(jsonString2, contains('null'));
68+
});
69+
});
70+
71+
group('OSInAppMessageClickResult', () {
72+
test('creates from valid JSON with all fields', () {
73+
final result = OSInAppMessageClickResult(validClickResultJson);
74+
75+
expect(result.actionId, 'action-123');
76+
expect(result.url, 'https://example.com');
77+
expect(result.closingMessage, true);
78+
});
79+
80+
test('creates from minimal JSON', () {
81+
final json = <String, dynamic>{
82+
'closing_message': false,
83+
};
84+
final result = OSInAppMessageClickResult(json);
85+
86+
expect(result.actionId, isNull);
87+
expect(result.url, isNull);
88+
expect(result.closingMessage, false);
89+
});
90+
91+
test('jsonRepresentation returns correct JSON string', () {
92+
final result = OSInAppMessageClickResult(validClickResultJson);
93+
final jsonString = result.jsonRepresentation();
94+
95+
expect(jsonString, contains('"action_id": "action-123"'));
96+
expect(jsonString, contains('"url": "https://example.com"'));
97+
expect(jsonString, contains('"closing_message": true'));
98+
});
99+
100+
test('jsonRepresentation handles null optional fields', () {
101+
final json = <String, dynamic>{
102+
'closing_message': false,
103+
};
104+
final result = OSInAppMessageClickResult(json);
105+
final jsonString = result.jsonRepresentation();
106+
107+
expect(jsonString, contains('"action_id": null'));
108+
expect(jsonString, contains('"url": null'));
109+
expect(jsonString, contains('"closing_message": false'));
110+
});
111+
});
112+
113+
group('OSInAppMessageClickEvent', () {
114+
test('creates from valid JSON with message and result', () {
115+
final json = {
116+
'message': validMessageJson,
117+
'result': validClickResultJson,
118+
'closing_message': false,
119+
};
120+
final event = OSInAppMessageClickEvent(json);
121+
122+
expect(event.message.messageId, 'test-message-id-123');
123+
expect(event.result.actionId, 'action-123');
124+
expect(event.result.url, 'https://example.com');
125+
expect(event.result.closingMessage, true);
126+
});
127+
128+
test('creates from JSON with minimal fields', () {
129+
final json = {
130+
'message': validMessageJson,
131+
'result': {
132+
'closing_message': false,
133+
},
134+
};
135+
final event = OSInAppMessageClickEvent(json);
136+
137+
expect(event.message.messageId, 'test-message-id-123');
138+
expect(event.result.actionId, isNull);
139+
expect(event.result.url, isNull);
140+
expect(event.result.closingMessage, false);
141+
});
142+
143+
test('jsonRepresentation returns correct JSON string', () {
144+
final json = {
145+
'message': {
146+
'message_id': 'test-message-id-123',
147+
},
148+
'result': {
149+
'action_id': 'action-123',
150+
'url': 'https://example.com',
151+
'closing_message': true,
152+
},
153+
};
154+
final event = OSInAppMessageClickEvent(json);
155+
final jsonString = event.jsonRepresentation();
156+
157+
expect(jsonString, contains('"message"'));
158+
expect(jsonString, contains('"result"'));
159+
});
160+
});
161+
162+
_testMessageEvent(
163+
'OSInAppMessageWillDisplayEvent',
164+
(json) => OSInAppMessageWillDisplayEvent(json),
165+
);
166+
_testMessageEvent(
167+
'OSInAppMessageDidDisplayEvent',
168+
(json) => OSInAppMessageDidDisplayEvent(json),
169+
);
170+
_testMessageEvent(
171+
'OSInAppMessageWillDismissEvent',
172+
(json) => OSInAppMessageWillDismissEvent(json),
173+
);
174+
_testMessageEvent(
175+
'OSInAppMessageDidDismissEvent',
176+
(json) => OSInAppMessageDidDismissEvent(json),
177+
);
178+
}

0 commit comments

Comments
 (0)