diff --git a/mobile/test/shared/relay/relay_socket_test.dart b/mobile/test/shared/relay/relay_socket_test.dart index e807c9bb1..5cd25cc2f 100644 --- a/mobile/test/shared/relay/relay_socket_test.dart +++ b/mobile/test/shared/relay/relay_socket_test.dart @@ -44,11 +44,37 @@ void main() { expect(socket.state, SocketState.authenticating); await channel.closeStream(); - await connecting; + await connecting.timeout(const Duration(seconds: 1)); expect(disconnections, hasLength(1)); expect(disconnections.single, isA()); expect(socket.state, SocketState.disconnected); + expect(channel.closeCount, 1); + }); + + test('auth-phase stream error reports one disconnection', () async { + final channel = _ReadyWebSocketChannel(); + final disconnections = []; + final socket = RelaySocket( + wsUrl: 'wss://relay.example', + nsec: null, + onMessage: (_) {}, + onConnected: () => fail('socket must not connect'), + onDisconnected: disconnections.add, + channelFactory: (_) => channel, + ); + + final connecting = socket.connect(); + await Future.delayed(Duration.zero); + expect(socket.state, SocketState.authenticating); + + channel.addStreamError(StateError('connection reset')); + await connecting.timeout(const Duration(seconds: 1)); + + expect(disconnections, hasLength(1)); + expect(disconnections.single, isA()); + expect(socket.state, SocketState.disconnected); + expect(channel.closeCount, 1); }); test('hung handshake times out, closes, and reports disconnection', () async { @@ -93,6 +119,8 @@ class _ReadyWebSocketChannel implements WebSocketChannel { Future closeStream() => _controller.close(); + void addStreamError(Object error) => _controller.addError(error); + @override late final WebSocketSink sink = _RecordingWebSocketSink( _controller.sink,