public async Task ReconnectTeam_TeamAndMemberName_ReturnsScrumTeamWithEstimationFinishedAndEstimationIsNull()
        {
            await using var fixture = new PlanningPokerSignalRClientFixture();

            var resultTask = fixture.Target.ReconnectTeam(PlanningPokerData.TeamName, PlanningPokerData.ScrumMasterName, fixture.CancellationToken);

            var sentMessage = await fixture.GetSentMessage();

            var invocationId = GetInvocationId(sentMessage);

            var estimationResult = PlanningPokerData.GetEstimationResult(scrumMasterEstimation: 8, memberEstimation: double.NaN);
            var scrumTeam        = PlanningPokerData.GetScrumTeam(member: true, state: TeamState.EstimationFinished, estimationResult: estimationResult);
            var reconnectResult  = PlanningPokerData.GetReconnectTeamResult(scrumTeam, lastMessageId: 2157483849, selectedEstimation: 8);
            var returnMessage    = new CompletionMessage(invocationId, null, reconnectResult, true);
            await fixture.ReceiveMessage(returnMessage);

            var result = await resultTask;

            Assert.AreEqual(reconnectResult, result);
            AssertAvailableEstimations(result.ScrumTeam);
            Assert.IsNotNull(result.SelectedEstimation);
            Assert.AreEqual(8.0, result.SelectedEstimation.Value);
            Assert.AreEqual(8.0, result.ScrumTeam.EstimationResult[0].Estimation.Value);
            Assert.IsNull(result.ScrumTeam.EstimationResult[1].Estimation);
        }
        public async Task GetMessages_LastMessageId_InvocationMessageIsSent()
        {
            await using var fixture = new PlanningPokerSignalRClientFixture();

            var resultTask = fixture.Target.GetMessages(PlanningPokerData.TeamName, PlanningPokerData.MemberName, 2157483849, fixture.CancellationToken);

            var sentMessage = await fixture.GetSentMessage();

            Assert.IsNotNull(sentMessage);
            Assert.IsInstanceOfType(sentMessage, typeof(InvocationMessage));
            var sentInvocationMessage = (InvocationMessage)sentMessage;

            Assert.AreEqual(RequestName, sentInvocationMessage.Target);
            var expectedArguments = new object[] { PlanningPokerData.TeamName, PlanningPokerData.MemberName, 2157483849L };

            CollectionAssert.AreEqual(expectedArguments, sentInvocationMessage.Arguments);

            var notifyMessage = new InvocationMessage(ResponseName, new object[] { new List <Message>() });
            await fixture.ReceiveMessage(notifyMessage);

            var returnMessage = new CompletionMessage(sentInvocationMessage.InvocationId, null, null, false);
            await fixture.ReceiveMessage(returnMessage);

            await resultTask;

            // Ensure asynchronous Dispose. Otherwise, Dispose is executed in OnNotify handler and it causes deadlock.
            await Task.Yield();
        }
        public async Task GetMessages_TeamAndMemberName_ReturnsEstimationEndedMessage()
        {
            await using var fixture = new PlanningPokerSignalRClientFixture();

            var resultTask = fixture.Target.GetMessages(PlanningPokerData.TeamName, PlanningPokerData.MemberName, 0, fixture.CancellationToken);

            var message = new EstimationResultMessage
            {
                Id               = 8,
                Type             = MessageType.EstimationEnded,
                EstimationResult = new List <EstimationResultItem>
                {
                    new EstimationResultItem
                    {
                        Member = new TeamMember {
                            Name = PlanningPokerData.ScrumMasterName, Type = PlanningPokerData.ScrumMasterType
                        },
                        Estimation = new Estimation {
                            Value = 2
                        }
                    },
                    new EstimationResultItem
                    {
                        Member = new TeamMember {
                            Name = PlanningPokerData.MemberName, Type = PlanningPokerData.MemberType
                        },
                        Estimation = new Estimation()
                    },
                    new EstimationResultItem
                    {
                        Member = new TeamMember {
                            Name = "Me", Type = PlanningPokerData.MemberType
                        }
                    },
                    new EstimationResultItem
                    {
                        Member = new TeamMember {
                            Name = PlanningPokerData.ObserverName, Type = PlanningPokerData.MemberType
                        },
                        Estimation = new Estimation {
                            Value = Estimation.PositiveInfinity
                        }
                    }
                }
            };

            await ProvideMessages(fixture, message);

            var result = await resultTask;
            await Task.Yield();

            Assert.AreEqual(1, result.Count);
            Assert.AreEqual(message, result[0]);
            var estimationResult = ((EstimationResultMessage)result[0]).EstimationResult;

            Assert.AreEqual(2.0, estimationResult[0].Estimation.Value);
            Assert.IsNull(estimationResult[1].Estimation.Value);
            Assert.IsNull(estimationResult[2].Estimation);
            Assert.IsTrue(double.IsPositiveInfinity(estimationResult[3].Estimation.Value.Value));
        }
        public async Task GetMessages_TeamAndMemberName_ReturnsEmptyMessage()
        {
            await using var fixture = new PlanningPokerSignalRClientFixture();

            var resultTask = fixture.Target.GetMessages(PlanningPokerData.TeamName, PlanningPokerData.MemberName, 0, fixture.CancellationToken);

            var message = new Message();

            await ProvideMessages(fixture, message);

            var result = await resultTask;
            await Task.Yield();

            Assert.AreEqual(1, result.Count);
            Assert.AreEqual(message, result[0]);
        }
        public async Task JoinTeam_ReturnsEmptyErrorMessage_PlanningPokerException()
        {
            await using var fixture = new PlanningPokerSignalRClientFixture();

            var resultTask = fixture.Target.JoinTeam(PlanningPokerData.TeamName, PlanningPokerData.MemberName, false, fixture.CancellationToken);

            var sentMessage = await fixture.GetSentMessage();

            var invocationId = GetInvocationId(sentMessage);

            var returnMessage = new CompletionMessage(invocationId, "An unexpected error occured. HubException: ", null, false);
            await fixture.ReceiveMessage(returnMessage);

            var exception = await Assert.ThrowsExceptionAsync <PlanningPokerException>(() => resultTask);

            Assert.AreEqual(string.Empty, exception.Message);
        }
        public async Task JoinTeam_TeamDoesNotExist_PlanningPokerException()
        {
            await using var fixture = new PlanningPokerSignalRClientFixture();

            var resultTask = fixture.Target.JoinTeam(PlanningPokerData.TeamName, PlanningPokerData.MemberName, false, fixture.CancellationToken);

            var sentMessage = await fixture.GetSentMessage();

            var invocationId = GetInvocationId(sentMessage);

            var returnMessage = new CompletionMessage(invocationId, "Team 'Test team' does not exist.", null, false);
            await fixture.ReceiveMessage(returnMessage);

            var exception = await Assert.ThrowsExceptionAsync <PlanningPokerException>(() => resultTask);

            Assert.AreEqual("Team 'Test team' does not exist.", exception.Message);
        }
        public async Task CreateTeam_TeamNameExists_PlanningPokerException()
        {
            await using var fixture = new PlanningPokerSignalRClientFixture();

            var resultTask = fixture.Target.CreateTeam(PlanningPokerData.TeamName, PlanningPokerData.ScrumMasterName, Deck.Standard, fixture.CancellationToken);

            var sentMessage = await fixture.GetSentMessage();

            var invocationId = GetInvocationId(sentMessage);

            var returnMessage = new CompletionMessage(invocationId, "An unexpected error occured. HubException: Team 'Test team' already exists.", null, false);
            await fixture.ReceiveMessage(returnMessage);

            var exception = await Assert.ThrowsExceptionAsync <PlanningPokerException>(() => resultTask);

            Assert.AreEqual("Team 'Test team' already exists.", exception.Message);
        }
        public async Task CreateTeam_TeamAndScrumMasterName_ReturnsScrumTeam()
        {
            await using var fixture = new PlanningPokerSignalRClientFixture();

            var resultTask = fixture.Target.CreateTeam(PlanningPokerData.TeamName, PlanningPokerData.ScrumMasterName, fixture.CancellationToken);

            var sentMessage = await fixture.GetSentMessage();

            var invocationId = GetInvocationId(sentMessage);

            var scrumTeam     = PlanningPokerData.GetScrumTeam();
            var returnMessage = new CompletionMessage(invocationId, null, scrumTeam, true);
            await fixture.ReceiveMessage(returnMessage);

            var result = await resultTask;

            Assert.AreEqual(scrumTeam, result);
            AssertAvailableEstimations(result);
        }
        private static async Task ProvideMessages(PlanningPokerSignalRClientFixture fixture, params Message[] messages)
        {
            var sentMessage = await fixture.GetSentMessage();

            Assert.IsNotNull(sentMessage);
            Assert.IsInstanceOfType(sentMessage, typeof(InvocationMessage));
            var sentInvocationMessage = (InvocationMessage)sentMessage;

            Assert.AreEqual(RequestName, sentInvocationMessage.Target);
            var expectedArguments = new object[] { PlanningPokerData.TeamName, PlanningPokerData.MemberName, 0L };

            CollectionAssert.AreEqual(expectedArguments, sentInvocationMessage.Arguments);

            var returnMessage = new CompletionMessage(sentInvocationMessage.InvocationId, null, null, false);
            await fixture.ReceiveMessage(returnMessage);

            var notifyMessage = new InvocationMessage(ResponseName, new object[] { messages.ToList() });
            await fixture.ReceiveMessage(notifyMessage);
        }
        public async Task JoinTeam_TeamAndObserverName_ReturnsScrumTeam()
        {
            await using var fixture = new PlanningPokerSignalRClientFixture();

            var resultTask = fixture.Target.JoinTeam(PlanningPokerData.TeamName, PlanningPokerData.ObserverName, false, fixture.CancellationToken);

            var sentMessage = await fixture.GetSentMessage();

            var invocationId = GetInvocationId(sentMessage);

            var scrumTeam     = PlanningPokerData.GetScrumTeam(observer: true);
            var teamResult    = PlanningPokerData.GetTeamResult(scrumTeam);
            var returnMessage = new CompletionMessage(invocationId, null, teamResult, true);
            await fixture.ReceiveMessage(returnMessage);

            var result = await resultTask;

            Assert.AreEqual(teamResult, result);
            AssertAvailableEstimations(result.ScrumTeam);
        }
        public async Task JoinTeam_TeamAndMemberName_ReturnsScrumTeamWithEstimationInProgress()
        {
            await using var fixture = new PlanningPokerSignalRClientFixture();

            var resultTask = fixture.Target.JoinTeam(PlanningPokerData.TeamName, PlanningPokerData.MemberName, false, fixture.CancellationToken);

            var sentMessage = await fixture.GetSentMessage();

            var invocationId = GetInvocationId(sentMessage);

            var estimationParticipants = PlanningPokerData.GetEstimationParticipants();
            var scrumTeam     = PlanningPokerData.GetScrumTeam(member: true, state: TeamState.EstimationInProgress, estimationParticipants: estimationParticipants);
            var returnMessage = new CompletionMessage(invocationId, null, scrumTeam, true);
            await fixture.ReceiveMessage(returnMessage);

            var result = await resultTask;

            Assert.AreEqual(scrumTeam, result);
            AssertAvailableEstimations(result);
        }
        public async Task DisconnectTeam_TeamNameAndMemberName_InvocationMessageIsSent()
        {
            await using var fixture = new PlanningPokerSignalRClientFixture();

            var resultTask = fixture.Target.DisconnectTeam(PlanningPokerData.TeamName, PlanningPokerData.MemberName, fixture.CancellationToken);

            var sentMessage = await fixture.GetSentMessage();

            var sentInvocationMessage = AssertIsInvocationMessage(sentMessage);

            Assert.AreEqual("DisconnectTeam", sentInvocationMessage.Target);
            var expectedArguments = new object[] { PlanningPokerData.TeamName, PlanningPokerData.MemberName };

            CollectionAssert.AreEqual(expectedArguments, sentInvocationMessage.Arguments);

            var returnMessage = new CompletionMessage(sentInvocationMessage.InvocationId, null, null, false);
            await fixture.ReceiveMessage(returnMessage);

            await resultTask;
        }
        public async Task SubmitEstimation_EstimationValue_InvocationMessageIsSent(string memberName, double?estimation, double?expectedSentValue)
        {
            await using var fixture = new PlanningPokerSignalRClientFixture();

            var resultTask = fixture.Target.SubmitEstimation(PlanningPokerData.TeamName, memberName, estimation, fixture.CancellationToken);

            var sentMessage = await fixture.GetSentMessage();

            var sentInvocationMessage = AssertIsInvocationMessage(sentMessage);

            Assert.AreEqual("SubmitEstimation", sentInvocationMessage.Target);
            var expectedArguments = new object[] { PlanningPokerData.TeamName, memberName, expectedSentValue };

            CollectionAssert.AreEqual(expectedArguments, sentInvocationMessage.Arguments);

            var returnMessage = new CompletionMessage(sentInvocationMessage.InvocationId, null, null, false);
            await fixture.ReceiveMessage(returnMessage);

            await resultTask;
        }
        public async Task ReconnectTeam_TeamAndMemberName_ReturnsScrumTeam()
        {
            await using var fixture = new PlanningPokerSignalRClientFixture();

            var resultTask = fixture.Target.ReconnectTeam(PlanningPokerData.TeamName, PlanningPokerData.MemberName, fixture.CancellationToken);

            var sentMessage = await fixture.GetSentMessage();

            var invocationId = GetInvocationId(sentMessage);

            var scrumTeam       = PlanningPokerData.GetScrumTeam(member: true);
            var reconnectResult = PlanningPokerData.GetReconnectTeamResultJson(scrumTeam);
            var returnMessage   = new CompletionMessage(invocationId, null, reconnectResult, true);
            await fixture.ReceiveMessage(returnMessage);

            var result = await resultTask;

            Assert.AreEqual(reconnectResult, result);
            AssertAvailableEstimations(result.ScrumTeam);
            Assert.IsNull(reconnectResult.SelectedEstimation);
        }
        public async Task JoinTeam_TeamNameAndObserverName_InvocationMessageIsSent()
        {
            await using var fixture = new PlanningPokerSignalRClientFixture();

            var resultTask = fixture.Target.JoinTeam(PlanningPokerData.TeamName, PlanningPokerData.ObserverName, true, fixture.CancellationToken);

            var sentMessage = await fixture.GetSentMessage();

            var sentInvocationMessage = AssertIsInvocationMessage(sentMessage);

            Assert.AreEqual("JoinTeam", sentInvocationMessage.Target);
            var expectedArguments = new object[] { PlanningPokerData.TeamName, PlanningPokerData.ObserverName, true };

            CollectionAssert.AreEqual(expectedArguments, sentInvocationMessage.Arguments);

            var scrumTeam     = PlanningPokerData.GetScrumTeam(observer: true);
            var returnMessage = new CompletionMessage(sentInvocationMessage.InvocationId, null, scrumTeam, true);
            await fixture.ReceiveMessage(returnMessage);

            await resultTask;
        }
        public async Task JoinTeam_TeamAndMemberName_ReturnsScrumTeamWithEstimationCanceled()
        {
            await using var fixture = new PlanningPokerSignalRClientFixture();

            var resultTask = fixture.Target.JoinTeam(PlanningPokerData.TeamName, PlanningPokerData.MemberName, false, fixture.CancellationToken);

            var sentMessage = await fixture.GetSentMessage();

            var invocationId = GetInvocationId(sentMessage);

            var estimationResult = PlanningPokerData.GetEstimationResult(scrumMasterEstimation: 0, memberEstimation: double.NaN);
            var scrumTeam        = PlanningPokerData.GetScrumTeam(member: true, state: TeamState.EstimationCanceled, estimationResult: estimationResult);
            var returnMessage    = new CompletionMessage(invocationId, null, scrumTeam, true);
            await fixture.ReceiveMessage(returnMessage);

            var result = await resultTask;

            Assert.AreEqual(scrumTeam, result);
            AssertAvailableEstimations(result);
            Assert.AreEqual(0.0, result.EstimationResult[0].Estimation.Value);
            Assert.IsNull(result.EstimationResult[1].Estimation);
        }
        public async Task CreateTeam_TeamNameAndScrumMaster_InvocationMessageIsSent(Deck deck)
        {
            await using var fixture = new PlanningPokerSignalRClientFixture();

            var resultTask = fixture.Target.CreateTeam(PlanningPokerData.TeamName, PlanningPokerData.ScrumMasterName, deck, fixture.CancellationToken);

            var sentMessage = await fixture.GetSentMessage();

            var sentInvocationMessage = AssertIsInvocationMessage(sentMessage);

            Assert.AreEqual("CreateTeam", sentInvocationMessage.Target);
            var expectedArguments = new object[] { PlanningPokerData.TeamName, PlanningPokerData.ScrumMasterName, deck };

            CollectionAssert.AreEqual(expectedArguments, sentInvocationMessage.Arguments);

            var scrumTeam     = PlanningPokerData.GetScrumTeam();
            var teamResult    = PlanningPokerData.GetTeamResult(scrumTeam);
            var returnMessage = new CompletionMessage(sentInvocationMessage.InvocationId, null, teamResult, true);
            await fixture.ReceiveMessage(returnMessage);

            await resultTask;
        }
        public async Task GetMessages_TeamAndMemberName_ReturnsMemberDisconnectedMessage()
        {
            await using var fixture = new PlanningPokerSignalRClientFixture();

            var resultTask = fixture.Target.GetMessages(PlanningPokerData.TeamName, PlanningPokerData.MemberName, 0, fixture.CancellationToken);

            var message = new MemberMessage
            {
                Id     = 2,
                Type   = MessageType.MemberDisconnected,
                Member = new TeamMember {
                    Name = PlanningPokerData.ObserverName, Type = PlanningPokerData.ObserverType
                }
            };

            await ProvideMessages(fixture, message);

            var result = await resultTask;
            await Task.Yield();

            Assert.AreEqual(1, result.Count);
            Assert.AreEqual(message, result[0]);
        }
        public async Task ReconnectTeam_TeamAndMemberName_ReturnsScrumTeamWithEstimationInProgress()
        {
            await using var fixture = new PlanningPokerSignalRClientFixture();

            var resultTask = fixture.Target.ReconnectTeam(PlanningPokerData.TeamName, PlanningPokerData.ScrumMasterName, fixture.CancellationToken);

            var sentMessage = await fixture.GetSentMessage();

            var invocationId = GetInvocationId(sentMessage);

            var estimationParticipants = PlanningPokerData.GetEstimationParticipants(scrumMaster: false, member: true);
            var scrumTeam       = PlanningPokerData.GetScrumTeam(member: true, state: TeamState.EstimationInProgress, estimationParticipants: estimationParticipants);
            var reconnectResult = PlanningPokerData.GetReconnectTeamResult(scrumTeam, lastMessageId: 1, selectedEstimation: null);
            var returnMessage   = new CompletionMessage(invocationId, null, reconnectResult, true);
            await fixture.ReceiveMessage(returnMessage);

            var result = await resultTask;

            Assert.AreEqual(reconnectResult, result);
            AssertAvailableEstimations(result.ScrumTeam);
            Assert.IsNotNull(result.SelectedEstimation);
            Assert.IsNull(result.SelectedEstimation.Value);
        }
        public async Task JoinTeam_TeamAndMemberName_ReturnsScrumTeamWithEstimationFinishedAndEstimationIsInfinity()
        {
            await using var fixture = new PlanningPokerSignalRClientFixture();

            var resultTask = fixture.Target.JoinTeam(PlanningPokerData.TeamName, PlanningPokerData.MemberName, false, fixture.CancellationToken);

            var sentMessage = await fixture.GetSentMessage();

            var invocationId = GetInvocationId(sentMessage);

            var estimationResult = PlanningPokerData.GetEstimationResult(scrumMasterEstimation: Estimation.PositiveInfinity, memberEstimation: null);
            var scrumTeam        = PlanningPokerData.GetScrumTeam(member: true, observer: true, state: TeamState.EstimationFinished, estimationResult: estimationResult);
            var teamResult       = PlanningPokerData.GetTeamResult(scrumTeam);
            var returnMessage    = new CompletionMessage(invocationId, null, teamResult, true);
            await fixture.ReceiveMessage(returnMessage);

            var result = await resultTask;

            Assert.AreEqual(teamResult, result);
            AssertAvailableEstimations(result.ScrumTeam);
            Assert.IsTrue(double.IsPositiveInfinity(result.ScrumTeam.EstimationResult[0].Estimation.Value.Value));
            Assert.IsNull(result.ScrumTeam.EstimationResult[1].Estimation.Value);
        }
        public async Task GetMessages_TeamAndMemberName_Returns3Messages()
        {
            await using var fixture = new PlanningPokerSignalRClientFixture();

            var resultTask = fixture.Target.GetMessages(PlanningPokerData.TeamName, PlanningPokerData.MemberName, 0, fixture.CancellationToken);

            var estimationStartedMessage = new Message
            {
                Id   = 8,
                Type = MessageType.EstimationStarted
            };
            var memberEstimatedMessage = new MemberMessage
            {
                Id     = 9,
                Type   = MessageType.MemberEstimated,
                Member = new TeamMember {
                    Name = PlanningPokerData.ScrumMasterName, Type = PlanningPokerData.ScrumMasterType
                }
            };
            var estimationEndedMessage = new EstimationResultMessage
            {
                Id               = 10,
                Type             = MessageType.MemberEstimated,
                EstimationResult = new List <EstimationResultItem>
                {
                    new EstimationResultItem
                    {
                        Member = new TeamMember {
                            Name = PlanningPokerData.ScrumMasterName, Type = PlanningPokerData.ScrumMasterType
                        },
                        Estimation = new Estimation {
                            Value = 5
                        }
                    },
                    new EstimationResultItem
                    {
                        Member = new TeamMember {
                            Name = PlanningPokerData.MemberName, Type = PlanningPokerData.MemberType
                        },
                        Estimation = new Estimation {
                            Value = 40
                        }
                    }
                }
            };

            await ProvideMessages(fixture, estimationStartedMessage, memberEstimatedMessage, estimationEndedMessage);

            var result = await resultTask;
            await Task.Yield();

            Assert.AreEqual(3, result.Count);
            Assert.AreEqual(estimationStartedMessage, result[0]);
            Assert.AreEqual(memberEstimatedMessage, result[1]);
            Assert.AreEqual(estimationEndedMessage, result[2]);

            var estimationResult = ((EstimationResultMessage)result[2]).EstimationResult;

            Assert.AreEqual(5.0, estimationResult[0].Estimation.Value);
            Assert.AreEqual(40.0, estimationResult[1].Estimation.Value);
        }