Skip to content

Commit c7d47ce

Browse files
draft
1 parent 2393a19 commit c7d47ce

File tree

2 files changed

+168
-10
lines changed

2 files changed

+168
-10
lines changed

lib/notifications/display.dart

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import 'dart:convert';
2+
import 'dart:io';
23

34
import 'package:http/http.dart' as http;
45
import 'package:collection/collection.dart';
@@ -281,10 +282,13 @@ class NotificationDisplayManager {
281282
try {
282283
// TODO timeout to prevent waiting indefinitely
283284
final resp = await http.get(url);
284-
return resp.bodyBytes;
285+
final bodyBytes = resp.bodyBytes;
286+
if (resp.statusCode == HttpStatus.ok) {
287+
return bodyBytes;
288+
}
285289
} catch (e) {
286290
// TODO(log)
287-
return null;
288291
}
292+
return null;
289293
}
290294
}

test/notifications/display_test.dart

+162-8
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
import 'dart:convert';
2+
import 'dart:io';
23
import 'dart:typed_data';
34

45
import 'package:checks/checks.dart';
56
import 'package:collection/collection.dart';
67
import 'package:fake_async/fake_async.dart';
78
import 'package:firebase_messaging/firebase_messaging.dart';
9+
import 'package:flutter/foundation.dart';
810
import 'package:flutter/material.dart';
911
import 'package:flutter_local_notifications/flutter_local_notifications.dart' hide Message, Person;
1012
import 'package:flutter_test/flutter_test.dart';
13+
import 'package:http/http.dart' as http;
14+
import 'package:http/testing.dart' as http_testing;
1115
import 'package:zulip/api/model/model.dart';
1216
import 'package:zulip/api/notifications.dart';
1317
import 'package:zulip/host/android_notifications.dart';
@@ -25,6 +29,7 @@ import 'package:zulip/widgets/theme.dart';
2529
import '../fake_async.dart';
2630
import '../model/binding.dart';
2731
import '../example_data.dart' as eg;
32+
import '../test_images.dart';
2833
import '../test_navigation.dart';
2934
import '../widgets/message_list_checks.dart';
3035
import '../widgets/page_checks.dart';
@@ -79,6 +84,15 @@ void main() {
7984
TestZulipBinding.ensureInitialized();
8085
final zulipLocalizations = GlobalLocalizations.zulipLocalizations;
8186

87+
final mockHttpClient = http_testing.MockClient(
88+
(request) async => http.Response.bytes(kSolidBlueAvatar, HttpStatus.ok));
89+
90+
void Function() run(Future<void> Function(FakeAsync async) callback) {
91+
return () => http.runWithClient(() {
92+
return awaitFakeAsync(callback);
93+
}, () => mockHttpClient);
94+
}
95+
8296
Future<void> init() async {
8397
addTearDown(testBinding.reset);
8498
testBinding.firebaseMessagingInitialToken = '012abc';
@@ -135,7 +149,9 @@ void main() {
135149
..text.equals(messageData.content)
136150
..timestampMs.equals(messageData.time * 1000)
137151
..person.which((it) => it.isNotNull()
138-
..iconBitmap.which((it) => isLast ? it.isNotNull() : it.isNull())
152+
..iconBitmap.which((it) => isLast
153+
? it.isNotNull().deepEquals(kSolidBlueAvatar)
154+
: it.isNull())
139155
..key.equals(expectedSenderKey)
140156
..name.equals(messageData.senderFullName));
141157
});
@@ -221,7 +237,7 @@ void main() {
221237
async.flushMicrotasks();
222238
}
223239

224-
test('stream message', () => awaitFakeAsync((async) async {
240+
test('stream message', run((async) async {
225241
await init();
226242
final stream = eg.stream();
227243
final message = eg.streamMessage(stream: stream);
@@ -231,7 +247,7 @@ void main() {
231247
expectedTagComponent: 'stream:${message.streamId}:${message.topic}');
232248
}));
233249

234-
test('stream message: multiple messages, same topic', () => awaitFakeAsync((async) async {
250+
test('stream message: multiple messages, same topic', run((async) async {
235251
await init();
236252
final stream = eg.stream();
237253
const topic = 'topic 1';
@@ -267,7 +283,67 @@ void main() {
267283
expectedTagComponent: expectedTagComponent);
268284
}));
269285

270-
test('stream message: stream name omitted', () => awaitFakeAsync((async) async {
286+
test('stream message: multiple messages, different topics', run((async) async {
287+
await init();
288+
final stream = eg.stream();
289+
const topicA = 'topic A';
290+
const topicB = 'topic B';
291+
final message1 = eg.streamMessage(topic: topicA, stream: stream);
292+
final data1 = messageFcmMessage(message1, streamName: stream.name);
293+
final message2 = eg.streamMessage(topic: topicB, stream: stream);
294+
final data2 = messageFcmMessage(message2, streamName: stream.name);
295+
final message3 = eg.streamMessage(topic: topicA, stream: stream);
296+
final data3 = messageFcmMessage(message3, streamName: stream.name);
297+
298+
await receiveFcmMessage(async, data1);
299+
checkNotification(data1,
300+
messageStyleMessages: [data1],
301+
expectedIsGroupConversation: true,
302+
expectedTitle: '#${stream.name} > $topicA',
303+
expectedTagComponent: 'stream:${stream.streamId}:$topicA');
304+
305+
await receiveFcmMessage(async, data2);
306+
checkNotification(data2,
307+
messageStyleMessages: [data2],
308+
expectedIsGroupConversation: true,
309+
expectedTitle: '#${stream.name} > $topicB',
310+
expectedTagComponent: 'stream:${stream.streamId}:$topicB');
311+
312+
await receiveFcmMessage(async, data3);
313+
checkNotification(data3,
314+
messageStyleMessages: [data1, data3],
315+
expectedIsGroupConversation: true,
316+
expectedTitle: '#${stream.name} > $topicA',
317+
expectedTagComponent: 'stream:${stream.streamId}:$topicA');
318+
}));
319+
320+
test('stream message: conversation stays same when stream is renamed', run((async) async {
321+
await init();
322+
var stream = eg.stream(streamId: 1, name: 'Before');
323+
const topic = 'topic';
324+
final message1 = eg.streamMessage(topic: topic, stream: stream);
325+
final data1 = messageFcmMessage(message1, streamName: stream.name);
326+
327+
await receiveFcmMessage(async, data1);
328+
checkNotification(data1,
329+
messageStyleMessages: [data1],
330+
expectedIsGroupConversation: true,
331+
expectedTitle: '#Before > $topic',
332+
expectedTagComponent: 'stream:${stream.streamId}:$topic');
333+
334+
stream = eg.stream(streamId: 1, name: 'After');
335+
final message2 = eg.streamMessage(topic: topic, stream: stream);
336+
final data2 = messageFcmMessage(message2, streamName: stream.name);
337+
338+
await receiveFcmMessage(async, data2);
339+
checkNotification(data2,
340+
messageStyleMessages: [data1, data2],
341+
expectedIsGroupConversation: true,
342+
expectedTitle: '#After > $topic',
343+
expectedTagComponent: 'stream:${stream.streamId}:$topic');
344+
}));
345+
346+
test('stream message: stream name omitted', () => run((async) async {
271347
await init();
272348
final stream = eg.stream();
273349
final message = eg.streamMessage(stream: stream);
@@ -277,7 +353,7 @@ void main() {
277353
expectedTagComponent: 'stream:${message.streamId}:${message.topic}');
278354
}));
279355

280-
test('group DM: 3 users', () => awaitFakeAsync((async) async {
356+
test('group DM: 3 users', () => run((async) async {
281357
await init();
282358
final message = eg.dmMessage(from: eg.thirdUser, to: [eg.otherUser, eg.selfUser]);
283359
await checkNotifications(async, messageFcmMessage(message),
@@ -286,7 +362,7 @@ void main() {
286362
expectedTagComponent: 'dm:${message.allRecipientIds.join(",")}');
287363
}));
288364

289-
test('group DM: more than 3 users', () => awaitFakeAsync((async) async {
365+
test('group DM: more than 3 users', () => run((async) async {
290366
await init();
291367
final message = eg.dmMessage(from: eg.thirdUser,
292368
to: [eg.otherUser, eg.selfUser, eg.fourthUser]);
@@ -296,7 +372,31 @@ void main() {
296372
expectedTagComponent: 'dm:${message.allRecipientIds.join(",")}');
297373
}));
298374

299-
test('1:1 DM', () => awaitFakeAsync((async) async {
375+
test('group DM: title updates with latest sender', () => run((async) async {
376+
await init();
377+
final message1 = eg.dmMessage(from: eg.otherUser, to: [eg.selfUser, eg.thirdUser]);
378+
final data1 = messageFcmMessage(message1);
379+
final message2 = eg.dmMessage(from: eg.thirdUser, to: [eg.selfUser, eg.otherUser]);
380+
final data2 = messageFcmMessage(message2);
381+
382+
final expectedTagComponent = 'dm:${message1.allRecipientIds.join(",")}';
383+
384+
await receiveFcmMessage(async, data1);
385+
checkNotification(data1,
386+
messageStyleMessages: [data1],
387+
expectedIsGroupConversation: true,
388+
expectedTitle: "${eg.otherUser.fullName} to you and 1 other",
389+
expectedTagComponent: expectedTagComponent);
390+
391+
await receiveFcmMessage(async, data2);
392+
checkNotification(data2,
393+
messageStyleMessages: [data1, data2],
394+
expectedIsGroupConversation: true,
395+
expectedTitle: "${eg.thirdUser.fullName} to you and 1 other",
396+
expectedTagComponent: expectedTagComponent);
397+
}));
398+
399+
test('1:1 DM', () => run((async) async {
300400
await init();
301401
final message = eg.dmMessage(from: eg.otherUser, to: [eg.selfUser]);
302402
await checkNotifications(async, messageFcmMessage(message),
@@ -305,7 +405,61 @@ void main() {
305405
expectedTagComponent: 'dm:${message.allRecipientIds.join(",")}');
306406
}));
307407

308-
test('self-DM', () => awaitFakeAsync((async) async {
408+
test('1:1 DM: title updates when sender name changes', () => run((async) async {
409+
await init();
410+
final otherUser = eg.user(fullName: 'Before');
411+
final message1 = eg.dmMessage(from: otherUser, to: [eg.selfUser]);
412+
final data1 = messageFcmMessage(message1);
413+
414+
final expectedTagComponent = 'dm:${message1.allRecipientIds.join(",")}';
415+
416+
await receiveFcmMessage(async, data1);
417+
checkNotification(data1,
418+
messageStyleMessages: [data1],
419+
expectedIsGroupConversation: false,
420+
expectedTitle: 'Before',
421+
expectedTagComponent: expectedTagComponent);
422+
423+
otherUser.fullName = 'After';
424+
final message2 = eg.dmMessage(from: otherUser, to: [eg.selfUser]);
425+
final data2 = messageFcmMessage(message2);
426+
427+
await receiveFcmMessage(async, data2);
428+
checkNotification(data2,
429+
messageStyleMessages: [data1, data2],
430+
expectedIsGroupConversation: false,
431+
expectedTitle: 'After',
432+
expectedTagComponent: expectedTagComponent);
433+
}));
434+
435+
test('1:1 DM: conversation stays same when sender email changes', () => run((async) async {
436+
await init();
437+
final otherUser = eg.user(email: '[email protected]');
438+
final message1 = eg.dmMessage(from: otherUser, to: [eg.selfUser]);
439+
final data1 = messageFcmMessage(message1);
440+
441+
final expectedTagComponent = 'dm:${message1.allRecipientIds.join(",")}';
442+
443+
await receiveFcmMessage(async, data1);
444+
checkNotification(data1,
445+
messageStyleMessages: [data1],
446+
expectedIsGroupConversation: false,
447+
expectedTitle: otherUser.fullName,
448+
expectedTagComponent: expectedTagComponent);
449+
450+
otherUser.email = '[email protected]';
451+
final message2 = eg.dmMessage(from: otherUser, to: [eg.selfUser]);
452+
final data2 = messageFcmMessage(message2);
453+
454+
await receiveFcmMessage(async, data2);
455+
checkNotification(data2,
456+
messageStyleMessages: [data1, data2],
457+
expectedIsGroupConversation: false,
458+
expectedTitle: otherUser.fullName,
459+
expectedTagComponent: expectedTagComponent);
460+
}));
461+
462+
test('self-DM', () => run((async) async {
309463
await init();
310464
final message = eg.dmMessage(from: eg.selfUser, to: []);
311465
await checkNotifications(async, messageFcmMessage(message),

0 commit comments

Comments
 (0)