1+
2+
13import 'package:checks/checks.dart' ;
24import 'package:flutter/material.dart' ;
35import 'package:flutter/services.dart' ;
46import 'package:flutter_gen/gen_l10n/zulip_localizations.dart' ;
57import 'package:flutter_test/flutter_test.dart' ;
8+ import 'package:http/http.dart' as http;
69import 'package:zulip/api/model/model.dart' ;
710import 'package:zulip/api/route/messages.dart' ;
811import 'package:zulip/model/compose.dart' ;
@@ -19,6 +22,7 @@ import '../example_data.dart' as eg;
1922import '../flutter_checks.dart' ;
2023import '../model/binding.dart' ;
2124import '../model/test_store.dart' ;
25+ import '../stdlib_checks.dart' ;
2226import '../test_clipboard.dart' ;
2327import '../test_share_plus.dart' ;
2428import 'compose_box_checks.dart' ;
@@ -90,6 +94,63 @@ void main() {
9094 (store.connection as FakeApiConnection ).prepare (httpStatus: 400 , json: fakeResponseJson);
9195 }
9296
97+ group ('AddThumbsUpButton' , () {
98+ setUp (() async {
99+ TestZulipBinding .ensureInitialized ();
100+ TestWidgetsFlutterBinding .ensureInitialized ();
101+ });
102+
103+ tearDown (() async {
104+ testBinding.reset ();
105+ });
106+
107+ Future <void > tapButton (WidgetTester tester) async {
108+ await tester.ensureVisible (find.byIcon (Icons .add_reaction_outlined, skipOffstage: false ));
109+ await tester.tap (find.byIcon (Icons .add_reaction_outlined));
110+ await tester.pump (); // [MenuItemButton.onPressed] called in a post-frame callback: flutter/flutter@e4a39fa2e
111+ }
112+
113+ testWidgets ('success' , (WidgetTester tester) async {
114+ final message = eg.streamMessage ();
115+ await setupToMessageActionSheet (tester, message: message, narrow: TopicNarrow .ofMessage (message));
116+ final store = await testBinding.globalStore.perAccount (eg.selfAccount.id);
117+
118+ final connection = store.connection as FakeApiConnection ;
119+ connection.prepare (json: {});
120+ await tapButton (tester);
121+ await tester.pump (Duration .zero);
122+
123+ check (connection.lastRequest).isA< http.Request > ()
124+ ..method.equals ('POST' )
125+ ..url.path.equals ('/api/v1/messages/${message .id }/reactions' )
126+ ..bodyFields.deepEquals ({
127+ 'reaction_type' : 'unicode_emoji' ,
128+ 'emoji_code' : '1f44d' ,
129+ 'emoji_name' : '+1' ,
130+ });
131+ });
132+
133+ testWidgets ('request has an error' , (WidgetTester tester) async {
134+ final message = eg.streamMessage ();
135+ await setupToMessageActionSheet (tester, message: message, narrow: TopicNarrow .ofMessage (message));
136+ final store = await testBinding.globalStore.perAccount (eg.selfAccount.id);
137+
138+ final connection = store.connection as FakeApiConnection ;
139+
140+ connection.prepare (httpStatus: 400 , json: {
141+ 'code' : 'BAD_REQUEST' ,
142+ 'msg' : 'Invalid message(s)' ,
143+ 'result' : 'error' ,
144+ });
145+ await tapButton (tester);
146+ await tester.pump (Duration .zero); // error arrives; error dialog shows
147+
148+ await tester.tap (find.byWidget (checkErrorDialog (tester,
149+ expectedTitle: 'Adding reaction failed' ,
150+ expectedMessage: 'Invalid message(s)' )));
151+ });
152+ });
153+
93154 group ('ShareButton' , () {
94155 // Tests should call setupMockSharePlus.
95156 setUp (() async {
@@ -177,6 +238,7 @@ void main() {
177238 ///
178239 /// Checks that there is a quote-and-reply button.
179240 Future <void > tapQuoteAndReplyButton (WidgetTester tester) async {
241+ await tester.ensureVisible (find.byIcon (Icons .format_quote_outlined, skipOffstage: false ));
180242 final quoteAndReplyButton = findQuoteAndReplyButton (tester);
181243 check (quoteAndReplyButton).isNotNull ();
182244 await tester.tap (find.byWidget (quoteAndReplyButton! ));
0 commit comments