You've already forked immich
mirror of
https://github.com/immich-app/immich.git
synced 2025-08-08 23:07:06 +02:00
feat(mobile): Auto switching server URLs (#14437)
This commit is contained in:
@ -1,6 +1,7 @@
|
||||
import 'package:immich_mobile/services/api.service.dart';
|
||||
import 'package:immich_mobile/services/entity.service.dart';
|
||||
import 'package:immich_mobile/services/hash.service.dart';
|
||||
import 'package:immich_mobile/services/network.service.dart';
|
||||
import 'package:immich_mobile/services/sync.service.dart';
|
||||
import 'package:immich_mobile/services/user.service.dart';
|
||||
import 'package:mocktail/mocktail.dart';
|
||||
@ -14,3 +15,5 @@ class MockSyncService extends Mock implements SyncService {}
|
||||
class MockHashService extends Mock implements HashService {}
|
||||
|
||||
class MockEntityService extends Mock implements EntityService {}
|
||||
|
||||
class MockNetworkService extends Mock implements NetworkService {}
|
||||
|
@ -1,8 +1,10 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:immich_mobile/entities/store.entity.dart';
|
||||
import 'package:immich_mobile/models/auth/auxilary_endpoint.model.dart';
|
||||
import 'package:immich_mobile/services/auth.service.dart';
|
||||
import 'package:mocktail/mocktail.dart';
|
||||
import 'package:openapi/api.dart';
|
||||
import '../repository.mocks.dart';
|
||||
import '../service.mocks.dart';
|
||||
import '../test_utils.dart';
|
||||
@ -12,12 +14,22 @@ void main() {
|
||||
late MockAuthApiRepository authApiRepository;
|
||||
late MockAuthRepository authRepository;
|
||||
late MockApiService apiService;
|
||||
late MockNetworkService networkService;
|
||||
|
||||
setUp(() async {
|
||||
authApiRepository = MockAuthApiRepository();
|
||||
authRepository = MockAuthRepository();
|
||||
apiService = MockApiService();
|
||||
sut = AuthService(authApiRepository, authRepository, apiService);
|
||||
networkService = MockNetworkService();
|
||||
|
||||
sut = AuthService(
|
||||
authApiRepository,
|
||||
authRepository,
|
||||
apiService,
|
||||
networkService,
|
||||
);
|
||||
|
||||
registerFallbackValue(Uri());
|
||||
});
|
||||
|
||||
group('validateServerUrl', () {
|
||||
@ -115,4 +127,182 @@ void main() {
|
||||
verify(() => authRepository.clearLocalData()).called(1);
|
||||
});
|
||||
});
|
||||
|
||||
group('setOpenApiServiceEndpoint', () {
|
||||
setUp(() {
|
||||
when(() => networkService.getWifiName())
|
||||
.thenAnswer((_) async => 'TestWifi');
|
||||
});
|
||||
|
||||
test('Should return null if auto endpoint switching is disabled', () async {
|
||||
when(() => authRepository.getEndpointSwitchingFeature())
|
||||
.thenReturn((false));
|
||||
|
||||
final result = await sut.setOpenApiServiceEndpoint();
|
||||
|
||||
expect(result, isNull);
|
||||
verify(() => authRepository.getEndpointSwitchingFeature()).called(1);
|
||||
verifyNever(() => networkService.getWifiName());
|
||||
});
|
||||
|
||||
test('Should set local connection if wifi name matches', () async {
|
||||
when(() => authRepository.getEndpointSwitchingFeature()).thenReturn(true);
|
||||
when(() => authRepository.getPreferredWifiName()).thenReturn('TestWifi');
|
||||
when(() => authRepository.getLocalEndpoint())
|
||||
.thenReturn('http://local.endpoint');
|
||||
when(() => apiService.resolveAndSetEndpoint('http://local.endpoint'))
|
||||
.thenAnswer((_) async => 'http://local.endpoint');
|
||||
|
||||
final result = await sut.setOpenApiServiceEndpoint();
|
||||
|
||||
expect(result, 'http://local.endpoint');
|
||||
verify(() => authRepository.getEndpointSwitchingFeature()).called(1);
|
||||
verify(() => networkService.getWifiName()).called(1);
|
||||
verify(() => authRepository.getPreferredWifiName()).called(1);
|
||||
verify(() => authRepository.getLocalEndpoint()).called(1);
|
||||
verify(() => apiService.resolveAndSetEndpoint('http://local.endpoint'))
|
||||
.called(1);
|
||||
});
|
||||
|
||||
test('Should set external endpoint if wifi name not matching', () async {
|
||||
when(() => authRepository.getEndpointSwitchingFeature()).thenReturn(true);
|
||||
when(() => authRepository.getPreferredWifiName())
|
||||
.thenReturn('DifferentWifi');
|
||||
when(() => authRepository.getExternalEndpointList()).thenReturn([
|
||||
AuxilaryEndpoint(
|
||||
url: 'https://external.endpoint',
|
||||
status: AuxCheckStatus.valid,
|
||||
),
|
||||
]);
|
||||
when(
|
||||
() => apiService.resolveAndSetEndpoint('https://external.endpoint'),
|
||||
).thenAnswer((_) async => 'https://external.endpoint/api');
|
||||
|
||||
final result = await sut.setOpenApiServiceEndpoint();
|
||||
|
||||
expect(result, 'https://external.endpoint/api');
|
||||
verify(() => authRepository.getEndpointSwitchingFeature()).called(1);
|
||||
verify(() => networkService.getWifiName()).called(1);
|
||||
verify(() => authRepository.getPreferredWifiName()).called(1);
|
||||
verify(() => authRepository.getExternalEndpointList()).called(1);
|
||||
verify(
|
||||
() => apiService.resolveAndSetEndpoint('https://external.endpoint'),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test('Should set second external endpoint if the first throw any error',
|
||||
() async {
|
||||
when(() => authRepository.getEndpointSwitchingFeature()).thenReturn(true);
|
||||
when(() => authRepository.getPreferredWifiName())
|
||||
.thenReturn('DifferentWifi');
|
||||
when(() => authRepository.getExternalEndpointList()).thenReturn([
|
||||
AuxilaryEndpoint(
|
||||
url: 'https://external.endpoint',
|
||||
status: AuxCheckStatus.valid,
|
||||
),
|
||||
AuxilaryEndpoint(
|
||||
url: 'https://external.endpoint2',
|
||||
status: AuxCheckStatus.valid,
|
||||
),
|
||||
]);
|
||||
|
||||
when(
|
||||
() => apiService.resolveAndSetEndpoint('https://external.endpoint'),
|
||||
).thenThrow(Exception('Invalid endpoint'));
|
||||
when(
|
||||
() => apiService.resolveAndSetEndpoint('https://external.endpoint2'),
|
||||
).thenAnswer((_) async => 'https://external.endpoint2/api');
|
||||
|
||||
final result = await sut.setOpenApiServiceEndpoint();
|
||||
|
||||
expect(result, 'https://external.endpoint2/api');
|
||||
verify(() => authRepository.getEndpointSwitchingFeature()).called(1);
|
||||
verify(() => networkService.getWifiName()).called(1);
|
||||
verify(() => authRepository.getPreferredWifiName()).called(1);
|
||||
verify(() => authRepository.getExternalEndpointList()).called(1);
|
||||
verify(
|
||||
() => apiService.resolveAndSetEndpoint('https://external.endpoint2'),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test('Should set second external endpoint if the first throw ApiException',
|
||||
() async {
|
||||
when(() => authRepository.getEndpointSwitchingFeature()).thenReturn(true);
|
||||
when(() => authRepository.getPreferredWifiName())
|
||||
.thenReturn('DifferentWifi');
|
||||
when(() => authRepository.getExternalEndpointList()).thenReturn([
|
||||
AuxilaryEndpoint(
|
||||
url: 'https://external.endpoint',
|
||||
status: AuxCheckStatus.valid,
|
||||
),
|
||||
AuxilaryEndpoint(
|
||||
url: 'https://external.endpoint2',
|
||||
status: AuxCheckStatus.valid,
|
||||
),
|
||||
]);
|
||||
|
||||
when(
|
||||
() => apiService.resolveAndSetEndpoint('https://external.endpoint'),
|
||||
).thenThrow(ApiException(503, 'Invalid endpoint'));
|
||||
when(
|
||||
() => apiService.resolveAndSetEndpoint('https://external.endpoint2'),
|
||||
).thenAnswer((_) async => 'https://external.endpoint2/api');
|
||||
|
||||
final result = await sut.setOpenApiServiceEndpoint();
|
||||
|
||||
expect(result, 'https://external.endpoint2/api');
|
||||
verify(() => authRepository.getEndpointSwitchingFeature()).called(1);
|
||||
verify(() => networkService.getWifiName()).called(1);
|
||||
verify(() => authRepository.getPreferredWifiName()).called(1);
|
||||
verify(() => authRepository.getExternalEndpointList()).called(1);
|
||||
verify(
|
||||
() => apiService.resolveAndSetEndpoint('https://external.endpoint2'),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test('Should handle error when setting local connection', () async {
|
||||
when(() => authRepository.getEndpointSwitchingFeature()).thenReturn(true);
|
||||
when(() => authRepository.getPreferredWifiName()).thenReturn('TestWifi');
|
||||
when(() => authRepository.getLocalEndpoint())
|
||||
.thenReturn('http://local.endpoint');
|
||||
when(() => apiService.resolveAndSetEndpoint('http://local.endpoint'))
|
||||
.thenThrow(Exception('Local endpoint error'));
|
||||
|
||||
final result = await sut.setOpenApiServiceEndpoint();
|
||||
|
||||
expect(result, isNull);
|
||||
verify(() => authRepository.getEndpointSwitchingFeature()).called(1);
|
||||
verify(() => networkService.getWifiName()).called(1);
|
||||
verify(() => authRepository.getPreferredWifiName()).called(1);
|
||||
verify(() => authRepository.getLocalEndpoint()).called(1);
|
||||
verify(() => apiService.resolveAndSetEndpoint('http://local.endpoint'))
|
||||
.called(1);
|
||||
});
|
||||
|
||||
test('Should handle error when setting external connection', () async {
|
||||
when(() => authRepository.getEndpointSwitchingFeature()).thenReturn(true);
|
||||
when(() => authRepository.getPreferredWifiName())
|
||||
.thenReturn('DifferentWifi');
|
||||
when(() => authRepository.getExternalEndpointList()).thenReturn([
|
||||
AuxilaryEndpoint(
|
||||
url: 'https://external.endpoint',
|
||||
status: AuxCheckStatus.valid,
|
||||
),
|
||||
]);
|
||||
when(
|
||||
() => apiService.resolveAndSetEndpoint('https://external.endpoint'),
|
||||
).thenThrow(Exception('External endpoint error'));
|
||||
|
||||
final result = await sut.setOpenApiServiceEndpoint();
|
||||
|
||||
expect(result, isNull);
|
||||
verify(() => authRepository.getEndpointSwitchingFeature()).called(1);
|
||||
verify(() => networkService.getWifiName()).called(1);
|
||||
verify(() => authRepository.getPreferredWifiName()).called(1);
|
||||
verify(() => authRepository.getExternalEndpointList()).called(1);
|
||||
verify(
|
||||
() => apiService.resolveAndSetEndpoint('https://external.endpoint'),
|
||||
).called(1);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
Reference in New Issue
Block a user