private PaymentProcessingData CreateData(DateTime startTimeInclusive, DateTime endTimeExclusive, CreatorPercentageOverrideData creatorPercentageOverride = null)
 {
     return(new PaymentProcessingData(
                SubscriberId,
                CreatorId,
                startTimeInclusive,
                endTimeExclusive,
                InitialCommittedAccountBalance,
                new List <SubscriberChannelsSnapshot>
     {
         new SubscriberChannelsSnapshot(
             DateTime.UtcNow,
             UserId.Random(),
             new List <SubscriberChannelsSnapshotItem>
         {
             new SubscriberChannelsSnapshotItem(ChannelId.Random(), 100, DateTime.UtcNow),
             new SubscriberChannelsSnapshotItem(ChannelId.Random(), 110, DateTime.UtcNow),
         }),
     },
                new List <SubscriberSnapshot>
     {
         new SubscriberSnapshot(DateTime.UtcNow, UserId.Random(), "*****@*****.**"),
         new SubscriberSnapshot(DateTime.UtcNow, UserId.Random(), "*****@*****.**"),
     },
                new List <CalculatedAccountBalanceSnapshot>
     {
         new CalculatedAccountBalanceSnapshot(DateTime.UtcNow, UserId.Random(), LedgerAccountType.FifthweekCredit, 10),
     },
                new List <CreatorChannelsSnapshot>
     {
         new CreatorChannelsSnapshot(
             DateTime.UtcNow,
             UserId.Random(),
             new List <CreatorChannelsSnapshotItem>
         {
             new CreatorChannelsSnapshotItem(ChannelId.Random(), 200),
             new CreatorChannelsSnapshotItem(ChannelId.Random(), 300),
         }),
     },
                new List <CreatorFreeAccessUsersSnapshot>
     {
         new CreatorFreeAccessUsersSnapshot(
             DateTime.UtcNow,
             UserId.Random(),
             new List <string> {
             "*****@*****.**", "*****@*****.**"
         }),
     },
                new List <CreatorPost>
     {
         new CreatorPost(ChannelId.Random(), DateTime.UtcNow),
         new CreatorPost(ChannelId.Random(), DateTime.UtcNow),
     },
                creatorPercentageOverride));
 }
        public async Task WhenRequesterMatchesRequestedUserId_ItShouldReturnNull()
        {
            var userId    = UserId.Random();
            var requester = Requester.Authenticated(userId);

            this.requesterSecurity.Setup(v => v.AuthenticateAsync(requester)).ReturnsAsync(userId);

            var result = await this.target.ExecuteAsync(requester, userId);

            Assert.IsNull(result);
        }
 private static List <MergedSnapshot> CreateMergedSnapshotResult()
 {
     return(new List <MergedSnapshot>
     {
         new MergedSnapshot(
             CreatorChannelsSnapshot.Default(Now, UserId.Random()),
             CreatorFreeAccessUsersSnapshot.Default(Now, UserId.Random()),
             SubscriberChannelsSnapshot.Default(Now, UserId.Random()),
             SubscriberSnapshot.Default(Now, UserId.Random()),
             CalculatedAccountBalanceSnapshot.DefaultFifthweekCreditAccount(Now, UserId.Random()))
     });
 }
        public async Task WhenNotEnoughRemainingCredit_ItShouldThrowException()
        {
            this.retryOnTransientFailure.Setup(v => v.HandleAsync(It.IsAny <Func <Task <GetCreditTransactionInformation.GetCreditTransactionResult> > >()))
            .ReturnsAsync(new GetCreditTransactionInformation.GetCreditTransactionResult(
                              UserId.Random(),
                              "stripeChargeId",
                              "taxamoTransactionKey",
                              100,
                              RefundCreditAmount.Value - 1));

            await ExpectedException.AssertExceptionAsync <BadRequestException>(
                () => this.target.ExecuteAsync(EnactingUserId, TransactionReference, Now, RefundCreditAmount, Reason, Comment));
        }
Example #5
0
        public void WhenAllSnapshotsBeforeEndTime_ItShouldReturnOriginalList()
        {
            var now       = DateTime.UtcNow;
            var snapshots = new List <ISnapshot>
            {
                SubscriberSnapshot.Default(now.AddDays(-3), UserId.Random()),
                SubscriberSnapshot.Default(now.AddDays(-2), UserId.Random()),
                SubscriberSnapshot.Default(now.AddDays(-1), UserId.Random()),
            };

            var result = this.target.Execute(now, snapshots);

            CollectionAssert.AreEqual(snapshots, result.ToList());
        }
Example #6
0
        public void ItShouldReturnTheGivenSnapshots()
        {
            var now   = DateTime.UtcNow;
            var input = new List <MergedSnapshot>
            {
                new MergedSnapshot(
                    CreatorChannelsSnapshot.Default(now, UserId.Random()),
                    CreatorFreeAccessUsersSnapshot.Default(now, UserId.Random()),
                    SubscriberChannelsSnapshot.Default(now, UserId.Random()),
                    SubscriberSnapshot.Default(now, UserId.Random()),
                    CalculatedAccountBalanceSnapshot.DefaultFifthweekCreditAccount(now, UserId.Random())),
            };

            Assert.AreSame(input, this.target.Execute(input));
        }
