Skip to content

Commit 488a9b9

Browse files
committed
Add tests for FeedsClient
1 parent 86df5c5 commit 488a9b9

File tree

1 file changed

+210
-0
lines changed

1 file changed

+210
-0
lines changed

packages/stream_feeds/test/feeds_client_test.dart

Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,20 @@
1+
import 'dart:async';
12
import 'dart:convert';
23

4+
import 'package:mocktail/mocktail.dart';
35
import 'package:stream_core/stream_core.dart';
46
import 'package:stream_feeds/src/generated/api/api.dart' as api;
57
import 'package:stream_feeds/src/ws/feeds_ws_event.dart';
68
import 'package:stream_feeds/stream_feeds.dart';
79
import 'package:test/test.dart';
810

11+
import 'mocks.dart';
12+
913
void main() {
14+
setUpAll(() {
15+
registerFallbackValue(const WsAuthMessageRequest(token: 'test_token'));
16+
});
17+
1018
group('FeedsClient', () {
1119
const testApiKey = 'test_api_key';
1220
const testUser = User(id: 'test_user_id', name: 'test_user_name');
@@ -185,6 +193,155 @@ void main() {
185193
await eventsSubscription.cancel();
186194
});
187195
});
196+
group('connect', () {
197+
test('should connect to the websocket', () {
198+
final webSocketClient = MockWebSocketClient();
199+
final connectionStateStream =
200+
MutableSharedEmitterImpl<WebSocketConnectionState>();
201+
when(() => webSocketClient.connectionStateStream)
202+
.thenReturn(connectionStateStream);
203+
204+
final client = FeedsClient(
205+
apiKey: testApiKey,
206+
user: testUser,
207+
userToken: testUserToken,
208+
environment: FakeFeedsClientEnvironment(
209+
webSocketClientBuilder: ({
210+
required String url,
211+
required EventDecoder eventDecoder,
212+
PingReguestBuilder? pingReguestBuilder,
213+
VoidCallback? onConnectionEstablished,
214+
VoidCallback? onConnected,
215+
}) =>
216+
webSocketClient,
217+
),
218+
);
219+
220+
client.connect();
221+
222+
verify(webSocketClient.connect).called(1);
223+
});
224+
225+
test('connect Future should complete after connection', () async {
226+
final webSocketClient = MockWebSocketClient();
227+
final connectionStateStream =
228+
MutableSharedEmitterImpl<WebSocketConnectionState>();
229+
when(() => webSocketClient.connectionStateStream)
230+
.thenReturn(connectionStateStream);
231+
232+
final client = FeedsClient(
233+
apiKey: testApiKey,
234+
user: testUser,
235+
userToken: testUserToken,
236+
environment: FakeFeedsClientEnvironment(
237+
webSocketClientBuilder:
238+
staticWebSocketClientBuilder(webSocketClient),
239+
),
240+
);
241+
242+
final connectFuture = client.connect();
243+
var isCompleted = false;
244+
unawaited(connectFuture.whenComplete(() => isCompleted = true));
245+
await Future<void>.delayed(Duration.zero);
246+
247+
expect(isCompleted, isFalse);
248+
249+
connectionStateStream.emit(WebSocketConnectionState.connected());
250+
await Future<void>.delayed(Duration.zero);
251+
expect(isCompleted, isTrue);
252+
});
253+
254+
test('Client should authenticate when connection established', () async {
255+
final webSocketClient = MockWebSocketClient();
256+
final connectionStateStream =
257+
MutableSharedEmitterImpl<WebSocketConnectionState>();
258+
when(() => webSocketClient.connectionStateStream)
259+
.thenReturn(connectionStateStream);
260+
261+
late VoidCallback? onConnectionEstablishedCallback;
262+
263+
final _ = FeedsClient(
264+
apiKey: testApiKey,
265+
user: testUser,
266+
userToken: testUserToken,
267+
environment: FakeFeedsClientEnvironment(
268+
webSocketClientBuilder: ({
269+
required String url,
270+
required EventDecoder eventDecoder,
271+
PingReguestBuilder? pingReguestBuilder,
272+
VoidCallback? onConnectionEstablished,
273+
VoidCallback? onConnected,
274+
}) {
275+
onConnectionEstablishedCallback = onConnectionEstablished;
276+
return webSocketClient;
277+
},
278+
),
279+
);
280+
281+
onConnectionEstablishedCallback?.call();
282+
await Future<void>.delayed(Duration.zero);
283+
284+
verify(() => webSocketClient.send(any<WsAuthMessageRequest>()))
285+
.called(1);
286+
});
287+
});
288+
289+
group('disconnect', () {
290+
test('dispose should disconnect websocket when connected', () {
291+
final webSocketClient = MockWebSocketClient();
292+
final connectionStateStream =
293+
MutableSharedEmitterImpl<WebSocketConnectionState>();
294+
295+
final connectionState = WebSocketConnectionState.connected();
296+
connectionStateStream.emit(connectionState);
297+
298+
when(() => webSocketClient.connectionState).thenReturn(connectionState);
299+
when(() => webSocketClient.connectionStateStream)
300+
.thenReturn(connectionStateStream);
301+
302+
final client = FeedsClient(
303+
apiKey: testApiKey,
304+
user: testUser,
305+
userToken: testUserToken,
306+
environment: FakeFeedsClientEnvironment(
307+
webSocketClientBuilder:
308+
staticWebSocketClientBuilder(webSocketClient),
309+
),
310+
);
311+
312+
client.dispose();
313+
314+
verify(webSocketClient.disconnect).called(1);
315+
});
316+
317+
test('dispose should not disconnect websocket when disconnected', () {
318+
final webSocketClient = MockWebSocketClient();
319+
final connectionStateStream =
320+
MutableSharedEmitterImpl<WebSocketConnectionState>();
321+
322+
final connectionState =
323+
Disconnected(source: DisconnectionSource.userInitiated());
324+
connectionStateStream.emit(connectionState);
325+
326+
when(() => webSocketClient.connectionState).thenReturn(connectionState);
327+
when(() => webSocketClient.connectionStateStream)
328+
.thenReturn(connectionStateStream);
329+
330+
final client = FeedsClient(
331+
apiKey: testApiKey,
332+
user: testUser,
333+
userToken: testUserToken,
334+
environment: FakeFeedsClientEnvironment(
335+
webSocketClientBuilder:
336+
staticWebSocketClientBuilder(webSocketClient),
337+
),
338+
);
339+
340+
client.dispose();
341+
342+
verifyNever(webSocketClient.disconnect);
343+
});
344+
});
188345
});
189346
}
190347

