Skip to content
Open
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
17 changes: 16 additions & 1 deletion lib/screens/dashboard/bloc/balance_cubit.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'dart:async';
import 'dart:developer' as developer;

import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:realunit_wallet/models/asset.dart';
Expand All @@ -19,7 +20,21 @@ class BalanceCubit extends Cubit<Balance> {
asset: asset,
),
) {
_subscription = _repository.watchBalance(state).listen(emit);
// Register an onError handler so a balance-stream error is logged instead
// of escaping as an unhandled async error that silently freezes the
// balance (issue #657 P3 #14). cancelOnError defaults to false, so the
// subscription stays alive and later balances still update the UI.
_subscription = _repository.watchBalance(state).listen(
emit,
onError: (Object error, StackTrace stackTrace) {
developer.log(
'balance stream error',
name: '$BalanceCubit',
error: error,
stackTrace: stackTrace,
);
},
);
}

final BalanceRepository _repository;
Expand Down
26 changes: 26 additions & 0 deletions test/screens/dashboard/balance_cubit_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,32 @@ void main() {
expect(cubit.state.balance, BigInt.from(12345));
});

test(
'a stream error is handled (not unhandled) and later balances still '
'update (issue #657 P3 #14 regression)', () async {
final cubit = build();

// Without an onError handler this error escaped as an unhandled async
// error (failing the test) and froze the balance. It must now be
// swallowed/logged, and — cancelOnError being false — a balance pushed
// afterwards must still reach the state.
controller.addError(Exception('balance backend blip'));
await Future<void>.delayed(Duration.zero);

final updated = Balance(
chainId: realUnitAsset.chainId,
contractAddress: realUnitAsset.address,
walletAddress: _address,
balance: BigInt.from(999),
asset: realUnitAsset,
);
final ready = cubit.stream.firstWhere((b) => b.balance == BigInt.from(999));
controller.add(updated);
await ready.timeout(const Duration(seconds: 1));

expect(cubit.state.balance, BigInt.from(999));
});

test('close() cancels the underlying stream subscription', () async {
final cubit = build();

Expand Down
Loading