예제 #1
0
파일: Cast.cs 프로젝트: n1ghtmare/Kauntr
        public async Task VoteWithCountdownIdThatDoesntExist_VoteIsAdded() {
            var voteService = TestableVoteService.Create();

            voteService.MockCountdownRepository
                       .Setup(x => x.GetByIdAsync(TestableVoteService.CountdownId))
                       .Returns(Task.FromResult(new Countdown {
                           Description = "Test description",
                           Id = TestableVoteService.CountdownId
                       }));

            var vote = new Vote {
                CountdownId = TestableVoteService.CountdownId,
                CastedById = TestableVoteService.AccountId,
                CastedOn = DateTime.UtcNow,
                Value = 1
            };

            await voteService.CastAsync(vote);
            Vote storedVote =
                await voteService.FakeVoteRepository.GetCountdownVoteAsync(TestableVoteService.CountdownId,
                                                                           TestableVoteService.AccountId);

            Assert.IsNotNull(storedVote);
            Assert.AreEqual(1, storedVote.Value);
        }
예제 #2
0
 private Task UpateOwnerReputationAsync(Vote vote, Vote existingVote, Account owner) {
     if (existingVote != null) {
         owner.Reputation -= CalculateRepScore(existingVote);
     }
     owner.Reputation += CalculateRepScore(vote);
     return _accountRepository.UpdateAsync(owner);
 }
예제 #3
0
 public Task UpdateAsync(Vote vote) {
     return Task.Run(() => {
         Vote v = _votes.FirstOrDefault(x => x.CountdownId == vote.CountdownId && x.CastedById == vote.CastedById);
         if (v != null) {
             v.Value = vote.Value;
         }
     });
 }
예제 #4
0
 public async Task CreateAsync(Vote vote) {
     using (SqlConnection connection = Connection) {
         const string sql =
             "INSERT INTO Votes (CountdownId, CommentId, Value, CastedById, CastedOn) " +
             "OUTPUT INSERTED.Id " +
             "VALUES (@CountdownId, @CommentId, @Value, @CastedById, @CastedOn)";
         vote.Id = (await connection.QueryAsync<Guid>(sql, vote)).Single();
     }
 }
예제 #5
0
 private async Task CreateNotification(Vote vote, Account owner) {
     var notification = new Notification {
         AccountId = owner.Id,
         Read = false,
         CreatedOn = DateTime.UtcNow,
         Type = NotificationType.Vote,
         Content = await GenerateNotificationContentAsync(vote)
     };
     _notificationDispatcher.Dispatch(notification);
 }
예제 #6
0
 private async Task<string> GenerateNotificationContentAsync(Vote vote) {
     if (vote.CountdownId != null) {
         Countdown countdown = await _countdownRepository.GetByIdAsync((int) vote.CountdownId);
         return string.Format("Upvoted on a Countdown - <a href=\"/Countdown/{0}\">{1}</a>",
                              countdown.Id, countdown.Description);
     }
     else {
         Countdown countdown = await _countdownRepository.GetByCommentIdAsync((int) vote.CommentId);
         return string.Format("Upvoted on a Comment - <a href=\"/Countdown/{0}#{1}\">{2}</a>",
                              countdown.Id, vote.CommentId, countdown.Description);
     }
 }
예제 #7
0
        public async Task CastAsync(Vote vote) {
            Task<Vote> existingVoteTask = GetExistingVoteAsync(vote);
            Task<Account> contentOwnerTask = GetContentOwnerAsync(vote);

            await Task.WhenAll(existingVoteTask, contentOwnerTask);

            Vote existingVote = await existingVoteTask;
            Account owner = await contentOwnerTask;

            if (existingVote == null) {
                await CreateVoteAsync(vote, owner);
            }
            else {
                await UpdateVoteAsync(vote, existingVote);
            }
            await UpateOwnerReputationAsync(vote, existingVote, owner);
        }
예제 #8
0
파일: Cast.cs 프로젝트: n1ghtmare/Kauntr
        public async Task VoteWithCommentIdThatDoesntExist_ReputationOfTheOwnerIsUpdated(short voteValue, int reputationScore) {
            var voteService = TestableVoteService.Create();

            voteService.MockCountdownRepository
                       .Setup(x => x.GetByCommentIdAsync(TestableVoteService.CommentId))
                       .Returns(Task.FromResult(new Countdown {
                           Description = "Test description",
                           Id = TestableVoteService.CountdownId
                       }));

            var vote = new Vote {
                CommentId = TestableVoteService.CommentId,
                CastedById = TestableVoteService.AccountId,
                CastedOn = DateTime.UtcNow,
                Value = voteValue
            };

            await voteService.CastAsync(vote);

            voteService.MockAccountRepository
                       .Verify(x => x.UpdateAsync(It.Is<Account>(a => a.Reputation == reputationScore)),
                               Times.Once());
        }
예제 #9
0
 public Task CreateAsync(Vote vote) {
     return Task.Run(() => _votes.Add(vote));
 }
