Skip to content

Commit

Permalink
test(user prefs/hide)
Browse files Browse the repository at this point in the history
- implement unit tests for the global_hide_bloc and user_prefs repository.
  • Loading branch information
thiagocarvalhodev committed Oct 22, 2024
1 parent 4d44634 commit 307d9c1
Show file tree
Hide file tree
Showing 6 changed files with 349 additions and 25 deletions.
6 changes: 3 additions & 3 deletions lib/blocs/hide/global_hide_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ class GlobalHideBloc extends Bloc<GlobalHideEvent, GlobalHideState> {
on<GlobalHideEvent>((event, emit) async {
if (event is ShowItems) {
emit(ShowingHiddenItems(userHasHiddenDrive: event.userHasHiddenItems));
_userPreferencesRepository.saveShowHiddenFiles(true);
await _userPreferencesRepository.saveShowHiddenFiles(true);
} else if (event is HideItems) {
emit(HiddingItems(userHasHiddenDrive: event.userHasHiddenItems));
_userPreferencesRepository.saveShowHiddenFiles(false);
await _userPreferencesRepository.saveShowHiddenFiles(false);
} else if (event is RefreshOptions) {
final hasHiddenItems = await _driveDao.hasHiddenItems().getSingle();
final hasHiddenItems = await _driveDao.userHasHiddenItems();
emit(state.copyWith(userHasHiddenDrive: hasHiddenItems));
}
});
Expand Down
1 change: 1 addition & 0 deletions lib/blocs/hide/hide_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,7 @@ class HideBloc extends Bloc<HideEvent, HideState> {
isHidden ? RevisionAction.hide : RevisionAction.unhide,
));
}

});
}

Expand Down
4 changes: 4 additions & 0 deletions lib/models/daos/drive_dao/drive_dao.dart
Original file line number Diff line number Diff line change
Expand Up @@ -736,6 +736,10 @@ class DriveDao extends DatabaseAccessor<Database> with _$DriveDaoMixin {
Future<int> numberOfFolders() {
return (select(folderEntries).table.count()).getSingle();
}

Future<bool> userHasHiddenItems() {
return hasHiddenItems().getSingle();
}
}

