204 lines
6.2 KiB
Dart
204 lines
6.2 KiB
Dart
import 'dart:async';
|
|
|
|
import 'package:flutter/services.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:mattermost_push_plugin/mattermost_push_plugin.dart';
|
|
|
|
void main() {
|
|
TestWidgetsFlutterBinding.ensureInitialized();
|
|
|
|
group('NotificationOpenedEvent.fromMap', () {
|
|
test('parses server_url, channel_id, root_id, is_crt_enabled', () {
|
|
final event = NotificationOpenedEvent.fromMap({
|
|
'server_url': 'https://mm.example.com',
|
|
'channel_id': 'channel-123',
|
|
'root_id': 'root-456',
|
|
'is_crt_enabled': 'true',
|
|
});
|
|
|
|
expect(event.serverUrl, 'https://mm.example.com');
|
|
expect(event.channelId, 'channel-123');
|
|
expect(event.rootId, 'root-456');
|
|
expect(event.isCRTEnabled, isTrue);
|
|
});
|
|
|
|
test('defaults isCRTEnabled to false when flag is absent or non-true', () {
|
|
final missing = NotificationOpenedEvent.fromMap({
|
|
'server_url': 'https://mm.example.com',
|
|
'channel_id': 'channel-123',
|
|
});
|
|
expect(missing.isCRTEnabled, isFalse);
|
|
|
|
final falsy = NotificationOpenedEvent.fromMap({
|
|
'is_crt_enabled': 'false',
|
|
});
|
|
expect(falsy.isCRTEnabled, isFalse);
|
|
});
|
|
});
|
|
|
|
group('MattermostPushPlugin.handleNativeEvent', () {
|
|
late MattermostPushPlugin plugin;
|
|
final actionChannel = MethodChannel(MattermostPushPlugin.actionChannelName);
|
|
|
|
setUp(() {
|
|
plugin = MattermostPushPlugin.instance;
|
|
plugin.onNavigateToChannel = null;
|
|
plugin.onNavigateToThread = null;
|
|
plugin.onDeviceTokenReady = null;
|
|
});
|
|
|
|
tearDown(() {
|
|
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
|
|
.setMockMethodCallHandler(actionChannel, null);
|
|
});
|
|
|
|
test('opened event emits NotificationOpenedEvent on stream', () async {
|
|
final future = plugin.onNotificationOpened.first;
|
|
|
|
plugin.handleNativeEvent({
|
|
'type': PushNotificationType.opened,
|
|
'server_url': 'https://mm.example.com',
|
|
'channel_id': 'channel-123',
|
|
});
|
|
|
|
final event = await future;
|
|
expect(event.serverUrl, 'https://mm.example.com');
|
|
expect(event.channelId, 'channel-123');
|
|
});
|
|
|
|
test(
|
|
'message event with userInteraction routes through opened handler',
|
|
() async {
|
|
String? navServer;
|
|
String? navChannel;
|
|
plugin.onNavigateToChannel = (s, c) {
|
|
navServer = s;
|
|
navChannel = c;
|
|
};
|
|
|
|
plugin.handleNativeEvent({
|
|
'type': PushNotificationType.message,
|
|
'userInteraction': true,
|
|
'server_url': 'https://mm.example.com',
|
|
'channel_id': 'channel-xyz',
|
|
});
|
|
|
|
expect(navServer, 'https://mm.example.com');
|
|
expect(navChannel, 'channel-xyz');
|
|
},
|
|
);
|
|
|
|
test('opened event with CRT and rootId routes to thread callback', () {
|
|
String? navServer;
|
|
String? navRoot;
|
|
plugin.onNavigateToThread = (s, r) {
|
|
navServer = s;
|
|
navRoot = r;
|
|
};
|
|
|
|
plugin.handleNativeEvent({
|
|
'type': PushNotificationType.opened,
|
|
'server_url': 'https://mm.example.com',
|
|
'channel_id': 'channel-123',
|
|
'root_id': 'root-789',
|
|
'is_crt_enabled': 'true',
|
|
});
|
|
|
|
expect(navServer, 'https://mm.example.com');
|
|
expect(navRoot, 'root-789');
|
|
});
|
|
|
|
test('opened event without server_url skips navigation callbacks', () {
|
|
var channelCalled = false;
|
|
var threadCalled = false;
|
|
plugin.onNavigateToChannel = (_, _) => channelCalled = true;
|
|
plugin.onNavigateToThread = (_, _) => threadCalled = true;
|
|
|
|
plugin.handleNativeEvent({
|
|
'type': PushNotificationType.opened,
|
|
'channel_id': 'channel-123',
|
|
});
|
|
|
|
expect(channelCalled, isFalse);
|
|
expect(threadCalled, isFalse);
|
|
});
|
|
|
|
test('every event is forwarded to onNotification stream', () async {
|
|
final future = plugin.onNotification.first;
|
|
|
|
plugin.handleNativeEvent({
|
|
'type': PushNotificationType.clear,
|
|
'channel_id': 'channel-123',
|
|
});
|
|
|
|
final raw = await future;
|
|
expect(raw['type'], PushNotificationType.clear);
|
|
expect(raw['channel_id'], 'channel-123');
|
|
});
|
|
|
|
test(
|
|
'token_refresh event saves formatted device token and invokes callback',
|
|
() async {
|
|
String? channelToken;
|
|
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
|
|
.setMockMethodCallHandler(actionChannel, (call) async {
|
|
if (call.method == 'saveDeviceToken') {
|
|
final args = call.arguments as Map;
|
|
channelToken = args['token'] as String?;
|
|
}
|
|
return null;
|
|
});
|
|
|
|
final completer = Completer<String>();
|
|
plugin.onDeviceTokenReady = completer.complete;
|
|
|
|
plugin.handleNativeEvent({
|
|
'type': PushNotificationType.tokenRefresh,
|
|
'token': 'raw-token',
|
|
});
|
|
|
|
final callbackToken = await completer.future;
|
|
expect(channelToken, 'android_rn-v2:raw-token');
|
|
expect(callbackToken, 'android_rn-v2:raw-token');
|
|
},
|
|
);
|
|
|
|
test(
|
|
'debugSendNativeEventForTesting invokes native debug method',
|
|
() async {
|
|
MethodCall? capturedCall;
|
|
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
|
|
.setMockMethodCallHandler(actionChannel, (call) async {
|
|
capturedCall = call;
|
|
return null;
|
|
});
|
|
|
|
await plugin.debugSendNativeEventForTesting({
|
|
'type': PushNotificationType.opened,
|
|
'server_url': 'https://mm.example.com',
|
|
'channel_id': 'channel-debug',
|
|
});
|
|
|
|
expect(capturedCall?.method, 'debugSendNativeEvent');
|
|
expect(capturedCall?.arguments, {
|
|
'type': PushNotificationType.opened,
|
|
'server_url': 'https://mm.example.com',
|
|
'channel_id': 'channel-debug',
|
|
});
|
|
},
|
|
);
|
|
});
|
|
|
|
group('Channel constants', () {
|
|
test('notification and action channel names are preserved', () {
|
|
expect(
|
|
MattermostPushPlugin.notificationChannelName,
|
|
'com.tokilabs.mattermost/notifications',
|
|
);
|
|
expect(
|
|
MattermostPushPlugin.actionChannelName,
|
|
'com.tokilabs.mattermost/notification_actions',
|
|
);
|
|
});
|
|
});
|
|
}
|