diff --git a/lib/data/dao/group_dao.dart b/lib/data/dao/group_dao.dart index 552b138..d1029d0 100644 --- a/lib/data/dao/group_dao.dart +++ b/lib/data/dao/group_dao.dart @@ -238,48 +238,4 @@ class GroupDao extends DatabaseAccessor with _$GroupDaoMixin { ); return rowsAffected > 0; } - - /// Replaces all players in a group with the provided list of players. - /// Removes all existing players from the group and adds the new players. - /// Also adds any new players to the player table if they don't exist. - /// Returns `true` if the group exists and players were replaced, `false` otherwise. - Future replaceGroupPlayers({ - required String groupId, - required List newPlayers, - }) async { - if (!await groupExists(groupId: groupId)) return false; - - await db.transaction(() async { - // Remove all existing players from the group - final deleteQuery = delete(db.playerGroupTable) - ..where((p) => p.groupId.equals(groupId)); - await deleteQuery.go(); - - // Add new players to the player table if they don't exist - await Future.wait( - newPlayers.map((player) async { - if (!await db.playerDao.playerExists(playerId: player.id)) { - await db.playerDao.addPlayer(player: player); - } - }), - ); - - // Add the new players to the group - await db.batch( - (b) => b.insertAll( - db.playerGroupTable, - newPlayers - .map( - (player) => PlayerGroupTableCompanion.insert( - playerId: player.id, - groupId: groupId, - ), - ) - .toList(), - mode: InsertMode.insertOrReplace, - ), - ); - }); - return true; - } } diff --git a/lib/data/dao/player_group_dao.dart b/lib/data/dao/player_group_dao.dart index 9411486..48c5653 100644 --- a/lib/data/dao/player_group_dao.dart +++ b/lib/data/dao/player_group_dao.dart @@ -11,8 +11,7 @@ class PlayerGroupDao extends DatabaseAccessor with _$PlayerGroupDaoMixin { PlayerGroupDao(super.db); - /// No need for a groupHasPlayers method since the members attribute is - /// not nullable + /* Create */ /// Adds a [player] to a group with the given [groupId]. /// If the player is already in the group, no action is taken. @@ -33,10 +32,11 @@ class PlayerGroupDao extends DatabaseAccessor await into(playerGroupTable).insert( PlayerGroupTableCompanion.insert(playerId: player.id, groupId: groupId), ); - return true; } + /* Read */ + /// Retrieves all players belonging to a specific group by [groupId]. Future> getPlayersOfGroup({required String groupId}) async { final query = select(playerGroupTable) @@ -53,18 +53,6 @@ class PlayerGroupDao extends DatabaseAccessor return groupMembers; } - /// Removes a player from a group based on [playerId] and [groupId]. - /// Returns `true` if more than 0 rows were affected, otherwise `false`. - Future removePlayerFromGroup({ - required String playerId, - required String groupId, - }) async { - final query = delete(playerGroupTable) - ..where((p) => p.playerId.equals(playerId) & p.groupId.equals(groupId)); - final rowsAffected = await query.go(); - return rowsAffected > 0; - } - /// Checks if a player with [playerId] is in the group with [groupId]. /// Returns `true` if the player is in the group, otherwise `false`. Future isPlayerInGroup({ @@ -76,4 +64,65 @@ class PlayerGroupDao extends DatabaseAccessor final result = await query.getSingleOrNull(); return result != null; } + + /* Update */ + + /// Replaces all players in a group with the provided list of players. + /// Removes all existing players from the group and adds the new players. + /// Also adds any new players to the player table if they don't exist. + /// Returns `true` if the group exists and players were replaced, `false` otherwise. + Future replaceGroupPlayers({ + required String groupId, + required List newPlayers, + }) async { + if (!await db.groupDao.groupExists(groupId: groupId)) return false; + if (newPlayers.isEmpty) return false; + + await db.transaction(() async { + // Remove all existing players from the group + final deleteQuery = delete(db.playerGroupTable) + ..where((p) => p.groupId.equals(groupId)); + await deleteQuery.go(); + + // Add new players to the player table if they don't exist + await Future.wait( + newPlayers.map((player) async { + if (!await db.playerDao.playerExists(playerId: player.id)) { + await db.playerDao.addPlayer(player: player); + } + }), + ); + + // Add the new players to the group + await db.batch( + (b) => b.insertAll( + db.playerGroupTable, + newPlayers + .map( + (player) => PlayerGroupTableCompanion.insert( + playerId: player.id, + groupId: groupId, + ), + ) + .toList(), + mode: InsertMode.insertOrReplace, + ), + ); + }); + return true; + } + + /* Delete */ + + /// Removes a player from a group based on [playerId] and [groupId]. + /// Returns `true` if more than 0 rows were affected, otherwise `false`. + Future removePlayerFromGroup({ + required String playerId, + required String groupId, + }) async { + final query = delete(playerGroupTable) + ..where((p) => p.playerId.equals(playerId) & p.groupId.equals(groupId)); + final rowsAffected = await query.go(); + return rowsAffected > 0; + } } diff --git a/lib/presentation/views/main_menu/group_view/create_group_view.dart b/lib/presentation/views/main_menu/group_view/create_group_view.dart index f88e2db..593499e 100644 --- a/lib/presentation/views/main_menu/group_view/create_group_view.dart +++ b/lib/presentation/views/main_menu/group_view/create_group_view.dart @@ -177,7 +177,7 @@ class _CreateGroupViewState extends State { } if (widget.groupToEdit!.members != selectedPlayers) { - successfullMemberChange = await db.groupDao.replaceGroupPlayers( + successfullMemberChange = await db.playerGroupDao.replaceGroupPlayers( groupId: widget.groupToEdit!.id, newPlayers: selectedPlayers, ); diff --git a/test/db_tests/aggregates/group_test.dart b/test/db_tests/aggregates/group_test.dart index 9040daf..786a260 100644 --- a/test/db_tests/aggregates/group_test.dart +++ b/test/db_tests/aggregates/group_test.dart @@ -306,7 +306,7 @@ void main() { ); final newPlayers = [testPlayer2, testPlayer4]; - final replaced = await database.groupDao.replaceGroupPlayers( + final replaced = await database.playerGroupDao.replaceGroupPlayers( groupId: testGroup1.id, newPlayers: newPlayers, ); @@ -332,7 +332,7 @@ void main() { ); expect(initialGroup.members.length, 3); - final replaced = await database.groupDao.replaceGroupPlayers( + final replaced = await database.playerGroupDao.replaceGroupPlayers( groupId: testGroup1.id, newPlayers: [], ); @@ -348,7 +348,7 @@ void main() { test( 'replaceGroupPlayers() returns false for non-existent group', () async { - final replaced = await database.groupDao.replaceGroupPlayers( + final replaced = await database.playerGroupDao.replaceGroupPlayers( groupId: 'non-existent-id', newPlayers: [testPlayer1], ); diff --git a/test/db_tests/relationships/player_group_test.dart b/test/db_tests/relationships/player_group_test.dart index f687b1c..42d083b 100644 --- a/test/db_tests/relationships/player_group_test.dart +++ b/test/db_tests/relationships/player_group_test.dart @@ -42,189 +42,162 @@ void main() { }); group('Player-Group Tests', () { - // Verifies that a player can be added to an existing group and isPlayerInGroup returns true. - test('Adding a player to a group works correctly', () async { - await database.groupDao.addGroup(group: testGroup); - await database.playerDao.addPlayer(player: testPlayer4); - await database.playerGroupDao.addPlayerToGroup( - groupId: testGroup.id, - player: testPlayer4, - ); - - var playerAdded = await database.playerGroupDao.isPlayerInGroup( - groupId: testGroup.id, - playerId: testPlayer4.id, - ); - - expect(playerAdded, true); - - playerAdded = await database.playerGroupDao.isPlayerInGroup( - groupId: testGroup.id, - playerId: '', - ); - - expect(playerAdded, false); - }); - - // Verifies that a player can be removed from a group and the group's member count decreases. - test('Removing player from group works correctly', () async { - await database.groupDao.addGroup(group: testGroup); - - final playerToRemove = testGroup.members[0]; - - final removed = await database.playerGroupDao.removePlayerFromGroup( - playerId: playerToRemove.id, - groupId: testGroup.id, - ); - expect(removed, true); - - final result = await database.groupDao.getGroupById( - groupId: testGroup.id, - ); - expect(result.members.length, testGroup.members.length - 1); - - final playerExists = result.members.any((p) => p.id == playerToRemove.id); - expect(playerExists, false); - }); - - // Verifies that getPlayersOfGroup returns all members of a group with correct data. - test('Retrieving players of a group works correctly', () async { - await database.groupDao.addGroup(group: testGroup); - final players = await database.playerGroupDao.getPlayersOfGroup( - groupId: testGroup.id, - ); - - for (int i = 0; i < players.length; i++) { - expect(players[i].id, testGroup.members[i].id); - expect(players[i].name, testGroup.members[i].name); - expect(players[i].createdAt, testGroup.members[i].createdAt); - } - }); - - // Verifies that isPlayerInGroup returns false for non-existent player. - test('isPlayerInGroup returns false for non-existent player', () async { - await database.groupDao.addGroup(group: testGroup); - - final result = await database.playerGroupDao.isPlayerInGroup( - playerId: 'non-existent-player-id', - groupId: testGroup.id, - ); - - expect(result, false); - }); - - // Verifies that isPlayerInGroup returns false for non-existent group. - test('isPlayerInGroup returns false for non-existent group', () async { - await database.playerDao.addPlayer(player: testPlayer1); - - final result = await database.playerGroupDao.isPlayerInGroup( - playerId: testPlayer1.id, - groupId: 'non-existent-group-id', - ); - - expect(result, false); - }); - - // Verifies that addPlayerToGroup returns false when player already in group. - test( - 'addPlayerToGroup returns false when player already in group', - () async { + group('CREATE', () { + test('addPlayerToGroup() works correctly', () async { await database.groupDao.addGroup(group: testGroup); - - // testPlayer1 is already in testGroup via group creation - final result = await database.playerGroupDao.addPlayerToGroup( - player: testPlayer1, - groupId: testGroup.id, - ); - - expect(result, false); - }, - ); - - // Verifies that addPlayerToGroup adds player to player table if not exists. - test( - 'addPlayerToGroup adds player to player table if not exists', - () async { - await database.groupDao.addGroup(group: testGroup); - - // testPlayer4 is not in the database yet - var playerExists = await database.playerDao.playerExists( - playerId: testPlayer4.id, - ); - expect(playerExists, false); - + await database.playerDao.addPlayer(player: testPlayer4); await database.playerGroupDao.addPlayerToGroup( - player: testPlayer4, groupId: testGroup.id, + player: testPlayer4, ); - // Now player should exist in player table - playerExists = await database.playerDao.playerExists( + var playerAdded = await database.playerGroupDao.isPlayerInGroup( + groupId: testGroup.id, playerId: testPlayer4.id, ); - expect(playerExists, true); - }, - ); - // Verifies that removePlayerFromGroup returns false for non-existent player. - test( - 'removePlayerFromGroup returns false for non-existent player', - () async { + expect(playerAdded, true); + }); + + test( + 'addPlayerToGroup() returns false when player already in group', + () async { + await database.groupDao.addGroup(group: testGroup); + + final added = await database.playerGroupDao.addPlayerToGroup( + player: testPlayer1, + groupId: testGroup.id, + ); + expect(added, isFalse); + }, + ); + + test( + 'addPlayerToGroup() adds player to player table if not exists', + () async { + await database.groupDao.addGroup(group: testGroup); + + var playerExists = await database.playerDao.playerExists( + playerId: testPlayer4.id, + ); + expect(playerExists, isFalse); + + await database.playerGroupDao.addPlayerToGroup( + player: testPlayer4, + groupId: testGroup.id, + ); + + playerExists = await database.playerDao.playerExists( + playerId: testPlayer4.id, + ); + expect(playerExists, isTrue); + }, + ); + }); + group('READ', () { + test( + 'isPlayerInGroup() returns false for non-existent player or group', + () async { + await database.groupDao.addGroup(group: testGroup); + + var isInGroup = await database.playerGroupDao.isPlayerInGroup( + playerId: 'non-existent-player-id', + groupId: testGroup.id, + ); + expect(isInGroup, false); + + isInGroup = await database.playerGroupDao.isPlayerInGroup( + playerId: testPlayer1.id, + groupId: 'non-existent-group-id', + ); + expect(isInGroup, false); + + isInGroup = await database.playerGroupDao.isPlayerInGroup( + playerId: 'non-existent-player-id', + groupId: 'non-existent-group-id', + ); + expect(isInGroup, false); + }, + ); + + test('getPlayersOfGroup() works correctly', () async { await database.groupDao.addGroup(group: testGroup); - - final result = await database.playerGroupDao.removePlayerFromGroup( - playerId: 'non-existent-player-id', + final players = await database.playerGroupDao.getPlayersOfGroup( groupId: testGroup.id, ); - expect(result, false); - }, - ); + for (int i = 0; i < players.length; i++) { + expect(players[i].id, testGroup.members[i].id); + expect(players[i].name, testGroup.members[i].name); + expect(players[i].createdAt, testGroup.members[i].createdAt); + } + }); - // Verifies that removePlayerFromGroup returns false for non-existent group. - test( - 'removePlayerFromGroup returns false for non-existent group', - () async { - await database.playerDao.addPlayer(player: testPlayer1); + test('getPlayersOfGroup() returns empty list for empty group', () async { + final emptyGroup = Group(name: 'Empty Group', members: []); + await database.groupDao.addGroup(group: emptyGroup); - final result = await database.playerGroupDao.removePlayerFromGroup( - playerId: testPlayer1.id, - groupId: 'non-existent-group-id', + final players = await database.playerGroupDao.getPlayersOfGroup( + groupId: emptyGroup.id, ); + expect(players, isEmpty); + }); - expect(result, false); - }, - ); - - // Verifies that getPlayersOfGroup returns empty list for group with no members. - test('getPlayersOfGroup returns empty list for empty group', () async { - final emptyGroup = Group( - name: 'Empty Group', - description: '', - members: [], + test( + 'getPlayersOfGroup() returns empty list for non-existent group', + () async { + final players = await database.playerGroupDao.getPlayersOfGroup( + groupId: 'non-existent-group-id', + ); + expect(players, isEmpty); + }, ); - await database.groupDao.addGroup(group: emptyGroup); + }); + group('UPDATE', () { + test('replaceGroupPlayers() works correctly ', () async { + await database.groupDao.addGroup(group: testGroup); - final players = await database.playerGroupDao.getPlayersOfGroup( - groupId: emptyGroup.id, - ); + var groupMembers = await database.groupDao.getGroupById( + groupId: testGroup.id, + ); + expect(groupMembers.members.length, testGroup.members.length); - expect(players, isEmpty); + final newPlayersList = [testPlayer3, testPlayer4]; + + final replaced = await database.playerGroupDao.replaceGroupPlayers( + groupId: testGroup.id, + newPlayers: newPlayersList, + ); + expect(replaced, isTrue); + + groupMembers = await database.groupDao.getGroupById( + groupId: testGroup.id, + ); + expect(groupMembers.members.length, 2); + expect(groupMembers.members.any((p) => p.id == testPlayer3.id), true); + expect(groupMembers.members.any((p) => p.id == testPlayer4.id), true); + }); + }); + group('DELETE', () { + test('removePlayerFromGroup() works correctly', () async { + await database.groupDao.addGroup(group: testGroup); + + final removed = await database.playerGroupDao.removePlayerFromGroup( + playerId: testPlayer1.id, + groupId: testGroup.id, + ); + expect(removed, true); + + final result = await database.groupDao.getGroupById( + groupId: testGroup.id, + ); + expect(result.members.length, testGroup.members.length - 1); + + final playerExists = result.members.any((p) => p.id == testPlayer1.id); + expect(playerExists, false); + }); }); - // Verifies that getPlayersOfGroup returns empty list for non-existent group. - test( - 'getPlayersOfGroup returns empty list for non-existent group', - () async { - final players = await database.playerGroupDao.getPlayersOfGroup( - groupId: 'non-existent-group-id', - ); - - expect(players, isEmpty); - }, - ); - - // Verifies that removing all players from a group leaves the group empty. test('Removing all players from a group leaves group empty', () async { await database.groupDao.addGroup(group: testGroup); @@ -240,137 +213,53 @@ void main() { ); expect(players, isEmpty); - // Group should still exist final groupExists = await database.groupDao.groupExists( groupId: testGroup.id, ); expect(groupExists, true); }); - // Verifies that a player can be in multiple groups. - test('Player can be in multiple groups', () async { - final secondGroup = Group( - name: 'Second Group', - description: '', - members: [], - ); + test('removePlayerFromGroup() works correctly', () async { await database.groupDao.addGroup(group: testGroup); - await database.groupDao.addGroup(group: secondGroup); - // Add testPlayer1 to second group (already in testGroup) - await database.playerGroupDao.addPlayerToGroup( - player: testPlayer1, - groupId: secondGroup.id, - ); - - final inFirstGroup = await database.playerGroupDao.isPlayerInGroup( + var removed = await database.playerGroupDao.removePlayerFromGroup( playerId: testPlayer1.id, groupId: testGroup.id, ); - final inSecondGroup = await database.playerGroupDao.isPlayerInGroup( + expect(removed, true); + + removed = await database.playerGroupDao.removePlayerFromGroup( playerId: testPlayer1.id, - groupId: secondGroup.id, - ); - - expect(inFirstGroup, true); - expect(inSecondGroup, true); - }); - - // Verifies that removing player from one group doesn't affect other groups. - test( - 'Removing player from one group does not affect other groups', - () async { - final secondGroup = Group( - name: 'Second Group', - description: '', - members: [testPlayer1], - ); - await database.groupDao.addGroup(group: testGroup); - await database.groupDao.addGroup(group: secondGroup); - - // Remove testPlayer1 from testGroup - await database.playerGroupDao.removePlayerFromGroup( - playerId: testPlayer1.id, - groupId: testGroup.id, - ); - - final inFirstGroup = await database.playerGroupDao.isPlayerInGroup( - playerId: testPlayer1.id, - groupId: testGroup.id, - ); - final inSecondGroup = await database.playerGroupDao.isPlayerInGroup( - playerId: testPlayer1.id, - groupId: secondGroup.id, - ); - - expect(inFirstGroup, false); - expect(inSecondGroup, true); - }, - ); - - // Verifies that addPlayerToGroup returns true on successful addition. - test('addPlayerToGroup returns true on successful addition', () async { - await database.groupDao.addGroup(group: testGroup); - await database.playerDao.addPlayer(player: testPlayer4); - - final result = await database.playerGroupDao.addPlayerToGroup( - player: testPlayer4, groupId: testGroup.id, ); - - expect(result, true); + expect(removed, false); }); - // Verifies that removing the same player twice returns false on second attempt. test( - 'Removing same player twice returns false on second attempt', + 'removePlayerFromGroup() returns false for non-existent player or group', () async { await database.groupDao.addGroup(group: testGroup); - final firstRemoval = await database.playerGroupDao - .removePlayerFromGroup( - playerId: testPlayer1.id, - groupId: testGroup.id, - ); - expect(firstRemoval, true); + await database.groupDao.addGroup(group: testGroup); - final secondRemoval = await database.playerGroupDao - .removePlayerFromGroup( - playerId: testPlayer1.id, - groupId: testGroup.id, - ); - expect(secondRemoval, false); + var removed = await database.playerGroupDao.removePlayerFromGroup( + playerId: 'non-existent-player-id', + groupId: testGroup.id, + ); + expect(removed, false); + + removed = await database.playerGroupDao.removePlayerFromGroup( + playerId: testPlayer1.id, + groupId: 'non-existent-group-id', + ); + expect(removed, false); + + removed = await database.playerGroupDao.removePlayerFromGroup( + playerId: 'non-existent-player-id', + groupId: 'non-existent-group-id', + ); + expect(removed, false); }, ); - - // Verifies that replaceGroupPlayers removes all existing players and replaces with new list. - test('replaceGroupPlayers replaces all group members correctly', () async { - // Create initial group with 3 players - await database.groupDao.addGroup(group: testGroup); - - // Verify initial members - var groupMembers = await database.groupDao.getGroupById( - groupId: testGroup.id, - ); - expect(groupMembers.members.length, 3); - - // Replace with new list containing 2 different players - final newPlayersList = [testPlayer3, testPlayer4]; - await database.groupDao.replaceGroupPlayers( - groupId: testGroup.id, - newPlayers: newPlayersList, - ); - - // Get updated group and verify members - groupMembers = await database.groupDao.getGroupById( - groupId: testGroup.id, - ); - - expect(groupMembers.members.length, 2); - expect(groupMembers.members.any((p) => p.id == testPlayer3.id), true); - expect(groupMembers.members.any((p) => p.id == testPlayer4.id), true); - expect(groupMembers.members.any((p) => p.id == testPlayer1.id), false); - expect(groupMembers.members.any((p) => p.id == testPlayer2.id), false); - }); }); }