test(persistence): Add test for channel query dao
Signed-off-by: Sahil Kumar <[email protected]>
This commit is contained in:
@@ -738,7 +738,8 @@ class StreamChatClient {
|
|||||||
await _chatPersistenceClient?.updateChannelQueries(
|
await _chatPersistenceClient?.updateChannelQueries(
|
||||||
filter,
|
filter,
|
||||||
channels.map((c) => c.channel.cid).toList(),
|
channels.map((c) => c.channel.cid).toList(),
|
||||||
paginationParams?.offset == null || paginationParams.offset == 0,
|
clearQueryCache:
|
||||||
|
paginationParams?.offset == null || paginationParams.offset == 0,
|
||||||
);
|
);
|
||||||
|
|
||||||
state.channels = updateData.key;
|
state.channels = updateData.key;
|
||||||
|
|||||||
@@ -100,10 +100,9 @@ abstract class ChatPersistenceClient {
|
|||||||
/// the list of matching rows will be deleted
|
/// the list of matching rows will be deleted
|
||||||
Future<void> updateChannelQueries(
|
Future<void> updateChannelQueries(
|
||||||
Map<String, dynamic> filter,
|
Map<String, dynamic> filter,
|
||||||
List<String> cids,
|
List<String> cids, {
|
||||||
// ignore: avoid_positional_boolean_parameters
|
bool clearQueryCache = false,
|
||||||
bool clearQueryCache,
|
});
|
||||||
);
|
|
||||||
|
|
||||||
/// Remove a message by [messageId]
|
/// Remove a message by [messageId]
|
||||||
Future<void> deleteMessageById(String messageId) =>
|
Future<void> deleteMessageById(String messageId) =>
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ class ChannelQueryDao extends DatabaseAccessor<MoorChatDatabase>
|
|||||||
Future<void> updateChannelQueries(
|
Future<void> updateChannelQueries(
|
||||||
Map<String, dynamic> filter,
|
Map<String, dynamic> filter,
|
||||||
List<String> cids, {
|
List<String> cids, {
|
||||||
bool clearQueryCache,
|
bool clearQueryCache = false,
|
||||||
}) async =>
|
}) async =>
|
||||||
transaction(() async {
|
transaction(() async {
|
||||||
final hash = _computeHash(filter);
|
final hash = _computeHash(filter);
|
||||||
@@ -57,6 +57,14 @@ class ChannelQueryDao extends DatabaseAccessor<MoorChatDatabase>
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
///
|
||||||
|
Future<List<String>> getCachedChannelCids(Map<String, dynamic> filter) {
|
||||||
|
final hash = _computeHash(filter);
|
||||||
|
return (select(channelQueries)..where((c) => c.queryHash.equals(hash)))
|
||||||
|
.map((c) => c.channelCid)
|
||||||
|
.get();
|
||||||
|
}
|
||||||
|
|
||||||
/// Get list of channels by filter, sort and paginationParams
|
/// Get list of channels by filter, sort and paginationParams
|
||||||
Future<List<ChannelModel>> getChannels({
|
Future<List<ChannelModel>> getChannels({
|
||||||
Map<String, dynamic> filter,
|
Map<String, dynamic> filter,
|
||||||
@@ -72,12 +80,7 @@ class ChannelQueryDao extends DatabaseAccessor<MoorChatDatabase>
|
|||||||
return true;
|
return true;
|
||||||
}(), '');
|
}(), '');
|
||||||
|
|
||||||
final hash = _computeHash(filter);
|
final cachedChannelCids = await getCachedChannelCids(filter);
|
||||||
final cachedChannelCids = await (select(channelQueries)
|
|
||||||
..where((c) => c.queryHash.equals(hash)))
|
|
||||||
.map((c) => c.channelCid)
|
|
||||||
.get();
|
|
||||||
|
|
||||||
final query = select(channels)..where((c) => c.cid.isIn(cachedChannelCids));
|
final query = select(channels)..where((c) => c.cid.isIn(cachedChannelCids));
|
||||||
|
|
||||||
final cachedChannels = await (query.join([
|
final cachedChannels = await (query.join([
|
||||||
|
|||||||
@@ -0,0 +1,270 @@
|
|||||||
|
import 'dart:math' as math;
|
||||||
|
|
||||||
|
import 'package:stream_chat/stream_chat.dart';
|
||||||
|
import 'package:stream_chat_persistence/src/dao/channel_query_dao.dart';
|
||||||
|
import 'package:stream_chat_persistence/src/db/moor_chat_database.dart';
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
MoorChatDatabase database;
|
||||||
|
ChannelQueryDao channelQueryDao;
|
||||||
|
|
||||||
|
setUp(() {
|
||||||
|
database = MoorChatDatabase.testable('testUserId');
|
||||||
|
channelQueryDao = database.channelQueryDao;
|
||||||
|
});
|
||||||
|
|
||||||
|
test('updateChannelQueries', () async {
|
||||||
|
const filter = {
|
||||||
|
'members': {
|
||||||
|
r'$in': ['testUserId'],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const cids = ['testCid1', 'testCid2', 'testCid3'];
|
||||||
|
|
||||||
|
final cachedCids = await channelQueryDao.getCachedChannelCids(filter);
|
||||||
|
expect(cachedCids, []);
|
||||||
|
|
||||||
|
// Updating channel queries
|
||||||
|
await channelQueryDao.updateChannelQueries(filter, cids);
|
||||||
|
|
||||||
|
final updatedCids = await channelQueryDao.getCachedChannelCids(filter);
|
||||||
|
expect(updatedCids, cids);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('getCachedChannelCids', () async {
|
||||||
|
const filter = {
|
||||||
|
'members': {
|
||||||
|
r'$in': ['testUserId'],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const cids = ['testCid1', 'testCid2', 'testCid3'];
|
||||||
|
|
||||||
|
final cachedCids = await channelQueryDao.getCachedChannelCids(filter);
|
||||||
|
expect(cachedCids, []);
|
||||||
|
|
||||||
|
// Updating channel queries
|
||||||
|
await channelQueryDao.updateChannelQueries(filter, cids);
|
||||||
|
|
||||||
|
final updatedCids = await channelQueryDao.getCachedChannelCids(filter);
|
||||||
|
expect(updatedCids, cids);
|
||||||
|
});
|
||||||
|
|
||||||
|
Future<List<ChannelModel>> _insertTestDataForGetChannel(
|
||||||
|
Map<String, Object> filter) async {
|
||||||
|
final now = DateTime.now();
|
||||||
|
final userDao = database.userDao;
|
||||||
|
final channelDao = database.channelDao;
|
||||||
|
|
||||||
|
const cids = ['testCid0', 'testCid1', 'testCid2'];
|
||||||
|
final users = List.generate(3, (index) => User(id: 'testId$index'));
|
||||||
|
final channels = List.generate(
|
||||||
|
3,
|
||||||
|
(index) => ChannelModel(
|
||||||
|
id: 'testId$index',
|
||||||
|
type: 'testType$index',
|
||||||
|
cid: cids[index],
|
||||||
|
createdBy: users[index],
|
||||||
|
config: ChannelConfig(),
|
||||||
|
extraData: {'test_custom_field': math.Random().nextInt(100)},
|
||||||
|
createdAt: now,
|
||||||
|
memberCount: math.Random().nextInt(100),
|
||||||
|
lastMessageAt: now.add(Duration(hours: index)),
|
||||||
|
),
|
||||||
|
).reversed.toList(growable: false);
|
||||||
|
|
||||||
|
await userDao.updateUsers(users);
|
||||||
|
await channelDao.updateChannels(channels);
|
||||||
|
await channelQueryDao.updateChannelQueries(filter, cids);
|
||||||
|
|
||||||
|
return channels;
|
||||||
|
}
|
||||||
|
|
||||||
|
group('getChannels', () {
|
||||||
|
const filter = {
|
||||||
|
'members': {
|
||||||
|
r'$in': ['testUserId'],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
test('should return empty list of channels', () async {
|
||||||
|
final channels = await channelQueryDao.getChannels(filter: filter);
|
||||||
|
expect(channels, []);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should return all the inserted channels', () async {
|
||||||
|
// Inserting test data for get channels
|
||||||
|
final insertedChannels = await _insertTestDataForGetChannel(filter);
|
||||||
|
|
||||||
|
// Should match with the inserted channels
|
||||||
|
final updatedChannels = await channelQueryDao.getChannels(filter: filter);
|
||||||
|
expect(updatedChannels.length, insertedChannels.length);
|
||||||
|
for (var i = 0; i < updatedChannels.length; i++) {
|
||||||
|
final updatedChannel = updatedChannels[i];
|
||||||
|
final insertedChannel = insertedChannels[i];
|
||||||
|
|
||||||
|
// Should match all the basic details
|
||||||
|
expect(updatedChannel.id, insertedChannel.id);
|
||||||
|
expect(updatedChannel.type, insertedChannel.type);
|
||||||
|
expect(updatedChannel.cid, insertedChannel.cid);
|
||||||
|
expect(updatedChannel.memberCount, insertedChannel.memberCount);
|
||||||
|
|
||||||
|
// Should match createdAt date
|
||||||
|
expect(
|
||||||
|
updatedChannel.createdAt.hour,
|
||||||
|
insertedChannel.createdAt.hour,
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
updatedChannel.createdAt.minute,
|
||||||
|
insertedChannel.createdAt.minute,
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
updatedChannel.createdAt.second,
|
||||||
|
insertedChannel.createdAt.second,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Should match lastMessageAt date
|
||||||
|
expect(
|
||||||
|
updatedChannel.lastMessageAt.hour,
|
||||||
|
insertedChannel.lastMessageAt.hour,
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
updatedChannel.lastMessageAt.minute,
|
||||||
|
insertedChannel.lastMessageAt.minute,
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
updatedChannel.lastMessageAt.second,
|
||||||
|
insertedChannel.lastMessageAt.second,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should return sorted channels using member count', () async {
|
||||||
|
int sortComparator(ChannelModel a, ChannelModel b) =>
|
||||||
|
b.memberCount.compareTo(a.memberCount);
|
||||||
|
|
||||||
|
// Inserting test data for get channels
|
||||||
|
final insertedChannels = await _insertTestDataForGetChannel(filter);
|
||||||
|
insertedChannels.sort(sortComparator);
|
||||||
|
|
||||||
|
// Should match with the inserted channels
|
||||||
|
final updatedChannels = await channelQueryDao.getChannels(
|
||||||
|
filter: filter,
|
||||||
|
sort: [SortOption('member_count', comparator: sortComparator)],
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(updatedChannels.length, insertedChannels.length);
|
||||||
|
for (var i = 0; i < updatedChannels.length; i++) {
|
||||||
|
final updatedChannel = updatedChannels[i];
|
||||||
|
final insertedChannel = insertedChannels[i];
|
||||||
|
|
||||||
|
// Should match all the basic details
|
||||||
|
expect(updatedChannel.id, insertedChannel.id);
|
||||||
|
expect(updatedChannel.type, insertedChannel.type);
|
||||||
|
expect(updatedChannel.cid, insertedChannel.cid);
|
||||||
|
expect(updatedChannel.memberCount, insertedChannel.memberCount);
|
||||||
|
|
||||||
|
// Should match createdAt date
|
||||||
|
expect(
|
||||||
|
updatedChannel.createdAt.hour,
|
||||||
|
insertedChannel.createdAt.hour,
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
updatedChannel.createdAt.minute,
|
||||||
|
insertedChannel.createdAt.minute,
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
updatedChannel.createdAt.second,
|
||||||
|
insertedChannel.createdAt.second,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Should match lastMessageAt date
|
||||||
|
expect(
|
||||||
|
updatedChannel.lastMessageAt.hour,
|
||||||
|
insertedChannel.lastMessageAt.hour,
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
updatedChannel.lastMessageAt.minute,
|
||||||
|
insertedChannel.lastMessageAt.minute,
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
updatedChannel.lastMessageAt.second,
|
||||||
|
insertedChannel.lastMessageAt.second,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should throw if comparator is not provided in sort list', () {
|
||||||
|
expect(
|
||||||
|
() => channelQueryDao.getChannels(
|
||||||
|
sort: [const SortOption('test_custom_field')],
|
||||||
|
),
|
||||||
|
throwsArgumentError,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should return sorted channels using custom field', () async {
|
||||||
|
int sortComparator(ChannelModel a, ChannelModel b) {
|
||||||
|
final aData = a.extraData['test_custom_field'] as int;
|
||||||
|
final bData = b.extraData['test_custom_field'] as int;
|
||||||
|
return bData.compareTo(aData);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inserting test data for get channels
|
||||||
|
final insertedChannels = await _insertTestDataForGetChannel(filter);
|
||||||
|
insertedChannels.sort(sortComparator);
|
||||||
|
|
||||||
|
// Should match with the inserted channels
|
||||||
|
final updatedChannels = await channelQueryDao.getChannels(
|
||||||
|
filter: filter,
|
||||||
|
sort: [SortOption('test_custom_field', comparator: sortComparator)],
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(updatedChannels.length, insertedChannels.length);
|
||||||
|
for (var i = 0; i < updatedChannels.length; i++) {
|
||||||
|
final updatedChannel = updatedChannels[i];
|
||||||
|
final insertedChannel = insertedChannels[i];
|
||||||
|
|
||||||
|
// Should match all the basic details
|
||||||
|
expect(updatedChannel.id, insertedChannel.id);
|
||||||
|
expect(updatedChannel.type, insertedChannel.type);
|
||||||
|
expect(updatedChannel.cid, insertedChannel.cid);
|
||||||
|
expect(updatedChannel.memberCount, insertedChannel.memberCount);
|
||||||
|
|
||||||
|
// Should match createdAt date
|
||||||
|
expect(
|
||||||
|
updatedChannel.createdAt.hour,
|
||||||
|
insertedChannel.createdAt.hour,
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
updatedChannel.createdAt.minute,
|
||||||
|
insertedChannel.createdAt.minute,
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
updatedChannel.createdAt.second,
|
||||||
|
insertedChannel.createdAt.second,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Should match lastMessageAt date
|
||||||
|
expect(
|
||||||
|
updatedChannel.lastMessageAt.hour,
|
||||||
|
insertedChannel.lastMessageAt.hour,
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
updatedChannel.lastMessageAt.minute,
|
||||||
|
insertedChannel.lastMessageAt.minute,
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
updatedChannel.lastMessageAt.second,
|
||||||
|
insertedChannel.lastMessageAt.second,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
tearDown(() async {
|
||||||
|
await database.disconnect();
|
||||||
|
});
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user