@@ -2,12 +2,17 @@ import 'package:checks/checks.dart';
22import 'package:flutter/widgets.dart' ;
33import 'package:flutter_test/flutter_test.dart' ;
44import 'package:zulip/api/core.dart' ;
5+ import 'package:zulip/api/model/initial_snapshot.dart' ;
6+ import 'package:zulip/model/content.dart' ;
7+ import 'package:zulip/model/store.dart' ;
58import 'package:zulip/widgets/image.dart' ;
69import 'package:zulip/widgets/store.dart' ;
710
811import '../example_data.dart' as eg;
912import '../model/binding.dart' ;
13+ import '../model/test_store.dart' ;
1014import '../test_images.dart' ;
15+ import 'test_app.dart' ;
1116
1217void main () {
1318 TestZulipBinding .ensureInitialized ();
@@ -51,4 +56,100 @@ void main() {
5156 check (tester.takeException ()).isA <AssertionError >();
5257 });
5358 });
59+
60+ group ('ImageThumbnailLocator.resolve' , () {
61+ late PerAccountStore store;
62+
63+ Future <void > prepare (WidgetTester tester) async {
64+ addTearDown (testBinding.reset);
65+
66+ final exampleFormats = [
67+ ThumbnailFormat (name: '840x560.webp' ,
68+ maxWidth: 840 , maxHeight: 560 , animated: false , format: 'webp' ),
69+ ThumbnailFormat (name: '840x560-anim.webp' ,
70+ maxWidth: 840 , maxHeight: 560 , animated: true , format: 'webp' ),
71+ ThumbnailFormat (name: '500x850.jpg' ,
72+ maxWidth: 500 , maxHeight: 850 , animated: false , format: 'jpg' ),
73+ ThumbnailFormat (name: '500x850-anim.jpg' ,
74+ maxWidth: 500 , maxHeight: 850 , animated: true , format: 'jpg' ),
75+ ThumbnailFormat (name: '1000x1000.webp' ,
76+ maxWidth: 1000 , maxHeight: 1000 , animated: false , format: 'webp' ),
77+ ThumbnailFormat (name: '1000x2000-anim.png' ,
78+ maxWidth: 1000 , maxHeight: 2000 , animated: true , format: 'png' ),
79+ ThumbnailFormat (name: '1000x1000-anim.webp' ,
80+ maxWidth: 1000 , maxHeight: 1000 , animated: true , format: 'webp' ),
81+ ThumbnailFormat (name: '1000x2000.png' ,
82+ maxWidth: 1000 , maxHeight: 2000 , animated: false , format: 'png' ),
83+ ];
84+
85+ await testBinding.globalStore.add (eg.selfAccount, eg.initialSnapshot (
86+ serverThumbnailFormats: exampleFormats,
87+ ));
88+
89+ store = await testBinding.globalStore.perAccount (eg.selfAccount.id);
90+ await store.addUser (eg.selfUser);
91+
92+ await tester.pumpWidget (TestZulipApp (accountId: eg.selfAccount.id));
93+ await tester.pump ();
94+ }
95+
96+ void doCheck (
97+ WidgetTester tester,
98+ double width,
99+ double height,
100+ bool animateIfSupported,
101+ String expected, {
102+ required bool animated,
103+ }) {
104+ final locator = ImageThumbnailLocator (
105+ urlPath: '/user_uploads/thumbnail/1/2/a/pic.jpg/840x560.webp' ,
106+ animated: animated,
107+ );
108+
109+ final context = tester.element (find.byType (Placeholder ));
110+ final result = locator.resolve (context,
111+ width: width, height: height,
112+ animationMode: animateIfSupported
113+ ? ImageAnimationMode .animateAlways
114+ : ImageAnimationMode .animateNever);
115+ check (result.toString ()).equals (expected);
116+ }
117+
118+ testWidgets ('animated version does not exist' , (tester) async {
119+ tester.view.devicePixelRatio = 2.0 ;
120+ addTearDown (tester.view.resetDevicePixelRatio);
121+
122+ await prepare (tester);
123+
124+ doCheck (tester, 200 , 200 , false , animated: false ,
125+ 'https://chat.example/user_uploads/thumbnail/1/2/a/pic.jpg/500x850.jpg' );
126+ doCheck (tester, 250 , 425 , true , animated: false ,
127+ 'https://chat.example/user_uploads/thumbnail/1/2/a/pic.jpg/500x850.jpg' );
128+ doCheck (tester, 250 , 425 , false , animated: false ,
129+ 'https://chat.example/user_uploads/thumbnail/1/2/a/pic.jpg/500x850.jpg' );
130+ // Different output from previous because it's is in physical pixels.
131+ doCheck (tester, 300 , 250 , true , animated: false ,
132+ 'https://chat.example/user_uploads/thumbnail/1/2/a/pic.jpg/840x560.webp' );
133+ doCheck (tester, 300 , 250 , false , animated: false ,
134+ 'https://chat.example/user_uploads/thumbnail/1/2/a/pic.jpg/840x560.webp' );
135+ doCheck (tester, 750 , 1000 , false , animated: false ,
136+ 'https://chat.example/user_uploads/thumbnail/1/2/a/pic.jpg/1000x2000.png' );
137+ });
138+
139+ testWidgets ('animated version exists' , (tester) async {
140+ tester.view.devicePixelRatio = 2.0 ;
141+ addTearDown (tester.view.resetDevicePixelRatio);
142+
143+ await prepare (tester);
144+
145+ doCheck (tester, 200 , 200 , false , animated: true ,
146+ 'https://chat.example/user_uploads/thumbnail/1/2/a/pic.jpg/500x850.jpg' );
147+ doCheck (tester, 250 , 425 , true , animated: true ,
148+ 'https://chat.example/user_uploads/thumbnail/1/2/a/pic.jpg/500x850-anim.jpg' );
149+ doCheck (tester, 250 , 425 , false , animated: true ,
150+ 'https://chat.example/user_uploads/thumbnail/1/2/a/pic.jpg/500x850.jpg' );
151+ doCheck (tester, 750 , 1000 , false , animated: true ,
152+ 'https://chat.example/user_uploads/thumbnail/1/2/a/pic.jpg/1000x2000.png' );
153+ });
154+ });
54155}
0 commit comments