예제 #10
0
 private async Task CreateVoteAsync(Vote vote, Account owner) {
     await _voteRepository.CreateAsync(vote);
     await CreateNotification(vote, owner);
 }
예제 #11
0
 private Task UpdateVoteAsync(Vote vote, Vote existingVote) {
     if (existingVote.Value == vote.Value) {
         throw new Exception("Can't cast the same vote twice");
     }
     vote.Id = existingVote.Id;
     return _voteRepository.UpdateAsync(vote);
 }
예제 #12
0
 private Task<Vote> GetExistingVoteAsync(Vote vote) {
     bool hasCommentId = vote.CommentId != null;
     bool hasCountdownId = vote.CountdownId != null;
     if (hasCommentId ^ hasCountdownId) {
         return hasCountdownId
                    ? _voteRepository.GetCountdownVoteAsync((int) vote.CountdownId, vote.CastedById)
                    : _voteRepository.GetCommentVoteAsync((int) vote.CommentId, vote.CastedById);
     }
     throw new ArgumentException("Can't determine the type of vote", "vote");
 }
예제 #13
0
 public void Delete(Vote vote) {
     _votes.Remove(vote);
 }
예제 #14
0
 private static int CalculateRepScore(Vote vote) {
     return vote.CountdownId != null
                ? CalculateCountdownRepScore(vote)
                : CalculateCommentRepScore(vote);
 }
예제 #15
0
파일: Cast.cs 프로젝트: n1ghtmare/Kauntr
        public async Task VoteWithCountdownId_CreatesANotificationForTheOwner() {
            var voteService = TestableVoteService.Create();

            var countdownVote = new Vote {
                CountdownId = TestableVoteService.CountdownId,
                CastedById = TestableVoteService.AccountId,
                Value = 1
            };

            var countdown = new Countdown {
                Description = "Test description",
                Id = TestableVoteService.CountdownId
            };
            voteService.MockCountdownRepository
                       .Setup(x => x.GetByIdAsync(TestableVoteService.CountdownId))
                       .Returns(Task.FromResult(countdown));

            await voteService.CastAsync(countdownVote);

            string expectedContent =
                string.Format("Upvoted on a Countdown - <a href=\"/Countdown/{0}\">{1}</a>", countdown.Id,
                              countdown.Description);

            voteService.MockNotificationDispatcher
                       .Verify(x =>
                               x.Dispatch(
                                   It.Is<Notification>(
                                       n => n.AccountId == TestableVoteService.OwnerId &&
                                            n.Content == expectedContent &&
                                            n.Read == false &&
                                            // TODO - Refactor this DateTime bit -> Possibly Inject an IClock and mock it
                                            (n.CreatedOn.Date == DateTime.UtcNow.Date && n.CreatedOn.Hour == DateTime.UtcNow.Hour && n.CreatedOn.Minute == DateTime.UtcNow.Minute) &&
                                            n.ReadOn == null &&
                                            n.Type == NotificationType.Vote
                                       )),
                               Times.Once());
        }
예제 #16
0
파일: Cast.cs 프로젝트: n1ghtmare/Kauntr
        public void VoteWithCommentIdAndCountdownId_ThrowsAnException() {
            var voteService = TestableVoteService.Create();

            var vote = new Vote {
                CommentId = TestableVoteService.CommentId,
                CountdownId = TestableVoteService.CountdownId,
                Value = 0
            };

            var ex = Assert.Throws<ArgumentException>(async () => await voteService.CastAsync(vote));

            Assert.AreEqual("Can't determine the type of vote\r\nParameter name: vote", ex.Message);
        }
예제 #17
0
파일: Cast.cs 프로젝트: n1ghtmare/Kauntr
        public async Task VoteWithCommentIdThatAlreadyHasTheSameVoteByTheAccountId_ThrowsAnException() {
            var voteService = TestableVoteService.Create();

            var vote = new Vote {
                CommentId = TestableVoteService.CommentId,
                CastedById = TestableVoteService.AccountId,
                Value = 1
            };

            await voteService.FakeVoteRepository.CreateAsync(vote);

            var ex = Assert.Throws<Exception>(async () => await voteService.CastAsync(vote));

            Assert.AreEqual("Can't cast the same vote twice", ex.Message);
        }
예제 #18
0
파일: Cast.cs 프로젝트: n1ghtmare/Kauntr
        public async Task VoteWithCommentIdThatAlreadyHasADifferentVoteByTheAccountId_UpdatesTheVote(short existingVoteValue, short newVoteValue) {
            var voteService = TestableVoteService.Create();

            var vote = new Vote {
                CommentId = TestableVoteService.CommentId,
                CastedById = TestableVoteService.AccountId,
                CastedOn = DateTime.UtcNow,
                Value = newVoteValue
            };

            await voteService.FakeVoteRepository.CreateAsync(new Vote {
                CommentId = TestableVoteService.CommentId,
                CastedById = TestableVoteService.AccountId,
                Value = existingVoteValue
            });

            await voteService.CastAsync(vote);
            Vote updatedVote = await voteService.FakeVoteRepository.GetCommentVoteAsync(TestableVoteService.CommentId, TestableVoteService.AccountId);

            Assert.AreEqual(newVoteValue, updatedVote.Value);
        }