Example #7
0
        public void WhenSnapshotsRequireTrim_ItShouldReturnTrimmedList()
        {
            var now       = DateTime.UtcNow;
            var snapshots = new List <ISnapshot>
            {
                SubscriberSnapshot.Default(now.AddDays(-3), UserId.Random()),
                SubscriberSnapshot.Default(now.AddDays(-2), UserId.Random()),
                SubscriberSnapshot.Default(now.AddDays(-1), UserId.Random()),
                SubscriberSnapshot.Default(now, UserId.Random()),
            };

            var result = this.target.Execute(now, snapshots);

            CollectionAssert.AreEqual(snapshots.Take(3).ToList(), result.ToList());
        }
        public async Task ItShouldReturnFalseIfNoUsersCharged()
        {
            var userId1 = UserId.Random();
            var userId2 = UserId.Random();
            var userId3 = UserId.Random();
            var userId4 = UserId.Random();
            var userId5 = UserId.Random();
            var input   = new List <CalculatedAccountBalanceResult>
            {
                new CalculatedAccountBalanceResult(DateTime.UtcNow, UserId.Random(), LedgerAccountType.FifthweekCredit, TopUpUserAccountsWithCredit.MinimumAccountBalanceBeforeCharge),
                new CalculatedAccountBalanceResult(DateTime.UtcNow, UserId.Random(), LedgerAccountType.Stripe, 0),
                new CalculatedAccountBalanceResult(DateTime.UtcNow, userId1, LedgerAccountType.FifthweekCredit, TopUpUserAccountsWithCredit.MinimumAccountBalanceBeforeCharge - 1),
                new CalculatedAccountBalanceResult(DateTime.UtcNow, userId2, LedgerAccountType.FifthweekCredit, -1m),
            };

            var usersRequiringRetry = new List <UserId> {
                userId3, userId4, userId5
            };

            this.getUsersRequiringPaymentRetry.Setup(v => v.ExecuteAsync()).ReturnsAsync(usersRequiringRetry);

            var usersRequiringCharge = new List <UserId> {
                userId1, userId2, userId3, userId4, userId5
            };

            this.incrementPaymentStatus.Setup(v => v.ExecuteAsync(It.IsAny <IReadOnlyList <UserId> >()))
            .Callback <IReadOnlyList <UserId> >(v => CollectionAssert.AreEquivalent(usersRequiringCharge, v.ToList()))
            .Returns(Task.FromResult(0)).Verifiable();

            this.getUserWeeklySubscriptionsCost.Setup(v => v.ExecuteAsync(userId1)).ReturnsAsync(0);
            this.getUserWeeklySubscriptionsCost.Setup(v => v.ExecuteAsync(userId2)).ReturnsAsync(0);
            this.getUserWeeklySubscriptionsCost.Setup(v => v.ExecuteAsync(userId3)).ReturnsAsync(0);
            this.getUserWeeklySubscriptionsCost.Setup(v => v.ExecuteAsync(userId4)).ReturnsAsync(TopUpUserAccountsWithCredit.MinimumPaymentAmount * 2);
            this.getUserWeeklySubscriptionsCost.Setup(v => v.ExecuteAsync(userId5)).ReturnsAsync(TopUpUserAccountsWithCredit.MinimumPaymentAmount * 2);

            // Test PaymentOriginKey with no KeyType.
            this.getUserPaymentOrigin.Setup(v => v.ExecuteAsync(userId4))
            .ReturnsAsync(new UserPaymentOriginResult("customer4", PaymentOriginKeyType.None, null, null, null, null, PaymentStatus.Retry1));

            this.getUserPaymentOrigin.Setup(v => v.ExecuteAsync(userId5))
            .ReturnsAsync(new UserPaymentOriginResult("customer5", PaymentOriginKeyType.Stripe, null, null, null, null, PaymentStatus.None));

            var result = await this.target.ExecuteAsync(input, new List <PaymentProcessingException>(), CancellationToken.None);

            this.incrementPaymentStatus.Verify();

            Assert.IsFalse(result);
        }
        public async Task WhenUserIsNotAdministrator_ItShouldPurposelyFailAuthentication()
        {
            var userId          = UserId.Random();
            var requestedUserId = UserId.Random();
            var requester       = Requester.Authenticated(userId);

            this.requesterSecurity.Setup(v => v.AuthenticateAsync(requester)).ReturnsAsync(userId);

            this.requesterSecurity.Setup(v => v.IsInRoleAsync(requester, FifthweekRole.Administrator))
            .ReturnsAsync(false);

            this.requesterSecurity.Setup(v => v.AuthenticateAsAsync(requester, requestedUserId))
            .Throws(new UnauthorizedException());

            await this.target.ExecuteAsync(requester, requestedUserId);
        }
Example #10
0
        public async Task ItShouldReturnNullIfUserDoesNotExist()
        {
            await this.DatabaseTestAsync(async testDatabase =>
            {
                this.target = new GetCreatorPercentageOverrideDbStatement(testDatabase);

                await this.CreateDataAsync(testDatabase);
                await testDatabase.TakeSnapshotAsync();

                var result = await this.target.ExecuteAsync(UserId.Random(), Now);

                Assert.IsNull(result);

                return(ExpectedSideEffects.None);
            });
        }
