1
+ import 'dart:convert' ;
2
+
1
3
import 'package:checks/checks.dart' ;
4
+ import 'package:http/http.dart' as http;
2
5
import 'package:test/scaffolding.dart' ;
3
6
import 'package:zulip/api/model/events.dart' ;
4
7
import 'package:zulip/api/model/model.dart' ;
8
+ import 'package:zulip/api/model/narrow.dart' ;
5
9
import 'package:zulip/api/route/messages.dart' ;
6
10
import 'package:zulip/model/content.dart' ;
7
11
import 'package:zulip/model/message_list.dart' ;
@@ -11,6 +15,7 @@ import 'package:zulip/model/store.dart';
11
15
import '../api/fake_api.dart' ;
12
16
import '../api/model/model_checks.dart' ;
13
17
import '../example_data.dart' as eg;
18
+ import '../stdlib_checks.dart' ;
14
19
import 'content_checks.dart' ;
15
20
16
21
void main () async {
@@ -58,6 +63,106 @@ void main() async {
58
63
checkNotifiedOnce ();
59
64
}
60
65
66
+ void checkLastRequest ({
67
+ required ApiNarrow narrow,
68
+ required String anchor,
69
+ bool ? includeAnchor,
70
+ required int numBefore,
71
+ required int numAfter,
72
+ }) {
73
+ check (connection.lastRequest).isA< http.Request > ()
74
+ ..method.equals ('GET' )
75
+ ..url.path.equals ('/api/v1/messages' )
76
+ ..url.queryParameters.deepEquals ({
77
+ 'narrow' : jsonEncode (narrow),
78
+ 'anchor' : anchor,
79
+ if (includeAnchor != null ) 'include_anchor' : includeAnchor.toString (),
80
+ 'num_before' : numBefore.toString (),
81
+ 'num_after' : numAfter.toString (),
82
+ });
83
+ }
84
+
85
+ test ('fetch' , () async {
86
+ const narrow = AllMessagesNarrow ();
87
+ prepare (narrow: narrow);
88
+ connection.prepare (json: newestResult (
89
+ foundOldest: false ,
90
+ messages: List .generate (100 , (i) => eg.streamMessage (id: 1000 + i)),
91
+ ).toJson ());
92
+ final fetchFuture = model.fetch ();
93
+ check (model).fetched.isFalse ();
94
+ checkInvariants (model);
95
+
96
+ checkNotNotified ();
97
+ await fetchFuture;
98
+ checkNotifiedOnce ();
99
+ check (model).messages.length.equals (100 );
100
+ checkLastRequest (
101
+ narrow: narrow.apiEncode (),
102
+ anchor: 'newest' ,
103
+ numBefore: 100 ,
104
+ numAfter: 10 ,
105
+ );
106
+ });
107
+
108
+ test ('fetch, short history' , () async {
109
+ prepare ();
110
+ connection.prepare (json: newestResult (
111
+ foundOldest: true ,
112
+ messages: List .generate (30 , (i) => eg.streamMessage (id: 1000 + i)),
113
+ ).toJson ());
114
+ await model.fetch ();
115
+ checkNotifiedOnce ();
116
+ check (model).messages.length.equals (30 );
117
+ });
118
+
119
+ test ('fetch, no messages found' , () async {
120
+ prepare ();
121
+ connection.prepare (json: newestResult (
122
+ foundOldest: true ,
123
+ messages: [],
124
+ ).toJson ());
125
+ await model.fetch ();
126
+ checkNotifiedOnce ();
127
+ check (model)
128
+ ..fetched.isTrue ()
129
+ ..messages.isEmpty ();
130
+ });
131
+
132
+ test ('maybeAddMessage' , () async {
133
+ final stream = eg.stream ();
134
+ prepare (narrow: StreamNarrow (stream.streamId));
135
+ await prepareMessages (foundOldest: true , messages:
136
+ List .generate (30 , (i) => eg.streamMessage (id: 1000 + i, stream: stream)));
137
+
138
+ check (model).messages.length.equals (30 );
139
+ model.maybeAddMessage (eg.streamMessage (id: 1100 , stream: stream));
140
+ checkNotifiedOnce ();
141
+ check (model).messages.length.equals (31 );
142
+ });
143
+
144
+ test ('maybeAddMessage, not in narrow' , () async {
145
+ final stream = eg.stream (streamId: 123 );
146
+ prepare (narrow: StreamNarrow (stream.streamId));
147
+ await prepareMessages (foundOldest: true , messages:
148
+ List .generate (30 , (i) => eg.streamMessage (id: 1000 + i, stream: stream)));
149
+
150
+ check (model).messages.length.equals (30 );
151
+ final otherStream = eg.stream (streamId: 234 );
152
+ model.maybeAddMessage (eg.streamMessage (id: 1100 , stream: otherStream));
153
+ checkNotNotified ();
154
+ check (model).messages.length.equals (30 );
155
+ });
156
+
157
+ test ('maybeAddMessage, before fetch' , () async {
158
+ final stream = eg.stream ();
159
+ prepare (narrow: StreamNarrow (stream.streamId));
160
+ model.maybeAddMessage (eg.streamMessage (id: 1100 , stream: stream));
161
+ checkNotNotified ();
162
+ check (model).fetched.isFalse ();
163
+ checkInvariants (model);
164
+ });
165
+
61
166
test ('findMessageWithId' , () async {
62
167
prepare ();
63
168
await prepareMessages (foundOldest: true , messages: [
@@ -254,6 +359,29 @@ void main() async {
254
359
});
255
360
});
256
361
});
362
+
363
+ test ('reassemble' , () async {
364
+ final stream = eg.stream ();
365
+ prepare (narrow: StreamNarrow (stream.streamId));
366
+ await prepareMessages (foundOldest: true , messages:
367
+ List .generate (30 , (i) => eg.streamMessage (id: 1000 + i, stream: stream)));
368
+ model.maybeAddMessage (eg.streamMessage (id: 1100 , stream: stream));
369
+ checkNotifiedOnce ();
370
+ check (model).messages.length.equals (31 );
371
+
372
+ // Mess with model.contents, to simulate it having come from
373
+ // a previous version of the code.
374
+ final correctContent = parseContent (model.messages[0 ].content);
375
+ model.contents[0 ] = const ZulipContent (nodes: [
376
+ ParagraphNode (links: null , nodes: [TextNode ('something outdated' )])
377
+ ]);
378
+ check (model.contents[0 ]).not (it ()..equalsNode (correctContent));
379
+
380
+ model.reassemble ();
381
+ checkNotifiedOnce ();
382
+ check (model).messages.length.equals (31 );
383
+ check (model.contents[0 ]).equalsNode (correctContent);
384
+ });
257
385
}
258
386
259
387
void checkInvariants (MessageListView model) {
0 commit comments