public async Task Handle_InstancesPresentFutureExpiry_ReturnsEmptyList() { //Arrange await using var environment = await IntegrationTestEnvironment.CreateAsync(); await environment.WithFreshDataContext(async dataContext => await dataContext.Instances.AddAsync(new Instance() { Name = "dummy", PlanId = "dummy", ExpiresAtUtc = DateTime.UtcNow.AddMinutes(1), Cluster = new Cluster() })); //Act var expiredInstances = await environment.Mediator.Send(new GetExpiredInstancesQuery()); //Assert Assert.IsNotNull(expiredInstances); Assert.AreEqual(0, expiredInstances.Length); }
public async Task Handle_ProperArgumentsGiven_DoggerInstanceIsCreatedInDatabase() { //Arrange var fakeProvisioningService = Substitute.For <IProvisioningService>(); var fakeAmazonLightsail = Substitute.For <IAmazonLightsail>(); FakeOutBundleFetching(fakeAmazonLightsail); var fakeFile = Substitute.For <IFile>(); await using var environment = await IntegrationTestEnvironment.CreateAsync(new EnvironmentSetupOptions () { IocConfiguration = services => { services.AddSingleton(fakeProvisioningService); services.AddSingleton(fakeAmazonLightsail); services.AddSingleton(fakeFile); } }); //Act await environment.Mediator.Send( new ProvisionDogfeedInstanceCommand( "some-instance-name")); //Assert await environment.WithFreshDataContext(async dataContext => { var cluster = await dataContext .Clusters .Include(x => x.Instances) .SingleOrDefaultAsync(); Assert.IsNotNull(cluster); Assert.AreEqual(DataContext.DoggerClusterId, cluster.Id); Assert.AreEqual(1, cluster.Instances.Count); Assert.AreEqual("some-instance-name", cluster.Instances.Single().Name); }); }
public async Task Handle_ExistingPullRequestFound_ReturnsExistingPullRequest() { //Arrange await using var environment = await IntegrationTestEnvironment.CreateAsync(); var pullDogRepository = new PullDogRepository() { Handle = "some-repository-handle", PullDogSettings = new PullDogSettings() { User = new User() { StripeCustomerId = "dummy" }, PlanId = "dummy", EncryptedApiKey = Array.Empty <byte>() } }; await environment.WithFreshDataContext(async dataContext => { await dataContext.PullDogPullRequests.AddAsync(new PullDogPullRequest() { Handle = "some-pull-request-handle", PullDogRepository = pullDogRepository }); }); //Act var pullRequest = await environment.Mediator.Send(new EnsurePullDogPullRequestCommand( pullDogRepository, "some-pull-request-handle")); //Assert Assert.IsNotNull(pullRequest); await environment.WithFreshDataContext(async dataContext => { Assert.AreEqual(1, await dataContext.PullDogPullRequests.CountAsync()); }); }
public async Task Handle_ProperArgumentsGiven_UnprovisionedInstanceIsAddedToDatabase() { //Arrange await using var environment = await IntegrationTestEnvironment.CreateAsync(new EnvironmentSetupOptions () { IocConfiguration = services => { services.AddSingleton(Substitute.For <IProvisioningService>()); } }); var user = await environment.Mediator.Send( new CreateUserForIdentityCommand( TestClaimsPrincipalFactory.CreateWithIdentityName("some-identity-name"))); //Act await environment.Mediator.Send( new ProvisionInstanceForUserCommand( new Plan( "dummy", 1337, new Bundle() { Price = 1337, BundleId = "dummy" }, Array.Empty <PullDogPlan>()), user)); //Assert await environment.WithFreshDataContext(async dataContext => { var addedInstance = await dataContext .Instances .SingleAsync(); Assert.IsNotNull(addedInstance); Assert.IsFalse(addedInstance.IsProvisioned); }); }
public async Task Handle_MultipleClusters_ReturnsDemoCluster() { //Arrange await using var environment = await IntegrationTestEnvironment.CreateAsync(); await environment.WithFreshDataContext(async dataContext => { await dataContext.Clusters.AddAsync(new Cluster()); await dataContext.Clusters.AddAsync(new Cluster() { Id = DataContext.DemoClusterId }); }); //Act var cluster = await environment.Mediator.Send(new EnsureClusterWithIdCommand(DataContext.DemoClusterId)); //Assert Assert.IsNotNull(cluster); Assert.AreEqual(DataContext.DemoClusterId, cluster.Id); }
public async Task Handle_NoPullDogSettingsFoundOnUser_ThrowsException() { //Arrange await using var environment = await IntegrationTestEnvironment.CreateAsync(); var userId = Guid.NewGuid(); await environment.WithFreshDataContext(async dataContext => await dataContext.Users.AddAsync(new User() { Id = userId, StripeCustomerId = "dummy", PullDogSettings = null })); //Act var exception = await Assert.ThrowsExceptionAsync <InvalidOperationException>(async() => await environment.Mediator.Send( new GetRepositoriesForUserQuery(userId))); //Assert Assert.IsNotNull(exception); }
public async Task Handle_InstancesWithoutPullRequestPresent_NothingIsDeleted() { //Arrange var fakeMediator = Substitute.For <IMediator>(); await using var environment = await IntegrationTestEnvironment.CreateAsync( new EnvironmentSetupOptions () { IocConfiguration = services => services.AddSingleton(fakeMediator) }); var user = new User() { StripeCustomerId = "dummy" }; await environment.WithFreshDataContext(async dataContext => { await dataContext.Users.AddAsync(user); await dataContext.Instances.AddAsync(new Instance() { Cluster = new Cluster() { User = user }, Name = "dummy", PlanId = "dummy", PullDogPullRequest = null }); }); //Act await environment.Mediator.Send(new DeleteAllPullDogInstancesForUserCommand(user.Id)); //Assert await fakeMediator .DidNotReceive() .Send(Arg.Any <DeleteInstanceByNameCommand>()); }
public async Task Handle_NoUserFoundInDatabase_SavesCredentialsOnCreatedUser() { //Arrange var fakeAmazonIdentityManagementService = Substitute.For <IAmazonIdentityManagementService>(); fakeAmazonIdentityManagementService .CreateAccessKeyAsync(Arg.Any <CreateAccessKeyRequest>()) .Returns(new CreateAccessKeyResponse() { AccessKey = new AccessKey() { SecretAccessKey = "some-secret-access-key", AccessKeyId = "some-access-key-id" } }); await using var environment = await IntegrationTestEnvironment.CreateAsync(new EnvironmentSetupOptions () { IocConfiguration = services => services.AddSingleton(fakeAmazonIdentityManagementService) }); var aesEncryptionHelper = environment.ServiceProvider.GetRequiredService <IAesEncryptionHelper>(); //Act await environment.Mediator.Send(new EnsureAmazonUserWithNameCommand("some-name")); //Assert await environment.WithFreshDataContext(async dataContext => { var userFromDatabase = await dataContext.AmazonUsers.SingleAsync(); Assert.AreNotEqual(0, userFromDatabase.EncryptedSecretAccessKey); Assert.AreNotEqual(0, userFromDatabase.EncryptedAccessKeyId); var decryptedAccessKey = await aesEncryptionHelper.DecryptAsync(userFromDatabase.EncryptedSecretAccessKey); var decryptedKeyId = await aesEncryptionHelper.DecryptAsync(userFromDatabase.EncryptedAccessKeyId); Assert.AreEqual("some-secret-access-key", decryptedAccessKey); Assert.AreEqual("some-access-key-id", decryptedKeyId); }); }
public async Task Handle_NestedTransactionsOuterExceptionThrown_InnerAndOuterTransactionContentsReverted() { //Arrange await using var environment = await IntegrationTestEnvironment.CreateAsync(); //Act var exception = await Assert.ThrowsExceptionAsync <TestException>(async() => { await environment.Mediator.Send(new TestCommand(async() => { await environment.DataContext.Clusters.AddAsync(new Cluster() { Name = "outer" }); await environment.DataContext.SaveChangesAsync(); await environment.Mediator.Send(new TestCommand(async() => { await environment.DataContext.Clusters.AddAsync(new Cluster() { Name = "inner" }); await environment.DataContext.SaveChangesAsync(); })); throw new TestException(); })); }); //Assert Assert.IsNotNull(exception); await environment.WithFreshDataContext(async (dataContext) => { var clusterCount = await dataContext.Clusters.CountAsync(); Assert.AreEqual(0, clusterCount); }); }
public async Task ThrowError_AnonymousUserAndProductionEnvironment_ReturnsNoErrorDetails() { //Arrange await using var environment = await IntegrationTestEnvironment.CreateAsync(new EnvironmentSetupOptions () { EnvironmentName = Environments.Production }); //Act using var httpClient = new HttpClient(); var response = await httpClient.GetAsync("http://localhost:14568/errors/throw"); //Assert Assert.AreEqual(HttpStatusCode.InternalServerError, response.StatusCode); var responseString = await response.Content.ReadAsStringAsync(); var responseObject = JsonSerializer.Deserialize <ProblemDetails>(responseString); Assert.AreEqual("An error occured while processing your request.", responseObject.Title); Assert.IsNull(responseObject.Detail); Assert.AreEqual(500, responseObject.Status); }
public async Task Handle_SinglePaymentMethodPresentOnStripeCustomer_SinglePaymentMethodReturned() { //Arrange await using var environment = await IntegrationTestEnvironment.CreateAsync(); var createdUser = await environment.Mediator.Send( new CreateUserForIdentityCommand( TestClaimsPrincipalFactory.CreateWithIdentityName("some-identity-name"))); var createdPaymentMethod = await environment .ServiceProvider .GetRequiredService <PaymentMethodService>() .CreateAsync(new PaymentMethodCreateOptions() { Card = new PaymentMethodCardCreateOptions() { Number = "4242424242424242", Cvc = "123", ExpMonth = 10, ExpYear = 30 }, Type = "card" }); await environment.Mediator.Send( new SetActivePaymentMethodForUserCommand( createdUser, createdPaymentMethod.Id)); //Act var activePaymentMethod = await environment.Mediator.Send( new GetActivePaymentMethodForUserQuery( createdUser)); //Assert Assert.IsNotNull(activePaymentMethod); }
public async Task Handle_ClusterIdGivenAndOneMatchingClusterOnUser_ClusterReturned() { //Arrange await using var environment = await IntegrationTestEnvironment.CreateAsync(); var fakeUserId = Guid.NewGuid(); var fakeClusterId = Guid.NewGuid(); var user = new User() { Id = fakeUserId, StripeCustomerId = "dummy" }; await environment.WithFreshDataContext(async dataContext => { await dataContext.Clusters.AddAsync(new Cluster() { User = user }); await dataContext.Clusters.AddAsync(new Cluster() { Id = fakeClusterId, User = user }); }); //Act var cluster = await environment.Mediator.Send(new GetClusterForUserQuery(fakeUserId) { ClusterId = fakeClusterId }); //Assert Assert.IsNotNull(cluster); Assert.AreEqual(fakeClusterId, cluster.Id); }
public async Task Handle_NoClustersOnUserByName_CreatesClusterByName() { //Arrange await using var environment = await IntegrationTestEnvironment.CreateAsync(); var user = new User() { StripeCustomerId = "dummy", Clusters = new List <Cluster>() { new Cluster() { Name = "some-non-matching-cluster-1" }, new Cluster() { Name = "some-non-matching-cluster-2" } } }; await environment.WithFreshDataContext(async dataContext => { await dataContext.Users.AddAsync(user); }); //Act var cluster = await environment.Mediator.Send(new EnsureClusterForUserCommand(user.Id) { ClusterName = "some-cluster-name" }); //Assert Assert.IsNotNull(cluster); Assert.AreEqual(cluster.UserId, user.Id); Assert.AreEqual("some-cluster-name", cluster.Name); }
public async Task Handle_NoMatchingInstanceFound_DoesNothing() { //Arrange var fakeMediator = Substitute.For <IMediator>(); await using var environment = await IntegrationTestEnvironment.CreateAsync(new EnvironmentSetupOptions () { IocConfiguration = services => services.AddSingleton(fakeMediator) }); //Act await environment.Mediator.Send(new DeleteInstanceByPullRequestCommand( "dummy", "dummy")); //Assert await fakeMediator .DidNotReceive() .Send(Arg.Any <DeleteInstanceByNameCommand>(), default); await fakeMediator .DidNotReceive() .Send(Arg.Any <UpsertPullRequestCommentCommand>(), default); }
public async Task Handle_ExistingPaymentMethodsPresent_DefaultPaymentMethodChangedToAddedMethod() { //Arrange await using var environment = await IntegrationTestEnvironment.CreateAsync(); var user = await environment.Mediator.Send( new CreateUserForIdentityCommand( TestClaimsPrincipalFactory.CreateWithIdentityName("some-identity-name"))); var paymentMethodService = environment .ServiceProvider .GetRequiredService <PaymentMethodService>(); var existingPaymentMethod = await CreatePaymentMethodAsync(paymentMethodService); await paymentMethodService.AttachAsync(existingPaymentMethod.Id, new PaymentMethodAttachOptions() { Customer = user.StripeCustomerId }); var newPaymentMethod = await CreatePaymentMethodAsync(paymentMethodService); //Act await environment.Mediator.Send( new SetActivePaymentMethodForUserCommand( user, newPaymentMethod.Id)); //Assert var stripeCustomer = await environment .ServiceProvider .GetRequiredService <CustomerService>() .GetAsync(user.StripeCustomerId); Assert.AreEqual(stripeCustomer.InvoiceSettings.DefaultPaymentMethodId, newPaymentMethod.Id); }
public async Task Handle_MultipleProvisionedInstancesButNoProvisionedPresent_NoLightsailInstancesReturned() { //Arrange var fakeGetInstanceByNameQueryHandler = Substitute.For <IRequestHandler <GetLightsailInstanceByNameQuery, global::Amazon.Lightsail.Model.Instance> >(); fakeGetInstanceByNameQueryHandler .Handle( Arg.Is <GetLightsailInstanceByNameQuery>( arg => arg.Name == "some-instance-1"), default) .Returns(new global::Amazon.Lightsail.Model.Instance() { Name = "some-instance-1" }); fakeGetInstanceByNameQueryHandler .Handle( Arg.Is <GetLightsailInstanceByNameQuery>( arg => arg.Name == "some-instance-2"), default) .Returns(new global::Amazon.Lightsail.Model.Instance() { Name = "some-instance-2" }); await using var environment = await IntegrationTestEnvironment.CreateAsync(new EnvironmentSetupOptions () { IocConfiguration = services => { services.AddSingleton(fakeGetInstanceByNameQueryHandler); } }); var userId = Guid.NewGuid(); await environment.WithFreshDataContext(async dataContext => { await dataContext.Users.AddAsync(new User() { Id = userId, StripeCustomerId = "dummy", Clusters = new List <Cluster>() { new Cluster() { Instances = new List <Instance>() { new Instance() { Name = "some-instance-1", PlanId = "dummy", IsProvisioned = false }, new Instance() { Name = "some-instance-2", PlanId = "dummy", IsProvisioned = false } } } } }); }); //Act var clusters = await environment.Mediator.Send( new GetProvisionedClustersWithInstancesForUserQuery(userId)); //Assert Assert.IsNotNull(clusters); Assert.AreEqual(0, clusters.Count); await fakeGetInstanceByNameQueryHandler .DidNotReceive() .Handle( Arg.Is <GetLightsailInstanceByNameQuery>( arg => arg.Name == "some-instance-1"), default); await fakeGetInstanceByNameQueryHandler .DidNotReceive() .Handle( Arg.Is <GetLightsailInstanceByNameQuery>( arg => arg.Name == "some-instance-2"), default); }
public async Task Handle_ProperArgumentsGivenAtEndOfMonth_FullServerProvisioningFlowIsRunAndProperInstanceIsCreated() { //Arrange var lastDayOfLastMonth = new DateTime( DateTime.Now.Year, DateTime.Now.Month, 1) .AddDays(-1); var fakeTimeProvider = Substitute.For <ITimeProvider>(); fakeTimeProvider .UtcNow .Returns(lastDayOfLastMonth); await using var environment = await IntegrationTestEnvironment.CreateAsync( new EnvironmentSetupOptions () { IocConfiguration = services => { FakeOutMinimalLightsailFeaturesForFullProvisioning(services); services.AddSingleton(fakeTimeProvider); } }); var provisioningService = environment .ServiceProvider .GetRequiredService <IProvisioningService>(); var paymentMethodService = environment .ServiceProvider .GetRequiredService <PaymentMethodService>(); var user = await environment.Mediator.Send( new CreateUserForIdentityCommand( TestClaimsPrincipalFactory.CreateWithIdentityName("some-identity-name"))); var paymentMethod = await CreatePaymentMethodAsync(paymentMethodService); await environment.Mediator.Send( new SetActivePaymentMethodForUserCommand( user, paymentMethod.Id)); //Act await environment.Mediator.Send( new ProvisionInstanceForUserCommand( new Plan( "nano_2_0", 1337, new Bundle() { Price = 1337, BundleId = "nano_2_0" }, Array.Empty <PullDogPlan>()), user)); await provisioningService.ProcessPendingJobsAsync(); //Assert await environment.WithFreshDataContext(async dataContext => { var provisionedInstance = await dataContext .Instances .Include(x => x.Cluster) .ThenInclude(x => x.User) .SingleAsync(); Assert.IsTrue(provisionedInstance.IsProvisioned); Assert.AreEqual(provisionedInstance.Cluster.UserId, user.Id); }); }
public async Task Handle_DatabaseRepositoriesAndGitHubRepositoriesFoundWithNoOverlap_IncludesAllRepositories() { //Arrange var fakeGitHubClientFactory = Substitute.For <IGitHubClientFactory>(); var fakeGitHubClient = await fakeGitHubClientFactory.CreateInstallationClientAsync(1337); fakeGitHubClient .GitHubApps .Installation .GetAllRepositoriesForCurrent() .Returns(new RepositoriesResponse( 2, new[] { new Repository(1), new Repository(2) })); await using var environment = await IntegrationTestEnvironment.CreateAsync(new EnvironmentSetupOptions () { IocConfiguration = services => services.AddSingleton(fakeGitHubClientFactory) }); var userId = Guid.NewGuid(); await environment.WithFreshDataContext(async dataContext => await dataContext.Users.AddAsync(new User() { Id = userId, StripeCustomerId = "dummy", PullDogSettings = new PullDogSettings() { PlanId = "dummy", EncryptedApiKey = Array.Empty <byte>(), Repositories = new List <PullDogRepository>() { new PullDogRepository() { Handle = "3", GitHubInstallationId = 1337 }, new PullDogRepository() { Handle = "4", GitHubInstallationId = 1337 } } } })); //Act var repositories = await environment.Mediator.Send( new GetRepositoriesForUserQuery(userId), default); //Assert Assert.IsNotNull(repositories); Assert.AreEqual(4, repositories.Count); Assert.IsTrue(repositories.Any(x => x.Handle == "1" && x.PullDogId == null)); Assert.IsTrue(repositories.Any(x => x.Handle == "2" && x.PullDogId == null)); Assert.IsTrue(repositories.Any(x => x.Handle == "3" && x.PullDogId != null)); Assert.IsTrue(repositories.Any(x => x.Handle == "4" && x.PullDogId != null)); }
public async Task Handle_SeveralSettings_ReturnsMatchingSettings() { //Arrange await using var environment = await IntegrationTestEnvironment.CreateAsync(); await environment.WithFreshDataContext(async dataContext => { await dataContext.PullDogSettings.AddAsync(new PullDogSettings() { PlanId = "dummy", User = new User() { StripeCustomerId = "dummy" }, EncryptedApiKey = Array.Empty <byte>(), Repositories = new List <PullDogRepository>() { new PullDogRepository() { Handle = "dummy", GitHubInstallationId = 1336 } } }); await dataContext.PullDogSettings.AddAsync(new PullDogSettings() { PlanId = "dummy", User = new User() { StripeCustomerId = "dummy" }, EncryptedApiKey = Array.Empty <byte>(), Repositories = new List <PullDogRepository>() { new PullDogRepository() { Handle = "dummy", GitHubInstallationId = 1337 } } }); await dataContext.PullDogSettings.AddAsync(new PullDogSettings() { PlanId = "dummy", User = new User() { StripeCustomerId = "dummy" }, EncryptedApiKey = Array.Empty <byte>(), Repositories = new List <PullDogRepository>() { new PullDogRepository() { Handle = "dummy", GitHubInstallationId = 1338 } } }); }); //Act var settings = await environment.Mediator.Send(new GetPullDogSettingsByGitHubInstallationIdQuery(1337)); //Assert Assert.IsNotNull(settings); Assert.AreEqual(1337, settings.Repositories.Single().GitHubInstallationId); }
public async Task PullDogWebhook_PullRequestNumberGivenViaPullRequest_FetchesPullRequestFromPullRequestNumber() { //Arrange var context = new WebhookPayloadContext( new WebhookPayload() { Repository = new RepositoryPayload() { Id = 1337 }, PullRequest = new PullRequestPayload() { Number = 1339 }, Installation = new InstallationPayload() { Id = 1338 } }, null !, null !, null !); var fakeMediator = Substitute.For <IMediator>(); fakeMediator .Send(Arg.Is <EnsurePullDogPullRequestCommand>(args => args.PullRequestHandle == "1339")) .Returns(new PullDogPullRequest()); fakeMediator .Send(Arg.Is <GetRepositoryByHandleQuery>(args => args.RepositoryHandle == "1337")) .Returns(new PullDogRepository() { GitHubInstallationId = 1338, PullDogSettings = new PullDogSettings() }); var fakeWebhookPayloadHandler = Substitute.For <IWebhookPayloadHandler>(); fakeWebhookPayloadHandler .CanHandle(Arg.Any <WebhookPayload>()) .Returns(true); await using var environment = await IntegrationTestEnvironment.CreateAsync(new EnvironmentSetupOptions () { IocConfiguration = services => { services.AddSingleton(fakeMediator); services.AddSingleton(fakeWebhookPayloadHandler); services.AddSingleton(Substitute.For <IConfigurationPayloadHandler>()); services.AddSingleton(GenerateTestGitHubOptions()); } }); var webhooksController = environment.ServiceProvider.GetRequiredService <WebhooksController>(); FakeOutAuthenticResponse(webhooksController); //Act await webhooksController.PullDogWebhook(context.Payload, default); //Assert fakeWebhookPayloadHandler .Received(1) .CanHandle(Arg.Any <WebhookPayload>()); await fakeWebhookPayloadHandler .Received(1) .HandleAsync(Arg.Is <WebhookPayloadContext>(args => args.PullRequest != null)); }
public async Task Handle_DatabaseInstancePresentAndAmazonExceptionThrown_NothingIsRemovedFromDatabase() { //Arrange var fakeAmazonLightsailClient = Substitute.For <IAmazonLightsail>(); fakeAmazonLightsailClient .DeleteInstanceAsync( Arg.Any <DeleteInstanceRequest>(), default) .Throws <TestException>(); var fakeLightsailOperationService = Substitute.For <ILightsailOperationService>(); await using var environment = await IntegrationTestEnvironment.CreateAsync(new EnvironmentSetupOptions () { IocConfiguration = services => { services.AddSingleton(fakeAmazonLightsailClient); services.AddSingleton(fakeLightsailOperationService); } }); var clusterId = Guid.NewGuid(); var cluster = new Cluster() { Id = clusterId, Instances = new List <Instance>() { new Instance() { Name = "not-matching", PlanId = "dummy" }, new Instance() { Name = "some-instance-name", PlanId = "dummy" } } }; await environment.WithFreshDataContext(async dataContext => { await dataContext.Clusters.AddAsync(cluster); }); //Act var exception = await Assert.ThrowsExceptionAsync <TestException>(async() => await environment.Mediator.Send( new DeleteInstanceByNameCommand("some-instance-name"), default)); //Assert Assert.IsNotNull(exception); await environment.WithFreshDataContext(async dataContext => { var refreshedCluster = await dataContext .Clusters .Include(x => x.Instances) .FirstOrDefaultAsync(x => x.Id == clusterId); var refreshedInstance = await dataContext.Instances.FirstOrDefaultAsync(x => x.Name == "some-instance-name"); Assert.IsNotNull(refreshedInstance); Assert.IsNotNull(refreshedCluster); Assert.AreEqual(2, refreshedCluster.Instances.Count); }); }
public async Task Dogfeed_ExistingDetachedInstances_DestroysDetachedInstances() { //Arrange var fakeMediator = Substitute.For <IMediator>(); FakeOutValidSupportedPlans(fakeMediator); FakeOutNewlyCreatedInstance(fakeMediator); fakeMediator .Send(Arg.Any <GetAllInstancesQuery>()) .Returns( new[] { new Instance() { Name = "some-random-instance" }, new Instance() { Name = "main-attached-instance-from-load-balancer" }, new Instance() { Name = "main-detached-instance-from-load-balancer" } }); fakeMediator .Send(Arg.Any <GetLoadBalancerByNameQuery>()) .Returns( new LoadBalancer() { InstanceHealthSummary = new List <InstanceHealthSummary>() { new InstanceHealthSummary() { InstanceName = "main-attached-instance-from-load-balancer", InstanceHealth = InstanceHealthState.Healthy }, new InstanceHealthSummary() { InstanceName = "new-instance", InstanceHealth = InstanceHealthState.Healthy } } }); await using var environment = await IntegrationTestEnvironment.CreateAsync(new EnvironmentSetupOptions () { IocConfiguration = services => { IocRegistry.ConfigureDogfeeding(services); FakeOutMinimalServices(services); services.AddSingleton(fakeMediator); } }); var dogfeedService = environment.ServiceProvider.GetRequiredService <IDogfeedService>(); //Act await dogfeedService.DogfeedAsync(); //Assert await fakeMediator .Received() .Send(Arg.Is <DeleteInstanceByNameCommand>( arg => arg.Name == "main-detached-instance-from-load-balancer")); }
public async Task Dogfeed_NewInstanceHealthTimeoutExceeded_ThrowsException() { //Arrange var fakeMediator = Substitute.For <IMediator>(); FakeOutValidSupportedPlans(fakeMediator); FakeOutNewlyCreatedInstance(fakeMediator); fakeMediator .Send(Arg.Any <GetLoadBalancerByNameQuery>()) .Returns( new LoadBalancer() { InstanceHealthSummary = new List <InstanceHealthSummary>() { new InstanceHealthSummary() { InstanceName = "new-instance", InstanceHealth = InstanceHealthState.Healthy } } }); var fakeStopwatchWithHighElapsedTime = Substitute.For <IStopwatch>(); fakeStopwatchWithHighElapsedTime .Elapsed .Returns(TimeSpan.FromMinutes(31)); var fakeTime = Substitute.For <ITime>(); fakeTime .StartStopwatch() .Returns(fakeStopwatchWithHighElapsedTime); await using var environment = await IntegrationTestEnvironment.CreateAsync(new EnvironmentSetupOptions () { IocConfiguration = services => { IocRegistry.ConfigureDogfeeding(services); FakeOutMinimalServices(services); services.AddSingleton(fakeMediator); services.AddSingleton(fakeTime); } }); var dogfeedService = environment.ServiceProvider.GetRequiredService <IDogfeedService>(); //Act var exception = await Assert.ThrowsExceptionAsync <NewInstanceHealthTimeoutException>(async() => await dogfeedService.DogfeedAsync()); //Assert Assert.IsNotNull(exception); await fakeMediator .Received() .Send(Arg.Is <DeleteInstanceByNameCommand>( arg => arg.Name == "new-instance")); }
public async Task Handle_ExistingClusterInstanceFoundAndDemoUserWithNoExpiry_ReducesExpiryToAnHour() { //Arrange await using var environment = await IntegrationTestEnvironment.CreateAsync(); var pullDogPullRequest = new PullDogPullRequest() { Handle = "dummy", PullDogRepository = new PullDogRepository() { Handle = "dummy", PullDogSettings = new PullDogSettings() { User = new User() { StripeCustomerId = "dummy" }, PoolSize = 0, PlanId = "dummy", EncryptedApiKey = Array.Empty <byte>() } } }; var oldInstance = new Instance() { Name = "existing-instance", PlanId = "dummy", PullDogPullRequest = pullDogPullRequest, Cluster = new Cluster() { Id = DataContext.PullDogDemoClusterId } }; await environment.DataContext.Instances.AddAsync(oldInstance); await environment.DataContext.SaveChangesAsync(); //Act var instance = await environment.Mediator.Send(new EnsurePullDogDatabaseInstanceCommand( pullDogPullRequest, new ConfigurationFile(new List <string>()))); //Assert Assert.AreSame(instance, oldInstance); Assert.AreEqual(instance.Name, oldInstance.Name); Assert.AreEqual(instance.Id, oldInstance.Id); await environment.WithFreshDataContext(async dataContext => { var refreshedOldInstance = await dataContext .Instances .AsNoTracking() .SingleAsync(); Assert.AreEqual(oldInstance.Name, refreshedOldInstance.Name); Assert.AreEqual(oldInstance.Id, refreshedOldInstance.Id); Assert.IsTrue(refreshedOldInstance.ExpiresAtUtc < DateTime.UtcNow.AddHours(1)); Assert.IsTrue(refreshedOldInstance.ExpiresAtUtc > DateTime.UtcNow.AddMinutes(50)); }); }
public async Task Handle_MatchingAndUnmatchingRepositoriesPresent_DeletesMatchingRepository() { //Arrange await using var environment = await IntegrationTestEnvironment.CreateAsync(); await environment.WithFreshDataContext(async dataContext => { await dataContext.PullDogRepositories.AddAsync(new PullDogRepository() { Handle = "dummy-1", PullDogSettings = new PullDogSettings() { EncryptedApiKey = Array.Empty <byte>(), PlanId = "dummy", User = new User() { StripeCustomerId = "dummy" } }, }); await dataContext.PullDogRepositories.AddAsync(new PullDogRepository() { Handle = "some-handle", PullDogSettings = new PullDogSettings() { EncryptedApiKey = Array.Empty <byte>(), PlanId = "dummy", User = new User() { StripeCustomerId = "dummy" } }, }); await dataContext.PullDogRepositories.AddAsync(new PullDogRepository() { Handle = "dummy-2", PullDogSettings = new PullDogSettings() { EncryptedApiKey = Array.Empty <byte>(), PlanId = "dummy", User = new User() { StripeCustomerId = "dummy" } }, }); }); Assert.AreEqual(3, await environment.DataContext.PullDogRepositories.CountAsync()); //Act await environment.Mediator.Send(new DeletePullDogRepositoryCommand( "some-handle")); //Assert await environment.WithFreshDataContext(async dataContext => { var repositories = await dataContext .PullDogRepositories .ToListAsync(); Assert.AreEqual(2, repositories.Count); Assert.IsFalse(repositories.Any(r => r.Handle == "some-handle")); }); }
public async Task Handle_DatabaseInstancesPresentWithPullRequests_InstanceIsRemovedFromClusterAndDatabase() { //Arrange var fakeAmazonLightsailClient = Substitute.For <IAmazonLightsail>(); fakeAmazonLightsailClient .DeleteInstanceAsync( Arg.Any <DeleteInstanceRequest>(), default) .Returns(new DeleteInstanceResponse() { Operations = new List <Operation>() }); var fakeLightsailOperationService = Substitute.For <ILightsailOperationService>(); var fakeGitHubClient = Substitute.For <IGitHubClient>(); fakeGitHubClient .GitHubApps .CreateInstallationToken(Arg.Any <long>()) .Returns(new AccessToken("dummy", DateTimeOffset.MaxValue)); var fakeGitHubClientFactory = Substitute.For <IGitHubClientFactory>(); var fakeGitHubInstallationClient = await fakeGitHubClientFactory.CreateInstallationClientAsync(1337); fakeGitHubInstallationClient .PullRequest .Get( 1338, 1339) .Returns( CreatePullRequestDto( CreateGitReferenceDto( CreateRepositoryDto( 1338)), CreateGitReferenceDto( CreateRepositoryDto( 1338)))); var fakePullDogFileCollectorFactory = Substitute.For <IPullDogFileCollectorFactory>(); await using var environment = await IntegrationTestEnvironment.CreateAsync(new EnvironmentSetupOptions () { IocConfiguration = services => { services.AddSingleton(fakeAmazonLightsailClient); services.AddSingleton(fakeLightsailOperationService); services.AddSingleton(fakeGitHubClient); services.AddSingleton(fakeGitHubClientFactory); services.AddSingleton(fakePullDogFileCollectorFactory); } }); var clusterId = Guid.NewGuid(); var cluster = new Cluster() { Id = clusterId, Instances = new List <Instance>() { new Instance() { Name = "not-matching", PlanId = "dummy", PullDogPullRequest = new PullDogPullRequest() { Handle = "dummy", PullDogRepository = new PullDogRepository() { Handle = "dummy", PullDogSettings = new PullDogSettings() { PlanId = "dummy", EncryptedApiKey = Array.Empty <byte>(), User = new User() { StripeCustomerId = "dummy" } } } } }, new Instance() { Name = "some-instance-name", PlanId = "dummy", PullDogPullRequest = new PullDogPullRequest() { Handle = "1339", PullDogRepository = new PullDogRepository() { Handle = "1338", GitHubInstallationId = 1337, PullDogSettings = new PullDogSettings() { PlanId = "dummy", EncryptedApiKey = Array.Empty <byte>(), User = new User() { StripeCustomerId = "dummy" } } } } } } }; await environment.WithFreshDataContext(async dataContext => { await dataContext.Clusters.AddAsync(cluster); }); //Act await environment.Mediator.Send( new DeleteInstanceByNameCommand("some-instance-name"), default); //Assert await environment.WithFreshDataContext(async dataContext => { var refreshedCluster = await dataContext .Clusters .Include(x => x.Instances) .FirstOrDefaultAsync(x => x.Id == clusterId); var refreshedInstance = await dataContext.Instances.FirstOrDefaultAsync(x => x.Name == "some-instance-name"); Assert.IsNull(refreshedInstance); Assert.IsNotNull(refreshedCluster); Assert.AreEqual(1, refreshedCluster.Instances.Count); Assert.AreNotEqual("some-instance-name", refreshedCluster.Instances.Single().Name); }); }
public async Task Handle_ExistingAuth0UserByGitHubUserIdPresent_DoesNothing() { //Arrange var fakeMediator = Substitute.For <IMediator>(); var fakeGitHubClientFactory = Substitute.For <IGitHubClientFactory>(); await using var environment = await IntegrationTestEnvironment.CreateAsync(new EnvironmentSetupOptions () { IocConfiguration = services => { services.AddSingleton(fakeGitHubClientFactory); services.AddSingleton(fakeMediator); } }); var userInDatabase = new Dogger.Domain.Models.User() { StripeCustomerId = "dummy", PullDogSettings = new PullDogSettings() { PlanId = "some-plan-id", EncryptedApiKey = Array.Empty <byte>(), Repositories = new List <PullDogRepository>() { new PullDogRepository() { GitHubInstallationId = 1337, Handle = "dummy" } } } }; await environment.DataContext.Users.AddAsync(userInDatabase); await environment.DataContext.SaveChangesAsync(); fakeMediator .Send(Arg.Any <GetDemoPlanQuery>()) .Returns( new Dogger.Domain.Queries.Plans.GetSupportedPlans.Plan( "demo-plan-id", 1337, new Bundle() { Price = 1337, BundleId = "demo-plan-id" }, Array.Empty <PullDogPlan>())); fakeMediator .Send(Arg.Any <GetAuth0UserFromGitHubUserIdQuery>()) .Returns(new global::Auth0.ManagementApi.Models.User() { UserId = "auth0-user-id" }); fakeMediator .Send(Arg.Is <EnsureUserForIdentityCommand>(args => args.Email == "*****@*****.**" && args.IdentityName == "auth0-user-id")) .Returns(userInDatabase); var fakeGitHubInstallationClient = await fakeGitHubClientFactory.CreateInstallationClientAsync(1337); fakeGitHubInstallationClient .GitHubApps .Installation .GetAllRepositoriesForCurrent() .Returns(new RepositoriesResponse(0, Array.Empty <Repository>())); var fakeGitHubClient = await fakeGitHubClientFactory.CreateInstallationInitiatorClientAsync("some-code"); fakeGitHubClient .User .Current() .Returns(new User()); fakeGitHubClient .User .Email .GetAll() .Returns(new[] { new EmailAddress("*****@*****.**", true, false, EmailVisibility.Public), new EmailAddress("*****@*****.**", true, true, EmailVisibility.Public), new EmailAddress("*****@*****.**", true, false, EmailVisibility.Public) }); //Act await environment.Mediator.Send(new InstallPullDogFromGitHubCommand( "some-code", 1337)); //Assert await environment.WithFreshDataContext(async dataContext => { var user = await dataContext .Users .Include(x => x.PullDogSettings) .ThenInclude(x => x.Repositories) .SingleAsync(); var settings = user.PullDogSettings; Assert.AreEqual(settings.Repositories.Single().GitHubInstallationId, 1337); Assert.AreEqual(settings.PlanId, "some-plan-id"); Assert.AreEqual(settings.PoolSize, 0); }); }
public async Task Handle_ExistingClusterInstanceFoundAndPaidUser_ReusesExistingInstanceAndUpdatesExpiry() { //Arrange await using var environment = await IntegrationTestEnvironment.CreateAsync(); var user = new User() { StripeCustomerId = "dummy" }; var pullDogPullRequest = new PullDogPullRequest() { Handle = "dummy", PullDogRepository = new PullDogRepository() { Handle = "dummy", PullDogSettings = new PullDogSettings() { User = user, PoolSize = 1, PlanId = "dummy", EncryptedApiKey = Array.Empty <byte>() } } }; var oldInstance = new Instance() { Name = "existing-instance", PlanId = "dummy", PullDogPullRequest = pullDogPullRequest, Cluster = new Cluster() { Name = "pull-dog", User = user } }; await environment.DataContext.Instances.AddAsync(oldInstance); await environment.DataContext.SaveChangesAsync(); //Act var instance = await environment.Mediator.Send(new EnsurePullDogDatabaseInstanceCommand( pullDogPullRequest, new ConfigurationFile(new List <string>()) { Expiry = TimeSpan.FromDays(30) })); //Assert Assert.AreSame(instance, oldInstance); Assert.AreEqual(instance.Name, oldInstance.Name); Assert.AreEqual(instance.Id, oldInstance.Id); await environment.WithFreshDataContext(async dataContext => { var refreshedOldInstance = await dataContext .Instances .AsNoTracking() .SingleOrDefaultAsync(x => x.Name == oldInstance.Name && x.Id == oldInstance.Id && x.ExpiresAtUtc > DateTime.UtcNow.AddDays(7)); Assert.IsNotNull(refreshedOldInstance); }); }
public async Task Handle_DeletionOfInstancesThrowsException_NothingIsCommitted() { //Arrange var fakeMediator = Substitute.For <IMediator>(); fakeMediator .Send(Arg.Is <GetPullDogPlanFromSettingsQuery>(args => args.DoggerPlanId == "some-new-plan-id")) .Returns(new PullDogPlan( "some-plan-id", 1337, 1338)); fakeMediator .Send(Arg.Any <DeleteAllPullDogInstancesForUserCommand>()) .Throws(new TestException()); await using var environment = await IntegrationTestEnvironment.CreateAsync( new EnvironmentSetupOptions () { IocConfiguration = services => services.AddSingleton(fakeMediator) }); var databaseUser = new User() { StripeCustomerId = "dummy", PullDogSettings = new PullDogSettings() { PoolSize = 1337, EncryptedApiKey = Array.Empty <byte>(), PlanId = "some-plan-id" } }; fakeMediator .Send(Arg.Is <GetUserByIdQuery>(args => args.UserId == databaseUser.Id)) .Returns(databaseUser); await environment.WithFreshDataContext(async dataContext => await dataContext.Users.AddAsync(databaseUser)); //Act var exception = await Assert.ThrowsExceptionAsync <TestException>(async() => await environment.Mediator.Send(new ChangePullDogPlanCommand( databaseUser.Id, 1338, "some-new-plan-id"))); //Assert Assert.IsNotNull(exception); await environment.WithFreshDataContext(async dataContext => { var refreshedSettings = await dataContext .PullDogSettings .AsNoTracking() .SingleOrDefaultAsync(); Assert.IsNotNull(refreshedSettings); Assert.AreEqual(1337, refreshedSettings.PoolSize); Assert.AreEqual("some-plan-id", refreshedSettings.PlanId); }); }
public async Task Handle_ProvisionedNonFreeInstancePresent_SubscriptionIsUpdated() { //Arrange var fakeInstanceId = Guid.NewGuid(); var fakeAmazonLightsailClient = Substitute.For <IAmazonLightsail>(); fakeAmazonLightsailClient .DeleteInstanceAsync( Arg.Any <DeleteInstanceRequest>(), default) .Returns(new DeleteInstanceResponse() { Operations = new List <Operation>() }); var fakeLightsailOperationService = Substitute.For <ILightsailOperationService>(); await using var environment = await IntegrationTestEnvironment.CreateAsync(new EnvironmentSetupOptions () { IocConfiguration = services => { services.AddSingleton(fakeAmazonLightsailClient); services.AddSingleton(fakeLightsailOperationService); } }); var stripeCustomerService = environment.ServiceProvider.GetRequiredService <CustomerService>(); var customer = await stripeCustomerService.CreateAsync(new CustomerCreateOptions() { Email = "*****@*****.**" }); var stripePaymentMethodService = environment.ServiceProvider.GetRequiredService <PaymentMethodService>(); var paymentMethod = await stripePaymentMethodService.AttachAsync("pm_card_visa", new PaymentMethodAttachOptions() { Customer = customer.Id }); var stripeSubscriptionService = environment.ServiceProvider.GetRequiredService <SubscriptionService>(); var subscription = await stripeSubscriptionService.CreateAsync(new SubscriptionCreateOptions() { Customer = customer.Id, DefaultPaymentMethod = paymentMethod.Id, Items = new List <SubscriptionItemOptions>() { new SubscriptionItemOptions() { Plan = "nano_2_0" } }, Metadata = new Dictionary <string, string>() { { "InstanceId", fakeInstanceId.ToString() } } }); var clusterId = Guid.NewGuid(); var user = new User() { StripeCustomerId = customer.Id, StripeSubscriptionId = subscription.Id }; var cluster = new Cluster() { Id = clusterId, User = user, UserId = user.Id }; user.Clusters.Add(cluster); var instance = new Instance() { Id = fakeInstanceId, Name = "some-instance-name", PlanId = "dummy", Cluster = cluster, ClusterId = cluster.Id, IsProvisioned = true }; cluster.Instances.Add(instance); await environment.WithFreshDataContext(async dataContext => { await dataContext.Clusters.AddAsync(cluster); await dataContext.Instances.AddAsync(instance); await dataContext.Users.AddAsync(user); }); //Act await environment.Mediator.Send( new DeleteInstanceByNameCommand("some-instance-name"), default); //Assert var refreshedSubscription = await stripeSubscriptionService.GetAsync(subscription.Id); Assert.AreNotEqual(refreshedSubscription.Status, subscription.Status); Assert.AreEqual("canceled", refreshedSubscription.Status); }