From 6980f203a2000d9b0cba8c7c1ea1d9a2a133d9d2 Mon Sep 17 00:00:00 2001 From: Mati Date: Fri, 15 Sep 2023 18:41:55 -0300 Subject: [PATCH 1/7] feat(create drive form): adds a description of the selected drive privacy PE-4597 --- .../drive_create/drive_create_cubit.dart | 23 +++++++++++---- .../drive_create/drive_create_state.dart | 13 ++++++++- lib/components/drive_create_form.dart | 29 +++++++++++++++++-- lib/l10n/app_en.arb | 8 +++++ 4 files changed, 64 insertions(+), 9 deletions(-) diff --git a/lib/blocs/drive_create/drive_create_cubit.dart b/lib/blocs/drive_create/drive_create_cubit.dart index 208c10a5da..0ecf864ca3 100644 --- a/lib/blocs/drive_create/drive_create_cubit.dart +++ b/lib/blocs/drive_create/drive_create_cubit.dart @@ -1,5 +1,9 @@ import 'package:ardrive/blocs/blocs.dart'; -import 'package:ardrive/entities/entities.dart'; +import 'package:ardrive/core/arfs/entities/arfs_entities.dart' + show DrivePrivacy; +import 'package:ardrive/entities/constants.dart' as constants; +import 'package:ardrive/entities/drive_entity.dart'; +import 'package:ardrive/entities/folder_entity.dart'; import 'package:ardrive/models/models.dart'; import 'package:ardrive/services/services.dart'; import 'package:ardrive/turbo/services/upload_service.dart'; @@ -15,7 +19,9 @@ part 'drive_create_state.dart'; class DriveCreateCubit extends Cubit { final form = FormGroup({ 'privacy': FormControl( - value: DrivePrivacy.private, validators: [Validators.required]), + value: DrivePrivacy.private.name, + validators: [Validators.required], + ), }); final ArweaveService _arweave; @@ -35,7 +41,14 @@ class DriveCreateCubit extends Cubit { _driveDao = driveDao, _profileCubit = profileCubit, _drivesCubit = drivesCubit, - super(DriveCreateInitial()); + super(DriveCreateInitial(privacy: DrivePrivacy.private)); + + void onPrivacyChanged() { + final privacy = form.control('privacy').value == DrivePrivacy.private.name + ? DrivePrivacy.private + : DrivePrivacy.public; + emit((state as DriveCreateInitial).copyWith(privacy: privacy)); + } Future submit( String driveName, @@ -72,8 +85,8 @@ class DriveCreateCubit extends Cubit { name: driveName, rootFolderId: createRes.rootFolderId, privacy: drivePrivacy, - authMode: drivePrivacy == DrivePrivacy.private - ? DriveAuthMode.password + authMode: drivePrivacy == constants.DrivePrivacy.private + ? constants.DriveAuthMode.password : null, ); diff --git a/lib/blocs/drive_create/drive_create_state.dart b/lib/blocs/drive_create/drive_create_state.dart index ac3d115a4e..4b0a6048e9 100644 --- a/lib/blocs/drive_create/drive_create_state.dart +++ b/lib/blocs/drive_create/drive_create_state.dart @@ -6,7 +6,18 @@ abstract class DriveCreateState extends Equatable { List get props => []; } -class DriveCreateInitial extends DriveCreateState {} +class DriveCreateInitial extends DriveCreateState { + final DrivePrivacy privacy; + + DriveCreateInitial({required this.privacy}); + + DriveCreateInitial copyWith({DrivePrivacy? privacy}) { + return DriveCreateInitial(privacy: privacy ?? this.privacy); + } + + @override + List get props => [privacy]; +} class DriveCreateZeroBalance extends DriveCreateState {} diff --git a/lib/components/drive_create_form.dart b/lib/components/drive_create_form.dart index 0645db6002..0aa1efe782 100644 --- a/lib/components/drive_create_form.dart +++ b/lib/components/drive_create_form.dart @@ -1,4 +1,5 @@ import 'package:ardrive/blocs/blocs.dart'; +import 'package:ardrive/core/arfs/entities/arfs_entities.dart'; import 'package:ardrive/l11n/l11n.dart'; import 'package:ardrive/models/models.dart'; import 'package:ardrive/pages/congestion_warning_wrapper.dart'; @@ -73,6 +74,9 @@ class _DriveCreateFormState extends State { ], ); } else { + final stateAsInitial = state as DriveCreateInitial; + final privacy = stateAsInitial.privacy; + return ArDriveStandardModal( title: appLocalizationsOf(context).createDriveEmphasized, content: SizedBox( @@ -108,24 +112,43 @@ class _DriveCreateFormState extends State { ReactiveDropdownField( formControlName: 'privacy', decoration: InputDecoration( - labelText: appLocalizationsOf(context).privacy), + labelText: appLocalizationsOf(context).privacy, + ), showErrors: (control) => control.dirty && control.invalid, validationMessages: kValidationMessages(appLocalizationsOf(context)), items: [ DropdownMenuItem( - value: 'public', + value: DrivePrivacy.public.name, child: Text(appLocalizationsOf(context).public), ), DropdownMenuItem( - value: 'private', + value: DrivePrivacy.private.name, child: Text( appLocalizationsOf(context).private, ), ) ], + onChanged: (_) { + context.read().onPrivacyChanged(); + }, ), + const SizedBox(height: 32), + Row(children: [ + if (privacy == DrivePrivacy.private) + Flexible( + child: Text( + appLocalizationsOf(context) + .drivePrivacyDescriptionPrivate, + )) + else + Flexible( + child: Text( + appLocalizationsOf(context) + .drivePrivacyDescriptionPublic, + )) + ]), ], ), ), diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 0619f9786b..a3e2c9823a 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -519,6 +519,14 @@ "@driveName": { "description": "The name of certain drive" }, + "drivePrivacyDescriptionPrivate": "Private Drives offer state-of-the-art security, you control access.", + "@drivePrivacyDescriptionPrivate": { + "description": "Explains private drives." + }, + "drivePrivacyDescriptionPublic": "Public Drives are discoverable, others can find and view the contents.", + "@drivePrivacyDescriptionPublic": { + "description": "Explains public drives." + }, "driveRoot": "Drive root", "@driveRoot": { "description": "The folder entity that is at the top of the folder hierarchy" From 68a11d010a271eb5888cf95099b50750d1aaffd8 Mon Sep 17 00:00:00 2001 From: Mati Date: Tue, 19 Sep 2023 12:47:08 -0300 Subject: [PATCH 2/7] feat(create drive cubit): fixes bad casting PE-4597 --- .../drive_create/drive_create_cubit.dart | 14 ++--- .../drive_create/drive_create_state.dart | 59 +++++++++++++++---- lib/components/drive_create_form.dart | 3 +- 3 files changed, 57 insertions(+), 19 deletions(-) diff --git a/lib/blocs/drive_create/drive_create_cubit.dart b/lib/blocs/drive_create/drive_create_cubit.dart index 0ecf864ca3..7050d2e5f7 100644 --- a/lib/blocs/drive_create/drive_create_cubit.dart +++ b/lib/blocs/drive_create/drive_create_cubit.dart @@ -41,13 +41,13 @@ class DriveCreateCubit extends Cubit { _driveDao = driveDao, _profileCubit = profileCubit, _drivesCubit = drivesCubit, - super(DriveCreateInitial(privacy: DrivePrivacy.private)); + super(const DriveCreateInitial(privacy: DrivePrivacy.private)); void onPrivacyChanged() { final privacy = form.control('privacy').value == DrivePrivacy.private.name ? DrivePrivacy.private : DrivePrivacy.public; - emit((state as DriveCreateInitial).copyWith(privacy: privacy)); + emit(state.copyWith(privacy: privacy)); } Future submit( @@ -55,18 +55,18 @@ class DriveCreateCubit extends Cubit { ) async { final profile = _profileCubit.state as ProfileLoggedIn; if (await _profileCubit.logoutIfWalletMismatch()) { - emit(DriveCreateWalletMismatch()); + emit(DriveCreateWalletMismatch(privacy: state.privacy)); return; } final minimumWalletBalance = BigInt.from(10000000); if (profile.walletBalance <= minimumWalletBalance && !_turboUploadService.useTurboUpload) { - emit(DriveCreateZeroBalance()); + emit(DriveCreateZeroBalance(privacy: state.privacy)); return; } - emit(DriveCreateInProgress()); + emit(DriveCreateInProgress(privacy: state.privacy)); try { final String drivePrivacy = form.control('privacy').value; @@ -153,12 +153,12 @@ class DriveCreateCubit extends Cubit { addError(err); } - emit(DriveCreateSuccess()); + emit(DriveCreateSuccess(privacy: state.privacy)); } @override void onError(Object error, StackTrace stackTrace) { - emit(DriveCreateFailure()); + emit(DriveCreateFailure(privacy: state.privacy)); super.onError(error, stackTrace); logger.e('Failed to create drive', error, stackTrace); diff --git a/lib/blocs/drive_create/drive_create_state.dart b/lib/blocs/drive_create/drive_create_state.dart index 4b0a6048e9..7c07247a49 100644 --- a/lib/blocs/drive_create/drive_create_state.dart +++ b/lib/blocs/drive_create/drive_create_state.dart @@ -2,29 +2,68 @@ part of 'drive_create_cubit.dart'; @immutable abstract class DriveCreateState extends Equatable { + final DrivePrivacy privacy; + + const DriveCreateState({required this.privacy}); + + DriveCreateState copyWith({DrivePrivacy? privacy}) { + throw UnimplementedError(); + } + @override - List get props => []; + List get props => [privacy]; } class DriveCreateInitial extends DriveCreateState { - final DrivePrivacy privacy; - - DriveCreateInitial({required this.privacy}); + const DriveCreateInitial({required super.privacy}); + @override DriveCreateInitial copyWith({DrivePrivacy? privacy}) { return DriveCreateInitial(privacy: privacy ?? this.privacy); } +} + +class DriveCreateZeroBalance extends DriveCreateState { + const DriveCreateZeroBalance({required super.privacy}); @override - List get props => [privacy]; + DriveCreateZeroBalance copyWith({DrivePrivacy? privacy}) { + return DriveCreateZeroBalance(privacy: privacy ?? this.privacy); + } +} + +class DriveCreateInProgress extends DriveCreateState { + const DriveCreateInProgress({required super.privacy}); + + @override + DriveCreateInProgress copyWith({DrivePrivacy? privacy}) { + return DriveCreateInProgress(privacy: privacy ?? this.privacy); + } } -class DriveCreateZeroBalance extends DriveCreateState {} +class DriveCreateSuccess extends DriveCreateState { + const DriveCreateSuccess({required super.privacy}); + + @override + DriveCreateSuccess copyWith({DrivePrivacy? privacy}) { + return DriveCreateSuccess(privacy: privacy ?? this.privacy); + } +} -class DriveCreateInProgress extends DriveCreateState {} +class DriveCreateFailure extends DriveCreateState { + const DriveCreateFailure({required super.privacy}); -class DriveCreateSuccess extends DriveCreateState {} + @override + DriveCreateFailure copyWith({DrivePrivacy? privacy}) { + return DriveCreateFailure(privacy: privacy ?? this.privacy); + } +} -class DriveCreateFailure extends DriveCreateState {} +class DriveCreateWalletMismatch extends DriveCreateState { + const DriveCreateWalletMismatch({required super.privacy}); -class DriveCreateWalletMismatch extends DriveCreateState {} + @override + DriveCreateWalletMismatch copyWith({DrivePrivacy? privacy}) { + return DriveCreateWalletMismatch(privacy: privacy ?? this.privacy); + } +} diff --git a/lib/components/drive_create_form.dart b/lib/components/drive_create_form.dart index 0aa1efe782..5800b22c93 100644 --- a/lib/components/drive_create_form.dart +++ b/lib/components/drive_create_form.dart @@ -74,8 +74,7 @@ class _DriveCreateFormState extends State { ], ); } else { - final stateAsInitial = state as DriveCreateInitial; - final privacy = stateAsInitial.privacy; + final privacy = state.privacy; return ArDriveStandardModal( title: appLocalizationsOf(context).createDriveEmphasized, From c90af0424e7545ac000a5702e7ec33e0be94fbcf Mon Sep 17 00:00:00 2001 From: Mati Date: Tue, 19 Sep 2023 12:47:36 -0300 Subject: [PATCH 3/7] test(create drive cubit): attempts to fix skipped test PE-4597 --- test/blocs/drive_create_cubit_test.dart | 235 +++++++++++++----------- 1 file changed, 132 insertions(+), 103 deletions(-) diff --git a/test/blocs/drive_create_cubit_test.dart b/test/blocs/drive_create_cubit_test.dart index 97c7694b6b..8ff7e10435 100644 --- a/test/blocs/drive_create_cubit_test.dart +++ b/test/blocs/drive_create_cubit_test.dart @@ -1,12 +1,11 @@ @Tags(['broken']) import 'package:ardrive/blocs/blocs.dart'; -import 'package:ardrive/core/crypto/crypto.dart'; -import 'package:ardrive/entities/entities.dart'; +import 'package:ardrive/core/arfs/entities/arfs_entities.dart'; +import 'package:ardrive/entities/entity.dart'; import 'package:ardrive/models/models.dart'; import 'package:ardrive/services/services.dart'; import 'package:ardrive/turbo/services/upload_service.dart'; -import 'package:ardrive/utils/app_flavors.dart'; import 'package:ardrive/utils/app_platform.dart'; import 'package:arweave/arweave.dart'; import 'package:bloc_test/bloc_test.dart'; @@ -19,109 +18,139 @@ import 'package:test/test.dart'; import '../test_utils/fakes.dart'; import '../test_utils/utils.dart'; +class FakeEntity extends Fake implements Entity {} + void main() { - group('DriveCreateCubit', () { - late Database db; - late DriveDao driveDao; - - late ArweaveService arweave; - late TurboUploadService turboUploadService; - late DrivesCubit drivesCubit; - late ProfileCubit profileCubit; - late DriveCreateCubit driveCreateCubit; - - const validDriveName = 'valid-drive-name'; - - setUp(() async { - registerFallbackValue(DrivesStateFake()); - registerFallbackValue(ProfileStateFake()); - - db = getTestDb(); - driveDao = db.driveDao; - final configService = ConfigService( - appFlavors: AppFlavors(MockEnvFetcher()), - configFetcher: MockConfigFetcher()); - final config = await configService.loadConfig(); - - AppPlatform.setMockPlatform(platform: SystemPlatform.unknown); - arweave = ArweaveService( - Arweave(gatewayUrl: Uri.parse(config.defaultArweaveGatewayUrl!)), - ArDriveCrypto(), + group( + 'DriveCreateCubit', + () { + late Database db; + late DriveDao driveDao; + + late ArweaveService arweave; + late TurboUploadService turboUploadService; + late DrivesCubit drivesCubit; + late ProfileCubit profileCubit; + late DriveCreateCubit driveCreateCubit; + + late Wallet wallet; + + const validDriveName = 'valid-drive-name'; + + setUp(() async { + wallet = getTestWallet(); + + registerFallbackValue(DrivesStateFake()); + registerFallbackValue(ProfileStateFake()); + registerFallbackValue(DataBundle(blob: Uint8List.fromList([]))); + registerFallbackValue(wallet); + registerFallbackValue(FakeEntity()); + + db = getTestDb(); + driveDao = db.driveDao; + AppPlatform.setMockPlatform(platform: SystemPlatform.unknown); + arweave = MockArweaveService(); + turboUploadService = DontUseUploadService(); + drivesCubit = MockDrivesCubit(); + profileCubit = MockProfileCubit(); + + final walletAddress = await wallet.getAddress(); + final walletOwner = await wallet.getAddress(); + + final keyBytes = Uint8List(32); + fillBytesWithSecureRandom(keyBytes); + + when(() => profileCubit.state).thenReturn( + ProfileLoggedIn( + username: 'Test', + password: '123', + wallet: wallet, + walletAddress: walletAddress, + walletBalance: BigInt.from(10000001), + cipherKey: SecretKey(keyBytes), + useTurbo: turboUploadService.useTurboUpload, + ), + ); + + when(() => profileCubit.logoutIfWalletMismatch()).thenAnswer( + (invocation) => Future.value(false), + ); + + when(() => arweave.prepareBundledDataItem(any(), any())).thenAnswer( + (invocation) => Future.value( + DataItem.withBlobData( + owner: walletOwner, + data: Uint8List.fromList([]), + ), + ), + ); + + when(() => arweave.prepareEntityDataItem(any(), any())).thenAnswer( + (invocation) => Future.value( + DataItem.withBlobData( + owner: walletOwner, + data: Uint8List.fromList([]), + ), + ), + ); + + driveCreateCubit = DriveCreateCubit( + arweave: arweave, + turboUploadService: turboUploadService, + driveDao: driveDao, + drivesCubit: drivesCubit, + profileCubit: profileCubit, + ); + }); + + tearDown(() async { + await db.close(); + }); + + blocTest( + 'create public drive', + build: () => driveCreateCubit, + act: (bloc) async { + bloc.form.value = { + 'name': validDriveName, + 'privacy': DrivePrivacy.public.name, + }; + await bloc.submit(''); + }, + expect: () => [ + const DriveCreateInProgress(privacy: DrivePrivacy.public), + const DriveCreateSuccess(privacy: DrivePrivacy.public), + ], + verify: (_) {}, ); - turboUploadService = DontUseUploadService(); - drivesCubit = MockDrivesCubit(); - profileCubit = MockProfileCubit(); - - final wallet = getTestWallet(); - final walletAddress = await wallet.getAddress(); - - final keyBytes = Uint8List(32); - fillBytesWithSecureRandom(keyBytes); - - when(() => profileCubit.state).thenReturn( - ProfileLoggedIn( - username: 'Test', - password: '123', - wallet: wallet, - walletAddress: walletAddress, - walletBalance: BigInt.one, - cipherKey: SecretKey(keyBytes), - useTurbo: turboUploadService.useTurboUpload, - ), + + blocTest( + 'create private drive', + build: () => driveCreateCubit, + act: (bloc) async { + bloc.form.value = { + 'name': validDriveName, + 'privacy': DrivePrivacy.private.name, + }; + + bloc.onPrivacyChanged(); + + await bloc.submit(''); + }, + expect: () => [ + const DriveCreateInProgress(privacy: DrivePrivacy.public), + const DriveCreateInProgress(privacy: DrivePrivacy.private), + const DriveCreateSuccess(privacy: DrivePrivacy.private), + ], + verify: (_) {}, ); - driveCreateCubit = DriveCreateCubit( - arweave: arweave, - turboUploadService: turboUploadService, - driveDao: driveDao, - drivesCubit: drivesCubit, - profileCubit: profileCubit, + blocTest( + 'does nothing when submitted without valid form', + build: () => driveCreateCubit, + act: (bloc) => bloc.submit(''), + expect: () => [], ); - }); - - tearDown(() async { - await db.close(); - }); - - blocTest( - 'create public drive', - build: () => driveCreateCubit, - act: (bloc) async { - bloc.form.value = { - 'name': validDriveName, - 'privacy': DrivePrivacy.public, - }; - await bloc.submit(''); - }, - expect: () => [ - DriveCreateInProgress(), - DriveCreateSuccess(), - ], - verify: (_) {}, - ); - - blocTest( - 'create private drive', - build: () => driveCreateCubit, - act: (bloc) async { - bloc.form.value = { - 'name': validDriveName, - 'privacy': DrivePrivacy.private, - }; - await bloc.submit(''); - }, - expect: () => [ - DriveCreateInProgress(), - DriveCreateSuccess(), - ], - verify: (_) {}, - ); - - blocTest( - 'does nothing when submitted without valid form', - build: () => driveCreateCubit, - act: (bloc) => bloc.submit(''), - expect: () => [], - ); - }, skip: 'Needs to update the tests'); + }, + ); } From b1033afb4734dd76bc356fab4dfdaf60d58e85c8 Mon Sep 17 00:00:00 2001 From: Mati Date: Tue, 19 Sep 2023 12:53:08 -0300 Subject: [PATCH 4/7] Revert "feat(create drive cubit): fixes bad casting PE-4597" This reverts commit 68a11d010a271eb5888cf95099b50750d1aaffd8. --- .../drive_create/drive_create_cubit.dart | 14 ++--- .../drive_create/drive_create_state.dart | 59 ++++--------------- lib/components/drive_create_form.dart | 3 +- 3 files changed, 19 insertions(+), 57 deletions(-) diff --git a/lib/blocs/drive_create/drive_create_cubit.dart b/lib/blocs/drive_create/drive_create_cubit.dart index 7050d2e5f7..0ecf864ca3 100644 --- a/lib/blocs/drive_create/drive_create_cubit.dart +++ b/lib/blocs/drive_create/drive_create_cubit.dart @@ -41,13 +41,13 @@ class DriveCreateCubit extends Cubit { _driveDao = driveDao, _profileCubit = profileCubit, _drivesCubit = drivesCubit, - super(const DriveCreateInitial(privacy: DrivePrivacy.private)); + super(DriveCreateInitial(privacy: DrivePrivacy.private)); void onPrivacyChanged() { final privacy = form.control('privacy').value == DrivePrivacy.private.name ? DrivePrivacy.private : DrivePrivacy.public; - emit(state.copyWith(privacy: privacy)); + emit((state as DriveCreateInitial).copyWith(privacy: privacy)); } Future submit( @@ -55,18 +55,18 @@ class DriveCreateCubit extends Cubit { ) async { final profile = _profileCubit.state as ProfileLoggedIn; if (await _profileCubit.logoutIfWalletMismatch()) { - emit(DriveCreateWalletMismatch(privacy: state.privacy)); + emit(DriveCreateWalletMismatch()); return; } final minimumWalletBalance = BigInt.from(10000000); if (profile.walletBalance <= minimumWalletBalance && !_turboUploadService.useTurboUpload) { - emit(DriveCreateZeroBalance(privacy: state.privacy)); + emit(DriveCreateZeroBalance()); return; } - emit(DriveCreateInProgress(privacy: state.privacy)); + emit(DriveCreateInProgress()); try { final String drivePrivacy = form.control('privacy').value; @@ -153,12 +153,12 @@ class DriveCreateCubit extends Cubit { addError(err); } - emit(DriveCreateSuccess(privacy: state.privacy)); + emit(DriveCreateSuccess()); } @override void onError(Object error, StackTrace stackTrace) { - emit(DriveCreateFailure(privacy: state.privacy)); + emit(DriveCreateFailure()); super.onError(error, stackTrace); logger.e('Failed to create drive', error, stackTrace); diff --git a/lib/blocs/drive_create/drive_create_state.dart b/lib/blocs/drive_create/drive_create_state.dart index 7c07247a49..4b0a6048e9 100644 --- a/lib/blocs/drive_create/drive_create_state.dart +++ b/lib/blocs/drive_create/drive_create_state.dart @@ -2,68 +2,29 @@ part of 'drive_create_cubit.dart'; @immutable abstract class DriveCreateState extends Equatable { - final DrivePrivacy privacy; - - const DriveCreateState({required this.privacy}); - - DriveCreateState copyWith({DrivePrivacy? privacy}) { - throw UnimplementedError(); - } - @override - List get props => [privacy]; + List get props => []; } class DriveCreateInitial extends DriveCreateState { - const DriveCreateInitial({required super.privacy}); + final DrivePrivacy privacy; + + DriveCreateInitial({required this.privacy}); - @override DriveCreateInitial copyWith({DrivePrivacy? privacy}) { return DriveCreateInitial(privacy: privacy ?? this.privacy); } -} - -class DriveCreateZeroBalance extends DriveCreateState { - const DriveCreateZeroBalance({required super.privacy}); - - @override - DriveCreateZeroBalance copyWith({DrivePrivacy? privacy}) { - return DriveCreateZeroBalance(privacy: privacy ?? this.privacy); - } -} - -class DriveCreateInProgress extends DriveCreateState { - const DriveCreateInProgress({required super.privacy}); @override - DriveCreateInProgress copyWith({DrivePrivacy? privacy}) { - return DriveCreateInProgress(privacy: privacy ?? this.privacy); - } + List get props => [privacy]; } -class DriveCreateSuccess extends DriveCreateState { - const DriveCreateSuccess({required super.privacy}); - - @override - DriveCreateSuccess copyWith({DrivePrivacy? privacy}) { - return DriveCreateSuccess(privacy: privacy ?? this.privacy); - } -} +class DriveCreateZeroBalance extends DriveCreateState {} -class DriveCreateFailure extends DriveCreateState { - const DriveCreateFailure({required super.privacy}); +class DriveCreateInProgress extends DriveCreateState {} - @override - DriveCreateFailure copyWith({DrivePrivacy? privacy}) { - return DriveCreateFailure(privacy: privacy ?? this.privacy); - } -} +class DriveCreateSuccess extends DriveCreateState {} -class DriveCreateWalletMismatch extends DriveCreateState { - const DriveCreateWalletMismatch({required super.privacy}); +class DriveCreateFailure extends DriveCreateState {} - @override - DriveCreateWalletMismatch copyWith({DrivePrivacy? privacy}) { - return DriveCreateWalletMismatch(privacy: privacy ?? this.privacy); - } -} +class DriveCreateWalletMismatch extends DriveCreateState {} diff --git a/lib/components/drive_create_form.dart b/lib/components/drive_create_form.dart index 5800b22c93..0aa1efe782 100644 --- a/lib/components/drive_create_form.dart +++ b/lib/components/drive_create_form.dart @@ -74,7 +74,8 @@ class _DriveCreateFormState extends State { ], ); } else { - final privacy = state.privacy; + final stateAsInitial = state as DriveCreateInitial; + final privacy = stateAsInitial.privacy; return ArDriveStandardModal( title: appLocalizationsOf(context).createDriveEmphasized, From dea7f44b843d151600ae4056da8d3313a9ff23ab Mon Sep 17 00:00:00 2001 From: Mati Date: Tue, 19 Sep 2023 12:53:21 -0300 Subject: [PATCH 5/7] Revert "test(create drive cubit): attempts to fix skipped test PE-4597" This reverts commit c90af0424e7545ac000a5702e7ec33e0be94fbcf. --- test/blocs/drive_create_cubit_test.dart | 235 +++++++++++------------- 1 file changed, 103 insertions(+), 132 deletions(-) diff --git a/test/blocs/drive_create_cubit_test.dart b/test/blocs/drive_create_cubit_test.dart index 8ff7e10435..97c7694b6b 100644 --- a/test/blocs/drive_create_cubit_test.dart +++ b/test/blocs/drive_create_cubit_test.dart @@ -1,11 +1,12 @@ @Tags(['broken']) import 'package:ardrive/blocs/blocs.dart'; -import 'package:ardrive/core/arfs/entities/arfs_entities.dart'; -import 'package:ardrive/entities/entity.dart'; +import 'package:ardrive/core/crypto/crypto.dart'; +import 'package:ardrive/entities/entities.dart'; import 'package:ardrive/models/models.dart'; import 'package:ardrive/services/services.dart'; import 'package:ardrive/turbo/services/upload_service.dart'; +import 'package:ardrive/utils/app_flavors.dart'; import 'package:ardrive/utils/app_platform.dart'; import 'package:arweave/arweave.dart'; import 'package:bloc_test/bloc_test.dart'; @@ -18,139 +19,109 @@ import 'package:test/test.dart'; import '../test_utils/fakes.dart'; import '../test_utils/utils.dart'; -class FakeEntity extends Fake implements Entity {} - void main() { - group( - 'DriveCreateCubit', - () { - late Database db; - late DriveDao driveDao; - - late ArweaveService arweave; - late TurboUploadService turboUploadService; - late DrivesCubit drivesCubit; - late ProfileCubit profileCubit; - late DriveCreateCubit driveCreateCubit; - - late Wallet wallet; - - const validDriveName = 'valid-drive-name'; - - setUp(() async { - wallet = getTestWallet(); - - registerFallbackValue(DrivesStateFake()); - registerFallbackValue(ProfileStateFake()); - registerFallbackValue(DataBundle(blob: Uint8List.fromList([]))); - registerFallbackValue(wallet); - registerFallbackValue(FakeEntity()); - - db = getTestDb(); - driveDao = db.driveDao; - AppPlatform.setMockPlatform(platform: SystemPlatform.unknown); - arweave = MockArweaveService(); - turboUploadService = DontUseUploadService(); - drivesCubit = MockDrivesCubit(); - profileCubit = MockProfileCubit(); - - final walletAddress = await wallet.getAddress(); - final walletOwner = await wallet.getAddress(); - - final keyBytes = Uint8List(32); - fillBytesWithSecureRandom(keyBytes); - - when(() => profileCubit.state).thenReturn( - ProfileLoggedIn( - username: 'Test', - password: '123', - wallet: wallet, - walletAddress: walletAddress, - walletBalance: BigInt.from(10000001), - cipherKey: SecretKey(keyBytes), - useTurbo: turboUploadService.useTurboUpload, - ), - ); - - when(() => profileCubit.logoutIfWalletMismatch()).thenAnswer( - (invocation) => Future.value(false), - ); - - when(() => arweave.prepareBundledDataItem(any(), any())).thenAnswer( - (invocation) => Future.value( - DataItem.withBlobData( - owner: walletOwner, - data: Uint8List.fromList([]), - ), - ), - ); - - when(() => arweave.prepareEntityDataItem(any(), any())).thenAnswer( - (invocation) => Future.value( - DataItem.withBlobData( - owner: walletOwner, - data: Uint8List.fromList([]), - ), - ), - ); - - driveCreateCubit = DriveCreateCubit( - arweave: arweave, - turboUploadService: turboUploadService, - driveDao: driveDao, - drivesCubit: drivesCubit, - profileCubit: profileCubit, - ); - }); - - tearDown(() async { - await db.close(); - }); - - blocTest( - 'create public drive', - build: () => driveCreateCubit, - act: (bloc) async { - bloc.form.value = { - 'name': validDriveName, - 'privacy': DrivePrivacy.public.name, - }; - await bloc.submit(''); - }, - expect: () => [ - const DriveCreateInProgress(privacy: DrivePrivacy.public), - const DriveCreateSuccess(privacy: DrivePrivacy.public), - ], - verify: (_) {}, + group('DriveCreateCubit', () { + late Database db; + late DriveDao driveDao; + + late ArweaveService arweave; + late TurboUploadService turboUploadService; + late DrivesCubit drivesCubit; + late ProfileCubit profileCubit; + late DriveCreateCubit driveCreateCubit; + + const validDriveName = 'valid-drive-name'; + + setUp(() async { + registerFallbackValue(DrivesStateFake()); + registerFallbackValue(ProfileStateFake()); + + db = getTestDb(); + driveDao = db.driveDao; + final configService = ConfigService( + appFlavors: AppFlavors(MockEnvFetcher()), + configFetcher: MockConfigFetcher()); + final config = await configService.loadConfig(); + + AppPlatform.setMockPlatform(platform: SystemPlatform.unknown); + arweave = ArweaveService( + Arweave(gatewayUrl: Uri.parse(config.defaultArweaveGatewayUrl!)), + ArDriveCrypto(), ); - - blocTest( - 'create private drive', - build: () => driveCreateCubit, - act: (bloc) async { - bloc.form.value = { - 'name': validDriveName, - 'privacy': DrivePrivacy.private.name, - }; - - bloc.onPrivacyChanged(); - - await bloc.submit(''); - }, - expect: () => [ - const DriveCreateInProgress(privacy: DrivePrivacy.public), - const DriveCreateInProgress(privacy: DrivePrivacy.private), - const DriveCreateSuccess(privacy: DrivePrivacy.private), - ], - verify: (_) {}, + turboUploadService = DontUseUploadService(); + drivesCubit = MockDrivesCubit(); + profileCubit = MockProfileCubit(); + + final wallet = getTestWallet(); + final walletAddress = await wallet.getAddress(); + + final keyBytes = Uint8List(32); + fillBytesWithSecureRandom(keyBytes); + + when(() => profileCubit.state).thenReturn( + ProfileLoggedIn( + username: 'Test', + password: '123', + wallet: wallet, + walletAddress: walletAddress, + walletBalance: BigInt.one, + cipherKey: SecretKey(keyBytes), + useTurbo: turboUploadService.useTurboUpload, + ), ); - blocTest( - 'does nothing when submitted without valid form', - build: () => driveCreateCubit, - act: (bloc) => bloc.submit(''), - expect: () => [], + driveCreateCubit = DriveCreateCubit( + arweave: arweave, + turboUploadService: turboUploadService, + driveDao: driveDao, + drivesCubit: drivesCubit, + profileCubit: profileCubit, ); - }, - ); + }); + + tearDown(() async { + await db.close(); + }); + + blocTest( + 'create public drive', + build: () => driveCreateCubit, + act: (bloc) async { + bloc.form.value = { + 'name': validDriveName, + 'privacy': DrivePrivacy.public, + }; + await bloc.submit(''); + }, + expect: () => [ + DriveCreateInProgress(), + DriveCreateSuccess(), + ], + verify: (_) {}, + ); + + blocTest( + 'create private drive', + build: () => driveCreateCubit, + act: (bloc) async { + bloc.form.value = { + 'name': validDriveName, + 'privacy': DrivePrivacy.private, + }; + await bloc.submit(''); + }, + expect: () => [ + DriveCreateInProgress(), + DriveCreateSuccess(), + ], + verify: (_) {}, + ); + + blocTest( + 'does nothing when submitted without valid form', + build: () => driveCreateCubit, + act: (bloc) => bloc.submit(''), + expect: () => [], + ); + }, skip: 'Needs to update the tests'); } From f6abb4efa35fd77527017b3a8dd69e5f7de72335 Mon Sep 17 00:00:00 2001 From: Mati Date: Tue, 19 Sep 2023 12:58:18 -0300 Subject: [PATCH 6/7] Revert "Revert "feat(create drive cubit): fixes bad casting PE-4597"" This reverts commit b1033afb4734dd76bc356fab4dfdaf60d58e85c8. --- .../drive_create/drive_create_cubit.dart | 14 ++--- .../drive_create/drive_create_state.dart | 59 +++++++++++++++---- lib/components/drive_create_form.dart | 3 +- 3 files changed, 57 insertions(+), 19 deletions(-) diff --git a/lib/blocs/drive_create/drive_create_cubit.dart b/lib/blocs/drive_create/drive_create_cubit.dart index 0ecf864ca3..7050d2e5f7 100644 --- a/lib/blocs/drive_create/drive_create_cubit.dart +++ b/lib/blocs/drive_create/drive_create_cubit.dart @@ -41,13 +41,13 @@ class DriveCreateCubit extends Cubit { _driveDao = driveDao, _profileCubit = profileCubit, _drivesCubit = drivesCubit, - super(DriveCreateInitial(privacy: DrivePrivacy.private)); + super(const DriveCreateInitial(privacy: DrivePrivacy.private)); void onPrivacyChanged() { final privacy = form.control('privacy').value == DrivePrivacy.private.name ? DrivePrivacy.private : DrivePrivacy.public; - emit((state as DriveCreateInitial).copyWith(privacy: privacy)); + emit(state.copyWith(privacy: privacy)); } Future submit( @@ -55,18 +55,18 @@ class DriveCreateCubit extends Cubit { ) async { final profile = _profileCubit.state as ProfileLoggedIn; if (await _profileCubit.logoutIfWalletMismatch()) { - emit(DriveCreateWalletMismatch()); + emit(DriveCreateWalletMismatch(privacy: state.privacy)); return; } final minimumWalletBalance = BigInt.from(10000000); if (profile.walletBalance <= minimumWalletBalance && !_turboUploadService.useTurboUpload) { - emit(DriveCreateZeroBalance()); + emit(DriveCreateZeroBalance(privacy: state.privacy)); return; } - emit(DriveCreateInProgress()); + emit(DriveCreateInProgress(privacy: state.privacy)); try { final String drivePrivacy = form.control('privacy').value; @@ -153,12 +153,12 @@ class DriveCreateCubit extends Cubit { addError(err); } - emit(DriveCreateSuccess()); + emit(DriveCreateSuccess(privacy: state.privacy)); } @override void onError(Object error, StackTrace stackTrace) { - emit(DriveCreateFailure()); + emit(DriveCreateFailure(privacy: state.privacy)); super.onError(error, stackTrace); logger.e('Failed to create drive', error, stackTrace); diff --git a/lib/blocs/drive_create/drive_create_state.dart b/lib/blocs/drive_create/drive_create_state.dart index 4b0a6048e9..7c07247a49 100644 --- a/lib/blocs/drive_create/drive_create_state.dart +++ b/lib/blocs/drive_create/drive_create_state.dart @@ -2,29 +2,68 @@ part of 'drive_create_cubit.dart'; @immutable abstract class DriveCreateState extends Equatable { + final DrivePrivacy privacy; + + const DriveCreateState({required this.privacy}); + + DriveCreateState copyWith({DrivePrivacy? privacy}) { + throw UnimplementedError(); + } + @override - List get props => []; + List get props => [privacy]; } class DriveCreateInitial extends DriveCreateState { - final DrivePrivacy privacy; - - DriveCreateInitial({required this.privacy}); + const DriveCreateInitial({required super.privacy}); + @override DriveCreateInitial copyWith({DrivePrivacy? privacy}) { return DriveCreateInitial(privacy: privacy ?? this.privacy); } +} + +class DriveCreateZeroBalance extends DriveCreateState { + const DriveCreateZeroBalance({required super.privacy}); @override - List get props => [privacy]; + DriveCreateZeroBalance copyWith({DrivePrivacy? privacy}) { + return DriveCreateZeroBalance(privacy: privacy ?? this.privacy); + } +} + +class DriveCreateInProgress extends DriveCreateState { + const DriveCreateInProgress({required super.privacy}); + + @override + DriveCreateInProgress copyWith({DrivePrivacy? privacy}) { + return DriveCreateInProgress(privacy: privacy ?? this.privacy); + } } -class DriveCreateZeroBalance extends DriveCreateState {} +class DriveCreateSuccess extends DriveCreateState { + const DriveCreateSuccess({required super.privacy}); + + @override + DriveCreateSuccess copyWith({DrivePrivacy? privacy}) { + return DriveCreateSuccess(privacy: privacy ?? this.privacy); + } +} -class DriveCreateInProgress extends DriveCreateState {} +class DriveCreateFailure extends DriveCreateState { + const DriveCreateFailure({required super.privacy}); -class DriveCreateSuccess extends DriveCreateState {} + @override + DriveCreateFailure copyWith({DrivePrivacy? privacy}) { + return DriveCreateFailure(privacy: privacy ?? this.privacy); + } +} -class DriveCreateFailure extends DriveCreateState {} +class DriveCreateWalletMismatch extends DriveCreateState { + const DriveCreateWalletMismatch({required super.privacy}); -class DriveCreateWalletMismatch extends DriveCreateState {} + @override + DriveCreateWalletMismatch copyWith({DrivePrivacy? privacy}) { + return DriveCreateWalletMismatch(privacy: privacy ?? this.privacy); + } +} diff --git a/lib/components/drive_create_form.dart b/lib/components/drive_create_form.dart index 0aa1efe782..5800b22c93 100644 --- a/lib/components/drive_create_form.dart +++ b/lib/components/drive_create_form.dart @@ -74,8 +74,7 @@ class _DriveCreateFormState extends State { ], ); } else { - final stateAsInitial = state as DriveCreateInitial; - final privacy = stateAsInitial.privacy; + final privacy = state.privacy; return ArDriveStandardModal( title: appLocalizationsOf(context).createDriveEmphasized, From 019b3f016351aaee02df1c72335dbc8050578550 Mon Sep 17 00:00:00 2001 From: Mati Date: Tue, 19 Sep 2023 12:58:22 -0300 Subject: [PATCH 7/7] Revert "Revert "test(create drive cubit): attempts to fix skipped test PE-4597"" This reverts commit dea7f44b843d151600ae4056da8d3313a9ff23ab. --- test/blocs/drive_create_cubit_test.dart | 235 +++++++++++++----------- 1 file changed, 132 insertions(+), 103 deletions(-) diff --git a/test/blocs/drive_create_cubit_test.dart b/test/blocs/drive_create_cubit_test.dart index 97c7694b6b..8ff7e10435 100644 --- a/test/blocs/drive_create_cubit_test.dart +++ b/test/blocs/drive_create_cubit_test.dart @@ -1,12 +1,11 @@ @Tags(['broken']) import 'package:ardrive/blocs/blocs.dart'; -import 'package:ardrive/core/crypto/crypto.dart'; -import 'package:ardrive/entities/entities.dart'; +import 'package:ardrive/core/arfs/entities/arfs_entities.dart'; +import 'package:ardrive/entities/entity.dart'; import 'package:ardrive/models/models.dart'; import 'package:ardrive/services/services.dart'; import 'package:ardrive/turbo/services/upload_service.dart'; -import 'package:ardrive/utils/app_flavors.dart'; import 'package:ardrive/utils/app_platform.dart'; import 'package:arweave/arweave.dart'; import 'package:bloc_test/bloc_test.dart'; @@ -19,109 +18,139 @@ import 'package:test/test.dart'; import '../test_utils/fakes.dart'; import '../test_utils/utils.dart'; +class FakeEntity extends Fake implements Entity {} + void main() { - group('DriveCreateCubit', () { - late Database db; - late DriveDao driveDao; - - late ArweaveService arweave; - late TurboUploadService turboUploadService; - late DrivesCubit drivesCubit; - late ProfileCubit profileCubit; - late DriveCreateCubit driveCreateCubit; - - const validDriveName = 'valid-drive-name'; - - setUp(() async { - registerFallbackValue(DrivesStateFake()); - registerFallbackValue(ProfileStateFake()); - - db = getTestDb(); - driveDao = db.driveDao; - final configService = ConfigService( - appFlavors: AppFlavors(MockEnvFetcher()), - configFetcher: MockConfigFetcher()); - final config = await configService.loadConfig(); - - AppPlatform.setMockPlatform(platform: SystemPlatform.unknown); - arweave = ArweaveService( - Arweave(gatewayUrl: Uri.parse(config.defaultArweaveGatewayUrl!)), - ArDriveCrypto(), + group( + 'DriveCreateCubit', + () { + late Database db; + late DriveDao driveDao; + + late ArweaveService arweave; + late TurboUploadService turboUploadService; + late DrivesCubit drivesCubit; + late ProfileCubit profileCubit; + late DriveCreateCubit driveCreateCubit; + + late Wallet wallet; + + const validDriveName = 'valid-drive-name'; + + setUp(() async { + wallet = getTestWallet(); + + registerFallbackValue(DrivesStateFake()); + registerFallbackValue(ProfileStateFake()); + registerFallbackValue(DataBundle(blob: Uint8List.fromList([]))); + registerFallbackValue(wallet); + registerFallbackValue(FakeEntity()); + + db = getTestDb(); + driveDao = db.driveDao; + AppPlatform.setMockPlatform(platform: SystemPlatform.unknown); + arweave = MockArweaveService(); + turboUploadService = DontUseUploadService(); + drivesCubit = MockDrivesCubit(); + profileCubit = MockProfileCubit(); + + final walletAddress = await wallet.getAddress(); + final walletOwner = await wallet.getAddress(); + + final keyBytes = Uint8List(32); + fillBytesWithSecureRandom(keyBytes); + + when(() => profileCubit.state).thenReturn( + ProfileLoggedIn( + username: 'Test', + password: '123', + wallet: wallet, + walletAddress: walletAddress, + walletBalance: BigInt.from(10000001), + cipherKey: SecretKey(keyBytes), + useTurbo: turboUploadService.useTurboUpload, + ), + ); + + when(() => profileCubit.logoutIfWalletMismatch()).thenAnswer( + (invocation) => Future.value(false), + ); + + when(() => arweave.prepareBundledDataItem(any(), any())).thenAnswer( + (invocation) => Future.value( + DataItem.withBlobData( + owner: walletOwner, + data: Uint8List.fromList([]), + ), + ), + ); + + when(() => arweave.prepareEntityDataItem(any(), any())).thenAnswer( + (invocation) => Future.value( + DataItem.withBlobData( + owner: walletOwner, + data: Uint8List.fromList([]), + ), + ), + ); + + driveCreateCubit = DriveCreateCubit( + arweave: arweave, + turboUploadService: turboUploadService, + driveDao: driveDao, + drivesCubit: drivesCubit, + profileCubit: profileCubit, + ); + }); + + tearDown(() async { + await db.close(); + }); + + blocTest( + 'create public drive', + build: () => driveCreateCubit, + act: (bloc) async { + bloc.form.value = { + 'name': validDriveName, + 'privacy': DrivePrivacy.public.name, + }; + await bloc.submit(''); + }, + expect: () => [ + const DriveCreateInProgress(privacy: DrivePrivacy.public), + const DriveCreateSuccess(privacy: DrivePrivacy.public), + ], + verify: (_) {}, ); - turboUploadService = DontUseUploadService(); - drivesCubit = MockDrivesCubit(); - profileCubit = MockProfileCubit(); - - final wallet = getTestWallet(); - final walletAddress = await wallet.getAddress(); - - final keyBytes = Uint8List(32); - fillBytesWithSecureRandom(keyBytes); - - when(() => profileCubit.state).thenReturn( - ProfileLoggedIn( - username: 'Test', - password: '123', - wallet: wallet, - walletAddress: walletAddress, - walletBalance: BigInt.one, - cipherKey: SecretKey(keyBytes), - useTurbo: turboUploadService.useTurboUpload, - ), + + blocTest( + 'create private drive', + build: () => driveCreateCubit, + act: (bloc) async { + bloc.form.value = { + 'name': validDriveName, + 'privacy': DrivePrivacy.private.name, + }; + + bloc.onPrivacyChanged(); + + await bloc.submit(''); + }, + expect: () => [ + const DriveCreateInProgress(privacy: DrivePrivacy.public), + const DriveCreateInProgress(privacy: DrivePrivacy.private), + const DriveCreateSuccess(privacy: DrivePrivacy.private), + ], + verify: (_) {}, ); - driveCreateCubit = DriveCreateCubit( - arweave: arweave, - turboUploadService: turboUploadService, - driveDao: driveDao, - drivesCubit: drivesCubit, - profileCubit: profileCubit, + blocTest( + 'does nothing when submitted without valid form', + build: () => driveCreateCubit, + act: (bloc) => bloc.submit(''), + expect: () => [], ); - }); - - tearDown(() async { - await db.close(); - }); - - blocTest( - 'create public drive', - build: () => driveCreateCubit, - act: (bloc) async { - bloc.form.value = { - 'name': validDriveName, - 'privacy': DrivePrivacy.public, - }; - await bloc.submit(''); - }, - expect: () => [ - DriveCreateInProgress(), - DriveCreateSuccess(), - ], - verify: (_) {}, - ); - - blocTest( - 'create private drive', - build: () => driveCreateCubit, - act: (bloc) async { - bloc.form.value = { - 'name': validDriveName, - 'privacy': DrivePrivacy.private, - }; - await bloc.submit(''); - }, - expect: () => [ - DriveCreateInProgress(), - DriveCreateSuccess(), - ], - verify: (_) {}, - ); - - blocTest( - 'does nothing when submitted without valid form', - build: () => driveCreateCubit, - act: (bloc) => bloc.submit(''), - expect: () => [], - ); - }, skip: 'Needs to update the tests'); + }, + ); }