From 6cd553cb38eaab3f606dc81857b5ab7f6aee25dd Mon Sep 17 00:00:00 2001 From: Terence ZAFINDRATAFA Date: Tue, 28 May 2024 17:13:57 +0200 Subject: [PATCH] TW-1702: regression fix + tests added for download on mobile --- .../download_manager/download_manager.dart | 24 +- .../manager/storage_directory_manager.dart | 2 + .../mixins/download_file_on_mobile_mixin.dart | 25 +- .../download_file_on_mobile_mixin_test.dart | 257 ++++ ...nload_file_on_mobile_mixin_test.mocks.dart | 1054 +++++++++++++++++ 5 files changed, 1343 insertions(+), 19 deletions(-) create mode 100644 test/mixin/download/download_file_on_mobile_mixin_test.dart create mode 100644 test/mixin/download/download_file_on_mobile_mixin_test.mocks.dart diff --git a/lib/utils/manager/download_manager/download_manager.dart b/lib/utils/manager/download_manager/download_manager.dart index a283163d0a..4f828da0b0 100644 --- a/lib/utils/manager/download_manager/download_manager.dart +++ b/lib/utils/manager/download_manager/download_manager.dart @@ -26,14 +26,14 @@ class DownloadManager { final workingQueue = getIt.get(); - final Map _eventIdMapDownloadFileInfo = {}; + final Map eventIdMapDownloadFileInfo = {}; void cancelDownload(String eventId) { - final cancelToken = _eventIdMapDownloadFileInfo[eventId]?.cancelToken; + final cancelToken = eventIdMapDownloadFileInfo[eventId]?.cancelToken; if (cancelToken != null) { try { cancelToken.cancel(); - _eventIdMapDownloadFileInfo[eventId]?.downloadStateStreamController.add( + eventIdMapDownloadFileInfo[eventId]?.downloadStateStreamController.add( Left( DownloadFileFailureState( exception: CancelDownloadingException(), @@ -44,7 +44,7 @@ class DownloadManager { Logs().e( 'DownloadManager::cancelDownload(): $e', ); - _eventIdMapDownloadFileInfo[eventId]?.downloadStateStreamController.add( + eventIdMapDownloadFileInfo[eventId]?.downloadStateStreamController.add( Left( DownloadFileFailureState(exception: e), ), @@ -60,7 +60,7 @@ class DownloadManager { ) { final streamController = StreamController>(); - _eventIdMapDownloadFileInfo[event.eventId] = DownloadFileInfo( + eventIdMapDownloadFileInfo[event.eventId] = DownloadFileInfo( eventId: event.eventId, cancelToken: CancelToken(), downloadStateStreamController: streamController, @@ -69,25 +69,25 @@ class DownloadManager { } Stream>? getDownloadStateStream(String eventId) { - return _eventIdMapDownloadFileInfo[eventId]?.downloadStream; + return eventIdMapDownloadFileInfo[eventId]?.downloadStream; } Future clear(String eventId) async { try { - await _eventIdMapDownloadFileInfo[eventId] + await eventIdMapDownloadFileInfo[eventId] ?.downloadStateStreamController .close(); } catch (e) { Logs().e( 'DownloadManager::_clear(): $e', ); - _eventIdMapDownloadFileInfo[eventId]?.downloadStateStreamController.add( + eventIdMapDownloadFileInfo[eventId]?.downloadStateStreamController.add( Left( DownloadFileFailureState(exception: e), ), ); } finally { - _eventIdMapDownloadFileInfo.remove(eventId); + eventIdMapDownloadFileInfo.remove(eventId); Logs().i( 'DownloadManager::clear with $eventId successfully', ); @@ -100,14 +100,14 @@ class DownloadManager { bool isFirstPriority = false, }) async { _initDownloadFileInfo(event); - final streamController = _eventIdMapDownloadFileInfo[event.eventId] + final streamController = eventIdMapDownloadFileInfo[event.eventId] ?.downloadStateStreamController; - final cancelToken = _eventIdMapDownloadFileInfo[event.eventId]?.cancelToken; + final cancelToken = eventIdMapDownloadFileInfo[event.eventId]?.cancelToken; if (streamController == null || cancelToken == null) { Logs().e( 'DownloadManager::download(): streamController or cancelToken is null', ); - _eventIdMapDownloadFileInfo[event.eventId] + eventIdMapDownloadFileInfo[event.eventId] ?.downloadStateStreamController .add( Left( diff --git a/lib/utils/manager/storage_directory_manager.dart b/lib/utils/manager/storage_directory_manager.dart index a45902f8f5..6cb8bc6913 100644 --- a/lib/utils/manager/storage_directory_manager.dart +++ b/lib/utils/manager/storage_directory_manager.dart @@ -13,6 +13,8 @@ class StorageDirectoryManager { static StorageDirectoryManager get instance => _instance; + factory StorageDirectoryManager() => _instance; + Future getFileStoreDirectory() async { try { try { diff --git a/lib/widgets/mixins/download_file_on_mobile_mixin.dart b/lib/widgets/mixins/download_file_on_mobile_mixin.dart index 4a2a438835..11a1db8228 100644 --- a/lib/widgets/mixins/download_file_on_mobile_mixin.dart +++ b/lib/widgets/mixins/download_file_on_mobile_mixin.dart @@ -6,6 +6,7 @@ import 'package:fluffychat/app_state/failure.dart'; import 'package:fluffychat/app_state/success.dart'; import 'package:fluffychat/di/global/get_it_initializer.dart'; import 'package:fluffychat/presentation/model/chat/downloading_state_presentation_model.dart'; +import 'package:fluffychat/utils/exception/downloading_exception.dart'; import 'package:fluffychat/utils/manager/download_manager/download_file_state.dart'; import 'package:fluffychat/utils/manager/storage_directory_manager.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions/download_file_extension.dart'; @@ -17,6 +18,8 @@ import 'package:matrix/matrix.dart'; mixin DownloadFileOnMobileMixin on State { final downloadManager = getIt.get(); + final storageDirectoryManager = StorageDirectoryManager(); + final downloadFileStateNotifier = ValueNotifier( const NotDownloadPresentationState(), ); @@ -66,15 +69,17 @@ mixin DownloadFileOnMobileMixin on State { } Future checkFileInDownloadsInApp() async { - final filePath = - await StorageDirectoryManager.instance.getFilePathInAppDownloads( + final filePath = await storageDirectoryManager.getFilePathInAppDownloads( eventId: event.eventId, fileName: event.filename, ); - final file = File(filePath); + updateStateIfFileExists(File(filePath)); + } + + Future updateStateIfFileExists(File file) async { if (await file.exists() && await file.length() == event.getFileSize()) { downloadFileStateNotifier.value = DownloadedPresentationState( - filePath: filePath, + filePath: file.path, ); return; } @@ -89,9 +94,15 @@ mixin DownloadFileOnMobileMixin on State { void setupDownloadingProcess(Either resultEvent) { resultEvent.fold( (failure) { - Logs() - .e('$T::setupDownloadingProcess::onDownloadingProcess(): $failure'); - downloadFileStateNotifier.value = const NotDownloadPresentationState(); + Logs().e('MessageDownloadContent::onDownloadingProcess(): $failure'); + if (failure is DownloadFileFailureState && + failure.exception is CancelDownloadingException) { + downloadFileStateNotifier.value = + const NotDownloadPresentationState(); + } else { + downloadFileStateNotifier.value = + DownloadErrorPresentationState(error: failure); + } streamSubscription?.cancel(); }, (success) { diff --git a/test/mixin/download/download_file_on_mobile_mixin_test.dart b/test/mixin/download/download_file_on_mobile_mixin_test.dart new file mode 100644 index 0000000000..11afc9ba40 --- /dev/null +++ b/test/mixin/download/download_file_on_mobile_mixin_test.dart @@ -0,0 +1,257 @@ +import 'dart:io'; + +import 'package:dartz/dartz.dart' hide State, OpenFile; +import 'package:fluffychat/di/global/get_it_initializer.dart'; +import 'package:fluffychat/presentation/model/chat/downloading_state_presentation_model.dart'; +import 'package:fluffychat/utils/exception/downloading_exception.dart'; +import 'package:fluffychat/utils/manager/download_manager/download_file_state.dart'; +import 'package:fluffychat/utils/manager/download_manager/download_manager.dart'; +import 'package:fluffychat/widgets/mixins/download_file_on_mobile_mixin.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:matrix/matrix.dart'; +import 'package:mockito/annotations.dart'; +import 'package:mockito/mockito.dart'; +import 'download_file_on_mobile_mixin_test.mocks.dart'; + +const fakeEventId = "fakeEventId"; +const fakeFilename = "fakeFilename"; + +class MockRoom extends Mock implements Room { + @override + // ignore: hash_and_equals + bool operator ==(dynamic other) { + if (identical(this, other)) return true; + // ignore: unrelated_type_equality_checks + return other is Room && other.id == id; + } + + @override + Map get sendingFilePlaceholders => super.noSuchMethod( + Invocation.getter(#sendingFilePlaceholders), + returnValue: {}, + returnValueForMissingStub: {}, + ); +} + +class MockEvent extends Mock implements Event { + MockEvent(this.fakeRoom); + final Room fakeRoom; + @override + String get eventId => fakeEventId; + + @override + Room get room => fakeRoom; + + @override + Map get infoMap => super.noSuchMethod( + Invocation.getter(#infoMap), + returnValue: {}, + returnValueForMissingStub: {}, + ); +} + +class DummyWidget extends StatefulWidget { + const DummyWidget({required this.event, super.key}); + + final Event event; + + @override + // ignore: no_logic_in_create_state + DummyWidgetState createState() => DummyWidgetState(event); +} + +class DummyWidgetState extends State + with DownloadFileOnMobileMixin { + DummyWidgetState(this.fakeEvent); + + final Event fakeEvent; + + @override + Widget build(BuildContext context) { + return Container(); + } + + @override + Event get event => fakeEvent; +} + +@GenerateNiceMocks([ + MockSpec(), + MockSpec(), +]) +void main() { + group('DownloadFileOnMobileMixin: setupDownloadingProcess', () { + late DummyWidgetState dummyState; + late Event fakeEvent; + late Room fakeRoom; + + setUpAll(() { + getIt.registerSingleton(MockDownloadManager()); + fakeRoom = MockRoom(); + fakeEvent = MockEvent(fakeRoom); + dummyState = DummyWidgetState(fakeEvent); + }); + + tearDownAll(() { + getIt.reset(); + }); + + test('should handle failure', () { + final failure = DownloadFileFailureState(exception: Exception()); + dummyState.setupDownloadingProcess(Left(failure)); + + expect( + dummyState.downloadFileStateNotifier.value, + isInstanceOf(), + ); + }); + + test('should handle cancel', () { + final failure = + DownloadFileFailureState(exception: CancelDownloadingException()); + dummyState.setupDownloadingProcess(Left(failure)); + + expect( + dummyState.downloadFileStateNotifier.value, + isInstanceOf(), + ); + }); + + test('should handle success with DownloadingFileState', () { + const success = DownloadingFileState(receive: 10, total: 100); + dummyState.setupDownloadingProcess(const Right(success)); + + expect( + dummyState.downloadFileStateNotifier.value, + isInstanceOf(), + ); + }); + + test('should handle success with DownloadNativeFileSuccessState', () { + const success = DownloadNativeFileSuccessState(filePath: 'path/to/file'); + dummyState.setupDownloadingProcess(const Right(success)); + + expect( + dummyState.downloadFileStateNotifier.value, + isInstanceOf(), + ); + }); + }); + + group("DownloadFileOnMobileMixin: checkFileExistInMemory", () { + setUpAll(() { + getIt.registerSingleton(MockDownloadManager()); + }); + + tearDownAll(() { + getIt.reset(); + }); + + test('should update downloadFileStateNotifier if file exists in memory', + () { + final fakeRoom = MockRoom(); + final fakeEvent = MockEvent(fakeRoom); + final dummyState = DummyWidgetState(fakeEvent); + + when(fakeRoom.sendingFilePlaceholders).thenReturn({ + fakeEventId: MatrixFile( + name: fakeFilename, + filePath: "path/to/file", + ), + }); + + expect(dummyState.checkFileExistInMemory(), isTrue); + expect( + dummyState.downloadFileStateNotifier.value, + isInstanceOf(), + ); + }); + + test( + 'should not update downloadFileStateNotifier if file does not exist in memory', + () { + final fakeRoom = MockRoom(); + final fakeEvent = MockEvent(fakeRoom); + final dummyState = DummyWidgetState(fakeEvent); + + expect(dummyState.checkFileExistInMemory(), isFalse); + expect( + dummyState.downloadFileStateNotifier.value, + isInstanceOf(), + ); + }); + }); + + group("updateStateIfFileExists", () { + setUpAll(() { + getIt.registerSingleton(MockDownloadManager()); + }); + + tearDownAll(() { + getIt.reset(); + }); + + test( + 'should update downloadFileStateNotifier if file exists in app downloads', + () async { + final fakeRoom = MockRoom(); + final fakeEvent = MockEvent(fakeRoom); + final dummyState = DummyWidgetState(fakeEvent); + + final file = MockFile(); + when(file.exists()).thenAnswer((_) async => true); + when(file.length()).thenAnswer((_) async => 123); + when(fakeEvent.infoMap).thenReturn({'size': 123}); + when(file.path).thenReturn('path/to/file'); + + await dummyState.updateStateIfFileExists(file); + + expect( + dummyState.downloadFileStateNotifier.value, + isInstanceOf(), + ); + }); + + test('should not update downloadFileStateNotifier if file does not exists', + () async { + final fakeRoom = MockRoom(); + final fakeEvent = MockEvent(fakeRoom); + final dummyState = DummyWidgetState(fakeEvent); + + final file = MockFile(); + when(file.exists()).thenAnswer((_) async => false); + when(file.length()).thenAnswer((_) async => 123); + when(fakeEvent.infoMap).thenReturn({'size': 123}); + when(file.path).thenReturn('path/to/file'); + + await dummyState.updateStateIfFileExists(file); + + expect( + dummyState.downloadFileStateNotifier.value, + isInstanceOf(), + ); + }); + + test( + 'should not update downloadFileStateNotifier if file does have the same size as the event', + () async { + final fakeRoom = MockRoom(); + final fakeEvent = MockEvent(fakeRoom); + final dummyState = DummyWidgetState(fakeEvent); + + final file = MockFile(); + when(file.exists()).thenAnswer((_) async => true); + when(file.length()).thenAnswer((_) async => 1234); + when(fakeEvent.infoMap).thenReturn({'size': 123}); + when(file.path).thenReturn('path/to/file'); + + await dummyState.updateStateIfFileExists(file); + + expect( + dummyState.downloadFileStateNotifier.value, + isInstanceOf(), + ); + }); + }); +} diff --git a/test/mixin/download/download_file_on_mobile_mixin_test.mocks.dart b/test/mixin/download/download_file_on_mobile_mixin_test.mocks.dart new file mode 100644 index 0000000000..8db9968b6c --- /dev/null +++ b/test/mixin/download/download_file_on_mobile_mixin_test.mocks.dart @@ -0,0 +1,1054 @@ +// Mocks generated by Mockito 5.4.4 from annotations +// in fluffychat/test/mixin/download/download_file_on_mobile_mixin_test.dart. +// Do not manually edit this file. + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'dart:async' as _i5; +import 'dart:convert' as _i6; +import 'dart:io' as _i2; +import 'dart:typed_data' as _i7; + +import 'package:dartz/dartz.dart' as _i10; +import 'package:fluffychat/app_state/failure.dart' as _i11; +import 'package:fluffychat/app_state/success.dart' as _i12; +import 'package:fluffychat/utils/manager/download_manager/download_file_info.dart' + as _i9; +import 'package:fluffychat/utils/manager/download_manager/download_manager.dart' + as _i8; +import 'package:fluffychat/utils/manager/download_manager/downloading_worker_queue.dart' + as _i3; +import 'package:matrix/matrix.dart' as _i13; +import 'package:mockito/mockito.dart' as _i1; +import 'package:mockito/src/dummies.dart' as _i4; + +// 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: prefer_const_constructors +// ignore_for_file: unnecessary_parenthesis +// ignore_for_file: camel_case_types +// ignore_for_file: subtype_of_sealed_class + +class _FakeFile_0 extends _i1.SmartFake implements _i2.File { + _FakeFile_0( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeUri_1 extends _i1.SmartFake implements Uri { + _FakeUri_1( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeDirectory_2 extends _i1.SmartFake implements _i2.Directory { + _FakeDirectory_2( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeFileSystemEntity_3 extends _i1.SmartFake + implements _i2.FileSystemEntity { + _FakeFileSystemEntity_3( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeDateTime_4 extends _i1.SmartFake implements DateTime { + _FakeDateTime_4( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeRandomAccessFile_5 extends _i1.SmartFake + implements _i2.RandomAccessFile { + _FakeRandomAccessFile_5( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeIOSink_6 extends _i1.SmartFake implements _i2.IOSink { + _FakeIOSink_6( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeFileStat_7 extends _i1.SmartFake implements _i2.FileStat { + _FakeFileStat_7( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeDownloadWorkerQueue_8 extends _i1.SmartFake + implements _i3.DownloadWorkerQueue { + _FakeDownloadWorkerQueue_8( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +/// A class which mocks [File]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockFile extends _i1.Mock implements _i2.File { + @override + _i2.File get absolute => (super.noSuchMethod( + Invocation.getter(#absolute), + returnValue: _FakeFile_0( + this, + Invocation.getter(#absolute), + ), + returnValueForMissingStub: _FakeFile_0( + this, + Invocation.getter(#absolute), + ), + ) as _i2.File); + + @override + String get path => (super.noSuchMethod( + Invocation.getter(#path), + returnValue: _i4.dummyValue( + this, + Invocation.getter(#path), + ), + returnValueForMissingStub: _i4.dummyValue( + this, + Invocation.getter(#path), + ), + ) as String); + + @override + Uri get uri => (super.noSuchMethod( + Invocation.getter(#uri), + returnValue: _FakeUri_1( + this, + Invocation.getter(#uri), + ), + returnValueForMissingStub: _FakeUri_1( + this, + Invocation.getter(#uri), + ), + ) as Uri); + + @override + bool get isAbsolute => (super.noSuchMethod( + Invocation.getter(#isAbsolute), + returnValue: false, + returnValueForMissingStub: false, + ) as bool); + + @override + _i2.Directory get parent => (super.noSuchMethod( + Invocation.getter(#parent), + returnValue: _FakeDirectory_2( + this, + Invocation.getter(#parent), + ), + returnValueForMissingStub: _FakeDirectory_2( + this, + Invocation.getter(#parent), + ), + ) as _i2.Directory); + + @override + _i5.Future<_i2.File> create({ + bool? recursive = false, + bool? exclusive = false, + }) => + (super.noSuchMethod( + Invocation.method( + #create, + [], + { + #recursive: recursive, + #exclusive: exclusive, + }, + ), + returnValue: _i5.Future<_i2.File>.value(_FakeFile_0( + this, + Invocation.method( + #create, + [], + { + #recursive: recursive, + #exclusive: exclusive, + }, + ), + )), + returnValueForMissingStub: _i5.Future<_i2.File>.value(_FakeFile_0( + this, + Invocation.method( + #create, + [], + { + #recursive: recursive, + #exclusive: exclusive, + }, + ), + )), + ) as _i5.Future<_i2.File>); + + @override + void createSync({ + bool? recursive = false, + bool? exclusive = false, + }) => + super.noSuchMethod( + Invocation.method( + #createSync, + [], + { + #recursive: recursive, + #exclusive: exclusive, + }, + ), + returnValueForMissingStub: null, + ); + + @override + _i5.Future<_i2.File> rename(String? newPath) => (super.noSuchMethod( + Invocation.method( + #rename, + [newPath], + ), + returnValue: _i5.Future<_i2.File>.value(_FakeFile_0( + this, + Invocation.method( + #rename, + [newPath], + ), + )), + returnValueForMissingStub: _i5.Future<_i2.File>.value(_FakeFile_0( + this, + Invocation.method( + #rename, + [newPath], + ), + )), + ) as _i5.Future<_i2.File>); + + @override + _i2.File renameSync(String? newPath) => (super.noSuchMethod( + Invocation.method( + #renameSync, + [newPath], + ), + returnValue: _FakeFile_0( + this, + Invocation.method( + #renameSync, + [newPath], + ), + ), + returnValueForMissingStub: _FakeFile_0( + this, + Invocation.method( + #renameSync, + [newPath], + ), + ), + ) as _i2.File); + + @override + _i5.Future<_i2.FileSystemEntity> delete({bool? recursive = false}) => + (super.noSuchMethod( + Invocation.method( + #delete, + [], + {#recursive: recursive}, + ), + returnValue: + _i5.Future<_i2.FileSystemEntity>.value(_FakeFileSystemEntity_3( + this, + Invocation.method( + #delete, + [], + {#recursive: recursive}, + ), + )), + returnValueForMissingStub: + _i5.Future<_i2.FileSystemEntity>.value(_FakeFileSystemEntity_3( + this, + Invocation.method( + #delete, + [], + {#recursive: recursive}, + ), + )), + ) as _i5.Future<_i2.FileSystemEntity>); + + @override + void deleteSync({bool? recursive = false}) => super.noSuchMethod( + Invocation.method( + #deleteSync, + [], + {#recursive: recursive}, + ), + returnValueForMissingStub: null, + ); + + @override + _i5.Future<_i2.File> copy(String? newPath) => (super.noSuchMethod( + Invocation.method( + #copy, + [newPath], + ), + returnValue: _i5.Future<_i2.File>.value(_FakeFile_0( + this, + Invocation.method( + #copy, + [newPath], + ), + )), + returnValueForMissingStub: _i5.Future<_i2.File>.value(_FakeFile_0( + this, + Invocation.method( + #copy, + [newPath], + ), + )), + ) as _i5.Future<_i2.File>); + + @override + _i2.File copySync(String? newPath) => (super.noSuchMethod( + Invocation.method( + #copySync, + [newPath], + ), + returnValue: _FakeFile_0( + this, + Invocation.method( + #copySync, + [newPath], + ), + ), + returnValueForMissingStub: _FakeFile_0( + this, + Invocation.method( + #copySync, + [newPath], + ), + ), + ) as _i2.File); + + @override + _i5.Future length() => (super.noSuchMethod( + Invocation.method( + #length, + [], + ), + returnValue: _i5.Future.value(0), + returnValueForMissingStub: _i5.Future.value(0), + ) as _i5.Future); + + @override + int lengthSync() => (super.noSuchMethod( + Invocation.method( + #lengthSync, + [], + ), + returnValue: 0, + returnValueForMissingStub: 0, + ) as int); + + @override + _i5.Future lastAccessed() => (super.noSuchMethod( + Invocation.method( + #lastAccessed, + [], + ), + returnValue: _i5.Future.value(_FakeDateTime_4( + this, + Invocation.method( + #lastAccessed, + [], + ), + )), + returnValueForMissingStub: _i5.Future.value(_FakeDateTime_4( + this, + Invocation.method( + #lastAccessed, + [], + ), + )), + ) as _i5.Future); + + @override + DateTime lastAccessedSync() => (super.noSuchMethod( + Invocation.method( + #lastAccessedSync, + [], + ), + returnValue: _FakeDateTime_4( + this, + Invocation.method( + #lastAccessedSync, + [], + ), + ), + returnValueForMissingStub: _FakeDateTime_4( + this, + Invocation.method( + #lastAccessedSync, + [], + ), + ), + ) as DateTime); + + @override + _i5.Future setLastAccessed(DateTime? time) => (super.noSuchMethod( + Invocation.method( + #setLastAccessed, + [time], + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + + @override + void setLastAccessedSync(DateTime? time) => super.noSuchMethod( + Invocation.method( + #setLastAccessedSync, + [time], + ), + returnValueForMissingStub: null, + ); + + @override + _i5.Future lastModified() => (super.noSuchMethod( + Invocation.method( + #lastModified, + [], + ), + returnValue: _i5.Future.value(_FakeDateTime_4( + this, + Invocation.method( + #lastModified, + [], + ), + )), + returnValueForMissingStub: _i5.Future.value(_FakeDateTime_4( + this, + Invocation.method( + #lastModified, + [], + ), + )), + ) as _i5.Future); + + @override + DateTime lastModifiedSync() => (super.noSuchMethod( + Invocation.method( + #lastModifiedSync, + [], + ), + returnValue: _FakeDateTime_4( + this, + Invocation.method( + #lastModifiedSync, + [], + ), + ), + returnValueForMissingStub: _FakeDateTime_4( + this, + Invocation.method( + #lastModifiedSync, + [], + ), + ), + ) as DateTime); + + @override + _i5.Future setLastModified(DateTime? time) => (super.noSuchMethod( + Invocation.method( + #setLastModified, + [time], + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + + @override + void setLastModifiedSync(DateTime? time) => super.noSuchMethod( + Invocation.method( + #setLastModifiedSync, + [time], + ), + returnValueForMissingStub: null, + ); + + @override + _i5.Future<_i2.RandomAccessFile> open( + {_i2.FileMode? mode = _i2.FileMode.read}) => + (super.noSuchMethod( + Invocation.method( + #open, + [], + {#mode: mode}, + ), + returnValue: + _i5.Future<_i2.RandomAccessFile>.value(_FakeRandomAccessFile_5( + this, + Invocation.method( + #open, + [], + {#mode: mode}, + ), + )), + returnValueForMissingStub: + _i5.Future<_i2.RandomAccessFile>.value(_FakeRandomAccessFile_5( + this, + Invocation.method( + #open, + [], + {#mode: mode}, + ), + )), + ) as _i5.Future<_i2.RandomAccessFile>); + + @override + _i2.RandomAccessFile openSync({_i2.FileMode? mode = _i2.FileMode.read}) => + (super.noSuchMethod( + Invocation.method( + #openSync, + [], + {#mode: mode}, + ), + returnValue: _FakeRandomAccessFile_5( + this, + Invocation.method( + #openSync, + [], + {#mode: mode}, + ), + ), + returnValueForMissingStub: _FakeRandomAccessFile_5( + this, + Invocation.method( + #openSync, + [], + {#mode: mode}, + ), + ), + ) as _i2.RandomAccessFile); + + @override + _i5.Stream> openRead([ + int? start, + int? end, + ]) => + (super.noSuchMethod( + Invocation.method( + #openRead, + [ + start, + end, + ], + ), + returnValue: _i5.Stream>.empty(), + returnValueForMissingStub: _i5.Stream>.empty(), + ) as _i5.Stream>); + + @override + _i2.IOSink openWrite({ + _i2.FileMode? mode = _i2.FileMode.write, + _i6.Encoding? encoding = const _i6.Utf8Codec(), + }) => + (super.noSuchMethod( + Invocation.method( + #openWrite, + [], + { + #mode: mode, + #encoding: encoding, + }, + ), + returnValue: _FakeIOSink_6( + this, + Invocation.method( + #openWrite, + [], + { + #mode: mode, + #encoding: encoding, + }, + ), + ), + returnValueForMissingStub: _FakeIOSink_6( + this, + Invocation.method( + #openWrite, + [], + { + #mode: mode, + #encoding: encoding, + }, + ), + ), + ) as _i2.IOSink); + + @override + _i5.Future<_i7.Uint8List> readAsBytes() => (super.noSuchMethod( + Invocation.method( + #readAsBytes, + [], + ), + returnValue: _i5.Future<_i7.Uint8List>.value(_i7.Uint8List(0)), + returnValueForMissingStub: + _i5.Future<_i7.Uint8List>.value(_i7.Uint8List(0)), + ) as _i5.Future<_i7.Uint8List>); + + @override + _i7.Uint8List readAsBytesSync() => (super.noSuchMethod( + Invocation.method( + #readAsBytesSync, + [], + ), + returnValue: _i7.Uint8List(0), + returnValueForMissingStub: _i7.Uint8List(0), + ) as _i7.Uint8List); + + @override + _i5.Future readAsString( + {_i6.Encoding? encoding = const _i6.Utf8Codec()}) => + (super.noSuchMethod( + Invocation.method( + #readAsString, + [], + {#encoding: encoding}, + ), + returnValue: _i5.Future.value(_i4.dummyValue( + this, + Invocation.method( + #readAsString, + [], + {#encoding: encoding}, + ), + )), + returnValueForMissingStub: + _i5.Future.value(_i4.dummyValue( + this, + Invocation.method( + #readAsString, + [], + {#encoding: encoding}, + ), + )), + ) as _i5.Future); + + @override + String readAsStringSync({_i6.Encoding? encoding = const _i6.Utf8Codec()}) => + (super.noSuchMethod( + Invocation.method( + #readAsStringSync, + [], + {#encoding: encoding}, + ), + returnValue: _i4.dummyValue( + this, + Invocation.method( + #readAsStringSync, + [], + {#encoding: encoding}, + ), + ), + returnValueForMissingStub: _i4.dummyValue( + this, + Invocation.method( + #readAsStringSync, + [], + {#encoding: encoding}, + ), + ), + ) as String); + + @override + _i5.Future> readAsLines( + {_i6.Encoding? encoding = const _i6.Utf8Codec()}) => + (super.noSuchMethod( + Invocation.method( + #readAsLines, + [], + {#encoding: encoding}, + ), + returnValue: _i5.Future>.value([]), + returnValueForMissingStub: _i5.Future>.value([]), + ) as _i5.Future>); + + @override + List readAsLinesSync( + {_i6.Encoding? encoding = const _i6.Utf8Codec()}) => + (super.noSuchMethod( + Invocation.method( + #readAsLinesSync, + [], + {#encoding: encoding}, + ), + returnValue: [], + returnValueForMissingStub: [], + ) as List); + + @override + _i5.Future<_i2.File> writeAsBytes( + List? bytes, { + _i2.FileMode? mode = _i2.FileMode.write, + bool? flush = false, + }) => + (super.noSuchMethod( + Invocation.method( + #writeAsBytes, + [bytes], + { + #mode: mode, + #flush: flush, + }, + ), + returnValue: _i5.Future<_i2.File>.value(_FakeFile_0( + this, + Invocation.method( + #writeAsBytes, + [bytes], + { + #mode: mode, + #flush: flush, + }, + ), + )), + returnValueForMissingStub: _i5.Future<_i2.File>.value(_FakeFile_0( + this, + Invocation.method( + #writeAsBytes, + [bytes], + { + #mode: mode, + #flush: flush, + }, + ), + )), + ) as _i5.Future<_i2.File>); + + @override + void writeAsBytesSync( + List? bytes, { + _i2.FileMode? mode = _i2.FileMode.write, + bool? flush = false, + }) => + super.noSuchMethod( + Invocation.method( + #writeAsBytesSync, + [bytes], + { + #mode: mode, + #flush: flush, + }, + ), + returnValueForMissingStub: null, + ); + + @override + _i5.Future<_i2.File> writeAsString( + String? contents, { + _i2.FileMode? mode = _i2.FileMode.write, + _i6.Encoding? encoding = const _i6.Utf8Codec(), + bool? flush = false, + }) => + (super.noSuchMethod( + Invocation.method( + #writeAsString, + [contents], + { + #mode: mode, + #encoding: encoding, + #flush: flush, + }, + ), + returnValue: _i5.Future<_i2.File>.value(_FakeFile_0( + this, + Invocation.method( + #writeAsString, + [contents], + { + #mode: mode, + #encoding: encoding, + #flush: flush, + }, + ), + )), + returnValueForMissingStub: _i5.Future<_i2.File>.value(_FakeFile_0( + this, + Invocation.method( + #writeAsString, + [contents], + { + #mode: mode, + #encoding: encoding, + #flush: flush, + }, + ), + )), + ) as _i5.Future<_i2.File>); + + @override + void writeAsStringSync( + String? contents, { + _i2.FileMode? mode = _i2.FileMode.write, + _i6.Encoding? encoding = const _i6.Utf8Codec(), + bool? flush = false, + }) => + super.noSuchMethod( + Invocation.method( + #writeAsStringSync, + [contents], + { + #mode: mode, + #encoding: encoding, + #flush: flush, + }, + ), + returnValueForMissingStub: null, + ); + + @override + _i5.Future exists() => (super.noSuchMethod( + Invocation.method( + #exists, + [], + ), + returnValue: _i5.Future.value(false), + returnValueForMissingStub: _i5.Future.value(false), + ) as _i5.Future); + + @override + bool existsSync() => (super.noSuchMethod( + Invocation.method( + #existsSync, + [], + ), + returnValue: false, + returnValueForMissingStub: false, + ) as bool); + + @override + _i5.Future resolveSymbolicLinks() => (super.noSuchMethod( + Invocation.method( + #resolveSymbolicLinks, + [], + ), + returnValue: _i5.Future.value(_i4.dummyValue( + this, + Invocation.method( + #resolveSymbolicLinks, + [], + ), + )), + returnValueForMissingStub: + _i5.Future.value(_i4.dummyValue( + this, + Invocation.method( + #resolveSymbolicLinks, + [], + ), + )), + ) as _i5.Future); + + @override + String resolveSymbolicLinksSync() => (super.noSuchMethod( + Invocation.method( + #resolveSymbolicLinksSync, + [], + ), + returnValue: _i4.dummyValue( + this, + Invocation.method( + #resolveSymbolicLinksSync, + [], + ), + ), + returnValueForMissingStub: _i4.dummyValue( + this, + Invocation.method( + #resolveSymbolicLinksSync, + [], + ), + ), + ) as String); + + @override + _i5.Future<_i2.FileStat> stat() => (super.noSuchMethod( + Invocation.method( + #stat, + [], + ), + returnValue: _i5.Future<_i2.FileStat>.value(_FakeFileStat_7( + this, + Invocation.method( + #stat, + [], + ), + )), + returnValueForMissingStub: + _i5.Future<_i2.FileStat>.value(_FakeFileStat_7( + this, + Invocation.method( + #stat, + [], + ), + )), + ) as _i5.Future<_i2.FileStat>); + + @override + _i2.FileStat statSync() => (super.noSuchMethod( + Invocation.method( + #statSync, + [], + ), + returnValue: _FakeFileStat_7( + this, + Invocation.method( + #statSync, + [], + ), + ), + returnValueForMissingStub: _FakeFileStat_7( + this, + Invocation.method( + #statSync, + [], + ), + ), + ) as _i2.FileStat); + + @override + _i5.Stream<_i2.FileSystemEvent> watch({ + int? events = 15, + bool? recursive = false, + }) => + (super.noSuchMethod( + Invocation.method( + #watch, + [], + { + #events: events, + #recursive: recursive, + }, + ), + returnValue: _i5.Stream<_i2.FileSystemEvent>.empty(), + returnValueForMissingStub: _i5.Stream<_i2.FileSystemEvent>.empty(), + ) as _i5.Stream<_i2.FileSystemEvent>); +} + +/// A class which mocks [DownloadManager]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockDownloadManager extends _i1.Mock implements _i8.DownloadManager { + @override + _i3.DownloadWorkerQueue get workingQueue => (super.noSuchMethod( + Invocation.getter(#workingQueue), + returnValue: _FakeDownloadWorkerQueue_8( + this, + Invocation.getter(#workingQueue), + ), + returnValueForMissingStub: _FakeDownloadWorkerQueue_8( + this, + Invocation.getter(#workingQueue), + ), + ) as _i3.DownloadWorkerQueue); + + @override + Map get eventIdMapDownloadFileInfo => + (super.noSuchMethod( + Invocation.getter(#eventIdMapDownloadFileInfo), + returnValue: {}, + returnValueForMissingStub: {}, + ) as Map); + + @override + void cancelDownload(String? eventId) => super.noSuchMethod( + Invocation.method( + #cancelDownload, + [eventId], + ), + returnValueForMissingStub: null, + ); + + @override + _i5.Stream<_i10.Either<_i11.Failure, _i12.Success>>? getDownloadStateStream( + String? eventId) => + (super.noSuchMethod( + Invocation.method( + #getDownloadStateStream, + [eventId], + ), + returnValueForMissingStub: null, + ) as _i5.Stream<_i10.Either<_i11.Failure, _i12.Success>>?); + + @override + _i5.Future clear(String? eventId) => (super.noSuchMethod( + Invocation.method( + #clear, + [eventId], + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + + @override + _i5.Future download({ + required _i13.Event? event, + bool? getThumbnail = false, + bool? isFirstPriority = false, + }) => + (super.noSuchMethod( + Invocation.method( + #download, + [], + { + #event: event, + #getThumbnail: getThumbnail, + #isFirstPriority: isFirstPriority, + }, + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); +}