private static void IndexReturnsCorrectDataWhenUserIsOrgAdmin()
        {
            const int organizationId = 99;
            var mockMediator = new Mock<IMediator>();
            mockMediator.Setup(x => x.Send(It.Is<CampaignListQuery>(c => c.OrganizationId == organizationId)))
                .Returns((CampaignListQuery q) => 
                {
                    var ret = new List<CampaignSummaryViewModel>
                    {
                        new CampaignSummaryViewModel { OrganizationId = organizationId }
                    };
                    return ret;
                }
            );

            var controller = new CampaignController(mockMediator.Object, null);
            controller.MakeUserAnOrgAdmin(organizationId.ToString());

            var view = (ViewResult)controller.Index();
            mockMediator.Verify(mock => mock.Send(It.Is<CampaignListQuery>(c => c.OrganizationId == organizationId)));

            // Org admin should only see own campaigns
            var viewModel = (IEnumerable<CampaignSummaryViewModel>)view.ViewData.Model;
            Assert.NotNull(viewModel);
            Assert.Equal(viewModel.Count(), 1);
            Assert.Equal(viewModel.First().OrganizationId, organizationId);
        }
        public void IndexSendsCampaignListQueryWithCorrectDataWhenUserIsOrgAdmin()
        {
            const int organizationId = 99;
            var mockMediator = new Mock<IMediator>();

            var controller = new CampaignController(mockMediator.Object, null);
            controller.MakeUserAnOrgAdmin(organizationId.ToString());
            controller.Index();

            mockMediator.Verify(mock => mock.Send(It.Is<CampaignListQuery>(q => q.OrganizationId == organizationId)));
        }
        public async Task IndexSendsIndexQueryWithCorrectData_WhenUserIsOrgAdmin()
        {
            const int organizationId = 99;
            var mockMediator = new Mock<IMediator>();

            var sut = new CampaignController(mockMediator.Object, null);
            sut.MakeUserAnOrgAdmin(organizationId.ToString());
            await sut.Index();

            mockMediator.Verify(mock => mock.SendAsync(It.Is<IndexQuery>(q => q.OrganizationId == organizationId)));
        }
        public async Task EditPostInsertsCampaign()
        {
            var OrganizationId = 99;
            var NewCampaignId = 100;
            var mockMediator = new Mock<IMediator>();
            mockMediator.Setup(x => x.SendAsync(It.IsAny<EditCampaignCommand>()))
                .Returns((EditCampaignCommand q) => Task.FromResult<int>(NewCampaignId) );

            var mockImageService = new Mock<IImageService>();
            var controller = new CampaignController(mockMediator.Object, mockImageService.Object);
            controller.MakeUserAnOrgAdmin(OrganizationId.ToString());

            var model = MassiveTrafficLightOutage_model;
            model.OrganizationId = OrganizationId;

            // verify the model is valid
            var validationContext = new ValidationContext(model, null, null);
            var validationResults = new List<ValidationResult>();
            Validator.TryValidateObject(model, validationContext, validationResults);
            Assert.Equal(0, validationResults.Count());

            var file = FormFile("image/jpeg");
            var view = (RedirectToActionResult) await controller.Edit(model, file);

            // verify the edit(add) is called
            mockMediator.Verify(mock => mock.SendAsync(It.Is<EditCampaignCommand>(c => c.Campaign.OrganizationId == OrganizationId)));

            // verify that the next route
            Assert.Equal(view.RouteValues["area"], "Admin");
            Assert.Equal(view.RouteValues["id"], NewCampaignId);

        }
        public async Task EditPostAddsCorrectKeyAndErrorMessageToModelStateWhenCampaignEndDateIsLessThanCampainStartDate()
        {
            var campaignSummaryModel = new CampaignSummaryViewModel { OrganizationId = 1, StartDate = DateTime.Now.AddDays(1), EndDate = DateTime.Now.AddDays(-1)};

            var sut = new CampaignController(null, null);
            sut.MakeUserAnOrgAdmin(campaignSummaryModel.OrganizationId.ToString());

            await sut.Edit(campaignSummaryModel, null);
            var modelStateErrorCollection = sut.ModelState.GetErrorMessagesByKey(nameof(CampaignSummaryViewModel.EndDate));

            Assert.Equal(modelStateErrorCollection.Single().ErrorMessage, "The end date must fall on or after the start date.");
        }
        public async Task DetailsReturnsCorrectViewModelWhenViewModelIsNotNullAndUserIsOrgAdmin()
        {
            const int campaignId = 100;
            const int organizationId = 99;
            var mockMediator = new Mock<IMediator>();

            // model is not null
            mockMediator.Setup(mock => mock.SendAsync(It.Is<CampaignDetailQuery>(c=>c.CampaignId == campaignId))).ReturnsAsync(new CampaignDetailViewModel { OrganizationId = organizationId, Id = campaignId }).Verifiable();

            // user is org admin
            var controller = new CampaignController(mockMediator.Object, null);
            controller.MakeUserAnOrgAdmin(organizationId.ToString());

            var view = (ViewResult)(await controller.Details(campaignId));
            var viewModel = (CampaignDetailViewModel)view.ViewData.Model;
            Assert.Equal(viewModel.Id, campaignId);
            Assert.Equal(viewModel.OrganizationId, organizationId);
        }
        public async Task DeleteCampaignImageCallsEditCampaignCommandWithCorrectData()
        {
            var mediatorMock = new Mock<IMediator>();

            var campaignSummaryViewModel = new CampaignSummaryViewModel
            {
                OrganizationId = 1,
                ImageUrl = "URL!"
            };

            mediatorMock.Setup(m => m.SendAsync(It.IsAny<CampaignSummaryQuery>())).ReturnsAsync(campaignSummaryViewModel);

            var imageServiceMock = new Mock<IImageService>();

            var sut = new CampaignController(mediatorMock.Object, imageServiceMock.Object);
            sut.MakeUserAnOrgAdmin(campaignSummaryViewModel.OrganizationId.ToString());

            await sut.DeleteCampaignImage(It.IsAny<int>());

            mediatorMock.Verify(m => m.SendAsync(It.Is<EditCampaignCommand>(s => s.Campaign == campaignSummaryViewModel)), Times.Once);
        }
        public async Task DetailConfirmedRedirectsToCorrectActionWithCorrectRouteValuesWhenUserIsOrgAdmin()
        {
            const int organizationId = 1;
            const int campaignId = 100;

            var mockMediator = new Mock<IMediator>();
            mockMediator.Setup(mock => mock.SendAsync(It.IsAny<CampaignSummaryQuery>())).ReturnsAsync(new CampaignSummaryViewModel { OrganizationId = organizationId });

            var sut = new CampaignController(mockMediator.Object, null);
            sut.MakeUserAnOrgAdmin(organizationId.ToString());

            var routeValues = new Dictionary<string, object> { ["area"] = "Admin" };

            var result = await sut.DeleteConfirmed(campaignId) as RedirectToActionResult;
            Assert.Equal(result.ActionName, nameof(CampaignController.Index));
            Assert.Equal(result.RouteValues, routeValues);
        }
        public async Task DeleteReturnsCorrectViewModelWhenUserIsOrgAdmin()
        {
            const int organizationId = 99;
            const int campaignId = 100;

            var mockMediator = new Mock<IMediator>();
            mockMediator.Setup(mock => mock.SendAsync(It.Is<CampaignSummaryQuery>(c => c.CampaignId == campaignId))).ReturnsAsync(new CampaignSummaryViewModel { Id = campaignId, OrganizationId = organizationId });

            var controller = new CampaignController(mockMediator.Object, null);
            controller.MakeUserAnOrgAdmin(organizationId.ToString());

            var view = (ViewResult)await controller.Delete(campaignId);
            var viewModel = (CampaignSummaryViewModel)view.ViewData.Model;

            Assert.Equal(viewModel.Id, campaignId);
        }
        public async Task DeleteSendsDeleteQueryWithCorrectCampaignId()
        {
            const int organizationId = 99;
            const int campaignId = 100;

            var mockMediator = new Mock<IMediator>();
            mockMediator.Setup(mock => mock.SendAsync(It.Is<DeleteViewModelQuery>(c => c.CampaignId == campaignId))).ReturnsAsync(new DeleteViewModel { Id = campaignId, OrganizationId = organizationId });

            var sut = new CampaignController(mockMediator.Object, null);
            sut.MakeUserAnOrgAdmin(organizationId.ToString());
            await sut.Delete(campaignId);

            mockMediator.Verify(mock => mock.SendAsync(It.Is<DeleteViewModelQuery>(c => c.CampaignId == campaignId)), Times.Once);
        }
        public async Task EditPostDoesNotInvokeDeleteImageAsync__WhenCampaignDoesNotHaveAnImage()
        {
            const int organizationId = 1;
            const int campaignId = 100;

            var mockMediator = new Mock<IMediator>();
            var mockImageService = new Mock<IImageService>();

            var file = FormFile("image/jpeg");
            mockImageService.Setup(x => x.UploadCampaignImageAsync(It.IsAny<int>(), It.IsAny<int>(), file)).ReturnsAsync("newImageUrl");

            var sut = new CampaignController(mockMediator.Object, mockImageService.Object);
            sut.MakeUserAnOrgAdmin(organizationId.ToString());

            var campaignSummaryViewModel = new CampaignSummaryViewModel
            {
                OrganizationId = organizationId,
                Id = campaignId,
                StartDate = new DateTimeOffset(new DateTime(2016, 2, 13)),
                EndDate = new DateTimeOffset(new DateTime(2016, 2, 14)),
            };

            await sut.Edit(campaignSummaryViewModel, file);
            mockImageService.Verify(mock => mock.DeleteImageAsync(It.IsAny<string>()), Times.Never);
        }
        public async Task EditPostInvokesUploadCampaignImageAsyncWithTheCorrectParameters_WhenFileUploadIsNotNull_AndFileIsAcceptableContentType()
        {
            const int organizationId = 1;
            const int campaignId = 100;

            var mockMediator = new Mock<IMediator>();
            var mockImageService = new Mock<IImageService>();

            var sut = new CampaignController(mockMediator.Object, mockImageService.Object);
            sut.MakeUserAnOrgAdmin(organizationId.ToString());

            var file = FormFile("image/jpeg");

            await sut.Edit(new CampaignSummaryViewModel { Name = "Foo", OrganizationId = organizationId, Id = campaignId}, file);

            mockImageService.Verify(mock => mock.UploadCampaignImageAsync(
                It.Is<int>(i => i == organizationId),
                It.Is<int>(i => i == campaignId),
                It.Is<IFormFile>(i => i == file)), Times.Once);
        }
        public async Task EditPostRedirectsToCorrectActionWithCorrectRouteValuesWhenModelStateIsValid()
        {
            const int organizationId = 99;
            const int campaignId = 100;

            var mockMediator = new Mock<IMediator>();
            mockMediator.Setup(x => x.SendAsync(It.IsAny<EditCampaignCommand>())).ReturnsAsync(campaignId);
            var sut = new CampaignController(mockMediator.Object, new Mock<IImageService>().Object);
            sut.MakeUserAnOrgAdmin(organizationId.ToString());

            var result = (RedirectToActionResult) await sut.Edit(new CampaignSummaryViewModel { Name = "Foo", OrganizationId = organizationId, Id = campaignId }, null);

            Assert.Equal(result.ActionName, "Details");
            Assert.Equal(result.RouteValues["area"], "Admin");
            Assert.Equal(result.RouteValues["id"], campaignId);
        }
        public async Task DeleteConfirmedSendsDeleteCampaignCommandWithCorrectCampaignId()
        {
            var viewModel = new DeleteViewModel {Id = 1 , OrganizationId = 1};

            var mediator = new Mock<IMediator>();
            mediator.Setup(a => a.SendAsync(It.IsAny<DeleteCampaignCommand>())).Verifiable();
            var sut = new CampaignController(mediator.Object, null);
            sut.MakeUserAnOrgAdmin(viewModel.OrganizationId.ToString());
            await sut.DeleteConfirmed(viewModel);

            mediator.Verify(mock => mock.SendAsync(It.Is<DeleteCampaignCommand>(i => i.CampaignId == viewModel.Id)), Times.Once);
        }
        public async Task DeleteCampaignImageReturnsJsonObjectWithStatusOfNothingToDeleteIfThereWasNoExistingImage()
        {
            var mediatorMock = new Mock<IMediator>();

            var campaignSummaryViewModel = new CampaignSummaryViewModel
            {
                OrganizationId = 1
            };

            mediatorMock.Setup(m => m.SendAsync(It.IsAny<CampaignSummaryQuery>())).ReturnsAsync(campaignSummaryViewModel);

            var imageServiceMock = new Mock<IImageService>();

            var sut = new CampaignController(mediatorMock.Object, imageServiceMock.Object);
            sut.MakeUserAnOrgAdmin(campaignSummaryViewModel.OrganizationId.ToString());

            var result = await sut.DeleteCampaignImage(It.IsAny<int>());

            result.Value.GetType()
                .GetProperty("status")
                .GetValue(result.Value)
                .ShouldBe("NothingToDelete");
        }
        public async Task EditPostReturnsCorrectViewModelWhenInvalidImageFormatIsSupplied()
        {
            const int organizationId = 100;
            var mockMediator = new Mock<IMediator>();
            var mockImageService = new Mock<IImageService>();

            var sut = new CampaignController(mockMediator.Object, mockImageService.Object);
            sut.MakeUserAnOrgAdmin(organizationId.ToString());

            var file = FormFile("audio/mpeg3");
            var model = MassiveTrafficLightOutage_model;
            model.OrganizationId = organizationId;

            var view = (ViewResult)(await sut.Edit(model, file));
            var viewModel = (CampaignSummaryViewModel)view.ViewData.Model;
            Assert.True(Object.ReferenceEquals(model, viewModel));
        }
        public async Task EditPostUploadsImageToImageService()
        {
            const int organizationId = 1;
            const int campaignId = 100;

            var mockMediator = new Mock<IMediator>();
            var mockImageService = new Mock<IImageService>();

            var sut = new CampaignController(mockMediator.Object, mockImageService.Object);
            sut.MakeUserAnOrgAdmin(organizationId.ToString());

            var file = FormFile("image/jpeg");

            await sut.Edit(new CampaignSummaryViewModel { Name = "Foo", OrganizationId = organizationId, Id = campaignId}, file);

            mockImageService.Verify(mock => mock.UploadCampaignImageAsync(
                        It.Is<int>(i => i == organizationId),
                        It.Is<int>(i => i == campaignId),
                It.Is<IFormFile>(i => i == file)), Times.Once);
        }
        public async Task DeleteReturnsCorrectViewWhenUserIsOrgAdmin()
        {
            const int organizationId = 1;

            var mediator = new Mock<IMediator>();
            mediator.Setup(x => x.SendAsync(It.IsAny<DeleteViewModelQuery>())).ReturnsAsync(new DeleteViewModel { OrganizationId = organizationId });

            var sut = new CampaignController(mediator.Object, null);
            sut.MakeUserAnOrgAdmin(organizationId.ToString());

            Assert.IsType<ViewResult>(await sut.Delete(It.IsAny<int>()));
        }
        public async Task DetailConfirmedSendsDeleteCampaignCommandWithCorrectCampaignIdWhenUserIsOrgAdmin()
        {
            const int organizationId = 1;
            const int campaignId = 100;

            var mockMediator = new Mock<IMediator>();
            mockMediator.Setup(mock => mock.SendAsync(It.IsAny<CampaignSummaryQuery>())).ReturnsAsync(new CampaignSummaryViewModel { OrganizationId = organizationId });

            var sut = new CampaignController(mockMediator.Object, null);
            sut.MakeUserAnOrgAdmin(organizationId.ToString());

            await sut.DeleteConfirmed(campaignId);

            mockMediator.Verify(mock => mock.SendAsync(It.Is<DeleteCampaignCommand>(i => i.CampaignId == campaignId)), Times.Once);
        }
        public async Task DetailConfirmedSendsDeleteCampaignCommandWithCorrectCampaignIdWhenUserIsOrgAdmin()
        {
            const int organizationId = 1;

            var mockMediator = new Mock<IMediator>();

            var viewModel = new DeleteViewModel { Id = 100, UserIsOrgAdmin = true };

            var sut = new CampaignController(mockMediator.Object, null);
            sut.MakeUserAnOrgAdmin(organizationId.ToString());

            await sut.DeleteConfirmed(viewModel);

            mockMediator.Verify(mock => mock.SendAsync(It.Is<DeleteCampaignCommand>(i => i.CampaignId == viewModel.Id)), Times.Once);
        }
        public async Task DetailConfirmedRedirectsToCorrectActionWithCorrectRouteValuesWhenUserIsOrgAdmin()
        {
            const int organizationId = 1;

            var viewModel = new DeleteViewModel { Id = 100, UserIsOrgAdmin = true };

            var sut = new CampaignController(Mock.Of<IMediator>(), null);
            sut.MakeUserAnOrgAdmin(organizationId.ToString());

            var routeValues = new Dictionary<string, object> { ["area"] = "Admin" };

            var result = await sut.DeleteConfirmed(viewModel) as RedirectToActionResult;
            Assert.Equal(result.ActionName, nameof(CampaignController.Index));
            Assert.Equal(result.RouteValues, routeValues);
        }
        public async Task DeleteCampaignImageReturnsJsonObjectWithStatusOfDateInvalidIfCampaignEndDateIsLessThanStartDate()
        {
            var mediatorMock = new Mock<IMediator>();

            var campaignSummaryViewModel = new CampaignSummaryViewModel
            {
                OrganizationId = 1,
                StartDate = DateTimeOffset.Now.AddDays(10),
                EndDate = DateTimeOffset.Now
            };
            mediatorMock.Setup(m => m.SendAsync(It.IsAny<CampaignSummaryQuery>())).ReturnsAsync(campaignSummaryViewModel);

            var imageServiceMock = new Mock<IImageService>();

            var sut = new CampaignController(mediatorMock.Object, imageServiceMock.Object);
            sut.MakeUserAnOrgAdmin(campaignSummaryViewModel.OrganizationId.ToString());

            var result = await sut.DeleteCampaignImage(It.IsAny<int>());

            result.Value.GetType()
                .GetProperty("status")
                .GetValue(result.Value)
                .ShouldBe("DateInvalid");

            result.Value.GetType()
                .GetProperty("message")
                .GetValue(result.Value)
                .ShouldBe("The end date must fall on or after the start date.");
        }