@@ -8,13 +8,21 @@ import 'package:flutter_test/flutter_test.dart';
8
8
import 'package:url_launcher/url_launcher.dart' ;
9
9
import 'package:zulip/api/core.dart' ;
10
10
import 'package:zulip/model/content.dart' ;
11
+ import 'package:zulip/model/narrow.dart' ;
11
12
import 'package:zulip/widgets/content.dart' ;
13
+ import 'package:zulip/widgets/message_list.dart' ;
14
+ import 'package:zulip/widgets/page.dart' ;
12
15
import 'package:zulip/widgets/store.dart' ;
13
16
17
+ import '../api/fake_api.dart' ;
14
18
import '../example_data.dart' as eg;
15
19
import '../model/binding.dart' ;
20
+ import '../model/message_list_test.dart' ;
16
21
import '../test_images.dart' ;
22
+ import '../test_navigation.dart' ;
17
23
import 'dialog_checks.dart' ;
24
+ import 'message_list_checks.dart' ;
25
+ import 'page_checks.dart' ;
18
26
19
27
void main () {
20
28
TestZulipBinding .ensureInitialized ();
@@ -158,6 +166,51 @@ void main() {
158
166
});
159
167
});
160
168
169
+ group ('LinkNode on internal links' , () {
170
+ Future <List <Route <dynamic >>> prepareContent (WidgetTester tester, {
171
+ required String html,
172
+ }) async {
173
+ await testBinding.globalStore.add (eg.selfAccount, eg.initialSnapshot (
174
+ streams: [eg.stream (streamId: 1 , name: 'check' )],
175
+ ));
176
+ addTearDown (testBinding.reset);
177
+ final pushedRoutes = < Route <dynamic >> [];
178
+ final testNavObserver = TestNavigatorObserver ()
179
+ ..onPushed = (route, prevRoute) => pushedRoutes.add (route);
180
+ await tester.pumpWidget (GlobalStoreWidget (child: MaterialApp (
181
+ navigatorObservers: [testNavObserver],
182
+ home: PerAccountStoreWidget (accountId: eg.selfAccount.id,
183
+ child: BlockContentList (nodes: parseContent (html).nodes)))));
184
+ await tester.pump ();
185
+ await tester.pump ();
186
+ assert (pushedRoutes.length == 1 );
187
+ pushedRoutes.removeLast ();
188
+ return pushedRoutes;
189
+ }
190
+
191
+ testWidgets ('valid internal links are resolved' , (tester) async {
192
+ final pushedRoutes = await prepareContent (tester,
193
+ html: '<p><a href="/#narrow/stream/1-check">stream</a></p>' );
194
+
195
+ await tester.tap (find.text ('stream' ));
196
+ check (testBinding.takeLaunchUrlCalls ()).isEmpty ();
197
+ check (pushedRoutes).single.isA <WidgetRoute >()
198
+ .page.isA <MessageListPage >()
199
+ .narrow.equals (const StreamNarrow (1 ));
200
+ });
201
+
202
+ testWidgets ('invalid internal links are not followed' , (tester) async {
203
+ final pushedRoutes = await prepareContent (tester,
204
+ html: '<p><a href="/#narrow/stream/1-check/topic">invalid</a></p>' );
205
+
206
+ await tester.tap (find.text ('invalid' ));
207
+ final expectedUrl = Uri .parse ('${eg .realmUrl }#narrow/stream/1-check/topic' );
208
+ check (testBinding.takeLaunchUrlCalls ())
209
+ .single.equals ((url: expectedUrl, mode: LaunchMode .externalApplication));
210
+ check (pushedRoutes).isEmpty ();
211
+ });
212
+ });
213
+
161
214
group ('UnicodeEmoji' , () {
162
215
Future <void > prepareContent (WidgetTester tester, String html) async {
163
216
await tester.pumpWidget (MaterialApp (home: BlockContentList (nodes: parseContent (html).nodes)));
0 commit comments