diff --git a/lib/api/register.dart b/lib/api/register.dart index b423595..b8e3a41 100644 --- a/lib/api/register.dart +++ b/lib/api/register.dart @@ -1,30 +1,43 @@ import 'package:uuid/uuid.dart'; -class ResponseFromRegisteringGame { - final UuidValue playerID; - final UuidValue lobbyID; +class PlayerInfo { + final UuidValue? playerID; + final UuidValue? lobbyID; + final String? passphrase; - const ResponseFromRegisteringGame({ + const PlayerInfo({ required this.playerID, required this.lobbyID, + required this.passphrase, }); - factory ResponseFromRegisteringGame.fromJson(Map json) { + factory PlayerInfo.fromJson(Map json) { final playerid = UuidValue(json['playerID']); final lobbyid = UuidValue(json['lobbyID']); + final passphrase = json['passphrase']; - return ResponseFromRegisteringGame(playerID: playerid, lobbyID: lobbyid); + return PlayerInfo( + playerID: playerid, lobbyID: lobbyid, passphrase: passphrase); } + + Map toJson() => { + 'playerID': playerID, + 'lobbyID': lobbyID, + 'passphrase': passphrase, + }; } class WebsocketMessageIdentifyPlayer { final String playerID; final String lobbyID; + final String? passphrase; const WebsocketMessageIdentifyPlayer({ required this.playerID, required this.lobbyID, + required this.passphrase, }); - Map toJson() => {'lobbyID': lobbyID, 'playerID': playerID}; + Map toJson() => + {'lobbyID': lobbyID, 'playerID': playerID, 'passphrase': passphrase}; } diff --git a/lib/chess_bloc/chess_bloc.dart b/lib/chess_bloc/chess_bloc.dart index fc459e5..248b59e 100644 --- a/lib/chess_bloc/chess_bloc.dart +++ b/lib/chess_bloc/chess_bloc.dart @@ -77,7 +77,7 @@ class ChessBloc extends Bloc { ServerConnection.getInstance().send(jsonEncode(apiMessage)); - //Temporary chess position until server responds with acknoledgement + //Temporary chess position until server responds with acknowledgement var move = ChessMove.fromApiMove(apiMove); var tempPosition = ChessPosition.getInstance().copyOfCurrentPosition; tempPosition[move.to] = tempPosition[move.from] ?? const ChessPiece.none(); diff --git a/lib/chess_bloc/chess_position.dart b/lib/chess_bloc/chess_position.dart index aaa3065..0b1cc5b 100644 --- a/lib/chess_bloc/chess_position.dart +++ b/lib/chess_bloc/chess_position.dart @@ -104,7 +104,7 @@ class ChessPosition { logString = '$logString\n'; } - print(logString); + log(logString); } void logHistory(ChessMoveHistory hist) { diff --git a/lib/connection/ws_connection.dart b/lib/connection/ws_connection.dart index 92690a6..3f51648 100644 --- a/lib/connection/ws_connection.dart +++ b/lib/connection/ws_connection.dart @@ -4,8 +4,8 @@ import 'package:flutter/foundation.dart'; import 'package:mchess/api/websocket_message.dart'; import 'package:mchess/chess_bloc/chess_bloc.dart'; import 'package:mchess/chess_bloc/chess_events.dart'; -import 'package:mchess/chess_bloc/chess_position.dart'; import 'package:mchess/api/register.dart'; +import 'package:mchess/connection_cubit/connection_cubit.dart'; import 'package:mchess/utils/chess_utils.dart'; import 'package:web_socket_channel/web_socket_channel.dart'; @@ -34,9 +34,7 @@ class ServerConnection { counter++; } - void connect(String playerID, lobbyID) { - if (wasConnected) channel.sink.close(); - + void connect(String playerID, lobbyID, String? passphrase) { if (kDebugMode) { channel = WebSocketChannel.connect(Uri.parse('ws://localhost:8080/api/ws')); @@ -44,15 +42,18 @@ class ServerConnection { channel = WebSocketChannel.connect( Uri.parse('wss://chess.sw-gross.de:9999/api/ws')); } - send(jsonEncode(WebsocketMessageIdentifyPlayer( - playerID: (playerID), lobbyID: (lobbyID)))); + send( + jsonEncode( + WebsocketMessageIdentifyPlayer( + playerID: (playerID), + lobbyID: (lobbyID), + passphrase: (passphrase), + ), + ), + ); log(channel.closeCode.toString()); - - wasConnected = true; - broadcast = channel.stream.asBroadcastStream(); - broadcast.listen(handleIncomingData); } @@ -78,6 +79,7 @@ class ServerConnection { void handleIncomingColorDeterminedMessage(ApiWebsocketMessage apiMessage) { ChessBloc.getInstance().add( ColorDetermined(myColor: ChessColor.fromApiColor(apiMessage.color!))); + ConnectionCubit.getInstance().opponentConnected(); } void handleIncomingMoveMessage(ApiWebsocketMessage apiMessage) { diff --git a/lib/connection_cubit/connection_cubit.dart b/lib/connection_cubit/connection_cubit.dart index d925cb3..9c9c3e2 100644 --- a/lib/connection_cubit/connection_cubit.dart +++ b/lib/connection_cubit/connection_cubit.dart @@ -15,16 +15,19 @@ class ConnectionCubit extends Cubit { return _instance; } - void connect(String playerID, lobbyID) { - ServerConnection.getInstance().connect(playerID, lobbyID); + void connect(String playerID, lobbyID, String? passphrase) { + ServerConnection.getInstance().connect(playerID, lobbyID, passphrase); + } + + void opponentConnected() { emit(ConnectionCubitState(true)); } } class ConnectionCubitState { - final bool reconnecting; + final bool opponentConnected; - ConnectionCubitState(this.reconnecting); + ConnectionCubitState(this.opponentConnected); factory ConnectionCubitState.init() { return ConnectionCubitState(false); diff --git a/lib/pages/chess_game.dart b/lib/pages/chess_game.dart index a442dd7..bf1baf1 100644 --- a/lib/pages/chess_game.dart +++ b/lib/pages/chess_game.dart @@ -6,16 +6,18 @@ import 'package:mchess/chess_bloc/chess_bloc.dart'; import 'package:mchess/chess/chess_board.dart'; import 'package:mchess/chess/turn_indicator_widget.dart'; -import 'package:mchess/connection_cubit/connection_cubit.dart'; - -import 'package:mchess/connection/ws_connection.dart'; import 'package:mchess/utils/widgets/server_log_widget.dart'; import 'package:uuid/uuid.dart'; class ChessGame extends StatefulWidget { final UuidValue playerID; final UuidValue lobbyID; - const ChessGame({required this.playerID, required this.lobbyID, super.key}); + final String? passphrase; + const ChessGame( + {required this.playerID, + required this.lobbyID, + required this.passphrase, + super.key}); @override State createState() => _ChessGameState(); @@ -25,49 +27,48 @@ class _ChessGameState extends State { @override void initState() { super.initState(); - ConnectionCubit.getInstance() - .connect(widget.playerID.uuid, widget.lobbyID.uuid); } @override Widget build(BuildContext context) { return Scaffold( - body: Center( - child: FittedBox( - fit: BoxFit.contain, - child: Column( - children: [ - if (kDebugMode) - StreamBuilder( - stream: ServerConnection.getInstance().broadcast, - builder: (context, snapshot) { - return ServerLogWidget( - snapshot.data ?? "", - textColor: Colors.white, - ); - }, - ), - Container( - margin: const EdgeInsets.all(20), - child: BlocBuilder( - builder: (context, state) { - return ChessBoard( - bState: state, - ); - }, - ), + body: FittedBox( + fit: BoxFit.contain, + child: Column( + children: [ + if (kDebugMode) const ServerLogWidget(textColor: Colors.white), + Container( + margin: const EdgeInsets.all(20), + child: BlocBuilder( + builder: (context, state) { + return ChessBoard( + bState: state, + ); + }, ), - if (kDebugMode) const TurnIndicator(), - ], - ), + ), + if (kDebugMode) const TurnIndicator(), + ], ), ), floatingActionButton: FloatingActionButton( onPressed: () { - context.goNamed('lobbySelector'); + context.push('/'); }, - child: const Icon(Icons.arrow_back), + child: const Icon(Icons.cancel), ), ); } } + +class ChessGameArguments { + final UuidValue lobbyID; + final UuidValue playerID; + final String? passphrase; + + ChessGameArguments({ + required this.lobbyID, + required this.playerID, + required this.passphrase, + }); +} diff --git a/lib/pages/host_game.dart b/lib/pages/host_game.dart new file mode 100644 index 0000000..8d0e0ea --- /dev/null +++ b/lib/pages/host_game.dart @@ -0,0 +1,144 @@ +import 'dart:developer'; + +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:go_router/go_router.dart'; +import 'package:http/http.dart'; +import 'package:mchess/api/register.dart'; +import 'package:mchess/chess_bloc/chess_bloc.dart'; +import 'package:mchess/chess_bloc/chess_events.dart'; +import 'package:mchess/connection_cubit/connection_cubit.dart'; +import 'package:http/http.dart' as http; +import 'dart:convert'; + +import 'package:mchess/pages/chess_game.dart'; + +class HostGameWidget extends StatefulWidget { + const HostGameWidget({super.key}); + + @override + State createState() => _HostGameWidgetState(); +} + +class _HostGameWidgetState extends State { + late Future registerResponse; + late ChessGameArguments chessGameArgs; + + @override + void initState() { + ChessBloc.getInstance().add(InitBoard()); + + registerResponse = hostPrivateGame(); + connectToWebsocket(registerResponse); + + super.initState(); + } + + void connectToWebsocket(Future resp) { + resp.then((value) { + if (value == null) return; + + chessGameArgs = ChessGameArguments( + lobbyID: value.lobbyID!, + playerID: value.playerID!, + passphrase: value.passphrase); + + ConnectionCubit.getInstance().connect( + value.playerID!.uuid, + value.lobbyID!.uuid, + value.passphrase, + ); + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Center( + child: FutureBuilder( + future: registerResponse, + builder: (context, snapshot) { + if (snapshot.connectionState != ConnectionState.done) { + return const SizedBox( + height: 100, + width: 100, + child: CircularProgressIndicator(), + ); + } else { + String passphrase = snapshot.data?.passphrase ?? "no passphrase"; + return BlocListener( + listener: (context, state) { + // We wait for our opponent to connect + if (state.opponentConnected) { + context.push('/game', extra: chessGameArgs); + } + }, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'Give this phrase to your friend and sit tight:', + style: TextStyle( + color: Theme.of(context).colorScheme.primary), + ), + const SizedBox(height: 25), + Text( + passphrase, + style: const TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(height: 25), + const CircularProgressIndicator() + ], + ), + ); + } + }, + ), + ), + floatingActionButton: FloatingActionButton( + child: const Icon(Icons.cancel), + onPressed: () { + context.push('/'); + }, + ), + ); + } + + Future hostPrivateGame() async { + String addr; + Response response; + + if (kDebugMode) { + addr = 'http://localhost:8080/api/hostPrivate'; + } else { + addr = 'https://chess.sw-gross.de:9999/api/hostPrivate'; + } + + try { + response = await http + .get(Uri.parse(addr), headers: {"Accept": "application/json"}); + } catch (e) { + log(e.toString()); + + if (!context.mounted) return null; + + const snackBar = SnackBar( + backgroundColor: Colors.amberAccent, + content: Text("mChess server is not responding. Try again or give up"), + ); + Future.delayed(const Duration(seconds: 2), () { + ScaffoldMessenger.of(context).clearSnackBars(); + ScaffoldMessenger.of(context).showSnackBar(snackBar); + context.pop(); + }); + return null; + } + + if (response.statusCode == 200) { + log(response.body); + return PlayerInfo.fromJson(jsonDecode(response.body)); + } + return null; + } +} diff --git a/lib/pages/join_game.dart b/lib/pages/join_game.dart new file mode 100644 index 0000000..99f6a42 --- /dev/null +++ b/lib/pages/join_game.dart @@ -0,0 +1,118 @@ +import 'dart:convert'; +import 'dart:developer'; + +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; +import 'package:http/http.dart' as http; +import 'package:http/http.dart'; +import 'package:mchess/api/register.dart'; +import 'package:mchess/connection_cubit/connection_cubit.dart'; +import 'package:mchess/pages/chess_game.dart'; + +class JoinGameWidget extends StatefulWidget { + const JoinGameWidget({ + super.key, + }); + + @override + State createState() => _JoinGameWidgetState(); +} + +class _JoinGameWidgetState extends State { + final myController = TextEditingController(); + late Future joinGameFuture; + + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: TextField( + controller: myController, + decoration: InputDecoration( + hintText: 'Enter passphrase here', + suffixIcon: IconButton( + onPressed: () { + joinGameFuture = joinPrivateGame(); + switchToGame(joinGameFuture); + }, + icon: const Icon(Icons.check), + )), + ), + floatingActionButton: FloatingActionButton( + onPressed: () { + context.push('/'); + }, + child: const Icon(Icons.cancel), + ), + ); + } + + void switchToGame(Future resp) { + resp.then((value) { + if (value == null) return; + + var chessGameArgs = ChessGameArguments( + lobbyID: value.lobbyID!, + playerID: value.playerID!, + passphrase: value.passphrase); + + ConnectionCubit.getInstance().connect( + value.playerID!.uuid, + value.lobbyID!.uuid, + value.passphrase, + ); + + context.push('/game', extra: chessGameArgs); + }); + } + + Future joinPrivateGame() async { + String addr; + Response response; + + // server expects us to send the passphrase + var info = PlayerInfo( + playerID: null, lobbyID: null, passphrase: myController.text); + + if (kDebugMode) { + addr = 'http://localhost:8080/api/joinPrivate'; + } else { + addr = 'https://chess.sw-gross.de:9999/api/joinPrivate'; + } + + try { + response = await http.post(Uri.parse(addr), + body: jsonEncode(info), headers: {"Accept": "application/json"}); + } catch (e) { + log(e.toString()); + + if (!context.mounted) return null; + + const snackBar = SnackBar( + backgroundColor: Colors.amberAccent, + content: Text("mChess server is not responding. Try again or give up"), + ); + Future.delayed(const Duration(seconds: 2), () { + ScaffoldMessenger.of(context).clearSnackBars(); + ScaffoldMessenger.of(context).showSnackBar(snackBar); + context.pop(); + }); + return null; + } + + if (response.statusCode == 200) { + var info = PlayerInfo.fromJson(jsonDecode(response.body)); + log('Player info received from server: '); + log('lobbyID: ${info.lobbyID}'); + log('playerID: ${info.playerID}'); + log('passphrase: ${info.passphrase}'); + return info; + } + return null; + } +} diff --git a/lib/pages/lobby_selector.dart b/lib/pages/lobby_selector.dart index 58bd720..6aad49a 100644 --- a/lib/pages/lobby_selector.dart +++ b/lib/pages/lobby_selector.dart @@ -4,17 +4,76 @@ import 'package:go_router/go_router.dart'; class LobbySelector extends StatelessWidget { const LobbySelector({super.key}); + final buttonStyle = const ButtonStyle(); + @override Widget build(BuildContext context) { return Scaffold( body: Center( - child: TextButton( - onPressed: () { - context.goNamed('prepareChessGame'); - }, - child: const Text('Random lobby'), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ElevatedButton( + onPressed: () { + context.push('/prepareRandom'); + }, + child: const Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.question_mark), + SizedBox( + width: 10, + ), + Text('Random') + ], + ), + ), + const SizedBox( + height: 25, + ), + ElevatedButton( + onPressed: () { + _dialogBuilder(context); + }, + child: const Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.lock), + SizedBox( + width: 10, + ), + Text('Private') + ], + ), + ), + ], ), ), ); } + + Future _dialogBuilder(BuildContext context) { + return showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('Host or join?'), + actions: [ + TextButton( + child: const Text('Host'), + onPressed: () { + context.push('/host'); + }, + ), + TextButton( + child: const Text('Join'), + onPressed: () { + context.push('/join'); + }, + ), + ], + ); + }, + ); + } } diff --git a/lib/pages/prepare_chess_game.dart b/lib/pages/prepare_chess_game.dart deleted file mode 100644 index 787b727..0000000 --- a/lib/pages/prepare_chess_game.dart +++ /dev/null @@ -1,96 +0,0 @@ -import 'dart:developer'; - -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; -import 'package:http/http.dart'; -import 'package:mchess/api/register.dart'; -import 'package:mchess/chess_bloc/chess_bloc.dart'; -import 'package:mchess/chess_bloc/chess_events.dart'; -import 'package:mchess/pages/chess_game.dart'; -import 'package:http/http.dart' as http; -import 'dart:convert'; - -class PrepareChessGameWidget extends StatefulWidget { - const PrepareChessGameWidget({super.key}); - - @override - State createState() => _PrepareChessGameWidgetState(); -} - -class _PrepareChessGameWidgetState extends State { - late Future randomGameResponse; - - @override - void initState() { - ChessBloc.getInstance().add(InitBoard()); - randomGameResponse = registerForRandomGame(); - super.initState(); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - body: FutureBuilder( - future: randomGameResponse, - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.done) { - log('Response from registering to random game ${snapshot.data}'); - - if (snapshot.data != null) { - return ChessGame( - playerID: snapshot.data!.playerID, - lobbyID: snapshot.data!.lobbyID, - ); - } - } - return const Center( - child: SizedBox( - height: 100, - width: 100, - child: CircularProgressIndicator(), - ), - ); - }, - ), - ); - } - - Future registerForRandomGame() async { - String addr; - if (kDebugMode) { - addr = 'http://localhost:8080/api/random'; - } else { - addr = 'https://chess.sw-gross.de:9999/api/random'; - } - - Response response; - - try { - response = await http - .get(Uri.parse(addr), headers: {"Accept": "application/json"}); - } catch (e) { - const snackBar = SnackBar( - backgroundColor: Colors.amberAccent, - content: - Text("mChess server is not responding. Try again or give up")); - - if (!context.mounted) return null; - - ScaffoldMessenger.of(context).clearSnackBars(); - ScaffoldMessenger.of(context).showSnackBar(snackBar); - - Future.delayed(const Duration(seconds: 2), () { - context.goNamed('lobbySelector'); - }); - - return null; - } - - if (response.statusCode == 200) { - log(response.body); - return ResponseFromRegisteringGame.fromJson(jsonDecode(response.body)); - } - return null; - } -} diff --git a/lib/pages/prepare_random_game.dart b/lib/pages/prepare_random_game.dart new file mode 100644 index 0000000..a2b9aaf --- /dev/null +++ b/lib/pages/prepare_random_game.dart @@ -0,0 +1,97 @@ +import 'dart:developer'; + +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; +import 'package:http/http.dart'; +import 'package:mchess/api/register.dart'; +import 'package:mchess/chess_bloc/chess_bloc.dart'; +import 'package:mchess/chess_bloc/chess_events.dart'; +import 'package:mchess/pages/chess_game.dart'; +import 'package:http/http.dart' as http; +import 'dart:convert'; + +class PrepareRandomGameWidget extends StatefulWidget { + const PrepareRandomGameWidget({super.key}); + + @override + State createState() => + _PrepareRandomGameWidgetState(); +} + +class _PrepareRandomGameWidgetState extends State { + late Future randomGameResponse; + + @override + void initState() { + ChessBloc.getInstance().add(InitBoard()); + + randomGameResponse = registerForRandomGame(); + + goToGameWhenResponseIsHere(randomGameResponse as Future); + + super.initState(); + } + + void goToGameWhenResponseIsHere(Future resp) { + resp.then((value) { + if (value == null) return; + context.push( + '/game', + extra: ChessGameArguments( + lobbyID: value.lobbyID!, + playerID: value.playerID!, + passphrase: value.passphrase), + ); + }); + } + + @override + Widget build(BuildContext context) { + return const Scaffold( + body: Center( + child: SizedBox( + height: 100, + width: 100, + child: CircularProgressIndicator(), + ), + ), + ); + } + + Future registerForRandomGame() async { + String addr; + Response response; + + if (kDebugMode) { + addr = 'http://localhost:8080/api/random'; + } else { + addr = 'https://chess.sw-gross.de:9999/api/random'; + } + + try { + response = await http + .get(Uri.parse(addr), headers: {"Accept": "application/json"}); + } catch (e) { + if (!context.mounted) return null; + + const snackBar = SnackBar( + backgroundColor: Colors.amberAccent, + content: Text("mChess server is not responding. Try again or give up"), + ); + Future.delayed(const Duration(seconds: 2), () { + ScaffoldMessenger.of(context).clearSnackBars(); + ScaffoldMessenger.of(context).showSnackBar(snackBar); + context.pop(); + }); + + return null; + } + + if (response.statusCode == 200) { + log(response.body); + return PlayerInfo.fromJson(jsonDecode(response.body)); + } + return null; + } +} diff --git a/lib/utils/chess_router.dart b/lib/utils/chess_router.dart index 5f5e4fd..e62cce1 100644 --- a/lib/utils/chess_router.dart +++ b/lib/utils/chess_router.dart @@ -1,6 +1,9 @@ import 'package:go_router/go_router.dart'; +import 'package:mchess/pages/chess_game.dart'; +import 'package:mchess/pages/join_game.dart'; import 'package:mchess/pages/lobby_selector.dart'; -import 'package:mchess/pages/prepare_chess_game.dart'; +import 'package:mchess/pages/host_game.dart'; +import 'package:mchess/pages/prepare_random_game.dart'; class ChessAppRouter { static final ChessAppRouter _instance = ChessAppRouter._internal(); @@ -19,11 +22,36 @@ class ChessAppRouter { builder: (context, state) => const LobbySelector(), ), GoRoute( - path: '/play', - name: 'prepareChessGame', + path: '/prepareRandom', + name: 'prepareRandom', builder: (context, state) { - return const PrepareChessGameWidget(); - }) + return const PrepareRandomGameWidget(); + }), + GoRoute( + path: '/host', + name: 'host', + builder: (context, state) { + return const HostGameWidget(); + }), + GoRoute( + path: '/join', + name: 'join', + builder: (context, state) { + return const JoinGameWidget(); + }), + GoRoute( + path: '/game', + name: 'game', + builder: (context, state) { + var args = state.extra as ChessGameArguments; + + return ChessGame( + lobbyID: args.lobbyID, + playerID: args.playerID, + passphrase: args.passphrase, + ); + }, + ) ], ); } diff --git a/lib/utils/widgets/server_log_widget.dart b/lib/utils/widgets/server_log_widget.dart index 84e3c21..8ac7416 100644 --- a/lib/utils/widgets/server_log_widget.dart +++ b/lib/utils/widgets/server_log_widget.dart @@ -1,10 +1,10 @@ import 'package:flutter/widgets.dart'; +import 'package:mchess/connection/ws_connection.dart'; class ServerLogWidget extends StatefulWidget { final Color textColor; - final String addString; - const ServerLogWidget(this.addString, {required this.textColor, super.key}); + const ServerLogWidget({required this.textColor, super.key}); @override State createState() => ServerLogWidgetState(); @@ -17,17 +17,11 @@ class ServerLogWidgetState extends State { @override Widget build(BuildContext context) { - log.add(widget.addString); - return SizedBox( - height: 200, - width: 200, - child: ListView( - children: [ - for (int i = 0; i < log.length; i++) - Text( - style: TextStyle(color: widget.textColor, fontSize: 20), log[i]) - ], - ), - ); + // return Container(); + return StreamBuilder( + stream: ServerConnection.getInstance().broadcast, + builder: (context, snapshot) { + return Container(); + }); } } diff --git a/test/widget_test.dart b/test/widget_test.dart index eaee974..5b8888c 100644 --- a/test/widget_test.dart +++ b/test/widget_test.dart @@ -15,6 +15,8 @@ void main() { // Build our app and trigger a frame. await tester.pumpWidget(ChessGame( playerID: UuidValue("test"), + lobbyID: UuidValue("testLobbyId"), + passphrase: 'test', )); // Verify that our counter starts at 0.