feat: integrate invite API and improve notification handling
- Add invite code display and binding functionality via API - Fix notification unread count sync on auth state change - Improve notification mark read with server state validation - Add auth state listener to trigger notification refresh - Add YaoCoinConverter for coin-to-yao type conversion - Remove YaoLegend from divination screens (UI cleanup) - Abbreviate relation labels in yao detail view - Add re-register notice to account delete screen - Update 'coins' terminology to 'points' in localization - Fix backend points consumption to only run in CHAT mode - Add HttpxAuthNoiseFilter to suppress auth endpoint logging - Fix notification static_schema import path - Add test coverage for notification bloc error handling - Update AGENTS.md page header rules and image handling - Delete deprecated run-dev.sh script
This commit is contained in:
@@ -10,6 +10,8 @@ class _FakeNotificationRepository implements NotificationRepository {
|
||||
final List<NotificationItem> items = [];
|
||||
int unreadCount = 0;
|
||||
int markAllReadCallCount = 0;
|
||||
bool failMarkRead = false;
|
||||
bool failMarkAllRead = false;
|
||||
|
||||
@override
|
||||
Future<NotificationListResult> listNotifications({
|
||||
@@ -28,6 +30,9 @@ class _FakeNotificationRepository implements NotificationRepository {
|
||||
|
||||
@override
|
||||
Future<NotificationItem> markRead({required String notificationId}) async {
|
||||
if (failMarkRead) {
|
||||
throw Exception('Mark read failed');
|
||||
}
|
||||
final idx = items.indexWhere((i) => i.id == notificationId);
|
||||
if (idx == -1) {
|
||||
throw Exception('Not found');
|
||||
@@ -39,6 +44,9 @@ class _FakeNotificationRepository implements NotificationRepository {
|
||||
|
||||
@override
|
||||
Future<int> markAllRead() async {
|
||||
if (failMarkAllRead) {
|
||||
throw Exception('Mark all read failed');
|
||||
}
|
||||
markAllReadCallCount++;
|
||||
final count = unreadCount;
|
||||
for (int i = 0; i < items.length; i++) {
|
||||
@@ -99,6 +107,21 @@ void main() {
|
||||
expect(bloc.state.unreadCount, 0);
|
||||
});
|
||||
|
||||
test(
|
||||
'MarkNotificationRead does not update state when request fails',
|
||||
() async {
|
||||
fakeRepo.items.add(makeItem(id: 'n1', isRead: false));
|
||||
fakeRepo.unreadCount = 1;
|
||||
fakeRepo.failMarkRead = true;
|
||||
await bloc.handleEvent(LoadNotifications());
|
||||
await bloc.handleEvent(RefreshUnreadCount());
|
||||
|
||||
await bloc.handleEvent(MarkNotificationRead(notificationId: 'n1'));
|
||||
expect(bloc.state.items.first.isRead, false);
|
||||
expect(bloc.state.unreadCount, 1);
|
||||
},
|
||||
);
|
||||
|
||||
test('MarkAllNotificationsRead marks all as read', () async {
|
||||
fakeRepo.items.addAll([
|
||||
makeItem(id: 'n1', isRead: false),
|
||||
@@ -112,6 +135,24 @@ void main() {
|
||||
expect(bloc.state.items.every((i) => i.isRead), true);
|
||||
});
|
||||
|
||||
test(
|
||||
'MarkAllNotificationsRead does not update state when request fails',
|
||||
() async {
|
||||
fakeRepo.items.addAll([
|
||||
makeItem(id: 'n1', isRead: false),
|
||||
makeItem(id: 'n2', isRead: false),
|
||||
]);
|
||||
fakeRepo.unreadCount = 2;
|
||||
fakeRepo.failMarkAllRead = true;
|
||||
await bloc.handleEvent(LoadNotifications());
|
||||
await bloc.handleEvent(RefreshUnreadCount());
|
||||
|
||||
await bloc.handleEvent(MarkAllNotificationsRead());
|
||||
expect(bloc.state.unreadCount, 2);
|
||||
expect(bloc.state.items.every((i) => !i.isRead), true);
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'NotificationCreatedEvent adds item and increments unreadCount',
|
||||
() async {
|
||||
|
||||
Reference in New Issue
Block a user