Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PE-4632: Persistent loading issue when creating drives #1369

Merged
merged 2 commits into from
Sep 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions lib/blocs/drive_create/drive_create_cubit.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,32 +41,32 @@ class DriveCreateCubit extends Cubit<DriveCreateState> {
_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<void> submit(
String driveName,
) 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;
Expand Down Expand Up @@ -153,12 +153,12 @@ class DriveCreateCubit extends Cubit<DriveCreateState> {
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);
Expand Down
59 changes: 49 additions & 10 deletions lib/blocs/drive_create/drive_create_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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<Object> get props => [];
List<Object> 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<Object> 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);
}
}
3 changes: 1 addition & 2 deletions lib/components/drive_create_form.dart
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,7 @@ class _DriveCreateFormState extends State<DriveCreateForm> {
],
);
} else {
final stateAsInitial = state as DriveCreateInitial;
final privacy = stateAsInitial.privacy;
final privacy = state.privacy;

return ArDriveStandardModal(
title: appLocalizationsOf(context).createDriveEmphasized,
Expand Down
235 changes: 132 additions & 103 deletions test/blocs/drive_create_cubit_test.dart
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
@Tags(['broken'])
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I attempted to fix this, but it was taking too much time so I left if Skipped still


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';
Expand All @@ -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<DriveCreateCubit, DriveCreateState>(
'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<DriveCreateCubit, DriveCreateState>(
'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<DriveCreateCubit, DriveCreateState>(
'does nothing when submitted without valid form',
build: () => driveCreateCubit,
act: (bloc) => bloc.submit(''),
expect: () => [],
);
});

tearDown(() async {
await db.close();
});

blocTest<DriveCreateCubit, DriveCreateState>(
'create public drive',
build: () => driveCreateCubit,
act: (bloc) async {
bloc.form.value = {
'name': validDriveName,
'privacy': DrivePrivacy.public,
};
await bloc.submit('');
},
expect: () => [
DriveCreateInProgress(),
DriveCreateSuccess(),
],
verify: (_) {},
);

blocTest<DriveCreateCubit, DriveCreateState>(
'create private drive',
build: () => driveCreateCubit,
act: (bloc) async {
bloc.form.value = {
'name': validDriveName,
'privacy': DrivePrivacy.private,
};
await bloc.submit('');
},
expect: () => [
DriveCreateInProgress(),
DriveCreateSuccess(),
],
verify: (_) {},
);

blocTest<DriveCreateCubit, DriveCreateState>(
'does nothing when submitted without valid form',
build: () => driveCreateCubit,
act: (bloc) => bloc.submit(''),
expect: () => [],
);
}, skip: 'Needs to update the tests');
},
);
}