class FolderNotFoundInDriveException implements Exception {
Expand Down
62 changes: 44 additions & 18 deletions lib/user/repositories/user_preferences_repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -80,39 +80,41 @@ class _UserPreferencesRepository implements UserPreferencesRepository {

@override
Future<void> saveTheme(ArDriveThemes theme) async {
(await _getStore()).putString(
'currentTheme',
theme.name,
await _updatePreference(
key: 'currentTheme',
value: theme.name,
updateFunction: (value) =>
_currentUserPreferences!.copyWith(currentTheme: theme),
);
}

@override
Future<void> saveLastSelectedDriveId(String driveId) async {
(await _getStore()).putString(
'lastSelectedDriveId',
driveId,
await _updatePreference(
key: 'lastSelectedDriveId',
value: driveId,
updateFunction: (value) =>
_currentUserPreferences!.copyWith(lastSelectedDriveId: value),
);
}

@override
Future<void> saveShowHiddenFiles(bool showHiddenFiles) async {
(await _getStore()).putBool(
'showHiddenFiles',
showHiddenFiles,
await _updatePreference(
key: 'showHiddenFiles',
value: showHiddenFiles,
updateFunction: (value) =>
_currentUserPreferences!.copyWith(showHiddenFiles: value),
);
}

@override
Future<void> saveUserHasHiddenItem(bool userHasHiddenDrive) async {
_currentUserPreferences = _currentUserPreferences!.copyWith(
userHasHiddenDrive: userHasHiddenDrive,
);

_userPreferencesController.sink.add(_currentUserPreferences!);

(await _getStore()).putBool(
'userHasHiddenDrive',
userHasHiddenDrive,
await _updatePreference(
key: 'userHasHiddenDrive',
value: userHasHiddenDrive,
updateFunction: (value) =>
_currentUserPreferences!.copyWith(userHasHiddenDrive: value),
);
}

Expand All @@ -125,6 +127,12 @@ class _UserPreferencesRepository implements UserPreferencesRepository {
@override
Future<void> clearLastSelectedDriveId() async {
(await _getStore()).remove('lastSelectedDriveId');

_currentUserPreferences = _currentUserPreferences!.copyWith(
lastSelectedDriveId: null,
);

_userPreferencesController.sink.add(_currentUserPreferences!);
}

// parse theme from string to ArDriveThemes
Expand All @@ -138,4 +146,22 @@ class _UserPreferencesRepository implements UserPreferencesRepository {
return ArDriveThemes.light;
}
}

Future<void> _updatePreference<T>({
required String key,
required T value,
required UserPreferences Function(T) updateFunction,
}) async {
_currentUserPreferences = updateFunction(value);
_userPreferencesController.sink.add(_currentUserPreferences!);

final store = await _getStore();
if (value is String) {
await store.putString(key, value as String);
} else if (value is bool) {
await store.putBool(key, value as bool);
} else {
throw ArgumentError('Unsupported type for preference value');
}
}
}
148 changes: 148 additions & 0 deletions test/blocs/hide/global_hide_bloc_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import 'package:ardrive/blocs/hide/global_hide_bloc.dart';
import 'package:ardrive/models/daos/drive_dao/drive_dao.dart';
import 'package:ardrive/user/repositories/user_preferences_repository.dart';
import 'package:ardrive/user/user_preferences.dart';
import 'package:ardrive_ui/ardrive_ui.dart';
import 'package:bloc_test/bloc_test.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';

class MockUserPreferencesRepository extends Mock
implements UserPreferencesRepository {}

class MockDriveDao extends Mock implements DriveDao {}

void main() {
late MockUserPreferencesRepository mockUserPreferencesRepository;
late MockDriveDao mockDriveDao;

setUp(() {
mockUserPreferencesRepository = MockUserPreferencesRepository();
mockDriveDao = MockDriveDao();

when(() => mockUserPreferencesRepository.watch()).thenAnswer(
(_) => const Stream.empty(),
);
when(() => mockDriveDao.userHasHiddenItems())
.thenAnswer((_) async => false);
});

blocTest<GlobalHideBloc, GlobalHideState>(
'initial state is correct',
setUp: () {
when(() => mockUserPreferencesRepository.saveShowHiddenFiles(false))
.thenAnswer((_) async {});
},
build: () => GlobalHideBloc(
userPreferencesRepository: mockUserPreferencesRepository,
driveDao: mockDriveDao,
),
verify: (bloc) {
expect(bloc.state, const GlobalHideInitial(userHasHiddenDrive: false));
},
);

blocTest<GlobalHideBloc, GlobalHideState>(
'ShowItems event emits ShowingHiddenItems state and saves preference',
build: () {
when(() => mockUserPreferencesRepository.saveShowHiddenFiles(true))
.thenAnswer((_) async {});
return GlobalHideBloc(
userPreferencesRepository: mockUserPreferencesRepository,
driveDao: mockDriveDao,
);
},
act: (bloc) => bloc.add(const ShowItems(userHasHiddenItems: true)),
expect: () => [const ShowingHiddenItems(userHasHiddenDrive: true)],
verify: (_) {
verify(() => mockUserPreferencesRepository.saveShowHiddenFiles(true))
.called(1);
},
);

blocTest<GlobalHideBloc, GlobalHideState>(
'HideItems event emits HiddingItems state and saves preference',
build: () {
when(() => mockUserPreferencesRepository.saveShowHiddenFiles(false))
.thenAnswer((_) async {});
return GlobalHideBloc(
userPreferencesRepository: mockUserPreferencesRepository,
driveDao: mockDriveDao,
);
},
act: (bloc) => bloc.add(const HideItems(userHasHiddenItems: false)),
expect: () => [const HiddingItems(userHasHiddenDrive: false)],
verify: (_) {
verify(() => mockUserPreferencesRepository.saveShowHiddenFiles(false))
.called(1);
},
);

blocTest<GlobalHideBloc, GlobalHideState>(
'RefreshOptions event emits updated state with userHasHiddenDrive',
build: () {
when(() => mockDriveDao.userHasHiddenItems())
.thenAnswer((_) async => true);
return GlobalHideBloc(
userPreferencesRepository: mockUserPreferencesRepository,
driveDao: mockDriveDao,
);
},
act: (bloc) => bloc.add(const RefreshOptions(userHasHiddenItems: true)),
expect: () => [const GlobalHideInitial(userHasHiddenDrive: true)],
verify: (_) {
verify(() => mockDriveDao.userHasHiddenItems()).called(1);
},
);

blocTest<GlobalHideBloc, GlobalHideState>(
'UserPreferencesRepository updates trigger events',
build: () {
// This test case verifies that the GlobalHideBloc correctly responds to
// changes in the UserPreferencesRepository. It simulates two scenarios:
//
// 1. When showHiddenFiles is set to true:
// - The bloc should emit a ShowingHiddenItems state
// - The userHasHiddenDrive property should be true
//
// 2. When showHiddenFiles is set to false:
// - The bloc should emit a HiddingItems state
// - The userHasHiddenDrive property should remain true
when(() => mockUserPreferencesRepository.watch()).thenAnswer(
(_) => Stream.fromIterable([
/// Show hidden files
const UserPreferences(
showHiddenFiles: true,
userHasHiddenDrive: true,
currentTheme: ArDriveThemes.light,
lastSelectedDriveId: ''),

/// Hide hidden files
const UserPreferences(
showHiddenFiles: false,
userHasHiddenDrive: true,
currentTheme: ArDriveThemes.light,
lastSelectedDriveId: ''),
]),
);

when(() => mockDriveDao.userHasHiddenItems())
.thenAnswer((_) async => true);

when(() => mockUserPreferencesRepository.saveShowHiddenFiles(any()))
.thenAnswer((_) async {});

return GlobalHideBloc(
userPreferencesRepository: mockUserPreferencesRepository,
driveDao: mockDriveDao,
);
},
expect: () => [
/// Show hidden files
const ShowingHiddenItems(userHasHiddenDrive: true),

/// Hide hidden files
const HiddingItems(userHasHiddenDrive: true),
],
);
}
Loading

0 comments on commit 307d9c1

Please sign in to comment.