@@ -236,6 +236,114 @@ public async Task CancelGameAsync_Should_TrackActivity()
236236 Assert . True ( stopActivityReceived ) ;
237237 }
238238
239+ [ Fact ]
240+ public async Task RevealGameAsync_Should_CancelAndReturnGameInfo ( )
241+ {
242+ // Arrange
243+ ( var httpClient , var handlerMock ) = GetHttpClientForRevealGame ( ) ;
244+ GamesClient gamesClient = new ( httpClient , NullLogger < GamesClient > . Instance ) ;
245+ var gameId = Guid . Parse ( "91f3c729-5e6e-459a-b656-2d77f3f45dd9" ) ;
246+
247+ // Act
248+ var game = await gamesClient . RevealGameAsync ( gameId , "test" , GameType . Game6x4 , TestContext . Current . CancellationToken ) ;
249+
250+ // Assert
251+ Assert . NotNull ( game ) ;
252+ Assert . Equal ( gameId , game . Id ) ;
253+ Assert . Equal ( "Game6x4" , game . GameType ) ;
254+ Assert . Equal ( "test" , game . PlayerName ) ;
255+ Assert . Equal ( 1 , game . LastMoveNumber ) ;
256+ Assert . Equal ( 4 , game . NumberCodes ) ;
257+ Assert . Equal ( 12 , game . MaxMoves ) ;
258+ Assert . False ( game . IsVictory ) ;
259+ Assert . NotNull ( game . Codes ) ;
260+ Assert . NotEmpty ( game . Codes ) ;
261+ Assert . NotNull ( game . Moves ) ;
262+ Assert . Single ( game . Moves ) ;
263+
264+ handlerMock . Protected ( ) . Verify (
265+ "SendAsync" ,
266+ Times . Exactly ( 2 ) , // PATCH and GET
267+ ItExpr . IsAny < HttpRequestMessage > ( ) ,
268+ ItExpr . IsAny < CancellationToken > ( ) ) ;
269+ }
270+
271+ [ Fact ]
272+ public async Task RevealGameAsync_Should_TrackActivity ( )
273+ {
274+ // Arrange
275+ ( var httpClient , var handlerMock ) = GetHttpClientForRevealGame ( ) ;
276+ bool startActivityReceived = false ;
277+ bool stopActivityReceived = false ;
278+ bool revealedEventReceived = false ;
279+ var gameId = Guid . Parse ( "91f3c729-5e6e-459a-b656-2d77f3f45dd9" ) ;
280+
281+ using ActivityListener listener = new ( )
282+ {
283+ ShouldListenTo = _ => true ,
284+ ActivityStarted = activity =>
285+ {
286+ if ( activity . OperationName == "RevealGameAsync" )
287+ {
288+ startActivityReceived = true ;
289+ Assert . Equal ( ActivityKind . Client , activity . Kind ) ;
290+ }
291+ } ,
292+ ActivityStopped = activity =>
293+ {
294+ if ( activity . OperationName == "RevealGameAsync" )
295+ {
296+ stopActivityReceived = true ;
297+ ActivityEvent ? revealedEvent = activity . Events . FirstOrDefault ( e => e . Name == "GameRevealed" ) ;
298+ if ( revealedEvent != null )
299+ {
300+ revealedEventReceived = true ;
301+ var tag = revealedEvent . Value . Tags . FirstOrDefault ( t => t . Key == "gameId" ) ;
302+ Assert . Equal ( gameId . ToString ( ) , tag . Value ) ;
303+ }
304+ Assert . Equal ( ActivityKind . Client , activity . Kind ) ;
305+ }
306+ } ,
307+ Sample = ( ref ActivityCreationOptions < ActivityContext > _ ) => ActivitySamplingResult . AllData
308+ } ;
309+ ActivitySource . AddActivityListener ( listener ) ;
310+ GamesClient gamesClient = new ( httpClient , NullLogger < GamesClient > . Instance ) ;
311+
312+ // Act
313+ await gamesClient . RevealGameAsync ( gameId , "test" , GameType . Game6x4 , TestContext . Current . CancellationToken ) ;
314+
315+ // Assert
316+ Assert . True ( startActivityReceived ) ;
317+ Assert . True ( stopActivityReceived ) ;
318+ Assert . True ( revealedEventReceived ) ;
319+ }
320+
321+ [ Fact ]
322+ public async Task RevealGameAsync_Should_Throw_OnPatchError ( )
323+ {
324+ // Arrange
325+ ( var httpClient , var handlerMock ) = GetHttpClientForRevealGame ( patchFails : true ) ;
326+ GamesClient gamesClient = new ( httpClient , NullLogger < GamesClient > . Instance ) ;
327+ var gameId = Guid . Parse ( "91f3c729-5e6e-459a-b656-2d77f3f45dd9" ) ;
328+
329+ // Act & Assert
330+ await Assert . ThrowsAsync < HttpRequestException > ( ( ) =>
331+ gamesClient . RevealGameAsync ( gameId , "test" , GameType . Game6x4 , TestContext . Current . CancellationToken ) ) ;
332+ }
333+
334+ [ Fact ]
335+ public async Task RevealGameAsync_Should_Throw_OnGetError ( )
336+ {
337+ // Arrange
338+ ( var httpClient , var handlerMock ) = GetHttpClientForRevealGame ( getFails : true ) ;
339+ GamesClient gamesClient = new ( httpClient , NullLogger < GamesClient > . Instance ) ;
340+ var gameId = Guid . Parse ( "91f3c729-5e6e-459a-b656-2d77f3f45dd9" ) ;
341+
342+ // Act & Assert
343+ await Assert . ThrowsAsync < HttpRequestException > ( ( ) =>
344+ gamesClient . RevealGameAsync ( gameId , "test" , GameType . Game6x4 , TestContext . Current . CancellationToken ) ) ;
345+ }
346+
239347 private static ( HttpClient Client , Mock < HttpMessageHandler > Handler ) GetHttpClientReturningACreatedGameSkeleton ( )
240348 {
241349 Mock < IConfiguration > configMock = new ( ) ;
@@ -564,4 +672,112 @@ private static (HttpClient Client, Mock<HttpMessageHandler> Handler) GetHttpClie
564672 BaseAddress = new Uri ( configMock . Object [ "GameAPIs" ] ?? throw new InvalidOperationException ( ) )
565673 } , handlerMock ) ;
566674 }
675+
676+ private static ( HttpClient Client , Mock < HttpMessageHandler > Handler ) GetHttpClientForRevealGame ( bool patchFails = false , bool getFails = false )
677+ {
678+ Mock < IConfiguration > configMock = new ( ) ;
679+ configMock . Setup ( x => x [ It . IsAny < string > ( ) ] ) . Returns ( "http://localhost:5000" ) ;
680+ Mock < HttpMessageHandler > handlerMock = new ( MockBehavior . Strict ) ;
681+ var gameId = "91f3c729-5e6e-459a-b656-2d77f3f45dd9" ;
682+ string getReturnMessage = """
683+ {
684+ "id": "91f3c729-5e6e-459a-b656-2d77f3f45dd9",
685+ "gameType": "Game6x4",
686+ "playerName": "test",
687+ "playerIsAuthenticated": false,
688+ "startTime": "2024-02-14T18:14:49.4420411Z",
689+ "endTime": "2024-02-14T18:20:00.0000000Z",
690+ "duration": "00:05:10.0000000",
691+ "lastMoveNumber": 1,
692+ "numberCodes": 4,
693+ "maxMoves": 12,
694+ "isVictory": false,
695+ "fieldValues": {
696+ "colors": [
697+ "Red",
698+ "Green",
699+ "Blue",
700+ "Yellow",
701+ "Purple",
702+ "Orange"
703+ ]
704+ },
705+ "codes": [
706+ "Yellow",
707+ "Yellow",
708+ "Green",
709+ "Green"
710+ ],
711+ "moves": [
712+ {
713+ "id": "963baba8-44b8-45e5-81f3-193959ae5bf6",
714+ "moveNumber": 1,
715+ "guessPegs": [
716+ "Red",
717+ "Green",
718+ "Blue",
719+ "Yellow"
720+ ],
721+ "keyPegs": [
722+ "White",
723+ "White"
724+ ]
725+ }
726+ ]
727+ }
728+ """ ;
729+ if ( ! patchFails )
730+ {
731+ handlerMock . Protected ( )
732+ . Setup < Task < HttpResponseMessage > > (
733+ "SendAsync" ,
734+ ItExpr . Is < HttpRequestMessage > ( req => req . Method == HttpMethod . Patch ) ,
735+ ItExpr . IsAny < CancellationToken > ( ) )
736+ . ReturnsAsync ( new HttpResponseMessage
737+ {
738+ StatusCode = HttpStatusCode . OK
739+ } ) . Verifiable ( ) ;
740+ }
741+ else
742+ {
743+ handlerMock . Protected ( )
744+ . Setup < Task < HttpResponseMessage > > (
745+ "SendAsync" ,
746+ ItExpr . Is < HttpRequestMessage > ( req => req . Method == HttpMethod . Patch ) ,
747+ ItExpr . IsAny < CancellationToken > ( ) )
748+ . ReturnsAsync ( new HttpResponseMessage
749+ {
750+ StatusCode = HttpStatusCode . BadRequest
751+ } ) . Verifiable ( ) ;
752+ }
753+ if ( ! getFails )
754+ {
755+ handlerMock . Protected ( )
756+ . Setup < Task < HttpResponseMessage > > (
757+ "SendAsync" ,
758+ ItExpr . Is < HttpRequestMessage > ( req => req . Method == HttpMethod . Get ) ,
759+ ItExpr . IsAny < CancellationToken > ( ) )
760+ . ReturnsAsync ( new HttpResponseMessage
761+ {
762+ StatusCode = HttpStatusCode . OK ,
763+ Content = new StringContent ( getReturnMessage , Encoding . UTF8 , "application/json" )
764+ } ) . Verifiable ( ) ;
765+ }
766+ else
767+ {
768+ handlerMock . Protected ( )
769+ . Setup < Task < HttpResponseMessage > > (
770+ "SendAsync" ,
771+ ItExpr . Is < HttpRequestMessage > ( req => req . Method == HttpMethod . Get ) ,
772+ ItExpr . IsAny < CancellationToken > ( ) )
773+ . ReturnsAsync ( new HttpResponseMessage
774+ {
775+ StatusCode = HttpStatusCode . NotFound
776+ } ) . Verifiable ( ) ;
777+ }
778+ return ( new ( handlerMock . Object )
779+ {
780+ BaseAddress = new Uri ( configMock . Object [ "GameAPIs" ] ?? throw new InvalidOperationException ( ) )
781+ } , handlerMock ) ;
782+ }
567783}
0 commit comments