예제 #19
0
파일: Cast.cs 프로젝트: n1ghtmare/Kauntr
        public async Task VoteWithCommentIdThatAlreadyHasADifferentVoteByTheAccountId_ReputationOfTheOwnerRolledbackAndUpdated(short existingVoteValue, short newVoteValue, int reputationScore) {
            var mockAccountRepository = new Mock<IAccountRepository>();
            mockAccountRepository
                .Setup(x => x.GetByCommentIdAsync(TestableVoteService.CommentId))
                .Returns(Task.FromResult(new Account {Id = TestableVoteService.OwnerId, Reputation = 10}));

            var mockVoteRepository = new Mock<IVoteRepository>();
            mockVoteRepository
                .Setup(x => x.GetCommentVoteAsync(It.IsAny<long>(), It.IsAny<int>()))
                .Returns(Task.FromResult(new Vote {
                    CommentId = TestableVoteService.CommentId,
                    CastedById = TestableVoteService.AccountId,
                    Value = existingVoteValue
                }));

            var voteService = new VoteService(
                mockVoteRepository.Object,
                new Mock<INotificationDispatcher>().Object,
                mockAccountRepository.Object,
                new Mock<ICountdownRepository>().Object);

            var vote = new Vote {
                CommentId = TestableVoteService.CommentId,
                CastedById = TestableVoteService.AccountId,
                CastedOn = DateTime.UtcNow,
                Value = newVoteValue
            };

            await voteService.CastAsync(vote);

            mockAccountRepository
                .Verify(x => x.UpdateAsync(It.Is<Account>(a => a.Reputation == reputationScore)),
                        Times.Once());
        }
예제 #20
0
 private static short CalculateCountdownRepScore(Vote vote) {
     return vote.Value > 0 ? CountdownUpVoteScore : CountdownDownVoteScore;
 }
예제 #21
0
 private static short CalculateCommentRepScore(Vote vote) {
     return vote.Value > 0 ? CommentUpVoteScore : CommentDownVoteScore;
 }
예제 #22
0
 public async Task UpdateAsync(Vote vote) {
     using (SqlConnection connection = Connection) {
         await connection.ExecuteAsync("UPDATE Votes SET Value = @Value, CastedOn = @CastedOn WHERE Id = @Id", vote);
     }
 }
예제 #23
0
파일: Cast.cs 프로젝트: n1ghtmare/Kauntr
        public void VoteWithCountdownIdThatHasAnInvalidOwner_ThrowsAnException() {
            var voteService = TestableVoteService.Create();

            voteService.MockAccountRepository
                       .Setup(x => x.GetByCountdownIdAsync(TestableVoteService.CountdownId))
                       .Returns(Task.FromResult<Account>(null));

            var commentVote = new Vote {
                CountdownId = TestableVoteService.CountdownId,
                CastedById = TestableVoteService.AccountId,
                Value = 1
            };

            var ex = Assert.Throws<Exception>(async () => await voteService.CastAsync(commentVote));

            Assert.AreEqual("Can't find the content owner", ex.Message);
        }
예제 #24
0
 private async Task CastVoteAsync(int commentId, short value) {
     Account account = await _contextService.GetCurrentAccountAsync();
     var vote = new Vote {
         CommentId = commentId,
         Value = value,
         CastedById = account.Id,
         CastedOn = DateTime.UtcNow
     };
     _voteService.CastAsync(vote);
 }
예제 #25
0
        private async Task<Account> GetContentOwnerAsync(Vote vote) {
            Account owner =
                vote.CommentId != null
                    ? await _accountRepository.GetByCommentIdAsync((int) vote.CommentId)
                    : await _accountRepository.GetByCountdownIdAsync((int) vote.CountdownId);

            if (owner == null) {
                throw new Exception("Can't find the content owner");
            }
            return owner;
        }
예제 #26
0
파일: Cast.cs 프로젝트: n1ghtmare/Kauntr
        public async Task VoteWithCountdownIdThatAlreadyHasAnOppositeVoteByTheAccountId_DoesntCreateANotificationForTheOwner() {
            var voteService = TestableVoteService.Create();

            var vote = new Vote {
                CountdownId = TestableVoteService.CountdownId,
                CastedById = TestableVoteService.AccountId,
                Value = -1
            };

            await voteService.FakeVoteRepository.CreateAsync(new Vote {
                CountdownId = TestableVoteService.CountdownId,
                CastedById = TestableVoteService.AccountId,
                Value = 1
            });

            await voteService.CastAsync(vote);

            voteService.MockNotificationDispatcher
                       .Verify(x => x.Dispatch(It.IsAny<Notification>()),
                               Times.Never);
        }