@@ -6,14 +6,18 @@ import 'package:http/http.dart' as http;
66import 'package:test/scaffolding.dart' ;
77import 'package:zulip/api/core.dart' ;
88import 'package:zulip/api/exception.dart' ;
9+ import 'package:zulip/model/binding.dart' ;
910import 'package:zulip/model/localizations.dart' ;
1011
12+ import '../model/binding.dart' ;
1113import '../stdlib_checks.dart' ;
1214import 'exception_checks.dart' ;
1315import 'fake_api.dart' ;
1416import '../example_data.dart' as eg;
1517
1618void main () {
19+ TestZulipBinding .ensureInitialized ();
20+
1721 test ('ApiConnection.get' , () async {
1822 Future <void > checkRequest (Map <String , dynamic >? params, String expectedRelativeUrl) {
1923 return FakeApiConnection .with_ (account: eg.selfAccount, (connection) async {
@@ -24,7 +28,7 @@ void main() {
2428 ..url.asString.equals ('${eg .realmUrl .origin }$expectedRelativeUrl ' )
2529 ..headers.deepEquals ({
2630 ...authHeader (email: eg.selfAccount.email, apiKey: eg.selfAccount.apiKey),
27- ...userAgentHeader () ,
31+ ...kFallbackUserAgentHeader ,
2832 })
2933 ..body.equals ('' );
3034 });
@@ -55,7 +59,7 @@ void main() {
5559 ..url.asString.equals ('${eg .realmUrl .origin }/api/v1/example/route' )
5660 ..headers.deepEquals ({
5761 ...authHeader (email: eg.selfAccount.email, apiKey: eg.selfAccount.apiKey),
58- ...userAgentHeader () ,
62+ ...kFallbackUserAgentHeader ,
5963 if (expectContentType)
6064 'content-type' : 'application/x-www-form-urlencoded; charset=utf-8' ,
6165 })
@@ -88,7 +92,7 @@ void main() {
8892 ..url.asString.equals ('${eg .realmUrl .origin }/api/v1/example/route' )
8993 ..headers.deepEquals ({
9094 ...authHeader (email: eg.selfAccount.email, apiKey: eg.selfAccount.apiKey),
91- ...userAgentHeader () ,
95+ ...kFallbackUserAgentHeader ,
9296 })
9397 ..fields.deepEquals ({})
9498 ..files.single.which ((it) => it
@@ -121,7 +125,7 @@ void main() {
121125 ..url.asString.equals ('${eg .realmUrl .origin }/api/v1/example/route' )
122126 ..headers.deepEquals ({
123127 ...authHeader (email: eg.selfAccount.email, apiKey: eg.selfAccount.apiKey),
124- ...userAgentHeader () ,
128+ ...kFallbackUserAgentHeader ,
125129 if (expectContentType)
126130 'content-type' : 'application/x-www-form-urlencoded; charset=utf-8' ,
127131 })
@@ -308,6 +312,57 @@ void main() {
308312 check (st.toString ()).contains ("distinctivelyNamedFromJson" );
309313 }
310314 });
315+
316+ group ('ApiConnection user-agent' , () {
317+ Future <void > checkUserAgent (String expectedUserAgent) async {
318+ return FakeApiConnection .with_ (account: eg.selfAccount, useBinding: true ,
319+ (connection) async {
320+ connection.prepare (json: {});
321+ await connection.get (kExampleRouteName, (json) => json, 'example/route' , null );
322+ check (connection.lastRequest! ).isA< http.Request > ()
323+ .headers['User-Agent' ].equals (expectedUserAgent);
324+
325+ connection.prepare (json: {});
326+ await connection.post (kExampleRouteName, (json) => json, 'example/route' , null );
327+ check (connection.lastRequest! ).isA< http.Request > ()
328+ .headers['User-Agent' ].equals (expectedUserAgent);
329+
330+ connection.prepare (json: {});
331+ await connection.postFileFromStream (
332+ kExampleRouteName,
333+ (json) => json, 'example/route' ,
334+ Stream .value ([1 ]), 1 ,
335+ );
336+ check (connection.lastRequest! ).isA< http.MultipartRequest > ()
337+ .headers['User-Agent' ].equals (expectedUserAgent);
338+
339+ connection.prepare (json: {});
340+ await connection.delete (kExampleRouteName, (json) => json, 'example/route' , null );
341+ check (connection.lastRequest! ).isA< http.Request > ()
342+ .headers['User-Agent' ].equals (expectedUserAgent);
343+ });
344+ }
345+
346+ const packageInfo = PackageInfo (version: '0.0.1' , buildNumber: '1' );
347+
348+ const testCases = [
349+ ('ZulipFlutter/0.0.1+1 (Android 14)' , AndroidDeviceInfo (release: '14' , sdkInt: 34 ), ),
350+ ('ZulipFlutter/0.0.1+1 (iOS 17.4)' , IosDeviceInfo (systemVersion: '17.4' ), ),
351+ ('ZulipFlutter/0.0.1+1 (macOS 14.5.0)' , MacOsDeviceInfo (majorVersion: 14 , minorVersion: 5 , patchVersion: 0 )),
352+ ('ZulipFlutter/0.0.1+1 (Windows)' , WindowsDeviceInfo (), ),
353+ ('ZulipFlutter/0.0.1+1 (Linux; Fedora Linux 40)' , LinuxDeviceInfo (name: 'Fedora Linux' , versionId: '40' ), ),
354+ ('ZulipFlutter/0.0.1+1 (Linux; Fedora Linux)' , LinuxDeviceInfo (name: 'Fedora Linux' , versionId: null ), ),
355+ ];
356+
357+ for (final (userAgent, deviceInfo) in testCases) {
358+ test ('matches $userAgent ' , () async {
359+ testBinding.deviceInfoResult = deviceInfo;
360+ testBinding.packageInfoResult = packageInfo;
361+ addTearDown (testBinding.reset);
362+ await checkUserAgent (userAgent);
363+ });
364+ }
365+ });
311366}
312367
313368class DistinctiveError extends Error {
0 commit comments