Skip to content

Commit 7ab5174

Browse files
test(status_check): cover CheckServiceStatusUsecase sanitized failures
1 parent 61e0c90 commit 7ab5174

1 file changed

Lines changed: 140 additions & 0 deletions

File tree

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
import 'package:bb_mobile/core/status/domain/entity/service_status.dart';
2+
import 'package:bb_mobile/core/status/domain/usecases/check_all_service_status_usecase.dart';
3+
import 'package:bb_mobile/core/utils/result.dart';
4+
import 'package:bb_mobile/core/wallet/domain/entities/wallet.dart';
5+
import 'package:bb_mobile/core/wallet/domain/usecases/get_wallets_usecase.dart';
6+
import 'package:bb_mobile/features/status_check/domain/check_service_status_usecase.dart';
7+
import 'package:bb_mobile/features/status_check/domain/status_check_failure.dart';
8+
import 'package:flutter_test/flutter_test.dart';
9+
import 'package:mocktail/mocktail.dart';
10+
11+
class _MockGetWalletsUsecase extends Mock implements GetWalletsUsecase {}
12+
13+
class _MockCheckAllServiceStatusUsecase extends Mock
14+
implements CheckAllServiceStatusUsecase {}
15+
16+
class _MockWallet extends Mock implements Wallet {}
17+
18+
void main() {
19+
late _MockGetWalletsUsecase getWalletsUsecase;
20+
late _MockCheckAllServiceStatusUsecase checkAllServiceStatusUsecase;
21+
late CheckServiceStatusUsecase usecase;
22+
23+
setUpAll(() {
24+
registerFallbackValue(Network.bitcoinMainnet);
25+
});
26+
27+
setUp(() {
28+
getWalletsUsecase = _MockGetWalletsUsecase();
29+
checkAllServiceStatusUsecase = _MockCheckAllServiceStatusUsecase();
30+
usecase = CheckServiceStatusUsecase(
31+
checkAllServiceStatusUsecase: checkAllServiceStatusUsecase,
32+
getWalletsUsecase: getWalletsUsecase,
33+
);
34+
});
35+
36+
_MockWallet walletWith({required bool isDefault, Network? network}) {
37+
final wallet = _MockWallet();
38+
when(() => wallet.isDefault).thenReturn(isDefault);
39+
if (network != null) {
40+
when(() => wallet.network).thenReturn(network);
41+
}
42+
return wallet;
43+
}
44+
45+
group('CheckServiceStatusUsecase', () {
46+
test(
47+
'returns NoDefaultWalletFailure when no wallet is the default',
48+
() async {
49+
when(
50+
() => getWalletsUsecase.execute(),
51+
).thenAnswer((_) async => [walletWith(isDefault: false)]);
52+
53+
final result = await usecase.execute();
54+
55+
expect(result, isA<Err<AllServicesStatus, StatusCheckFailure>>());
56+
final failure =
57+
(result as Err<AllServicesStatus, StatusCheckFailure>).failure;
58+
expect(failure, isA<NoDefaultWalletFailure>());
59+
},
60+
);
61+
62+
test('maps a NoWalletsFoundException to NoDefaultWalletFailure without '
63+
'leaking the raw reason (NoDefaultWalletFailure carries no message '
64+
'field, so it structurally cannot leak)', () async {
65+
when(() => getWalletsUsecase.execute()).thenThrow(
66+
NoWalletsFoundException(
67+
'No wallets found for the current environment: mainnet',
68+
),
69+
);
70+
71+
final result = await usecase.execute();
72+
73+
expect(result, isA<Err<AllServicesStatus, StatusCheckFailure>>());
74+
expect(
75+
(result as Err<AllServicesStatus, StatusCheckFailure>).failure,
76+
isA<NoDefaultWalletFailure>(),
77+
);
78+
});
79+
80+
test('maps an unexpected GetWalletsUsecase failure to a sanitized failure '
81+
'without leaking the raw reason', () async {
82+
when(
83+
() => getWalletsUsecase.execute(),
84+
).thenThrow(Exception('electrum: connection reset by 1.2.3.4'));
85+
86+
final result = await usecase.execute();
87+
88+
expect(result, isA<Err<AllServicesStatus, StatusCheckFailure>>());
89+
final failure =
90+
(result as Err<AllServicesStatus, StatusCheckFailure>).failure;
91+
expect(failure, isA<StatusCheckUnexpectedFailure>());
92+
// The raw reason lives only in the log-only `logMessage` field, and
93+
// `toTranslated` never reads it — asserted by the l10n extension's
94+
// exhaustive switch, not here.
95+
});
96+
97+
test('maps an unexpected CheckAllServiceStatusUsecase failure to a '
98+
'sanitized failure', () async {
99+
when(() => getWalletsUsecase.execute()).thenAnswer(
100+
(_) async => [
101+
walletWith(isDefault: true, network: Network.bitcoinMainnet),
102+
],
103+
);
104+
when(
105+
() => checkAllServiceStatusUsecase.execute(
106+
network: any(named: 'network'),
107+
),
108+
).thenThrow(Exception('unexpected internal failure'));
109+
110+
final result = await usecase.execute();
111+
112+
expect(
113+
(result as Err<AllServicesStatus, StatusCheckFailure>).failure,
114+
isA<StatusCheckUnexpectedFailure>(),
115+
);
116+
});
117+
118+
test('returns Ok with the service status on success', () async {
119+
when(() => getWalletsUsecase.execute()).thenAnswer(
120+
(_) async => [
121+
walletWith(isDefault: true, network: Network.bitcoinMainnet),
122+
],
123+
);
124+
const status = AllServicesStatus();
125+
when(
126+
() => checkAllServiceStatusUsecase.execute(
127+
network: any(named: 'network'),
128+
),
129+
).thenAnswer((_) async => status);
130+
131+
final result = await usecase.execute();
132+
133+
expect(result, isA<Ok<AllServicesStatus, StatusCheckFailure>>());
134+
expect(
135+
(result as Ok<AllServicesStatus, StatusCheckFailure>).value,
136+
status,
137+
);
138+
});
139+
});
140+
}

0 commit comments

Comments
 (0)