|
| 1 | +import 'dart:async'; |
| 2 | + |
1 | 3 | import 'package:flutter_test/flutter_test.dart'; |
| 4 | +import 'package:flutter_riverpod/flutter_riverpod.dart'; |
2 | 5 | import 'package:zcash_wallet/src/providers/rpc_endpoint_latency_provider.dart'; |
3 | 6 |
|
4 | 7 | void main() { |
@@ -47,4 +50,95 @@ void main() { |
47 | 50 | expect(sample.label, 'Unavailable'); |
48 | 51 | }); |
49 | 52 | }); |
| 53 | + |
| 54 | + group('RpcEndpointLatencyNotifier', () { |
| 55 | + test('marks presets checking before resolving measured latency', () async { |
| 56 | + final completer = Completer<String>(); |
| 57 | + final container = ProviderContainer( |
| 58 | + overrides: [ |
| 59 | + rpcEndpointChainNameGetterProvider.overrideWithValue( |
| 60 | + (_) => completer.future, |
| 61 | + ), |
| 62 | + ], |
| 63 | + ); |
| 64 | + addTearDown(container.dispose); |
| 65 | + |
| 66 | + final refresh = container |
| 67 | + .read(rpcEndpointLatencyProvider.notifier) |
| 68 | + .refresh('main'); |
| 69 | + |
| 70 | + await Future<void>.delayed(Duration.zero); |
| 71 | + |
| 72 | + final checkingState = container.read(rpcEndpointLatencyProvider); |
| 73 | + expect( |
| 74 | + checkingState.samples.values.every( |
| 75 | + (sample) => sample.status == RpcEndpointLatencyStatus.checking, |
| 76 | + ), |
| 77 | + isTrue, |
| 78 | + ); |
| 79 | + |
| 80 | + completer.complete('main'); |
| 81 | + await refresh; |
| 82 | + |
| 83 | + final finalState = container.read(rpcEndpointLatencyProvider); |
| 84 | + expect( |
| 85 | + finalState.samples.values.every( |
| 86 | + (sample) => sample.status == RpcEndpointLatencyStatus.available, |
| 87 | + ), |
| 88 | + isTrue, |
| 89 | + ); |
| 90 | + }); |
| 91 | + |
| 92 | + test('discard stale samples when a newer refresh starts', () async { |
| 93 | + final completers = <Completer<String>>[]; |
| 94 | + final container = ProviderContainer( |
| 95 | + overrides: [ |
| 96 | + rpcEndpointChainNameGetterProvider.overrideWithValue((_) { |
| 97 | + final completer = Completer<String>(); |
| 98 | + completers.add(completer); |
| 99 | + return completer.future; |
| 100 | + }), |
| 101 | + ], |
| 102 | + ); |
| 103 | + addTearDown(container.dispose); |
| 104 | + |
| 105 | + final firstRefresh = container |
| 106 | + .read(rpcEndpointLatencyProvider.notifier) |
| 107 | + .refresh('main'); |
| 108 | + await Future<void>.delayed(Duration.zero); |
| 109 | + final firstCompleters = List<Completer<String>>.of(completers); |
| 110 | + |
| 111 | + final secondRefresh = container |
| 112 | + .read(rpcEndpointLatencyProvider.notifier) |
| 113 | + .refresh('main'); |
| 114 | + await Future<void>.delayed(Duration.zero); |
| 115 | + final secondCompleters = completers |
| 116 | + .where((completer) => !firstCompleters.contains(completer)) |
| 117 | + .toList(); |
| 118 | + |
| 119 | + for (final completer in firstCompleters) { |
| 120 | + completer.complete('test'); |
| 121 | + } |
| 122 | + await firstRefresh; |
| 123 | + final afterStale = container.read(rpcEndpointLatencyProvider); |
| 124 | + expect( |
| 125 | + afterStale.samples.values.every( |
| 126 | + (sample) => sample.status == RpcEndpointLatencyStatus.checking, |
| 127 | + ), |
| 128 | + isTrue, |
| 129 | + ); |
| 130 | + |
| 131 | + for (final completer in secondCompleters) { |
| 132 | + completer.complete('main'); |
| 133 | + } |
| 134 | + await secondRefresh; |
| 135 | + final finalState = container.read(rpcEndpointLatencyProvider); |
| 136 | + expect( |
| 137 | + finalState.samples.values.every( |
| 138 | + (sample) => sample.status == RpcEndpointLatencyStatus.available, |
| 139 | + ), |
| 140 | + isTrue, |
| 141 | + ); |
| 142 | + }); |
| 143 | + }); |
50 | 144 | } |
0 commit comments