Skip to content

Commit 410de59

Browse files
committed
squash? Test everything, parameterized
Signed-off-by: Zixuan James Li <[email protected]>
1 parent 5eb0863 commit 410de59

File tree

1 file changed

+124
-190
lines changed

1 file changed

+124
-190
lines changed

test/model/unreads_test.dart

+124-190
Original file line numberDiff line numberDiff line change
@@ -470,212 +470,146 @@ void main() {
470470
}
471471
});
472472

473-
// For the reader:
474-
// This implements tests without heavily parameterizing them;
475-
// see and compare with the next commit that changes this.
476473
group('moves', () {
477-
final origChannel = eg.stream();
474+
final origChannel = eg.stream(name: 'old channel');
475+
final newChannel = eg.stream(name: 'new channel');
476+
final newUnsubscribedChannel = eg.stream(name: 'new unsubscribed channel');
478477
const origTopic = 'origTopic';
479478
const newTopic = 'newTopic';
480479

481-
Future<void> prepareStore() async {
482-
prepare();
483-
await channelStore.addStream(origChannel);
484-
await channelStore.addSubscription(eg.subscription(origChannel));
485-
}
486-
487-
group('move read messages', () {
488-
final readMessages = List<StreamMessage>.generate(10,
489-
(_) => eg.streamMessage(
490-
stream: origChannel, topic: origTopic, flags: [MessageFlag.read]));
491-
492-
test('to new channel', () async {
493-
await prepareStore();
494-
final newChannel = eg.stream();
495-
await channelStore.addStream(newChannel);
496-
await channelStore.addSubscription(eg.subscription(newChannel));
497-
fillWithMessages(readMessages);
498-
499-
model.handleUpdateMessageEvent(eg.updateMessageEventMoveFrom(
500-
origMessages: readMessages,
501-
newStreamId: newChannel.streamId));
502-
checkNotNotified();
503-
checkMatchesMessages([]);
504-
});
505-
506-
test('to new topic', () async {
507-
await prepareStore();
508-
fillWithMessages(readMessages);
480+
void doTestMove(String moveDescription, {
481+
ZulipStream? channelAfterMove,
482+
String? topicAfterMove,
483+
required Set<StreamMessage> messages,
484+
required Set<StreamMessage> messagesToMove,
485+
required Set<StreamMessage> expectedUnreadMessagesAfterMove,
486+
}) async {
487+
assert(messages.containsAll(messagesToMove));
488+
assert(channelAfterMove != null || topicAfterMove != null);
489+
channelAfterMove ??= origChannel;
490+
topicAfterMove ??= origTopic;
491+
492+
test('$moveDescription from #${origChannel.name} > $origTopic, to #${channelAfterMove.name} > $newTopic', () async {
493+
prepare();
494+
await channelStore.addStreams(
495+
[origChannel, newChannel, newUnsubscribedChannel]);
496+
await channelStore.addSubscriptions(
497+
[eg.subscription(origChannel), eg.subscription(newChannel)]);
498+
fillWithMessages(messages);
509499

510500
model.handleUpdateMessageEvent(eg.updateMessageEventMoveFrom(
511-
origMessages: readMessages,
512-
newTopicStr: newTopic));
513-
checkNotNotified();
514-
checkMatchesMessages([]);
515-
});
516-
517-
test('from topic with unreads', () async {
518-
await prepareStore();
519-
final unreadMessage = eg.streamMessage(
520-
stream: origChannel, topic: origTopic);
521-
fillWithMessages([...readMessages, unreadMessage]);
522-
523-
model.handleUpdateMessageEvent(eg.updateMessageEventMoveFrom(
524-
origMessages: readMessages,
525-
newTopicStr: newTopic));
526-
checkNotNotified();
527-
checkMatchesMessages([unreadMessage]);
528-
});
529-
530-
test('to topic with unreads', () async {
531-
await prepareStore();
532-
final unreadMessage = eg.streamMessage(
533-
stream: origChannel, topic: newTopic);
534-
fillWithMessages([...readMessages, unreadMessage]);
535-
536-
model.handleUpdateMessageEvent(eg.updateMessageEventMoveFrom(
537-
origMessages: readMessages,
538-
newTopicStr: newTopic,
501+
origMessages: messagesToMove.toList(),
502+
newStreamId: channelAfterMove!.streamId,
503+
newTopicStr: topicAfterMove,
539504
));
540-
checkNotNotified();
541-
checkMatchesMessages([unreadMessage]);
542-
});
543-
});
544-
545-
group('move unread messages', () {
546-
final unreadMessages = List<StreamMessage>.generate(10,
547-
(_) => eg.streamMessage(stream: origChannel, topic: origTopic));
548-
549-
test('to another subscribed channel; same topic name', () async {
550-
await prepareStore();
551-
final newChannel = eg.stream();
552-
await channelStore.addStream(newChannel);
553-
await channelStore.addSubscription(eg.subscription(newChannel));
554-
fillWithMessages(unreadMessages);
555-
556-
model.handleUpdateMessageEvent(eg.updateMessageEventMoveFrom(
557-
origMessages: unreadMessages,
558-
newStreamId: newChannel.streamId));
559-
checkNotifiedOnce();
560-
checkMatchesMessages([
561-
for (final message in unreadMessages)
562-
Message.fromJson(
563-
message.toJson()..['stream_id'] = newChannel.streamId),
564-
]);
565-
});
566-
567-
test('to another subscribed channel; different topic name', () async {
568-
await prepareStore();
569-
final newChannel = eg.stream();
570-
await channelStore.addStream(newChannel);
571-
await channelStore.addSubscription(eg.subscription(newChannel));
572-
fillWithMessages(unreadMessages);
573-
574-
model.handleUpdateMessageEvent(eg.updateMessageEventMoveFrom(
575-
origMessages: unreadMessages,
576-
newStreamId: newChannel.streamId,
577-
newTopicStr: newTopic));
578-
checkNotifiedOnce();
579-
checkMatchesMessages([
580-
for (final message in unreadMessages)
581-
Message.fromJson(
582-
message.toJson()
583-
..['stream_id'] = newChannel.streamId
584-
..['subject'] = newTopic
585-
),
586-
]);
587-
});
588-
589-
test('to unsubscribed channel', () async {
590-
await prepareStore();
591-
final newChannel = eg.stream();
592-
await channelStore.addStream(newChannel);
593-
assert(!channelStore.subscriptions.containsKey(newChannel.streamId));
594-
fillWithMessages(unreadMessages);
595-
596-
model.handleUpdateMessageEvent(eg.updateMessageEventMoveFrom(
597-
origMessages: unreadMessages,
598-
newStreamId: newChannel.streamId));
599-
checkNotifiedOnce();
600-
checkMatchesMessages([]);
601-
});
602-
603-
test('to new topic', () async {
604-
await prepareStore();
605-
fillWithMessages(unreadMessages);
606-
607-
model.handleUpdateMessageEvent(eg.updateMessageEventMoveFrom(
608-
origMessages: unreadMessages,
609-
newTopicStr: newTopic));
610-
checkNotifiedOnce();
611-
checkMatchesMessages([
612-
for (final message in unreadMessages)
613-
Message.fromJson(message.toJson()..['subject'] = newTopic),
614-
]);
615-
});
616-
617-
test('from topic containing other unreads', () async {
618-
await prepareStore();
619-
final unreadMessage = eg.streamMessage(
620-
stream: origChannel, topic: origTopic);
621-
fillWithMessages([...unreadMessages, unreadMessage]);
622-
623-
model.handleUpdateMessageEvent(eg.updateMessageEventMoveFrom(
624-
origMessages: unreadMessages,
625-
newTopicStr: newTopic));
626-
checkNotifiedOnce();
505+
final movedUnreads =
506+
expectedUnreadMessagesAfterMove.intersection(messagesToMove);
507+
final otherUnreads =
508+
expectedUnreadMessagesAfterMove.difference(messagesToMove);
627509
checkMatchesMessages([
628-
for (final message in unreadMessages)
629-
Message.fromJson(message.toJson()..['subject'] = newTopic),
630-
unreadMessage,
510+
for (final message in movedUnreads)
511+
StreamMessage.fromJson(message.toJson()
512+
..['stream_id'] = channelAfterMove.streamId
513+
..['subject'] = topicAfterMove),
514+
...otherUnreads,
631515
]);
516+
// The union of `movedUnreads` and `otherUnreads` might not contain
517+
// some unreads found with this check, since unreads can be dropped
518+
// when they are moved to an unsubscribed channel.
519+
messagesToMove.any(
520+
(message) => !message.flags.contains(MessageFlag.read)
521+
) ? checkNotifiedOnce()
522+
: checkNotNotified();
632523
});
524+
}
633525

634-
test('to topic containing other unreads', () async {
635-
await prepareStore();
636-
final unreadMessage = eg.streamMessage(
637-
stream: origChannel, topic: newTopic);
638-
fillWithMessages([...unreadMessages, unreadMessage]);
526+
final unreadMessages = List<StreamMessage>.generate(10,
527+
(_) => eg.streamMessage(stream: origChannel, topic: origTopic)).toSet();
528+
final readMessages = List<StreamMessage>.generate(10,
529+
(_) => eg.streamMessage(
530+
stream: origChannel, topic: origTopic, flags: [MessageFlag.read])).toSet();
531+
final messagesAtStart = unreadMessages.union(readMessages);
532+
final messagesToMoveCases = [
533+
('move some unread messages', unreadMessages.take(5).toSet()),
534+
('move some read messages', readMessages.take(5).toSet()),
535+
('move all unread messages', unreadMessages),
536+
('move all read messages', readMessages),
537+
('move all messages', messagesAtStart),
538+
];
639539

640-
model.handleUpdateMessageEvent(eg.updateMessageEventMoveFrom(
641-
origMessages: unreadMessages,
642-
newTopicStr: newTopic));
643-
checkNotifiedOnce();
644-
checkMatchesMessages([
645-
for (final message in unreadMessages)
646-
Message.fromJson(message.toJson()..['subject'] = newTopic),
647-
unreadMessage,
648-
]);
649-
});
540+
group('move to conversations with unreads', () {
541+
final destinations = [
542+
(newChannel, newTopic),
543+
(newChannel, null),
544+
(null, newTopic),
545+
];
546+
for (final (moveDescription, messagesToMove) in messagesToMoveCases) {
547+
for (final (channel, topic) in destinations) {
548+
final unreadMessagesAtDestination = List<StreamMessage>.generate(10,
549+
(_) => eg.streamMessage(stream: channel, topic: topic)).toSet();
550+
doTestMove(moveDescription,
551+
channelAfterMove: channel,
552+
topicAfterMove: topic,
553+
messages: messagesAtStart.union(unreadMessagesAtDestination),
554+
messagesToMove: messagesToMove,
555+
expectedUnreadMessagesAfterMove:
556+
unreadMessages.union(unreadMessagesAtDestination));
557+
}
558+
}
559+
});
650560

651-
test('tolerates unsorted messages', () async {
652-
await prepareStore();
653-
final unreadMessages = List.generate(10,
654-
(i) => eg.streamMessage(id: 1000-i, stream: origChannel, topic: origTopic));
655-
fillWithMessages(unreadMessages);
561+
group('move to conversations in unsubscribed channels', () {
562+
final unsubscribedDestinations = [
563+
(newUnsubscribedChannel, newTopic),
564+
(newUnsubscribedChannel, null),
565+
];
566+
for (final (moveDescription, messagesToMove) in messagesToMoveCases) {
567+
for (final (channel, topic) in unsubscribedDestinations) {
568+
doTestMove(moveDescription,
569+
channelAfterMove: channel,
570+
topicAfterMove: topic,
571+
messages: messagesAtStart,
572+
messagesToMove: messagesToMove,
573+
expectedUnreadMessagesAfterMove:
574+
unreadMessages.difference(messagesToMove));
575+
}
576+
}
577+
});
656578

657-
model.handleUpdateMessageEvent(eg.updateMessageEventMoveFrom(
658-
origMessages: unreadMessages,
659-
newTopicStr: newTopic));
660-
checkNotifiedOnce();
661-
checkMatchesMessages([
662-
for (final message in unreadMessages)
663-
Message.fromJson(message.toJson()..['subject'] = newTopic)
664-
]);
665-
});
579+
test('tolerates unsorted messages', () async {
580+
prepare();
581+
await channelStore.addStream(origChannel);
582+
await channelStore.addSubscription(eg.subscription(origChannel));
583+
final unreadMessages = List.generate(10,
584+
(i) => eg.streamMessage(id: 1000-i, stream: origChannel, topic: origTopic));
585+
fillWithMessages(unreadMessages);
666586

667-
test('tolerates unreads unknown to the model', () async {
668-
await prepareStore();
669-
final unknownUnreadMessage = eg.streamMessage(
670-
stream: eg.stream(), topic: origTopic);
671-
fillWithMessages(unreadMessages);
587+
model.handleUpdateMessageEvent(eg.updateMessageEventMoveFrom(
588+
origMessages: unreadMessages,
589+
newTopicStr: newTopic));
590+
checkNotifiedOnce();
591+
checkMatchesMessages([
592+
for (final message in unreadMessages)
593+
Message.fromJson(message.toJson()..['subject'] = newTopic)
594+
]);
595+
});
672596

673-
model.handleUpdateMessageEvent(eg.updateMessageEventMoveFrom(
674-
origMessages: [unknownUnreadMessage],
675-
newTopicStr: newTopic));
676-
checkNotNotified();
677-
checkMatchesMessages(unreadMessages);
678-
});
597+
test('tolerates unreads unknown to the model', () async {
598+
prepare();
599+
await channelStore.addStream(origChannel);
600+
await channelStore.addSubscription(eg.subscription(origChannel));
601+
fillWithMessages(unreadMessages);
602+
603+
final unknownChannel = eg.stream();
604+
assert(!channelStore.streams.containsKey(unknownChannel.streamId));
605+
final unknownUnreadMessage = eg.streamMessage(
606+
stream: unknownChannel, topic: origTopic);
607+
608+
model.handleUpdateMessageEvent(eg.updateMessageEventMoveFrom(
609+
origMessages: [unknownUnreadMessage],
610+
newTopicStr: newTopic));
611+
checkNotNotified();
612+
checkMatchesMessages(unreadMessages);
679613
});
680614
});
681615
});

0 commit comments

Comments
 (0)