Add feedback service, reminder diagnostics and smooth week transitions
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
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');
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user