Example #11
0
        public void ItShouldSetTheTimeStampToTheMaximumOfItsComponents()
        {
            Assert.AreEqual(
                Now.AddDays(1),
                new MergedSnapshot(
                    CreatorChannelsSnapshot.Default(Now.AddDays(1), UserId.Random()),
                    CreatorFreeAccessUsersSnapshot.Default(Now, UserId.Random()),
                    SubscriberChannelsSnapshot.Default(Now, UserId.Random()),
                    SubscriberSnapshot.Default(Now, UserId.Random()),
                    CalculatedAccountBalanceSnapshot.Default(Now, UserId.Random(), default(LedgerAccountType))).Timestamp);

            Assert.AreEqual(
                Now.AddDays(1),
                new MergedSnapshot(
                    CreatorChannelsSnapshot.Default(Now, UserId.Random()),
                    CreatorFreeAccessUsersSnapshot.Default(Now.AddDays(1), UserId.Random()),
                    SubscriberChannelsSnapshot.Default(Now, UserId.Random()),
                    SubscriberSnapshot.Default(Now, UserId.Random()),
                    CalculatedAccountBalanceSnapshot.Default(Now, UserId.Random(), default(LedgerAccountType))).Timestamp);

            Assert.AreEqual(
                Now.AddDays(1),
                new MergedSnapshot(
                    CreatorChannelsSnapshot.Default(Now, UserId.Random()),
                    CreatorFreeAccessUsersSnapshot.Default(Now, UserId.Random()),
                    SubscriberChannelsSnapshot.Default(Now.AddDays(1), UserId.Random()),
                    SubscriberSnapshot.Default(Now, UserId.Random()),
                    CalculatedAccountBalanceSnapshot.Default(Now, UserId.Random(), default(LedgerAccountType))).Timestamp);

            Assert.AreEqual(
                Now.AddDays(1),
                new MergedSnapshot(
                    CreatorChannelsSnapshot.Default(Now, UserId.Random()),
                    CreatorFreeAccessUsersSnapshot.Default(Now, UserId.Random()),
                    SubscriberChannelsSnapshot.Default(Now, UserId.Random()),
                    SubscriberSnapshot.Default(Now.AddDays(1), UserId.Random()),
                    CalculatedAccountBalanceSnapshot.Default(Now, UserId.Random(), default(LedgerAccountType))).Timestamp);

            Assert.AreEqual(
                Now.AddDays(1),
                new MergedSnapshot(
                    CreatorChannelsSnapshot.Default(Now, UserId.Random()),
                    CreatorFreeAccessUsersSnapshot.Default(Now, UserId.Random()),
                    SubscriberChannelsSnapshot.Default(Now, UserId.Random()),
                    SubscriberSnapshot.Default(Now, UserId.Random()),
                    CalculatedAccountBalanceSnapshot.Default(Now.AddDays(1), UserId.Random(), default(LedgerAccountType))).Timestamp);
        }
Example #12
0
        public void WhenSingleSnapshot_WhenDateIsNotEndDate_ItShouldNotModifyCollection()
        {
            var input = new List <MergedSnapshot>
            {
                new MergedSnapshot(
                    Now.AddDays(1),
                    CreatorChannelsSnapshot.Default(Now, UserId.Random()),
                    CreatorFreeAccessUsersSnapshot.Default(Now, UserId.Random()),
                    this.subscriberChannels,
                    SubscriberSnapshot.Default(Now, UserId.Random()),
                    CalculatedAccountBalanceSnapshot.DefaultFifthweekCreditAccount(Now, UserId.Random()))
            };

            var output = this.target.Execute(input);

            CollectionAssert.AreEqual(input, output.ToList());
        }
        public async Task ItShouldReturnComments()
        {
            var expectedResult = new CommentsResult(
                new List <CommentsResult.Item>
            {
                new CommentsResult.Item(CommentId.Random(), PostId.Random(), UserId.Random(), new Username("blah"), new Comment("comment"), DateTime.UtcNow),
            });

            this.getComments.Setup(v => v.ExecuteAsync(PostId))
            .Returns(Task.FromResult(expectedResult))
            .Verifiable();

            var result = await this.target.HandleAsync(new GetCommentsQuery(Requester, PostId, Timestamp));

            Assert.AreEqual(expectedResult, result);
            this.getComments.Verify();
        }
Example #14
0
        public async Task WhenUserIdHasNoRoles_ItReturnEmptyList()
        {
            await this.DatabaseTestAsync(async testDatabase =>
            {
                this.target = new GetUserRolesDbStatement(testDatabase);

                var userIds = await this.CreateDataAsync(testDatabase, 20);
                await testDatabase.TakeSnapshotAsync();

                var result = await this.target.ExecuteAsync(UserId.Random());

                Assert.AreEqual(
                    new GetUserRolesDbStatement.UserRoles(new List <GetUserRolesDbStatement.UserRoles.UserRole>()),
                    result);

                return(ExpectedSideEffects.None);
            });
        }
