diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 804f441..138b281 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -215,7 +215,7 @@ isa = PBXProject; attributes = { BuildIndependentTargetsInParallel = YES; - LastUpgradeCheck = 1510; + LastUpgradeCheck = 1620; ORGANIZATIONNAME = ""; TargetAttributes = { 331C8080294A63A400263BE5 = { diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 1728d10..51c28c5 100644 --- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ testingGetLowestScoreIndex(List roundScores) => + _getLowestScoreIndex(roundScores); + /// Returns the index of the player with the lowest score. If there are /// multiple players with the same lowest score, all of them are returned. /// [roundScores] is a list of the scores of all players in the current round. @@ -157,6 +163,12 @@ class GameSession { return lowestScoreIndex; } + @visibleForTesting + void testingAssignPoints(int roundNum, List roundScores, + int caboPlayerIndex, List winnerIndex, [int? loserIndex]) => + _assignPoints( + roundNum, roundScores, caboPlayerIndex, winnerIndex, loserIndex); + /// Assigns points to the players based on the scores of the current round. /// [roundNum] is the number of the current round. /// [roundScores] is the raw list of the scores of all players in the current round. @@ -238,6 +250,9 @@ class GameSession { } } + @visibleForTesting + void testingSumPoints() => _sumPoints(); + /// Sums up the points of all players and stores the result in the /// playerScores list. void _sumPoints() { diff --git a/test/data/game_session_test.dart b/test/data/game_session_test.dart new file mode 100644 index 0000000..0e9bfa1 --- /dev/null +++ b/test/data/game_session_test.dart @@ -0,0 +1,164 @@ +import 'package:cabo_counter/data/game_session.dart'; +import 'package:test/test.dart'; + +void main() { + late GameSession session; + final testPlayers = ['Alice', 'Bob', 'Charlie']; + final testDate = DateTime(2023, 1, 1); + const testTitle = 'Test Game'; + + setUp(() { + session = GameSession( + createdAt: testDate, + gameTitle: testTitle, + players: testPlayers, + pointLimit: 100, + caboPenalty: 5, + isPointsLimitEnabled: true, + ); + }); + + group('Initialization & JSON', () { + test('Initialization', () { + expect(session.gameTitle, testTitle); + expect(session.players, testPlayers); + expect(session.playerScores, [0, 0, 0]); + expect(session.roundNumber, 1); + expect(session.isGameFinished, isFalse); + expect(session.winner, isEmpty); + }); + + test('toJson and fromJson', () { + // Add some rounds to test serialization + session.addRoundScoresToList(1, [10, 20, 30], [10, 20, 30], 0); + session.addRoundScoresToList(2, [15, 25, 35], [5, 5, 5], 1); + + final json = session.toJson(); + final fromJsonSession = GameSession.fromJson(json); + + expect(fromJsonSession.gameTitle, testTitle); + expect(fromJsonSession.players, testPlayers); + expect(fromJsonSession.roundList.length, 2); + }); + + test('null values in JSON', () { + expect( + () => GameSession.fromJson({ + 'createdAt': testDate.toIso8601String(), + 'gameTitle': null, // Invalid + 'players': testPlayers, + 'pointLimit': 100, + 'caboPenalty': 50, + 'isPointsLimitEnabled': true, + 'isGameFinished': false, + 'winner': '', + 'roundNumber': 1, + 'playerScores': [0, 0, 0], + 'roundList': [], + }), + throwsA(isA())); + }); + }); + + group('Helper Functions', () { + test('getLengthOfPlayerNames', () { + expect(session.getLengthOfPlayerNames(), + equals(15)); // Alice(5) + Bob(3) + Charlie(7) + }); + + test('increaseRound', () { + expect(session.roundNumber, 1); + session.increaseRound(); + expect(session.roundNumber, 2); + }); + + test('getLowestScoreIndex', () { + List lowestScoreIndex; + + lowestScoreIndex = session.testingGetLowestScoreIndex([5, 10, 15]); + expect(lowestScoreIndex, [0]); + + lowestScoreIndex = session.testingGetLowestScoreIndex([5, 5, 15]); + expect(lowestScoreIndex, [0, 1]); + + lowestScoreIndex = session.testingGetLowestScoreIndex([5, 5, 5]); + expect(lowestScoreIndex, [0, 1, 2]); + }); + }); + + group('Game Functions', () { + test('applyKamikaze', () { + session.applyKamikaze(1, 0); // Alice has kamikaze + expect(session.roundList[0].scoreUpdates, [0, 50, 50]); + expect(session.roundList[0].scores, [0, 0, 0]); + expect(session.roundList[0].kamikazePlayerIndex, 0); + expect(session.roundList[0].caboPlayerIndex, 0); + }); + + test('calculateScoredPoints - CABO player has lowest', () { + session.calculateScoredPoints(1, [3, 5, 8], 0); // Alice has lowest + expect(session.roundList[0].scoreUpdates, equals([0, 5, 8])); + }); + + test('calculateScoredPoints - CABO player not lowest', () { + session.calculateScoredPoints(1, [5, 3, 8], 0); // Bob has lowest + expect(session.roundList[0].scoreUpdates, [10, 0, 8]); + }); + + test('addRoundScoresToList', () { + session.addRoundScoresToList(1, [3, 5, 8], [0, 5, 8], 0); + expect(session.roundList.length, 1); + expect(session.roundList[0].roundNum, 1); + expect(session.roundList[0].scoreUpdates, [0, 5, 8]); + expect(session.roundList[0].scores, [3, 5, 8]); + expect(session.roundList[0].kamikazePlayerIndex, isNull); + expect(session.roundList[0].caboPlayerIndex, 0); + }); + + test('updatePoints - game not finished', () async { + session.addRoundScoresToList(1, [10, 20, 30], [10, 20, 30], 0); + await session.updatePoints(); + expect(session.isGameFinished, isFalse); + }); + + test('updatePoints - game finished', () async { + session.addRoundScoresToList(1, [101, 20, 30], [101, 20, 30], 0); + await session.updatePoints(); + expect(session.isGameFinished, isTrue); + }); + + test('_assignPoints', () { + // Alice said Cabo and has the lowest score + session.testingAssignPoints(1, [5, 10, 15], 0, [0]); + expect(session.roundList[0].scoreUpdates, [0, 10, 15]); + + // Alice said Cabo and has not the lowest score + session.testingAssignPoints(1, [5, 10, 15], 0, [1], 0); + expect(session.roundList[0].scoreUpdates, [10, 0, 15]); + + // Bob and Charlie have the lowest score, Alice said Cabo + session.testingAssignPoints(1, [15, 5, 5], 0, [1, 2], 0); + expect(session.roundList[0].scoreUpdates, [20, 0, 0]); + }); + + test('_sumPoints', () async { + session.addRoundScoresToList(1, [10, 20, 30], [10, 20, 30], 0); + session.addRoundScoresToList(2, [5, 5, 5], [5, 5, 5], 1); + session.testingSumPoints(); + expect(session.playerScores, [15, 25, 35]); + }); + + test('_checkHundredPointsReached via updatePoints', () { + session.addRoundScoresToList(1, [50, 5, 15], [50, 0, 15], 1); + session.addRoundScoresToList(2, [50, 5, 15], [50, 0, 15], 1); + session.updatePoints(); + expect(session.playerScores, equals([50, 0, 30])); + }); + + test('_setWinner via updatePoints', () async { + session.addRoundScoresToList(1, [101, 20, 30], [101, 0, 30], 1); + await session.updatePoints(); + expect(session.winner, 'Bob'); // Bob has lowest score (20) + }); + }); +} diff --git a/test/data/round_test.dart b/test/data/round_test.dart new file mode 100644 index 0000000..3e5ef4e --- /dev/null +++ b/test/data/round_test.dart @@ -0,0 +1,117 @@ +import 'package:cabo_counter/data/round.dart'; +import 'package:test/test.dart'; + +void main() { + late Round round; + const testRoundNum = 1; + const testCaboPlayerIndex = 0; + const testKamikazePlayerIndex = 1; + const testScores = [10, 20, 30]; + const testScoreUpdates = [5, 15, 25]; + + setUp(() { + round = Round( + roundNum: testRoundNum, + caboPlayerIndex: testCaboPlayerIndex, + kamikazePlayerIndex: testKamikazePlayerIndex, + scores: testScores, + scoreUpdates: testScoreUpdates, + ); + }); + + group('Constructor Tests', () { + test('Constructor sets correct values', () { + expect(round.roundNum, testRoundNum); + expect(round.caboPlayerIndex, testCaboPlayerIndex); + expect(round.kamikazePlayerIndex, testKamikazePlayerIndex); + expect(round.scores, testScores); + expect(round.scoreUpdates, testScoreUpdates); + }); + + test('Constructor with null kamikazePlayerIndex', () { + final roundWithoutKamikaze = Round( + roundNum: testRoundNum, + caboPlayerIndex: testCaboPlayerIndex, + kamikazePlayerIndex: null, + scores: testScores, + scoreUpdates: testScoreUpdates, + ); + + expect(roundWithoutKamikaze.kamikazePlayerIndex, isNull); + }); + }); + + group('JSON Methods', () { + test('toJson() returns correct map', () { + final jsonMap = round.toJson(); + + expect(jsonMap['roundNum'], equals(testRoundNum)); + expect(jsonMap['caboPlayerIndex'], equals(testCaboPlayerIndex)); + expect(jsonMap['kamikazePlayerIndex'], equals(testKamikazePlayerIndex)); + expect(jsonMap['scores'], equals(testScores)); + expect(jsonMap['scoreUpdates'], equals(testScoreUpdates)); + }); + + test('fromJson() creates correct Round object', () { + final jsonMap = { + 'roundNum': testRoundNum, + 'caboPlayerIndex': testCaboPlayerIndex, + 'kamikazePlayerIndex': testKamikazePlayerIndex, + 'scores': testScores, + 'scoreUpdates': testScoreUpdates, + }; + + final fromJsonRound = Round.fromJson(jsonMap); + + expect(fromJsonRound.roundNum, testRoundNum); + expect(fromJsonRound.caboPlayerIndex, testCaboPlayerIndex); + expect(fromJsonRound.kamikazePlayerIndex, testKamikazePlayerIndex); + expect(fromJsonRound.scores, testScores); + expect(fromJsonRound.scoreUpdates, testScoreUpdates); + }); + + test('fromJson() with null kamikazePlayerIndex', () { + final jsonMap = { + 'roundNum': testRoundNum, + 'caboPlayerIndex': testCaboPlayerIndex, + 'kamikazePlayerIndex': null, + 'scores': testScores, + 'scoreUpdates': testScoreUpdates, + }; + + final fromJsonRound = Round.fromJson(jsonMap); + + expect(fromJsonRound.kamikazePlayerIndex, isNull); + }); + }); + + group('toString()', () { + test('toString() returns correct string representation', () { + final expectedString = 'Round $testRoundNum, ' + 'caboPlayerIndex: $testCaboPlayerIndex, ' + 'kamikazePlayerIndex: $testKamikazePlayerIndex, ' + 'scores: $testScores, ' + 'scoreUpdates: $testScoreUpdates, '; + + expect(round.toString(), equals(expectedString)); + }); + + test('toString() with null kamikazePlayerIndex', () { + final roundWithoutKamikaze = Round( + roundNum: testRoundNum, + caboPlayerIndex: testCaboPlayerIndex, + kamikazePlayerIndex: null, + scores: testScores, + scoreUpdates: testScoreUpdates, + ); + + final expectedString = 'Round $testRoundNum, ' + 'caboPlayerIndex: $testCaboPlayerIndex, ' + 'kamikazePlayerIndex: null, ' + 'scores: $testScores, ' + 'scoreUpdates: $testScoreUpdates, '; + + expect(roundWithoutKamikaze.toString(), expectedString); + }); + }); +}