@@ -231,3 +388,56 @@ final testUserResponse = api.UserResponse(
231388
teams: const [],
232389
updatedAt: DateTime.now(),
233390
);
391+
392+
FakeWebSocketClientBuilder staticWebSocketClientBuilder(
393+
WebSocketClient webSocketClient,
394+
) {
395+
return ({
396+
required String url,
397+
required EventDecoder eventDecoder,
398+
PingReguestBuilder? pingReguestBuilder,
399+
VoidCallback? onConnectionEstablished,
400+
VoidCallback? onConnected,
401+
}) =>
402+
webSocketClient;
403+
}
404+
405+
typedef FakeWebSocketClientBuilder = WebSocketClient Function({
406+
required String url,
407+
required EventDecoder eventDecoder,
408+
PingReguestBuilder? pingReguestBuilder,
409+
VoidCallback? onConnectionEstablished,
410+
VoidCallback? onConnected,
411+
});
412+
413+
class FakeFeedsClientEnvironment extends FeedsClientEnvironment {
414+
FakeFeedsClientEnvironment({
415+
this.webSocketClientBuilder,
416+
});
417+
418+
// websocket client builder
419+
FakeWebSocketClientBuilder? webSocketClientBuilder;
420+
421+
@override
422+
WebSocketClient createWebSocketClient({
423+
required String url,
424+
required EventDecoder eventDecoder,
425+
PingReguestBuilder? pingReguestBuilder,
426+
VoidCallback? onConnectionEstablished,
427+
VoidCallback? onConnected,
428+
}) =>
429+
webSocketClientBuilder?.call(
430+
url: url,
431+
eventDecoder: eventDecoder,
432+
pingReguestBuilder: pingReguestBuilder,
433+
onConnectionEstablished: onConnectionEstablished,
434+
onConnected: onConnected,
435+
) ??
436+
super.createWebSocketClient(
437+
url: url,
438+
eventDecoder: eventDecoder,
439+
pingReguestBuilder: pingReguestBuilder,
440+
onConnectionEstablished: onConnectionEstablished,
441+
onConnected: onConnected,
442+
);
443+
}

0 commit comments

Comments
 (0)