diff --git a/packages/stream_chat_persistence/lib/src/db/moor_chat_database.dart b/packages/stream_chat_persistence/lib/src/db/moor_chat_database.dart index cc3e86b3..2edaed4f 100644 --- a/packages/stream_chat_persistence/lib/src/db/moor_chat_database.dart +++ b/packages/stream_chat_persistence/lib/src/db/moor_chat_database.dart @@ -1,23 +1,22 @@ -import 'package:moor/isolate.dart'; +import 'package:meta/meta.dart'; +import 'package:moor/ffi.dart'; import 'package:moor/moor.dart'; import 'package:stream_chat/stream_chat.dart'; -import '../converter/converter.dart'; -import '../dao/dao.dart'; -import '../entity/entity.dart'; -import 'shared/shared_db.dart'; +import 'package:stream_chat_persistence/src/converter/converter.dart'; +import 'package:stream_chat_persistence/src/dao/dao.dart'; +import 'package:stream_chat_persistence/src/entity/entity.dart'; +import 'package:stream_chat_persistence/src/db/shared/shared_db.dart'; part 'moor_chat_database.g.dart'; LazyDatabase _openConnection( String userId, { bool logStatements = false, - bool persistOnDisk = true, }) => LazyDatabase(() async => SharedDB.constructDatabase( userId, logStatements: logStatements, - persistOnDisk: persistOnDisk, )); /// A chat database implemented using moor @@ -47,11 +46,9 @@ class MoorChatDatabase extends _$MoorChatDatabase { MoorChatDatabase( this._userId, { logStatements = false, - bool persistOnDisk = true, }) : super(_openConnection( _userId, logStatements: logStatements, - persistOnDisk: persistOnDisk, )); /// Instantiate a new database instance @@ -60,6 +57,10 @@ class MoorChatDatabase extends _$MoorChatDatabase { DatabaseConnection connection, ) : super.connect(connection); + /// Custom constructor used only for testing + @visibleForTesting + MoorChatDatabase.testable(this._userId) : super(VmDatabase.memory()); + final String _userId; /// User id to which the database is connected diff --git a/packages/stream_chat_persistence/lib/src/db/shared/native_db.dart b/packages/stream_chat_persistence/lib/src/db/shared/native_db.dart index 7592247e..a3b1ce8e 100644 --- a/packages/stream_chat_persistence/lib/src/db/shared/native_db.dart +++ b/packages/stream_chat_persistence/lib/src/db/shared/native_db.dart @@ -21,20 +21,17 @@ class SharedDB { static Future constructDatabase( String userId, { bool logStatements = false, - bool persistOnDisk = true, }) async { final dbName = 'db_$userId'; - if (persistOnDisk) { - if (Platform.isIOS || Platform.isAndroid) { - final dir = await getApplicationDocumentsDirectory(); - final path = join(dir.path, '$dbName.sqlite'); - final file = File(path); - return VmDatabase(file, logStatements: logStatements); - } - if (Platform.isMacOS || Platform.isLinux) { - final file = File('$dbName.sqlite'); - return VmDatabase(file, logStatements: logStatements); - } + if (Platform.isIOS || Platform.isAndroid) { + final dir = await getApplicationDocumentsDirectory(); + final path = join(dir.path, '$dbName.sqlite'); + final file = File(path); + return VmDatabase(file, logStatements: logStatements); + } + if (Platform.isMacOS || Platform.isLinux) { + final file = File('$dbName.sqlite'); + return VmDatabase(file, logStatements: logStatements); } return VmDatabase.memory(logStatements: logStatements); } diff --git a/packages/stream_chat_persistence/lib/src/db/shared/unsupported_db.dart b/packages/stream_chat_persistence/lib/src/db/shared/unsupported_db.dart index 3a764d24..15734a7c 100644 --- a/packages/stream_chat_persistence/lib/src/db/shared/unsupported_db.dart +++ b/packages/stream_chat_persistence/lib/src/db/shared/unsupported_db.dart @@ -10,7 +10,6 @@ class SharedDB { static Future constructDatabase( String userId, { bool logStatements = false, - bool persistOnDisk = true, }) { throw UnsupportedError( 'No implementation of the constructDatabase api provided'); diff --git a/packages/stream_chat_persistence/lib/src/db/shared/web_db.dart b/packages/stream_chat_persistence/lib/src/db/shared/web_db.dart index 32b108ba..7388543e 100644 --- a/packages/stream_chat_persistence/lib/src/db/shared/web_db.dart +++ b/packages/stream_chat_persistence/lib/src/db/shared/web_db.dart @@ -12,7 +12,6 @@ class SharedDB { static Future constructDatabase( String userId, { bool logStatements = false, - bool persistOnDisk = true, // ignored on web }) async { final dbName = 'db_$userId'; return WebDatabase(dbName, logStatements: logStatements); diff --git a/packages/stream_chat_persistence/lib/src/mapper/channel_mapper.dart b/packages/stream_chat_persistence/lib/src/mapper/channel_mapper.dart index 5c8e3e2a..65315519 100644 --- a/packages/stream_chat_persistence/lib/src/mapper/channel_mapper.dart +++ b/packages/stream_chat_persistence/lib/src/mapper/channel_mapper.dart @@ -46,14 +46,14 @@ extension ChannelModelX on ChannelModel { id: id, type: type, cid: cid, - config: config.toJson(), + config: config?.toJson(), frozen: frozen, lastMessageAt: lastMessageAt, createdAt: createdAt, updatedAt: updatedAt, deletedAt: deletedAt, memberCount: memberCount, - createdById: createdBy.id, + createdById: createdBy?.id, extraData: extraData, ); } diff --git a/packages/stream_chat_persistence/test/src/dao/channel_dao_test.dart b/packages/stream_chat_persistence/test/src/dao/channel_dao_test.dart new file mode 100644 index 00000000..9d6a3070 --- /dev/null +++ b/packages/stream_chat_persistence/test/src/dao/channel_dao_test.dart @@ -0,0 +1,139 @@ +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]); + }); + +// /// Updates all the channels using the new [channelList] data +// Future updateChannels(List channelList) => batch( +// (it) => it.insertAll( +// channels, +// channelList.map((c) => c.toEntity()).toList(), +// mode: InsertMode.insertOrReplace, +// ), +// ); + + 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(); + }); +}