Example #15
0
        public void WhenTwoSnapshots_WhenDatesOnEndDatesButStraddleEndDates_ItShouldModifyCollection()
        {
            var input = new List <MergedSnapshot>
            {
                new MergedSnapshot(
                    Now,
                    CreatorChannelsSnapshot.Default(Now, UserId.Random()),
                    CreatorFreeAccessUsersSnapshot.Default(Now, UserId.Random()),
                    this.subscriberChannels,
                    SubscriberSnapshot.Default(Now, UserId.Random()),
                    CalculatedAccountBalanceSnapshot.DefaultFifthweekCreditAccount(Now, UserId.Random())),
                new MergedSnapshot(
                    Now.AddDays(21),
                    CreatorChannelsSnapshot.Default(Now, UserId.Random()),
                    CreatorFreeAccessUsersSnapshot.Default(Now, UserId.Random()),
                    SubscriberChannelsSnapshot.Default(Now, UserId.Random()),
                    SubscriberSnapshot.Default(Now, UserId.Random()),
                    CalculatedAccountBalanceSnapshot.DefaultFifthweekCreditAccount(Now, UserId.Random()))
            };

            var expected = new List <MergedSnapshot>
            {
                input[0],
                new MergedSnapshot(
                    Now.AddDays(7),
                    input[0].CreatorChannels,
                    input[0].CreatorFreeAccessUsers,
                    input[0].SubscriberChannels,
                    input[0].Subscriber,
                    input[0].CalculatedAccountBalance),
                new MergedSnapshot(
                    Now.AddDays(14),
                    input[0].CreatorChannels,
                    input[0].CreatorFreeAccessUsers,
                    input[0].SubscriberChannels,
                    input[0].Subscriber,
                    input[0].CalculatedAccountBalance),
                input[1],
            };

            var output = this.target.Execute(input);

            CollectionAssert.AreEqual(expected, output.ToList());
        }
        public async Task ItShouldReturnZeroTotalRevenueForUnknownUser()
        {
            await this.DatabaseTestAsync(async testDatabase =>
            {
                this.target = new GetCreatorRevenueDbStatement(testDatabase);

                await this.CreateDataAsync(testDatabase);
                await testDatabase.TakeSnapshotAsync();

                var result = await this.target.ExecuteAsync(UserId.Random(), Now.AddDays(5));

                Assert.AreEqual(new GetCreatorRevenueDbStatement.GetCreatorRevenueDbStatementResult(
                                    0,
                                    0,
                                    0),
                                result);

                return(ExpectedSideEffects.None);
            });
        }
Example #17
0
        public async Task WhenNotCreditRecord_ItThrowAnException()
        {
            var transactionReference = TransactionReference.Random();
            var refundData           = AddRefund(UserId, transactionReference.Value, 100);

            var record = CreateAppendOnlyLedgerRecord(
                new Random(),
                UserId,
                UserId.Random(),
                -100,
                LedgerAccountType.FifthweekCredit,
                LedgerTransactionType.SubscriptionPayment,
                transactionReference.Value);

            this.getRecordsForTransaction.Setup(v => v.ExecuteAsync(transactionReference)).ReturnsAsync(new List <AppendOnlyLedgerRecord> {
                record
            });

            await this.target.ExecuteAsync(transactionReference);
        }
Example #18
0
        public async Task WhenGettingComments_ItShouldIssueGetCommentsCommand()
        {
            var expectedResult = new CommentsResult(
                new List <CommentsResult.Item>
            {
                new CommentsResult.Item(CommentId.Random(), PostId.Random(), UserId.Random(), new Username("blah"), new Comment("comment"), DateTime.UtcNow),
            });
            var timestamp = DateTime.UtcNow;

            this.timestampCreator.Setup(v => v.Now()).Returns(timestamp);
            this.requesterContext.Setup(_ => _.GetRequesterAsync()).ReturnsAsync(Requester);
            this.getComments.Setup(v => v.HandleAsync(new GetCommentsQuery(Requester, PostId, timestamp)))
            .Returns(Task.FromResult(expectedResult))
            .Verifiable();

            var result = await this.target.GetComments(PostId.Value.EncodeGuid());

            Assert.AreEqual(expectedResult, result);
            this.getComments.Verify();
        }
