브라우저 smoke의 선행 조건으로 test host를 web build 가능 상태로 만들고, 후속 runtime evidence 계획과 완료 로그를 함께 남긴다.
202 lines
6.6 KiB
Dart
202 lines
6.6 KiB
Dart
import 'dart:async';
|
|
|
|
import 'package:firebase_core/firebase_core.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:nexo_messaging/nexo_messaging.dart';
|
|
|
|
Future<void> main() async {
|
|
WidgetsFlutterBinding.ensureInitialized();
|
|
await _initializeFirebaseForHarness();
|
|
runApp(const MyApp());
|
|
}
|
|
|
|
Future<void> _initializeFirebaseForHarness() async {
|
|
try {
|
|
await Firebase.initializeApp();
|
|
} catch (error, stackTrace) {
|
|
debugPrint('[NexoClient] Firebase initialization skipped: $error');
|
|
debugPrintStack(stackTrace: stackTrace);
|
|
}
|
|
}
|
|
|
|
class MyApp extends StatefulWidget {
|
|
const MyApp({super.key, this.initializePlugin = true});
|
|
|
|
final bool initializePlugin;
|
|
|
|
@override
|
|
State<MyApp> createState() => _MyAppState();
|
|
}
|
|
|
|
class _MyAppState extends State<MyApp> {
|
|
String? _deviceToken;
|
|
String? _lastNotification;
|
|
String? _lastOpened;
|
|
String? _lastNavigation;
|
|
NexoMessagingWebNotificationStatus? _webNotificationStatus;
|
|
NexoMessagingWebNotificationDisplayResult? _lastWebDisplay;
|
|
StreamSubscription<Map<String, dynamic>>? _notificationSubscription;
|
|
StreamSubscription<NotificationOpenedEvent>? _openedSubscription;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
final plugin = NexoMessagingPlugin.instance;
|
|
plugin.onDeviceTokenReady = (token) {
|
|
if (!mounted) return;
|
|
setState(() => _deviceToken = token);
|
|
};
|
|
plugin.onNavigateToChannel = (serverUrl, channelId) {
|
|
if (!mounted) return;
|
|
setState(() => _lastNavigation = 'channel:$serverUrl/$channelId');
|
|
};
|
|
plugin.onNavigateToThread = (serverUrl, rootId) {
|
|
if (!mounted) return;
|
|
setState(() => _lastNavigation = 'thread:$serverUrl/$rootId');
|
|
};
|
|
_notificationSubscription = plugin.onNotification.listen((event) {
|
|
if (!mounted) return;
|
|
setState(() => _lastNotification = _formatMap(event));
|
|
});
|
|
_openedSubscription = plugin.onNotificationOpened.listen((event) {
|
|
if (!mounted) return;
|
|
setState(() => _lastOpened = _formatOpened(event));
|
|
});
|
|
if (widget.initializePlugin) {
|
|
unawaited(_initializePlugin(plugin));
|
|
}
|
|
}
|
|
|
|
Future<void> _initializePlugin(NexoMessagingPlugin plugin) async {
|
|
try {
|
|
await _configureSmokeAuthToken(plugin);
|
|
await plugin.initialize();
|
|
} catch (error, stackTrace) {
|
|
debugPrint('[NexoClient] Failed to initialize messaging plugin: $error');
|
|
debugPrintStack(stackTrace: stackTrace);
|
|
}
|
|
}
|
|
|
|
Future<void> _configureSmokeAuthToken(NexoMessagingPlugin plugin) async {
|
|
const serverUrl = String.fromEnvironment('NEXO_SMOKE_SERVER_URL');
|
|
const authToken = String.fromEnvironment('NEXO_SMOKE_AUTH_TOKEN');
|
|
const identifier = String.fromEnvironment('NEXO_SMOKE_SERVER_IDENTIFIER');
|
|
if (serverUrl.isEmpty || authToken.isEmpty) return;
|
|
|
|
await plugin.setAuthToken(
|
|
serverUrl,
|
|
authToken,
|
|
identifier: identifier.isEmpty ? null : identifier,
|
|
);
|
|
debugPrint('[NexoClient] Smoke auth token configured');
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_notificationSubscription?.cancel();
|
|
_openedSubscription?.cancel();
|
|
final plugin = NexoMessagingPlugin.instance;
|
|
plugin.onDeviceTokenReady = null;
|
|
plugin.onNavigateToChannel = null;
|
|
plugin.onNavigateToThread = null;
|
|
super.dispose();
|
|
}
|
|
|
|
String _formatMap(Map<String, dynamic> map) {
|
|
return map.entries.map((e) => '${e.key}: ${e.value}').join(', ');
|
|
}
|
|
|
|
String _formatOpened(NotificationOpenedEvent event) {
|
|
return 'server_url: ${event.serverUrl}, channel_id: ${event.channelId}, root_id: ${event.rootId}, is_crt_enabled: ${event.isCRTEnabled}';
|
|
}
|
|
|
|
String _formatWebSupport() {
|
|
if (_webNotificationStatus == null) return 'unknown';
|
|
return _webNotificationStatus!.isSupported ? 'yes' : 'no';
|
|
}
|
|
|
|
String _formatWebPermission() {
|
|
if (_webNotificationStatus == null) return 'unknown';
|
|
return _webNotificationStatus!.permission.name;
|
|
}
|
|
|
|
String _formatWebDisplay() {
|
|
if (_lastWebDisplay == null) return 'none';
|
|
if (!_lastWebDisplay!.isSupported) return 'unsupported';
|
|
if (!_lastWebDisplay!.permissionGranted) return 'permission denied';
|
|
return _lastWebDisplay!.success ? 'shown' : 'failed';
|
|
}
|
|
|
|
Future<void> _refreshWebNotificationStatus(NexoMessagingPlugin plugin) async {
|
|
try {
|
|
final status = await plugin.getWebNotificationPermissionStatus();
|
|
if (!mounted) return;
|
|
setState(() => _webNotificationStatus = status);
|
|
} catch (e) {
|
|
debugPrint('[NexoClient] Web permission refresh failed: $e');
|
|
}
|
|
}
|
|
|
|
Future<void> _requestWebNotificationPermission(
|
|
NexoMessagingPlugin plugin,
|
|
) async {
|
|
try {
|
|
final status = await plugin.requestWebNotificationPermission();
|
|
if (!mounted) return;
|
|
setState(() => _webNotificationStatus = status);
|
|
} catch (e) {
|
|
debugPrint('[NexoClient] Web permission request failed: $e');
|
|
}
|
|
}
|
|
|
|
void _showWebSmokeNotification(NexoMessagingPlugin plugin) {
|
|
final result = plugin.showWebForegroundNotification({
|
|
'title': 'Nexo Smoke',
|
|
'body': 'Web notification smoke test',
|
|
'server_url': 'https://nexo.example.com',
|
|
'channel_id': 'smoke-channel',
|
|
});
|
|
setState(() => _lastWebDisplay = result);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final plugin = NexoMessagingPlugin.instance;
|
|
return MaterialApp(
|
|
home: Scaffold(
|
|
appBar: AppBar(title: const Text('Nexo client')),
|
|
body: ListView(
|
|
padding: const EdgeInsets.all(16),
|
|
children: [
|
|
Text('Device token: ${_deviceToken ?? 'pending'}'),
|
|
Text('Last notification: ${_lastNotification ?? 'none'}'),
|
|
Text('Last opened: ${_lastOpened ?? 'none'}'),
|
|
Text('Last navigation: ${_lastNavigation ?? 'none'}'),
|
|
Text('Web notification support: ${_formatWebSupport()}'),
|
|
Text(
|
|
'Web notification permission: ${_formatWebPermission()}',
|
|
key: const Key('web-permission-status'),
|
|
),
|
|
Text(
|
|
'Last web display: ${_formatWebDisplay()}',
|
|
key: const Key('web-display-status'),
|
|
),
|
|
ElevatedButton(
|
|
onPressed: () => unawaited(_refreshWebNotificationStatus(plugin)),
|
|
child: const Text('Refresh web permission'),
|
|
),
|
|
ElevatedButton(
|
|
onPressed: () =>
|
|
unawaited(_requestWebNotificationPermission(plugin)),
|
|
child: const Text('Request web permission'),
|
|
),
|
|
ElevatedButton(
|
|
onPressed: () => _showWebSmokeNotification(plugin),
|
|
child: const Text('Show web smoke notification'),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|