public async Task Handle_DemoInstanceAlreadyProvisioned_UpdatesPullRequestCommentWithMessageExplainingWhy()
        {
            //Arrange
            var fakeMediator = Substitute.For <IMediator>();

            fakeMediator
            .Send(Arg.Any <EnsurePullDogDatabaseInstanceCommand>())
            .Throws(new PullDogDemoInstanceAlreadyProvisionedException(new []
            {
                new PullRequestDetails(
                    "some-repository-name",
                    "some-indirect-pull-request-link",
                    "some-direct-pull-request-link")
            }));

            fakeMediator
            .Send(Arg.Any <EnsurePullDogPullRequestCommand>())
            .Returns(new PullDogPullRequest());

            fakeMediator
            .Send(Arg.Any <GetConfigurationForPullRequestQuery>())
            .Returns(new ConfigurationFile(new List <string>()));

            var fakeProvisioningService         = Substitute.For <IProvisioningService>();
            var fakeSlackClient                 = Substitute.For <ISlackClient>();
            var fakePullDogFileCollectorFactory = Substitute.For <IPullDogFileCollectorFactory>();

            var fakePullDogRepositoryClient = await fakePullDogFileCollectorFactory.CreateAsync(Arg.Any <PullDogPullRequest>());

            fakePullDogRepositoryClient
            .GetRepositoryFilesFromConfiguration(Arg.Any <ConfigurationFile>())
            .Returns(Array.Empty <RepositoryFile>());

            var handler = new ProvisionPullDogEnvironmentCommandHandler(
                fakeMediator,
                fakeProvisioningService,
                fakeSlackClient,
                fakePullDogFileCollectorFactory);

            //Act
            await handler.Handle(
                new ProvisionPullDogEnvironmentCommand(
                    "some-pull-request-handle",
                    new PullDogRepository()
            {
                GitHubInstallationId = 1337,
                PullDogSettings = new PullDogSettings()
            }),
                default);

            //Assert
            await fakeProvisioningService
            .DidNotReceive()
            .ScheduleJobAsync(
                Arg.Any <AggregateProvisioningStateFlow>());

            await fakeMediator
            .Received(1)
            .Send(Arg.Any <UpsertPullRequestCommentCommand>());
        }
        public async Task Handle_InstallationIdNotFound_ThrowsException()
        {
            //Arrange
            var fakeMediator                    = Substitute.For <IMediator>();
            var fakeProvisioningService         = Substitute.For <IProvisioningService>();
            var fakeSlackClient                 = Substitute.For <ISlackClient>();
            var fakePullDogFileCollectorFactory = Substitute.For <IPullDogFileCollectorFactory>();

            var fakePullDogRepositoryClient = await fakePullDogFileCollectorFactory.CreateAsync(Arg.Any <PullDogPullRequest>());

            fakePullDogRepositoryClient
            .GetRepositoryFilesFromConfiguration(Arg.Any <ConfigurationFile>())
            .Returns(Array.Empty <RepositoryFile>());

            var handler = new ProvisionPullDogEnvironmentCommandHandler(
                fakeMediator,
                fakeProvisioningService,
                fakeSlackClient,
                fakePullDogFileCollectorFactory);

            //Act
            var exception = await Assert.ThrowsExceptionAsync <InvalidOperationException>(async() =>
                                                                                          await handler.Handle(
                                                                                              new ProvisionPullDogEnvironmentCommand(
                                                                                                  "some-pull-request-handle",
                                                                                                  new PullDogRepository()
            {
                GitHubInstallationId = null,
                PullDogSettings      = new PullDogSettings()
            }),
                                                                                              default));

            //Assert
            Assert.IsNotNull(exception);
        }
        public async Task Handle_ValidProvisionConditionsGiven_SchedulesJobWithDockerComposeContents()
        {
            //Arrange
            var databaseInstance = new Instance()
            {
                Name = "some-instance-name"
            };

            var fakeMediator = Substitute.For <IMediator>();

            fakeMediator
            .Send(Arg.Any <EnsurePullDogDatabaseInstanceCommand>())
            .Returns(databaseInstance);

            fakeMediator
            .Send(Arg.Any <EnsurePullDogPullRequestCommand>())
            .Returns(new PullDogPullRequest());

            fakeMediator
            .Send(Arg.Any <GetConfigurationForPullRequestQuery>())
            .Returns(new ConfigurationFile(new List <string> {
                "some-docker-compose-path"
            }));

            var fakeProvisioningService         = Substitute.For <IProvisioningService>();
            var fakeSlackClient                 = Substitute.For <ISlackClient>();
            var fakePullDogFileCollectorFactory = Substitute.For <IPullDogFileCollectorFactory>();

            var fakePullDogRepositoryClient = await fakePullDogFileCollectorFactory.CreateAsync(Arg.Any <PullDogPullRequest>());

            fakePullDogRepositoryClient
            .GetRepositoryFilesFromConfiguration(Arg.Any <ConfigurationFile>())
            .Returns(Array.Empty <RepositoryFile>());

            var handler = new ProvisionPullDogEnvironmentCommandHandler(
                fakeMediator,
                fakeProvisioningService,
                fakeSlackClient,
                fakePullDogFileCollectorFactory);

            //Act
            await handler.Handle(
                new ProvisionPullDogEnvironmentCommand(
                    "some-pull-request-handle",
                    new PullDogRepository()
            {
                GitHubInstallationId = 1337,
                PullDogSettings = new PullDogSettings()
            }),
                default);

            //Assert
            await fakeProvisioningService
            .Received(1)
            .ScheduleJobAsync(
                Arg.Is <AggregateProvisioningStateFlow>(args =>
                                                        args.GetFlowOfType <DeployToClusterStateFlow>(1).DockerComposeYmlFilePaths.Single() == "some-docker-compose-path"));
        }
        public async Task Handle_DockerComposeYmlContentsNotFound_ExplainsWhyInComment()
        {
            //Arrange
            var fakeMediator = Substitute.For <IMediator>();

            fakeMediator
            .Send(Arg.Any <EnsurePullDogPullRequestCommand>())
            .Returns(new PullDogPullRequest());

            fakeMediator
            .Send(Arg.Any <GetConfigurationForPullRequestQuery>())
            .Returns(new ConfigurationFile(new List <string>()));

            var fakeProvisioningService         = Substitute.For <IProvisioningService>();
            var fakeSlackClient                 = Substitute.For <ISlackClient>();
            var fakePullDogFileCollectorFactory = Substitute.For <IPullDogFileCollectorFactory>();

            var fakePullDogRepositoryClient = await fakePullDogFileCollectorFactory.CreateAsync(Arg.Any <PullDogPullRequest>());

            fakePullDogRepositoryClient
            .GetConfigurationFileAsync()
            .Returns(new ConfigurationFile(new List <string>()));

            fakePullDogRepositoryClient
            .GetRepositoryFilesFromConfiguration(Arg.Any <ConfigurationFile>())
            .Returns((RepositoryFile[])null);

            var handler = new ProvisionPullDogEnvironmentCommandHandler(
                fakeMediator,
                fakeProvisioningService,
                fakeSlackClient,
                fakePullDogFileCollectorFactory);

            //Act
            await handler.Handle(
                new ProvisionPullDogEnvironmentCommand(
                    "some-pull-request-handle",
                    new PullDogRepository()
            {
                GitHubInstallationId = 1337,
                PullDogSettings = new PullDogSettings()
            }),
                default);

            //Assert
            await fakePullDogRepositoryClient
            .Received(1)
            .GetRepositoryFilesFromConfiguration(Arg.Any <ConfigurationFile>());

            await fakeMediator
            .Received(1)
            .Send(Arg.Any <UpsertPullRequestCommentCommand>());
        }
        public async Task Handle_NoConfigurationFileFound_DoesNothing()
        {
            //Arrange
            var fakeMediator = Substitute.For <IMediator>();

            fakeMediator
            .Send(Arg.Any <EnsurePullDogDatabaseInstanceCommand>())
            .Throws(new PullDogDemoInstanceAlreadyProvisionedException(Array.Empty <PullRequestDetails>()));

            fakeMediator
            .Send(Arg.Any <EnsurePullDogPullRequestCommand>())
            .Returns(new PullDogPullRequest());

            var fakeProvisioningService         = Substitute.For <IProvisioningService>();
            var fakeSlackClient                 = Substitute.For <ISlackClient>();
            var fakePullDogFileCollectorFactory = Substitute.For <IPullDogFileCollectorFactory>();

            var fakePullDogRepositoryClient = await fakePullDogFileCollectorFactory.CreateAsync(Arg.Any <PullDogPullRequest>());

            fakePullDogRepositoryClient
            .GetConfigurationFileAsync()
            .Returns((ConfigurationFile)null);

            fakePullDogRepositoryClient
            .GetRepositoryFilesFromConfiguration(Arg.Any <ConfigurationFile>())
            .Returns(Array.Empty <RepositoryFile>());

            var handler = new ProvisionPullDogEnvironmentCommandHandler(
                fakeMediator,
                fakeProvisioningService,
                fakeSlackClient,
                fakePullDogFileCollectorFactory);

            //Act
            await handler.Handle(
                new ProvisionPullDogEnvironmentCommand(
                    "some-pull-request-handle",
                    new PullDogRepository()
            {
                GitHubInstallationId = 1337,
                PullDogSettings = new PullDogSettings()
            }),
                default);

            //Assert
            await fakeProvisioningService
            .DidNotReceive()
            .ScheduleJobAsync(
                Arg.Any <AggregateProvisioningStateFlow>());
        }
        public async Task Handle_ConfigurationOverridePresentInRequest_UpdatesPullRequestConfigurationOverride()
        {
            //Arrange
            var databaseInstance = new Instance()
            {
                Name = "some-instance-name"
            };

            var fakeMediator = Substitute.For <IMediator>();

            fakeMediator
            .Send(Arg.Any <EnsurePullDogDatabaseInstanceCommand>())
            .Returns(databaseInstance);

            fakeMediator
            .Send(Arg.Any <EnsurePullDogPullRequestCommand>())
            .Returns(new PullDogPullRequest());

            fakeMediator
            .Send(Arg.Any <GetConfigurationForPullRequestQuery>())
            .Returns(new ConfigurationFile(new List <string>()));

            var fakeProvisioningService         = Substitute.For <IProvisioningService>();
            var fakeSlackClient                 = Substitute.For <ISlackClient>();
            var fakePullDogFileCollectorFactory = Substitute.For <IPullDogFileCollectorFactory>();

            var fakePullDogRepositoryClient = await fakePullDogFileCollectorFactory.CreateAsync(Arg.Any <PullDogPullRequest>());

            fakePullDogRepositoryClient
            .GetRepositoryFilesFromConfiguration(Arg.Any <ConfigurationFile>())
            .Returns(Array.Empty <RepositoryFile>());

            var handler = new ProvisionPullDogEnvironmentCommandHandler(
                fakeMediator,
                fakeProvisioningService,
                fakeSlackClient,
                fakePullDogFileCollectorFactory);

            //Act
            await handler.Handle(
                new ProvisionPullDogEnvironmentCommand(
                    "some-pull-request-handle",
                    new PullDogRepository()
            {
                GitHubInstallationId = 1337,
                PullDogSettings = new PullDogSettings()
            })
            {
                ConfigurationOverride = new ConfigurationFileOverride()
            },
                default);

            //Assert
            await fakeProvisioningService
            .Received(1)
            .ScheduleJobAsync(
                Arg.Any <AggregateProvisioningStateFlow>());

            await fakeMediator
            .Received(1)
            .Send(Arg.Any <OverrideConfigurationForPullRequestCommand>());
        }