Skip to content

Commit

Permalink
Merge pull request #1859 from ardriveapp/PE-6767-enhance-error-handli…
Browse files Browse the repository at this point in the history
…ng-on-assign-name-flow

PE-6767: enhance error handling on assign name flow
  • Loading branch information
thiagocarvalhodev authored Sep 18, 2024
2 parents 979c2d0 + 0643e3b commit 09b04a0
Show file tree
Hide file tree
Showing 4 changed files with 195 additions and 39 deletions.
80 changes: 41 additions & 39 deletions lib/arns/presentation/assign_name_bloc/assign_name_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,22 @@ class AssignNameBloc extends Bloc<AssignNameEvent, AssignNameState> {
_arnsRepository = arnsRepository,
super(AssignNameInitial()) {
on<LoadNames>((event, emit) async {
emit(LoadingNames());
try {
emit(LoadingNames());

final walletAddress = await _auth.getWalletAddress();
final walletAddress = await _auth.getWalletAddress();

final names = await _arnsRepository.getAntRecordsForWallet(walletAddress!);
final names =
await _arnsRepository.getAntRecordsForWallet(walletAddress!);

if (names.isEmpty) {
emit(AssignNameEmptyState());
} else {
emit(NamesLoaded(names: names));
if (names.isEmpty) {
emit(AssignNameEmptyState());
} else {
emit(NamesLoaded(names: names));
}
} catch (e) {
logger.e('Failed to load ArNS names', e);
emit(LoadingNamesFailed());
}
});

Expand Down Expand Up @@ -94,41 +100,37 @@ class AssignNameBloc extends Bloc<AssignNameEvent, AssignNameState> {
on<ConfirmSelectionAndUpload>((event, emit) async {
try {
emit(ConfirmingSelection());
try {
if (fileDataTableItem == null) {
throw StateError('File data table item is null');
}

ARNSUndername undername;

if (_selectedUndername == null) {
undername = ARNSUndername(
name: '@',
record: ARNSRecord(
transactionId: fileDataTableItem.dataTxId, ttlSeconds: 3600),
domain: _selectedANTRecord!.domain,
);
} else {
undername = ARNSUndername(
name: _selectedUndername!.name,
record: ARNSRecord(
transactionId: fileDataTableItem.dataTxId,
ttlSeconds: 3600,
),
domain: _selectedANTRecord!.domain,
);
}

await _arnsRepository.setUndernamesToFile(
undername: undername,
fileId: fileDataTableItem.fileId,
driveId: fileDataTableItem.driveId,
processId: _selectedANTRecord!.processId,
if (fileDataTableItem == null) {
throw StateError('File data table item is null');
}

ARNSUndername undername;

if (_selectedUndername == null) {
undername = ARNSUndername(
name: '@',
record: ARNSRecord(
transactionId: fileDataTableItem.dataTxId, ttlSeconds: 3600),
domain: _selectedANTRecord!.domain,
);
} else {
undername = ARNSUndername(
name: _selectedUndername!.name,
record: ARNSRecord(
transactionId: fileDataTableItem.dataTxId,
ttlSeconds: 3600,
),
domain: _selectedANTRecord!.domain,
);
} catch (e) {
logger.e('Failed to set ARNS', e);
}

await _arnsRepository.setUndernamesToFile(
undername: undername,
fileId: fileDataTableItem.fileId,
driveId: fileDataTableItem.driveId,
processId: _selectedANTRecord!.processId,
);

final (address, arAddress) = getAddressesFromArns(
domain: _selectedANTRecord!.domain,
undername: _selectedUndername?.name,
Expand Down
2 changes: 2 additions & 0 deletions lib/arns/presentation/assign_name_bloc/assign_name_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,6 @@ final class LoadingUndernames extends AssignNameState {}

class SelectionFailed extends AssignNameState {}

final class LoadingNamesFailed extends AssignNameState {}

final class EmptySelection extends AssignNameState {}
58 changes: 58 additions & 0 deletions lib/arns/presentation/assign_name_modal.dart
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,28 @@ class _AssignArNSNameModalState extends State<_AssignArNSNameModal> {
return const Center(child: CircularProgressIndicator());
} else if (state is AssignNameEmptyState) {
return const _AssignNameEmptyState();
} else if (state is SelectionFailed) {
final colorTokens =
ArDriveTheme.of(context).themeData.colorTokens;
return Center(
child: Text(
'Error assigning ArNS name. Please try again later',
style: typography.paragraphLarge(
color: colorTokens.textMid,
),
),
);
} else if (state is LoadingNamesFailed) {
final colorTokens =
ArDriveTheme.of(context).themeData.colorTokens;
return Center(
child: Text(
'Error fetching ArNS names. Please try again later',
style: typography.paragraphLarge(
color: colorTokens.textMid,
),
),
);
}

return const SizedBox();
Expand Down Expand Up @@ -299,6 +321,42 @@ class _AssignArNSNameModalState extends State<_AssignArNSNameModal> {
return [];
}

if (state is LoadingNamesFailed) {
return [
ModalAction(
action: () {
Navigator.of(context).pop();
},
title: 'Cancel',
),
ModalAction(
action: () {
context
.read<AssignNameBloc>()
.add(const LoadNames(updateARNSRecords: true));
},
title: 'Try again',
),
];
}

if (state is SelectionFailed) {
return [
ModalAction(
action: () {
Navigator.of(context).pop();
},
title: 'Cancel',
),
ModalAction(
action: () {
context.read<AssignNameBloc>().add(ConfirmSelectionAndUpload());
},
title: 'Try again',
),
];
}

late final bool isButtonEnabled;

if (state is NamesLoaded && state.selectedName != null) {
Expand Down
94 changes: 94 additions & 0 deletions test/arns/presentation/assign_name_bloc/assign_name_bloc_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,29 @@ void main() {
walletAddress,
)).called(1);
});

test('emits [LoadingNames, LoadingNamesFailed] when LoadNames is added',
() async {
// Arrange
const walletAddress = 'test_wallet_address';

when(() => mockAuth.getWalletAddress())
.thenAnswer((_) async => walletAddress);
when(() => mockArnsRepository.getAntRecordsForWallet(walletAddress,
update: true)).thenThrow(StateError('Test error'));

// Act
assignNameBloc.add(const LoadNames());

// Assert
await expectLater(
assignNameBloc.stream,
emitsInOrder([
isA<LoadingNames>(),
isA<LoadingNamesFailed>(),
]),
);
});
});

group('SelectName', () {
Expand Down Expand Up @@ -353,5 +376,76 @@ void main() {
},
);
});

blocTest<AssignNameBloc, AssignNameState>(
'emits [ConfirmingSelection, SelectionFailed] when ConfirmSelection is added',
build: () {
when(() => mockFileDataTableItem.dataTxId)
.thenReturn('test_data_tx_id');
when(() => mockFileDataTableItem.fileId).thenReturn('test_file_id');
when(() => mockFileDataTableItem.driveId).thenReturn('test_drive_id');
final antRecords = [
ANTRecord(domain: 'test1.ar', processId: 'process1'),
ANTRecord(domain: 'test2.ar', processId: 'process2'),
];

const walletAddress = 'test_wallet_address';

when(() => mockAuth.getWalletAddress())
.thenAnswer((_) async => walletAddress);
when(() => mockArnsRepository.getAntRecordsForWallet(
walletAddress,
)).thenAnswer((_) async => antRecords);

/// FAILED CALL
when(() => mockArnsRepository.setUndernamesToFile(
undername: any(named: 'undername'),
fileId: any(named: 'fileId'),
driveId: any(named: 'driveId'),
processId: any(named: 'processId'),
)).thenThrow(StateError('Test error'));
when(() => mockArnsRepository.getARNSUndernames(any())).thenAnswer(
(_) async => [
ARNSUndername(
name: 'undername',
domain: 'domain',
record: ARNSRecord(transactionId: 'test_tx_id', ttlSeconds: 3600),
)
],
);
return assignNameBloc;
},
act: (bloc) {
bloc.add(const LoadNames());
bloc.add(
SelectName(ANTRecord(domain: 'domain', processId: 'process_id')));
bloc.add(const LoadUndernames());
bloc.add(SelectUndername(
undername: ARNSUndername(
name: 'undername',
domain: 'domain',
record: ARNSRecord(transactionId: 'test_tx_id', ttlSeconds: 3600),
),
));
bloc.add(ConfirmSelectionAndUpload());
},
expect: () => [
isA<LoadingNames>(),
isA<NamesLoaded>(),
isA<LoadingUndernames>(),
isA<UndernamesLoaded>(),
isA<UndernamesLoaded>(),
isA<ConfirmingSelection>(),
isA<SelectionFailed>(),
],
verify: (_) {
verify(() => mockArnsRepository.setUndernamesToFile(
undername: any(named: 'undername'),
fileId: any(named: 'fileId'),
driveId: any(named: 'driveId'),
processId: any(named: 'processId'),
)).called(1);
},
);
});
}

0 comments on commit 09b04a0

Please sign in to comment.