@@ -9,12 +9,16 @@ import 'package:flutter/material.dart';
9
9
import 'package:plugin_platform_interface/plugin_platform_interface.dart' ;
10
10
import 'package:video_player_platform_interface/video_player_platform_interface.dart' ;
11
11
import 'package:video_player/video_player.dart' ;
12
+ import 'package:zulip/api/model/model.dart' ;
12
13
import 'package:zulip/model/localizations.dart' ;
14
+ import 'package:zulip/widgets/app.dart' ;
15
+ import 'package:zulip/widgets/content.dart' ;
13
16
import 'package:zulip/widgets/lightbox.dart' ;
14
17
import 'package:zulip/widgets/store.dart' ;
15
18
16
19
import '../example_data.dart' as eg;
17
20
import '../model/binding.dart' ;
21
+ import '../test_images.dart' ;
18
22
import 'dialog_checks.dart' ;
19
23
20
24
const kTestVideoUrl = "https://a/video.mp4" ;
@@ -194,6 +198,87 @@ class FakeVideoPlayerPlatform extends Fake
194
198
void main () {
195
199
TestZulipBinding .ensureInitialized ();
196
200
201
+ group ('_ImageLightboxPage' , () {
202
+ final src = Uri .parse ('https://chat.example/lightbox-image.png' );
203
+
204
+ Future <void > setupPage (WidgetTester tester, {
205
+ Message ? message,
206
+ required Uri ? thumbnailUrl,
207
+ }) async {
208
+ addTearDown (testBinding.reset);
209
+ await testBinding.globalStore.add (eg.selfAccount, eg.initialSnapshot ());
210
+
211
+ await tester.pumpWidget (const ZulipApp ());
212
+ await tester.pump ();
213
+ final navigator = await ZulipApp .navigator;
214
+ navigator.push (getLightboxRoute (
215
+ accountId: eg.selfAccount.id,
216
+ message: message ?? eg.streamMessage (),
217
+ src: src,
218
+ thumbnailUrl: thumbnailUrl,
219
+ mediaType: MediaType .image,
220
+ ));
221
+ await tester.pump (); // per-account store
222
+ await tester.pump (const Duration (milliseconds: 301 )); // nav transition
223
+ }
224
+
225
+ testWidgets ('shows image' , (tester) async {
226
+ prepareBoringImageHttpClient ();
227
+ await setupPage (tester, thumbnailUrl: null );
228
+
229
+ final image = tester.widget <RealmContentNetworkImage >(
230
+ find.byType (RealmContentNetworkImage ));
231
+ check (image.src).equals (src);
232
+
233
+ debugNetworkImageHttpClientProvider = null ;
234
+ });
235
+
236
+ testWidgets ('app bar shows sender name and date' , (tester) async {
237
+ prepareBoringImageHttpClient ();
238
+ final timestamp = DateTime .parse ("2024-07-23 23:12:24" ).millisecondsSinceEpoch ~ / 1000 ;
239
+ final message = eg.streamMessage (sender: eg.otherUser, timestamp: timestamp);
240
+ await setupPage (tester, message: message, thumbnailUrl: null );
241
+
242
+ // We're looking for a RichText, in the app bar, with both the
243
+ // sender's name and the timestamp.
244
+ final labelTextWidget = tester.widget <RichText >(
245
+ find.descendant (of: find.byType (AppBar ).last,
246
+ matching: find.textContaining (findRichText: true ,
247
+ eg.otherUser.fullName)));
248
+ check (labelTextWidget.text.toPlainText ())
249
+ .contains ('Jul 23, 2024 23:12:24' );
250
+
251
+ debugNetworkImageHttpClientProvider = null ;
252
+ });
253
+
254
+ testWidgets ('header and footer hidden and shown by tapping image' , (tester) async {
255
+ prepareBoringImageHttpClient ();
256
+ final message = eg.streamMessage (sender: eg.otherUser);
257
+ await setupPage (tester, message: message, thumbnailUrl: null );
258
+
259
+ tester.widget (find.byType (AppBar ));
260
+ tester.widget (find.byType (BottomAppBar ));
261
+
262
+ await tester.tap (find.byType (ZulipApp ));
263
+ await tester.pump ();
264
+ check (tester.widgetList (find.byType (AppBar ))).isEmpty ();
265
+ check (tester.widgetList (find.byType (BottomAppBar ))).isEmpty ();
266
+
267
+ await tester.tap (find.byType (ZulipApp ));
268
+ await tester.pump ();
269
+ tester.widget (find.byType (AppBar ));
270
+ tester.widget (find.byType (BottomAppBar ));
271
+
272
+ debugNetworkImageHttpClientProvider = null ;
273
+ });
274
+
275
+ // TODO test _CopyLinkButton
276
+ // TODO test thumbnail gets shown, then gets replaced when main image loads
277
+ // TODO test image is scaled down to fit, but not up
278
+ // TODO test image doesn't change size when header and footer hidden/shown
279
+ // TODO test image doesn't show in inset area by default, but does if user zooms/pans it there
280
+ });
281
+
197
282
group ('VideoDurationLabel' , () {
198
283
const cases = [
199
284
(Duration (milliseconds: 1 ), '00:00' , '1ms' ),
0 commit comments