diff --git a/lib/main.dart b/lib/main.dart index 98b87e7..caffa57 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -8,15 +8,16 @@ void main() { ); } +// Main application widget class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( - theme: halloweenTheme, - home: const PlayerRegistry(), - debugShowCheckedModeBanner: false, + theme: halloweenTheme, // Apply custom theme + home: const PlayerRegistry(), // Set initial screen to PlayerRegistry + debugShowCheckedModeBanner: false, // Disable debug banner ); } } diff --git a/lib/models/game.dart b/lib/models/game.dart index dcceec0..684c2ef 100644 --- a/lib/models/game.dart +++ b/lib/models/game.dart @@ -1,14 +1,22 @@ import 'package:werwolf/models/role.dart'; - import 'player.dart'; class Game { + // List to store player objects List players = []; + + // List to store player names List playernames = []; + + // Initial number of werewolves int numWolves = 1; + + // Map to store special roles and their activation status Map specialRoles = {}; + // Constructor to initialize the game with player names Game({required this.playernames}) { + // Initialize specialRoles map, setting all special roles to false for (Role role in Role.values) { if (role != Role.dorfbewohner && role != Role.werwolf) { specialRoles[role] = false; @@ -16,43 +24,64 @@ class Game { } } + // Method to increment the number of werewolves void incrementWolves() { + // Increment only if conditions are met: enough players and balance maintained if (numWolves < playernames.length - 1 && (playernames.length) >= ((numWolves + 1) * 3)) { numWolves++; } } + // Method to decrement the number of werewolves void decrementWolves() { + // Decrement only if there's more than one werewolf if (numWolves > 1) { numWolves--; } } + // Method to get the current number of werewolves int getWolves() { return numWolves; } + // Method to get all players with their assigned roles List getAllPlayers() { + // Clear the players list to start fresh players.clear(); + + // List to hold roles randomly assigned to players List randomRoles = []; + + // Add werewolf roles to the list for (var i = 0; i < numWolves; i++) { randomRoles.add(Role.werwolf); } + + // Add active special roles to the list for (var specialRole in specialRoles.keys) { if (specialRoles[specialRole]) { randomRoles.add(specialRole); } } + + // Fill the remaining roles with dorfbewohner for (var i = randomRoles.length; i < playernames.length; i++) { randomRoles.add(Role.dorfbewohner); } + + // Shuffle the roles to ensure randomness randomRoles.shuffle(); + + // Assign roles to players and create Player objects for (var playerName in playernames) { players .add(Player(name: playerName, role: randomRoles.last, isDead: false)); randomRoles.removeLast(); } + + // Return the list of players with their roles return players; } } diff --git a/lib/models/player.dart b/lib/models/player.dart index 2aaddcd..8a709c6 100644 --- a/lib/models/player.dart +++ b/lib/models/player.dart @@ -1,9 +1,14 @@ import 'package:werwolf/models/role.dart'; +// Define a class named Player class Player { + // Declare a string variable to store the player's name String name; + // Declare a variable of type Role to store the player's role Role role; + // Declare a boolean variable to indicate whether the player is dead bool isDead; + // Constructor for the Player class with required parameters for name, role, and isDead status Player({required this.name, required this.role, required this.isDead}); } diff --git a/lib/models/role.dart b/lib/models/role.dart index 1c41100..9eb8cac 100644 --- a/lib/models/role.dart +++ b/lib/models/role.dart @@ -1,18 +1,21 @@ +// Enum representing different roles in the game enum Role { dorfbewohner, werwolf, joker, seher, doctor } +// Extension on the Role enum to provide string representations extension RoleExtension on Role { + // Getter to convert enum value to its string representation String get stringValue { switch (this) { case Role.dorfbewohner: - return 'Dorfbewohner'; + return 'Dorfbewohner'; // Returns 'Dorfbewohner' for the dorfbewohner role case Role.werwolf: - return 'Werwolf'; + return 'Werwolf'; // Returns 'Werwolf' for the werwolf role case Role.joker: - return 'Joker'; + return 'Joker'; // Returns 'Joker' for the joker role case Role.seher: - return 'Seher'; + return 'Seher'; // Returns 'Seher' for the seher role case Role.doctor: - return 'Doctor'; + return 'Doctor'; // Returns 'Doctor' for the doctor role } } } diff --git a/lib/screens/flippingcards.dart b/lib/screens/flippingcards.dart index eff8940..4631baa 100644 --- a/lib/screens/flippingcards.dart +++ b/lib/screens/flippingcards.dart @@ -7,6 +7,7 @@ import 'package:werwolf/screens/gameboard.dart'; import '../models/player.dart'; import '../models/role.dart'; +// FlipingCard is a StatefulWidget that takes a list of players as input class FlipingCard extends StatefulWidget { final List players; const FlipingCard({required this.players, super.key}); @@ -15,17 +16,19 @@ class FlipingCard extends StatefulWidget { State createState() => _FlipingCardState(); } +// State class for FlipingCard class _FlipingCardState extends State { - int index = 0; + int index = 0; // Index to keep track of the current player - late FlipCardController _controller; + late FlipCardController _controller; // Controller for the flip card @override void initState() { super.initState(); - _controller = FlipCardController(); + _controller = FlipCardController(); // Initialize the flip card controller } + // Method to render the content of the flip card _renderContent(context) { return Card( elevation: 0.0, @@ -56,7 +59,7 @@ class _FlipingCardState extends State { ), ), const Text( - 'Klick um deine Rolle zu sehen!', + 'Click to see your role!', textAlign: TextAlign.center, ), ], @@ -124,14 +127,14 @@ class _FlipingCardState extends State { onPressed: () { setState(() { if (index > 0 && index <= widget.players.length) { - index--; + index--; // Go to the previous player if (!_controller.state!.isFront) { _controller.toggleCardWithoutAnimation(); } } }); }, - child: const Text("Zurück"), + child: const Text("Back"), ), ), Flexible( @@ -139,11 +142,12 @@ class _FlipingCardState extends State { onPressed: () { setState(() { if (index >= 0 && index < widget.players.length - 1) { - index++; + index++; // Go to the next player if (!_controller.state!.isFront) { _controller.toggleCardWithoutAnimation(); } } else if (index == widget.players.length - 1) { + // Navigate to the game board if it's the last player Navigator.push( context, MaterialPageRoute( @@ -155,8 +159,8 @@ class _FlipingCardState extends State { }); }, child: Text(index != widget.players.length - 1 - ? "Nächster Spieler" - : "Spiel anfangen!"), + ? "Next Player" + : "Start Game!"), ), ), ], diff --git a/lib/screens/gameboard.dart b/lib/screens/gameboard.dart index 4e65cdc..1f17e49 100644 --- a/lib/screens/gameboard.dart +++ b/lib/screens/gameboard.dart @@ -3,6 +3,7 @@ import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import '../models/player.dart'; import '../models/role.dart'; +// Main widget for displaying the player grid class PlayerGridView extends StatefulWidget { final List players; @@ -14,7 +15,7 @@ class PlayerGridView extends StatefulWidget { } class _PlayerGridViewState extends State { - bool isNight = true; + bool isNight = true; // Variable to track whether it is night or day @override void initState() { @@ -35,7 +36,7 @@ class _PlayerGridViewState extends State { ), const SizedBox(width: 10), Text( - isNight ? 'Nacht' : 'Tag', + isNight ? 'Nacht' : 'Tag', // Display whether it is night or day ), ], ), @@ -44,21 +45,21 @@ class _PlayerGridViewState extends State { IconButton( icon: const Icon(Icons.info), onPressed: () { - _showRolesDialog(); + _showRolesDialog(); // Show dialog with player roles }, ), ], leading: IconButton( icon: const Icon(FontAwesomeIcons.xmark), onPressed: () { - Navigator.popUntil(context, ModalRoute.withName('/')); + Navigator.popUntil(context, ModalRoute.withName('/')); // Return to main screen }, ), ), body: Container( color: isNight ? const Color(0xff2d2d2d) - : const Color.fromARGB(255, 194, 216, 225), + : const Color.fromARGB(255, 194, 216, 225), // Set background color based on night/day padding: const EdgeInsets.only(left: 15, right: 15), child: Column( children: [ @@ -66,7 +67,7 @@ class _PlayerGridViewState extends State { child: GridView.builder( gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: - MediaQuery.of(context).size.shortestSide < 600 ? 2 : 4, + MediaQuery.of(context).size.shortestSide < 600 ? 2 : 4, // Adjust grid based on screen size mainAxisSpacing: 10, crossAxisSpacing: 10, ), @@ -78,14 +79,14 @@ class _PlayerGridViewState extends State { onTap: () { setState(() { if (!widget.players[index].isDead) { - _killPlayer(widget.players[index]); + _killPlayer(widget.players[index]); // Mark player as dead } }); }, child: Card( color: widget.players[index].isDead ? Colors.grey - : Theme.of(context).colorScheme.primary, + : Theme.of(context).colorScheme.primary, // Change card color based on player status child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ @@ -98,7 +99,7 @@ class _PlayerGridViewState extends State { ), if (widget.players[index].isDead) const Icon(Icons.close, - color: Colors.red, size: 48), + color: Colors.red, size: 48), // Show icon if player is dead ], ), ), @@ -113,7 +114,7 @@ class _PlayerGridViewState extends State { Padding( padding: const EdgeInsets.only(bottom: 60, top: 10), child: ElevatedButton( - onPressed: _changePhase, + onPressed: _changePhase, // Change phase between night and day child: Text(isNight ? 'Tag skippen' : 'Nacht skippen'), ), ), @@ -127,14 +128,14 @@ class _PlayerGridViewState extends State { if (isNight) { if (player.role != Role.werwolf) { player.isDead = true; - _checkWinCondition(); + _checkWinCondition(); // Check win condition after killing player isNight = false; } } else { player.isDead = true; - _checkWinCondition(); + _checkWinCondition(); // Check win condition after killing player if (player.role == Role.joker) { - _showWinDialog('Der Joker hat gewonnen!'); + _showWinDialog('Der Joker hat gewonnen!'); // Show win dialog for Joker } isNight = true; } @@ -142,11 +143,7 @@ class _PlayerGridViewState extends State { } void _changePhase() { - if (isNight) { - isNight = false; - } else { - isNight = true; - } + isNight = !isNight; // Toggle between night and day setState(() {}); } @@ -159,9 +156,9 @@ class _PlayerGridViewState extends State { .length; if (countWolves == 0) { - _showWinDialog('Die Dorfbewohner haben gewonnen!'); + _showWinDialog('Die Dorfbewohner haben gewonnen!'); // Show win dialog for villagers } else if (countWolves >= countVillagers) { - _showWinDialog('Die Werwölfe haben gewonnen!'); + _showWinDialog('Die Werwölfe haben gewonnen!'); // Show win dialog for werewolves } } @@ -176,7 +173,7 @@ class _PlayerGridViewState extends State { TextButton( child: const Text('Spiel beenden'), onPressed: () { - Navigator.popUntil(context, ModalRoute.withName('/')); + Navigator.popUntil(context, ModalRoute.withName('/')); // Return to main screen }, ), ], @@ -217,7 +214,7 @@ class _PlayerGridViewState extends State { TextButton( child: const Text('OK'), onPressed: () { - Navigator.of(context).pop(); + Navigator.of(context).pop(); // Close dialog }, ), ], diff --git a/lib/screens/playerregistry.dart b/lib/screens/playerregistry.dart index 00a1dfe..acd1137 100644 --- a/lib/screens/playerregistry.dart +++ b/lib/screens/playerregistry.dart @@ -1,25 +1,28 @@ import 'package:flutter/material.dart'; import 'package:werwolf/screens/settings.dart'; +// Define the PlayerRegistry StatefulWidget class PlayerRegistry extends StatefulWidget { const PlayerRegistry({super.key}); @override + // Create the state for the PlayerRegistry widget // ignore: library_private_types_in_public_api _PlayerRegistryState createState() => _PlayerRegistryState(); } +// Define the state for the PlayerRegistry widget class _PlayerRegistryState extends State { - final TextEditingController _playerController = TextEditingController(); - final _formKey = GlobalKey(); - String _errorMessage = ""; - List playernames = []; + final TextEditingController _playerController = TextEditingController(); // Controller for player name input + final _formKey = GlobalKey(); // Key for form validation + String _errorMessage = ""; // Error message string + List playernames = []; // List to store player names @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: const Text("Werwolf"), + title: const Text("Werwolf"), // App bar title centerTitle: true, ), body: Padding( @@ -32,8 +35,8 @@ class _PlayerRegistryState extends State { key: _formKey, controller: _playerController, decoration: InputDecoration( - errorText: _errorMessage == "" ? null : _errorMessage, - labelText: 'Spielername', + errorText: _errorMessage == "" ? null : _errorMessage, // Display error message if exists + labelText: 'Spielername', // Label for text field focusedBorder: OutlineInputBorder( borderSide: BorderSide( color: Theme.of(context).colorScheme.primary), @@ -54,14 +57,14 @@ class _PlayerRegistryState extends State { onSubmitted: (value) { setState(() { if (_playerController.text.isEmpty) { - _errorMessage = "Spielername ist leer!"; + _errorMessage = "Spielername ist leer!"; // Error for empty name } else if (playernames.contains(value)) { - _errorMessage = "Dieser Spieler existiert bereits"; + _errorMessage = "Dieser Spieler existiert bereits"; // Error for duplicate name _playerController.clear(); } else { _errorMessage = ""; _playerController.clear(); - playernames.add(value); + playernames.add(value); // Add valid player name to list } }); }, @@ -73,15 +76,15 @@ class _PlayerRegistryState extends State { itemBuilder: (context, index) { return ListTile( title: Text( - playernames[index], + playernames[index], // Display player name ), trailing: IconButton( onPressed: () { setState(() { - playernames.remove(playernames[index]); + playernames.remove(playernames[index]); // Remove player name from list }); }, - icon: const Icon(Icons.remove)), + icon: const Icon(Icons.remove)), // Remove icon button ); }, ), @@ -93,16 +96,16 @@ class _PlayerRegistryState extends State { context, MaterialPageRoute( builder: (context) => GameSettings( - playernames: playernames, + playernames: playernames, // Pass player names to next screen ), )); } else { setState(() { - _errorMessage = "Es müssen mindestens 6 Spieler sein!"; + _errorMessage = "Es müssen mindestens 6 Spieler sein!"; // Error for not enough players }); } }, - child: const Text('Spiel einstellen'), + child: const Text('Spiel einstellen'), // Button to start game settings ), const Padding(padding: EdgeInsets.all(30)) ], diff --git a/lib/screens/settings.dart b/lib/screens/settings.dart index dc209d5..4369cbe 100644 --- a/lib/screens/settings.dart +++ b/lib/screens/settings.dart @@ -4,6 +4,7 @@ import 'package:werwolf/screens/flippingcards.dart'; import '../models/game.dart'; import '../models/role.dart'; +// Main widget for game settings class GameSettings extends StatefulWidget { final List playernames; const GameSettings({required this.playernames, super.key}); @@ -17,7 +18,7 @@ class _GameSettingsState extends State { @override void initState() { - game = Game(playernames: widget.playernames); + game = Game(playernames: widget.playernames); // Initialize the game with player names super.initState(); } @@ -27,7 +28,7 @@ class _GameSettingsState extends State { appBar: AppBar( title: Text( "Werwolf", - style: Theme.of(context).textTheme.titleLarge, + style: Theme.of(context).textTheme.titleLarge, // Use large title style from theme ), centerTitle: true, ), @@ -36,8 +37,8 @@ class _GameSettingsState extends State { child: Column( children: [ Text( - "Anzahl der Spieler ${widget.playernames.length}", - style: Theme.of(context).textTheme.titleLarge, + "Anzahl der Spieler ${widget.playernames.length}", // Display number of players + style: Theme.of(context).textTheme.titleLarge, // Use large title style from theme ), const Divider( height: 60, @@ -47,14 +48,13 @@ class _GameSettingsState extends State { crossAxisAlignment: CrossAxisAlignment.center, children: [ Text( - "Anzahl der Werwölfe ${game.getWolves()}", - style: - Theme.of(context).textTheme.bodyLarge, + "Anzahl der Werwölfe ${game.getWolves()}", // Display number of werewolves + style: Theme.of(context).textTheme.bodyLarge, // Use large body style from theme ), IconButton( onPressed: () { setState(() { - game.decrementWolves(); + game.decrementWolves(); // Decrease the number of werewolves }); }, icon: const Icon(Icons.remove, color: Colors.white), @@ -62,7 +62,7 @@ class _GameSettingsState extends State { IconButton( onPressed: () { setState(() { - game.incrementWolves(); + game.incrementWolves(); // Increase the number of werewolves }); }, icon: const Icon(Icons.add, color: Colors.white), @@ -75,9 +75,8 @@ class _GameSettingsState extends State { Padding( padding: const EdgeInsets.only(top: 8.0, bottom: 20), child: Text( - "Spezielle Rollen", - style: - Theme.of(context).textTheme.titleLarge, + "Spezielle Rollen", // Display special roles section + style: Theme.of(context).textTheme.titleLarge, // Use large title style from theme ), ), Expanded( @@ -89,22 +88,20 @@ class _GameSettingsState extends State { Role role = Role.values[index]; return ListTile( title: Text( - role.stringValue, - style: Theme.of(context) - .textTheme - .bodyLarge, + role.stringValue, // Display role name + style: Theme.of(context).textTheme.bodyLarge, // Use large body style from theme ), trailing: Switch( value: game.specialRoles[role], onChanged: (bool value) { setState(() { - game.specialRoles[role] = value; + game.specialRoles[role] = value; // Toggle special role }); }, ), ); } - return Container(); + return Container(); // Return empty container if not a special role }, ), ), @@ -113,13 +110,12 @@ class _GameSettingsState extends State { Navigator.push( context, MaterialPageRoute( - builder: (context) => - FlipingCard(players: game.getAllPlayers()), + builder: (context) => FlipingCard(players: game.getAllPlayers()), // Start game ), ); }, child: const Text( - 'Spiel starten!', + 'Spiel starten!', // Start game button text ), ), const Padding(padding: EdgeInsets.all(30)), diff --git a/pubspec.lock b/pubspec.lock index 36ac543..bd45b7b 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -118,6 +118,11 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_driver: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" flutter_lints: dependency: "direct dev" description: @@ -147,6 +152,11 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.0" + fuchsia_remote_debug_protocol: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" glob: dependency: transitive description: @@ -171,6 +181,11 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.2" + integration_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" io: dependency: transitive description: @@ -283,6 +298,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.9.0" + platform: + dependency: transitive + description: + name: platform + sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec" + url: "https://pub.dev" + source: hosted + version: "3.1.4" pool: dependency: transitive description: @@ -291,6 +314,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.5.1" + process: + dependency: transitive + description: + name: process + sha256: "21e54fd2faf1b5bdd5102afd25012184a6793927648ea81eea80552ac9405b32" + url: "https://pub.dev" + source: hosted + version: "5.0.2" pub_semver: dependency: transitive description: @@ -384,6 +415,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.0" + sync_http: + dependency: transitive + description: + name: sync_http + sha256: "7f0cd72eca000d2e026bcd6f990b81d0ca06022ef4e32fb257b30d3d1014a961" + url: "https://pub.dev" + source: hosted + version: "0.3.1" term_glyph: dependency: transitive description: @@ -464,6 +503,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.4.5" + webdriver: + dependency: transitive + description: + name: webdriver + sha256: "003d7da9519e1e5f329422b36c4dcdf18d7d2978d1ba099ea4e45ba490ed845e" + url: "https://pub.dev" + source: hosted + version: "3.0.3" webkit_inspection_protocol: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index ff4f1fb..e0181fb 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,6 +17,8 @@ dev_dependencies: sdk: flutter flutter_lints: ^2.0.0 test: ^1.25.2 + integration_test: + sdk: flutter flutter: uses-material-design: true diff --git a/test/integration_test/app_test.dart b/test/integration_test/app_test.dart new file mode 100644 index 0000000..96cb524 --- /dev/null +++ b/test/integration_test/app_test.dart @@ -0,0 +1,76 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; +import 'package:werwolf/main.dart' as app; +import 'package:werwolf/screens/playerregistry.dart'; +import 'package:werwolf/screens/settings.dart'; +import 'package:werwolf/screens/flippingcards.dart'; +import 'package:werwolf/screens/gameboard.dart'; + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + group('Werwolf Game Integration Tests', () { + testWidgets('Complete game flow', (WidgetTester tester) async { + app.main(); + await tester.pumpAndSettle(); + + // Ensure we are on the PlayerRegistry screen + expect(find.byType(PlayerRegistry), findsOneWidget); + + // Add players + for (int i = 0; i < 6; i++) { + await tester.enterText(find.byType(TextField), 'Player $i'); + await tester.testTextInput.receiveAction(TextInputAction.done); + await tester.pumpAndSettle(); + } + + // Ensure all players are added + for (int i = 0; i < 6; i++) { + expect(find.text('Player $i'), findsOneWidget); + } + + // Navigate to GameSettings screen + await tester.tap(find.text('Spiel einstellen')); + await tester.pumpAndSettle(); + expect(find.byType(GameSettings), findsOneWidget); + + // Ensure the number of players and wolves are displayed correctly + expect(find.text('Anzahl der Spieler 6'), findsOneWidget); + expect(find.text('Anzahl der Werwölfe 1'), findsOneWidget); + + // Toggle a special role + await tester.tap(find.byType(Switch).first); + await tester.pumpAndSettle(); + expect((tester.widget(find.byType(Switch).first) as Switch).value, true); + + // Navigate to FlipingCard screen + await tester.tap(find.text('Spiel starten!')); + await tester.pumpAndSettle(); + expect(find.byType(FlipingCard), findsOneWidget); + + // Flip through all players + for (int i = 0; i < 6; i++) { + await tester.tap(find.text('Klick um deine Rolle zu sehen!')); + await tester.pumpAndSettle(); + await tester.tap(find.text('Nächster Spieler')); + await tester.pumpAndSettle(); + } + + // Ensure we navigate to the game board + await tester.tap(find.text('Spiel anfangen!')); + await tester.pumpAndSettle(); + expect(find.byType(PlayerGridView), findsOneWidget); + + // Tap to kill a player + await tester.tap(find.text('Player 0')); + await tester.pumpAndSettle(); + expect(find.byIcon(Icons.close), findsOneWidget); + + // Skip phase + await tester.tap(find.text('Tag skippen')); + await tester.pumpAndSettle(); + expect(find.text('Nacht skippen'), findsOneWidget); + }); + }); +} diff --git a/test/settings_test.dart b/test/settings_test.dart new file mode 100644 index 0000000..0ed9ecb --- /dev/null +++ b/test/settings_test.dart @@ -0,0 +1,50 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:werwolf/screens/settings.dart'; +import 'package:werwolf/screens/flippingcards.dart'; + +void main() { + group('GameSettings Tests', () { + List playerNames = ['Alice', 'Bob', 'Charlie', 'Dave', 'Eve', 'Frank']; + + testWidgets('Displays number of players', (WidgetTester tester) async { + await tester.pumpWidget(MaterialApp(home: GameSettings(playernames: playerNames))); + + expect(find.text('Anzahl der Spieler 6'), findsOneWidget); + }); + + testWidgets('Displays number of wolves and increments/decrements correctly', (WidgetTester tester) async { + await tester.pumpWidget(MaterialApp(home: GameSettings(playernames: playerNames))); + + expect(find.text('Anzahl der Werwölfe 1'), findsOneWidget); + + await tester.tap(find.byIcon(Icons.add)); + await tester.pumpAndSettle(); + expect(find.text('Anzahl der Werwölfe 2'), findsOneWidget); + + await tester.tap(find.byIcon(Icons.remove)); + await tester.pumpAndSettle(); + expect(find.text('Anzahl der Werwölfe 1'), findsOneWidget); + }); + + testWidgets('Displays special roles and toggles switches', (WidgetTester tester) async { + await tester.pumpWidget(MaterialApp(home: GameSettings(playernames: playerNames))); + + expect(find.text('Spezielle Rollen'), findsOneWidget); + + await tester.tap(find.byType(Switch).first); + await tester.pumpAndSettle(); + + expect((tester.widget(find.byType(Switch).first) as Switch).value, true); + }); + + testWidgets('Navigates to FlipingCard screen on start', (WidgetTester tester) async { + await tester.pumpWidget(MaterialApp(home: GameSettings(playernames: playerNames))); + + await tester.tap(find.text('Spiel starten!')); + await tester.pumpAndSettle(); + + expect(find.byType(FlipingCard), findsOneWidget); + }); + }); +}