public async void Cancel_UserCancelsRequest_DeletesFriendship()
        {
            Friendship received = new Friendship
            {
                ReceiverId = member.UserId,
                Receiver = member,
                RequesterId = otherMember1.UserId,
                Requester = otherMember1,
                RequestStatus = FriendshipRequestStatus.Pending
            };

            Mock<IVeilDataAccess> dbStub = TestHelpers.GetVeilDataAccessFake();

            Mock<DbSet<Member>> memberDbSetStub = TestHelpers.GetFakeAsyncDbSet(new List<Member> { member, otherMember1 }.AsQueryable());
            memberDbSetStub.Setup(db => db.FindAsync(member.UserId)).ReturnsAsync(member);

            Mock<DbSet<Friendship>> friendshipDbSetStub = TestHelpers.GetFakeAsyncDbSet(new List<Friendship> { received }.AsQueryable());
            friendshipDbSetStub.Setup(db => db.Remove(It.IsAny<Friendship>())).Verifiable();

            dbStub.Setup(db => db.Members).Returns(memberDbSetStub.Object);
            dbStub.Setup(db => db.Friendships).Returns(friendshipDbSetStub.Object);

            Mock<ControllerContext> context = new Mock<ControllerContext>();
            context.Setup(c => c.HttpContext.User.Identity).Returns<IIdentity>(null);
            context.Setup(c => c.HttpContext.User.Identity.IsAuthenticated).Returns(true);

            Mock<IGuidUserIdGetter> idGetterStub = new Mock<IGuidUserIdGetter>();
            idGetterStub.Setup(id => id.GetUserId(It.IsAny<IIdentity>())).Returns(member.UserId);

            FriendListController controller = new FriendListController(dbStub.Object, idGetterStub.Object)
            {
                ControllerContext = context.Object
            };

            await controller.Cancel(otherMember1.UserId);

            Assert.That(
                () =>
                    friendshipDbSetStub.Verify(db => db.Remove(It.IsAny<Friendship>()),
                    Times.Exactly(1)),
                Throws.Nothing);
        }
        public async void AddFriendRequest_AddRequestedNotAcceptedYet_NothingChanged()
        {
            Friendship friendship = new Friendship
            {
                RequesterId = member.UserId,
                Requester = member,
                ReceiverId = otherMember1.UserId,
                Receiver = otherMember1,
                RequestStatus = FriendshipRequestStatus.Pending
            };

            Mock<IVeilDataAccess> dbStub = TestHelpers.GetVeilDataAccessFake();

            Mock<DbSet<Member>> memberDbSetStub = TestHelpers.GetFakeAsyncDbSet(new List<Member> { member, otherMember1 }.AsQueryable());
            memberDbSetStub.Setup(db => db.FindAsync(member.UserId)).ReturnsAsync(member);

            Mock<DbSet<Friendship>> friendshipDbSetStub = TestHelpers.GetFakeAsyncDbSet(new List<Friendship> { friendship }.AsQueryable());
            friendshipDbSetStub.Setup(db => db.Add(It.IsAny<Friendship>())).Returns<Friendship>(i => i).Verifiable();

            dbStub.Setup(db => db.Members).Returns(memberDbSetStub.Object);
            dbStub.Setup(db => db.Friendships).Returns(friendshipDbSetStub.Object);

            Mock<ControllerContext> context = new Mock<ControllerContext>();
            context.Setup(c => c.HttpContext.User.Identity).Returns<IIdentity>(null);
            context.Setup(c => c.HttpContext.User.Identity.IsAuthenticated).Returns(true);

            Mock<IGuidUserIdGetter> idGetterStub = new Mock<IGuidUserIdGetter>();
            idGetterStub.Setup(id => id.GetUserId(It.IsAny<IIdentity>())).Returns(member.UserId);

            FriendListController controller = new FriendListController(dbStub.Object, idGetterStub.Object)
            {
                ControllerContext = context.Object
            };

            await controller.AddFriendRequest(otherMember1.UserAccount.UserName);

            Assert.That(
                () =>
                    friendshipDbSetStub.Verify(db => db.Add(It.IsAny<Friendship>()),
                    Times.Never),
                Throws.Nothing);
            Assert.That(
                () =>
                    dbStub.Verify(db => db.SaveChangesAsync(),
                    Times.Never),
                Throws.Nothing);
        }
        public async void Index_MemberViewsFriendList_OneRequestedOneReceivedOneFriend_ReturnsCorrectViewModel()
        {
            Friendship requested = new Friendship()
            {
                ReceiverId = otherMember1.UserId,
                RequesterId = member.UserId,
                RequestStatus = FriendshipRequestStatus.Pending
            };

            Friendship received = new Friendship()
            {
                ReceiverId = member.UserId,
                RequesterId = otherMember2.UserId,
                RequestStatus = FriendshipRequestStatus.Pending
            };

            Friendship friend = new Friendship()
            {
                ReceiverId = member.UserId,
                RequesterId = otherMember3.UserId,
                RequestStatus = FriendshipRequestStatus.Accepted
            };

            member.RequestedFriendships.Add(requested);
            member.ReceivedFriendships.Add(received);
            member.ReceivedFriendships.Add(friend);

            Mock<IVeilDataAccess> dbStub = TestHelpers.GetVeilDataAccessFake();

            Mock<DbSet<Member>> memberDbSetStub = TestHelpers.GetFakeAsyncDbSet(new List<Member> { member }.AsQueryable());
            memberDbSetStub.Setup(db => db.FindAsync(member.UserId)).ReturnsAsync(member);
            memberDbSetStub.SetupForInclude();

            dbStub.Setup(db => db.Members).Returns(memberDbSetStub.Object);

            Mock<ControllerContext> context = new Mock<ControllerContext>();
            context.Setup(c => c.HttpContext.User.Identity).Returns<IIdentity>(null);
            context.Setup(c => c.HttpContext.User.Identity.IsAuthenticated).Returns(true);

            Mock<IGuidUserIdGetter> idGetterStub = new Mock<IGuidUserIdGetter>();
            idGetterStub.Setup(id => id.GetUserId(It.IsAny<IIdentity>())).Returns(member.UserId);

            FriendListController controller = new FriendListController(dbStub.Object, idGetterStub.Object)
            {
                ControllerContext = context.Object
            };

            var result = await controller.Index() as ViewResult;

            Assert.That(result.Model != null);

            var model = (FriendsListViewModel)result.Model;

            Assert.That(model.PendingSentFriendships.Count == 1);
            Assert.That(model.PendingReceivedFriendships.Count == 1);
            Assert.That(model.ConfirmedFriends.Count == 1);
        }
        public async void AddFriendRequest_AddFriendIncorrectUsername_DoesntAddFriendship()
        {
            Mock<IVeilDataAccess> dbStub = TestHelpers.GetVeilDataAccessFake();

            Mock<DbSet<Member>> memberDbSetStub = TestHelpers.GetFakeAsyncDbSet(new List<Member> { member }.AsQueryable());
            memberDbSetStub.Setup(db => db.FindAsync(member.UserId)).ReturnsAsync(member);

            Mock<DbSet<Friendship>> friendshipDbSetStub = TestHelpers.GetFakeAsyncDbSet(new List<Friendship>().AsQueryable());

            dbStub.Setup(db => db.Members).Returns(memberDbSetStub.Object);
            dbStub.Setup(db => db.Friendships).Returns(friendshipDbSetStub.Object);

            Mock<ControllerContext> context = new Mock<ControllerContext>();
            context.Setup(c => c.HttpContext.User.Identity).Returns<IIdentity>(null);
            context.Setup(c => c.HttpContext.User.Identity.IsAuthenticated).Returns(true);

            Mock<IGuidUserIdGetter> idGetterStub = new Mock<IGuidUserIdGetter>();
            idGetterStub.Setup(id => id.GetUserId(It.IsAny<IIdentity>())).Returns(member.UserId);

            FriendListController controller = new FriendListController(dbStub.Object, idGetterStub.Object)
            {
                ControllerContext = context.Object
            };


            Friendship friend = new Friendship()
            {
                ReceiverId = member.UserId,
                RequesterId = otherMember1.UserId,
                RequestStatus = FriendshipRequestStatus.Pending
            };

            dbStub.Setup(db => db.Friendships.Add(friend)).Verifiable();

            //otherMember1 isn't in the mocked db
            await controller.AddFriendRequest(otherMember1.UserAccount.UserName);

            Assert.That(
                () =>
                    dbStub.Verify(db => db.Friendships.Add(friend),
                    Times.Never),
                Throws.Nothing);
        }
        public async Task<ActionResult> AddFriendRequest(string username)
        {
            Guid currentMemberGuid = idGetter.GetUserId(User.Identity);

            Member currentUser = await db.Members
                .Where(m => m.UserId == currentMemberGuid)
                .FirstOrDefaultAsync();

            Member targetUser = await db.Members
                .Where(m => m.UserAccount.UserName == username)
                .FirstOrDefaultAsync();

            if (currentUser == targetUser)
            {
                this.AddAlert(AlertType.Error, "Cannot add yourself as a friend.");

                return RedirectToAction("Index");
            }

            if (targetUser == null)
            {
                this.AddAlert(AlertType.Error, $"No member with the username '{username}' exists.");

                return RedirectToAction("Index");
            }

            Friendship existingFriendship = await db.Friendships
                .Where(
                    f =>
                        (f.Requester.UserId == currentUser.UserId && f.Receiver.UserId == targetUser.UserId) ||
                            (f.Requester.UserId == targetUser.UserId &&
                                f.Receiver.UserId == currentUser.UserId))
                .FirstOrDefaultAsync();

            if (existingFriendship == null)
            {
                Friendship friendship = new Friendship()
                {
                    RequesterId = currentUser.UserId,
                    ReceiverId = targetUser.UserId,
                    RequestStatus = FriendshipRequestStatus.Pending
                };

                db.Friendships.Add(friendship);
                await db.SaveChangesAsync();

                this.AddAlert(AlertType.Success, $"Request sent to {targetUser.UserAccount.UserName}.");
            }
            else if (existingFriendship.RequestStatus == FriendshipRequestStatus.Accepted)
            {
                this.AddAlert(
                    AlertType.Info, $"You are already friends with {targetUser.UserAccount.UserName}.");
            }
            else if (existingFriendship.Requester == currentUser)
            {
                this.AddAlert(
                    AlertType.Info, $"Request already sent to {targetUser.UserAccount.UserName}.");
            }
            else if (existingFriendship.Receiver == currentUser)
            {
                existingFriendship.RequestStatus = FriendshipRequestStatus.Accepted;

                await db.SaveChangesAsync();

                this.AddAlert(
                    AlertType.Success, $"Request from {targetUser.UserAccount.UserName} approved.");
            }

            return RedirectToAction("Index");
        }