Example #19
0
        private async Task <List <IIdentityEquatable> > CreateEntitiesAsync(TestDatabaseContext testDatabase)
        {
            var random = new Random();

            using (var connection = testDatabase.CreateConnection())
            {
                var expectedDeletions = new List <IIdentityEquatable>();
                await this.AddUser(connection, random, UserId.Random(), IncludedDate, false);

                expectedDeletions.AddRange(await this.AddUser(connection, random, TestUserId1, IncludedDate, true));
                var channelId = new ChannelId(expectedDeletions.OfType <Channel>().First().Id);
                expectedDeletions.AddRange(await this.AddUser(connection, random, TestUserId2, IncludedDate, true, TestUserId1, channelId));

                var nonDeletedUserEntities = await this.AddUser(connection, random, TestUserId3, EndDate, true, TestUserId1, channelId);

                expectedDeletions.AddRange(nonDeletedUserEntities.OfType <ChannelSubscription>());

                // Files shouldn't be deleted.
                return(expectedDeletions.Where(v => !(v is File)).ToList());
            }
        }
        public async Task ItShouldStopProcessingUsersIfCancelled()
        {
            this.timestampCreator.SetupSequence(v => v.Now()).Returns(Now1).Returns(Now2);
            this.guidCreator.SetupSequence(v => v.CreateSqlSequential()).Returns(TransactionReference1.Value).Returns(TransactionReference2.Value);

            var userId1 = UserId.Random();
            var userId2 = UserId.Random();
            var userId3 = UserId.Random();
            var userId4 = UserId.Random();
            var userId5 = UserId.Random();
            var input   = new List <CalculatedAccountBalanceResult>
            {
                new CalculatedAccountBalanceResult(DateTime.UtcNow, UserId.Random(), LedgerAccountType.FifthweekCredit, TopUpUserAccountsWithCredit.MinimumAccountBalanceBeforeCharge),
                new CalculatedAccountBalanceResult(DateTime.UtcNow, UserId.Random(), LedgerAccountType.Stripe, 0),
                new CalculatedAccountBalanceResult(DateTime.UtcNow, userId1, LedgerAccountType.FifthweekCredit, TopUpUserAccountsWithCredit.MinimumAccountBalanceBeforeCharge - 1),
                new CalculatedAccountBalanceResult(DateTime.UtcNow, userId2, LedgerAccountType.FifthweekCredit, -1m),
            };

            var usersRequiringRetry = new List <UserId> {
                userId3, userId4, userId5
            };

            this.getUsersRequiringPaymentRetry.Setup(v => v.ExecuteAsync()).ReturnsAsync(usersRequiringRetry);

            var usersRequiringCharge = new List <UserId> {
                userId1, userId2, userId3, userId4, userId5
            };

            this.incrementPaymentStatus.Setup(v => v.ExecuteAsync(It.IsAny <IReadOnlyList <UserId> >()))
            .Callback <IReadOnlyList <UserId> >(v => CollectionAssert.AreEquivalent(usersRequiringCharge, v.ToList()))
            .Returns(Task.FromResult(0)).Verifiable();

            var cts = new CancellationTokenSource();

            this.getUserWeeklySubscriptionsCost.Setup(v => v.ExecuteAsync(userId1)).ReturnsAsync(0).Callback <UserId>(a => cts.Cancel());

            await this.target.ExecuteAsync(input, new List <PaymentProcessingException>(), cts.Token);
        }
        public async Task WhenUserIsAdministrator_ItShouldReturnImpersonatedRequester()
        {
            var userId          = UserId.Random();
            var requestedUserId = UserId.Random();
            var requester       = Requester.Authenticated(userId);

            this.requesterSecurity.Setup(v => v.AuthenticateAsync(requester)).ReturnsAsync(userId);

            this.requesterSecurity.Setup(v => v.IsInRoleAsync(requester, FifthweekRole.Administrator))
            .ReturnsAsync(true);

            this.getUserRoles.Setup(v => v.ExecuteAsync(requestedUserId)).ReturnsAsync(
                new GetUserRolesDbStatement.UserRoles(
                    new List <GetUserRolesDbStatement.UserRoles.UserRole>
            {
                new GetUserRolesDbStatement.UserRoles.UserRole(Guid.NewGuid(), "role1"),
            }));

            var result = await this.target.ExecuteAsync(requester, requestedUserId);

            Assert.AreEqual(
                Requester.Authenticated(requestedUserId, requester, "role1"),
                result);
        }
