test(persistence): add tests for message dao

Signed-off-by: Sahil Kumar <[email protected]>
This commit is contained in:
Sahil Kumar
2021-03-16 18:42:06 +05:30
parent 2e20616145
commit a24ec99a44
2 changed files with 257 additions and 3 deletions
@@ -72,7 +72,7 @@ class MessageDao extends DatabaseAccessor<MoorChatDatabase>
/// [Messages.channelCid] with [cid]
Future<List<Message>> getThreadMessages(String cid) async =>
Future.wait(await (select(messages).join([
leftOuterJoin(users, messages.userId.equalsExp(_users.id)),
leftOuterJoin(_users, messages.userId.equalsExp(_users.id)),
leftOuterJoin(_pinnedByUsers,
messages.pinnedByUserId.equalsExp(_pinnedByUsers.id)),
])
@@ -89,10 +89,11 @@ class MessageDao extends DatabaseAccessor<MoorChatDatabase>
PaginationParams options,
}) async {
final msgList = await Future.wait(await (select(messages).join([
innerJoin(_users, messages.userId.equalsExp(_users.id)),
innerJoin(
leftOuterJoin(_users, messages.userId.equalsExp(_users.id)),
leftOuterJoin(
_pinnedByUsers, messages.pinnedByUserId.equalsExp(_pinnedByUsers.id)),
])
..where(isNotNull(messages.parentId))
..where(messages.parentId.equals(parentId))
..orderBy([OrderingTerm.asc(messages.createdAt)]))
.map(_messageFromJoinRow)
@@ -0,0 +1,253 @@
import 'dart:math' as math;
import 'package:stream_chat/stream_chat.dart';
import 'package:stream_chat_persistence/src/dao/dao.dart';
import 'package:stream_chat_persistence/src/db/moor_chat_database.dart';
import 'package:test/test.dart';
void main() {
MessageDao messageDao;
MoorChatDatabase database;
setUp(() {
database = MoorChatDatabase.testable('testUserId');
messageDao = database.messageDao;
});
Future<List<Message>> _prepareTestData(
String cid, {
bool threads = false,
int count = 3,
}) async {
final messages = List.generate(
count,
(index) => Message(
id: 'testMessageId$cid$index',
type: 'testType',
user: User(id: 'testUserId$index'),
createdAt: DateTime.now(),
shadowed: math.Random().nextBool(),
showInChannel: math.Random().nextBool(),
replyCount: index,
updatedAt: DateTime.now(),
extraData: {'extra_test_field': 'extraTestData'},
text: 'Dummy text #$index',
pinned: math.Random().nextBool(),
pinnedAt: DateTime.now(),
pinnedBy: User(id: 'testUserId$index'),
),
);
final threadMessages = List.generate(
count,
(index) => Message(
id: 'testThreadMessageId$cid$index',
type: 'testType',
user: User(id: 'testUserId$index'),
parentId: messages[index].id,
createdAt: DateTime.now(),
shadowed: math.Random().nextBool(),
showInChannel: math.Random().nextBool(),
replyCount: index,
updatedAt: DateTime.now(),
extraData: {'extra_test_field': 'extraTestData'},
text: 'Dummy text #$index',
pinned: math.Random().nextBool(),
pinnedAt: DateTime.now(),
pinnedBy: User(id: 'testUserId$index'),
),
);
final allMessages = [...messages, if (threads) ...threadMessages];
await messageDao.updateMessages(cid, allMessages);
return allMessages;
}
test('deleteMessageByIds', () async {
const cid = 'testCid';
// Preparing test data
final insertedMessages = await _prepareTestData(cid);
// Fetched message list should match the test message list length
final messages = await messageDao.getMessagesByCid(cid);
expect(messages.length, insertedMessages.length);
// Deleting 2 messages from DB
await messageDao.deleteMessageByIds(
['testMessageId${cid}0', 'testMessageId${cid}1'],
);
// New fetched messages length should 2 less than the
// previous fetched messages
final newMessages = await messageDao.getMessagesByCid(cid);
expect(newMessages.length, messages.length - 2);
});
group('deleteMessageByCids', () {
const cid1 = 'testCid1';
const cid2 = 'testCid2';
test('should delete all the messages of first channel', () async {
// Preparing test data
final cid1InsertedMessages = await _prepareTestData(cid1);
final cid2InsertedMessages = await _prepareTestData(cid2);
// Fetched message list should match the test message list length
final cid1Messages = await messageDao.getMessagesByCid(cid1);
final cid2Messages = await messageDao.getMessagesByCid(cid2);
expect(cid1Messages.length, cid1InsertedMessages.length);
expect(cid2Messages.length, cid2InsertedMessages.length);
// Deleting all the messages of cid1
await messageDao.deleteMessageByCids([cid1]);
// Fetched messages length of only cid1 should be empty
final cid1FetchedMessages = await messageDao.getMessagesByCid(cid1);
final cid2FetchedMessages = await messageDao.getMessagesByCid(cid2);
expect(cid1FetchedMessages, isEmpty);
expect(cid2FetchedMessages, isNotEmpty);
});
test('should delete all the messages of both channel', () async {
// Preparing test data
final cid1InsertedMessages = await _prepareTestData(cid1);
final cid2InsertedMessages = await _prepareTestData(cid2);
// Fetched message list should match the test message list length
final cid1Messages = await messageDao.getMessagesByCid(cid1);
final cid2Messages = await messageDao.getMessagesByCid(cid2);
expect(cid1Messages.length, cid1InsertedMessages.length);
expect(cid2Messages.length, cid2InsertedMessages.length);
// Deleting all the messages of cid1
await messageDao.deleteMessageByCids([cid1, cid2]);
// Fetched messages length of both cid1 and cid2 should be empty
final cid1FetchedMessages = await messageDao.getMessagesByCid(cid1);
final cid2FetchedMessages = await messageDao.getMessagesByCid(cid2);
expect(cid1FetchedMessages, isEmpty);
expect(cid2FetchedMessages, isEmpty);
});
});
test('getMessageById', () async {
const cid = 'testCid';
const id = 'testMessageId${cid}0';
// Should be null initially
final message = await messageDao.getMessageById(id);
expect(message, isNull);
// Adding test message with the cid and id
final insertedMessages = await _prepareTestData(cid, count: 1);
expect(insertedMessages.first.id, id);
// Fetched message id should match the inserted message id
final fetchedMessage = await messageDao.getMessageById(id);
expect(fetchedMessage.id, insertedMessages.first.id);
});
test('getThreadMessages', () async {
const cid = 'testCid';
// Messages should be empty initially
final messages = await messageDao.getThreadMessages(cid);
expect(messages, isEmpty);
// Preparing test data
final insertedMessages = await _prepareTestData(cid, threads: true);
expect(insertedMessages, isNotEmpty);
// Should fetch all the thread messages of cid
final threadMessages = await messageDao.getThreadMessages(cid);
expect(threadMessages, isNotEmpty);
for (final message in threadMessages) {
expect(message.parentId, isNotNull);
}
});
test('getThreadMessagesByParentId', () async {
const cid = 'testCid';
const parentId = 'testMessageId${cid}0';
// Messages should be empty initially
final messages = await messageDao.getThreadMessagesByParentId(parentId);
expect(messages, isEmpty);
// Preparing test data
final insertedMessages = await _prepareTestData(cid, threads: true);
expect(insertedMessages, isNotEmpty);
// Should fetch all the thread messages of parentId
final threadMessages =
await messageDao.getThreadMessagesByParentId(parentId);
expect(threadMessages.length, 1);
expect(threadMessages.first.parentId, parentId);
});
test('getMessagesByCid', () async {
const cid = 'testCid';
// Should be empty initially
final messages = await messageDao.getMessagesByCid(cid);
expect(messages, isEmpty);
// Preparing test data
final insertedMessages = await _prepareTestData(cid);
expect(insertedMessages, isNotEmpty);
// Fetched message should match the inserted messages
final fetchedMessages = await messageDao.getMessagesByCid(cid);
expect(fetchedMessages.length, insertedMessages.length);
for (var i = 0; i < fetchedMessages.length; i++) {
final fetchedMessage = fetchedMessages[i];
final insertedMessage = insertedMessages[i];
expect(fetchedMessage.id, insertedMessage.id);
}
});
test('updateMessages', () async {
const cid = 'testCid';
// Preparing test data
final insertedMessages = await _prepareTestData(cid);
expect(insertedMessages, isNotEmpty);
// Modifying one of the message and also adding one new
final copyMessage = insertedMessages.first.copyWith(showInChannel: false);
final newMessage = Message(
id: 'testMessageId${cid}4',
type: 'testType',
user: User(id: 'testUserId4'),
createdAt: DateTime.now(),
shadowed: math.Random().nextBool(),
showInChannel: math.Random().nextBool(),
replyCount: 4,
updatedAt: DateTime.now(),
extraData: {'extra_test_field': 'extraTestData'},
text: 'Dummy text #4',
pinned: math.Random().nextBool(),
pinnedAt: DateTime.now(),
pinnedBy: User(id: 'testUserId4'),
);
await messageDao.updateMessages(cid, [copyMessage, newMessage]);
// Fetched messages length should be one more than inserted message.
// copyMessage `showInChannel` modified field should be false.
// Fetched messages should contain the newMessage.
final fetchedMessages = await messageDao.getMessagesByCid(cid);
expect(fetchedMessages.length, insertedMessages.length + 1);
expect(
fetchedMessages.firstWhere((it) => it.id == copyMessage.id).showInChannel,
false,
);
expect(
fetchedMessages.map((it) => it.id).contains('testMessageId${cid}4'),
true,
);
});
tearDown(() async {
await database.disconnect();
});
}