nostr tools added
This commit is contained in:
@@ -207,11 +207,28 @@ void main() {
|
||||
];
|
||||
|
||||
final mockDio = _createMockDio(
|
||||
onGet: (path) => Response(
|
||||
statusCode: 200,
|
||||
data: mockAssets,
|
||||
requestOptions: RequestOptions(path: path),
|
||||
),
|
||||
onPost: (path, data) {
|
||||
if (path == '/api/search/metadata') {
|
||||
// Return the correct nested response structure
|
||||
return Response(
|
||||
statusCode: 200,
|
||||
data: {
|
||||
'assets': {
|
||||
'items': mockAssets,
|
||||
'total': mockAssets.length,
|
||||
'count': mockAssets.length,
|
||||
'nextPage': null,
|
||||
}
|
||||
},
|
||||
requestOptions: RequestOptions(path: path),
|
||||
);
|
||||
}
|
||||
return Response(
|
||||
statusCode: 200,
|
||||
data: {},
|
||||
requestOptions: RequestOptions(path: path),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
final immichService = ImmichService(
|
||||
@@ -238,28 +255,38 @@ void main() {
|
||||
test('fetchAssets - pagination', () async {
|
||||
// Arrange
|
||||
final mockDio = _createMockDio(
|
||||
onGet: (path) {
|
||||
// Extract query parameters from request options
|
||||
// The path might be just the endpoint, so we need to check request options
|
||||
final uri = path.startsWith('http')
|
||||
? Uri.parse(path)
|
||||
: Uri.parse('https://immich.example.com$path');
|
||||
final queryParams = uri.queryParameters;
|
||||
final skip = int.parse(queryParams['skip'] ?? '0');
|
||||
final limit = int.parse(queryParams['limit'] ?? '100');
|
||||
onPost: (path, data) {
|
||||
if (path == '/api/search/metadata') {
|
||||
// Extract limit and skip from request body (data), not query params
|
||||
final requestData = data as Map<String, dynamic>;
|
||||
final limit = requestData['limit'] as int? ?? 100;
|
||||
final skip = requestData['skip'] as int? ?? 0;
|
||||
|
||||
return Response(
|
||||
statusCode: 200,
|
||||
data: {
|
||||
'assets': {
|
||||
'items': List.generate(
|
||||
limit,
|
||||
(i) => {
|
||||
'id': 'asset-${skip + i}',
|
||||
'originalFileName': 'image${skip + i}.jpg',
|
||||
'createdAt': DateTime.now().toIso8601String(),
|
||||
'fileSizeByte': 1000,
|
||||
'mimeType': 'image/jpeg',
|
||||
},
|
||||
),
|
||||
'total': 100, // Mock total
|
||||
'count': limit,
|
||||
'nextPage': null,
|
||||
}
|
||||
},
|
||||
requestOptions: RequestOptions(path: path),
|
||||
);
|
||||
}
|
||||
return Response(
|
||||
statusCode: 200,
|
||||
data: List.generate(
|
||||
limit,
|
||||
(i) => {
|
||||
'id': 'asset-${skip + i}',
|
||||
'originalFileName': 'image${skip + i}.jpg',
|
||||
'createdAt': DateTime.now().toIso8601String(),
|
||||
'fileSizeByte': 1000,
|
||||
'mimeType': 'image/jpeg',
|
||||
},
|
||||
),
|
||||
data: {},
|
||||
requestOptions: RequestOptions(path: path),
|
||||
);
|
||||
},
|
||||
@@ -287,11 +314,20 @@ void main() {
|
||||
test('fetchAssets - server error', () async {
|
||||
// Arrange
|
||||
final mockDio = _createMockDio(
|
||||
onGet: (path) => Response(
|
||||
statusCode: 500,
|
||||
data: {'error': 'Internal server error'},
|
||||
requestOptions: RequestOptions(path: path),
|
||||
),
|
||||
onPost: (path, data) {
|
||||
if (path == '/api/search/metadata') {
|
||||
return Response(
|
||||
statusCode: 500,
|
||||
data: {'error': 'Internal server error', 'message': 'Internal server error'},
|
||||
requestOptions: RequestOptions(path: path),
|
||||
);
|
||||
}
|
||||
return Response(
|
||||
statusCode: 200,
|
||||
data: {},
|
||||
requestOptions: RequestOptions(path: path),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
final immichService = ImmichService(
|
||||
|
||||
@@ -5,6 +5,7 @@ import 'package:mockito/mockito.dart';
|
||||
import 'package:app_boilerplate/ui/navigation/main_navigation_scaffold.dart';
|
||||
import 'package:app_boilerplate/data/local/local_storage_service.dart';
|
||||
import 'package:app_boilerplate/data/nostr/nostr_service.dart';
|
||||
import 'package:app_boilerplate/data/nostr/models/nostr_keypair.dart';
|
||||
import 'package:app_boilerplate/data/sync/sync_engine.dart';
|
||||
import 'package:app_boilerplate/data/session/session_service.dart';
|
||||
import 'package:app_boilerplate/data/firebase/firebase_service.dart';
|
||||
@@ -36,6 +37,11 @@ void main() {
|
||||
when(mockSessionService.isLoggedIn).thenReturn(false);
|
||||
when(mockSessionService.currentUser).thenReturn(null);
|
||||
when(mockFirebaseService.isEnabled).thenReturn(false);
|
||||
when(mockNostrService.getRelays()).thenReturn([]);
|
||||
|
||||
// Stub NostrService methods that might be called by UI
|
||||
final mockKeyPair = NostrKeyPair.generate();
|
||||
when(mockNostrService.generateKeyPair()).thenReturn(mockKeyPair);
|
||||
});
|
||||
|
||||
Widget createTestWidget() {
|
||||
@@ -68,7 +74,8 @@ void main() {
|
||||
await tester.pumpWidget(createTestWidget());
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.text('Home'), findsOneWidget); // AppBar title
|
||||
// Home text might appear in AppBar and body, so check for at least one
|
||||
expect(find.text('Home'), findsWidgets);
|
||||
expect(find.byIcon(Icons.home), findsWidgets);
|
||||
});
|
||||
|
||||
@@ -76,8 +83,8 @@ void main() {
|
||||
await tester.pumpWidget(createTestWidget());
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// Verify Home is shown initially
|
||||
expect(find.text('Home'), findsOneWidget);
|
||||
// Verify Home is shown initially (might appear multiple times)
|
||||
expect(find.text('Home'), findsWidgets);
|
||||
|
||||
// Verify navigation structure allows switching
|
||||
expect(find.byType(BottomNavigationBar), findsOneWidget);
|
||||
@@ -116,7 +123,7 @@ void main() {
|
||||
await tester.pumpWidget(createTestWidget());
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.text('Home'), findsOneWidget); // AppBar title
|
||||
expect(find.text('Home'), findsWidgets); // AppBar title and/or body
|
||||
expect(find.byType(Scaffold), findsWidgets);
|
||||
});
|
||||
|
||||
@@ -128,7 +135,7 @@ void main() {
|
||||
expect(find.byType(BottomNavigationBar), findsOneWidget);
|
||||
expect(find.byType(Scaffold), findsWidgets);
|
||||
// IndexedStack is internal - verify it indirectly by checking scaffold renders
|
||||
expect(find.text('Home'), findsOneWidget); // Home screen should be visible
|
||||
expect(find.text('Home'), findsWidgets); // Home screen should be visible
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -6,23 +6,24 @@
|
||||
import 'dart:async' as _i9;
|
||||
import 'dart:io' as _i2;
|
||||
|
||||
import 'package:app_boilerplate/data/firebase/firebase_service.dart' as _i18;
|
||||
import 'package:app_boilerplate/data/firebase/firebase_service.dart' as _i19;
|
||||
import 'package:app_boilerplate/data/firebase/models/firebase_config.dart'
|
||||
as _i6;
|
||||
import 'package:app_boilerplate/data/local/local_storage_service.dart' as _i7;
|
||||
import 'package:app_boilerplate/data/local/models/item.dart' as _i10;
|
||||
import 'package:app_boilerplate/data/nostr/models/nostr_event.dart' as _i4;
|
||||
import 'package:app_boilerplate/data/nostr/models/nostr_keypair.dart' as _i3;
|
||||
import 'package:app_boilerplate/data/nostr/models/nostr_profile.dart' as _i13;
|
||||
import 'package:app_boilerplate/data/nostr/models/nostr_relay.dart' as _i12;
|
||||
import 'package:app_boilerplate/data/nostr/nostr_service.dart' as _i11;
|
||||
import 'package:app_boilerplate/data/session/models/user.dart' as _i5;
|
||||
import 'package:app_boilerplate/data/session/session_service.dart' as _i17;
|
||||
import 'package:app_boilerplate/data/sync/models/sync_operation.dart' as _i14;
|
||||
import 'package:app_boilerplate/data/sync/models/sync_status.dart' as _i15;
|
||||
import 'package:app_boilerplate/data/sync/sync_engine.dart' as _i13;
|
||||
import 'package:app_boilerplate/data/session/session_service.dart' as _i18;
|
||||
import 'package:app_boilerplate/data/sync/models/sync_operation.dart' as _i15;
|
||||
import 'package:app_boilerplate/data/sync/models/sync_status.dart' as _i16;
|
||||
import 'package:app_boilerplate/data/sync/sync_engine.dart' as _i14;
|
||||
import 'package:firebase_auth/firebase_auth.dart' as _i8;
|
||||
import 'package:mockito/mockito.dart' as _i1;
|
||||
import 'package:mockito/src/dummies.dart' as _i16;
|
||||
import 'package:mockito/src/dummies.dart' as _i17;
|
||||
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: avoid_redundant_argument_values
|
||||
@@ -377,6 +378,20 @@ class MockNostrService extends _i1.Mock implements _i11.NostrService {
|
||||
)),
|
||||
) as _i9.Future<_i4.NostrEvent>);
|
||||
|
||||
@override
|
||||
_i9.Future<_i13.NostrProfile?> fetchProfile(
|
||||
String? publicKey, {
|
||||
Duration? timeout = const Duration(seconds: 10),
|
||||
}) =>
|
||||
(super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#fetchProfile,
|
||||
[publicKey],
|
||||
{#timeout: timeout},
|
||||
),
|
||||
returnValue: _i9.Future<_i13.NostrProfile?>.value(),
|
||||
) as _i9.Future<_i13.NostrProfile?>);
|
||||
|
||||
@override
|
||||
void dispose() => super.noSuchMethod(
|
||||
Invocation.method(
|
||||
@@ -390,7 +405,7 @@ class MockNostrService extends _i1.Mock implements _i11.NostrService {
|
||||
/// A class which mocks [SyncEngine].
|
||||
///
|
||||
/// See the documentation for Mockito's code generation for more information.
|
||||
class MockSyncEngine extends _i1.Mock implements _i13.SyncEngine {
|
||||
class MockSyncEngine extends _i1.Mock implements _i14.SyncEngine {
|
||||
MockSyncEngine() {
|
||||
_i1.throwOnMissingStub(this);
|
||||
}
|
||||
@@ -402,10 +417,10 @@ class MockSyncEngine extends _i1.Mock implements _i13.SyncEngine {
|
||||
) as int);
|
||||
|
||||
@override
|
||||
_i9.Stream<_i14.SyncOperation> get statusStream => (super.noSuchMethod(
|
||||
_i9.Stream<_i15.SyncOperation> get statusStream => (super.noSuchMethod(
|
||||
Invocation.getter(#statusStream),
|
||||
returnValue: _i9.Stream<_i14.SyncOperation>.empty(),
|
||||
) as _i9.Stream<_i14.SyncOperation>);
|
||||
returnValue: _i9.Stream<_i15.SyncOperation>.empty(),
|
||||
) as _i9.Stream<_i15.SyncOperation>);
|
||||
|
||||
@override
|
||||
void setNostrKeyPair(_i3.NostrKeyPair? keypair) => super.noSuchMethod(
|
||||
@@ -417,7 +432,7 @@ class MockSyncEngine extends _i1.Mock implements _i13.SyncEngine {
|
||||
);
|
||||
|
||||
@override
|
||||
void setConflictResolution(_i15.ConflictResolution? strategy) =>
|
||||
void setConflictResolution(_i16.ConflictResolution? strategy) =>
|
||||
super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#setConflictResolution,
|
||||
@@ -427,25 +442,25 @@ class MockSyncEngine extends _i1.Mock implements _i13.SyncEngine {
|
||||
);
|
||||
|
||||
@override
|
||||
List<_i14.SyncOperation> getPendingOperations() => (super.noSuchMethod(
|
||||
List<_i15.SyncOperation> getPendingOperations() => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#getPendingOperations,
|
||||
[],
|
||||
),
|
||||
returnValue: <_i14.SyncOperation>[],
|
||||
) as List<_i14.SyncOperation>);
|
||||
returnValue: <_i15.SyncOperation>[],
|
||||
) as List<_i15.SyncOperation>);
|
||||
|
||||
@override
|
||||
List<_i14.SyncOperation> getAllOperations() => (super.noSuchMethod(
|
||||
List<_i15.SyncOperation> getAllOperations() => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#getAllOperations,
|
||||
[],
|
||||
),
|
||||
returnValue: <_i14.SyncOperation>[],
|
||||
) as List<_i14.SyncOperation>);
|
||||
returnValue: <_i15.SyncOperation>[],
|
||||
) as List<_i15.SyncOperation>);
|
||||
|
||||
@override
|
||||
void queueOperation(_i14.SyncOperation? operation) => super.noSuchMethod(
|
||||
void queueOperation(_i15.SyncOperation? operation) => super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#queueOperation,
|
||||
[operation],
|
||||
@@ -456,7 +471,7 @@ class MockSyncEngine extends _i1.Mock implements _i13.SyncEngine {
|
||||
@override
|
||||
_i9.Future<String> syncToImmich(
|
||||
String? itemId, {
|
||||
_i15.SyncPriority? priority = _i15.SyncPriority.normal,
|
||||
_i16.SyncPriority? priority = _i16.SyncPriority.normal,
|
||||
}) =>
|
||||
(super.noSuchMethod(
|
||||
Invocation.method(
|
||||
@@ -464,7 +479,7 @@ class MockSyncEngine extends _i1.Mock implements _i13.SyncEngine {
|
||||
[itemId],
|
||||
{#priority: priority},
|
||||
),
|
||||
returnValue: _i9.Future<String>.value(_i16.dummyValue<String>(
|
||||
returnValue: _i9.Future<String>.value(_i17.dummyValue<String>(
|
||||
this,
|
||||
Invocation.method(
|
||||
#syncToImmich,
|
||||
@@ -477,7 +492,7 @@ class MockSyncEngine extends _i1.Mock implements _i13.SyncEngine {
|
||||
@override
|
||||
_i9.Future<String> syncFromImmich(
|
||||
String? assetId, {
|
||||
_i15.SyncPriority? priority = _i15.SyncPriority.normal,
|
||||
_i16.SyncPriority? priority = _i16.SyncPriority.normal,
|
||||
}) =>
|
||||
(super.noSuchMethod(
|
||||
Invocation.method(
|
||||
@@ -485,7 +500,7 @@ class MockSyncEngine extends _i1.Mock implements _i13.SyncEngine {
|
||||
[assetId],
|
||||
{#priority: priority},
|
||||
),
|
||||
returnValue: _i9.Future<String>.value(_i16.dummyValue<String>(
|
||||
returnValue: _i9.Future<String>.value(_i17.dummyValue<String>(
|
||||
this,
|
||||
Invocation.method(
|
||||
#syncFromImmich,
|
||||
@@ -498,7 +513,7 @@ class MockSyncEngine extends _i1.Mock implements _i13.SyncEngine {
|
||||
@override
|
||||
_i9.Future<String> syncToNostr(
|
||||
String? itemId, {
|
||||
_i15.SyncPriority? priority = _i15.SyncPriority.normal,
|
||||
_i16.SyncPriority? priority = _i16.SyncPriority.normal,
|
||||
}) =>
|
||||
(super.noSuchMethod(
|
||||
Invocation.method(
|
||||
@@ -506,7 +521,7 @@ class MockSyncEngine extends _i1.Mock implements _i13.SyncEngine {
|
||||
[itemId],
|
||||
{#priority: priority},
|
||||
),
|
||||
returnValue: _i9.Future<String>.value(_i16.dummyValue<String>(
|
||||
returnValue: _i9.Future<String>.value(_i17.dummyValue<String>(
|
||||
this,
|
||||
Invocation.method(
|
||||
#syncToNostr,
|
||||
@@ -518,7 +533,7 @@ class MockSyncEngine extends _i1.Mock implements _i13.SyncEngine {
|
||||
|
||||
@override
|
||||
_i9.Future<List<String>> syncAll(
|
||||
{_i15.SyncPriority? priority = _i15.SyncPriority.normal}) =>
|
||||
{_i16.SyncPriority? priority = _i16.SyncPriority.normal}) =>
|
||||
(super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#syncAll,
|
||||
@@ -575,7 +590,7 @@ class MockSyncEngine extends _i1.Mock implements _i13.SyncEngine {
|
||||
/// A class which mocks [SessionService].
|
||||
///
|
||||
/// See the documentation for Mockito's code generation for more information.
|
||||
class MockSessionService extends _i1.Mock implements _i17.SessionService {
|
||||
class MockSessionService extends _i1.Mock implements _i18.SessionService {
|
||||
MockSessionService() {
|
||||
_i1.throwOnMissingStub(this);
|
||||
}
|
||||
@@ -616,6 +631,22 @@ class MockSessionService extends _i1.Mock implements _i17.SessionService {
|
||||
)),
|
||||
) as _i9.Future<_i5.User>);
|
||||
|
||||
@override
|
||||
_i9.Future<_i5.User> loginWithNostr(String? nsecOrNpub) =>
|
||||
(super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#loginWithNostr,
|
||||
[nsecOrNpub],
|
||||
),
|
||||
returnValue: _i9.Future<_i5.User>.value(_FakeUser_3(
|
||||
this,
|
||||
Invocation.method(
|
||||
#loginWithNostr,
|
||||
[nsecOrNpub],
|
||||
),
|
||||
)),
|
||||
) as _i9.Future<_i5.User>);
|
||||
|
||||
@override
|
||||
_i9.Future<void> logout({bool? clearCache = true}) => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
@@ -664,7 +695,7 @@ class MockSessionService extends _i1.Mock implements _i17.SessionService {
|
||||
/// A class which mocks [FirebaseService].
|
||||
///
|
||||
/// See the documentation for Mockito's code generation for more information.
|
||||
class MockFirebaseService extends _i1.Mock implements _i18.FirebaseService {
|
||||
class MockFirebaseService extends _i1.Mock implements _i19.FirebaseService {
|
||||
MockFirebaseService() {
|
||||
_i1.throwOnMissingStub(this);
|
||||
}
|
||||
@@ -780,7 +811,7 @@ class MockFirebaseService extends _i1.Mock implements _i18.FirebaseService {
|
||||
path,
|
||||
],
|
||||
),
|
||||
returnValue: _i9.Future<String>.value(_i16.dummyValue<String>(
|
||||
returnValue: _i9.Future<String>.value(_i17.dummyValue<String>(
|
||||
this,
|
||||
Invocation.method(
|
||||
#uploadFile,
|
||||
|
||||
Reference in New Issue
Block a user