Example #22
0
        public async Task ItShouldStoreTheDataInABlob()
        {
            var data = new PersistedPaymentProcessingData(
                Guid.NewGuid(),
                new PaymentProcessingData(
                    UserId.Random(),
                    UserId.Random(),
                    DateTime.UtcNow,
                    DateTime.UtcNow,
                    new CommittedAccountBalance(100m),
                    new List <SubscriberChannelsSnapshot>
            {
                new SubscriberChannelsSnapshot(
                    DateTime.UtcNow,
                    UserId.Random(),
                    new List <SubscriberChannelsSnapshotItem>
                {
                    new SubscriberChannelsSnapshotItem(ChannelId.Random(), 100, DateTime.UtcNow),
                    new SubscriberChannelsSnapshotItem(ChannelId.Random(), 110, DateTime.UtcNow),
                }),
            },
                    new List <SubscriberSnapshot>
            {
                new SubscriberSnapshot(DateTime.UtcNow, UserId.Random(), "*****@*****.**"),
                new SubscriberSnapshot(DateTime.UtcNow, UserId.Random(), "*****@*****.**"),
            },
                    new List <CalculatedAccountBalanceSnapshot>
            {
                new CalculatedAccountBalanceSnapshot(DateTime.UtcNow, UserId.Random(), LedgerAccountType.FifthweekCredit, 10),
            },
                    new List <CreatorChannelsSnapshot>
            {
                new CreatorChannelsSnapshot(
                    DateTime.UtcNow,
                    UserId.Random(),
                    new List <CreatorChannelsSnapshotItem>
                {
                    new CreatorChannelsSnapshotItem(ChannelId.Random(), 200),
                    new CreatorChannelsSnapshotItem(ChannelId.Random(), 300),
                }),
            },
                    new List <CreatorFreeAccessUsersSnapshot>
            {
                new CreatorFreeAccessUsersSnapshot(
                    DateTime.UtcNow,
                    UserId.Random(),
                    new List <string> {
                    "*****@*****.**", "*****@*****.**"
                }),
            },
                    new List <CreatorPost>
            {
                new CreatorPost(ChannelId.Random(), DateTime.UtcNow),
                new CreatorPost(ChannelId.Random(), DateTime.UtcNow),
            },
                    new CreatorPercentageOverrideData(0.3m, DateTime.UtcNow)),
                new PaymentProcessingResults(
                    new CommittedAccountBalance(80m),
                    new List <PaymentProcessingResult>
            {
                new PaymentProcessingResult(DateTime.UtcNow, DateTime.UtcNow.AddDays(1), new AggregateCostSummary(24), null, true),
                new PaymentProcessingResult(DateTime.UtcNow, DateTime.UtcNow.AddDays(2), new AggregateCostSummary(44), new CreatorPercentageOverrideData(0.5m, DateTime.UtcNow), false),
            }));

            var client = new Mock <ICloudBlobClient>();

            this.cloudStorageAccount.Setup(v => v.CreateCloudBlobClient()).Returns(client.Object);
            var container = new Mock <ICloudBlobContainer>();

            client.Setup(v => v.GetContainerReference(Shared.Constants.PaymentProcessingDataContainerName)).Returns(container.Object);
            var blob = new Mock <ICloudBlockBlob>();

            container.Setup(v => v.GetBlockBlobReference(data.Id.ToString())).Returns(blob.Object);

            string blobString = null;

            blob.Setup(v => v.UploadTextAsync(It.IsAny <string>())).Callback <string>(s => blobString = s).Returns(Task.FromResult(0));

            await this.target.ExecuteAsync(data);

            Assert.IsNotNull(blobString);
            Assert.AreEqual(data, JsonConvert.DeserializeObject <PersistedPaymentProcessingData>(blobString));
        }
        private async Task ParameterizedTestAsync(
            Func <UserId,
                  UserId,
                  IReadOnlyList <ChannelId>,
                  IReadOnlyList <QueueId>,
                  DateTime,
                  bool,
                  NonNegativeInt,
                  PositiveInt,
                  IReadOnlyList <PreviewNewsfeedPost>,
                  int,
                  Task> parameterizedTest)
        {
            var totalLivePosts = SortedLiveNewsfeedPosts.Count;

            NonNegativeInt noPaginationStart = NonNegativeInt.Parse(0);
            PositiveInt    noPaginationCount = PositiveInt.Parse(int.MaxValue);

            var wrapper = new ParameterizedTestWrapper(parameterizedTest);

            parameterizedTest = wrapper.Execute;

            var visibleSortedLiveNewsfeedPosts =
                SortedLiveNewsfeedPosts.Where(v => !v.ChannelId.Equals(ChannelIds[3])).ToList();

            // No pagination.
            await parameterizedTest(
                CreatorId, CreatorId, null, null, Now, false, noPaginationStart, noPaginationCount, visibleSortedLiveNewsfeedPosts.ToList(), 0);

            // Paginate from start.
            await parameterizedTest(
                CreatorId, CreatorId, null, null, Now, false, NonNegativeInt.Parse(0), PositiveInt.Parse(10), visibleSortedLiveNewsfeedPosts.Take(10).ToList(), 0);

            // Paginate from middle with different page size and page index.
            await parameterizedTest(
                CreatorId, CreatorId, null, null, Now, false, NonNegativeInt.Parse(5), PositiveInt.Parse(10), visibleSortedLiveNewsfeedPosts.Skip(5).Take(10).ToList(), 0);

            // Paginate from middle with same page size and page index.
            await parameterizedTest(
                CreatorId, CreatorId, null, null, Now, false, NonNegativeInt.Parse(10), PositiveInt.Parse(10), visibleSortedLiveNewsfeedPosts.Skip(10).Take(10).ToList(), 0);

            // Paginate from near end, requesting up to last post.
            await parameterizedTest(
                CreatorId, CreatorId, null, null, Now, false, NonNegativeInt.Parse(totalLivePosts - 10), PositiveInt.Parse(10), visibleSortedLiveNewsfeedPosts.Skip(totalLivePosts - 10).Take(10).ToList(), 0);

            // Paginate from near end, requesting beyond last post.
            await parameterizedTest(
                CreatorId, CreatorId, null, null, Now, false, NonNegativeInt.Parse(totalLivePosts - 5), PositiveInt.Parse(10), visibleSortedLiveNewsfeedPosts.Skip(totalLivePosts - 5).Take(10).ToList(), 0);

            // Paginate from end, requesting beyond last post.
            await parameterizedTest(
                CreatorId, CreatorId, null, null, Now, false, NonNegativeInt.Parse(totalLivePosts), PositiveInt.Parse(1), new PreviewNewsfeedPost[0], 0);

            // Paginate from beyond end, requesting beyond last post.
            await parameterizedTest(
                CreatorId, CreatorId, null, null, Now, false, NonNegativeInt.Parse(totalLivePosts + 1), PositiveInt.Parse(1), new PreviewNewsfeedPost[0], 0);

            // Unsubscribed.
            await parameterizedTest(
                UnsubscribedUserId, CreatorId, null, null, Now, false, noPaginationStart, noPaginationCount, visibleSortedLiveNewsfeedPosts, 0);

            // Unsubscribed, fetch from all subscriptions (will ignore non-discoverable channel).
            await parameterizedTest(
                UnsubscribedUserId, null, null, null, Now, false, noPaginationStart, noPaginationCount, SortedLiveNewsfeedPosts.Where(v => v.ChannelId.Equals(ChannelIds[0]) || v.ChannelId.Equals(ChannelIds[2])).ToList(), 10);

            // Logged out.
            await parameterizedTest(
                null, CreatorId, null, null, Now, false, noPaginationStart, noPaginationCount, visibleSortedLiveNewsfeedPosts, 0);

            // Logged out, fetch from all subscriptions (will ignore non-discoverable channel).
            await parameterizedTest(
                null, null, null, null, Now, false, noPaginationStart, noPaginationCount, SortedLiveNewsfeedPosts.Where(v => v.ChannelId.Equals(ChannelIds[0]) || v.ChannelId.Equals(ChannelIds[2])).ToList(), 10);

            // Logged in as creator, filter by channel for creator (will ignore non-discoverable channel).
            await parameterizedTest(
                CreatorId, null, null, null, Now, false, noPaginationStart, noPaginationCount, SortedLiveNewsfeedPosts.Where(v => v.ChannelId.Equals(ChannelIds[0]) || v.ChannelId.Equals(ChannelIds[2])).ToList(), 0);

            // Filter by channel for creator.
            await parameterizedTest(
                CreatorId, CreatorId, new[] { ChannelIds[0] }, null, Now, false, noPaginationStart, noPaginationCount, SortedLiveNewsfeedPosts.Where(v => v.ChannelId.Equals(ChannelIds[0])).ToList(), 0);

            // Filter by channel.
            await parameterizedTest(
                UnsubscribedUserId, null, new[] { ChannelIds[0] }, null, Now, false, noPaginationStart, noPaginationCount, SortedLiveNewsfeedPosts.Where(v => v.ChannelId.Equals(ChannelIds[0])).ToList(), 10);

            // Filter by channel 2.
            await parameterizedTest(
                UnsubscribedUserId, null, new[] { ChannelIds[1] }, null, Now, false, noPaginationStart, noPaginationCount, SortedLiveNewsfeedPosts.Where(v => v.ChannelId.Equals(ChannelIds[1])).ToList(), 10);

            // Filter by valid channel and creator combination.
            await parameterizedTest(
                UnsubscribedUserId, CreatorId, new[] { ChannelIds[0] }, null, Now, false, noPaginationStart, noPaginationCount, SortedLiveNewsfeedPosts.Where(v => v.ChannelId.Equals(ChannelIds[0])).ToList(), 10);

            // Filter by invalid channel and creator combination.
            await parameterizedTest(
                UnsubscribedUserId, UserId.Random(), new[] { ChannelIds[0] }, null, Now, false, noPaginationStart, noPaginationCount, new PreviewNewsfeedPost[0], 10);

            // Search forwards from now.
            await parameterizedTest(
                CreatorId, CreatorId, null, null, Now, true, noPaginationStart, noPaginationCount, new PreviewNewsfeedPost[0], 0);

            // Search forwards from beginning.
            await parameterizedTest(
                CreatorId, CreatorId, null, null, SqlDateTime.MinValue.Value, true, noPaginationStart, noPaginationCount, visibleSortedLiveNewsfeedPosts.AsEnumerable().Reverse().ToList(), 0);

            // Paginate forwards from middle with different page size and page index.
            await parameterizedTest(
                CreatorId, CreatorId, null, null, SqlDateTime.MinValue.Value, true, NonNegativeInt.Parse(5), PositiveInt.Parse(10), visibleSortedLiveNewsfeedPosts.AsEnumerable().Reverse().Skip(5).Take(10).ToList(), 0);
        }
