From 7a70e7c6b025f1d794b603879afd42bd833f29c3 Mon Sep 17 00:00:00 2001 From: Shu Chen Date: Tue, 16 Jan 2024 14:14:53 +0000 Subject: [PATCH] compose: Specify TextCapitalization.sentences on TextField in _ContentInput --- lib/widgets/compose_box.dart | 1 + test/flutter_checks.dart | 6 ++- test/widgets/compose_box_test.dart | 80 ++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 1 deletion(-) diff --git a/lib/widgets/compose_box.dart b/lib/widgets/compose_box.dart index bdb64838f11..ea80368bd65 100644 --- a/lib/widgets/compose_box.dart +++ b/lib/widgets/compose_box.dart @@ -302,6 +302,7 @@ class _ContentInput extends StatelessWidget { style: TextStyle(color: colorScheme.onSurface), decoration: InputDecoration.collapsed(hintText: hintText), maxLines: null, + textCapitalization: TextCapitalization.sentences, ); }), )); diff --git a/test/flutter_checks.dart b/test/flutter_checks.dart index c83ff46cdd3..6fcd4a1a184 100644 --- a/test/flutter_checks.dart +++ b/test/flutter_checks.dart @@ -2,8 +2,8 @@ library; import 'package:checks/checks.dart'; +import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:flutter/widgets.dart'; extension AnimationChecks on Subject> { Subject get status => has((d) => d.status, 'status'); @@ -48,6 +48,10 @@ extension TextChecks on Subject { Subject get data => has((t) => t.data, 'data'); } +extension TextFieldChecks on Subject { + Subject get textCapitalization => has((t) => t.textCapitalization, 'textCapitalization'); +} + extension TextStyleChecks on Subject { Subject get inherit => has((t) => t.inherit, 'inherit'); Subject?> get fontVariations => has((t) => t.fontVariations, 'fontVariations'); diff --git a/test/widgets/compose_box_test.dart b/test/widgets/compose_box_test.dart index 76fc263307e..d138ee8dde3 100644 --- a/test/widgets/compose_box_test.dart +++ b/test/widgets/compose_box_test.dart @@ -1,9 +1,23 @@ import 'package:checks/checks.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/zulip_localizations.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:zulip/api/route/messages.dart'; +import 'package:zulip/model/narrow.dart'; import 'package:zulip/widgets/compose_box.dart'; +import 'package:zulip/widgets/message_list.dart'; +import 'package:zulip/widgets/store.dart'; + +import '../api/fake_api.dart'; +import '../example_data.dart' as eg; +import '../flutter_checks.dart'; +import '../model/binding.dart'; +import '../model/test_store.dart'; void main() { + TestZulipBinding.ensureInitialized(); + TestWidgetsFlutterBinding.ensureInitialized(); + group('ComposeContentController', () { group('insertPadded', () { // Like `parseMarkedText` in test/model/autocomplete_test.dart, @@ -105,4 +119,70 @@ void main() { }); }); }); + + group('ComposeBox textCapitalization', () { + final message = eg.streamMessage(); + + Future setupToComposeBox(WidgetTester tester, Narrow narrow) async { + addTearDown(testBinding.reset); + await testBinding.globalStore.add(eg.selfAccount, eg.initialSnapshot( + streams: [eg.stream(streamId: message.streamId)], + )); + final store = await testBinding.globalStore.perAccount(eg.selfAccount.id); + final connection = store.connection as FakeApiConnection; + + // prepare message list data + connection.prepare(json: GetMessagesResult( + anchor: message.id, + foundNewest: true, + foundOldest: true, + foundAnchor: true, + historyLimited: false, + messages: [message], + ).toJson()); + + await tester.pumpWidget( + MaterialApp( + localizationsDelegates: ZulipLocalizations.localizationsDelegates, + supportedLocales: ZulipLocalizations.supportedLocales, + home: GlobalStoreWidget( + child: PerAccountStoreWidget( + accountId: eg.selfAccount.id, + child: MessageListPage(narrow: narrow))))); + + // global store, per-account store, and message list get loaded + await tester.pumpAndSettle(); + } + + void checkComposeBoxTextFields(WidgetTester tester, {required bool expectTopicTextField}) { + final composeBoxController = tester.widget(find.byType(ComposeBox)) + .controllerKey!.currentState!; + + final topicTextField = tester.widgetList(find.byWidgetPredicate( + (widget) => widget is TextField + && widget.controller == composeBoxController.topicController)).singleOrNull; + if (expectTopicTextField) { + check(topicTextField).isA() + .textCapitalization.equals(TextCapitalization.none); + } else { + check(topicTextField).isNull(); + } + + final contentTextField = tester.widget(find.byWidgetPredicate( + (widget) => widget is TextField + && widget.controller == composeBoxController.contentController)); + check(contentTextField).isA() + .textCapitalization.equals(TextCapitalization.sentences); + } + + testWidgets('_StreamComposeBox', (tester) async { + await setupToComposeBox(tester, StreamNarrow(message.streamId)); + checkComposeBoxTextFields(tester, expectTopicTextField: true); + }); + + testWidgets('_FixedDestinationComposeBox', (tester) async { + await setupToComposeBox(tester, TopicNarrow.ofMessage(message)); + checkComposeBoxTextFields(tester, expectTopicTextField: false); + }); + }); }