fix(ui): fix stopTyping unhandled exceptions when network is off or spotty. (#1296)

* feat(llc, ui): Introduce `keyStrokeHandler` to properly handle keyStrokes.

Signed-off-by: xsahil03x <[email protected]>

* chore(ui): update CHANGELOG.md

Signed-off-by: xsahil03x <[email protected]>

* test(llc): add key_stroke_handler_test.dart

Signed-off-by: xsahil03x <[email protected]>
This commit is contained in:
Sahil Kumar
2022-08-05 16:57:32 +02:00
committed by GitHub
parent b3a7ca2897
commit bd1876c159
8 changed files with 352 additions and 149 deletions
@@ -2658,16 +2658,22 @@ void main() {
});
test(
'''should send `typingStart` event if there is not already a typingEvent or the difference between the two is >= 2 seconds''',
'''should send `typingStart` event if there is not already a typingEvent or the difference between the two is > 3 seconds''',
() async {
final typingEvent = Event(type: EventType.typingStart);
final startTypingEvent = Event(type: EventType.typingStart);
final stopTypingEvent = Event(type: EventType.typingStop);
when(() => channel.config?.typingEvents).thenReturn(true);
when(() => client.sendEvent(
channelId,
channelType,
any(that: isSameEventAs(typingEvent)),
any(that: isSameEventAs(startTypingEvent)),
)).thenAnswer((_) async => EmptyResponse());
when(() => client.sendEvent(
channelId,
channelType,
any(that: isSameEventAs(stopTypingEvent)),
)).thenAnswer((_) async => EmptyResponse());
await channel.keyStroke();
@@ -2675,7 +2681,12 @@ void main() {
verify(() => client.sendEvent(
channelId,
channelType,
any(that: isSameEventAs(typingEvent)),
any(that: isSameEventAs(startTypingEvent)),
)).called(1);
verify(() => client.sendEvent(
channelId,
channelType,
any(that: isSameEventAs(stopTypingEvent)),
)).called(1);
},
);
@@ -2688,7 +2699,7 @@ void main() {
final typingStopEvent = Event(type: EventType.typingStop);
await channel.keyStroke();
await channel.stopTyping();
verifyNever(() => client.sendEvent(
channelId,
@@ -0,0 +1,73 @@
// ignore_for_file: avoid_redundant_argument_values
import 'package:mocktail/mocktail.dart';
import 'package:stream_chat/stream_chat.dart';
import 'package:test/test.dart';
mixin OnKeyStrokeEvent {
Future<void> call([String? parentId]);
}
class OnStartTyping extends Mock implements OnKeyStrokeEvent {}
class OnStopTyping extends Mock implements OnKeyStrokeEvent {}
void main() {
final onStartTyping = OnStartTyping();
final onStopTyping = OnStopTyping();
late KeyStrokeHandler keyStrokeHandler;
const startTypingEventTimeout = 1;
const startTypingResendInterval = 2;
setUp(() {
when(() => onStartTyping(any())).thenAnswer((_) => Future.value());
when(() => onStopTyping(any())).thenAnswer((_) => Future.value());
keyStrokeHandler = KeyStrokeHandler(
onStartTyping: onStartTyping,
onStopTyping: onStopTyping,
startTypingEventTimeout: startTypingEventTimeout,
startTypingResendInterval: startTypingResendInterval,
);
});
tearDown(() {
keyStrokeHandler.cancel();
clearInteractions(onStartTyping);
clearInteractions(onStopTyping);
});
group('call', () {
test('should work fine', () {
expect(keyStrokeHandler.call(), completes);
});
test('should call onStartTyping', () async {
keyStrokeHandler.call();
verify(() => onStartTyping(any())).called(1);
});
test('should call onStopTyping', () async {
keyStrokeHandler
..call()
..cancel();
verify(() => onStopTyping(any())).called(1);
});
test('should call onStartTyping after startTypingResendInterval', () async {
final watch = Stopwatch()..start();
while (watch.elapsed.inSeconds <= startTypingResendInterval) {
keyStrokeHandler.call();
}
watch.stop();
verify(() => onStartTyping(any())).called(2);
});
test('should call onStopTyping after startTypingEventTimeout', () async {
keyStrokeHandler.call();
await Future.delayed(const Duration(seconds: startTypingEventTimeout));
verify(() => onStopTyping(any())).called(1);
});
});
}