Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions mobile/lib/providers/app_life_cycle.provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ class AppLifeCycleNotifier extends StateNotifier<AppLifeCycleEnum> {
syncSuccess = await backgroundManager.syncRemote();
}, "syncRemote"),
]);
_ref.invalidate(memoryLaneProvider);
_ref.invalidate(allMemoriesProvider);
if (syncSuccess) {
await Future.wait([
Expand Down
54 changes: 53 additions & 1 deletion mobile/test/providers/app_life_cycle_provider_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,30 @@ import 'dart:async';

import 'package:flutter_test/flutter_test.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/constants/enums.dart';
import 'package:immich_mobile/domain/models/config/app_config.dart';
import 'package:immich_mobile/domain/models/log.model.dart';
import 'package:immich_mobile/domain/services/device_permission.service.dart';
import 'package:immich_mobile/domain/services/log.service.dart';
import 'package:immich_mobile/models/auth/auth_state.model.dart';
import 'package:immich_mobile/models/server_info/server_version.model.dart';
import 'package:immich_mobile/providers/app_life_cycle.provider.dart';
import 'package:immich_mobile/providers/auth.provider.dart';
import 'package:immich_mobile/providers/background_sync.provider.dart';
import 'package:immich_mobile/providers/backup/backup.provider.dart';
import 'package:immich_mobile/providers/gallery_permission.provider.dart';
import 'package:immich_mobile/providers/infrastructure/memory.provider.dart';
import 'package:immich_mobile/providers/infrastructure/platform.provider.dart';
import 'package:immich_mobile/providers/infrastructure/settings.provider.dart';
import 'package:immich_mobile/providers/permission.provider.dart';
import 'package:immich_mobile/providers/server_info.provider.dart';
import 'package:immich_mobile/providers/websocket.provider.dart';
import 'package:immich_mobile/utils/upload_speed_calculator.dart';
import 'package:mocktail/mocktail.dart';
import 'package:permission_handler/permission_handler.dart';

import '../infrastructure/repository.mock.dart';
import '../repository.mocks.dart';
import '../service.mocks.dart';

class FakeLogMessage extends Fake implements LogMessage {}
Expand Down Expand Up @@ -51,6 +60,7 @@ class TestWebsocketNotifier extends WebsocketNotifier {

int connectCount = 0;
int disconnectCount = 0;
bool throwOnConnect = true;
final connectCalled = Completer<void>();

@override
Expand All @@ -59,7 +69,9 @@ class TestWebsocketNotifier extends WebsocketNotifier {
if (!connectCalled.isCompleted) {
connectCalled.complete();
}
throw StateError('unexpected websocket connection');
if (throwOnConnect) {
throw StateError('unexpected websocket connection');
}
}

@override
Expand All @@ -70,6 +82,18 @@ class TestDriftBackupNotifier extends BackupNotifier {
TestDriftBackupNotifier() : super(MockForegroundUploadService(), MockBackgroundUploadService(), UploadSpeedManager());
}

class TestNotificationPermissionNotifier extends NotificationPermissionNotifier {
@override
Future<PermissionStatus> getNotificationPermission() async => state;
}

class TestGalleryPermissionNotifier extends GalleryPermissionNotifier {
TestGalleryPermissionNotifier() : super(DevicePermissionService(MockPermissionRepository()));

@override
Future<DevicePermissionStatus> getGalleryPermissionStatus() async => state;
}

void main() {
late LogService logService;
late Completer<ServerVersion?> serverVersion;
Expand All @@ -79,6 +103,7 @@ void main() {
late TestWebsocketNotifier websocket;
late AppLifeCycleNotifier lifeCycle;
late int serverVersionCount;
late int memoryLaneBuilds;

setUpAll(() async {
final logRepository = MockLogRepository();
Expand All @@ -100,14 +125,20 @@ void main() {
serverVersion = Completer<ServerVersion?>();
serverInfoService = MockServerInfoService();
lockService = MockBackgroundWorkerLockService();
final backgroundSync = MockBackgroundSyncManager();
serverVersionCount = 0;
memoryLaneBuilds = 0;

when(() => serverInfoService.getServerVersion()).thenAnswer((_) {
serverVersionCount++;
return serverVersionCount == 1 ? serverVersion.future : Future<ServerVersion?>.value();
});
when(() => lockService.lock()).thenAnswer((_) async {});
when(() => lockService.unlock()).thenAnswer((_) async {});
when(() => backgroundSync.cancelResumeSyncs()).thenAnswer((_) async {});
when(() => backgroundSync.syncLocal(full: any(named: 'full'))).thenAnswer((_) async {});
when(() => backgroundSync.syncRemote()).thenAnswer((_) async => true);
when(() => backgroundSync.hashAssets()).thenAnswer((_) async {});

container = ProviderContainer(
overrides: [
Expand All @@ -118,6 +149,14 @@ void main() {
}),
backupProvider.overrideWith((_) => TestDriftBackupNotifier()),
backgroundWorkerLockServiceProvider.overrideWithValue(lockService),
backgroundSyncProvider.overrideWithValue(backgroundSync),
appConfigProvider.overrideWithValue(defaultConfig),
notificationPermissionProvider.overrideWith((_) => TestNotificationPermissionNotifier()),
galleryPermissionNotifier.overrideWith((_) => TestGalleryPermissionNotifier()),
memoryLaneProvider.overrideWith((_) {
memoryLaneBuilds++;
return const [];
}),
],
);
lifeCycle = container.read(appStateProvider.notifier);
Expand Down Expand Up @@ -177,4 +216,17 @@ void main() {
expect(websocket.disconnectCount, 2);
expect(websocket.connectCount, 1);
});

test('resume re-queries the memory lane', () async {
container.listen(memoryLaneProvider, (_, _) {});
expect(memoryLaneBuilds, 1);

await lifeCycle.handleAppPause();
websocket.throwOnConnect = false;
serverVersion.complete();
await lifeCycle.handleAppResume();
await Future<void>.delayed(Duration.zero);

expect(memoryLaneBuilds, 2);
});
}
Loading