fix(stream_chat_persistence): tests
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
import 'package:mocktail/mocktail.dart';
|
||||
import 'package:stream_chat_persistence/src/dao/dao.dart';
|
||||
import 'package:stream_chat_persistence/src/db/moor_chat_database.dart';
|
||||
|
||||
class MockChatDatabase extends Mock implements MoorChatDatabase {
|
||||
UserDao _userDao;
|
||||
|
||||
@override
|
||||
UserDao get userDao => _userDao ??= MockUserDao();
|
||||
|
||||
ChannelDao _channelDao;
|
||||
|
||||
@override
|
||||
ChannelDao get channelDao => _channelDao ??= MockChannelDao();
|
||||
|
||||
MessageDao _messageDao;
|
||||
|
||||
@override
|
||||
MessageDao get messageDao => _messageDao ??= MockMessageDao();
|
||||
|
||||
PinnedMessageDao _pinnedMessageDao;
|
||||
|
||||
@override
|
||||
PinnedMessageDao get pinnedMessageDao =>
|
||||
_pinnedMessageDao ??= MockPinnedMessageDao();
|
||||
|
||||
MemberDao _memberDao;
|
||||
|
||||
@override
|
||||
MemberDao get memberDao => _memberDao ??= MockMemberDao();
|
||||
|
||||
ReactionDao _reactionDao;
|
||||
|
||||
@override
|
||||
ReactionDao get reactionDao => _reactionDao ??= MockReactionDao();
|
||||
|
||||
ReadDao _readDao;
|
||||
|
||||
@override
|
||||
ReadDao get readDao => _readDao ??= MockReadDao();
|
||||
|
||||
ChannelQueryDao _channelQueryDao;
|
||||
|
||||
@override
|
||||
ChannelQueryDao get channelQueryDao =>
|
||||
_channelQueryDao ??= MockChannelQueryDao();
|
||||
|
||||
ConnectionEventDao _connectionEventDao;
|
||||
|
||||
@override
|
||||
ConnectionEventDao get connectionEventDao =>
|
||||
_connectionEventDao ??= MockConnectionEventDao();
|
||||
}
|
||||
|
||||
class MockUserDao extends Mock implements UserDao {}
|
||||
|
||||
class MockChannelDao extends Mock implements ChannelDao {}
|
||||
|
||||
class MockMessageDao extends Mock implements MessageDao {}
|
||||
|
||||
class MockPinnedMessageDao extends Mock implements PinnedMessageDao {}
|
||||
|
||||
class MockMemberDao extends Mock implements MemberDao {}
|
||||
|
||||
class MockReactionDao extends Mock implements ReactionDao {}
|
||||
|
||||
class MockReadDao extends Mock implements ReadDao {}
|
||||
|
||||
class MockChannelQueryDao extends Mock implements ChannelQueryDao {}
|
||||
|
||||
class MockConnectionEventDao extends Mock implements ConnectionEventDao {}
|
||||
@@ -0,0 +1,53 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:test/test.dart';
|
||||
import 'package:stream_chat_persistence/src/converter/list_converter.dart';
|
||||
|
||||
void main() {
|
||||
group('mapToDart', () {
|
||||
final listConverter = ListConverter<String>();
|
||||
|
||||
test('should return null if nothing is provided', () {
|
||||
final res = listConverter.mapToDart(null);
|
||||
expect(res, isNull);
|
||||
});
|
||||
|
||||
test('should throw type error if the provided json is not a list', () {
|
||||
final json = {'test_key': 'testData'};
|
||||
expect(
|
||||
() => listConverter.mapToDart(jsonEncode(json)),
|
||||
throwsA(isA<TypeError>()),
|
||||
);
|
||||
});
|
||||
|
||||
test('should throw type error if the provided json is not a list of String',
|
||||
() {
|
||||
final json = [22, 33, 44];
|
||||
expect(
|
||||
() => listConverter.mapToDart(jsonEncode(json)),
|
||||
throwsA(isA<TypeError>()),
|
||||
);
|
||||
});
|
||||
|
||||
test('should return list of String if json data list is provided', () {
|
||||
final data = ['data1', 'data2', 'data3'];
|
||||
final res = listConverter.mapToDart(jsonEncode(data));
|
||||
expect(res.length, data.length);
|
||||
});
|
||||
});
|
||||
|
||||
group('mapToSql', () {
|
||||
final listConverter = ListConverter<String>();
|
||||
|
||||
test('should return null if nothing is provided', () {
|
||||
final res = listConverter.mapToSql(null);
|
||||
expect(res, isNull);
|
||||
});
|
||||
|
||||
test('should return json string if data list is provided', () {
|
||||
final data = ['data1', 'data2', 'data3'];
|
||||
final res = listConverter.mapToSql(data);
|
||||
expect(res, jsonEncode(data));
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:test/test.dart';
|
||||
import 'package:stream_chat_persistence/src/converter/map_converter.dart';
|
||||
|
||||
void main() {
|
||||
group('mapToDart', () {
|
||||
final mapConverter = MapConverter<String>();
|
||||
|
||||
test('should return null if nothing is provided', () {
|
||||
final res = mapConverter.mapToDart(null);
|
||||
expect(res, isNull);
|
||||
});
|
||||
|
||||
test('should throw type error if the provided json is not a map', () {
|
||||
const json = ['testData1', 'testData2', 'testData3'];
|
||||
expect(
|
||||
() => mapConverter.mapToDart(jsonEncode(json)),
|
||||
throwsA(isA<TypeError>()),
|
||||
);
|
||||
});
|
||||
|
||||
test(
|
||||
'should throw type error if the provided json is not a '
|
||||
'map of String, String',
|
||||
() {
|
||||
const json = {'test_key': 22, 'test_key2': 33, 'test_key3': 44};
|
||||
expect(
|
||||
() => mapConverter.mapToDart(jsonEncode(json)),
|
||||
throwsA(isA<TypeError>()),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
test('should return map of String, String if json data is provided', () {
|
||||
const data = {
|
||||
'test_key': 'testValue',
|
||||
'test_key2': 'testValue2',
|
||||
'test_key3': 'testValue3',
|
||||
};
|
||||
final res = mapConverter.mapToDart(jsonEncode(data));
|
||||
expect(res, data);
|
||||
});
|
||||
});
|
||||
|
||||
group('mapToSql', () {
|
||||
final mapConverter = MapConverter<String>();
|
||||
|
||||
test('should return null if nothing is provided', () {
|
||||
final res = mapConverter.mapToSql(null);
|
||||
expect(res, isNull);
|
||||
});
|
||||
|
||||
test('should return json string if data map is provided', () {
|
||||
const data = {
|
||||
'test_key': 'testValue',
|
||||
'test_key2': 'testValue2',
|
||||
'test_key3': 'testValue3',
|
||||
};
|
||||
final res = mapConverter.mapToSql(data);
|
||||
expect(res, jsonEncode(data));
|
||||
});
|
||||
});
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
import 'package:test/test.dart';
|
||||
import 'package:stream_chat/stream_chat.dart';
|
||||
import 'package:stream_chat_persistence/src/converter/message_sending_status_converter.dart';
|
||||
|
||||
void main() {
|
||||
group('mapToDart', () {
|
||||
final statusConverter = MessageSendingStatusConverter();
|
||||
|
||||
test('should return null if nothing is provided', () {
|
||||
final res = statusConverter.mapToDart(null);
|
||||
expect(res, isNull);
|
||||
});
|
||||
|
||||
test('should return expected status if status code is provided', () {
|
||||
final res = statusConverter.mapToDart(3);
|
||||
expect(res, MessageSendingStatus.updating);
|
||||
});
|
||||
});
|
||||
|
||||
group('mapToSql', () {
|
||||
final statusConverter = MessageSendingStatusConverter();
|
||||
|
||||
test('should return null if nothing is provided', () {
|
||||
final res = statusConverter.mapToSql(null);
|
||||
expect(res, isNull);
|
||||
});
|
||||
|
||||
test('should return expected code if the status is provided', () {
|
||||
final res = statusConverter.mapToSql(MessageSendingStatus.updating);
|
||||
expect(res, 3);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
import 'package:stream_chat/stream_chat.dart';
|
||||
import 'package:stream_chat_persistence/src/dao/channel_dao.dart';
|
||||
import 'package:stream_chat_persistence/src/db/moor_chat_database.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
void main() {
|
||||
ChannelDao channelDao;
|
||||
MoorChatDatabase database;
|
||||
|
||||
setUp(() {
|
||||
database = MoorChatDatabase.testable('testUserId');
|
||||
channelDao = database.channelDao;
|
||||
});
|
||||
|
||||
test('getChannelByCid', () async {
|
||||
const id = 'testId';
|
||||
const cid = 'testCid';
|
||||
const type = 'testType';
|
||||
|
||||
// Should be null initially
|
||||
final channel = await channelDao.getChannelByCid(cid);
|
||||
expect(channel, isNull);
|
||||
|
||||
// Saving a dummy channel
|
||||
final dummyChannel = ChannelModel(
|
||||
id: id,
|
||||
type: type,
|
||||
cid: cid,
|
||||
config: ChannelConfig(),
|
||||
);
|
||||
await channelDao.updateChannels([dummyChannel]);
|
||||
|
||||
// Should match the dummy channel
|
||||
final updatedChannel = await channelDao.getChannelByCid(cid);
|
||||
expect(updatedChannel.id, id);
|
||||
expect(updatedChannel.cid, cid);
|
||||
expect(updatedChannel.type, type);
|
||||
});
|
||||
|
||||
test('deleteChannelByCids', () async {
|
||||
const id = 'testId';
|
||||
const cid = 'testCid';
|
||||
const type = 'testType';
|
||||
|
||||
// Saving a dummy channel
|
||||
final dummyChannel = ChannelModel(
|
||||
id: id,
|
||||
type: type,
|
||||
cid: cid,
|
||||
config: ChannelConfig(),
|
||||
);
|
||||
await channelDao.updateChannels([dummyChannel]);
|
||||
|
||||
// Should match the dummy channel
|
||||
final updatedChannel = await channelDao.getChannelByCid(cid);
|
||||
expect(updatedChannel.id, id);
|
||||
expect(updatedChannel.cid, cid);
|
||||
expect(updatedChannel.type, type);
|
||||
|
||||
// Deleting the dummyChannel using cid
|
||||
await channelDao.deleteChannelByCids([cid]);
|
||||
|
||||
// Fetched channel Should be null
|
||||
final channel = await channelDao.getChannelByCid(cid);
|
||||
expect(channel, isNull);
|
||||
});
|
||||
|
||||
test('cids', () async {
|
||||
// Should be empty initially
|
||||
final cids = await channelDao.cids;
|
||||
expect(cids, []);
|
||||
|
||||
const id = 'testId';
|
||||
const cid = 'testCid';
|
||||
const type = 'testType';
|
||||
|
||||
// Saving a dummy channel
|
||||
final dummyChannel = ChannelModel(
|
||||
id: id,
|
||||
type: type,
|
||||
cid: cid,
|
||||
config: ChannelConfig(),
|
||||
);
|
||||
await channelDao.updateChannels([dummyChannel]);
|
||||
|
||||
// Should return the cid of the dummy channel
|
||||
final updatedCids = await channelDao.cids;
|
||||
expect(updatedCids, [cid]);
|
||||
});
|
||||
|
||||
test('updateChannels', () async {
|
||||
const id = 'testId';
|
||||
const cid = 'testCid';
|
||||
const type = 'testType';
|
||||
|
||||
// Should be null initially
|
||||
final channel = await channelDao.getChannelByCid(cid);
|
||||
expect(channel, isNull);
|
||||
|
||||
// Saving a dummy channel
|
||||
final dummyChannel = ChannelModel(
|
||||
id: id,
|
||||
type: type,
|
||||
cid: cid,
|
||||
config: ChannelConfig(),
|
||||
);
|
||||
await channelDao.updateChannels([dummyChannel]);
|
||||
|
||||
// Should match the dummy channel
|
||||
final updatedChannel = await channelDao.getChannelByCid(cid);
|
||||
expect(updatedChannel.id, id);
|
||||
expect(updatedChannel.cid, cid);
|
||||
expect(updatedChannel.type, type);
|
||||
|
||||
// Updating the previously saved channel
|
||||
const newType = 'newTestType';
|
||||
final newChannel = dummyChannel.copyWith(type: newType);
|
||||
await channelDao.updateChannels([newChannel]);
|
||||
|
||||
// Should match the new channel
|
||||
final newUpdatedChannel = await channelDao.getChannelByCid(cid);
|
||||
expect(newUpdatedChannel.id, id);
|
||||
expect(newUpdatedChannel.cid, cid);
|
||||
expect(newUpdatedChannel.type, newType);
|
||||
});
|
||||
|
||||
tearDown(() async {
|
||||
await database.disconnect();
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,273 @@
|
||||
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';
|
||||
|
||||
import '../utils/date_matcher.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, isEmpty);
|
||||
|
||||
// Updating channel queries
|
||||
await channelQueryDao.updateChannelQueries(filter, cids);
|
||||
|
||||
final updatedCids = await channelQueryDao.getCachedChannelCids(filter);
|
||||
expect(updatedCids, cids);
|
||||
});
|
||||
|
||||
test('clear queryCache before updateChannelQueries', () async {
|
||||
const filter = {
|
||||
'members': {
|
||||
r'$in': ['testUserId'],
|
||||
},
|
||||
};
|
||||
|
||||
const cids = ['testCid1', 'testCid2', 'testCid3'];
|
||||
|
||||
final cachedCids = await channelQueryDao.getCachedChannelCids(filter);
|
||||
expect(cachedCids, isEmpty);
|
||||
|
||||
// Updating channel queries
|
||||
await channelQueryDao.updateChannelQueries(
|
||||
filter,
|
||||
cids,
|
||||
clearQueryCache: true,
|
||||
);
|
||||
|
||||
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, isEmpty);
|
||||
|
||||
// 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, {
|
||||
int count = 3,
|
||||
}) async {
|
||||
final now = DateTime.now();
|
||||
final userDao = database.userDao;
|
||||
final channelDao = database.channelDao;
|
||||
|
||||
final cids = List.generate(count, (index) => 'testCid$index');
|
||||
final users = List.generate(count, (index) => User(id: 'testId$index'));
|
||||
final channels = List.generate(
|
||||
count,
|
||||
(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, isEmpty);
|
||||
});
|
||||
|
||||
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,
|
||||
isSameDateAs(insertedChannel.createdAt),
|
||||
);
|
||||
|
||||
// Should match lastMessageAt date
|
||||
expect(
|
||||
updatedChannel.lastMessageAt,
|
||||
isSameDateAs(insertedChannel.lastMessageAt),
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
test(
|
||||
'should return all the inserted channels along with pagination applied',
|
||||
() async {
|
||||
const offset = 5;
|
||||
const limit = 15;
|
||||
const pagination = PaginationParams(offset: offset, limit: limit);
|
||||
|
||||
// Inserting test data for get channels
|
||||
final insertedChannels = await _insertTestDataForGetChannel(
|
||||
filter,
|
||||
count: 30,
|
||||
);
|
||||
|
||||
// Should match with the inserted channels
|
||||
final updatedChannels = await channelQueryDao.getChannels(
|
||||
filter: filter,
|
||||
paginationParams: pagination,
|
||||
);
|
||||
expect(updatedChannels.length, limit);
|
||||
expect(updatedChannels.first.id, 'testId24');
|
||||
expect(updatedChannels.first.cid, 'testCid24');
|
||||
},
|
||||
);
|
||||
|
||||
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,
|
||||
isSameDateAs(insertedChannel.createdAt),
|
||||
);
|
||||
|
||||
// Should match lastMessageAt date
|
||||
expect(
|
||||
updatedChannel.lastMessageAt,
|
||||
isSameDateAs(insertedChannel.lastMessageAt),
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
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,
|
||||
isSameDateAs(insertedChannel.createdAt),
|
||||
);
|
||||
|
||||
// Should match lastMessageAt date
|
||||
expect(
|
||||
updatedChannel.lastMessageAt,
|
||||
isSameDateAs(insertedChannel.lastMessageAt),
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
tearDown(() async {
|
||||
await database.disconnect();
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
import 'package:stream_chat/stream_chat.dart';
|
||||
import 'package:stream_chat_persistence/src/dao/connection_event_dao.dart';
|
||||
import 'package:stream_chat_persistence/src/db/moor_chat_database.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import '../utils/date_matcher.dart';
|
||||
|
||||
void main() {
|
||||
ConnectionEventDao eventDao;
|
||||
MoorChatDatabase database;
|
||||
|
||||
setUp(() {
|
||||
database = MoorChatDatabase.testable('testUserId');
|
||||
eventDao = database.connectionEventDao;
|
||||
});
|
||||
|
||||
test('connectionEvent', () async {
|
||||
// Should be null initially
|
||||
final event = await eventDao.connectionEvent;
|
||||
expect(event, isNull);
|
||||
|
||||
// Adding a new event
|
||||
final newEvent = Event(
|
||||
createdAt: DateTime.now(),
|
||||
totalUnreadCount: 33,
|
||||
unreadChannels: 3,
|
||||
me: OwnUser(id: 'testUserId'),
|
||||
);
|
||||
await eventDao.updateConnectionEvent(newEvent);
|
||||
|
||||
// Should match the added event
|
||||
final updatedEvent = await eventDao.connectionEvent;
|
||||
expect(updatedEvent.me.id, newEvent.me.id);
|
||||
expect(updatedEvent.totalUnreadCount, newEvent.totalUnreadCount);
|
||||
expect(updatedEvent.unreadChannels, newEvent.unreadChannels);
|
||||
});
|
||||
|
||||
test('lastSyncAt', () async {
|
||||
// Should be null initially
|
||||
final lastSyncAt = await eventDao.lastSyncAt;
|
||||
expect(lastSyncAt, isNull);
|
||||
|
||||
// Adding an event for testing
|
||||
final event = Event(
|
||||
createdAt: DateTime.now(),
|
||||
totalUnreadCount: 33,
|
||||
unreadChannels: 3,
|
||||
me: OwnUser(id: 'testUserId'),
|
||||
);
|
||||
await eventDao.updateConnectionEvent(event);
|
||||
|
||||
// Updating it's last sync
|
||||
final now = DateTime.now();
|
||||
await eventDao.updateLastSyncAt(now);
|
||||
|
||||
// Should match the updated last sync
|
||||
final updatedLastSyncAt = await eventDao.lastSyncAt;
|
||||
expect(updatedLastSyncAt, isSameDateAs(now));
|
||||
});
|
||||
|
||||
test('updateConnectionEvent', () async {
|
||||
// Adding and event for testing
|
||||
final event = Event(
|
||||
createdAt: DateTime.now(),
|
||||
totalUnreadCount: 33,
|
||||
unreadChannels: 3,
|
||||
me: OwnUser(id: 'testUserId'),
|
||||
);
|
||||
await eventDao.updateConnectionEvent(event);
|
||||
|
||||
// Should match the previously added event
|
||||
final fetchedEvent = await eventDao.connectionEvent;
|
||||
expect(fetchedEvent.me.id, event.me.id);
|
||||
expect(fetchedEvent.totalUnreadCount, event.totalUnreadCount);
|
||||
expect(fetchedEvent.unreadChannels, event.unreadChannels);
|
||||
|
||||
// Updating the added event
|
||||
final newEvent = event.copyWith(unreadChannels: 4);
|
||||
await eventDao.updateConnectionEvent(newEvent);
|
||||
|
||||
// Should match the updated event
|
||||
final fetchedNewEvent = await eventDao.connectionEvent;
|
||||
expect(fetchedNewEvent.me.id, event.me.id);
|
||||
expect(fetchedNewEvent.totalUnreadCount, event.totalUnreadCount);
|
||||
expect(fetchedNewEvent.unreadChannels, newEvent.unreadChannels);
|
||||
});
|
||||
|
||||
test('updateLastSyncAt', () async {
|
||||
// Should be null initially
|
||||
final lastSyncAt = await eventDao.lastSyncAt;
|
||||
expect(lastSyncAt, isNull);
|
||||
|
||||
// Adding an event just for testing
|
||||
final event = Event(
|
||||
createdAt: DateTime.now(),
|
||||
totalUnreadCount: 33,
|
||||
unreadChannels: 3,
|
||||
me: OwnUser(id: 'testUserId'),
|
||||
);
|
||||
await eventDao.updateConnectionEvent(event);
|
||||
|
||||
// Updating it's last sync
|
||||
final now = DateTime.now();
|
||||
await eventDao.updateLastSyncAt(now);
|
||||
|
||||
// Should match the last sync
|
||||
final updatedLastSyncAt = await eventDao.lastSyncAt;
|
||||
expect(updatedLastSyncAt, isSameDateAs(now));
|
||||
});
|
||||
|
||||
tearDown(() async {
|
||||
await database.disconnect();
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
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';
|
||||
|
||||
import '../utils/date_matcher.dart';
|
||||
|
||||
void main() {
|
||||
MemberDao memberDao;
|
||||
MoorChatDatabase database;
|
||||
|
||||
setUp(() {
|
||||
database = MoorChatDatabase.testable('testUserId');
|
||||
memberDao = database.memberDao;
|
||||
});
|
||||
|
||||
Future<List<Member>> _prepareTestData(String cid) async {
|
||||
final users = List.generate(3, (index) => User(id: 'testUserId$index'));
|
||||
final memberList = List.generate(
|
||||
3,
|
||||
(index) => Member(
|
||||
user: users[index],
|
||||
banned: math.Random().nextBool(),
|
||||
shadowBanned: math.Random().nextBool(),
|
||||
createdAt: DateTime.now(),
|
||||
isModerator: math.Random().nextBool(),
|
||||
invited: math.Random().nextBool(),
|
||||
inviteAcceptedAt: DateTime.now(),
|
||||
role: 'testRole',
|
||||
updatedAt: DateTime.now(),
|
||||
),
|
||||
);
|
||||
await database.userDao.updateUsers(users);
|
||||
await memberDao.updateMembers(cid, memberList);
|
||||
return memberList;
|
||||
}
|
||||
|
||||
test('getMembersByCid', () async {
|
||||
const cid = 'testCid';
|
||||
|
||||
// Should be empty initially
|
||||
final members = await memberDao.getMembersByCid(cid);
|
||||
expect(members, isEmpty);
|
||||
|
||||
// Preparing test data
|
||||
final memberList = await _prepareTestData(cid);
|
||||
|
||||
// Should match the previous test data
|
||||
final fetchedMembers = await memberDao.getMembersByCid(cid);
|
||||
expect(fetchedMembers.length, memberList.length);
|
||||
for (var i = 0; i < fetchedMembers.length; i++) {
|
||||
final member = memberList[i];
|
||||
final fetchedMember = fetchedMembers[i];
|
||||
expect(fetchedMember.user.id, member.user.id);
|
||||
expect(fetchedMember.banned, member.banned);
|
||||
expect(fetchedMember.shadowBanned, member.shadowBanned);
|
||||
expect(fetchedMember.createdAt, isSameDateAs(member.createdAt));
|
||||
expect(fetchedMember.isModerator, member.isModerator);
|
||||
expect(fetchedMember.invited, member.invited);
|
||||
expect(fetchedMember.role, member.role);
|
||||
expect(fetchedMember.updatedAt, isSameDateAs(member.updatedAt));
|
||||
expect(
|
||||
fetchedMember.inviteAcceptedAt,
|
||||
isSameDateAs(member.inviteAcceptedAt),
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
test('updateMembers', () async {
|
||||
const cid = 'testCid';
|
||||
|
||||
// Preparing test data
|
||||
final memberList = await _prepareTestData(cid);
|
||||
|
||||
// Should match the previous test data
|
||||
final fetchedMembers = await memberDao.getMembersByCid(cid);
|
||||
expect(fetchedMembers.length, memberList.length);
|
||||
for (var i = 0; i < fetchedMembers.length; i++) {
|
||||
final member = memberList[i];
|
||||
final fetchedMember = fetchedMembers[i];
|
||||
expect(fetchedMember.user.id, member.user.id);
|
||||
expect(fetchedMember.banned, member.banned);
|
||||
expect(fetchedMember.shadowBanned, member.shadowBanned);
|
||||
expect(fetchedMember.createdAt, isSameDateAs(member.createdAt));
|
||||
expect(fetchedMember.isModerator, member.isModerator);
|
||||
expect(fetchedMember.invited, member.invited);
|
||||
expect(fetchedMember.role, member.role);
|
||||
expect(fetchedMember.updatedAt, isSameDateAs(member.updatedAt));
|
||||
expect(
|
||||
fetchedMember.inviteAcceptedAt,
|
||||
isSameDateAs(member.inviteAcceptedAt),
|
||||
);
|
||||
}
|
||||
|
||||
// Modifying one of the member and also adding one new
|
||||
final copyMember = fetchedMembers.first.copyWith(banned: true);
|
||||
final newUser = User(id: 'testUserId3');
|
||||
final newMember = Member(
|
||||
user: newUser,
|
||||
banned: math.Random().nextBool(),
|
||||
shadowBanned: math.Random().nextBool(),
|
||||
createdAt: DateTime.now(),
|
||||
isModerator: math.Random().nextBool(),
|
||||
invited: math.Random().nextBool(),
|
||||
inviteAcceptedAt: DateTime.now(),
|
||||
role: 'testRole',
|
||||
updatedAt: DateTime.now(),
|
||||
);
|
||||
await database.userDao.updateUsers([newUser]);
|
||||
await memberDao.updateMembers(cid, [copyMember, newMember]);
|
||||
|
||||
// Fetched member length should be one more than inserted members.
|
||||
// copyMember `banned` modified field should be true.
|
||||
// Fetched members should contain the newMember.
|
||||
final newFetchedMembers = await memberDao.getMembersByCid(cid);
|
||||
expect(newFetchedMembers.length, fetchedMembers.length + 1);
|
||||
expect(
|
||||
newFetchedMembers
|
||||
.firstWhere((it) => it.user.id == copyMember.user.id)
|
||||
.banned,
|
||||
true,
|
||||
);
|
||||
expect(
|
||||
newFetchedMembers
|
||||
.where((it) => it.user.id == newMember.user.id)
|
||||
.isNotEmpty,
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
test('deleteMemberByCids', () async {
|
||||
const cid = 'testCid';
|
||||
|
||||
// Preparing test data
|
||||
final members = await _prepareTestData(cid);
|
||||
final fetchedMembers = await memberDao.getMembersByCid(cid);
|
||||
expect(members.length, fetchedMembers.length);
|
||||
|
||||
// Deleting all the members
|
||||
await memberDao.deleteMemberByCids([cid]);
|
||||
|
||||
// Fetched member list should be empty
|
||||
final newFetchedMembers = await memberDao.getMembersByCid(cid);
|
||||
expect(newFetchedMembers, isEmpty);
|
||||
});
|
||||
|
||||
tearDown(() async {
|
||||
await database.disconnect();
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,362 @@
|
||||
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 quoted = false,
|
||||
bool threads = false,
|
||||
bool mapAllThreadToFirstMessage = false,
|
||||
int count = 3,
|
||||
}) async {
|
||||
final users = List.generate(count, (index) => User(id: 'testUserId$index'));
|
||||
final messages = List.generate(
|
||||
count,
|
||||
(index) => Message(
|
||||
id: 'testMessageId$cid$index',
|
||||
type: 'testType',
|
||||
user: users[index],
|
||||
createdAt: DateTime.now(),
|
||||
shadowed: 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 quotedMessages = List.generate(
|
||||
count,
|
||||
(index) => Message(
|
||||
id: 'testQuotedMessageId$cid$index',
|
||||
type: 'testType',
|
||||
user: users[index],
|
||||
createdAt: DateTime.now(),
|
||||
shadowed: math.Random().nextBool(),
|
||||
replyCount: index,
|
||||
updatedAt: DateTime.now(),
|
||||
extraData: {'extra_test_field': 'extraTestData'},
|
||||
text: 'Dummy text #$index',
|
||||
quotedMessageId: messages[index].id,
|
||||
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: users[index],
|
||||
parentId:
|
||||
mapAllThreadToFirstMessage ? messages[0].id : messages[index].id,
|
||||
createdAt: DateTime.now(),
|
||||
shadowed: 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 (quoted) ...quotedMessages,
|
||||
if (threads) ...threadMessages
|
||||
];
|
||||
await database.userDao.updateUsers(users);
|
||||
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('getThreadMessagesByParentId along with pagination', () async {
|
||||
const cid = 'testCid';
|
||||
const parentId = 'testMessageId${cid}0';
|
||||
const options = PaginationParams(
|
||||
limit: 15,
|
||||
lessThan: 'testThreadMessageId${cid}25',
|
||||
greaterThanOrEqual: 'testThreadMessageId${cid}5',
|
||||
);
|
||||
|
||||
// Messages should be empty initially
|
||||
final messages = await messageDao.getThreadMessagesByParentId(
|
||||
parentId,
|
||||
options: options,
|
||||
);
|
||||
expect(messages, isEmpty);
|
||||
|
||||
// Preparing test data
|
||||
final insertedMessages = await _prepareTestData(
|
||||
cid,
|
||||
threads: true,
|
||||
mapAllThreadToFirstMessage: true,
|
||||
count: 30,
|
||||
);
|
||||
expect(insertedMessages, isNotEmpty);
|
||||
|
||||
// Should fetch all the thread messages of parentId and apply the pagination
|
||||
final threadMessages = await messageDao.getThreadMessagesByParentId(
|
||||
parentId,
|
||||
options: options,
|
||||
);
|
||||
expect(threadMessages.length, 15);
|
||||
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('getMessagesByCid along with quotedMessage', () 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, quoted: true);
|
||||
expect(insertedMessages, isNotEmpty);
|
||||
|
||||
// Fetched message should match the inserted messages
|
||||
final fetchedMessages = await messageDao.getMessagesByCid(cid);
|
||||
expect(fetchedMessages.length, insertedMessages.length);
|
||||
final quoted = fetchedMessages.where((it) => it.quotedMessage != null);
|
||||
expect(quoted.length, insertedMessages.length / 2);
|
||||
});
|
||||
|
||||
test('getMessagesByCid along with pagination', () async {
|
||||
const cid = 'testCid';
|
||||
const limit = 15;
|
||||
const lessThan = 'testMessageId${cid}25';
|
||||
const greaterThanOrEqual = 'testMessageId${cid}5';
|
||||
const pagination = PaginationParams(
|
||||
limit: limit,
|
||||
lessThan: lessThan,
|
||||
greaterThanOrEqual: greaterThanOrEqual,
|
||||
);
|
||||
|
||||
// Should be empty initially
|
||||
final messages = await messageDao.getMessagesByCid(
|
||||
cid,
|
||||
messagePagination: pagination,
|
||||
);
|
||||
expect(messages, isEmpty);
|
||||
|
||||
// Preparing test data
|
||||
final insertedMessages = await _prepareTestData(cid, count: 30);
|
||||
expect(insertedMessages, isNotEmpty);
|
||||
|
||||
// Fetched message should match the inserted messages
|
||||
final fetchedMessages = await messageDao.getMessagesByCid(
|
||||
cid,
|
||||
messagePagination: pagination,
|
||||
);
|
||||
expect(fetchedMessages.length, limit);
|
||||
expect(fetchedMessages.first.id, greaterThanOrEqual);
|
||||
expect(fetchedMessages.last.id != lessThan, true);
|
||||
});
|
||||
|
||||
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(newMessage.id),
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
tearDown(() async {
|
||||
await database.disconnect();
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,363 @@
|
||||
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() {
|
||||
PinnedMessageDao pinnedMessageDao;
|
||||
MoorChatDatabase database;
|
||||
|
||||
setUp(() {
|
||||
database = MoorChatDatabase.testable('testUserId');
|
||||
pinnedMessageDao = database.pinnedMessageDao;
|
||||
});
|
||||
|
||||
Future<List<Message>> _prepareTestData(
|
||||
String cid, {
|
||||
bool quoted = false,
|
||||
bool threads = false,
|
||||
bool mapAllThreadToFirstMessage = false,
|
||||
int count = 3,
|
||||
}) async {
|
||||
final users = List.generate(count, (index) => User(id: 'testUserId$index'));
|
||||
final messages = List.generate(
|
||||
count,
|
||||
(index) => Message(
|
||||
id: 'testMessageId$cid$index',
|
||||
type: 'testType',
|
||||
user: users[index],
|
||||
createdAt: DateTime.now(),
|
||||
shadowed: 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 quotedMessages = List.generate(
|
||||
count,
|
||||
(index) => Message(
|
||||
id: 'testQuotedMessageId$cid$index',
|
||||
type: 'testType',
|
||||
user: users[index],
|
||||
createdAt: DateTime.now(),
|
||||
shadowed: math.Random().nextBool(),
|
||||
replyCount: index,
|
||||
updatedAt: DateTime.now(),
|
||||
extraData: {'extra_test_field': 'extraTestData'},
|
||||
text: 'Dummy text #$index',
|
||||
quotedMessageId: messages[index].id,
|
||||
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: users[index],
|
||||
parentId:
|
||||
mapAllThreadToFirstMessage ? messages[0].id : messages[index].id,
|
||||
createdAt: DateTime.now(),
|
||||
shadowed: 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 (quoted) ...quotedMessages,
|
||||
if (threads) ...threadMessages
|
||||
];
|
||||
await database.userDao.updateUsers(users);
|
||||
await pinnedMessageDao.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 pinnedMessageDao.getMessagesByCid(cid);
|
||||
expect(messages.length, insertedMessages.length);
|
||||
|
||||
// Deleting 2 messages from DB
|
||||
await pinnedMessageDao.deleteMessageByIds(
|
||||
['testMessageId${cid}0', 'testMessageId${cid}1'],
|
||||
);
|
||||
|
||||
// New fetched messages length should 2 less than the
|
||||
// previous fetched messages
|
||||
final newMessages = await pinnedMessageDao.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 pinnedMessageDao.getMessagesByCid(cid1);
|
||||
final cid2Messages = await pinnedMessageDao.getMessagesByCid(cid2);
|
||||
expect(cid1Messages.length, cid1InsertedMessages.length);
|
||||
expect(cid2Messages.length, cid2InsertedMessages.length);
|
||||
|
||||
// Deleting all the messages of cid1
|
||||
await pinnedMessageDao.deleteMessageByCids([cid1]);
|
||||
|
||||
// Fetched messages length of only cid1 should be empty
|
||||
final cid1FetchedMessages = await pinnedMessageDao.getMessagesByCid(cid1);
|
||||
final cid2FetchedMessages = await pinnedMessageDao.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 pinnedMessageDao.getMessagesByCid(cid1);
|
||||
final cid2Messages = await pinnedMessageDao.getMessagesByCid(cid2);
|
||||
expect(cid1Messages.length, cid1InsertedMessages.length);
|
||||
expect(cid2Messages.length, cid2InsertedMessages.length);
|
||||
|
||||
// Deleting all the messages of cid1
|
||||
await pinnedMessageDao.deleteMessageByCids([cid1, cid2]);
|
||||
|
||||
// Fetched messages length of both cid1 and cid2 should be empty
|
||||
final cid1FetchedMessages = await pinnedMessageDao.getMessagesByCid(cid1);
|
||||
final cid2FetchedMessages = await pinnedMessageDao.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 pinnedMessageDao.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 pinnedMessageDao.getMessageById(id);
|
||||
expect(fetchedMessage.id, insertedMessages.first.id);
|
||||
});
|
||||
|
||||
test('getThreadMessages', () async {
|
||||
const cid = 'testCid';
|
||||
|
||||
// Messages should be empty initially
|
||||
final messages = await pinnedMessageDao.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 pinnedMessageDao.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 pinnedMessageDao.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 pinnedMessageDao.getThreadMessagesByParentId(parentId);
|
||||
expect(threadMessages.length, 1);
|
||||
expect(threadMessages.first.parentId, parentId);
|
||||
});
|
||||
|
||||
test('getThreadMessagesByParentId along with pagination', () async {
|
||||
const cid = 'testCid';
|
||||
const parentId = 'testMessageId${cid}0';
|
||||
const options = PaginationParams(
|
||||
limit: 15,
|
||||
lessThan: 'testThreadMessageId${cid}25',
|
||||
greaterThanOrEqual: 'testThreadMessageId${cid}5',
|
||||
);
|
||||
|
||||
// Messages should be empty initially
|
||||
final messages = await pinnedMessageDao.getThreadMessagesByParentId(
|
||||
parentId,
|
||||
options: options,
|
||||
);
|
||||
expect(messages, isEmpty);
|
||||
|
||||
// Preparing test data
|
||||
final insertedMessages = await _prepareTestData(
|
||||
cid,
|
||||
threads: true,
|
||||
mapAllThreadToFirstMessage: true,
|
||||
count: 30,
|
||||
);
|
||||
expect(insertedMessages, isNotEmpty);
|
||||
|
||||
// Should fetch all the thread messages of parentId and apply the pagination
|
||||
final threadMessages = await pinnedMessageDao.getThreadMessagesByParentId(
|
||||
parentId,
|
||||
options: options,
|
||||
);
|
||||
expect(threadMessages.length, 15);
|
||||
expect(threadMessages.first.parentId, parentId);
|
||||
});
|
||||
|
||||
test('getMessagesByCid', () async {
|
||||
const cid = 'testCid';
|
||||
|
||||
// Should be empty initially
|
||||
final messages = await pinnedMessageDao.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 pinnedMessageDao.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('getMessagesByCid along with quotedMessage', () async {
|
||||
const cid = 'testCid';
|
||||
|
||||
// Should be empty initially
|
||||
final messages = await pinnedMessageDao.getMessagesByCid(cid);
|
||||
expect(messages, isEmpty);
|
||||
|
||||
// Preparing test data
|
||||
final insertedMessages = await _prepareTestData(cid, quoted: true);
|
||||
expect(insertedMessages, isNotEmpty);
|
||||
|
||||
// Fetched message should match the inserted messages
|
||||
final fetchedMessages = await pinnedMessageDao.getMessagesByCid(cid);
|
||||
expect(fetchedMessages.length, insertedMessages.length);
|
||||
final quoted = fetchedMessages.where((it) => it.quotedMessage != null);
|
||||
expect(quoted.length, insertedMessages.length / 2);
|
||||
});
|
||||
|
||||
test('getMessagesByCid along with pagination', () async {
|
||||
const cid = 'testCid';
|
||||
const limit = 15;
|
||||
const lessThan = 'testMessageId${cid}25';
|
||||
const greaterThanOrEqual = 'testMessageId${cid}5';
|
||||
const pagination = PaginationParams(
|
||||
limit: limit,
|
||||
lessThan: lessThan,
|
||||
greaterThanOrEqual: greaterThanOrEqual,
|
||||
);
|
||||
|
||||
// Should be empty initially
|
||||
final messages = await pinnedMessageDao.getMessagesByCid(
|
||||
cid,
|
||||
messagePagination: pagination,
|
||||
);
|
||||
expect(messages, isEmpty);
|
||||
|
||||
// Preparing test data
|
||||
final insertedMessages = await _prepareTestData(cid, count: 30);
|
||||
expect(insertedMessages, isNotEmpty);
|
||||
|
||||
// Fetched message should match the inserted messages
|
||||
final fetchedMessages = await pinnedMessageDao.getMessagesByCid(
|
||||
cid,
|
||||
messagePagination: pagination,
|
||||
);
|
||||
expect(fetchedMessages.length, limit);
|
||||
expect(fetchedMessages.first.id, greaterThanOrEqual);
|
||||
expect(fetchedMessages.last.id != lessThan, true);
|
||||
});
|
||||
|
||||
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 pinnedMessageDao.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 pinnedMessageDao.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(newMessage.id),
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
tearDown(() async {
|
||||
await database.disconnect();
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:stream_chat/stream_chat.dart';
|
||||
import 'package:stream_chat_persistence/src/dao/reaction_dao.dart';
|
||||
import 'package:stream_chat_persistence/src/db/moor_chat_database.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
void main() {
|
||||
ReactionDao reactionDao;
|
||||
MoorChatDatabase database;
|
||||
|
||||
setUp(() {
|
||||
database = MoorChatDatabase.testable('testUserId');
|
||||
reactionDao = database.reactionDao;
|
||||
});
|
||||
|
||||
Future<List<Reaction>> _prepareReactionData(
|
||||
String messageId, {
|
||||
String userId,
|
||||
int count = 3,
|
||||
}) async {
|
||||
final users = List.generate(count, (index) => User(id: 'testUserId$index'));
|
||||
final message = Message(
|
||||
id: messageId,
|
||||
type: 'testType',
|
||||
user: users.first,
|
||||
createdAt: DateTime.now(),
|
||||
shadowed: math.Random().nextBool(),
|
||||
showInChannel: math.Random().nextBool(),
|
||||
replyCount: 3,
|
||||
updatedAt: DateTime.now(),
|
||||
extraData: {'extra_test_field': 'extraTestData'},
|
||||
text: 'Dummy text',
|
||||
pinned: math.Random().nextBool(),
|
||||
pinnedAt: DateTime.now(),
|
||||
pinnedBy: users.first,
|
||||
);
|
||||
final reactions = List.generate(
|
||||
count,
|
||||
(index) => Reaction(
|
||||
type: 'testType$index',
|
||||
createdAt: DateTime.now(),
|
||||
userId: userId ?? users[index].id,
|
||||
messageId: message.id,
|
||||
score: count + 3,
|
||||
extraData: {'extra_test_field': 'extraTestData'},
|
||||
),
|
||||
);
|
||||
|
||||
await database.userDao.updateUsers(users);
|
||||
await database.messageDao.updateMessages('testCid', [message]);
|
||||
await reactionDao.updateReactions(reactions);
|
||||
|
||||
return reactions;
|
||||
}
|
||||
|
||||
test('getReactions', () async {
|
||||
const messageId = 'testMessageId';
|
||||
|
||||
// Should be empty initially
|
||||
final reactions = await reactionDao.getReactions(messageId);
|
||||
expect(reactions, isEmpty);
|
||||
|
||||
// Adding sample reactions
|
||||
final insertedReactions = await _prepareReactionData(messageId);
|
||||
expect(insertedReactions, isNotEmpty);
|
||||
|
||||
// Fetched reaction length should match inserted reactions length.
|
||||
// Every reaction messageId should match the provided messageId.
|
||||
final fetchedReactions = await reactionDao.getReactions(messageId);
|
||||
expect(fetchedReactions.length, insertedReactions.length);
|
||||
expect(fetchedReactions.every((it) => it.messageId == messageId), true);
|
||||
});
|
||||
|
||||
test('getReactionsByUserId', () async {
|
||||
const messageId = 'testMessageId';
|
||||
const userId = 'testUserId';
|
||||
|
||||
// Should be empty initially
|
||||
final reactions = await reactionDao.getReactionsByUserId(messageId, userId);
|
||||
expect(reactions, isEmpty);
|
||||
|
||||
// Adding sample reactions
|
||||
final insertedReactions =
|
||||
await _prepareReactionData(messageId, userId: userId);
|
||||
expect(insertedReactions, isNotEmpty);
|
||||
|
||||
// Fetched reaction length should match inserted reactions length.
|
||||
// Every reaction messageId should match the provided messageId.
|
||||
// Every reaction userId should match the provided userId.
|
||||
final fetchedReactions =
|
||||
await reactionDao.getReactionsByUserId(messageId, userId);
|
||||
expect(fetchedReactions.length, insertedReactions.length);
|
||||
expect(fetchedReactions.every((it) => it.messageId == messageId), true);
|
||||
expect(fetchedReactions.every((it) => it.userId == userId), true);
|
||||
});
|
||||
|
||||
test('updateReactions', () async {
|
||||
const messageId = 'testMessageId';
|
||||
|
||||
// Preparing test data
|
||||
final reactions = await _prepareReactionData(messageId);
|
||||
|
||||
// Modifying one of the reaction and also adding one new
|
||||
final copyReaction = reactions.first.copyWith(score: 33);
|
||||
final newReaction = Reaction(
|
||||
type: 'testType3',
|
||||
createdAt: DateTime.now(),
|
||||
userId: 'testUserId3',
|
||||
messageId: messageId,
|
||||
score: 30,
|
||||
extraData: {'extra_test_field': 'extraTestData'},
|
||||
);
|
||||
|
||||
await reactionDao.updateReactions([copyReaction, newReaction]);
|
||||
|
||||
// Fetched reaction length should be one more than inserted reactions.
|
||||
// copyReaction `score` modified field should be 33.
|
||||
// Fetched reactions should contain the newReaction.
|
||||
final fetchedReactions = await reactionDao.getReactions(messageId);
|
||||
expect(fetchedReactions.length, reactions.length + 1);
|
||||
expect(
|
||||
fetchedReactions
|
||||
.firstWhere((it) =>
|
||||
it.userId == copyReaction.userId && it.type == copyReaction.type)
|
||||
.score,
|
||||
33,
|
||||
);
|
||||
expect(
|
||||
fetchedReactions
|
||||
.where((it) =>
|
||||
it.userId == newReaction.userId && it.type == newReaction.type)
|
||||
.isNotEmpty,
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
group('deleteReactionsByMessageIds', () {
|
||||
const messageId1 = 'testMessageId1';
|
||||
const messageId2 = 'testMessageId2';
|
||||
test('should delete all the reactions of first message', () async {
|
||||
// Preparing test data
|
||||
final insertedReactions1 = await _prepareReactionData(messageId1);
|
||||
final insertedReactions2 = await _prepareReactionData(messageId2);
|
||||
|
||||
// Fetched reaction list length should match
|
||||
// the inserted reactions list length
|
||||
final reactions1 = await reactionDao.getReactions(messageId1);
|
||||
final reactions2 = await reactionDao.getReactions(messageId2);
|
||||
expect(reactions1.length, insertedReactions1.length);
|
||||
expect(reactions2.length, insertedReactions2.length);
|
||||
|
||||
// Deleting all the reactions of messageId1
|
||||
await reactionDao.deleteReactionsByMessageIds([messageId1]);
|
||||
|
||||
// Fetched reactions length of only messageId1 should be empty
|
||||
final fetchedReactions1 = await reactionDao.getReactions(messageId1);
|
||||
final fetchedReactions2 = await reactionDao.getReactions(messageId2);
|
||||
expect(fetchedReactions1, isEmpty);
|
||||
expect(fetchedReactions2, isNotEmpty);
|
||||
});
|
||||
test('should delete all the messages of both message', () async {
|
||||
// Preparing test data
|
||||
final insertedReactions1 = await _prepareReactionData(messageId1);
|
||||
final insertedReactions2 = await _prepareReactionData(messageId2);
|
||||
|
||||
// Fetched reaction list length should match
|
||||
// the inserted reactions list length
|
||||
final reactions1 = await reactionDao.getReactions(messageId1);
|
||||
final reactions2 = await reactionDao.getReactions(messageId2);
|
||||
expect(reactions1.length, insertedReactions1.length);
|
||||
expect(reactions2.length, insertedReactions2.length);
|
||||
|
||||
// Deleting all the reactions of messageId1 and messageId2
|
||||
await reactionDao.deleteReactionsByMessageIds([messageId1, messageId2]);
|
||||
|
||||
// Fetched reactions length of both messages should be empty
|
||||
final fetchedReactions1 = await reactionDao.getReactions(messageId1);
|
||||
final fetchedReactions2 = await reactionDao.getReactions(messageId2);
|
||||
expect(fetchedReactions1, isEmpty);
|
||||
expect(fetchedReactions2, isEmpty);
|
||||
});
|
||||
});
|
||||
|
||||
tearDown(() async {
|
||||
await database.disconnect();
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
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';
|
||||
|
||||
import '../utils/date_matcher.dart';
|
||||
|
||||
void main() {
|
||||
ReadDao readDao;
|
||||
MoorChatDatabase database;
|
||||
|
||||
setUp(() {
|
||||
database = MoorChatDatabase.testable('testUserId');
|
||||
readDao = database.readDao;
|
||||
});
|
||||
|
||||
Future<List<Read>> _prepareReadData(String cid, {int count = 3}) async {
|
||||
final users = List.generate(count, (index) => User(id: 'testUserId$index'));
|
||||
final reads = List.generate(
|
||||
count,
|
||||
(index) => Read(
|
||||
lastRead: DateTime.now(),
|
||||
user: users[index],
|
||||
unreadMessages: index + 10,
|
||||
),
|
||||
);
|
||||
|
||||
await database.userDao.updateUsers(users);
|
||||
await readDao.updateReads(cid, reads);
|
||||
return reads;
|
||||
}
|
||||
|
||||
test('getReadsByCid', () async {
|
||||
const cid = 'testCid';
|
||||
|
||||
// Should be empty initially
|
||||
final reads = await readDao.getReadsByCid(cid);
|
||||
expect(reads, isEmpty);
|
||||
|
||||
// Preparing test data
|
||||
final insertedReads = await _prepareReadData(cid);
|
||||
expect(insertedReads, isNotEmpty);
|
||||
|
||||
// Fetched reads should be equal to inserted reads
|
||||
final fetchedReads = await readDao.getReadsByCid(cid);
|
||||
expect(fetchedReads.length, insertedReads.length);
|
||||
for (var i = 0; i < fetchedReads.length; i++) {
|
||||
final fetchedRead = fetchedReads[i];
|
||||
final insertedRead = insertedReads[i];
|
||||
expect(fetchedRead.user.id, insertedRead.user.id);
|
||||
expect(fetchedRead.lastRead, isSameDateAs(insertedRead.lastRead));
|
||||
expect(fetchedRead.unreadMessages, insertedRead.unreadMessages);
|
||||
}
|
||||
});
|
||||
|
||||
test('updateReads', () async {
|
||||
const cid = 'testCid';
|
||||
|
||||
// Preparing test data
|
||||
final insertedReads = await _prepareReadData(cid);
|
||||
|
||||
// Modifying one of the read and also adding one new
|
||||
final copyRead = insertedReads.first.copyWith(unreadMessages: 33);
|
||||
final newUser = User(id: 'testUserId3');
|
||||
final newRead = Read(
|
||||
lastRead: DateTime.now(),
|
||||
user: newUser,
|
||||
unreadMessages: 30,
|
||||
);
|
||||
await database.userDao.updateUsers([newUser]);
|
||||
await readDao.updateReads(cid, [copyRead, newRead]);
|
||||
|
||||
// Fetched reads length should be one more than inserted reads.
|
||||
// copyRead `unreadMessages` modified field should be 33.
|
||||
// Fetched reads should contain the newRead.
|
||||
final fetchedReads = await readDao.getReadsByCid(cid);
|
||||
expect(fetchedReads.length, insertedReads.length + 1);
|
||||
expect(
|
||||
fetchedReads
|
||||
.firstWhere((it) => it.user.id == copyRead.user.id)
|
||||
.unreadMessages,
|
||||
33,
|
||||
);
|
||||
expect(
|
||||
fetchedReads
|
||||
.where((it) =>
|
||||
it.user.id == newRead.user.id &&
|
||||
it.unreadMessages == newRead.unreadMessages)
|
||||
.isNotEmpty,
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
tearDown(() async {
|
||||
await database.disconnect();
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
import 'dart:math' as math;
|
||||
|
||||
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';
|
||||
import 'package:stream_chat/stream_chat.dart';
|
||||
|
||||
void main() {
|
||||
UserDao userDao;
|
||||
MoorChatDatabase database;
|
||||
|
||||
setUp(() {
|
||||
database = MoorChatDatabase.testable('testUserId');
|
||||
userDao = database.userDao;
|
||||
});
|
||||
|
||||
Future<List<User>> _prepareUserData({int count = 3}) async {
|
||||
final users = List.generate(
|
||||
count,
|
||||
(index) => User(
|
||||
id: 'testUserId$index',
|
||||
role: 'testRole',
|
||||
createdAt: DateTime.now(),
|
||||
updatedAt: DateTime.now(),
|
||||
lastActive: DateTime.now(),
|
||||
online: math.Random().nextBool(),
|
||||
banned: math.Random().nextBool(),
|
||||
),
|
||||
);
|
||||
await userDao.updateUsers(users);
|
||||
return users;
|
||||
}
|
||||
|
||||
test('updateUsers', () async {
|
||||
// Preparing test data
|
||||
final insertedUsers = await _prepareUserData();
|
||||
|
||||
// Modifying one of the user and also adding one new
|
||||
final copyUser = insertedUsers.first.copyWith(online: false);
|
||||
final newUser = User(
|
||||
id: 'testUserId3',
|
||||
role: 'testRole',
|
||||
createdAt: DateTime.now(),
|
||||
updatedAt: DateTime.now(),
|
||||
lastActive: DateTime.now(),
|
||||
online: math.Random().nextBool(),
|
||||
banned: math.Random().nextBool(),
|
||||
);
|
||||
await userDao.updateUsers([copyUser, newUser]);
|
||||
|
||||
// Fetched users length should be one more than inserted users.
|
||||
// copyUser `online` modified field should be `false`.
|
||||
// Fetched users should contain the newUser.
|
||||
final fetchedUsers = await userDao.getUsers();
|
||||
expect(fetchedUsers.length, insertedUsers.length + 1);
|
||||
expect(fetchedUsers.firstWhere((it) => it.id == copyUser.id).online, false);
|
||||
expect(fetchedUsers.contains(newUser), true);
|
||||
});
|
||||
|
||||
test('getUsers', () async {
|
||||
// Should be empty initially
|
||||
final users = await userDao.getUsers();
|
||||
expect(users, isEmpty);
|
||||
|
||||
// Preparing test data
|
||||
final insertedUsers = await _prepareUserData();
|
||||
expect(insertedUsers, isNotEmpty);
|
||||
|
||||
// Fetched user list should match inserted user list length
|
||||
final fetchedUsers = await userDao.getUsers();
|
||||
expect(fetchedUsers.length, insertedUsers.length);
|
||||
});
|
||||
|
||||
tearDown(() async {
|
||||
await database.disconnect();
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
import 'package:test/test.dart';
|
||||
import 'package:moor/ffi.dart';
|
||||
import 'package:moor/isolate.dart';
|
||||
import 'package:moor/moor.dart' hide isNotNull;
|
||||
import 'package:stream_chat_persistence/src/db/moor_chat_database.dart';
|
||||
|
||||
DatabaseConnection _backgroundConnection() =>
|
||||
DatabaseConnection.fromExecutor(VmDatabase.memory());
|
||||
|
||||
void main() {
|
||||
test(
|
||||
'default constructor should create a new instance of MoorChatDatabase',
|
||||
() async {
|
||||
const userId = 'testUserId';
|
||||
final executor = VmDatabase.memory();
|
||||
final database = MoorChatDatabase(userId, executor);
|
||||
expect(database, isNotNull);
|
||||
expect(database.userId, userId);
|
||||
|
||||
addTearDown(() async {
|
||||
await database.disconnect();
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'connect constructor should create a new instance of MoorChatDatabase',
|
||||
() async {
|
||||
const userId = 'testUserId';
|
||||
final isolate = await MoorIsolate.spawn(_backgroundConnection);
|
||||
final connection = DatabaseConnection.delayed(isolate.connect());
|
||||
|
||||
final database = MoorChatDatabase.connect(userId, connection);
|
||||
expect(database, isNotNull);
|
||||
expect(database.userId, userId);
|
||||
|
||||
addTearDown(() async {
|
||||
await database.disconnect();
|
||||
await isolate.shutdownAll();
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:test/test.dart';
|
||||
import 'package:stream_chat/stream_chat.dart';
|
||||
import 'package:stream_chat_persistence/src/db/moor_chat_database.dart';
|
||||
import 'package:stream_chat_persistence/src/mapper/channel_mapper.dart';
|
||||
import '../utils/date_matcher.dart';
|
||||
|
||||
void main() {
|
||||
group('ChannelEntity', () {
|
||||
final user = User(id: 'testUserId');
|
||||
final entity = ChannelEntity(
|
||||
id: 'testId',
|
||||
type: 'testType',
|
||||
cid: 'testCid',
|
||||
config: {'max_message_length': 33},
|
||||
frozen: math.Random().nextBool(),
|
||||
lastMessageAt: DateTime.now(),
|
||||
createdAt: DateTime.now(),
|
||||
updatedAt: DateTime.now(),
|
||||
deletedAt: DateTime.now(),
|
||||
memberCount: 33,
|
||||
createdById: user.id,
|
||||
extraData: {'test_extra_data': 'testData'},
|
||||
);
|
||||
|
||||
test('toChannelModel should map entity into ChannelModel', () {
|
||||
final channelModel = entity.toChannelModel(createdBy: user);
|
||||
expect(channelModel, isA<ChannelModel>());
|
||||
expect(channelModel.id, entity.id);
|
||||
expect(channelModel.config.toJson()['max_message_length'], 33);
|
||||
expect(channelModel.frozen, entity.frozen);
|
||||
expect(channelModel.createdAt, isSameDateAs(entity.createdAt));
|
||||
expect(channelModel.updatedAt, isSameDateAs(entity.updatedAt));
|
||||
expect(channelModel.memberCount, entity.memberCount);
|
||||
expect(channelModel.cid, entity.cid);
|
||||
expect(channelModel.lastMessageAt, isSameDateAs(entity.lastMessageAt));
|
||||
expect(channelModel.deletedAt, isSameDateAs(entity.deletedAt));
|
||||
expect(channelModel.extraData, entity.extraData);
|
||||
expect(channelModel.createdBy.id, entity.createdById);
|
||||
});
|
||||
|
||||
test('toChannelState should map entity into ChannelState ', () {
|
||||
final members = List.generate(3, (index) => Member());
|
||||
final reads = List.generate(3, (index) => Read());
|
||||
final messages = List.generate(3, (index) => Message());
|
||||
|
||||
final channelState = entity.toChannelState(
|
||||
createdBy: user,
|
||||
members: members,
|
||||
reads: reads,
|
||||
messages: messages,
|
||||
pinnedMessages: messages,
|
||||
);
|
||||
|
||||
expect(channelState, isA<ChannelState>());
|
||||
expect(channelState.members.length, members.length);
|
||||
expect(channelState.read.length, reads.length);
|
||||
expect(channelState.messages.length, messages.length);
|
||||
expect(channelState.pinnedMessages.length, messages.length);
|
||||
|
||||
final channelModel = channelState.channel;
|
||||
expect(channelModel.id, entity.id);
|
||||
expect(channelModel.config.toJson()['max_message_length'], 33);
|
||||
expect(channelModel.frozen, entity.frozen);
|
||||
expect(channelModel.createdAt, isSameDateAs(entity.createdAt));
|
||||
expect(channelModel.updatedAt, isSameDateAs(entity.updatedAt));
|
||||
expect(channelModel.memberCount, entity.memberCount);
|
||||
expect(channelModel.cid, entity.cid);
|
||||
expect(channelModel.lastMessageAt, isSameDateAs(entity.lastMessageAt));
|
||||
expect(channelModel.deletedAt, isSameDateAs(entity.deletedAt));
|
||||
expect(channelModel.extraData, entity.extraData);
|
||||
expect(channelModel.createdBy.id, entity.createdById);
|
||||
});
|
||||
});
|
||||
|
||||
test('toEntity should map model into ChannelEntity', () {
|
||||
final createdBy = User(id: 'testUserId');
|
||||
final model = ChannelModel(
|
||||
id: 'testId',
|
||||
type: 'testType',
|
||||
cid: 'testCid',
|
||||
config: ChannelConfig(maxMessageLength: 33),
|
||||
frozen: math.Random().nextBool(),
|
||||
lastMessageAt: DateTime.now(),
|
||||
createdAt: DateTime.now(),
|
||||
updatedAt: DateTime.now(),
|
||||
deletedAt: DateTime.now(),
|
||||
memberCount: 33,
|
||||
createdBy: createdBy,
|
||||
extraData: {'test_extra_data': 'testData'},
|
||||
);
|
||||
|
||||
final channelEntity = model.toEntity();
|
||||
expect(channelEntity, isA<ChannelEntity>());
|
||||
expect(channelEntity.id, model.id);
|
||||
expect(
|
||||
channelEntity.config['max_message_length'],
|
||||
model.config.maxMessageLength,
|
||||
);
|
||||
expect(channelEntity.frozen, model.frozen);
|
||||
expect(channelEntity.createdAt, isSameDateAs(model.createdAt));
|
||||
expect(channelEntity.updatedAt, isSameDateAs(model.updatedAt));
|
||||
expect(channelEntity.memberCount, model.memberCount);
|
||||
expect(channelEntity.cid, model.cid);
|
||||
expect(channelEntity.lastMessageAt, isSameDateAs(model.lastMessageAt));
|
||||
expect(channelEntity.deletedAt, isSameDateAs(model.deletedAt));
|
||||
expect(channelEntity.extraData, model.extraData);
|
||||
expect(channelEntity.createdById, model.createdBy.id);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import 'package:test/test.dart';
|
||||
import 'package:stream_chat/stream_chat.dart';
|
||||
import 'package:stream_chat_persistence/src/db/moor_chat_database.dart';
|
||||
import 'package:stream_chat_persistence/src/mapper/event_mapper.dart';
|
||||
|
||||
void main() {
|
||||
test('toEvent should map entity into Event', () {
|
||||
final ownUser = OwnUser(id: 'testUserId');
|
||||
final entity = ConnectionEventEntity(
|
||||
id: 3,
|
||||
ownUser: ownUser.toJson(),
|
||||
totalUnreadCount: 33,
|
||||
unreadChannels: 33,
|
||||
lastSyncAt: DateTime.now(),
|
||||
lastEventAt: DateTime.now(),
|
||||
);
|
||||
final event = entity.toEvent();
|
||||
expect(event, isA<Event>());
|
||||
expect(event.me.id, ownUser.id);
|
||||
expect(event.totalUnreadCount, entity.totalUnreadCount);
|
||||
expect(event.unreadChannels, entity.unreadChannels);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:test/test.dart';
|
||||
import 'package:stream_chat/stream_chat.dart';
|
||||
import 'package:stream_chat_persistence/src/db/moor_chat_database.dart';
|
||||
import 'package:stream_chat_persistence/src/mapper/member_mapper.dart';
|
||||
|
||||
import '../utils/date_matcher.dart';
|
||||
|
||||
void main() {
|
||||
test('toMember should map entity into Member', () {
|
||||
final user = User(id: 'testUserId');
|
||||
final entity = MemberEntity(
|
||||
userId: user.id,
|
||||
channelCid: 'testCid',
|
||||
createdAt: DateTime.now(),
|
||||
updatedAt: DateTime.now(),
|
||||
role: 'testRole',
|
||||
inviteAcceptedAt: DateTime.now(),
|
||||
inviteRejectedAt: DateTime.now(),
|
||||
invited: math.Random().nextBool(),
|
||||
banned: math.Random().nextBool(),
|
||||
shadowBanned: math.Random().nextBool(),
|
||||
isModerator: math.Random().nextBool(),
|
||||
);
|
||||
final member = entity.toMember(user: user);
|
||||
expect(member, isA<Member>());
|
||||
expect(member.user.id, entity.userId);
|
||||
expect(member.createdAt, isSameDateAs(entity.createdAt));
|
||||
expect(member.updatedAt, isSameDateAs(entity.updatedAt));
|
||||
expect(member.role, entity.role);
|
||||
expect(member.inviteAcceptedAt, isSameDateAs(entity.inviteAcceptedAt));
|
||||
expect(member.inviteRejectedAt, isSameDateAs(entity.inviteRejectedAt));
|
||||
expect(member.invited, entity.invited);
|
||||
expect(member.banned, entity.banned);
|
||||
expect(member.shadowBanned, entity.shadowBanned);
|
||||
expect(member.isModerator, entity.isModerator);
|
||||
});
|
||||
|
||||
test('toEntity show map member into MemberEntity', () {
|
||||
const cid = 'testCid';
|
||||
final user = User(id: 'testUserId');
|
||||
final member = Member(
|
||||
user: user,
|
||||
createdAt: DateTime.now(),
|
||||
updatedAt: DateTime.now(),
|
||||
role: 'testRole',
|
||||
inviteAcceptedAt: DateTime.now(),
|
||||
inviteRejectedAt: DateTime.now(),
|
||||
invited: math.Random().nextBool(),
|
||||
banned: math.Random().nextBool(),
|
||||
shadowBanned: math.Random().nextBool(),
|
||||
isModerator: math.Random().nextBool(),
|
||||
);
|
||||
final entity = member.toEntity(cid: cid);
|
||||
expect(entity, isA<MemberEntity>());
|
||||
expect(entity.channelCid, cid);
|
||||
expect(entity.userId, member.user.id);
|
||||
expect(entity.createdAt, isSameDateAs(member.createdAt));
|
||||
expect(entity.updatedAt, isSameDateAs(member.updatedAt));
|
||||
expect(entity.role, member.role);
|
||||
expect(entity.inviteAcceptedAt, isSameDateAs(member.inviteAcceptedAt));
|
||||
expect(entity.inviteRejectedAt, isSameDateAs(member.inviteRejectedAt));
|
||||
expect(entity.invited, member.invited);
|
||||
expect(entity.banned, member.banned);
|
||||
expect(entity.shadowBanned, member.shadowBanned);
|
||||
expect(entity.isModerator, member.isModerator);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:test/test.dart';
|
||||
import 'package:stream_chat/stream_chat.dart';
|
||||
import 'package:stream_chat_persistence/src/db/moor_chat_database.dart';
|
||||
import 'package:stream_chat_persistence/src/mapper/message_mapper.dart';
|
||||
|
||||
import '../utils/date_matcher.dart';
|
||||
|
||||
void main() {
|
||||
test('toMessage should map the entity into Message', () {
|
||||
final user = User(id: 'testUserId');
|
||||
final quotedMessage = Message(id: 'testQuotedMessageId');
|
||||
final reactions = List.generate(
|
||||
3,
|
||||
(index) => Reaction(
|
||||
messageId: 'testMessageId',
|
||||
createdAt: DateTime.now(),
|
||||
type: 'testType$index',
|
||||
user: user,
|
||||
score: math.Random().nextInt(50),
|
||||
),
|
||||
);
|
||||
final attachments = List.generate(
|
||||
3,
|
||||
(index) => Attachment(
|
||||
id: 'testAttachmentId',
|
||||
type: 'testAttachmentType',
|
||||
assetUrl: 'testAssetUrl',
|
||||
),
|
||||
);
|
||||
final entity = MessageEntity(
|
||||
id: 'testMessageId',
|
||||
attachments: attachments?.map((it) => jsonEncode(it.toData()))?.toList(),
|
||||
channelCid: 'testCid',
|
||||
type: 'testType',
|
||||
parentId: 'testParentId',
|
||||
quotedMessageId: quotedMessage.id,
|
||||
command: 'testCommand',
|
||||
createdAt: DateTime.now(),
|
||||
shadowed: math.Random().nextBool(),
|
||||
showInChannel: math.Random().nextBool(),
|
||||
replyCount: 33,
|
||||
reactionScores: {for (final r in reactions) r.type: r.score},
|
||||
reactionCounts: reactions.fold(
|
||||
{},
|
||||
(prev, curr) =>
|
||||
prev..update(curr.type, (value) => value + 1, ifAbsent: () => 1),
|
||||
),
|
||||
status: MessageSendingStatus.sent,
|
||||
updatedAt: DateTime.now(),
|
||||
extraData: {'extra_test_data': 'extraData'},
|
||||
userId: user.id,
|
||||
deletedAt: DateTime.now(),
|
||||
messageText: 'dummy text',
|
||||
pinned: true,
|
||||
pinExpires: DateTime.now().toUtc(),
|
||||
pinnedAt: DateTime.now(),
|
||||
pinnedByUserId: user.id,
|
||||
);
|
||||
final message = entity.toMessage(
|
||||
user: user,
|
||||
pinnedBy: user,
|
||||
latestReactions: reactions,
|
||||
ownReactions: reactions,
|
||||
quotedMessage: quotedMessage,
|
||||
);
|
||||
|
||||
expect(message, isA<Message>());
|
||||
expect(message.id, entity.id);
|
||||
expect(message.type, entity.type);
|
||||
expect(message.parentId, entity.parentId);
|
||||
expect(message.quotedMessageId, entity.quotedMessageId);
|
||||
expect(message.command, entity.command);
|
||||
expect(message.createdAt, isSameDateAs(entity.createdAt));
|
||||
expect(message.shadowed, entity.shadowed);
|
||||
expect(message.showInChannel, entity.showInChannel);
|
||||
expect(message.replyCount, entity.replyCount);
|
||||
expect(message.reactionScores, entity.reactionScores);
|
||||
expect(message.reactionCounts, entity.reactionCounts);
|
||||
expect(message.status, entity.status);
|
||||
expect(message.updatedAt, isSameDateAs(entity.updatedAt));
|
||||
expect(message.extraData, entity.extraData);
|
||||
expect(message.user.id, entity.userId);
|
||||
expect(message.deletedAt, isSameDateAs(entity.deletedAt));
|
||||
expect(message.text, entity.messageText);
|
||||
expect(message.pinned, entity.pinned);
|
||||
expect(message.pinExpires, isSameDateAs(entity.pinExpires));
|
||||
expect(message.pinnedAt, isSameDateAs(entity.pinnedAt));
|
||||
expect(message.pinnedBy.id, entity.pinnedByUserId);
|
||||
expect(message.reactionCounts, entity.reactionCounts);
|
||||
expect(message.reactionScores, entity.reactionScores);
|
||||
for (var i = 0; i < message.attachments.length; i++) {
|
||||
final messageAttachment = message.attachments[i];
|
||||
final entityAttachmentData = jsonDecode(entity.attachments[i]);
|
||||
final entityAttachment = Attachment.fromData(entityAttachmentData);
|
||||
expect(messageAttachment.id, entityAttachment.id);
|
||||
expect(messageAttachment.type, entityAttachment.type);
|
||||
expect(messageAttachment.assetUrl, entityAttachment.assetUrl);
|
||||
}
|
||||
});
|
||||
|
||||
test('toEntity should map message into MessageEntity', () {
|
||||
const cid = 'testCid';
|
||||
final user = User(id: 'testUserId');
|
||||
final quotedMessage = Message(id: 'testQuotedMessageId');
|
||||
final reactions = List.generate(
|
||||
3,
|
||||
(index) => Reaction(
|
||||
messageId: 'testMessageId',
|
||||
createdAt: DateTime.now(),
|
||||
type: 'testType$index',
|
||||
user: user,
|
||||
score: math.Random().nextInt(50),
|
||||
),
|
||||
);
|
||||
final attachments = List.generate(
|
||||
3,
|
||||
(index) => Attachment(
|
||||
id: 'testAttachmentId',
|
||||
type: 'testAttachmentType',
|
||||
assetUrl: 'testAssetUrl',
|
||||
),
|
||||
);
|
||||
final message = Message(
|
||||
id: 'testMessageId',
|
||||
attachments: attachments,
|
||||
type: 'testType',
|
||||
parentId: 'testParentId',
|
||||
quotedMessageId: quotedMessage.id,
|
||||
command: 'testCommand',
|
||||
createdAt: DateTime.now(),
|
||||
shadowed: math.Random().nextBool(),
|
||||
showInChannel: math.Random().nextBool(),
|
||||
replyCount: 33,
|
||||
reactionScores: {for (final r in reactions) r.type: r.score},
|
||||
reactionCounts: reactions.fold(
|
||||
{},
|
||||
(prev, curr) =>
|
||||
prev..update(curr.type, (value) => value + 1, ifAbsent: () => 1),
|
||||
),
|
||||
status: MessageSendingStatus.sending,
|
||||
updatedAt: DateTime.now(),
|
||||
extraData: {'extra_test_data': 'extraData'},
|
||||
user: user,
|
||||
deletedAt: DateTime.now(),
|
||||
text: 'dummy text',
|
||||
pinned: true,
|
||||
pinExpires: DateTime.now(),
|
||||
pinnedAt: DateTime.now(),
|
||||
pinnedBy: user,
|
||||
);
|
||||
final entity = message.toEntity(cid: cid);
|
||||
expect(entity, isA<MessageEntity>());
|
||||
expect(entity.id, message.id);
|
||||
expect(entity.type, message.type);
|
||||
expect(entity.parentId, message.parentId);
|
||||
expect(entity.quotedMessageId, message.quotedMessageId);
|
||||
expect(entity.command, message.command);
|
||||
expect(entity.createdAt, isSameDateAs(message.createdAt));
|
||||
expect(entity.shadowed, message.shadowed);
|
||||
expect(entity.showInChannel, message.showInChannel);
|
||||
expect(entity.replyCount, message.replyCount);
|
||||
expect(entity.reactionScores, message.reactionScores);
|
||||
expect(entity.reactionCounts, message.reactionCounts);
|
||||
expect(entity.status, message.status);
|
||||
expect(entity.updatedAt, isSameDateAs(message.updatedAt));
|
||||
expect(entity.extraData, message.extraData);
|
||||
expect(entity.userId, message.user.id);
|
||||
expect(entity.deletedAt, isSameDateAs(message.deletedAt));
|
||||
expect(entity.messageText, message.text);
|
||||
expect(entity.pinned, message.pinned);
|
||||
expect(entity.pinExpires, isSameDateAs(message.pinExpires));
|
||||
expect(entity.pinnedAt, isSameDateAs(message.pinnedAt));
|
||||
expect(entity.pinnedByUserId, message.pinnedBy.id);
|
||||
expect(entity.reactionCounts, message.reactionCounts);
|
||||
expect(entity.reactionScores, message.reactionScores);
|
||||
expect(
|
||||
entity.attachments,
|
||||
message.attachments?.map((it) => jsonEncode(it.toData()))?.toList(),
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:test/test.dart';
|
||||
import 'package:stream_chat/stream_chat.dart';
|
||||
import 'package:stream_chat_persistence/src/db/moor_chat_database.dart';
|
||||
import 'package:stream_chat_persistence/src/mapper/pinned_message_mapper.dart';
|
||||
|
||||
import '../utils/date_matcher.dart';
|
||||
|
||||
void main() {
|
||||
test('toMessage should map the entity into Message', () {
|
||||
final user = User(id: 'testUserId');
|
||||
final quotedMessage = Message(id: 'testQuotedMessageId');
|
||||
final reactions = List.generate(
|
||||
3,
|
||||
(index) => Reaction(
|
||||
messageId: 'testMessageId',
|
||||
createdAt: DateTime.now(),
|
||||
type: 'testType$index',
|
||||
user: user,
|
||||
score: math.Random().nextInt(50),
|
||||
),
|
||||
);
|
||||
final attachments = List.generate(
|
||||
3,
|
||||
(index) => Attachment(
|
||||
id: 'testAttachmentId',
|
||||
type: 'testAttachmentType',
|
||||
assetUrl: 'testAssetUrl',
|
||||
),
|
||||
);
|
||||
final entity = PinnedMessageEntity(
|
||||
id: 'testMessageId',
|
||||
attachments: attachments?.map((it) => jsonEncode(it.toData()))?.toList(),
|
||||
channelCid: 'testCid',
|
||||
type: 'testType',
|
||||
parentId: 'testParentId',
|
||||
quotedMessageId: quotedMessage.id,
|
||||
command: 'testCommand',
|
||||
createdAt: DateTime.now(),
|
||||
shadowed: math.Random().nextBool(),
|
||||
showInChannel: math.Random().nextBool(),
|
||||
replyCount: 33,
|
||||
reactionScores: {for (final r in reactions) r.type: r.score},
|
||||
reactionCounts: reactions.fold(
|
||||
{},
|
||||
(prev, curr) =>
|
||||
prev..update(curr.type, (value) => value + 1, ifAbsent: () => 1),
|
||||
),
|
||||
status: MessageSendingStatus.sent,
|
||||
updatedAt: DateTime.now(),
|
||||
extraData: {'extra_test_data': 'extraData'},
|
||||
userId: user.id,
|
||||
deletedAt: DateTime.now(),
|
||||
messageText: 'dummy text',
|
||||
pinned: true,
|
||||
pinExpires: DateTime.now().toUtc(),
|
||||
pinnedAt: DateTime.now(),
|
||||
pinnedByUserId: user.id,
|
||||
);
|
||||
final message = entity.toMessage(
|
||||
user: user,
|
||||
pinnedBy: user,
|
||||
latestReactions: reactions,
|
||||
ownReactions: reactions,
|
||||
quotedMessage: quotedMessage,
|
||||
);
|
||||
|
||||
expect(message, isA<Message>());
|
||||
expect(message.id, entity.id);
|
||||
expect(message.type, entity.type);
|
||||
expect(message.parentId, entity.parentId);
|
||||
expect(message.quotedMessageId, entity.quotedMessageId);
|
||||
expect(message.command, entity.command);
|
||||
expect(message.createdAt, isSameDateAs(entity.createdAt));
|
||||
expect(message.shadowed, entity.shadowed);
|
||||
expect(message.showInChannel, entity.showInChannel);
|
||||
expect(message.replyCount, entity.replyCount);
|
||||
expect(message.reactionScores, entity.reactionScores);
|
||||
expect(message.reactionCounts, entity.reactionCounts);
|
||||
expect(message.status, entity.status);
|
||||
expect(message.updatedAt, isSameDateAs(entity.updatedAt));
|
||||
expect(message.extraData, entity.extraData);
|
||||
expect(message.user.id, entity.userId);
|
||||
expect(message.deletedAt, isSameDateAs(entity.deletedAt));
|
||||
expect(message.text, entity.messageText);
|
||||
expect(message.pinned, entity.pinned);
|
||||
expect(message.pinExpires, isSameDateAs(entity.pinExpires));
|
||||
expect(message.pinnedAt, isSameDateAs(entity.pinnedAt));
|
||||
expect(message.pinnedBy.id, entity.pinnedByUserId);
|
||||
expect(message.reactionCounts, entity.reactionCounts);
|
||||
expect(message.reactionScores, entity.reactionScores);
|
||||
for (var i = 0; i < message.attachments.length; i++) {
|
||||
final messageAttachment = message.attachments[i];
|
||||
final entityAttachmentData = jsonDecode(entity.attachments[i]);
|
||||
final entityAttachment = Attachment.fromData(entityAttachmentData);
|
||||
expect(messageAttachment.id, entityAttachment.id);
|
||||
expect(messageAttachment.type, entityAttachment.type);
|
||||
expect(messageAttachment.assetUrl, entityAttachment.assetUrl);
|
||||
}
|
||||
});
|
||||
|
||||
test('toPinnedEntity should map message into PinnedMessageEntity', () {
|
||||
const cid = 'testCid';
|
||||
final user = User(id: 'testUserId');
|
||||
final quotedMessage = Message(id: 'testQuotedMessageId');
|
||||
final reactions = List.generate(
|
||||
3,
|
||||
(index) => Reaction(
|
||||
messageId: 'testMessageId',
|
||||
createdAt: DateTime.now(),
|
||||
type: 'testType$index',
|
||||
user: user,
|
||||
score: math.Random().nextInt(50),
|
||||
),
|
||||
);
|
||||
final attachments = List.generate(
|
||||
3,
|
||||
(index) => Attachment(
|
||||
id: 'testAttachmentId',
|
||||
type: 'testAttachmentType',
|
||||
assetUrl: 'testAssetUrl',
|
||||
),
|
||||
);
|
||||
final message = Message(
|
||||
id: 'testMessageId',
|
||||
attachments: attachments,
|
||||
type: 'testType',
|
||||
parentId: 'testParentId',
|
||||
quotedMessageId: quotedMessage.id,
|
||||
command: 'testCommand',
|
||||
createdAt: DateTime.now(),
|
||||
shadowed: math.Random().nextBool(),
|
||||
showInChannel: math.Random().nextBool(),
|
||||
replyCount: 33,
|
||||
reactionScores: {for (final r in reactions) r.type: r.score},
|
||||
reactionCounts: reactions.fold(
|
||||
{},
|
||||
(prev, curr) =>
|
||||
prev..update(curr.type, (value) => value + 1, ifAbsent: () => 1),
|
||||
),
|
||||
status: MessageSendingStatus.sending,
|
||||
updatedAt: DateTime.now(),
|
||||
extraData: {'extra_test_data': 'extraData'},
|
||||
user: user,
|
||||
deletedAt: DateTime.now(),
|
||||
text: 'dummy text',
|
||||
pinned: true,
|
||||
pinExpires: DateTime.now(),
|
||||
pinnedAt: DateTime.now(),
|
||||
pinnedBy: user,
|
||||
);
|
||||
final entity = message.toPinnedEntity(cid: cid);
|
||||
expect(entity, isA<PinnedMessageEntity>());
|
||||
expect(entity.id, message.id);
|
||||
expect(entity.type, message.type);
|
||||
expect(entity.parentId, message.parentId);
|
||||
expect(entity.quotedMessageId, message.quotedMessageId);
|
||||
expect(entity.command, message.command);
|
||||
expect(entity.createdAt, isSameDateAs(message.createdAt));
|
||||
expect(entity.shadowed, message.shadowed);
|
||||
expect(entity.showInChannel, message.showInChannel);
|
||||
expect(entity.replyCount, message.replyCount);
|
||||
expect(entity.reactionScores, message.reactionScores);
|
||||
expect(entity.reactionCounts, message.reactionCounts);
|
||||
expect(entity.status, message.status);
|
||||
expect(entity.updatedAt, isSameDateAs(message.updatedAt));
|
||||
expect(entity.extraData, message.extraData);
|
||||
expect(entity.userId, message.user.id);
|
||||
expect(entity.deletedAt, isSameDateAs(message.deletedAt));
|
||||
expect(entity.messageText, message.text);
|
||||
expect(entity.pinned, message.pinned);
|
||||
expect(entity.pinExpires, isSameDateAs(message.pinExpires));
|
||||
expect(entity.pinnedAt, isSameDateAs(message.pinnedAt));
|
||||
expect(entity.pinnedByUserId, message.pinnedBy.id);
|
||||
expect(entity.reactionCounts, message.reactionCounts);
|
||||
expect(entity.reactionScores, message.reactionScores);
|
||||
expect(
|
||||
entity.attachments,
|
||||
message.attachments?.map((it) => jsonEncode(it.toData()))?.toList(),
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
import 'package:test/test.dart';
|
||||
import 'package:stream_chat/stream_chat.dart';
|
||||
import 'package:stream_chat_persistence/src/db/moor_chat_database.dart';
|
||||
import 'package:stream_chat_persistence/src/mapper/reaction_mapper.dart';
|
||||
|
||||
import '../utils/date_matcher.dart';
|
||||
|
||||
void main() {
|
||||
test('toReaction should map the entity into Reaction', () {
|
||||
final user = User(id: 'testUserId');
|
||||
final message = Message(id: 'testMessageId');
|
||||
final entity = ReactionEntity(
|
||||
userId: user.id,
|
||||
messageId: message.id,
|
||||
type: 'haha',
|
||||
score: 33,
|
||||
createdAt: DateTime.now(),
|
||||
extraData: {'extra_test_data': 'extraData'},
|
||||
);
|
||||
|
||||
final reaction = entity.toReaction(user: user);
|
||||
expect(reaction, isA<Reaction>());
|
||||
expect(reaction.userId, entity.userId);
|
||||
expect(reaction.messageId, entity.messageId);
|
||||
expect(reaction.type, entity.type);
|
||||
expect(reaction.score, entity.score);
|
||||
expect(reaction.createdAt, isSameDateAs(entity.createdAt));
|
||||
expect(reaction.extraData, entity.extraData);
|
||||
});
|
||||
|
||||
test('toEntity should map reaction into ReactionEntity', () {
|
||||
final user = User(id: 'testUserId');
|
||||
final message = Message(id: 'testMessageId');
|
||||
final reaction = Reaction(
|
||||
userId: user.id,
|
||||
messageId: message.id,
|
||||
type: 'haha',
|
||||
score: 33,
|
||||
createdAt: DateTime.now(),
|
||||
extraData: {'extra_test_data': 'extraData'},
|
||||
);
|
||||
|
||||
final entity = reaction.toEntity();
|
||||
expect(entity, isA<ReactionEntity>());
|
||||
expect(entity.userId, reaction.userId);
|
||||
expect(entity.messageId, reaction.messageId);
|
||||
expect(entity.type, reaction.type);
|
||||
expect(entity.score, reaction.score);
|
||||
expect(entity.createdAt, isSameDateAs(reaction.createdAt));
|
||||
expect(entity.extraData, reaction.extraData);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import 'package:test/test.dart';
|
||||
import 'package:stream_chat/stream_chat.dart';
|
||||
import 'package:stream_chat_persistence/src/db/moor_chat_database.dart';
|
||||
import 'package:stream_chat_persistence/src/mapper/read_mapper.dart';
|
||||
|
||||
import '../utils/date_matcher.dart';
|
||||
|
||||
void main() {
|
||||
test('toRead should map entity into Read', () {
|
||||
const cid = 'testCid';
|
||||
final user = User(id: 'testUserId');
|
||||
final entity = ReadEntity(
|
||||
lastRead: DateTime.now(),
|
||||
userId: user.id,
|
||||
channelCid: cid,
|
||||
unreadMessages: 33,
|
||||
);
|
||||
|
||||
final read = entity.toRead(user: user);
|
||||
expect(read, isA<Read>());
|
||||
expect(read.lastRead, isSameDateAs(entity.lastRead));
|
||||
expect(read.user.id, entity.userId);
|
||||
expect(read.unreadMessages, entity.unreadMessages);
|
||||
});
|
||||
|
||||
test('toEntity should map read into ReadEntity', () {
|
||||
const cid = 'testCid';
|
||||
final user = User(id: 'testUserId');
|
||||
final read = Read(
|
||||
lastRead: DateTime.now(),
|
||||
user: user,
|
||||
unreadMessages: 33,
|
||||
);
|
||||
|
||||
final entity = read.toEntity(cid: cid);
|
||||
expect(entity, isA<ReadEntity>());
|
||||
expect(entity.lastRead, isSameDateAs(read.lastRead));
|
||||
expect(entity.userId, read.user.id);
|
||||
expect(entity.unreadMessages, read.unreadMessages);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
import 'dart:math' as math;
|
||||
import 'package:test/test.dart';
|
||||
import 'package:stream_chat/stream_chat.dart';
|
||||
import 'package:stream_chat_persistence/src/db/moor_chat_database.dart';
|
||||
import 'package:stream_chat_persistence/src/mapper/user_mapper.dart';
|
||||
|
||||
import '../utils/date_matcher.dart';
|
||||
|
||||
void main() {
|
||||
test('toUser should map entity into User', () {
|
||||
final entity = UserEntity(
|
||||
id: 'testUserId',
|
||||
role: 'testType',
|
||||
createdAt: DateTime.now(),
|
||||
updatedAt: DateTime.now(),
|
||||
lastActive: DateTime.now(),
|
||||
online: math.Random().nextBool(),
|
||||
banned: math.Random().nextBool(),
|
||||
extraData: {'test_extra_data': 'extraData'},
|
||||
);
|
||||
final user = entity.toUser();
|
||||
expect(user, isA<User>());
|
||||
expect(user.id, entity.id);
|
||||
expect(user.role, entity.role);
|
||||
expect(user.createdAt, isSameDateAs(entity.createdAt));
|
||||
expect(user.updatedAt, isSameDateAs(entity.updatedAt));
|
||||
expect(user.lastActive, isSameDateAs(entity.lastActive));
|
||||
expect(user.online, entity.online);
|
||||
expect(user.banned, entity.banned);
|
||||
expect(user.extraData, entity.extraData);
|
||||
});
|
||||
|
||||
test('toEntity should map user into UserEntity', () {
|
||||
final user = User(
|
||||
id: 'testUserId',
|
||||
role: 'testType',
|
||||
createdAt: DateTime.now(),
|
||||
updatedAt: DateTime.now(),
|
||||
lastActive: DateTime.now(),
|
||||
online: math.Random().nextBool(),
|
||||
banned: math.Random().nextBool(),
|
||||
extraData: {'test_extra_data': 'extraData'},
|
||||
);
|
||||
final entity = user.toEntity();
|
||||
expect(entity, isA<UserEntity>());
|
||||
expect(entity.id, user.id);
|
||||
expect(entity.role, user.role);
|
||||
expect(entity.createdAt, isSameDateAs(user.createdAt));
|
||||
expect(entity.updatedAt, isSameDateAs(user.updatedAt));
|
||||
expect(entity.lastActive, isSameDateAs(user.lastActive));
|
||||
expect(entity.online, user.online);
|
||||
expect(entity.banned, user.banned);
|
||||
expect(entity.extraData, user.extraData);
|
||||
});
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
import 'package:stream_chat/stream_chat.dart';
|
||||
import 'package:stream_chat_persistence/src/db/moor_chat_database.dart';
|
||||
import 'package:stream_chat_persistence/src/stream_chat_persistence_client.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
void main() {
|
||||
group('connect', () {
|
||||
test('throws exception because already connected', () {
|
||||
final streamChatPersistenceClient = StreamChatPersistenceClient(
|
||||
connectionMode: ConnectionMode.background,
|
||||
logLevel: Level.INFO,
|
||||
)..db = MoorChatDatabase(
|
||||
'test',
|
||||
persistOnDisk: false,
|
||||
);
|
||||
|
||||
expect(
|
||||
() => streamChatPersistenceClient.connect('test'),
|
||||
throwsA(allOf(isException, predicate((e) {
|
||||
return e.message ==
|
||||
'An instance of StreamChatDatabase is already connected.\n'
|
||||
'disconnect the previous instance before connecting again.';
|
||||
}))),
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import 'package:test/test.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
Matcher isSameDateAs(DateTime targetDate) =>
|
||||
_IsSameDateAs(targetDate: targetDate);
|
||||
|
||||
class _IsSameDateAs extends Matcher {
|
||||
const _IsSameDateAs({
|
||||
@required this.targetDate,
|
||||
}) : assert(targetDate != null, '');
|
||||
|
||||
final DateTime targetDate;
|
||||
|
||||
@override
|
||||
bool matches(covariant DateTime date, Map matchState) =>
|
||||
date.year == targetDate.year &&
|
||||
date.month == targetDate.month &&
|
||||
date.day == targetDate.day &&
|
||||
date.hour == targetDate.hour &&
|
||||
date.minute == targetDate.minute &&
|
||||
date.second == targetDate.second;
|
||||
|
||||
@override
|
||||
Description describe(Description description) =>
|
||||
description.add('is same date as $targetDate');
|
||||
}
|
||||
@@ -0,0 +1,558 @@
|
||||
import 'package:mocktail/mocktail.dart';
|
||||
import 'package:stream_chat/stream_chat.dart';
|
||||
import 'package:stream_chat_persistence/src/db/moor_chat_database.dart';
|
||||
import 'package:stream_chat_persistence/src/stream_chat_persistence_client.dart';
|
||||
import 'package:test/test.dart';
|
||||
import 'mock_chat_database.dart';
|
||||
import 'src/utils/date_matcher.dart';
|
||||
|
||||
MoorChatDatabase _testDatabaseProvider(String userId, ConnectionMode mode) =>
|
||||
MoorChatDatabase.testable(userId);
|
||||
|
||||
void main() {
|
||||
group('client constructor', () {
|
||||
test('throws assertion error if null connectionMode is provided', () {
|
||||
expect(
|
||||
() => StreamChatPersistenceClient(connectionMode: null),
|
||||
throwsA(isA<AssertionError>()),
|
||||
);
|
||||
});
|
||||
|
||||
test('throws assertion error if null logLevel is provided', () {
|
||||
expect(
|
||||
() => StreamChatPersistenceClient(logLevel: null),
|
||||
throwsA(isA<AssertionError>()),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
group('connect', () {
|
||||
const userId = 'testUserId';
|
||||
test('successfully connects with the Database', () async {
|
||||
final client = StreamChatPersistenceClient(logLevel: Level.ALL);
|
||||
expect(client.db, isNull);
|
||||
await client.connect(userId, databaseProvider: _testDatabaseProvider);
|
||||
expect(client.db, isNotNull);
|
||||
expect(client.db, isA<MoorChatDatabase>());
|
||||
expect(client.db.userId, userId);
|
||||
|
||||
addTearDown(() async {
|
||||
await client.disconnect();
|
||||
});
|
||||
});
|
||||
|
||||
test('throws if already connected', () async {
|
||||
final client = StreamChatPersistenceClient(logLevel: Level.ALL);
|
||||
expect(client.db, isNull);
|
||||
await client.connect(userId, databaseProvider: _testDatabaseProvider);
|
||||
expect(client.db, isNotNull);
|
||||
expect(client.db, isNotNull);
|
||||
expect(client.db, isA<MoorChatDatabase>());
|
||||
expect(client.db.userId, userId);
|
||||
expect(
|
||||
() => client.connect(userId, databaseProvider: _testDatabaseProvider),
|
||||
throwsException,
|
||||
);
|
||||
|
||||
addTearDown(() async {
|
||||
await client.disconnect();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('disconnect', () async {
|
||||
const userId = 'testUserId';
|
||||
final client = StreamChatPersistenceClient(logLevel: Level.ALL);
|
||||
await client.connect(userId, databaseProvider: _testDatabaseProvider);
|
||||
expect(client.db, isNotNull);
|
||||
await client.disconnect(flush: true);
|
||||
expect(client.db, isNull);
|
||||
});
|
||||
|
||||
group('client functions', () {
|
||||
const userId = 'testUserId';
|
||||
final mockDatabase = MockChatDatabase();
|
||||
MoorChatDatabase _mockDatabaseProvider(_, __) => mockDatabase;
|
||||
StreamChatPersistenceClient client;
|
||||
|
||||
setUp(() async {
|
||||
client = StreamChatPersistenceClient(logLevel: Level.ALL);
|
||||
await client.connect(userId, databaseProvider: _mockDatabaseProvider);
|
||||
});
|
||||
|
||||
test('getReplies', () async {
|
||||
const parentId = 'testParentId';
|
||||
final replies = List.generate(3, (index) => Message(id: 'testId$index'));
|
||||
|
||||
when(() => mockDatabase.messageDao.getThreadMessagesByParentId(parentId))
|
||||
.thenAnswer((_) async => replies);
|
||||
|
||||
final fetchedReplies = await client.getReplies(parentId);
|
||||
expect(fetchedReplies.length, replies.length);
|
||||
verify(() =>
|
||||
mockDatabase.messageDao.getThreadMessagesByParentId(parentId))
|
||||
.called(1);
|
||||
});
|
||||
|
||||
test('getConnectionInfo', () async {
|
||||
final event = Event(type: 'testEvent');
|
||||
when(() => mockDatabase.connectionEventDao.connectionEvent)
|
||||
.thenAnswer((_) async => event);
|
||||
|
||||
final fetchedEvent = await client.getConnectionInfo();
|
||||
expect(fetchedEvent.type, event.type);
|
||||
verify(() => mockDatabase.connectionEventDao.connectionEvent).called(1);
|
||||
});
|
||||
|
||||
test('getLastSyncAt', () async {
|
||||
final lastSync = DateTime.now();
|
||||
when(() => mockDatabase.connectionEventDao.lastSyncAt)
|
||||
.thenAnswer((_) async => lastSync);
|
||||
|
||||
final fetchedLastSync = await client.getLastSyncAt();
|
||||
expect(fetchedLastSync, isSameDateAs(lastSync));
|
||||
verify(() => mockDatabase.connectionEventDao.lastSyncAt).called(1);
|
||||
});
|
||||
|
||||
test('updateConnectionInfo', () async {
|
||||
final event = Event(type: 'testEvent');
|
||||
when(() => mockDatabase.connectionEventDao.updateConnectionEvent(event))
|
||||
.thenAnswer((_) async {
|
||||
return;
|
||||
});
|
||||
|
||||
await client.updateConnectionInfo(event);
|
||||
verify(() => mockDatabase.connectionEventDao.updateConnectionEvent(event))
|
||||
.called(1);
|
||||
});
|
||||
|
||||
test('updateLastSyncAt', () async {
|
||||
final lastSync = DateTime.now();
|
||||
when(() => mockDatabase.connectionEventDao.updateLastSyncAt(lastSync))
|
||||
.thenAnswer((_) {
|
||||
return;
|
||||
});
|
||||
|
||||
await client.updateLastSyncAt(lastSync);
|
||||
verify(() => mockDatabase.connectionEventDao.updateLastSyncAt(lastSync))
|
||||
.called(1);
|
||||
});
|
||||
|
||||
test('getChannelCids', () async {
|
||||
final channelCids = List.generate(3, (index) => 'testCid$index');
|
||||
when(() => mockDatabase.channelDao.cids)
|
||||
.thenAnswer((_) async => channelCids);
|
||||
|
||||
final fetchedChannelCids = await client.getChannelCids();
|
||||
expect(fetchedChannelCids.length, channelCids.length);
|
||||
verify(() => mockDatabase.channelDao.cids).called(1);
|
||||
});
|
||||
|
||||
test('getChannelByCid', () async {
|
||||
const cid = 'testCid';
|
||||
final channelModel = ChannelModel(cid: cid);
|
||||
when(() => mockDatabase.channelDao.getChannelByCid(cid))
|
||||
.thenAnswer((_) async => channelModel);
|
||||
|
||||
final fetchedChannelModel = await client.getChannelByCid(cid);
|
||||
expect(fetchedChannelModel.cid, channelModel.cid);
|
||||
verify(() => mockDatabase.channelDao.getChannelByCid(cid)).called(1);
|
||||
});
|
||||
|
||||
test('getMembersByCid', () async {
|
||||
const cid = 'testCid';
|
||||
final members = List.generate(3, (index) => Member());
|
||||
when(() => mockDatabase.memberDao.getMembersByCid(cid))
|
||||
.thenAnswer((_) async => members);
|
||||
|
||||
final fetchedMembers = await client.getMembersByCid(cid);
|
||||
expect(fetchedMembers.length, members.length);
|
||||
verify(() => mockDatabase.memberDao.getMembersByCid(cid)).called(1);
|
||||
});
|
||||
|
||||
test('getReadsByCid', () async {
|
||||
const cid = 'testCid';
|
||||
final reads = List.generate(3, (index) => Read());
|
||||
when(() => mockDatabase.readDao.getReadsByCid(cid))
|
||||
.thenAnswer((_) async => reads);
|
||||
|
||||
final fetchedReads = await client.getReadsByCid(cid);
|
||||
expect(fetchedReads.length, reads.length);
|
||||
verify(() => mockDatabase.readDao.getReadsByCid(cid)).called(1);
|
||||
});
|
||||
|
||||
test('getMessagesByCid', () async {
|
||||
const cid = 'testCid';
|
||||
final messages = List.generate(3, (index) => Message());
|
||||
when(() => mockDatabase.messageDao.getMessagesByCid(cid))
|
||||
.thenAnswer((_) async => messages);
|
||||
|
||||
final fetchedMessages = await client.getMessagesByCid(cid);
|
||||
expect(fetchedMessages.length, messages.length);
|
||||
verify(() => mockDatabase.messageDao.getMessagesByCid(cid)).called(1);
|
||||
});
|
||||
|
||||
test('getPinnedMessagesByCid', () async {
|
||||
const cid = 'testCid';
|
||||
final messages = List.generate(3, (index) => Message());
|
||||
when(() => mockDatabase.pinnedMessageDao.getMessagesByCid(cid))
|
||||
.thenAnswer((_) async => messages);
|
||||
|
||||
final fetchedMessages = await client.getPinnedMessagesByCid(cid);
|
||||
expect(fetchedMessages.length, messages.length);
|
||||
verify(() => mockDatabase.pinnedMessageDao.getMessagesByCid(cid))
|
||||
.called(1);
|
||||
});
|
||||
|
||||
test('getChannelStateByCid', () async {
|
||||
const cid = 'testCid';
|
||||
final messages = List.generate(3, (index) => Message());
|
||||
final members = List.generate(3, (index) => Member());
|
||||
final reads = List.generate(3, (index) => Read());
|
||||
final channel = ChannelModel(cid: cid);
|
||||
|
||||
when(() => mockDatabase.memberDao.getMembersByCid(cid))
|
||||
.thenAnswer((_) async => members);
|
||||
when(() => mockDatabase.readDao.getReadsByCid(cid))
|
||||
.thenAnswer((_) async => reads);
|
||||
when(() => mockDatabase.channelDao.getChannelByCid(cid))
|
||||
.thenAnswer((_) async => channel);
|
||||
when(() => mockDatabase.messageDao.getMessagesByCid(cid))
|
||||
.thenAnswer((_) async => messages);
|
||||
when(() => mockDatabase.pinnedMessageDao.getMessagesByCid(cid))
|
||||
.thenAnswer((_) async => messages);
|
||||
|
||||
final fetchedChannelState = await client.getChannelStateByCid(cid);
|
||||
expect(fetchedChannelState.messages.length, messages.length);
|
||||
expect(fetchedChannelState.pinnedMessages.length, messages.length);
|
||||
expect(fetchedChannelState.members.length, members.length);
|
||||
expect(fetchedChannelState.read.length, reads.length);
|
||||
expect(fetchedChannelState.channel.cid, channel.cid);
|
||||
|
||||
verify(() => mockDatabase.memberDao.getMembersByCid(cid)).called(1);
|
||||
verify(() => mockDatabase.readDao.getReadsByCid(cid)).called(1);
|
||||
verify(() => mockDatabase.channelDao.getChannelByCid(cid)).called(1);
|
||||
verify(() => mockDatabase.messageDao.getMessagesByCid(cid)).called(1);
|
||||
verify(() => mockDatabase.pinnedMessageDao.getMessagesByCid(cid))
|
||||
.called(1);
|
||||
});
|
||||
|
||||
test('getChannelStates', () async {
|
||||
const cid = 'testCid';
|
||||
final channels = List.generate(3, (index) => ChannelModel(cid: cid));
|
||||
final messages = List.generate(3, (index) => Message());
|
||||
final members = List.generate(3, (index) => Member());
|
||||
final reads = List.generate(3, (index) => Read());
|
||||
final channel = ChannelModel(cid: cid);
|
||||
final channelStates = channels
|
||||
.map(
|
||||
(channel) => ChannelState(
|
||||
channel: channel,
|
||||
messages: messages,
|
||||
pinnedMessages: messages,
|
||||
members: members,
|
||||
read: reads,
|
||||
),
|
||||
)
|
||||
.toList(growable: false);
|
||||
|
||||
when(() => mockDatabase.channelQueryDao.getChannels())
|
||||
.thenAnswer((_) async => channels);
|
||||
when(() => mockDatabase.memberDao.getMembersByCid(cid))
|
||||
.thenAnswer((_) async => members);
|
||||
when(() => mockDatabase.readDao.getReadsByCid(cid))
|
||||
.thenAnswer((_) async => reads);
|
||||
when(() => mockDatabase.channelDao.getChannelByCid(cid))
|
||||
.thenAnswer((_) async => channel);
|
||||
when(() => mockDatabase.messageDao.getMessagesByCid(cid))
|
||||
.thenAnswer((_) async => messages);
|
||||
when(() => mockDatabase.pinnedMessageDao.getMessagesByCid(cid))
|
||||
.thenAnswer((_) async => messages);
|
||||
|
||||
final fetchedChannelStates = await client.getChannelStates();
|
||||
expect(fetchedChannelStates.length, channelStates.length);
|
||||
|
||||
for (var i = 0; i < fetchedChannelStates.length; i++) {
|
||||
final original = channelStates[i];
|
||||
final fetched = fetchedChannelStates[i];
|
||||
expect(fetched.members.length, original.members.length);
|
||||
expect(fetched.messages.length, original.messages.length);
|
||||
expect(fetched.pinnedMessages.length, original.pinnedMessages.length);
|
||||
expect(fetched.read.length, original.read.length);
|
||||
expect(fetched.channel.cid, original.channel.cid);
|
||||
}
|
||||
|
||||
verify(() => mockDatabase.channelQueryDao.getChannels()).called(1);
|
||||
verify(() => mockDatabase.memberDao.getMembersByCid(cid)).called(3);
|
||||
verify(() => mockDatabase.readDao.getReadsByCid(cid)).called(3);
|
||||
verify(() => mockDatabase.channelDao.getChannelByCid(cid)).called(3);
|
||||
verify(() => mockDatabase.messageDao.getMessagesByCid(cid)).called(3);
|
||||
verify(() => mockDatabase.pinnedMessageDao.getMessagesByCid(cid))
|
||||
.called(3);
|
||||
});
|
||||
|
||||
test('updateChannelQueries', () async {
|
||||
const filter = <String, dynamic>{};
|
||||
const cids = <String>[];
|
||||
when(() =>
|
||||
mockDatabase.channelQueryDao.updateChannelQueries(filter, cids))
|
||||
.thenAnswer((realInvocation) async {
|
||||
return;
|
||||
});
|
||||
|
||||
await client.updateChannelQueries(filter, cids);
|
||||
verify(() =>
|
||||
mockDatabase.channelQueryDao.updateChannelQueries(filter, cids))
|
||||
.called(1);
|
||||
});
|
||||
|
||||
test('deleteMessageById', () async {
|
||||
const messageId = 'testMessageId';
|
||||
when(() => mockDatabase.messageDao.deleteMessageByIds([messageId]))
|
||||
.thenAnswer((_) async {
|
||||
return;
|
||||
});
|
||||
|
||||
await client.deleteMessageById(messageId);
|
||||
verify(() => mockDatabase.messageDao.deleteMessageByIds([messageId]))
|
||||
.called(1);
|
||||
});
|
||||
|
||||
test('deletePinnedMessageById', () async {
|
||||
const messageId = 'testMessageId';
|
||||
when(() => mockDatabase.pinnedMessageDao.deleteMessageByIds([messageId]))
|
||||
.thenAnswer((_) async {
|
||||
return;
|
||||
});
|
||||
|
||||
await client.deletePinnedMessageById(messageId);
|
||||
verify(() =>
|
||||
mockDatabase.pinnedMessageDao.deleteMessageByIds([messageId]))
|
||||
.called(1);
|
||||
});
|
||||
|
||||
test('deleteMessageByIds', () async {
|
||||
const messageIds = <String>[];
|
||||
when(() => mockDatabase.messageDao.deleteMessageByIds(messageIds))
|
||||
.thenAnswer((_) async {
|
||||
return;
|
||||
});
|
||||
|
||||
await client.deleteMessageByIds(messageIds);
|
||||
verify(() => mockDatabase.messageDao.deleteMessageByIds(messageIds))
|
||||
.called(1);
|
||||
});
|
||||
|
||||
test('deletePinnedMessageByIds', () async {
|
||||
const messageIds = <String>[];
|
||||
when(() => mockDatabase.pinnedMessageDao.deleteMessageByIds(messageIds))
|
||||
.thenAnswer((_) async {
|
||||
return;
|
||||
});
|
||||
|
||||
await client.deletePinnedMessageByIds(messageIds);
|
||||
verify(() => mockDatabase.pinnedMessageDao.deleteMessageByIds(messageIds))
|
||||
.called(1);
|
||||
});
|
||||
|
||||
test('deleteMessageByCid', () async {
|
||||
const cid = 'testCid';
|
||||
when(() => mockDatabase.messageDao.deleteMessageByCids([cid]))
|
||||
.thenAnswer((_) async {
|
||||
return;
|
||||
});
|
||||
|
||||
await client.deleteMessageByCid(cid);
|
||||
verify(() => mockDatabase.messageDao.deleteMessageByCids([cid]))
|
||||
.called(1);
|
||||
});
|
||||
|
||||
test('deletePinnedMessageByCid', () async {
|
||||
const cid = 'testCid';
|
||||
when(() => mockDatabase.pinnedMessageDao.deleteMessageByCids([cid]))
|
||||
.thenAnswer((_) async {
|
||||
return;
|
||||
});
|
||||
|
||||
await client.deletePinnedMessageByCid(cid);
|
||||
verify(() => mockDatabase.pinnedMessageDao.deleteMessageByCids([cid]))
|
||||
.called(1);
|
||||
});
|
||||
|
||||
test('deleteMessageByCids', () async {
|
||||
const cids = <String>[];
|
||||
when(() => mockDatabase.messageDao.deleteMessageByCids(cids))
|
||||
.thenAnswer((_) async {
|
||||
return;
|
||||
});
|
||||
|
||||
await client.deleteMessageByCids(cids);
|
||||
verify(() => mockDatabase.messageDao.deleteMessageByCids(cids)).called(1);
|
||||
});
|
||||
|
||||
test('deletePinnedMessageByCids', () async {
|
||||
const cids = <String>[];
|
||||
when(() => mockDatabase.pinnedMessageDao.deleteMessageByCids(cids))
|
||||
.thenAnswer((_) async {
|
||||
return;
|
||||
});
|
||||
|
||||
await client.deletePinnedMessageByCids(cids);
|
||||
verify(() => mockDatabase.pinnedMessageDao.deleteMessageByCids(cids))
|
||||
.called(1);
|
||||
});
|
||||
|
||||
test('deleteChannels', () async {
|
||||
const cids = <String>[];
|
||||
when(() => mockDatabase.channelDao.deleteChannelByCids(cids))
|
||||
.thenAnswer((_) async {
|
||||
return;
|
||||
});
|
||||
|
||||
await client.deleteChannels(cids);
|
||||
verify(() => mockDatabase.channelDao.deleteChannelByCids(cids)).called(1);
|
||||
});
|
||||
|
||||
test('updateMessages', () async {
|
||||
const cid = 'testCid';
|
||||
final messages = List.generate(3, (index) => Message());
|
||||
when(() => mockDatabase.messageDao.updateMessages(cid, messages))
|
||||
.thenAnswer((_) async {
|
||||
return;
|
||||
});
|
||||
|
||||
await client.updateMessages(cid, messages);
|
||||
verify(() => mockDatabase.messageDao.updateMessages(cid, messages))
|
||||
.called(1);
|
||||
});
|
||||
|
||||
test('updatePinnedMessages', () async {
|
||||
const cid = 'testCid';
|
||||
final messages = List.generate(3, (index) => Message());
|
||||
when(() => mockDatabase.pinnedMessageDao.updateMessages(cid, messages))
|
||||
.thenAnswer((_) async {
|
||||
return;
|
||||
});
|
||||
|
||||
await client.updatePinnedMessages(cid, messages);
|
||||
verify(() => mockDatabase.pinnedMessageDao.updateMessages(cid, messages))
|
||||
.called(1);
|
||||
});
|
||||
|
||||
test('getChannelThreads', () async {
|
||||
const cid = 'testCid';
|
||||
final messages =
|
||||
List.generate(3, (index) => Message(parentId: 'testParentId$index'));
|
||||
final threads = messages.fold<Map<String, List<Message>>>(
|
||||
{},
|
||||
(prev, curr) {
|
||||
return prev
|
||||
..update(
|
||||
curr.parentId,
|
||||
(value) => [...value, curr],
|
||||
ifAbsent: () => [],
|
||||
);
|
||||
},
|
||||
);
|
||||
when(() => mockDatabase.messageDao.getThreadMessages(cid))
|
||||
.thenAnswer((realInvocation) async => messages);
|
||||
|
||||
final fetchedThreads = await client.getChannelThreads(cid);
|
||||
expect(fetchedThreads.length, threads.length);
|
||||
for (var i = 0; i < fetchedThreads.length; i++) {
|
||||
final original = threads.entries.elementAt(i);
|
||||
final fetched = fetchedThreads.entries.elementAt(i);
|
||||
expect(fetched.key, original.key);
|
||||
}
|
||||
|
||||
verify(() => mockDatabase.messageDao.getThreadMessages(cid)).called(1);
|
||||
});
|
||||
|
||||
test('updateChannels', () async {
|
||||
final channels = List.generate(3, (index) => ChannelModel());
|
||||
when(() => mockDatabase.channelDao.updateChannels(channels))
|
||||
.thenAnswer((_) async {
|
||||
return;
|
||||
});
|
||||
|
||||
await client.updateChannels(channels);
|
||||
verify(() => mockDatabase.channelDao.updateChannels(channels)).called(1);
|
||||
});
|
||||
|
||||
test('updateMembers', () async {
|
||||
const cid = 'testCid';
|
||||
final members = List.generate(3, (index) => Member());
|
||||
when(() => mockDatabase.memberDao.updateMembers(cid, members))
|
||||
.thenAnswer((_) async {
|
||||
return;
|
||||
});
|
||||
|
||||
await client.updateMembers(cid, members);
|
||||
verify(() => mockDatabase.memberDao.updateMembers(cid, members))
|
||||
.called(1);
|
||||
});
|
||||
|
||||
test('updateReads', () async {
|
||||
const cid = 'testCid';
|
||||
final reads = List.generate(3, (index) => Read());
|
||||
when(() => mockDatabase.readDao.updateReads(cid, reads))
|
||||
.thenAnswer((_) async {
|
||||
return;
|
||||
});
|
||||
|
||||
await client.updateReads(cid, reads);
|
||||
verify(() => mockDatabase.readDao.updateReads(cid, reads)).called(1);
|
||||
});
|
||||
|
||||
test('updateUsers', () async {
|
||||
final users = List.generate(3, (index) => User());
|
||||
when(() => mockDatabase.userDao.updateUsers(users)).thenAnswer((_) async {
|
||||
return;
|
||||
});
|
||||
|
||||
await client.updateUsers(users);
|
||||
verify(() => mockDatabase.userDao.updateUsers(users)).called(1);
|
||||
});
|
||||
|
||||
test('updateReactions', () async {
|
||||
final reactions = List.generate(3, (index) => Reaction());
|
||||
when(() => mockDatabase.reactionDao.updateReactions(reactions))
|
||||
.thenAnswer((_) async {
|
||||
return;
|
||||
});
|
||||
|
||||
await client.updateReactions(reactions);
|
||||
verify(() => mockDatabase.reactionDao.updateReactions(reactions))
|
||||
.called(1);
|
||||
});
|
||||
|
||||
test('deleteReactionsByMessageId', () async {
|
||||
final messageIds = <String>[];
|
||||
when(() =>
|
||||
mockDatabase.reactionDao.deleteReactionsByMessageIds(messageIds))
|
||||
.thenAnswer((_) async {
|
||||
return;
|
||||
});
|
||||
|
||||
await client.deleteReactionsByMessageId(messageIds);
|
||||
verify(() =>
|
||||
mockDatabase.reactionDao.deleteReactionsByMessageIds(messageIds))
|
||||
.called(1);
|
||||
});
|
||||
|
||||
test('deleteMembersByCids', () async {
|
||||
final cids = <String>[];
|
||||
when(() => mockDatabase.memberDao.deleteMemberByCids(cids))
|
||||
.thenAnswer((_) async {
|
||||
return;
|
||||
});
|
||||
|
||||
await client.deleteMembersByCids(cids);
|
||||
verify(() => mockDatabase.memberDao.deleteMemberByCids(cids)).called(1);
|
||||
});
|
||||
|
||||
tearDown(() async {
|
||||
await client.disconnect(flush: true);
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user