Files
TPSchedule/mobile/test/widgets/reminder_tools_test.dart
T

143 lines
4.6 KiB
Dart

import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:hepan_everyday/app/app_controller.dart';
import 'package:hepan_everyday/domain/app_snapshot.dart';
import 'package:hepan_everyday/domain/app_settings.dart';
import 'package:hepan_everyday/features/profile/reminder_tools.dart';
import '../support/fakes.dart';
class _Notifications extends FakeNotifications {
Completer<Map<String, Object?>>? diagnosis;
int? reconciliationsAtDiagnosis;
final tests = <bool>[];
@override
Future<String> sendTestReminder({required bool scheduled}) async {
tests.add(scheduled);
return scheduled ? '已安排测试提醒' : '已发送测试提醒';
}
@override
Future<Map<String, Object?>> diagnose() async {
reconciliationsAtDiagnosis = reconciliations;
return diagnosis?.future ??
{
'notifications': true,
'exactAlarm': false,
'pendingCount': 2,
'channelImportance': 4,
'channelSound': true,
'system': {
'manufacturer': 'TestPhone',
'model': 'TestModel',
'sdk': 35,
'backgroundRestricted': true,
'account': 'private@example.com',
},
'courseNames': ['Private course name'],
'account': 'private@example.com',
'errorCode': 'none',
};
}
@override
Future<void> openSettings({required bool background}) async {}
}
Future<void> _open(WidgetTester tester, _Notifications notifications) async {
final controller = AppController(
MemoryStore(AppSnapshot(settings: AppSettings())),
notifications,
FakeCalendar(),
() => DateTime.utc(2026, 10, 14),
);
await controller.initialize();
addTearDown(controller.dispose);
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: SingleChildScrollView(
child: ReminderTools(controller: controller),
),
),
),
);
}
void main() {
testWidgets('test controls distinguish immediate and background reminders', (
tester,
) async {
final notifications = _Notifications();
await _open(tester, notifications);
await tester.tap(find.text('立即测试提醒'));
await tester.pumpAndSettle();
expect(find.text('已发送测试提醒'), findsOneWidget);
await tester.tap(find.text('10 秒后台测试'));
await tester.pumpAndSettle();
expect(notifications.tests, [false, true]);
expect(find.textContaining('Home'), findsOneWidget);
});
testWidgets('diagnosis refreshes services and prevents overlapping actions', (
tester,
) async {
final notifications = _Notifications()
..diagnosis = Completer<Map<String, Object?>>();
await _open(tester, notifications);
final previous = notifications.reconciliations;
await tester.tap(find.text('检查提醒'));
await tester.pump();
expect(notifications.reconciliationsAtDiagnosis, previous + 1);
for (final button in tester.widgetList<TextButton>(
find.byType(TextButton),
)) {
expect(button.onPressed, isNull);
}
notifications.diagnosis!.complete({'notifications': false});
await tester.pumpAndSettle();
expect(find.textContaining('系统通知已关闭'), findsOneWidget);
expect(find.text('复制提醒诊断'), findsOneWidget);
});
testWidgets('copied diagnostics omit unapproved fields and private values', (
tester,
) async {
String? copied;
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(
SystemChannels.platform,
(call) async {
if (call.method == 'Clipboard.setData') {
copied = (call.arguments as Map)['text'] as String;
}
return null;
},
);
addTearDown(
() => tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(
SystemChannels.platform,
null,
),
);
await _open(tester, _Notifications());
await tester.tap(find.text('检查提醒'));
await tester.pumpAndSettle();
await tester.ensureVisible(find.text('复制提醒诊断'));
await tester.tap(find.text('复制提醒诊断'));
await tester.pumpAndSettle();
expect(copied, isNotNull);
expect(copied, isNot(contains('private@example.com')));
expect(copied, isNot(contains('Private course name')));
final report = jsonDecode(copied!) as Map;
expect(report['pendingCount'], 2);
expect(report['courseCount'], 0);
expect(report['appVersion'], isNotEmpty);
expect((report['system'] as Map)['model'], 'TestModel');
});
}