diff --git a/packages/stream_chat/lib/src/models/user.dart b/packages/stream_chat/lib/src/models/user.dart index 618c1986..3b9f9add 100644 --- a/packages/stream_chat/lib/src/models/user.dart +++ b/packages/stream_chat/lib/src/models/user.dart @@ -100,4 +100,28 @@ class User { /// Serialize to json Map toJson() => Serialization.moveFromExtraDataToRoot(_$UserToJson(this), topLevelFields); + + /// Creates a copy of [User] with specified attributes overridden. + User copyWith({ + String id, + String role, + DateTime createdAt, + DateTime updatedAt, + DateTime lastActive, + bool online, + Map extraData, + bool banned, + List teams, + }) => + User( + id: id ?? this.id, + role: role ?? this.role, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + lastActive: lastActive ?? this.lastActive, + online: online ?? this.online, + extraData: extraData ?? this.extraData, + banned: banned ?? this.banned, + teams: teams ?? this.teams, + ); } diff --git a/packages/stream_chat_persistence/lib/src/dao/user_dao.dart b/packages/stream_chat_persistence/lib/src/dao/user_dao.dart index 65ce1521..9cdff8e7 100644 --- a/packages/stream_chat_persistence/lib/src/dao/user_dao.dart +++ b/packages/stream_chat_persistence/lib/src/dao/user_dao.dart @@ -20,4 +20,10 @@ class UserDao extends DatabaseAccessor with _$UserDaoMixin { mode: InsertMode.insertOrReplace, ), ); + + /// Returns the list of all the users stored in db + Future> getUsers() => + (select(users)..orderBy([(u) => OrderingTerm.desc(u.createdAt)])) + .map((it) => it.toUser()) + .get(); } diff --git a/packages/stream_chat_persistence/test/src/dao/user_dao_test.dart b/packages/stream_chat_persistence/test/src/dao/user_dao_test.dart new file mode 100644 index 00000000..8c5898a0 --- /dev/null +++ b/packages/stream_chat_persistence/test/src/dao/user_dao_test.dart @@ -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> _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(); + }); +}