Example #24
0
 public async Task WhenUserIsNotAuthorized_ItShouldThrowAnException()
 {
     await this.target.HandleAsync(new UpdatePaymentOriginCommand(
                                       Requester, UserId.Random(), StripeToken, CountryCode, CreditCardPrefix, IpAddress));
 }
 public async Task WhenUserIdIsNull_ItShouldThrowAnException()
 {
     await this.target.ExecuteAsync(Requester.Authenticated(UserId.Random()), null);
 }
Example #26
0
 private static MergedSnapshot CreateSnapshot(DateTime timestamp)
 {
     return(new MergedSnapshot(
                timestamp,
                CreatorChannelsSnapshot.Default(Now, UserId.Random()),
                CreatorFreeAccessUsersSnapshot.Default(Now, UserId.Random()),
                SubscriberChannelsSnapshot.Default(Now, UserId.Random()),
                SubscriberSnapshot.Default(Now, UserId.Random()),
                CalculatedAccountBalanceSnapshot.DefaultFifthweekCreditAccount(Now, UserId.Random())));
 }
 public async Task WhenUserIsNotAuthorized_ItShouldThrowAnException()
 {
     await this.target.HandleAsync(new GetCreditRequestSummaryQuery(
                                       Requester, UserId.Random(), null));
 }
        public async Task ItShouldChargeAllNecessaryUsers()
        {
            this.timestampCreator.SetupSequence(v => v.Now()).Returns(Now1).Returns(Now2);
            this.guidCreator.SetupSequence(v => v.CreateSqlSequential()).Returns(TransactionReference1.Value).Returns(TransactionReference2.Value);

            var userId1 = UserId.Random();
            var userId2 = UserId.Random();
            var userId3 = UserId.Random();
            var userId4 = UserId.Random();
            var userId5 = UserId.Random();
            var input   = new List <CalculatedAccountBalanceResult>
            {
                new CalculatedAccountBalanceResult(DateTime.UtcNow, UserId.Random(), LedgerAccountType.FifthweekCredit, TopUpUserAccountsWithCredit.MinimumAccountBalanceBeforeCharge),
                new CalculatedAccountBalanceResult(DateTime.UtcNow, UserId.Random(), LedgerAccountType.Stripe, 0),
                new CalculatedAccountBalanceResult(DateTime.UtcNow, userId1, LedgerAccountType.FifthweekCredit, TopUpUserAccountsWithCredit.MinimumAccountBalanceBeforeCharge - 1),
                new CalculatedAccountBalanceResult(DateTime.UtcNow, userId2, LedgerAccountType.FifthweekCredit, -1m),
            };

            var usersRequiringRetry = new List <UserId> {
                userId3, userId4, userId5
            };

            this.getUsersRequiringPaymentRetry.Setup(v => v.ExecuteAsync()).ReturnsAsync(usersRequiringRetry);

            var usersRequiringCharge = new List <UserId> {
                userId1, userId2, userId3, userId4, userId5
            };

            this.incrementPaymentStatus.Setup(v => v.ExecuteAsync(It.IsAny <IReadOnlyList <UserId> >()))
            .Callback <IReadOnlyList <UserId> >(v => CollectionAssert.AreEquivalent(usersRequiringCharge, v.ToList()))
            .Returns(Task.FromResult(0)).Verifiable();

            this.getUserWeeklySubscriptionsCost.Setup(v => v.ExecuteAsync(userId1)).ReturnsAsync(TopUpUserAccountsWithCredit.MinimumPaymentAmount - 1);
            this.getUserWeeklySubscriptionsCost.Setup(v => v.ExecuteAsync(userId2)).ReturnsAsync(TopUpUserAccountsWithCredit.MinimumPaymentAmount + 1);
            this.getUserWeeklySubscriptionsCost.Setup(v => v.ExecuteAsync(userId3)).ReturnsAsync(0);
            this.getUserWeeklySubscriptionsCost.Setup(v => v.ExecuteAsync(userId4)).ReturnsAsync(TopUpUserAccountsWithCredit.MinimumPaymentAmount * 2);
            this.getUserWeeklySubscriptionsCost.Setup(v => v.ExecuteAsync(userId5)).ReturnsAsync(TopUpUserAccountsWithCredit.MinimumPaymentAmount * 2);

            this.getUserPaymentOrigin.Setup(v => v.ExecuteAsync(userId1))
            .ReturnsAsync(new UserPaymentOriginResult("customer1", PaymentOriginKeyType.Stripe, null, null, null, null, PaymentStatus.Retry1));
            this.getUserPaymentOrigin.Setup(v => v.ExecuteAsync(userId2))
            .ReturnsAsync(new UserPaymentOriginResult("customer2", PaymentOriginKeyType.Stripe, null, null, null, null, PaymentStatus.Retry1));

            // Test PaymentOriginKeyType with no key.
            this.getUserPaymentOrigin.Setup(v => v.ExecuteAsync(userId4))
            .ReturnsAsync(new UserPaymentOriginResult(null, PaymentOriginKeyType.Stripe, null, null, null, null, PaymentStatus.Retry1));

            this.getUserPaymentOrigin.Setup(v => v.ExecuteAsync(userId5))
            .ReturnsAsync(new UserPaymentOriginResult("customer5", PaymentOriginKeyType.Stripe, null, null, null, null, PaymentStatus.None));

            this.applyUserCredit.Setup(v => v.ExecuteAsync(userId1, Now1, TransactionReference1, PositiveInt.Parse(TopUpUserAccountsWithCredit.MinimumPaymentAmount), null, UserType.StandardUser))
            .Returns(Task.FromResult(0))
            .Verifiable();

            this.applyUserCredit.Setup(v => v.ExecuteAsync(userId2, Now2, TransactionReference2, PositiveInt.Parse(TopUpUserAccountsWithCredit.MinimumPaymentAmount + 1), null, UserType.StandardUser))
            .Returns(Task.FromResult(0))
            .Verifiable();

            var result = await this.target.ExecuteAsync(input, new List <PaymentProcessingException>(), CancellationToken.None);

            this.incrementPaymentStatus.Verify();
            this.applyUserCredit.Verify();

            Assert.IsTrue(result);
        }
 public async Task WhenRequesterIsNull_ItShouldThrowAnException()
 {
     await this.target.ExecuteAsync(null, UserId.Random());
 }
        public async Task WhenSuccessfullyAcquiresLease_AndProcessingCausesErrors_ItShouldLogErrors()
        {
            this.paymentProcessingLease.Setup(v => v.TryAcquireLeaseAsync()).ReturnsAsync(true).Verifiable();
            this.paymentProcessingLease.Setup(v => v.GetTimeSinceLastLeaseAsync()).ReturnsAsync(TimeSpan.MaxValue).Verifiable();
            this.paymentProcessingLease.Setup(v => v.GetIsAcquired()).Returns(true);

            var error1 = new PaymentProcessingException(new DivideByZeroException(), UserId.Random(), UserId.Random());
            var error2 = new PaymentProcessingException(new DivideByZeroException(), UserId.Random(), UserId.Random());

            this.processAllPayments.Setup(v => v.ExecuteAsync(this.paymentProcessingLease.Object, It.Is <List <PaymentProcessingException> >(l => l.Count == 0), CancellationToken))
            .Callback <IKeepAliveHandler, List <PaymentProcessingException>, CancellationToken>(
                (lease, errors, ct) =>
            {
                errors.Add(error1);
                errors.Add(error2);
            })
            .Returns(Task.FromResult(0)).Verifiable();

            this.requestProcessPayments.Setup(v => v.ExecuteAsync()).Returns(Task.FromResult(0)).Verifiable();
            this.paymentProcessingLease.Setup(v => v.UpdateTimestampsAsync()).Returns(Task.FromResult(0)).Verifiable();
            this.paymentProcessingLease.Setup(v => v.ReleaseLeaseAsync()).Returns(Task.FromResult(0)).Verifiable();

            this.logger.Setup(v => v.Error(error1)).Verifiable();
            this.logger.Setup(v => v.Error(error2)).Verifiable();

            await this.target.ProcessPaymentsAsync(new ProcessPaymentsMessage(), this.logger.Object, CancellationToken);

            this.paymentProcessingLease.Verify();
            this.requestProcessPayments.Verify();
            this.processAllPayments.Verify();

            this.logger.Verify();
        }