diff --git a/test/providers/auth_provider_test.mocks.dart b/test/providers/auth_provider_test.mocks.dart index 0394e4a..2457a55 100644 --- a/test/providers/auth_provider_test.mocks.dart +++ b/test/providers/auth_provider_test.mocks.dart @@ -8,6 +8,7 @@ import 'dart:async' as _i4; import 'package:coves_flutter/models/coves_session.dart' as _i2; import 'package:coves_flutter/services/coves_auth_service.dart' as _i3; import 'package:mockito/mockito.dart' as _i1; +import 'package:mockito/src/dummies.dart' as _i5; // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values @@ -90,4 +91,15 @@ class MockCovesAuthService extends _i1.Mock implements _i3.CovesAuthService { returnValueForMissingStub: _i4.Future.value(), ) as _i4.Future); + + @override + String validateAndNormalizeHandle(String? handle) => + (super.noSuchMethod( + Invocation.method(#validateAndNormalizeHandle, [handle]), + returnValue: _i5.dummyValue( + this, + Invocation.method(#validateAndNormalizeHandle, [handle]), + ), + ) + as String); } diff --git a/test/providers/comments_provider_test.dart b/test/providers/comments_provider_test.dart index 2444b97..257bde1 100644 --- a/test/providers/comments_provider_test.dart +++ b/test/providers/comments_provider_test.dart @@ -4,7 +4,6 @@ import 'package:coves_flutter/providers/auth_provider.dart'; import 'package:coves_flutter/providers/comments_provider.dart'; import 'package:coves_flutter/providers/vote_provider.dart'; import 'package:coves_flutter/services/coves_api_service.dart'; -import 'package:coves_flutter/services/vote_service.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; @@ -12,7 +11,7 @@ import 'package:mockito/mockito.dart'; import 'comments_provider_test.mocks.dart'; // Generate mocks for dependencies -@GenerateMocks([AuthProvider, CovesApiService, VoteProvider, VoteService]) +@GenerateMocks([AuthProvider, CovesApiService, VoteProvider]) void main() { TestWidgetsFlutterBinding.ensureInitialized(); @@ -21,13 +20,11 @@ void main() { late MockAuthProvider mockAuthProvider; late MockCovesApiService mockApiService; late MockVoteProvider mockVoteProvider; - late MockVoteService mockVoteService; setUp(() { mockAuthProvider = MockAuthProvider(); mockApiService = MockCovesApiService(); mockVoteProvider = MockVoteProvider(); - mockVoteService = MockVoteService(); // Default: user is authenticated when(mockAuthProvider.isAuthenticated).thenReturn(true); @@ -39,7 +36,6 @@ void main() { mockAuthProvider, apiService: mockApiService, voteProvider: mockVoteProvider, - voteService: mockVoteService, ); }); @@ -73,10 +69,6 @@ void main() { ), ).thenAnswer((_) async => mockResponse); - when( - mockVoteService.getUserVotes(), - ).thenAnswer((_) async => {}); - await commentsProvider.loadComments( postUri: testPostUri, refresh: true, @@ -102,10 +94,6 @@ void main() { ), ).thenAnswer((_) async => mockResponse); - when( - mockVoteService.getUserVotes(), - ).thenAnswer((_) async => {}); - await commentsProvider.loadComments( postUri: testPostUri, refresh: true, @@ -179,10 +167,6 @@ void main() { ), ).thenAnswer((_) async => firstResponse); - when( - mockVoteService.getUserVotes(), - ).thenAnswer((_) async => {}); - await commentsProvider.loadComments( postUri: testPostUri, refresh: true, @@ -234,10 +218,6 @@ void main() { ), ).thenAnswer((_) async => firstResponse); - when( - mockVoteService.getUserVotes(), - ).thenAnswer((_) async => {}); - await commentsProvider.loadComments( postUri: testPostUri, refresh: true, @@ -292,10 +272,6 @@ void main() { ), ).thenAnswer((_) async => response); - when( - mockVoteService.getUserVotes(), - ).thenAnswer((_) async => {}); - await commentsProvider.loadComments( postUri: testPostUri, refresh: true, @@ -323,10 +299,6 @@ void main() { ), ).thenAnswer((_) async => firstResponse); - when( - mockVoteService.getUserVotes(), - ).thenAnswer((_) async => {}); - await commentsProvider.loadComments( postUri: testPostUri, refresh: true, @@ -384,10 +356,6 @@ void main() { return response; }); - when( - mockVoteService.getUserVotes(), - ).thenAnswer((_) async => {}); - // Start first load final firstFuture = commentsProvider.loadComments( postUri: testPostUri, @@ -417,45 +385,38 @@ void main() { ).called(2); }); - test('should load vote state when authenticated', () async { - final mockComments = [_createMockThreadComment('comment1')]; - - final mockResponse = CommentsResponse(post: {}, comments: mockComments); - - when( - mockApiService.getComments( - postUri: anyNamed('postUri'), - sort: anyNamed('sort'), - timeframe: anyNamed('timeframe'), - depth: anyNamed('depth'), - limit: anyNamed('limit'), - cursor: anyNamed('cursor'), - ), - ).thenAnswer((_) async => mockResponse); - - final mockUserVotes = { - 'comment1': const VoteInfo( - voteUri: 'at://did:plc:test/social.coves.feed.vote/123', - direction: 'up', - rkey: '123', - ), - }; - - when( - mockVoteService.getUserVotes(), - ).thenAnswer((_) async => mockUserVotes); - when(mockVoteProvider.loadInitialVotes(any)).thenReturn(null); - - await commentsProvider.loadComments( - postUri: testPostUri, - refresh: true, - ); + test( + 'should initialize vote state from viewer data when authenticated', + () async { + final mockComments = [_createMockThreadComment('comment1')]; + + final mockResponse = CommentsResponse( + post: {}, + comments: mockComments, + ); + + when( + mockApiService.getComments( + postUri: anyNamed('postUri'), + sort: anyNamed('sort'), + timeframe: anyNamed('timeframe'), + depth: anyNamed('depth'), + limit: anyNamed('limit'), + cursor: anyNamed('cursor'), + ), + ).thenAnswer((_) async => mockResponse); + + await commentsProvider.loadComments( + postUri: testPostUri, + refresh: true, + ); - verify(mockVoteService.getUserVotes()).called(1); - verify(mockVoteProvider.loadInitialVotes(mockUserVotes)).called(1); - }); + expect(commentsProvider.comments.length, 1); + expect(commentsProvider.error, null); + }, + ); - test('should not load vote state when not authenticated', () async { + test('should not initialize vote state when not authenticated', () async { when(mockAuthProvider.isAuthenticated).thenReturn(false); final mockResponse = CommentsResponse( @@ -479,36 +440,6 @@ void main() { refresh: true, ); - verifyNever(mockVoteService.getUserVotes()); - verifyNever(mockVoteProvider.loadInitialVotes(any)); - }); - - test('should continue loading comments if vote loading fails', () async { - final mockComments = [_createMockThreadComment('comment1')]; - - final mockResponse = CommentsResponse(post: {}, comments: mockComments); - - when( - mockApiService.getComments( - postUri: anyNamed('postUri'), - sort: anyNamed('sort'), - timeframe: anyNamed('timeframe'), - depth: anyNamed('depth'), - limit: anyNamed('limit'), - cursor: anyNamed('cursor'), - ), - ).thenAnswer((_) async => mockResponse); - - when( - mockVoteService.getUserVotes(), - ).thenThrow(Exception('Vote service error')); - - await commentsProvider.loadComments( - postUri: testPostUri, - refresh: true, - ); - - // Comments should still be loaded despite vote error expect(commentsProvider.comments.length, 1); expect(commentsProvider.error, null); }); @@ -534,10 +465,6 @@ void main() { ), ).thenAnswer((_) async => initialResponse); - when( - mockVoteService.getUserVotes(), - ).thenAnswer((_) async => {}); - await commentsProvider.loadComments( postUri: testPostUri, refresh: true, @@ -595,10 +522,6 @@ void main() { ), ).thenAnswer((_) async => response); - when( - mockVoteService.getUserVotes(), - ).thenAnswer((_) async => {}); - await commentsProvider.loadComments( postUri: testPostUri, refresh: true, @@ -641,10 +564,6 @@ void main() { ), ).thenAnswer((_) async => initialResponse); - when( - mockVoteService.getUserVotes(), - ).thenAnswer((_) async => {}); - await commentsProvider.loadComments( postUri: testPostUri, refresh: true, @@ -714,10 +633,6 @@ void main() { ), ).thenAnswer((_) async => initialResponse); - when( - mockVoteService.getUserVotes(), - ).thenAnswer((_) async => {}); - await commentsProvider.loadComments( postUri: testPostUri, refresh: true, @@ -765,10 +680,6 @@ void main() { ), ).thenAnswer((_) async => response); - when( - mockVoteService.getUserVotes(), - ).thenAnswer((_) async => {}); - await commentsProvider.loadComments( postUri: testPostUri, refresh: true, @@ -848,10 +759,6 @@ void main() { ), ).thenAnswer((_) async => successResponse); - when( - mockVoteService.getUserVotes(), - ).thenAnswer((_) async => {}); - await commentsProvider.retry(); expect(commentsProvider.error, null); @@ -879,10 +786,6 @@ void main() { ), ).thenAnswer((_) async => response); - when( - mockVoteService.getUserVotes(), - ).thenAnswer((_) async => {}); - await commentsProvider.loadComments( postUri: testPostUri, refresh: true, @@ -917,10 +820,6 @@ void main() { ), ).thenAnswer((_) async => response); - when( - mockVoteService.getUserVotes(), - ).thenAnswer((_) async => {}); - expect(commentsProvider.currentTimeNotifier.value, null); await commentsProvider.loadComments( @@ -948,10 +847,6 @@ void main() { ), ).thenAnswer((_) async => response); - when( - mockVoteService.getUserVotes(), - ).thenAnswer((_) async => {}); - await commentsProvider.loadComments( postUri: 'at://did:plc:test/social.coves.post.record/123', refresh: true, @@ -990,10 +885,6 @@ void main() { ), ).thenAnswer((_) async => response); - when( - mockVoteService.getUserVotes(), - ).thenAnswer((_) async => {}); - await commentsProvider.loadComments( postUri: 'at://did:plc:test/social.coves.post.record/123', refresh: true, @@ -1022,10 +913,6 @@ void main() { return response; }); - when( - mockVoteService.getUserVotes(), - ).thenAnswer((_) async => {}); - final loadFuture = commentsProvider.loadComments( postUri: 'at://did:plc:test/social.coves.post.record/123', refresh: true, @@ -1040,6 +927,329 @@ void main() { expect(commentsProvider.isLoading, false); }); }); + + group('Vote state initialization from viewer data', () { + const testPostUri = 'at://did:plc:test/social.coves.post.record/123'; + + test('should initialize vote state when viewer.vote is "up"', () async { + final response = CommentsResponse( + post: {}, + comments: [ + _createMockThreadCommentWithViewer( + uri: 'comment1', + vote: 'up', + voteUri: 'at://did:plc:test/social.coves.feed.vote/vote1', + ), + ], + ); + + when( + mockApiService.getComments( + postUri: anyNamed('postUri'), + sort: anyNamed('sort'), + timeframe: anyNamed('timeframe'), + depth: anyNamed('depth'), + limit: anyNamed('limit'), + cursor: anyNamed('cursor'), + ), + ).thenAnswer((_) async => response); + + await commentsProvider.loadComments( + postUri: testPostUri, + refresh: true, + ); + + verify( + mockVoteProvider.setInitialVoteState( + postUri: 'comment1', + voteDirection: 'up', + voteUri: 'at://did:plc:test/social.coves.feed.vote/vote1', + ), + ).called(1); + }); + + test('should initialize vote state when viewer.vote is "down"', () async { + final response = CommentsResponse( + post: {}, + comments: [ + _createMockThreadCommentWithViewer( + uri: 'comment1', + vote: 'down', + voteUri: 'at://did:plc:test/social.coves.feed.vote/vote1', + ), + ], + ); + + when( + mockApiService.getComments( + postUri: anyNamed('postUri'), + sort: anyNamed('sort'), + timeframe: anyNamed('timeframe'), + depth: anyNamed('depth'), + limit: anyNamed('limit'), + cursor: anyNamed('cursor'), + ), + ).thenAnswer((_) async => response); + + await commentsProvider.loadComments( + postUri: testPostUri, + refresh: true, + ); + + verify( + mockVoteProvider.setInitialVoteState( + postUri: 'comment1', + voteDirection: 'down', + voteUri: 'at://did:plc:test/social.coves.feed.vote/vote1', + ), + ).called(1); + }); + + test( + 'should clear stale vote state when viewer.vote is null on refresh', + () async { + final response = CommentsResponse( + post: {}, + comments: [ + _createMockThreadCommentWithViewer( + uri: 'comment1', + vote: null, + voteUri: null, + ), + ], + ); + + when( + mockApiService.getComments( + postUri: anyNamed('postUri'), + sort: anyNamed('sort'), + timeframe: anyNamed('timeframe'), + depth: anyNamed('depth'), + limit: anyNamed('limit'), + cursor: anyNamed('cursor'), + ), + ).thenAnswer((_) async => response); + + await commentsProvider.loadComments( + postUri: testPostUri, + refresh: true, + ); + + // Should call setInitialVoteState with null to clear stale state + verify( + mockVoteProvider.setInitialVoteState( + postUri: 'comment1', + voteDirection: null, + voteUri: null, + ), + ).called(1); + }, + ); + + test( + 'should initialize vote state recursively for nested replies', + () async { + final response = CommentsResponse( + post: {}, + comments: [ + _createMockThreadCommentWithViewer( + uri: 'parent-comment', + vote: 'up', + voteUri: 'at://did:plc:test/social.coves.feed.vote/vote-parent', + replies: [ + _createMockThreadCommentWithViewer( + uri: 'reply-comment', + vote: 'down', + voteUri: + 'at://did:plc:test/social.coves.feed.vote/vote-reply', + ), + ], + ), + ], + ); + + when( + mockApiService.getComments( + postUri: anyNamed('postUri'), + sort: anyNamed('sort'), + timeframe: anyNamed('timeframe'), + depth: anyNamed('depth'), + limit: anyNamed('limit'), + cursor: anyNamed('cursor'), + ), + ).thenAnswer((_) async => response); + + await commentsProvider.loadComments( + postUri: testPostUri, + refresh: true, + ); + + // Should initialize vote state for both parent and reply + verify( + mockVoteProvider.setInitialVoteState( + postUri: 'parent-comment', + voteDirection: 'up', + voteUri: 'at://did:plc:test/social.coves.feed.vote/vote-parent', + ), + ).called(1); + + verify( + mockVoteProvider.setInitialVoteState( + postUri: 'reply-comment', + voteDirection: 'down', + voteUri: 'at://did:plc:test/social.coves.feed.vote/vote-reply', + ), + ).called(1); + }, + ); + + test('should initialize vote state for deeply nested replies', () async { + final response = CommentsResponse( + post: {}, + comments: [ + _createMockThreadCommentWithViewer( + uri: 'level-0', + vote: 'up', + voteUri: 'at://did:plc:test/social.coves.feed.vote/vote-0', + replies: [ + _createMockThreadCommentWithViewer( + uri: 'level-1', + vote: 'up', + voteUri: 'at://did:plc:test/social.coves.feed.vote/vote-1', + replies: [ + _createMockThreadCommentWithViewer( + uri: 'level-2', + vote: 'down', + voteUri: + 'at://did:plc:test/social.coves.feed.vote/vote-2', + ), + ], + ), + ], + ), + ], + ); + + when( + mockApiService.getComments( + postUri: anyNamed('postUri'), + sort: anyNamed('sort'), + timeframe: anyNamed('timeframe'), + depth: anyNamed('depth'), + limit: anyNamed('limit'), + cursor: anyNamed('cursor'), + ), + ).thenAnswer((_) async => response); + + await commentsProvider.loadComments( + postUri: testPostUri, + refresh: true, + ); + + // Should initialize vote state for all 3 levels + verify( + mockVoteProvider.setInitialVoteState( + postUri: anyNamed('postUri'), + voteDirection: anyNamed('voteDirection'), + voteUri: anyNamed('voteUri'), + ), + ).called(3); + }); + + test( + 'should only initialize vote state for new comments on pagination', + () async { + // First page: comment1 with upvote + final page1Response = CommentsResponse( + post: {}, + comments: [ + _createMockThreadCommentWithViewer( + uri: 'comment1', + vote: 'up', + voteUri: 'at://did:plc:test/social.coves.feed.vote/vote1', + ), + ], + cursor: 'cursor1', + ); + + // Second page: comment2 with downvote + final page2Response = CommentsResponse( + post: {}, + comments: [ + _createMockThreadCommentWithViewer( + uri: 'comment2', + vote: 'down', + voteUri: 'at://did:plc:test/social.coves.feed.vote/vote2', + ), + ], + ); + + // First call returns page 1 + when( + mockApiService.getComments( + postUri: anyNamed('postUri'), + sort: anyNamed('sort'), + timeframe: anyNamed('timeframe'), + depth: anyNamed('depth'), + limit: anyNamed('limit'), + cursor: null, + ), + ).thenAnswer((_) async => page1Response); + + // Second call (with cursor) returns page 2 + when( + mockApiService.getComments( + postUri: anyNamed('postUri'), + sort: anyNamed('sort'), + timeframe: anyNamed('timeframe'), + depth: anyNamed('depth'), + limit: anyNamed('limit'), + cursor: 'cursor1', + ), + ).thenAnswer((_) async => page2Response); + + // Load first page (refresh) + await commentsProvider.loadComments( + postUri: testPostUri, + refresh: true, + ); + + // Verify comment1 vote initialized + verify( + mockVoteProvider.setInitialVoteState( + postUri: 'comment1', + voteDirection: 'up', + voteUri: 'at://did:plc:test/social.coves.feed.vote/vote1', + ), + ).called(1); + + // Clear previous verifications + clearInteractions(mockVoteProvider); + + // Load second page (pagination, not refresh) + await commentsProvider.loadMoreComments(); + + // Should ONLY initialize vote state for comment2 (new comments) + // NOT re-initialize comment1 (which would wipe optimistic votes) + verify( + mockVoteProvider.setInitialVoteState( + postUri: 'comment2', + voteDirection: 'down', + voteUri: 'at://did:plc:test/social.coves.feed.vote/vote2', + ), + ).called(1); + + // Verify comment1 was NOT re-initialized during pagination + verifyNever( + mockVoteProvider.setInitialVoteState( + postUri: 'comment1', + voteDirection: anyNamed('voteDirection'), + voteUri: anyNamed('voteUri'), + ), + ); + }, + ); + }); }); } @@ -1065,3 +1275,33 @@ ThreadViewComment _createMockThreadComment(String uri) { ), ); } + +// Helper function to create mock comments with viewer state and optional replies +ThreadViewComment _createMockThreadCommentWithViewer({ + required String uri, + String? vote, + String? voteUri, + List? replies, +}) { + return ThreadViewComment( + comment: CommentView( + uri: uri, + cid: 'cid-$uri', + content: 'Test comment content', + createdAt: DateTime.parse('2025-01-01T12:00:00Z'), + indexedAt: DateTime.parse('2025-01-01T12:00:00Z'), + author: AuthorView( + did: 'did:plc:author', + handle: 'test.user', + displayName: 'Test User', + ), + post: CommentRef( + uri: 'at://did:plc:test/social.coves.post.record/123', + cid: 'post-cid', + ), + stats: CommentStats(score: 10, upvotes: 12, downvotes: 2), + viewer: CommentViewerState(vote: vote, voteUri: voteUri), + ), + replies: replies, + ); +} diff --git a/test/providers/comments_provider_test.mocks.dart b/test/providers/comments_provider_test.mocks.dart index 6d4cef3..55b5ef3 100644 --- a/test/providers/comments_provider_test.mocks.dart +++ b/test/providers/comments_provider_test.mocks.dart @@ -3,15 +3,14 @@ // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i6; -import 'dart:ui' as _i7; +import 'dart:async' as _i5; +import 'dart:ui' as _i6; import 'package:coves_flutter/models/comment.dart' as _i3; import 'package:coves_flutter/models/post.dart' as _i2; -import 'package:coves_flutter/providers/auth_provider.dart' as _i5; -import 'package:coves_flutter/providers/vote_provider.dart' as _i9; -import 'package:coves_flutter/services/coves_api_service.dart' as _i8; -import 'package:coves_flutter/services/vote_service.dart' as _i4; +import 'package:coves_flutter/providers/auth_provider.dart' as _i4; +import 'package:coves_flutter/providers/vote_provider.dart' as _i8; +import 'package:coves_flutter/services/coves_api_service.dart' as _i7; import 'package:mockito/mockito.dart' as _i1; // ignore_for_file: type=lint @@ -41,15 +40,10 @@ class _FakeCommentsResponse_1 extends _i1.SmartFake : super(parent, parentInvocation); } -class _FakeVoteResponse_2 extends _i1.SmartFake implements _i4.VoteResponse { - _FakeVoteResponse_2(Object parent, Invocation parentInvocation) - : super(parent, parentInvocation); -} - /// A class which mocks [AuthProvider]. /// /// See the documentation for Mockito's code generation for more information. -class MockAuthProvider extends _i1.Mock implements _i5.AuthProvider { +class MockAuthProvider extends _i1.Mock implements _i4.AuthProvider { MockAuthProvider() { _i1.throwOnMissingStub(this); } @@ -73,47 +67,47 @@ class MockAuthProvider extends _i1.Mock implements _i5.AuthProvider { as bool); @override - _i6.Future getAccessToken() => + _i5.Future getAccessToken() => (super.noSuchMethod( Invocation.method(#getAccessToken, []), - returnValue: _i6.Future.value(), + returnValue: _i5.Future.value(), ) - as _i6.Future); + as _i5.Future); @override - _i6.Future initialize() => + _i5.Future initialize() => (super.noSuchMethod( Invocation.method(#initialize, []), - returnValue: _i6.Future.value(), - returnValueForMissingStub: _i6.Future.value(), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), ) - as _i6.Future); + as _i5.Future); @override - _i6.Future signIn(String? handle) => + _i5.Future signIn(String? handle) => (super.noSuchMethod( Invocation.method(#signIn, [handle]), - returnValue: _i6.Future.value(), - returnValueForMissingStub: _i6.Future.value(), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), ) - as _i6.Future); + as _i5.Future); @override - _i6.Future signOut() => + _i5.Future signOut() => (super.noSuchMethod( Invocation.method(#signOut, []), - returnValue: _i6.Future.value(), - returnValueForMissingStub: _i6.Future.value(), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), ) - as _i6.Future); + as _i5.Future); @override - _i6.Future refreshToken() => + _i5.Future refreshToken() => (super.noSuchMethod( Invocation.method(#refreshToken, []), - returnValue: _i6.Future.value(false), + returnValue: _i5.Future.value(false), ) - as _i6.Future); + as _i5.Future); @override void clearError() => super.noSuchMethod( @@ -122,13 +116,13 @@ class MockAuthProvider extends _i1.Mock implements _i5.AuthProvider { ); @override - void addListener(_i7.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i6.VoidCallback? listener) => super.noSuchMethod( Invocation.method(#addListener, [listener]), returnValueForMissingStub: null, ); @override - void removeListener(_i7.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i6.VoidCallback? listener) => super.noSuchMethod( Invocation.method(#removeListener, [listener]), returnValueForMissingStub: null, ); @@ -149,13 +143,13 @@ class MockAuthProvider extends _i1.Mock implements _i5.AuthProvider { /// A class which mocks [CovesApiService]. /// /// See the documentation for Mockito's code generation for more information. -class MockCovesApiService extends _i1.Mock implements _i8.CovesApiService { +class MockCovesApiService extends _i1.Mock implements _i7.CovesApiService { MockCovesApiService() { _i1.throwOnMissingStub(this); } @override - _i6.Future<_i2.TimelineResponse> getTimeline({ + _i5.Future<_i2.TimelineResponse> getTimeline({ String? sort = 'hot', String? timeframe, int? limit = 15, @@ -168,7 +162,7 @@ class MockCovesApiService extends _i1.Mock implements _i8.CovesApiService { #limit: limit, #cursor: cursor, }), - returnValue: _i6.Future<_i2.TimelineResponse>.value( + returnValue: _i5.Future<_i2.TimelineResponse>.value( _FakeTimelineResponse_0( this, Invocation.method(#getTimeline, [], { @@ -180,10 +174,10 @@ class MockCovesApiService extends _i1.Mock implements _i8.CovesApiService { ), ), ) - as _i6.Future<_i2.TimelineResponse>); + as _i5.Future<_i2.TimelineResponse>); @override - _i6.Future<_i2.TimelineResponse> getDiscover({ + _i5.Future<_i2.TimelineResponse> getDiscover({ String? sort = 'hot', String? timeframe, int? limit = 15, @@ -196,7 +190,7 @@ class MockCovesApiService extends _i1.Mock implements _i8.CovesApiService { #limit: limit, #cursor: cursor, }), - returnValue: _i6.Future<_i2.TimelineResponse>.value( + returnValue: _i5.Future<_i2.TimelineResponse>.value( _FakeTimelineResponse_0( this, Invocation.method(#getDiscover, [], { @@ -208,10 +202,10 @@ class MockCovesApiService extends _i1.Mock implements _i8.CovesApiService { ), ), ) - as _i6.Future<_i2.TimelineResponse>); + as _i5.Future<_i2.TimelineResponse>); @override - _i6.Future<_i3.CommentsResponse> getComments({ + _i5.Future<_i3.CommentsResponse> getComments({ required String? postUri, String? sort = 'hot', String? timeframe, @@ -228,7 +222,7 @@ class MockCovesApiService extends _i1.Mock implements _i8.CovesApiService { #limit: limit, #cursor: cursor, }), - returnValue: _i6.Future<_i3.CommentsResponse>.value( + returnValue: _i5.Future<_i3.CommentsResponse>.value( _FakeCommentsResponse_1( this, Invocation.method(#getComments, [], { @@ -242,7 +236,7 @@ class MockCovesApiService extends _i1.Mock implements _i8.CovesApiService { ), ), ) - as _i6.Future<_i3.CommentsResponse>); + as _i5.Future<_i3.CommentsResponse>); @override void dispose() => super.noSuchMethod( @@ -254,7 +248,7 @@ class MockCovesApiService extends _i1.Mock implements _i8.CovesApiService { /// A class which mocks [VoteProvider]. /// /// See the documentation for Mockito's code generation for more information. -class MockVoteProvider extends _i1.Mock implements _i9.VoteProvider { +class MockVoteProvider extends _i1.Mock implements _i8.VoteProvider { MockVoteProvider() { _i1.throwOnMissingStub(this); } @@ -271,9 +265,9 @@ class MockVoteProvider extends _i1.Mock implements _i9.VoteProvider { ); @override - _i9.VoteState? getVoteState(String? postUri) => + _i8.VoteState? getVoteState(String? postUri) => (super.noSuchMethod(Invocation.method(#getVoteState, [postUri])) - as _i9.VoteState?); + as _i8.VoteState?); @override bool isLiked(String? postUri) => @@ -300,7 +294,7 @@ class MockVoteProvider extends _i1.Mock implements _i9.VoteProvider { as int); @override - _i6.Future toggleVote({ + _i5.Future toggleVote({ required String? postUri, required String? postCid, String? direction = 'up', @@ -311,9 +305,9 @@ class MockVoteProvider extends _i1.Mock implements _i9.VoteProvider { #postCid: postCid, #direction: direction, }), - returnValue: _i6.Future.value(false), + returnValue: _i5.Future.value(false), ) - as _i6.Future); + as _i5.Future); @override void setInitialVoteState({ @@ -329,12 +323,6 @@ class MockVoteProvider extends _i1.Mock implements _i9.VoteProvider { returnValueForMissingStub: null, ); - @override - void loadInitialVotes(Map? votes) => super.noSuchMethod( - Invocation.method(#loadInitialVotes, [votes]), - returnValueForMissingStub: null, - ); - @override void clear() => super.noSuchMethod( Invocation.method(#clear, []), @@ -342,13 +330,13 @@ class MockVoteProvider extends _i1.Mock implements _i9.VoteProvider { ); @override - void addListener(_i7.VoidCallback? listener) => super.noSuchMethod( + void addListener(_i6.VoidCallback? listener) => super.noSuchMethod( Invocation.method(#addListener, [listener]), returnValueForMissingStub: null, ); @override - void removeListener(_i7.VoidCallback? listener) => super.noSuchMethod( + void removeListener(_i6.VoidCallback? listener) => super.noSuchMethod( Invocation.method(#removeListener, [listener]), returnValueForMissingStub: null, ); @@ -359,53 +347,3 @@ class MockVoteProvider extends _i1.Mock implements _i9.VoteProvider { returnValueForMissingStub: null, ); } - -/// A class which mocks [VoteService]. -/// -/// See the documentation for Mockito's code generation for more information. -class MockVoteService extends _i1.Mock implements _i4.VoteService { - MockVoteService() { - _i1.throwOnMissingStub(this); - } - - @override - _i6.Future> getUserVotes() => - (super.noSuchMethod( - Invocation.method(#getUserVotes, []), - returnValue: _i6.Future>.value( - {}, - ), - ) - as _i6.Future>); - - @override - _i6.Future<_i4.VoteResponse> createVote({ - required String? postUri, - required String? postCid, - String? direction = 'up', - String? existingVoteRkey, - String? existingVoteDirection, - }) => - (super.noSuchMethod( - Invocation.method(#createVote, [], { - #postUri: postUri, - #postCid: postCid, - #direction: direction, - #existingVoteRkey: existingVoteRkey, - #existingVoteDirection: existingVoteDirection, - }), - returnValue: _i6.Future<_i4.VoteResponse>.value( - _FakeVoteResponse_2( - this, - Invocation.method(#createVote, [], { - #postUri: postUri, - #postCid: postCid, - #direction: direction, - #existingVoteRkey: existingVoteRkey, - #existingVoteDirection: existingVoteDirection, - }), - ), - ), - ) - as _i6.Future<_i4.VoteResponse>); -} diff --git a/test/providers/feed_provider_test.dart b/test/providers/feed_provider_test.dart index bec8b94..12350a8 100644 --- a/test/providers/feed_provider_test.dart +++ b/test/providers/feed_provider_test.dart @@ -1,6 +1,7 @@ import 'package:coves_flutter/models/post.dart'; import 'package:coves_flutter/providers/auth_provider.dart'; import 'package:coves_flutter/providers/feed_provider.dart'; +import 'package:coves_flutter/providers/vote_provider.dart'; import 'package:coves_flutter/services/coves_api_service.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/annotations.dart'; @@ -9,7 +10,7 @@ import 'package:mockito/mockito.dart'; import 'feed_provider_test.mocks.dart'; // Generate mocks -@GenerateMocks([AuthProvider, CovesApiService]) +@GenerateMocks([AuthProvider, CovesApiService, VoteProvider]) void main() { group('FeedProvider', () { late FeedProvider feedProvider; @@ -435,6 +436,205 @@ void main() { expect(feedProvider.isLoading, false); }); }); + + group('Vote state initialization from viewer data', () { + late MockVoteProvider mockVoteProvider; + late FeedProvider feedProviderWithVotes; + + setUp(() { + mockVoteProvider = MockVoteProvider(); + feedProviderWithVotes = FeedProvider( + mockAuthProvider, + apiService: mockApiService, + voteProvider: mockVoteProvider, + ); + }); + + tearDown(() { + feedProviderWithVotes.dispose(); + }); + + test('should initialize vote state when viewer.vote is "up"', () async { + when(mockAuthProvider.isAuthenticated).thenReturn(true); + + final mockResponse = TimelineResponse( + feed: [ + _createMockPostWithViewer( + uri: 'at://did:plc:test/social.coves.post.record/1', + vote: 'up', + voteUri: 'at://did:plc:test/social.coves.feed.vote/vote1', + ), + ], + cursor: 'cursor', + ); + + when( + mockApiService.getTimeline( + sort: anyNamed('sort'), + timeframe: anyNamed('timeframe'), + limit: anyNamed('limit'), + cursor: anyNamed('cursor'), + ), + ).thenAnswer((_) async => mockResponse); + + await feedProviderWithVotes.fetchTimeline(refresh: true); + + verify( + mockVoteProvider.setInitialVoteState( + postUri: 'at://did:plc:test/social.coves.post.record/1', + voteDirection: 'up', + voteUri: 'at://did:plc:test/social.coves.feed.vote/vote1', + ), + ).called(1); + }); + + test('should initialize vote state when viewer.vote is "down"', () async { + when(mockAuthProvider.isAuthenticated).thenReturn(true); + + final mockResponse = TimelineResponse( + feed: [ + _createMockPostWithViewer( + uri: 'at://did:plc:test/social.coves.post.record/1', + vote: 'down', + voteUri: 'at://did:plc:test/social.coves.feed.vote/vote1', + ), + ], + cursor: 'cursor', + ); + + when( + mockApiService.getTimeline( + sort: anyNamed('sort'), + timeframe: anyNamed('timeframe'), + limit: anyNamed('limit'), + cursor: anyNamed('cursor'), + ), + ).thenAnswer((_) async => mockResponse); + + await feedProviderWithVotes.fetchTimeline(refresh: true); + + verify( + mockVoteProvider.setInitialVoteState( + postUri: 'at://did:plc:test/social.coves.post.record/1', + voteDirection: 'down', + voteUri: 'at://did:plc:test/social.coves.feed.vote/vote1', + ), + ).called(1); + }); + + test( + 'should clear stale vote state when viewer.vote is null on refresh', + () async { + when(mockAuthProvider.isAuthenticated).thenReturn(true); + + // Feed item with null vote (user removed vote on another device) + final mockResponse = TimelineResponse( + feed: [ + _createMockPostWithViewer( + uri: 'at://did:plc:test/social.coves.post.record/1', + vote: null, + voteUri: null, + ), + ], + cursor: 'cursor', + ); + + when( + mockApiService.getTimeline( + sort: anyNamed('sort'), + timeframe: anyNamed('timeframe'), + limit: anyNamed('limit'), + cursor: anyNamed('cursor'), + ), + ).thenAnswer((_) async => mockResponse); + + await feedProviderWithVotes.fetchTimeline(refresh: true); + + // Should call setInitialVoteState with null to clear stale state + verify( + mockVoteProvider.setInitialVoteState( + postUri: 'at://did:plc:test/social.coves.post.record/1', + voteDirection: null, + voteUri: null, + ), + ).called(1); + }, + ); + + test( + 'should initialize vote state for all feed items including no viewer', + () async { + when(mockAuthProvider.isAuthenticated).thenReturn(true); + + final mockResponse = TimelineResponse( + feed: [ + _createMockPostWithViewer( + uri: 'at://did:plc:test/social.coves.post.record/1', + vote: 'up', + voteUri: 'at://did:plc:test/social.coves.feed.vote/vote1', + ), + _createMockPost(), // No viewer state + ], + cursor: 'cursor', + ); + + when( + mockApiService.getTimeline( + sort: anyNamed('sort'), + timeframe: anyNamed('timeframe'), + limit: anyNamed('limit'), + cursor: anyNamed('cursor'), + ), + ).thenAnswer((_) async => mockResponse); + + await feedProviderWithVotes.fetchTimeline(refresh: true); + + // Should be called for both posts + verify( + mockVoteProvider.setInitialVoteState( + postUri: anyNamed('postUri'), + voteDirection: anyNamed('voteDirection'), + voteUri: anyNamed('voteUri'), + ), + ).called(2); + }, + ); + + test('should not initialize vote state when not authenticated', () async { + when(mockAuthProvider.isAuthenticated).thenReturn(false); + + final mockResponse = TimelineResponse( + feed: [ + _createMockPostWithViewer( + uri: 'at://did:plc:test/social.coves.post.record/1', + vote: 'up', + voteUri: 'at://did:plc:test/social.coves.feed.vote/vote1', + ), + ], + cursor: 'cursor', + ); + + when( + mockApiService.getDiscover( + sort: anyNamed('sort'), + timeframe: anyNamed('timeframe'), + limit: anyNamed('limit'), + cursor: anyNamed('cursor'), + ), + ).thenAnswer((_) async => mockResponse); + + await feedProviderWithVotes.fetchDiscover(refresh: true); + + // Should NOT call setInitialVoteState when not authenticated + verifyNever( + mockVoteProvider.setInitialVoteState( + postUri: anyNamed('postUri'), + voteDirection: anyNamed('voteDirection'), + voteUri: anyNamed('voteUri'), + ), + ); + }); + }); }); } @@ -460,3 +660,31 @@ FeedViewPost _createMockPost() { ), ); } + +// Helper function to create mock posts with viewer state +FeedViewPost _createMockPostWithViewer({ + required String uri, + String? vote, + String? voteUri, +}) { + return FeedViewPost( + post: PostView( + uri: uri, + cid: 'test-cid', + rkey: 'test-rkey', + author: AuthorView( + did: 'did:plc:author', + handle: 'test.user', + displayName: 'Test User', + ), + community: CommunityRef(did: 'did:plc:community', name: 'test-community'), + createdAt: DateTime.parse('2025-01-01T12:00:00Z'), + indexedAt: DateTime.parse('2025-01-01T12:00:00Z'), + text: 'Test body', + title: 'Test Post', + stats: PostStats(score: 42, upvotes: 50, downvotes: 8, commentCount: 5), + facets: [], + viewer: ViewerState(vote: vote, voteUri: voteUri), + ), + ); +} diff --git a/test/providers/feed_provider_test.mocks.dart b/test/providers/feed_provider_test.mocks.dart index 40bd76e..cba6ee9 100644 --- a/test/providers/feed_provider_test.mocks.dart +++ b/test/providers/feed_provider_test.mocks.dart @@ -9,6 +9,7 @@ import 'dart:ui' as _i6; import 'package:coves_flutter/models/comment.dart' as _i3; import 'package:coves_flutter/models/post.dart' as _i2; import 'package:coves_flutter/providers/auth_provider.dart' as _i4; +import 'package:coves_flutter/providers/vote_provider.dart' as _i8; import 'package:coves_flutter/services/coves_api_service.dart' as _i7; import 'package:mockito/mockito.dart' as _i1; @@ -243,3 +244,106 @@ class MockCovesApiService extends _i1.Mock implements _i7.CovesApiService { returnValueForMissingStub: null, ); } + +/// A class which mocks [VoteProvider]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockVoteProvider extends _i1.Mock implements _i8.VoteProvider { + MockVoteProvider() { + _i1.throwOnMissingStub(this); + } + + @override + bool get hasListeners => + (super.noSuchMethod(Invocation.getter(#hasListeners), returnValue: false) + as bool); + + @override + void dispose() => super.noSuchMethod( + Invocation.method(#dispose, []), + returnValueForMissingStub: null, + ); + + @override + _i8.VoteState? getVoteState(String? postUri) => + (super.noSuchMethod(Invocation.method(#getVoteState, [postUri])) + as _i8.VoteState?); + + @override + bool isLiked(String? postUri) => + (super.noSuchMethod( + Invocation.method(#isLiked, [postUri]), + returnValue: false, + ) + as bool); + + @override + bool isPending(String? postUri) => + (super.noSuchMethod( + Invocation.method(#isPending, [postUri]), + returnValue: false, + ) + as bool); + + @override + int getAdjustedScore(String? postUri, int? serverScore) => + (super.noSuchMethod( + Invocation.method(#getAdjustedScore, [postUri, serverScore]), + returnValue: 0, + ) + as int); + + @override + _i5.Future toggleVote({ + required String? postUri, + required String? postCid, + String? direction = 'up', + }) => + (super.noSuchMethod( + Invocation.method(#toggleVote, [], { + #postUri: postUri, + #postCid: postCid, + #direction: direction, + }), + returnValue: _i5.Future.value(false), + ) + as _i5.Future); + + @override + void setInitialVoteState({ + required String? postUri, + String? voteDirection, + String? voteUri, + }) => super.noSuchMethod( + Invocation.method(#setInitialVoteState, [], { + #postUri: postUri, + #voteDirection: voteDirection, + #voteUri: voteUri, + }), + returnValueForMissingStub: null, + ); + + @override + void clear() => super.noSuchMethod( + Invocation.method(#clear, []), + returnValueForMissingStub: null, + ); + + @override + void addListener(_i6.VoidCallback? listener) => super.noSuchMethod( + Invocation.method(#addListener, [listener]), + returnValueForMissingStub: null, + ); + + @override + void removeListener(_i6.VoidCallback? listener) => super.noSuchMethod( + Invocation.method(#removeListener, [listener]), + returnValueForMissingStub: null, + ); + + @override + void notifyListeners() => super.noSuchMethod( + Invocation.method(#notifyListeners, []), + returnValueForMissingStub: null, + ); +} diff --git a/test/providers/vote_provider_test.dart b/test/providers/vote_provider_test.dart index b9d3863..acd74de 100644 --- a/test/providers/vote_provider_test.dart +++ b/test/providers/vote_provider_test.dart @@ -46,8 +46,6 @@ void main() { postUri: anyNamed('postUri'), postCid: anyNamed('postCid'), direction: anyNamed('direction'), - existingVoteRkey: anyNamed('existingVoteRkey'), - existingVoteDirection: anyNamed('existingVoteDirection'), ), ).thenAnswer( (_) async => const VoteResponse( @@ -104,8 +102,6 @@ void main() { postUri: anyNamed('postUri'), postCid: anyNamed('postCid'), direction: anyNamed('direction'), - existingVoteRkey: anyNamed('existingVoteRkey'), - existingVoteDirection: anyNamed('existingVoteDirection'), ), ).thenAnswer((_) async => const VoteResponse(deleted: true)); @@ -136,8 +132,6 @@ void main() { postUri: anyNamed('postUri'), postCid: anyNamed('postCid'), direction: anyNamed('direction'), - existingVoteRkey: anyNamed('existingVoteRkey'), - existingVoteDirection: anyNamed('existingVoteDirection'), ), ).thenThrow(ApiException('Network error', statusCode: 500)); @@ -181,8 +175,6 @@ void main() { postUri: anyNamed('postUri'), postCid: anyNamed('postCid'), direction: anyNamed('direction'), - existingVoteRkey: anyNamed('existingVoteRkey'), - existingVoteDirection: anyNamed('existingVoteDirection'), ), ).thenThrow(NetworkException('Connection failed')); @@ -208,8 +200,6 @@ void main() { postUri: anyNamed('postUri'), postCid: anyNamed('postCid'), direction: anyNamed('direction'), - existingVoteRkey: anyNamed('existingVoteRkey'), - existingVoteDirection: anyNamed('existingVoteDirection'), ), ).thenAnswer((_) async { await Future.delayed(const Duration(milliseconds: 100)); @@ -246,8 +236,6 @@ void main() { postUri: anyNamed('postUri'), postCid: anyNamed('postCid'), direction: anyNamed('direction'), - existingVoteRkey: anyNamed('existingVoteRkey'), - existingVoteDirection: anyNamed('existingVoteDirection'), ), ).called(1); }); @@ -258,8 +246,6 @@ void main() { postUri: anyNamed('postUri'), postCid: anyNamed('postCid'), direction: anyNamed('direction'), - existingVoteRkey: anyNamed('existingVoteRkey'), - existingVoteDirection: anyNamed('existingVoteDirection'), ), ).thenAnswer( (_) async => const VoteResponse( @@ -303,6 +289,46 @@ void main() { expect(voteState?.deleted, false); }); + test('should set initial vote state with "down" direction', () { + voteProvider.setInitialVoteState( + postUri: testPostUri, + voteDirection: 'down', + voteUri: 'at://did:plc:test/social.coves.feed.vote/456', + ); + + // Should not be "liked" (isLiked checks for 'up' direction) + expect(voteProvider.isLiked(testPostUri), false); + + final voteState = voteProvider.getVoteState(testPostUri); + expect(voteState?.direction, 'down'); + expect(voteState?.uri, 'at://did:plc:test/social.coves.feed.vote/456'); + expect(voteState?.deleted, false); + }); + + test('should extract rkey from voteUri', () { + voteProvider.setInitialVoteState( + postUri: testPostUri, + voteDirection: 'up', + voteUri: 'at://did:plc:test/social.coves.feed.vote/3kbyxyz123', + ); + + final voteState = voteProvider.getVoteState(testPostUri); + expect(voteState?.rkey, '3kbyxyz123'); + }); + + test('should handle voteUri being null', () { + voteProvider.setInitialVoteState( + postUri: testPostUri, + voteDirection: 'up', + ); + + final voteState = voteProvider.getVoteState(testPostUri); + expect(voteState?.direction, 'up'); + expect(voteState?.uri, null); + expect(voteState?.rkey, null); + expect(voteState?.deleted, false); + }); + test('should remove vote state when voteDirection is null', () { // First set a vote voteProvider.setInitialVoteState( @@ -320,6 +346,72 @@ void main() { expect(voteProvider.getVoteState(testPostUri), null); }); + test('should clear stale vote state when refreshing with null vote', () { + // Simulate initial state from previous session + voteProvider.setInitialVoteState( + postUri: testPostUri, + voteDirection: 'up', + voteUri: 'at://did:plc:test/social.coves.feed.vote/456', + ); + + expect(voteProvider.isLiked(testPostUri), true); + + // Simulate refresh where server returns viewer.vote = null + // (user removed vote on another device) + voteProvider.setInitialVoteState( + postUri: testPostUri, + voteDirection: null, + ); + + // Vote should be cleared + expect(voteProvider.isLiked(testPostUri), false); + expect(voteProvider.getVoteState(testPostUri), null); + }); + + test('should clear stale score adjustment on refresh', () async { + // Simulate optimistic upvote that created a +1 adjustment + when( + mockVoteService.createVote( + postUri: anyNamed('postUri'), + postCid: anyNamed('postCid'), + direction: anyNamed('direction'), + ), + ).thenAnswer( + (_) async => const VoteResponse( + uri: 'at://did:plc:test/social.coves.feed.vote/456', + cid: 'bafy123', + rkey: '456', + deleted: false, + ), + ); + + // Create vote - this sets _scoreAdjustments[testPostUri] = +1 + await voteProvider.toggleVote( + postUri: testPostUri, + postCid: 'bafy2bzacepostcid123', + ); + + // Verify adjustment exists + const serverScore = 10; + expect(voteProvider.getAdjustedScore(testPostUri, serverScore), 11); + + // Now simulate a feed refresh - server returns fresh score (11) + // which already includes the vote. The adjustment should be cleared. + voteProvider.setInitialVoteState( + postUri: testPostUri, + voteDirection: 'up', + voteUri: 'at://did:plc:test/social.coves.feed.vote/456', + ); + + // After refresh, adjustment should be cleared (server score is truth) + // If we pass the NEW server score (11), we should get 11, not 12 + const freshServerScore = 11; + expect( + voteProvider.getAdjustedScore(testPostUri, freshServerScore), + 11, + ); + }); + test('should not notify listeners when setting initial state', () { var notificationCount = 0; voteProvider @@ -337,6 +429,34 @@ void main() { }); }); + group('VoteState.extractRkeyFromUri', () { + test('should extract rkey from valid AT-URI', () { + expect( + VoteState.extractRkeyFromUri( + 'at://did:plc:test/social.coves.feed.vote/3kbyxyz123', + ), + '3kbyxyz123', + ); + }); + + test('should return null for null uri', () { + expect(VoteState.extractRkeyFromUri(null), null); + }); + + test('should handle URI with no path segments', () { + expect(VoteState.extractRkeyFromUri(''), ''); + }); + + test('should handle complex rkey values', () { + expect( + VoteState.extractRkeyFromUri( + 'at://did:plc:abc123xyz/social.coves.feed.vote/3lbp7kw2abc', + ), + '3lbp7kw2abc', + ); + }); + }); + group('clear', () { test('should clear all vote state', () { const post1 = 'at://did:plc:test/social.coves.post.record/1'; @@ -391,8 +511,6 @@ void main() { postUri: anyNamed('postUri'), postCid: anyNamed('postCid'), direction: anyNamed('direction'), - existingVoteRkey: anyNamed('existingVoteRkey'), - existingVoteDirection: anyNamed('existingVoteDirection'), ), ).thenAnswer((_) async { await Future.delayed(const Duration(milliseconds: 50)); @@ -441,8 +559,6 @@ void main() { postUri: anyNamed('postUri'), postCid: anyNamed('postCid'), direction: anyNamed('direction'), - existingVoteRkey: anyNamed('existingVoteRkey'), - existingVoteDirection: anyNamed('existingVoteDirection'), ), ).thenAnswer( (_) async => const VoteResponse( @@ -482,8 +598,6 @@ void main() { postUri: anyNamed('postUri'), postCid: anyNamed('postCid'), direction: anyNamed('direction'), - existingVoteRkey: anyNamed('existingVoteRkey'), - existingVoteDirection: anyNamed('existingVoteDirection'), ), ).thenAnswer((_) async => const VoteResponse(deleted: true)); @@ -508,8 +622,6 @@ void main() { postUri: anyNamed('postUri'), postCid: anyNamed('postCid'), direction: anyNamed('direction'), - existingVoteRkey: anyNamed('existingVoteRkey'), - existingVoteDirection: anyNamed('existingVoteDirection'), ), ).thenAnswer( (_) async => const VoteResponse( @@ -548,8 +660,6 @@ void main() { postUri: anyNamed('postUri'), postCid: anyNamed('postCid'), direction: anyNamed('direction'), - existingVoteRkey: anyNamed('existingVoteRkey'), - existingVoteDirection: anyNamed('existingVoteDirection'), ), ).thenAnswer( (_) async => const VoteResponse( @@ -589,8 +699,6 @@ void main() { postUri: anyNamed('postUri'), postCid: anyNamed('postCid'), direction: anyNamed('direction'), - existingVoteRkey: anyNamed('existingVoteRkey'), - existingVoteDirection: anyNamed('existingVoteDirection'), ), ).thenAnswer( (_) async => const VoteResponse( @@ -622,8 +730,6 @@ void main() { postUri: anyNamed('postUri'), postCid: anyNamed('postCid'), direction: anyNamed('direction'), - existingVoteRkey: anyNamed('existingVoteRkey'), - existingVoteDirection: anyNamed('existingVoteDirection'), ), ).thenThrow(ApiException('Network error', statusCode: 500)); diff --git a/test/providers/vote_provider_test.mocks.dart b/test/providers/vote_provider_test.mocks.dart index 87770f9..bef0656 100644 --- a/test/providers/vote_provider_test.mocks.dart +++ b/test/providers/vote_provider_test.mocks.dart @@ -38,31 +38,17 @@ class MockVoteService extends _i1.Mock implements _i2.VoteService { _i1.throwOnMissingStub(this); } - @override - _i3.Future> getUserVotes() => - (super.noSuchMethod( - Invocation.method(#getUserVotes, []), - returnValue: _i3.Future>.value( - {}, - ), - ) - as _i3.Future>); - @override _i3.Future<_i2.VoteResponse> createVote({ required String? postUri, required String? postCid, String? direction = 'up', - String? existingVoteRkey, - String? existingVoteDirection, }) => (super.noSuchMethod( Invocation.method(#createVote, [], { #postUri: postUri, #postCid: postCid, #direction: direction, - #existingVoteRkey: existingVoteRkey, - #existingVoteDirection: existingVoteDirection, }), returnValue: _i3.Future<_i2.VoteResponse>.value( _FakeVoteResponse_0( @@ -71,8 +57,6 @@ class MockVoteService extends _i1.Mock implements _i2.VoteService { #postUri: postUri, #postCid: postCid, #direction: direction, - #existingVoteRkey: existingVoteRkey, - #existingVoteDirection: existingVoteDirection, }), ), ), diff --git a/test/services/coves_auth_service_environment_test.mocks.dart b/test/services/coves_auth_service_environment_test.mocks.dart new file mode 100644 index 0000000..3c007c1 --- /dev/null +++ b/test/services/coves_auth_service_environment_test.mocks.dart @@ -0,0 +1,1102 @@ +// Mocks generated by Mockito 5.4.6 from annotations +// in coves_flutter/test/services/coves_auth_service_environment_test.dart. +// Do not manually edit this file. + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'dart:async' as _i9; + +import 'package:dio/src/adapter.dart' as _i4; +import 'package:dio/src/cancel_token.dart' as _i10; +import 'package:dio/src/dio.dart' as _i7; +import 'package:dio/src/dio_mixin.dart' as _i3; +import 'package:dio/src/options.dart' as _i2; +import 'package:dio/src/response.dart' as _i6; +import 'package:dio/src/transformer.dart' as _i5; +import 'package:flutter/foundation.dart' as _i11; +import 'package:flutter_secure_storage/flutter_secure_storage.dart' as _i8; +import 'package:mockito/mockito.dart' as _i1; + +// ignore_for_file: type=lint +// ignore_for_file: avoid_redundant_argument_values +// ignore_for_file: avoid_setters_without_getters +// ignore_for_file: comment_references +// ignore_for_file: deprecated_member_use +// ignore_for_file: deprecated_member_use_from_same_package +// ignore_for_file: implementation_imports +// ignore_for_file: invalid_use_of_visible_for_testing_member +// ignore_for_file: must_be_immutable +// ignore_for_file: prefer_const_constructors +// ignore_for_file: unnecessary_parenthesis +// ignore_for_file: camel_case_types +// ignore_for_file: subtype_of_sealed_class +// ignore_for_file: invalid_use_of_internal_member + +class _FakeBaseOptions_0 extends _i1.SmartFake implements _i2.BaseOptions { + _FakeBaseOptions_0(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeInterceptors_1 extends _i1.SmartFake implements _i3.Interceptors { + _FakeInterceptors_1(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeHttpClientAdapter_2 extends _i1.SmartFake + implements _i4.HttpClientAdapter { + _FakeHttpClientAdapter_2(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeTransformer_3 extends _i1.SmartFake implements _i5.Transformer { + _FakeTransformer_3(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeResponse_4 extends _i1.SmartFake implements _i6.Response { + _FakeResponse_4(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeDio_5 extends _i1.SmartFake implements _i7.Dio { + _FakeDio_5(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeIOSOptions_6 extends _i1.SmartFake implements _i8.IOSOptions { + _FakeIOSOptions_6(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeAndroidOptions_7 extends _i1.SmartFake + implements _i8.AndroidOptions { + _FakeAndroidOptions_7(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeLinuxOptions_8 extends _i1.SmartFake implements _i8.LinuxOptions { + _FakeLinuxOptions_8(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeWindowsOptions_9 extends _i1.SmartFake + implements _i8.WindowsOptions { + _FakeWindowsOptions_9(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeWebOptions_10 extends _i1.SmartFake implements _i8.WebOptions { + _FakeWebOptions_10(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeMacOsOptions_11 extends _i1.SmartFake implements _i8.MacOsOptions { + _FakeMacOsOptions_11(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +/// A class which mocks [Dio]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockDio extends _i1.Mock implements _i7.Dio { + MockDio() { + _i1.throwOnMissingStub(this); + } + + @override + _i2.BaseOptions get options => + (super.noSuchMethod( + Invocation.getter(#options), + returnValue: _FakeBaseOptions_0(this, Invocation.getter(#options)), + ) + as _i2.BaseOptions); + + @override + _i3.Interceptors get interceptors => + (super.noSuchMethod( + Invocation.getter(#interceptors), + returnValue: _FakeInterceptors_1( + this, + Invocation.getter(#interceptors), + ), + ) + as _i3.Interceptors); + + @override + _i4.HttpClientAdapter get httpClientAdapter => + (super.noSuchMethod( + Invocation.getter(#httpClientAdapter), + returnValue: _FakeHttpClientAdapter_2( + this, + Invocation.getter(#httpClientAdapter), + ), + ) + as _i4.HttpClientAdapter); + + @override + _i5.Transformer get transformer => + (super.noSuchMethod( + Invocation.getter(#transformer), + returnValue: _FakeTransformer_3( + this, + Invocation.getter(#transformer), + ), + ) + as _i5.Transformer); + + @override + set options(_i2.BaseOptions? value) => super.noSuchMethod( + Invocation.setter(#options, value), + returnValueForMissingStub: null, + ); + + @override + set httpClientAdapter(_i4.HttpClientAdapter? value) => super.noSuchMethod( + Invocation.setter(#httpClientAdapter, value), + returnValueForMissingStub: null, + ); + + @override + set transformer(_i5.Transformer? value) => super.noSuchMethod( + Invocation.setter(#transformer, value), + returnValueForMissingStub: null, + ); + + @override + void close({bool? force = false}) => super.noSuchMethod( + Invocation.method(#close, [], {#force: force}), + returnValueForMissingStub: null, + ); + + @override + _i9.Future<_i6.Response> head( + String? path, { + Object? data, + Map? queryParameters, + _i2.Options? options, + _i10.CancelToken? cancelToken, + }) => + (super.noSuchMethod( + Invocation.method( + #head, + [path], + { + #data: data, + #queryParameters: queryParameters, + #options: options, + #cancelToken: cancelToken, + }, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #head, + [path], + { + #data: data, + #queryParameters: queryParameters, + #options: options, + #cancelToken: cancelToken, + }, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> headUri( + Uri? uri, { + Object? data, + _i2.Options? options, + _i10.CancelToken? cancelToken, + }) => + (super.noSuchMethod( + Invocation.method( + #headUri, + [uri], + {#data: data, #options: options, #cancelToken: cancelToken}, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #headUri, + [uri], + {#data: data, #options: options, #cancelToken: cancelToken}, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> get( + String? path, { + Object? data, + Map? queryParameters, + _i2.Options? options, + _i10.CancelToken? cancelToken, + _i2.ProgressCallback? onReceiveProgress, + }) => + (super.noSuchMethod( + Invocation.method( + #get, + [path], + { + #data: data, + #queryParameters: queryParameters, + #options: options, + #cancelToken: cancelToken, + #onReceiveProgress: onReceiveProgress, + }, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #get, + [path], + { + #data: data, + #queryParameters: queryParameters, + #options: options, + #cancelToken: cancelToken, + #onReceiveProgress: onReceiveProgress, + }, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> getUri( + Uri? uri, { + Object? data, + _i2.Options? options, + _i10.CancelToken? cancelToken, + _i2.ProgressCallback? onReceiveProgress, + }) => + (super.noSuchMethod( + Invocation.method( + #getUri, + [uri], + { + #data: data, + #options: options, + #cancelToken: cancelToken, + #onReceiveProgress: onReceiveProgress, + }, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #getUri, + [uri], + { + #data: data, + #options: options, + #cancelToken: cancelToken, + #onReceiveProgress: onReceiveProgress, + }, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> post( + String? path, { + Object? data, + Map? queryParameters, + _i2.Options? options, + _i10.CancelToken? cancelToken, + _i2.ProgressCallback? onSendProgress, + _i2.ProgressCallback? onReceiveProgress, + }) => + (super.noSuchMethod( + Invocation.method( + #post, + [path], + { + #data: data, + #queryParameters: queryParameters, + #options: options, + #cancelToken: cancelToken, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #post, + [path], + { + #data: data, + #queryParameters: queryParameters, + #options: options, + #cancelToken: cancelToken, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> postUri( + Uri? uri, { + Object? data, + _i2.Options? options, + _i10.CancelToken? cancelToken, + _i2.ProgressCallback? onSendProgress, + _i2.ProgressCallback? onReceiveProgress, + }) => + (super.noSuchMethod( + Invocation.method( + #postUri, + [uri], + { + #data: data, + #options: options, + #cancelToken: cancelToken, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #postUri, + [uri], + { + #data: data, + #options: options, + #cancelToken: cancelToken, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> put( + String? path, { + Object? data, + Map? queryParameters, + _i2.Options? options, + _i10.CancelToken? cancelToken, + _i2.ProgressCallback? onSendProgress, + _i2.ProgressCallback? onReceiveProgress, + }) => + (super.noSuchMethod( + Invocation.method( + #put, + [path], + { + #data: data, + #queryParameters: queryParameters, + #options: options, + #cancelToken: cancelToken, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #put, + [path], + { + #data: data, + #queryParameters: queryParameters, + #options: options, + #cancelToken: cancelToken, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> putUri( + Uri? uri, { + Object? data, + _i2.Options? options, + _i10.CancelToken? cancelToken, + _i2.ProgressCallback? onSendProgress, + _i2.ProgressCallback? onReceiveProgress, + }) => + (super.noSuchMethod( + Invocation.method( + #putUri, + [uri], + { + #data: data, + #options: options, + #cancelToken: cancelToken, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #putUri, + [uri], + { + #data: data, + #options: options, + #cancelToken: cancelToken, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> patch( + String? path, { + Object? data, + Map? queryParameters, + _i2.Options? options, + _i10.CancelToken? cancelToken, + _i2.ProgressCallback? onSendProgress, + _i2.ProgressCallback? onReceiveProgress, + }) => + (super.noSuchMethod( + Invocation.method( + #patch, + [path], + { + #data: data, + #queryParameters: queryParameters, + #options: options, + #cancelToken: cancelToken, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #patch, + [path], + { + #data: data, + #queryParameters: queryParameters, + #options: options, + #cancelToken: cancelToken, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> patchUri( + Uri? uri, { + Object? data, + _i2.Options? options, + _i10.CancelToken? cancelToken, + _i2.ProgressCallback? onSendProgress, + _i2.ProgressCallback? onReceiveProgress, + }) => + (super.noSuchMethod( + Invocation.method( + #patchUri, + [uri], + { + #data: data, + #options: options, + #cancelToken: cancelToken, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #patchUri, + [uri], + { + #data: data, + #options: options, + #cancelToken: cancelToken, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> delete( + String? path, { + Object? data, + Map? queryParameters, + _i2.Options? options, + _i10.CancelToken? cancelToken, + }) => + (super.noSuchMethod( + Invocation.method( + #delete, + [path], + { + #data: data, + #queryParameters: queryParameters, + #options: options, + #cancelToken: cancelToken, + }, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #delete, + [path], + { + #data: data, + #queryParameters: queryParameters, + #options: options, + #cancelToken: cancelToken, + }, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> deleteUri( + Uri? uri, { + Object? data, + _i2.Options? options, + _i10.CancelToken? cancelToken, + }) => + (super.noSuchMethod( + Invocation.method( + #deleteUri, + [uri], + {#data: data, #options: options, #cancelToken: cancelToken}, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #deleteUri, + [uri], + {#data: data, #options: options, #cancelToken: cancelToken}, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> download( + String? urlPath, + dynamic savePath, { + _i2.ProgressCallback? onReceiveProgress, + Map? queryParameters, + _i10.CancelToken? cancelToken, + bool? deleteOnError = true, + _i2.FileAccessMode? fileAccessMode = _i2.FileAccessMode.write, + String? lengthHeader = 'content-length', + Object? data, + _i2.Options? options, + }) => + (super.noSuchMethod( + Invocation.method( + #download, + [urlPath, savePath], + { + #onReceiveProgress: onReceiveProgress, + #queryParameters: queryParameters, + #cancelToken: cancelToken, + #deleteOnError: deleteOnError, + #fileAccessMode: fileAccessMode, + #lengthHeader: lengthHeader, + #data: data, + #options: options, + }, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #download, + [urlPath, savePath], + { + #onReceiveProgress: onReceiveProgress, + #queryParameters: queryParameters, + #cancelToken: cancelToken, + #deleteOnError: deleteOnError, + #fileAccessMode: fileAccessMode, + #lengthHeader: lengthHeader, + #data: data, + #options: options, + }, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> downloadUri( + Uri? uri, + dynamic savePath, { + _i2.ProgressCallback? onReceiveProgress, + _i10.CancelToken? cancelToken, + bool? deleteOnError = true, + _i2.FileAccessMode? fileAccessMode = _i2.FileAccessMode.write, + String? lengthHeader = 'content-length', + Object? data, + _i2.Options? options, + }) => + (super.noSuchMethod( + Invocation.method( + #downloadUri, + [uri, savePath], + { + #onReceiveProgress: onReceiveProgress, + #cancelToken: cancelToken, + #deleteOnError: deleteOnError, + #fileAccessMode: fileAccessMode, + #lengthHeader: lengthHeader, + #data: data, + #options: options, + }, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #downloadUri, + [uri, savePath], + { + #onReceiveProgress: onReceiveProgress, + #cancelToken: cancelToken, + #deleteOnError: deleteOnError, + #fileAccessMode: fileAccessMode, + #lengthHeader: lengthHeader, + #data: data, + #options: options, + }, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> request( + String? url, { + Object? data, + Map? queryParameters, + _i10.CancelToken? cancelToken, + _i2.Options? options, + _i2.ProgressCallback? onSendProgress, + _i2.ProgressCallback? onReceiveProgress, + }) => + (super.noSuchMethod( + Invocation.method( + #request, + [url], + { + #data: data, + #queryParameters: queryParameters, + #cancelToken: cancelToken, + #options: options, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #request, + [url], + { + #data: data, + #queryParameters: queryParameters, + #cancelToken: cancelToken, + #options: options, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> requestUri( + Uri? uri, { + Object? data, + _i10.CancelToken? cancelToken, + _i2.Options? options, + _i2.ProgressCallback? onSendProgress, + _i2.ProgressCallback? onReceiveProgress, + }) => + (super.noSuchMethod( + Invocation.method( + #requestUri, + [uri], + { + #data: data, + #cancelToken: cancelToken, + #options: options, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #requestUri, + [uri], + { + #data: data, + #cancelToken: cancelToken, + #options: options, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> fetch(_i2.RequestOptions? requestOptions) => + (super.noSuchMethod( + Invocation.method(#fetch, [requestOptions]), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method(#fetch, [requestOptions]), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i7.Dio clone({ + _i2.BaseOptions? options, + _i3.Interceptors? interceptors, + _i4.HttpClientAdapter? httpClientAdapter, + _i5.Transformer? transformer, + }) => + (super.noSuchMethod( + Invocation.method(#clone, [], { + #options: options, + #interceptors: interceptors, + #httpClientAdapter: httpClientAdapter, + #transformer: transformer, + }), + returnValue: _FakeDio_5( + this, + Invocation.method(#clone, [], { + #options: options, + #interceptors: interceptors, + #httpClientAdapter: httpClientAdapter, + #transformer: transformer, + }), + ), + ) + as _i7.Dio); +} + +/// A class which mocks [FlutterSecureStorage]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockFlutterSecureStorage extends _i1.Mock + implements _i8.FlutterSecureStorage { + MockFlutterSecureStorage() { + _i1.throwOnMissingStub(this); + } + + @override + _i8.IOSOptions get iOptions => + (super.noSuchMethod( + Invocation.getter(#iOptions), + returnValue: _FakeIOSOptions_6(this, Invocation.getter(#iOptions)), + ) + as _i8.IOSOptions); + + @override + _i8.AndroidOptions get aOptions => + (super.noSuchMethod( + Invocation.getter(#aOptions), + returnValue: _FakeAndroidOptions_7( + this, + Invocation.getter(#aOptions), + ), + ) + as _i8.AndroidOptions); + + @override + _i8.LinuxOptions get lOptions => + (super.noSuchMethod( + Invocation.getter(#lOptions), + returnValue: _FakeLinuxOptions_8( + this, + Invocation.getter(#lOptions), + ), + ) + as _i8.LinuxOptions); + + @override + _i8.WindowsOptions get wOptions => + (super.noSuchMethod( + Invocation.getter(#wOptions), + returnValue: _FakeWindowsOptions_9( + this, + Invocation.getter(#wOptions), + ), + ) + as _i8.WindowsOptions); + + @override + _i8.WebOptions get webOptions => + (super.noSuchMethod( + Invocation.getter(#webOptions), + returnValue: _FakeWebOptions_10( + this, + Invocation.getter(#webOptions), + ), + ) + as _i8.WebOptions); + + @override + _i8.MacOsOptions get mOptions => + (super.noSuchMethod( + Invocation.getter(#mOptions), + returnValue: _FakeMacOsOptions_11( + this, + Invocation.getter(#mOptions), + ), + ) + as _i8.MacOsOptions); + + @override + void registerListener({ + required String? key, + required _i11.ValueChanged? listener, + }) => super.noSuchMethod( + Invocation.method(#registerListener, [], {#key: key, #listener: listener}), + returnValueForMissingStub: null, + ); + + @override + void unregisterListener({ + required String? key, + required _i11.ValueChanged? listener, + }) => super.noSuchMethod( + Invocation.method(#unregisterListener, [], { + #key: key, + #listener: listener, + }), + returnValueForMissingStub: null, + ); + + @override + void unregisterAllListenersForKey({required String? key}) => + super.noSuchMethod( + Invocation.method(#unregisterAllListenersForKey, [], {#key: key}), + returnValueForMissingStub: null, + ); + + @override + void unregisterAllListeners() => super.noSuchMethod( + Invocation.method(#unregisterAllListeners, []), + returnValueForMissingStub: null, + ); + + @override + _i9.Future write({ + required String? key, + required String? value, + _i8.IOSOptions? iOptions, + _i8.AndroidOptions? aOptions, + _i8.LinuxOptions? lOptions, + _i8.WebOptions? webOptions, + _i8.MacOsOptions? mOptions, + _i8.WindowsOptions? wOptions, + }) => + (super.noSuchMethod( + Invocation.method(#write, [], { + #key: key, + #value: value, + #iOptions: iOptions, + #aOptions: aOptions, + #lOptions: lOptions, + #webOptions: webOptions, + #mOptions: mOptions, + #wOptions: wOptions, + }), + returnValue: _i9.Future.value(), + returnValueForMissingStub: _i9.Future.value(), + ) + as _i9.Future); + + @override + _i9.Future read({ + required String? key, + _i8.IOSOptions? iOptions, + _i8.AndroidOptions? aOptions, + _i8.LinuxOptions? lOptions, + _i8.WebOptions? webOptions, + _i8.MacOsOptions? mOptions, + _i8.WindowsOptions? wOptions, + }) => + (super.noSuchMethod( + Invocation.method(#read, [], { + #key: key, + #iOptions: iOptions, + #aOptions: aOptions, + #lOptions: lOptions, + #webOptions: webOptions, + #mOptions: mOptions, + #wOptions: wOptions, + }), + returnValue: _i9.Future.value(), + ) + as _i9.Future); + + @override + _i9.Future containsKey({ + required String? key, + _i8.IOSOptions? iOptions, + _i8.AndroidOptions? aOptions, + _i8.LinuxOptions? lOptions, + _i8.WebOptions? webOptions, + _i8.MacOsOptions? mOptions, + _i8.WindowsOptions? wOptions, + }) => + (super.noSuchMethod( + Invocation.method(#containsKey, [], { + #key: key, + #iOptions: iOptions, + #aOptions: aOptions, + #lOptions: lOptions, + #webOptions: webOptions, + #mOptions: mOptions, + #wOptions: wOptions, + }), + returnValue: _i9.Future.value(false), + ) + as _i9.Future); + + @override + _i9.Future delete({ + required String? key, + _i8.IOSOptions? iOptions, + _i8.AndroidOptions? aOptions, + _i8.LinuxOptions? lOptions, + _i8.WebOptions? webOptions, + _i8.MacOsOptions? mOptions, + _i8.WindowsOptions? wOptions, + }) => + (super.noSuchMethod( + Invocation.method(#delete, [], { + #key: key, + #iOptions: iOptions, + #aOptions: aOptions, + #lOptions: lOptions, + #webOptions: webOptions, + #mOptions: mOptions, + #wOptions: wOptions, + }), + returnValue: _i9.Future.value(), + returnValueForMissingStub: _i9.Future.value(), + ) + as _i9.Future); + + @override + _i9.Future> readAll({ + _i8.IOSOptions? iOptions, + _i8.AndroidOptions? aOptions, + _i8.LinuxOptions? lOptions, + _i8.WebOptions? webOptions, + _i8.MacOsOptions? mOptions, + _i8.WindowsOptions? wOptions, + }) => + (super.noSuchMethod( + Invocation.method(#readAll, [], { + #iOptions: iOptions, + #aOptions: aOptions, + #lOptions: lOptions, + #webOptions: webOptions, + #mOptions: mOptions, + #wOptions: wOptions, + }), + returnValue: _i9.Future>.value( + {}, + ), + ) + as _i9.Future>); + + @override + _i9.Future deleteAll({ + _i8.IOSOptions? iOptions, + _i8.AndroidOptions? aOptions, + _i8.LinuxOptions? lOptions, + _i8.WebOptions? webOptions, + _i8.MacOsOptions? mOptions, + _i8.WindowsOptions? wOptions, + }) => + (super.noSuchMethod( + Invocation.method(#deleteAll, [], { + #iOptions: iOptions, + #aOptions: aOptions, + #lOptions: lOptions, + #webOptions: webOptions, + #mOptions: mOptions, + #wOptions: wOptions, + }), + returnValue: _i9.Future.value(), + returnValueForMissingStub: _i9.Future.value(), + ) + as _i9.Future); + + @override + _i9.Future isCupertinoProtectedDataAvailable() => + (super.noSuchMethod( + Invocation.method(#isCupertinoProtectedDataAvailable, []), + returnValue: _i9.Future.value(), + ) + as _i9.Future); +} diff --git a/test/services/coves_auth_service_singleton_test.mocks.dart b/test/services/coves_auth_service_singleton_test.mocks.dart new file mode 100644 index 0000000..22df811 --- /dev/null +++ b/test/services/coves_auth_service_singleton_test.mocks.dart @@ -0,0 +1,1102 @@ +// Mocks generated by Mockito 5.4.6 from annotations +// in coves_flutter/test/services/coves_auth_service_singleton_test.dart. +// Do not manually edit this file. + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'dart:async' as _i9; + +import 'package:dio/src/adapter.dart' as _i4; +import 'package:dio/src/cancel_token.dart' as _i10; +import 'package:dio/src/dio.dart' as _i7; +import 'package:dio/src/dio_mixin.dart' as _i3; +import 'package:dio/src/options.dart' as _i2; +import 'package:dio/src/response.dart' as _i6; +import 'package:dio/src/transformer.dart' as _i5; +import 'package:flutter/foundation.dart' as _i11; +import 'package:flutter_secure_storage/flutter_secure_storage.dart' as _i8; +import 'package:mockito/mockito.dart' as _i1; + +// ignore_for_file: type=lint +// ignore_for_file: avoid_redundant_argument_values +// ignore_for_file: avoid_setters_without_getters +// ignore_for_file: comment_references +// ignore_for_file: deprecated_member_use +// ignore_for_file: deprecated_member_use_from_same_package +// ignore_for_file: implementation_imports +// ignore_for_file: invalid_use_of_visible_for_testing_member +// ignore_for_file: must_be_immutable +// ignore_for_file: prefer_const_constructors +// ignore_for_file: unnecessary_parenthesis +// ignore_for_file: camel_case_types +// ignore_for_file: subtype_of_sealed_class +// ignore_for_file: invalid_use_of_internal_member + +class _FakeBaseOptions_0 extends _i1.SmartFake implements _i2.BaseOptions { + _FakeBaseOptions_0(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeInterceptors_1 extends _i1.SmartFake implements _i3.Interceptors { + _FakeInterceptors_1(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeHttpClientAdapter_2 extends _i1.SmartFake + implements _i4.HttpClientAdapter { + _FakeHttpClientAdapter_2(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeTransformer_3 extends _i1.SmartFake implements _i5.Transformer { + _FakeTransformer_3(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeResponse_4 extends _i1.SmartFake implements _i6.Response { + _FakeResponse_4(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeDio_5 extends _i1.SmartFake implements _i7.Dio { + _FakeDio_5(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeIOSOptions_6 extends _i1.SmartFake implements _i8.IOSOptions { + _FakeIOSOptions_6(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeAndroidOptions_7 extends _i1.SmartFake + implements _i8.AndroidOptions { + _FakeAndroidOptions_7(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeLinuxOptions_8 extends _i1.SmartFake implements _i8.LinuxOptions { + _FakeLinuxOptions_8(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeWindowsOptions_9 extends _i1.SmartFake + implements _i8.WindowsOptions { + _FakeWindowsOptions_9(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeWebOptions_10 extends _i1.SmartFake implements _i8.WebOptions { + _FakeWebOptions_10(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeMacOsOptions_11 extends _i1.SmartFake implements _i8.MacOsOptions { + _FakeMacOsOptions_11(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +/// A class which mocks [Dio]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockDio extends _i1.Mock implements _i7.Dio { + MockDio() { + _i1.throwOnMissingStub(this); + } + + @override + _i2.BaseOptions get options => + (super.noSuchMethod( + Invocation.getter(#options), + returnValue: _FakeBaseOptions_0(this, Invocation.getter(#options)), + ) + as _i2.BaseOptions); + + @override + _i3.Interceptors get interceptors => + (super.noSuchMethod( + Invocation.getter(#interceptors), + returnValue: _FakeInterceptors_1( + this, + Invocation.getter(#interceptors), + ), + ) + as _i3.Interceptors); + + @override + _i4.HttpClientAdapter get httpClientAdapter => + (super.noSuchMethod( + Invocation.getter(#httpClientAdapter), + returnValue: _FakeHttpClientAdapter_2( + this, + Invocation.getter(#httpClientAdapter), + ), + ) + as _i4.HttpClientAdapter); + + @override + _i5.Transformer get transformer => + (super.noSuchMethod( + Invocation.getter(#transformer), + returnValue: _FakeTransformer_3( + this, + Invocation.getter(#transformer), + ), + ) + as _i5.Transformer); + + @override + set options(_i2.BaseOptions? value) => super.noSuchMethod( + Invocation.setter(#options, value), + returnValueForMissingStub: null, + ); + + @override + set httpClientAdapter(_i4.HttpClientAdapter? value) => super.noSuchMethod( + Invocation.setter(#httpClientAdapter, value), + returnValueForMissingStub: null, + ); + + @override + set transformer(_i5.Transformer? value) => super.noSuchMethod( + Invocation.setter(#transformer, value), + returnValueForMissingStub: null, + ); + + @override + void close({bool? force = false}) => super.noSuchMethod( + Invocation.method(#close, [], {#force: force}), + returnValueForMissingStub: null, + ); + + @override + _i9.Future<_i6.Response> head( + String? path, { + Object? data, + Map? queryParameters, + _i2.Options? options, + _i10.CancelToken? cancelToken, + }) => + (super.noSuchMethod( + Invocation.method( + #head, + [path], + { + #data: data, + #queryParameters: queryParameters, + #options: options, + #cancelToken: cancelToken, + }, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #head, + [path], + { + #data: data, + #queryParameters: queryParameters, + #options: options, + #cancelToken: cancelToken, + }, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> headUri( + Uri? uri, { + Object? data, + _i2.Options? options, + _i10.CancelToken? cancelToken, + }) => + (super.noSuchMethod( + Invocation.method( + #headUri, + [uri], + {#data: data, #options: options, #cancelToken: cancelToken}, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #headUri, + [uri], + {#data: data, #options: options, #cancelToken: cancelToken}, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> get( + String? path, { + Object? data, + Map? queryParameters, + _i2.Options? options, + _i10.CancelToken? cancelToken, + _i2.ProgressCallback? onReceiveProgress, + }) => + (super.noSuchMethod( + Invocation.method( + #get, + [path], + { + #data: data, + #queryParameters: queryParameters, + #options: options, + #cancelToken: cancelToken, + #onReceiveProgress: onReceiveProgress, + }, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #get, + [path], + { + #data: data, + #queryParameters: queryParameters, + #options: options, + #cancelToken: cancelToken, + #onReceiveProgress: onReceiveProgress, + }, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> getUri( + Uri? uri, { + Object? data, + _i2.Options? options, + _i10.CancelToken? cancelToken, + _i2.ProgressCallback? onReceiveProgress, + }) => + (super.noSuchMethod( + Invocation.method( + #getUri, + [uri], + { + #data: data, + #options: options, + #cancelToken: cancelToken, + #onReceiveProgress: onReceiveProgress, + }, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #getUri, + [uri], + { + #data: data, + #options: options, + #cancelToken: cancelToken, + #onReceiveProgress: onReceiveProgress, + }, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> post( + String? path, { + Object? data, + Map? queryParameters, + _i2.Options? options, + _i10.CancelToken? cancelToken, + _i2.ProgressCallback? onSendProgress, + _i2.ProgressCallback? onReceiveProgress, + }) => + (super.noSuchMethod( + Invocation.method( + #post, + [path], + { + #data: data, + #queryParameters: queryParameters, + #options: options, + #cancelToken: cancelToken, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #post, + [path], + { + #data: data, + #queryParameters: queryParameters, + #options: options, + #cancelToken: cancelToken, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> postUri( + Uri? uri, { + Object? data, + _i2.Options? options, + _i10.CancelToken? cancelToken, + _i2.ProgressCallback? onSendProgress, + _i2.ProgressCallback? onReceiveProgress, + }) => + (super.noSuchMethod( + Invocation.method( + #postUri, + [uri], + { + #data: data, + #options: options, + #cancelToken: cancelToken, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #postUri, + [uri], + { + #data: data, + #options: options, + #cancelToken: cancelToken, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> put( + String? path, { + Object? data, + Map? queryParameters, + _i2.Options? options, + _i10.CancelToken? cancelToken, + _i2.ProgressCallback? onSendProgress, + _i2.ProgressCallback? onReceiveProgress, + }) => + (super.noSuchMethod( + Invocation.method( + #put, + [path], + { + #data: data, + #queryParameters: queryParameters, + #options: options, + #cancelToken: cancelToken, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #put, + [path], + { + #data: data, + #queryParameters: queryParameters, + #options: options, + #cancelToken: cancelToken, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> putUri( + Uri? uri, { + Object? data, + _i2.Options? options, + _i10.CancelToken? cancelToken, + _i2.ProgressCallback? onSendProgress, + _i2.ProgressCallback? onReceiveProgress, + }) => + (super.noSuchMethod( + Invocation.method( + #putUri, + [uri], + { + #data: data, + #options: options, + #cancelToken: cancelToken, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #putUri, + [uri], + { + #data: data, + #options: options, + #cancelToken: cancelToken, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> patch( + String? path, { + Object? data, + Map? queryParameters, + _i2.Options? options, + _i10.CancelToken? cancelToken, + _i2.ProgressCallback? onSendProgress, + _i2.ProgressCallback? onReceiveProgress, + }) => + (super.noSuchMethod( + Invocation.method( + #patch, + [path], + { + #data: data, + #queryParameters: queryParameters, + #options: options, + #cancelToken: cancelToken, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #patch, + [path], + { + #data: data, + #queryParameters: queryParameters, + #options: options, + #cancelToken: cancelToken, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> patchUri( + Uri? uri, { + Object? data, + _i2.Options? options, + _i10.CancelToken? cancelToken, + _i2.ProgressCallback? onSendProgress, + _i2.ProgressCallback? onReceiveProgress, + }) => + (super.noSuchMethod( + Invocation.method( + #patchUri, + [uri], + { + #data: data, + #options: options, + #cancelToken: cancelToken, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #patchUri, + [uri], + { + #data: data, + #options: options, + #cancelToken: cancelToken, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> delete( + String? path, { + Object? data, + Map? queryParameters, + _i2.Options? options, + _i10.CancelToken? cancelToken, + }) => + (super.noSuchMethod( + Invocation.method( + #delete, + [path], + { + #data: data, + #queryParameters: queryParameters, + #options: options, + #cancelToken: cancelToken, + }, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #delete, + [path], + { + #data: data, + #queryParameters: queryParameters, + #options: options, + #cancelToken: cancelToken, + }, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> deleteUri( + Uri? uri, { + Object? data, + _i2.Options? options, + _i10.CancelToken? cancelToken, + }) => + (super.noSuchMethod( + Invocation.method( + #deleteUri, + [uri], + {#data: data, #options: options, #cancelToken: cancelToken}, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #deleteUri, + [uri], + {#data: data, #options: options, #cancelToken: cancelToken}, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> download( + String? urlPath, + dynamic savePath, { + _i2.ProgressCallback? onReceiveProgress, + Map? queryParameters, + _i10.CancelToken? cancelToken, + bool? deleteOnError = true, + _i2.FileAccessMode? fileAccessMode = _i2.FileAccessMode.write, + String? lengthHeader = 'content-length', + Object? data, + _i2.Options? options, + }) => + (super.noSuchMethod( + Invocation.method( + #download, + [urlPath, savePath], + { + #onReceiveProgress: onReceiveProgress, + #queryParameters: queryParameters, + #cancelToken: cancelToken, + #deleteOnError: deleteOnError, + #fileAccessMode: fileAccessMode, + #lengthHeader: lengthHeader, + #data: data, + #options: options, + }, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #download, + [urlPath, savePath], + { + #onReceiveProgress: onReceiveProgress, + #queryParameters: queryParameters, + #cancelToken: cancelToken, + #deleteOnError: deleteOnError, + #fileAccessMode: fileAccessMode, + #lengthHeader: lengthHeader, + #data: data, + #options: options, + }, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> downloadUri( + Uri? uri, + dynamic savePath, { + _i2.ProgressCallback? onReceiveProgress, + _i10.CancelToken? cancelToken, + bool? deleteOnError = true, + _i2.FileAccessMode? fileAccessMode = _i2.FileAccessMode.write, + String? lengthHeader = 'content-length', + Object? data, + _i2.Options? options, + }) => + (super.noSuchMethod( + Invocation.method( + #downloadUri, + [uri, savePath], + { + #onReceiveProgress: onReceiveProgress, + #cancelToken: cancelToken, + #deleteOnError: deleteOnError, + #fileAccessMode: fileAccessMode, + #lengthHeader: lengthHeader, + #data: data, + #options: options, + }, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #downloadUri, + [uri, savePath], + { + #onReceiveProgress: onReceiveProgress, + #cancelToken: cancelToken, + #deleteOnError: deleteOnError, + #fileAccessMode: fileAccessMode, + #lengthHeader: lengthHeader, + #data: data, + #options: options, + }, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> request( + String? url, { + Object? data, + Map? queryParameters, + _i10.CancelToken? cancelToken, + _i2.Options? options, + _i2.ProgressCallback? onSendProgress, + _i2.ProgressCallback? onReceiveProgress, + }) => + (super.noSuchMethod( + Invocation.method( + #request, + [url], + { + #data: data, + #queryParameters: queryParameters, + #cancelToken: cancelToken, + #options: options, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #request, + [url], + { + #data: data, + #queryParameters: queryParameters, + #cancelToken: cancelToken, + #options: options, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> requestUri( + Uri? uri, { + Object? data, + _i10.CancelToken? cancelToken, + _i2.Options? options, + _i2.ProgressCallback? onSendProgress, + _i2.ProgressCallback? onReceiveProgress, + }) => + (super.noSuchMethod( + Invocation.method( + #requestUri, + [uri], + { + #data: data, + #cancelToken: cancelToken, + #options: options, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #requestUri, + [uri], + { + #data: data, + #cancelToken: cancelToken, + #options: options, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> fetch(_i2.RequestOptions? requestOptions) => + (super.noSuchMethod( + Invocation.method(#fetch, [requestOptions]), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method(#fetch, [requestOptions]), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i7.Dio clone({ + _i2.BaseOptions? options, + _i3.Interceptors? interceptors, + _i4.HttpClientAdapter? httpClientAdapter, + _i5.Transformer? transformer, + }) => + (super.noSuchMethod( + Invocation.method(#clone, [], { + #options: options, + #interceptors: interceptors, + #httpClientAdapter: httpClientAdapter, + #transformer: transformer, + }), + returnValue: _FakeDio_5( + this, + Invocation.method(#clone, [], { + #options: options, + #interceptors: interceptors, + #httpClientAdapter: httpClientAdapter, + #transformer: transformer, + }), + ), + ) + as _i7.Dio); +} + +/// A class which mocks [FlutterSecureStorage]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockFlutterSecureStorage extends _i1.Mock + implements _i8.FlutterSecureStorage { + MockFlutterSecureStorage() { + _i1.throwOnMissingStub(this); + } + + @override + _i8.IOSOptions get iOptions => + (super.noSuchMethod( + Invocation.getter(#iOptions), + returnValue: _FakeIOSOptions_6(this, Invocation.getter(#iOptions)), + ) + as _i8.IOSOptions); + + @override + _i8.AndroidOptions get aOptions => + (super.noSuchMethod( + Invocation.getter(#aOptions), + returnValue: _FakeAndroidOptions_7( + this, + Invocation.getter(#aOptions), + ), + ) + as _i8.AndroidOptions); + + @override + _i8.LinuxOptions get lOptions => + (super.noSuchMethod( + Invocation.getter(#lOptions), + returnValue: _FakeLinuxOptions_8( + this, + Invocation.getter(#lOptions), + ), + ) + as _i8.LinuxOptions); + + @override + _i8.WindowsOptions get wOptions => + (super.noSuchMethod( + Invocation.getter(#wOptions), + returnValue: _FakeWindowsOptions_9( + this, + Invocation.getter(#wOptions), + ), + ) + as _i8.WindowsOptions); + + @override + _i8.WebOptions get webOptions => + (super.noSuchMethod( + Invocation.getter(#webOptions), + returnValue: _FakeWebOptions_10( + this, + Invocation.getter(#webOptions), + ), + ) + as _i8.WebOptions); + + @override + _i8.MacOsOptions get mOptions => + (super.noSuchMethod( + Invocation.getter(#mOptions), + returnValue: _FakeMacOsOptions_11( + this, + Invocation.getter(#mOptions), + ), + ) + as _i8.MacOsOptions); + + @override + void registerListener({ + required String? key, + required _i11.ValueChanged? listener, + }) => super.noSuchMethod( + Invocation.method(#registerListener, [], {#key: key, #listener: listener}), + returnValueForMissingStub: null, + ); + + @override + void unregisterListener({ + required String? key, + required _i11.ValueChanged? listener, + }) => super.noSuchMethod( + Invocation.method(#unregisterListener, [], { + #key: key, + #listener: listener, + }), + returnValueForMissingStub: null, + ); + + @override + void unregisterAllListenersForKey({required String? key}) => + super.noSuchMethod( + Invocation.method(#unregisterAllListenersForKey, [], {#key: key}), + returnValueForMissingStub: null, + ); + + @override + void unregisterAllListeners() => super.noSuchMethod( + Invocation.method(#unregisterAllListeners, []), + returnValueForMissingStub: null, + ); + + @override + _i9.Future write({ + required String? key, + required String? value, + _i8.IOSOptions? iOptions, + _i8.AndroidOptions? aOptions, + _i8.LinuxOptions? lOptions, + _i8.WebOptions? webOptions, + _i8.MacOsOptions? mOptions, + _i8.WindowsOptions? wOptions, + }) => + (super.noSuchMethod( + Invocation.method(#write, [], { + #key: key, + #value: value, + #iOptions: iOptions, + #aOptions: aOptions, + #lOptions: lOptions, + #webOptions: webOptions, + #mOptions: mOptions, + #wOptions: wOptions, + }), + returnValue: _i9.Future.value(), + returnValueForMissingStub: _i9.Future.value(), + ) + as _i9.Future); + + @override + _i9.Future read({ + required String? key, + _i8.IOSOptions? iOptions, + _i8.AndroidOptions? aOptions, + _i8.LinuxOptions? lOptions, + _i8.WebOptions? webOptions, + _i8.MacOsOptions? mOptions, + _i8.WindowsOptions? wOptions, + }) => + (super.noSuchMethod( + Invocation.method(#read, [], { + #key: key, + #iOptions: iOptions, + #aOptions: aOptions, + #lOptions: lOptions, + #webOptions: webOptions, + #mOptions: mOptions, + #wOptions: wOptions, + }), + returnValue: _i9.Future.value(), + ) + as _i9.Future); + + @override + _i9.Future containsKey({ + required String? key, + _i8.IOSOptions? iOptions, + _i8.AndroidOptions? aOptions, + _i8.LinuxOptions? lOptions, + _i8.WebOptions? webOptions, + _i8.MacOsOptions? mOptions, + _i8.WindowsOptions? wOptions, + }) => + (super.noSuchMethod( + Invocation.method(#containsKey, [], { + #key: key, + #iOptions: iOptions, + #aOptions: aOptions, + #lOptions: lOptions, + #webOptions: webOptions, + #mOptions: mOptions, + #wOptions: wOptions, + }), + returnValue: _i9.Future.value(false), + ) + as _i9.Future); + + @override + _i9.Future delete({ + required String? key, + _i8.IOSOptions? iOptions, + _i8.AndroidOptions? aOptions, + _i8.LinuxOptions? lOptions, + _i8.WebOptions? webOptions, + _i8.MacOsOptions? mOptions, + _i8.WindowsOptions? wOptions, + }) => + (super.noSuchMethod( + Invocation.method(#delete, [], { + #key: key, + #iOptions: iOptions, + #aOptions: aOptions, + #lOptions: lOptions, + #webOptions: webOptions, + #mOptions: mOptions, + #wOptions: wOptions, + }), + returnValue: _i9.Future.value(), + returnValueForMissingStub: _i9.Future.value(), + ) + as _i9.Future); + + @override + _i9.Future> readAll({ + _i8.IOSOptions? iOptions, + _i8.AndroidOptions? aOptions, + _i8.LinuxOptions? lOptions, + _i8.WebOptions? webOptions, + _i8.MacOsOptions? mOptions, + _i8.WindowsOptions? wOptions, + }) => + (super.noSuchMethod( + Invocation.method(#readAll, [], { + #iOptions: iOptions, + #aOptions: aOptions, + #lOptions: lOptions, + #webOptions: webOptions, + #mOptions: mOptions, + #wOptions: wOptions, + }), + returnValue: _i9.Future>.value( + {}, + ), + ) + as _i9.Future>); + + @override + _i9.Future deleteAll({ + _i8.IOSOptions? iOptions, + _i8.AndroidOptions? aOptions, + _i8.LinuxOptions? lOptions, + _i8.WebOptions? webOptions, + _i8.MacOsOptions? mOptions, + _i8.WindowsOptions? wOptions, + }) => + (super.noSuchMethod( + Invocation.method(#deleteAll, [], { + #iOptions: iOptions, + #aOptions: aOptions, + #lOptions: lOptions, + #webOptions: webOptions, + #mOptions: mOptions, + #wOptions: wOptions, + }), + returnValue: _i9.Future.value(), + returnValueForMissingStub: _i9.Future.value(), + ) + as _i9.Future); + + @override + _i9.Future isCupertinoProtectedDataAvailable() => + (super.noSuchMethod( + Invocation.method(#isCupertinoProtectedDataAvailable, []), + returnValue: _i9.Future.value(), + ) + as _i9.Future); +} diff --git a/test/services/coves_auth_service_validation_test.mocks.dart b/test/services/coves_auth_service_validation_test.mocks.dart new file mode 100644 index 0000000..0ceaf28 --- /dev/null +++ b/test/services/coves_auth_service_validation_test.mocks.dart @@ -0,0 +1,1102 @@ +// Mocks generated by Mockito 5.4.6 from annotations +// in coves_flutter/test/services/coves_auth_service_validation_test.dart. +// Do not manually edit this file. + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'dart:async' as _i9; + +import 'package:dio/src/adapter.dart' as _i4; +import 'package:dio/src/cancel_token.dart' as _i10; +import 'package:dio/src/dio.dart' as _i7; +import 'package:dio/src/dio_mixin.dart' as _i3; +import 'package:dio/src/options.dart' as _i2; +import 'package:dio/src/response.dart' as _i6; +import 'package:dio/src/transformer.dart' as _i5; +import 'package:flutter/foundation.dart' as _i11; +import 'package:flutter_secure_storage/flutter_secure_storage.dart' as _i8; +import 'package:mockito/mockito.dart' as _i1; + +// ignore_for_file: type=lint +// ignore_for_file: avoid_redundant_argument_values +// ignore_for_file: avoid_setters_without_getters +// ignore_for_file: comment_references +// ignore_for_file: deprecated_member_use +// ignore_for_file: deprecated_member_use_from_same_package +// ignore_for_file: implementation_imports +// ignore_for_file: invalid_use_of_visible_for_testing_member +// ignore_for_file: must_be_immutable +// ignore_for_file: prefer_const_constructors +// ignore_for_file: unnecessary_parenthesis +// ignore_for_file: camel_case_types +// ignore_for_file: subtype_of_sealed_class +// ignore_for_file: invalid_use_of_internal_member + +class _FakeBaseOptions_0 extends _i1.SmartFake implements _i2.BaseOptions { + _FakeBaseOptions_0(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeInterceptors_1 extends _i1.SmartFake implements _i3.Interceptors { + _FakeInterceptors_1(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeHttpClientAdapter_2 extends _i1.SmartFake + implements _i4.HttpClientAdapter { + _FakeHttpClientAdapter_2(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeTransformer_3 extends _i1.SmartFake implements _i5.Transformer { + _FakeTransformer_3(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeResponse_4 extends _i1.SmartFake implements _i6.Response { + _FakeResponse_4(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeDio_5 extends _i1.SmartFake implements _i7.Dio { + _FakeDio_5(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeIOSOptions_6 extends _i1.SmartFake implements _i8.IOSOptions { + _FakeIOSOptions_6(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeAndroidOptions_7 extends _i1.SmartFake + implements _i8.AndroidOptions { + _FakeAndroidOptions_7(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeLinuxOptions_8 extends _i1.SmartFake implements _i8.LinuxOptions { + _FakeLinuxOptions_8(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeWindowsOptions_9 extends _i1.SmartFake + implements _i8.WindowsOptions { + _FakeWindowsOptions_9(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeWebOptions_10 extends _i1.SmartFake implements _i8.WebOptions { + _FakeWebOptions_10(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeMacOsOptions_11 extends _i1.SmartFake implements _i8.MacOsOptions { + _FakeMacOsOptions_11(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +/// A class which mocks [Dio]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockDio extends _i1.Mock implements _i7.Dio { + MockDio() { + _i1.throwOnMissingStub(this); + } + + @override + _i2.BaseOptions get options => + (super.noSuchMethod( + Invocation.getter(#options), + returnValue: _FakeBaseOptions_0(this, Invocation.getter(#options)), + ) + as _i2.BaseOptions); + + @override + _i3.Interceptors get interceptors => + (super.noSuchMethod( + Invocation.getter(#interceptors), + returnValue: _FakeInterceptors_1( + this, + Invocation.getter(#interceptors), + ), + ) + as _i3.Interceptors); + + @override + _i4.HttpClientAdapter get httpClientAdapter => + (super.noSuchMethod( + Invocation.getter(#httpClientAdapter), + returnValue: _FakeHttpClientAdapter_2( + this, + Invocation.getter(#httpClientAdapter), + ), + ) + as _i4.HttpClientAdapter); + + @override + _i5.Transformer get transformer => + (super.noSuchMethod( + Invocation.getter(#transformer), + returnValue: _FakeTransformer_3( + this, + Invocation.getter(#transformer), + ), + ) + as _i5.Transformer); + + @override + set options(_i2.BaseOptions? value) => super.noSuchMethod( + Invocation.setter(#options, value), + returnValueForMissingStub: null, + ); + + @override + set httpClientAdapter(_i4.HttpClientAdapter? value) => super.noSuchMethod( + Invocation.setter(#httpClientAdapter, value), + returnValueForMissingStub: null, + ); + + @override + set transformer(_i5.Transformer? value) => super.noSuchMethod( + Invocation.setter(#transformer, value), + returnValueForMissingStub: null, + ); + + @override + void close({bool? force = false}) => super.noSuchMethod( + Invocation.method(#close, [], {#force: force}), + returnValueForMissingStub: null, + ); + + @override + _i9.Future<_i6.Response> head( + String? path, { + Object? data, + Map? queryParameters, + _i2.Options? options, + _i10.CancelToken? cancelToken, + }) => + (super.noSuchMethod( + Invocation.method( + #head, + [path], + { + #data: data, + #queryParameters: queryParameters, + #options: options, + #cancelToken: cancelToken, + }, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #head, + [path], + { + #data: data, + #queryParameters: queryParameters, + #options: options, + #cancelToken: cancelToken, + }, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> headUri( + Uri? uri, { + Object? data, + _i2.Options? options, + _i10.CancelToken? cancelToken, + }) => + (super.noSuchMethod( + Invocation.method( + #headUri, + [uri], + {#data: data, #options: options, #cancelToken: cancelToken}, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #headUri, + [uri], + {#data: data, #options: options, #cancelToken: cancelToken}, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> get( + String? path, { + Object? data, + Map? queryParameters, + _i2.Options? options, + _i10.CancelToken? cancelToken, + _i2.ProgressCallback? onReceiveProgress, + }) => + (super.noSuchMethod( + Invocation.method( + #get, + [path], + { + #data: data, + #queryParameters: queryParameters, + #options: options, + #cancelToken: cancelToken, + #onReceiveProgress: onReceiveProgress, + }, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #get, + [path], + { + #data: data, + #queryParameters: queryParameters, + #options: options, + #cancelToken: cancelToken, + #onReceiveProgress: onReceiveProgress, + }, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> getUri( + Uri? uri, { + Object? data, + _i2.Options? options, + _i10.CancelToken? cancelToken, + _i2.ProgressCallback? onReceiveProgress, + }) => + (super.noSuchMethod( + Invocation.method( + #getUri, + [uri], + { + #data: data, + #options: options, + #cancelToken: cancelToken, + #onReceiveProgress: onReceiveProgress, + }, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #getUri, + [uri], + { + #data: data, + #options: options, + #cancelToken: cancelToken, + #onReceiveProgress: onReceiveProgress, + }, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> post( + String? path, { + Object? data, + Map? queryParameters, + _i2.Options? options, + _i10.CancelToken? cancelToken, + _i2.ProgressCallback? onSendProgress, + _i2.ProgressCallback? onReceiveProgress, + }) => + (super.noSuchMethod( + Invocation.method( + #post, + [path], + { + #data: data, + #queryParameters: queryParameters, + #options: options, + #cancelToken: cancelToken, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #post, + [path], + { + #data: data, + #queryParameters: queryParameters, + #options: options, + #cancelToken: cancelToken, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> postUri( + Uri? uri, { + Object? data, + _i2.Options? options, + _i10.CancelToken? cancelToken, + _i2.ProgressCallback? onSendProgress, + _i2.ProgressCallback? onReceiveProgress, + }) => + (super.noSuchMethod( + Invocation.method( + #postUri, + [uri], + { + #data: data, + #options: options, + #cancelToken: cancelToken, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #postUri, + [uri], + { + #data: data, + #options: options, + #cancelToken: cancelToken, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> put( + String? path, { + Object? data, + Map? queryParameters, + _i2.Options? options, + _i10.CancelToken? cancelToken, + _i2.ProgressCallback? onSendProgress, + _i2.ProgressCallback? onReceiveProgress, + }) => + (super.noSuchMethod( + Invocation.method( + #put, + [path], + { + #data: data, + #queryParameters: queryParameters, + #options: options, + #cancelToken: cancelToken, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #put, + [path], + { + #data: data, + #queryParameters: queryParameters, + #options: options, + #cancelToken: cancelToken, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> putUri( + Uri? uri, { + Object? data, + _i2.Options? options, + _i10.CancelToken? cancelToken, + _i2.ProgressCallback? onSendProgress, + _i2.ProgressCallback? onReceiveProgress, + }) => + (super.noSuchMethod( + Invocation.method( + #putUri, + [uri], + { + #data: data, + #options: options, + #cancelToken: cancelToken, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #putUri, + [uri], + { + #data: data, + #options: options, + #cancelToken: cancelToken, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> patch( + String? path, { + Object? data, + Map? queryParameters, + _i2.Options? options, + _i10.CancelToken? cancelToken, + _i2.ProgressCallback? onSendProgress, + _i2.ProgressCallback? onReceiveProgress, + }) => + (super.noSuchMethod( + Invocation.method( + #patch, + [path], + { + #data: data, + #queryParameters: queryParameters, + #options: options, + #cancelToken: cancelToken, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #patch, + [path], + { + #data: data, + #queryParameters: queryParameters, + #options: options, + #cancelToken: cancelToken, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> patchUri( + Uri? uri, { + Object? data, + _i2.Options? options, + _i10.CancelToken? cancelToken, + _i2.ProgressCallback? onSendProgress, + _i2.ProgressCallback? onReceiveProgress, + }) => + (super.noSuchMethod( + Invocation.method( + #patchUri, + [uri], + { + #data: data, + #options: options, + #cancelToken: cancelToken, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #patchUri, + [uri], + { + #data: data, + #options: options, + #cancelToken: cancelToken, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> delete( + String? path, { + Object? data, + Map? queryParameters, + _i2.Options? options, + _i10.CancelToken? cancelToken, + }) => + (super.noSuchMethod( + Invocation.method( + #delete, + [path], + { + #data: data, + #queryParameters: queryParameters, + #options: options, + #cancelToken: cancelToken, + }, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #delete, + [path], + { + #data: data, + #queryParameters: queryParameters, + #options: options, + #cancelToken: cancelToken, + }, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> deleteUri( + Uri? uri, { + Object? data, + _i2.Options? options, + _i10.CancelToken? cancelToken, + }) => + (super.noSuchMethod( + Invocation.method( + #deleteUri, + [uri], + {#data: data, #options: options, #cancelToken: cancelToken}, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #deleteUri, + [uri], + {#data: data, #options: options, #cancelToken: cancelToken}, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> download( + String? urlPath, + dynamic savePath, { + _i2.ProgressCallback? onReceiveProgress, + Map? queryParameters, + _i10.CancelToken? cancelToken, + bool? deleteOnError = true, + _i2.FileAccessMode? fileAccessMode = _i2.FileAccessMode.write, + String? lengthHeader = 'content-length', + Object? data, + _i2.Options? options, + }) => + (super.noSuchMethod( + Invocation.method( + #download, + [urlPath, savePath], + { + #onReceiveProgress: onReceiveProgress, + #queryParameters: queryParameters, + #cancelToken: cancelToken, + #deleteOnError: deleteOnError, + #fileAccessMode: fileAccessMode, + #lengthHeader: lengthHeader, + #data: data, + #options: options, + }, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #download, + [urlPath, savePath], + { + #onReceiveProgress: onReceiveProgress, + #queryParameters: queryParameters, + #cancelToken: cancelToken, + #deleteOnError: deleteOnError, + #fileAccessMode: fileAccessMode, + #lengthHeader: lengthHeader, + #data: data, + #options: options, + }, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> downloadUri( + Uri? uri, + dynamic savePath, { + _i2.ProgressCallback? onReceiveProgress, + _i10.CancelToken? cancelToken, + bool? deleteOnError = true, + _i2.FileAccessMode? fileAccessMode = _i2.FileAccessMode.write, + String? lengthHeader = 'content-length', + Object? data, + _i2.Options? options, + }) => + (super.noSuchMethod( + Invocation.method( + #downloadUri, + [uri, savePath], + { + #onReceiveProgress: onReceiveProgress, + #cancelToken: cancelToken, + #deleteOnError: deleteOnError, + #fileAccessMode: fileAccessMode, + #lengthHeader: lengthHeader, + #data: data, + #options: options, + }, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #downloadUri, + [uri, savePath], + { + #onReceiveProgress: onReceiveProgress, + #cancelToken: cancelToken, + #deleteOnError: deleteOnError, + #fileAccessMode: fileAccessMode, + #lengthHeader: lengthHeader, + #data: data, + #options: options, + }, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> request( + String? url, { + Object? data, + Map? queryParameters, + _i10.CancelToken? cancelToken, + _i2.Options? options, + _i2.ProgressCallback? onSendProgress, + _i2.ProgressCallback? onReceiveProgress, + }) => + (super.noSuchMethod( + Invocation.method( + #request, + [url], + { + #data: data, + #queryParameters: queryParameters, + #cancelToken: cancelToken, + #options: options, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #request, + [url], + { + #data: data, + #queryParameters: queryParameters, + #cancelToken: cancelToken, + #options: options, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> requestUri( + Uri? uri, { + Object? data, + _i10.CancelToken? cancelToken, + _i2.Options? options, + _i2.ProgressCallback? onSendProgress, + _i2.ProgressCallback? onReceiveProgress, + }) => + (super.noSuchMethod( + Invocation.method( + #requestUri, + [uri], + { + #data: data, + #cancelToken: cancelToken, + #options: options, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method( + #requestUri, + [uri], + { + #data: data, + #cancelToken: cancelToken, + #options: options, + #onSendProgress: onSendProgress, + #onReceiveProgress: onReceiveProgress, + }, + ), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i9.Future<_i6.Response> fetch(_i2.RequestOptions? requestOptions) => + (super.noSuchMethod( + Invocation.method(#fetch, [requestOptions]), + returnValue: _i9.Future<_i6.Response>.value( + _FakeResponse_4( + this, + Invocation.method(#fetch, [requestOptions]), + ), + ), + ) + as _i9.Future<_i6.Response>); + + @override + _i7.Dio clone({ + _i2.BaseOptions? options, + _i3.Interceptors? interceptors, + _i4.HttpClientAdapter? httpClientAdapter, + _i5.Transformer? transformer, + }) => + (super.noSuchMethod( + Invocation.method(#clone, [], { + #options: options, + #interceptors: interceptors, + #httpClientAdapter: httpClientAdapter, + #transformer: transformer, + }), + returnValue: _FakeDio_5( + this, + Invocation.method(#clone, [], { + #options: options, + #interceptors: interceptors, + #httpClientAdapter: httpClientAdapter, + #transformer: transformer, + }), + ), + ) + as _i7.Dio); +} + +/// A class which mocks [FlutterSecureStorage]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockFlutterSecureStorage extends _i1.Mock + implements _i8.FlutterSecureStorage { + MockFlutterSecureStorage() { + _i1.throwOnMissingStub(this); + } + + @override + _i8.IOSOptions get iOptions => + (super.noSuchMethod( + Invocation.getter(#iOptions), + returnValue: _FakeIOSOptions_6(this, Invocation.getter(#iOptions)), + ) + as _i8.IOSOptions); + + @override + _i8.AndroidOptions get aOptions => + (super.noSuchMethod( + Invocation.getter(#aOptions), + returnValue: _FakeAndroidOptions_7( + this, + Invocation.getter(#aOptions), + ), + ) + as _i8.AndroidOptions); + + @override + _i8.LinuxOptions get lOptions => + (super.noSuchMethod( + Invocation.getter(#lOptions), + returnValue: _FakeLinuxOptions_8( + this, + Invocation.getter(#lOptions), + ), + ) + as _i8.LinuxOptions); + + @override + _i8.WindowsOptions get wOptions => + (super.noSuchMethod( + Invocation.getter(#wOptions), + returnValue: _FakeWindowsOptions_9( + this, + Invocation.getter(#wOptions), + ), + ) + as _i8.WindowsOptions); + + @override + _i8.WebOptions get webOptions => + (super.noSuchMethod( + Invocation.getter(#webOptions), + returnValue: _FakeWebOptions_10( + this, + Invocation.getter(#webOptions), + ), + ) + as _i8.WebOptions); + + @override + _i8.MacOsOptions get mOptions => + (super.noSuchMethod( + Invocation.getter(#mOptions), + returnValue: _FakeMacOsOptions_11( + this, + Invocation.getter(#mOptions), + ), + ) + as _i8.MacOsOptions); + + @override + void registerListener({ + required String? key, + required _i11.ValueChanged? listener, + }) => super.noSuchMethod( + Invocation.method(#registerListener, [], {#key: key, #listener: listener}), + returnValueForMissingStub: null, + ); + + @override + void unregisterListener({ + required String? key, + required _i11.ValueChanged? listener, + }) => super.noSuchMethod( + Invocation.method(#unregisterListener, [], { + #key: key, + #listener: listener, + }), + returnValueForMissingStub: null, + ); + + @override + void unregisterAllListenersForKey({required String? key}) => + super.noSuchMethod( + Invocation.method(#unregisterAllListenersForKey, [], {#key: key}), + returnValueForMissingStub: null, + ); + + @override + void unregisterAllListeners() => super.noSuchMethod( + Invocation.method(#unregisterAllListeners, []), + returnValueForMissingStub: null, + ); + + @override + _i9.Future write({ + required String? key, + required String? value, + _i8.IOSOptions? iOptions, + _i8.AndroidOptions? aOptions, + _i8.LinuxOptions? lOptions, + _i8.WebOptions? webOptions, + _i8.MacOsOptions? mOptions, + _i8.WindowsOptions? wOptions, + }) => + (super.noSuchMethod( + Invocation.method(#write, [], { + #key: key, + #value: value, + #iOptions: iOptions, + #aOptions: aOptions, + #lOptions: lOptions, + #webOptions: webOptions, + #mOptions: mOptions, + #wOptions: wOptions, + }), + returnValue: _i9.Future.value(), + returnValueForMissingStub: _i9.Future.value(), + ) + as _i9.Future); + + @override + _i9.Future read({ + required String? key, + _i8.IOSOptions? iOptions, + _i8.AndroidOptions? aOptions, + _i8.LinuxOptions? lOptions, + _i8.WebOptions? webOptions, + _i8.MacOsOptions? mOptions, + _i8.WindowsOptions? wOptions, + }) => + (super.noSuchMethod( + Invocation.method(#read, [], { + #key: key, + #iOptions: iOptions, + #aOptions: aOptions, + #lOptions: lOptions, + #webOptions: webOptions, + #mOptions: mOptions, + #wOptions: wOptions, + }), + returnValue: _i9.Future.value(), + ) + as _i9.Future); + + @override + _i9.Future containsKey({ + required String? key, + _i8.IOSOptions? iOptions, + _i8.AndroidOptions? aOptions, + _i8.LinuxOptions? lOptions, + _i8.WebOptions? webOptions, + _i8.MacOsOptions? mOptions, + _i8.WindowsOptions? wOptions, + }) => + (super.noSuchMethod( + Invocation.method(#containsKey, [], { + #key: key, + #iOptions: iOptions, + #aOptions: aOptions, + #lOptions: lOptions, + #webOptions: webOptions, + #mOptions: mOptions, + #wOptions: wOptions, + }), + returnValue: _i9.Future.value(false), + ) + as _i9.Future); + + @override + _i9.Future delete({ + required String? key, + _i8.IOSOptions? iOptions, + _i8.AndroidOptions? aOptions, + _i8.LinuxOptions? lOptions, + _i8.WebOptions? webOptions, + _i8.MacOsOptions? mOptions, + _i8.WindowsOptions? wOptions, + }) => + (super.noSuchMethod( + Invocation.method(#delete, [], { + #key: key, + #iOptions: iOptions, + #aOptions: aOptions, + #lOptions: lOptions, + #webOptions: webOptions, + #mOptions: mOptions, + #wOptions: wOptions, + }), + returnValue: _i9.Future.value(), + returnValueForMissingStub: _i9.Future.value(), + ) + as _i9.Future); + + @override + _i9.Future> readAll({ + _i8.IOSOptions? iOptions, + _i8.AndroidOptions? aOptions, + _i8.LinuxOptions? lOptions, + _i8.WebOptions? webOptions, + _i8.MacOsOptions? mOptions, + _i8.WindowsOptions? wOptions, + }) => + (super.noSuchMethod( + Invocation.method(#readAll, [], { + #iOptions: iOptions, + #aOptions: aOptions, + #lOptions: lOptions, + #webOptions: webOptions, + #mOptions: mOptions, + #wOptions: wOptions, + }), + returnValue: _i9.Future>.value( + {}, + ), + ) + as _i9.Future>); + + @override + _i9.Future deleteAll({ + _i8.IOSOptions? iOptions, + _i8.AndroidOptions? aOptions, + _i8.LinuxOptions? lOptions, + _i8.WebOptions? webOptions, + _i8.MacOsOptions? mOptions, + _i8.WindowsOptions? wOptions, + }) => + (super.noSuchMethod( + Invocation.method(#deleteAll, [], { + #iOptions: iOptions, + #aOptions: aOptions, + #lOptions: lOptions, + #webOptions: webOptions, + #mOptions: mOptions, + #wOptions: wOptions, + }), + returnValue: _i9.Future.value(), + returnValueForMissingStub: _i9.Future.value(), + ) + as _i9.Future); + + @override + _i9.Future isCupertinoProtectedDataAvailable() => + (super.noSuchMethod( + Invocation.method(#isCupertinoProtectedDataAvailable, []), + returnValue: _i9.Future.value(), + ) + as _i9.Future); +} diff --git a/test/services/vote_service_test.dart b/test/services/vote_service_test.dart index 536402a..2ab4ffa 100644 --- a/test/services/vote_service_test.dart +++ b/test/services/vote_service_test.dart @@ -30,29 +30,6 @@ void main() { }); }); - group('ExistingVote', () { - test('should store direction and rkey', () { - const vote = ExistingVote(direction: 'up', rkey: 'abc123'); - - expect(vote.direction, 'up'); - expect(vote.rkey, 'abc123'); - }); - }); - - group('VoteInfo', () { - test('should store vote info', () { - const info = VoteInfo( - direction: 'up', - voteUri: 'at://did:plc:test/social.coves.feed.vote/123', - rkey: '123', - ); - - expect(info.direction, 'up'); - expect(info.voteUri, 'at://did:plc:test/social.coves.feed.vote/123'); - expect(info.rkey, '123'); - }); - }); - group('API Exception handling', () { test('should throw ApiException on Dio network error', () { final dioError = DioException( diff --git a/test/services/vote_service_token_refresh_test.dart b/test/services/vote_service_token_refresh_test.dart index dfac38f..d0c26b5 100644 --- a/test/services/vote_service_token_refresh_test.dart +++ b/test/services/vote_service_token_refresh_test.dart @@ -250,40 +250,7 @@ void main() { expect(signOutCallCount, 0); }); - test('should handle 401 on vote delete and retry', () async { - const rkey = 'abc123'; - - // Mock will always return 401 - dioAdapter.onPost( - '/xrpc/social.coves.feed.vote.delete', - (server) => server.reply(401, { - 'error': 'Unauthorized', - 'message': 'Token expired', - }), - data: {'rkey': rkey}, - ); - - // Create vote with existing vote (will trigger delete) - expect( - () => voteService.createVote( - postUri: 'at://did:plc:test/social.coves.post.record/123', - postCid: 'bafy123', - direction: 'up', - existingVoteRkey: rkey, - existingVoteDirection: 'up', - ), - throwsA(isA()), - ); - - // Wait for async operations - await Future.delayed(const Duration(milliseconds: 100)); - - // Verify token refresh was called - expect(tokenRefreshCallCount, 1); - - // Verify user was signed out after retry failed - expect(signOutCallCount, 1); - }); + // Note: delete method was removed - backend handles toggle via create endpoint test('should throw ApiException when session is null', () async { // Create service that returns null session @@ -347,20 +314,25 @@ void main() { sessionId: 'session123', ); - // Second request should use the new token + // Second request uses a different post + const postUri2 = 'at://did:plc:test/social.coves.post.record/456'; dioAdapter.onPost( - '/xrpc/social.coves.feed.vote.delete', - (server) => server.reply(200, {}), - data: {'rkey': 'xyz'}, + '/xrpc/social.coves.feed.vote.create', + (server) => server.reply(200, { + 'uri': 'at://did:plc:test/social.coves.feed.vote/abc', + 'cid': 'bafy789', + }), + data: { + 'subject': {'uri': postUri2, 'cid': postCid}, + 'direction': 'up', + }, ); - // Make second request (delete vote) + // Make second request await voteService.createVote( - postUri: postUri, + postUri: postUri2, postCid: postCid, direction: 'up', - existingVoteRkey: 'xyz', - existingVoteDirection: 'up', ); // Verify no refresh was needed (tokens were valid) diff --git a/test/test_helpers/mock_providers.dart b/test/test_helpers/mock_providers.dart index ab31eea..0a2eeee 100644 --- a/test/test_helpers/mock_providers.dart +++ b/test/test_helpers/mock_providers.dart @@ -1,6 +1,5 @@ import 'package:coves_flutter/models/coves_session.dart'; import 'package:coves_flutter/providers/vote_provider.dart'; -import 'package:coves_flutter/services/vote_service.dart'; import 'package:flutter/foundation.dart'; /// Mock AuthProvider for testing @@ -104,21 +103,31 @@ class MockVoteProvider extends ChangeNotifier { notifyListeners(); } - void loadInitialVotes(Map votes) { - for (final entry in votes.entries) { - final postUri = entry.key; - final voteInfo = entry.value; + void setInitialVoteState({ + required String postUri, + String? voteDirection, + String? voteUri, + }) { + if (voteDirection != null) { + String? rkey; + if (voteUri != null) { + final parts = voteUri.split('/'); + if (parts.isNotEmpty) { + rkey = parts.last; + } + } _votes[postUri] = VoteState( - direction: voteInfo.direction, - uri: voteInfo.voteUri, - rkey: voteInfo.rkey, + direction: voteDirection, + uri: voteUri, + rkey: rkey, deleted: false, ); _scoreAdjustments.remove(postUri); + } else { + _votes.remove(postUri); } - notifyListeners(); } void clear() {