@@ -6,27 +6,34 @@ import 'package:http/http.dart' as http;
6
6
import 'package:test/scaffolding.dart' ;
7
7
import 'package:zulip/api/core.dart' ;
8
8
import 'package:zulip/api/exception.dart' ;
9
+ import 'package:zulip/model/binding.dart' ;
9
10
import 'package:zulip/model/localizations.dart' ;
10
11
12
+ import '../model/binding.dart' ;
11
13
import '../stdlib_checks.dart' ;
12
14
import 'exception_checks.dart' ;
13
15
import 'fake_api.dart' ;
14
16
import '../example_data.dart' as eg;
15
17
16
18
void main () {
19
+ TestZulipBinding .ensureInitialized ();
20
+ tearDown (testBinding.reset);
21
+
17
22
test ('ApiConnection.get' , () async {
18
23
Future <void > checkRequest (Map <String , dynamic >? params, String expectedRelativeUrl) {
19
- return FakeApiConnection .with_ (account: eg.selfAccount, (connection) async {
20
- connection.prepare (json: {});
21
- await connection.get (kExampleRouteName, (json) => json, 'example/route' , params);
22
- check (connection.lastRequest! ).isA< http.Request > ()
23
- ..method.equals ('GET' )
24
- ..url.asString.equals ('${eg .realmUrl .origin }$expectedRelativeUrl ' )
25
- ..headers.deepEquals ({
26
- ...authHeader (email: eg.selfAccount.email, apiKey: eg.selfAccount.apiKey),
27
- ...userAgentHeader (),
28
- })
29
- ..body.equals ('' );
24
+ return FakeApiConnection .with_ (account: eg.selfAccount,
25
+ useBinding: true ,
26
+ (connection) async {
27
+ connection.prepare (json: {});
28
+ await connection.get (kExampleRouteName, (json) => json, 'example/route' , params);
29
+ check (connection.lastRequest! ).isA< http.Request > ()
30
+ ..method.equals ('GET' )
31
+ ..url.asString.equals ('${eg .realmUrl .origin }$expectedRelativeUrl ' )
32
+ ..headers.deepEquals ({
33
+ ...authHeader (email: eg.selfAccount.email, apiKey: eg.selfAccount.apiKey),
34
+ ...userAgentHeader (),
35
+ })
36
+ ..body.equals ('' );
30
37
});
31
38
}
32
39
@@ -47,19 +54,21 @@ void main() {
47
54
48
55
test ('ApiConnection.post' , () async {
49
56
Future <void > checkRequest (Map <String , dynamic >? params, String expectedBody, {bool expectContentType = true }) {
50
- return FakeApiConnection .with_ (account: eg.selfAccount, (connection) async {
51
- connection.prepare (json: {});
52
- await connection.post (kExampleRouteName, (json) => json, 'example/route' , params);
53
- check (connection.lastRequest! ).isA< http.Request > ()
54
- ..method.equals ('POST' )
55
- ..url.asString.equals ('${eg .realmUrl .origin }/api/v1/example/route' )
56
- ..headers.deepEquals ({
57
- ...authHeader (email: eg.selfAccount.email, apiKey: eg.selfAccount.apiKey),
58
- ...userAgentHeader (),
59
- if (expectContentType)
60
- 'content-type' : 'application/x-www-form-urlencoded; charset=utf-8' ,
61
- })
62
- ..body.equals (expectedBody);
57
+ return FakeApiConnection .with_ (account: eg.selfAccount,
58
+ useBinding: true ,
59
+ (connection) async {
60
+ connection.prepare (json: {});
61
+ await connection.post (kExampleRouteName, (json) => json, 'example/route' , params);
62
+ check (connection.lastRequest! ).isA< http.Request > ()
63
+ ..method.equals ('POST' )
64
+ ..url.asString.equals ('${eg .realmUrl .origin }/api/v1/example/route' )
65
+ ..headers.deepEquals ({
66
+ ...authHeader (email: eg.selfAccount.email, apiKey: eg.selfAccount.apiKey),
67
+ ...userAgentHeader (),
68
+ if (expectContentType)
69
+ 'content-type' : 'application/x-www-form-urlencoded; charset=utf-8' ,
70
+ })
71
+ ..body.equals (expectedBody);
63
72
});
64
73
}
65
74
@@ -78,26 +87,28 @@ void main() {
78
87
79
88
test ('ApiConnection.postFileFromStream' , () async {
80
89
Future <void > checkRequest (List <List <int >> content, int length, String ? filename) {
81
- return FakeApiConnection .with_ (account: eg.selfAccount, (connection) async {
82
- connection.prepare (json: {});
83
- await connection.postFileFromStream (
84
- kExampleRouteName, (json) => json, 'example/route' ,
85
- Stream .fromIterable (content), length, filename: filename);
86
- check (connection.lastRequest! ).isA< http.MultipartRequest > ()
87
- ..method.equals ('POST' )
88
- ..url.asString.equals ('${eg .realmUrl .origin }/api/v1/example/route' )
89
- ..headers.deepEquals ({
90
- ...authHeader (email: eg.selfAccount.email, apiKey: eg.selfAccount.apiKey),
91
- ...userAgentHeader (),
92
- })
93
- ..fields.deepEquals ({})
94
- ..files.single.which ((it) => it
95
- ..field.equals ('file' )
96
- ..length.equals (length)
97
- ..filename.equals (filename)
98
- ..has <Future <List <int >>>((f) => f.finalize ().toBytes (), 'contents' )
99
- .completes ((it) => it.deepEquals (content.expand ((l) => l)))
100
- );
90
+ return FakeApiConnection .with_ (account: eg.selfAccount,
91
+ useBinding: true ,
92
+ (connection) async {
93
+ connection.prepare (json: {});
94
+ await connection.postFileFromStream (
95
+ kExampleRouteName, (json) => json, 'example/route' ,
96
+ Stream .fromIterable (content), length, filename: filename);
97
+ check (connection.lastRequest! ).isA< http.MultipartRequest > ()
98
+ ..method.equals ('POST' )
99
+ ..url.asString.equals ('${eg .realmUrl .origin }/api/v1/example/route' )
100
+ ..headers.deepEquals ({
101
+ ...authHeader (email: eg.selfAccount.email, apiKey: eg.selfAccount.apiKey),
102
+ ...userAgentHeader (),
103
+ })
104
+ ..fields.deepEquals ({})
105
+ ..files.single.which ((it) => it
106
+ ..field.equals ('file' )
107
+ ..length.equals (length)
108
+ ..filename.equals (filename)
109
+ ..has <Future <List <int >>>((f) => f.finalize ().toBytes (), 'contents' )
110
+ .completes ((it) => it.deepEquals (content.expand ((l) => l)))
111
+ );
101
112
});
102
113
}
103
114
@@ -113,19 +124,21 @@ void main() {
113
124
114
125
test ('ApiConnection.delete' , () async {
115
126
Future <void > checkRequest (Map <String , dynamic >? params, String expectedBody, {bool expectContentType = true }) {
116
- return FakeApiConnection .with_ (account: eg.selfAccount, (connection) async {
117
- connection.prepare (json: {});
118
- await connection.delete (kExampleRouteName, (json) => json, 'example/route' , params);
119
- check (connection.lastRequest! ).isA< http.Request > ()
120
- ..method.equals ('DELETE' )
121
- ..url.asString.equals ('${eg .realmUrl .origin }/api/v1/example/route' )
122
- ..headers.deepEquals ({
123
- ...authHeader (email: eg.selfAccount.email, apiKey: eg.selfAccount.apiKey),
124
- ...userAgentHeader (),
125
- if (expectContentType)
126
- 'content-type' : 'application/x-www-form-urlencoded; charset=utf-8' ,
127
- })
128
- ..body.equals (expectedBody);
127
+ return FakeApiConnection .with_ (account: eg.selfAccount,
128
+ useBinding: true ,
129
+ (connection) async {
130
+ connection.prepare (json: {});
131
+ await connection.delete (kExampleRouteName, (json) => json, 'example/route' , params);
132
+ check (connection.lastRequest! ).isA< http.Request > ()
133
+ ..method.equals ('DELETE' )
134
+ ..url.asString.equals ('${eg .realmUrl .origin }/api/v1/example/route' )
135
+ ..headers.deepEquals ({
136
+ ...authHeader (email: eg.selfAccount.email, apiKey: eg.selfAccount.apiKey),
137
+ ...userAgentHeader (),
138
+ if (expectContentType)
139
+ 'content-type' : 'application/x-www-form-urlencoded; charset=utf-8' ,
140
+ })
141
+ ..body.equals (expectedBody);
129
142
});
130
143
}
131
144
@@ -308,6 +321,41 @@ void main() {
308
321
check (st.toString ()).contains ("distinctivelyNamedFromJson" );
309
322
}
310
323
});
324
+
325
+ group ('ApiConnection user-agent' , () {
326
+ Future <void > checkUserAgent (String expectedUserAgent) async {
327
+ return FakeApiConnection .with_ (account: eg.selfAccount,
328
+ useBinding: true ,
329
+ (connection) async {
330
+ connection.prepare (json: {});
331
+ await connection.get (kExampleRouteName, (json) => json, 'example/route' , null );
332
+ check (connection.lastRequest! ).isA< http.Request > ()
333
+ .headers.deepEquals ({
334
+ ...authHeader (email: eg.selfAccount.email, apiKey: eg.selfAccount.apiKey),
335
+ ...{'User-Agent' : expectedUserAgent},
336
+ });
337
+ });
338
+ }
339
+
340
+ final packageInfo = PackageInfo (version: '0.0.1' , buildNumber: '1' );
341
+
342
+ final testCases = [
343
+ ('ZulipFlutter/0.0.1+1 (Android 14)' , AndroidDeviceInfo (release: '14' , sdkInt: 34 ), packageInfo),
344
+ ('ZulipFlutter/0.0.1+1 (iOS 17.4)' , IosDeviceInfo (systemVersion: '17.4' ), packageInfo),
345
+ ('ZulipFlutter/0.0.1+1 (macOS 14.5.0)' , MacOsDeviceInfo (majorVersion: 14 , minorVersion: 5 , patchVersion: 0 ), packageInfo),
346
+ ('ZulipFlutter/0.0.1+1 (Windows)' , WindowsDeviceInfo (), packageInfo),
347
+ ('ZulipFlutter/0.0.1+1 (Linux; Fedora Linux 40)' , LinuxDeviceInfo (name: 'Fedora Linux' , versionId: '40' ), packageInfo),
348
+ ('ZulipFlutter/0.0.1+1 (Linux; Fedora Linux)' , LinuxDeviceInfo (name: 'Fedora Linux' , versionId: null ), packageInfo),
349
+ ];
350
+
351
+ for (final (userAgent, deviceInfo, packageInfo) in testCases) {
352
+ test ('matches $userAgent ' , () async {
353
+ testBinding.deviceInfoResult = deviceInfo;
354
+ testBinding.packageInfoResult = packageInfo;
355
+ await checkUserAgent (userAgent);
356
+ });
357
+ }
358
+ });
311
359
}
312
360
313
361
class DistinctiveError extends Error {
0 commit comments