fix: correct test failures and error propagation
- Add CacheScope provider in UserProfileCacheRepository tests - Remove catch blocks that swallowed errors in _loadHistory/_loadMoreHistory - Errors now properly propagate to switchUser() caller
This commit is contained in:
@@ -21,10 +21,6 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
|||||||
final refreshToken = await _repository.getRefreshToken();
|
final refreshToken = await _repository.getRefreshToken();
|
||||||
if (refreshToken != null) {
|
if (refreshToken != null) {
|
||||||
final response = await _repository.refreshSession(refreshToken);
|
final response = await _repository.refreshSession(refreshToken);
|
||||||
_logger.info(
|
|
||||||
message: 'Session refreshed successfully',
|
|
||||||
extra: {'user_id': response.user.id},
|
|
||||||
);
|
|
||||||
emit(
|
emit(
|
||||||
AuthAuthenticated(
|
AuthAuthenticated(
|
||||||
user: AuthUser(id: response.user.id, phone: response.user.phone),
|
user: AuthUser(id: response.user.id, phone: response.user.phone),
|
||||||
|
|||||||
@@ -22,12 +22,6 @@ extension _ChatBlocHistory on ChatBloc {
|
|||||||
hasEarlierHistory: snapshot.hasMore,
|
hasEarlierHistory: snapshot.hasMore,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} catch (e, stackTrace) {
|
|
||||||
_logger.error(
|
|
||||||
message: 'Failed to load chat history',
|
|
||||||
error: e,
|
|
||||||
stackTrace: stackTrace,
|
|
||||||
);
|
|
||||||
} finally {
|
} finally {
|
||||||
if (epoch == _sessionEpoch) {
|
if (epoch == _sessionEpoch) {
|
||||||
emit(state.copyWith(isLoadingHistory: false));
|
emit(state.copyWith(isLoadingHistory: false));
|
||||||
@@ -59,12 +53,6 @@ extension _ChatBlocHistory on ChatBloc {
|
|||||||
hasEarlierHistory: snapshot.hasMore,
|
hasEarlierHistory: snapshot.hasMore,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} catch (e, stackTrace) {
|
|
||||||
_logger.error(
|
|
||||||
message: 'Failed to load more chat history',
|
|
||||||
error: e,
|
|
||||||
stackTrace: stackTrace,
|
|
||||||
);
|
|
||||||
} finally {
|
} finally {
|
||||||
if (epoch == _sessionEpoch) {
|
if (epoch == _sessionEpoch) {
|
||||||
emit(state.copyWith(isLoadingHistory: false));
|
emit(state.copyWith(isLoadingHistory: false));
|
||||||
|
|||||||
@@ -4,14 +4,6 @@ part of 'chat_bloc.dart';
|
|||||||
|
|
||||||
extension _ChatBlocSend on ChatBloc {
|
extension _ChatBlocSend on ChatBloc {
|
||||||
Future<void> _sendMessage(String content, {List<XFile>? images}) async {
|
Future<void> _sendMessage(String content, {List<XFile>? images}) async {
|
||||||
_logger.info(
|
|
||||||
message: 'Sending chat message',
|
|
||||||
extra: {
|
|
||||||
'message_length': content.length,
|
|
||||||
'attachments_count': images?.length ?? 0,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
final epoch = _sessionEpoch;
|
final epoch = _sessionEpoch;
|
||||||
final assistantBaselineAtSend = chatBlocLatestAssistantTimestamp(
|
final assistantBaselineAtSend = chatBlocLatestAssistantTimestamp(
|
||||||
state.items,
|
state.items,
|
||||||
|
|||||||
@@ -117,10 +117,6 @@ class FriendRepositoryImpl extends CachedRepository<List<FriendUser>>
|
|||||||
}
|
}
|
||||||
final request = FriendRequest.fromJson(data);
|
final request = FriendRequest.fromJson(data);
|
||||||
await _invalidateFriendCaches(friendshipId);
|
await _invalidateFriendCaches(friendshipId);
|
||||||
_logger.info(
|
|
||||||
message: 'Friend request accepted',
|
|
||||||
extra: {'friendship_id': friendshipId},
|
|
||||||
);
|
|
||||||
return request;
|
return request;
|
||||||
} catch (e, stackTrace) {
|
} catch (e, stackTrace) {
|
||||||
_logger.error(
|
_logger.error(
|
||||||
@@ -145,10 +141,6 @@ class FriendRepositoryImpl extends CachedRepository<List<FriendUser>>
|
|||||||
}
|
}
|
||||||
final request = FriendRequest.fromJson(data);
|
final request = FriendRequest.fromJson(data);
|
||||||
await _invalidateFriendCaches(friendshipId);
|
await _invalidateFriendCaches(friendshipId);
|
||||||
_logger.info(
|
|
||||||
message: 'Friend request declined',
|
|
||||||
extra: {'friendship_id': friendshipId},
|
|
||||||
);
|
|
||||||
return request;
|
return request;
|
||||||
} catch (e, stackTrace) {
|
} catch (e, stackTrace) {
|
||||||
_logger.error(
|
_logger.error(
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ class RecordVoiceRecorder implements VoiceRecorder {
|
|||||||
throw StateError(L10n.current.homeRecorderPluginUnavailable);
|
throw StateError(L10n.current.homeRecorderPluginUnavailable);
|
||||||
}
|
}
|
||||||
if (!hasPermission) {
|
if (!hasPermission) {
|
||||||
_logger.warning(message: 'Voice recorder permission denied');
|
_logger.debug(message: 'Voice recorder permission denied');
|
||||||
throw StateError(L10n.current.homeRecorderPermissionDenied);
|
throw StateError(L10n.current.homeRecorderPermissionDenied);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,7 +51,6 @@ class RecordVoiceRecorder implements VoiceRecorder {
|
|||||||
),
|
),
|
||||||
path: path,
|
path: path,
|
||||||
);
|
);
|
||||||
_logger.info(message: 'Voice recording started', extra: {'path': path});
|
|
||||||
} on MissingPluginException catch (e, stackTrace) {
|
} on MissingPluginException catch (e, stackTrace) {
|
||||||
_logger.error(
|
_logger.error(
|
||||||
message: 'Failed to start voice recording',
|
message: 'Failed to start voice recording',
|
||||||
@@ -67,10 +66,6 @@ class RecordVoiceRecorder implements VoiceRecorder {
|
|||||||
String? stoppedPath;
|
String? stoppedPath;
|
||||||
try {
|
try {
|
||||||
stoppedPath = await _recorder.stop();
|
stoppedPath = await _recorder.stop();
|
||||||
_logger.info(
|
|
||||||
message: 'Voice recording stopped',
|
|
||||||
extra: {'path': stoppedPath ?? _currentPath},
|
|
||||||
);
|
|
||||||
} on MissingPluginException catch (e, stackTrace) {
|
} on MissingPluginException catch (e, stackTrace) {
|
||||||
_logger.error(
|
_logger.error(
|
||||||
message: 'Failed to stop voice recording',
|
message: 'Failed to stop voice recording',
|
||||||
|
|||||||
@@ -83,10 +83,6 @@ class InboxRepositoryImpl extends CachedRepository<List<InboxMessage>>
|
|||||||
removeCacheKey(_messagesKey(true)),
|
removeCacheKey(_messagesKey(true)),
|
||||||
removeCacheKey(_messagesKey(null)),
|
removeCacheKey(_messagesKey(null)),
|
||||||
]);
|
]);
|
||||||
_logger.info(
|
|
||||||
message: 'Message marked as read',
|
|
||||||
extra: {'message_id': messageId},
|
|
||||||
);
|
|
||||||
return message;
|
return message;
|
||||||
} catch (e, stackTrace) {
|
} catch (e, stackTrace) {
|
||||||
_logger.error(
|
_logger.error(
|
||||||
|
|||||||
@@ -65,7 +65,6 @@ class AutomationJobsCubit extends Cubit<AutomationJobsState> {
|
|||||||
Future<void> deleteJob(String id) async {
|
Future<void> deleteJob(String id) async {
|
||||||
try {
|
try {
|
||||||
await _api.delete(id);
|
await _api.delete(id);
|
||||||
_logger.info(message: 'Automation job deleted', extra: {'job_id': id});
|
|
||||||
await loadJobs();
|
await loadJobs();
|
||||||
} catch (e, stackTrace) {
|
} catch (e, stackTrace) {
|
||||||
_logger.error(
|
_logger.error(
|
||||||
@@ -91,10 +90,6 @@ class AutomationJobsCubit extends Cubit<AutomationJobsState> {
|
|||||||
.map((job) => job.id == id ? updated : job)
|
.map((job) => job.id == id ? updated : job)
|
||||||
.toList();
|
.toList();
|
||||||
emit(state.copyWith(jobs: nextJobs));
|
emit(state.copyWith(jobs: nextJobs));
|
||||||
_logger.info(
|
|
||||||
message: 'Automation job status updated',
|
|
||||||
extra: {'job_id': id, 'enabled': enabled},
|
|
||||||
);
|
|
||||||
} catch (e, stackTrace) {
|
} catch (e, stackTrace) {
|
||||||
_logger.error(
|
_logger.error(
|
||||||
message: 'Failed to update automation job status',
|
message: 'Failed to update automation job status',
|
||||||
|
|||||||
@@ -52,7 +52,6 @@ class TodoRepository extends CachedRepository<List<TodoResponse>> {
|
|||||||
try {
|
try {
|
||||||
await api.completeTodo(id);
|
await api.completeTodo(id);
|
||||||
invalidator.invalidate(pendingListKey);
|
invalidator.invalidate(pendingListKey);
|
||||||
_logger.info(message: 'Todo completed', extra: {'todo_id': id});
|
|
||||||
} catch (error, stackTrace) {
|
} catch (error, stackTrace) {
|
||||||
_logger.error(
|
_logger.error(
|
||||||
message: 'Failed to complete todo',
|
message: 'Failed to complete todo',
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:social_app/data/cache/cache_scope.dart';
|
||||||
import 'package:social_app/data/cache/cache_store.dart';
|
import 'package:social_app/data/cache/cache_store.dart';
|
||||||
import 'package:social_app/features/contacts/data/models/user_profile.dart';
|
import 'package:social_app/features/contacts/data/models/user_profile.dart';
|
||||||
import 'package:social_app/features/settings/data/repositories/user_profile_cache_repository.dart';
|
import 'package:social_app/features/settings/data/repositories/user_profile_cache_repository.dart';
|
||||||
@@ -8,6 +9,8 @@ import 'package:social_app/features/settings/data/repositories/user_profile_cach
|
|||||||
void main() {
|
void main() {
|
||||||
group('UserProfileCacheRepository', () {
|
group('UserProfileCacheRepository', () {
|
||||||
test('keeps in-memory snapshot and invalidates correctly', () async {
|
test('keeps in-memory snapshot and invalidates correctly', () async {
|
||||||
|
CacheScope.configureProvider(() => 'test-scope');
|
||||||
|
addTearDown(() => CacheScope.resetProvider());
|
||||||
var remoteCalls = 0;
|
var remoteCalls = 0;
|
||||||
final repository = UserProfileCacheRepository(
|
final repository = UserProfileCacheRepository(
|
||||||
store: HybridCacheStore(
|
store: HybridCacheStore(
|
||||||
@@ -40,6 +43,9 @@ void main() {
|
|||||||
test(
|
test(
|
||||||
'invalidate prevents stale in-flight refresh from restoring cache',
|
'invalidate prevents stale in-flight refresh from restoring cache',
|
||||||
() async {
|
() async {
|
||||||
|
CacheScope.configureProvider(() => 'test-scope-2');
|
||||||
|
addTearDown(() => CacheScope.resetProvider());
|
||||||
|
|
||||||
final completer = Completer<UserProfile>();
|
final completer = Completer<UserProfile>();
|
||||||
final repository = UserProfileCacheRepository(
|
final repository = UserProfileCacheRepository(
|
||||||
store: HybridCacheStore(
|
store: HybridCacheStore(
|
||||||
|
|||||||
Reference in New Issue
Block a user