public async Task BodyThrowsInvalidProfileExceptionWhenCriticalSegmentDoesNotExist()
        {
            // Arrange
            var controller    = BuildProfileController(MediaTypeNames.Application.Json);
            var bodyViewModel = new BodyViewModel
            {
                CanonicalName = FakeArticleName,
                Segments      = new List <SegmentModel>
                {
                    new SegmentModel
                    {
                        Segment = JobProfileSegment.WhatItTakes,
                        Markup  = new HtmlString("someContent"),
                    },
                    new SegmentModel
                    {
                        Segment = JobProfileSegment.HowToBecome,
                        Markup  = new HtmlString("someContent"),
                    },
                },
            };

            A.CallTo(() => FakeJobProfileService.GetByNameAsync(A <string> .Ignored)).Returns(A.Fake <JobProfileModel>());
            A.CallTo(() => FakeJobProfileService.GetByAlternativeNameAsync(A <string> .Ignored)).Returns((JobProfileModel)null);
            A.CallTo(() => FakeMapper.Map <BodyViewModel>(A <JobProfileModel> .Ignored)).Returns(bodyViewModel);
            A.CallTo(() => FakeRedirectionSecurityService.IsValidHost(A <Uri> .Ignored)).Returns(true);

            // Act
            await Assert.ThrowsAsync <InvalidProfileException>(async() => await controller.Body(FakeArticleName).ConfigureAwait(false)).ConfigureAwait(false);

            controller.Dispose();
        }
        public async Task JobProfileControllerBodyReturnsNotAcceptable(string mediaTypeName)
        {
            // Arrange
            var expectedResult = A.Fake <JobProfileModel>();
            var controller     = BuildProfileController(mediaTypeName);

            expectedResult.CanonicalName = FakeArticleName;

            A.CallTo(() => FakeJobProfileService.GetByNameAsync(A <string> .Ignored)).Returns(expectedResult);
            A.CallTo(() => FakeRedirectionSecurityService.IsValidHost(A <Uri> .Ignored)).Returns(true);
            A.CallTo(() => FakeMapper.Map <BodyViewModel>(A <JobProfileModel> .Ignored)).Returns(DefaultBodyViewModel);

            // Act
            var result = await controller.Body(FakeArticleName).ConfigureAwait(false);

            // Assert
            A.CallTo(() => FakeJobProfileService.GetByNameAsync(A <string> .Ignored)).MustHaveHappenedOnceExactly();
            A.CallTo(() => FakeMapper.Map <BodyViewModel>(A <JobProfileModel> .Ignored)).MustHaveHappenedOnceExactly();

            var statusResult = Assert.IsType <StatusCodeResult>(result);

            Assert.Equal((int)HttpStatusCode.NotAcceptable, statusResult.StatusCode);

            controller.Dispose();
        }
        public async Task JobProfileControllerBodyJsonAndHtmlReturnsRedirectWhenAlternateArticleExistsWithValidHost(string mediaTypeName)
        {
            // Arrange
            var expectedAlternativeResult = A.Fake <JobProfileModel>();
            var controller = BuildProfileController(mediaTypeName, host: "localhosttest", whitelist: new string[] { "6357b4c93a1bfd4901871836a03602586222c6a9ae05a48d67dda806d2c2eca6" });

            A.CallTo(() => FakeJobProfileService.GetByNameAsync(A <string> .Ignored)).Returns((JobProfileModel)null);
            A.CallTo(() => FakeJobProfileService.GetByAlternativeNameAsync(A <string> .Ignored))
            .Returns(expectedAlternativeResult);
            A.CallTo(() => FakeRedirectionSecurityService.IsValidHost(A <Uri> .Ignored)).Returns(true);
            // Act
            var result = await controller.Body(FakeArticleName).ConfigureAwait(false);

            // Assert
            A.CallTo(() => FakeJobProfileService.GetByNameAsync(A <string> .Ignored)).MustHaveHappenedOnceExactly();
            A.CallTo(() => FakeJobProfileService.GetByAlternativeNameAsync(A <string> .Ignored))
            .MustHaveHappenedOnceExactly();

            var statusResult = Assert.IsType <RedirectResult>(result);

            statusResult.Url.Should().NotBeNullOrWhiteSpace();
            Assert.True(statusResult.Permanent);

            controller.Dispose();
        }
        public async Task JobProfileControllerBodyJsonReturnsSuccess(string mediaTypeName)
        {
            // Arrange
            var expectedResult = A.Dummy <JobProfileModel>();
            var controller     = BuildProfileController(mediaTypeName);

            expectedResult.CanonicalName = FakeArticleName;
            expectedResult.Segments      = new List <SegmentModel>();

            A.CallTo(() => FakeJobProfileService.GetByNameAsync(A <string> .Ignored)).Returns(expectedResult);
            A.CallTo(() => FakeRedirectionSecurityService.IsValidHost(A <Uri> .Ignored)).Returns(true);
            A.CallTo(() => FakeMapper.Map <BodyViewModel>(A <JobProfileModel> .Ignored)).Returns(DefaultBodyViewModel);

            // Act
            var result = await controller.Body(FakeArticleName).ConfigureAwait(false);

            // Assert
            A.CallTo(() => FakeJobProfileService.GetByNameAsync(A <string> .Ignored)).MustHaveHappenedOnceExactly();
            A.CallTo(() => FakeMapper.Map <BodyViewModel>(A <JobProfileModel> .Ignored)).MustHaveHappenedOnceExactly();

            var jsonResult = Assert.IsType <OkObjectResult>(result);

            Assert.IsAssignableFrom <List <SegmentModel> >(jsonResult.Value);

            controller.Dispose();
        }
        public async Task JobProfileControllerBodyHtmlAndJsonReturnsNoContentWhenNoAlternateArticle(
            string mediaTypeName)
        {
            // Arrange
            var controller = BuildProfileController(mediaTypeName);

            A.CallTo(() => FakeJobProfileService.GetByNameAsync(A <string> .Ignored)).Returns((JobProfileModel)null);
            A.CallTo(() => FakeJobProfileService.GetByAlternativeNameAsync(A <string> .Ignored))
            .Returns((JobProfileModel)null);
            A.CallTo(() => FakeRedirectionSecurityService.IsValidHost(A <Uri> .Ignored)).Returns(true);

            // Act
            var result = await controller.Body(FakeArticleName).ConfigureAwait(false);

            // Assert
            A.CallTo(() => FakeJobProfileService.GetByNameAsync(A <string> .Ignored)).MustHaveHappenedOnceExactly();
            A.CallTo(() => FakeJobProfileService.GetByAlternativeNameAsync(A <string> .Ignored))
            .MustHaveHappenedOnceExactly();
            Assert.IsType <NotFoundResult>(result);

            controller.Dispose();
        }
        public async Task BodyReturnsOfflineMarkupWhenNonCriticalSegmentsHaveNoMarkup(List <SegmentModel> segments)
        {
            // Arrange
            var controller    = BuildProfileController(MediaTypeNames.Application.Json);
            var bodyViewModel = new BodyViewModel
            {
                CanonicalName = FakeArticleName,
                Segments      = segments,
            };

            var offlineSegmentModel = new OfflineSegmentModel
            {
                OfflineMarkup = new HtmlString("<h1>Some offline markup for this non-critical segment</h1>"),
            };

            A.CallTo(() => FakeJobProfileService.GetByNameAsync(A <string> .Ignored)).Returns(A.Fake <JobProfileModel>());
            A.CallTo(() => FakeJobProfileService.GetByAlternativeNameAsync(A <string> .Ignored)).Returns((JobProfileModel)null);
            A.CallTo(() => FakeMapper.Map <BodyViewModel>(A <JobProfileModel> .Ignored)).Returns(bodyViewModel);
            A.CallTo(() => FakeSegmentService.GetOfflineSegment(A <JobProfileSegment> .Ignored)).Returns(offlineSegmentModel);
            A.CallTo(() => FakeRedirectionSecurityService.IsValidHost(A <Uri> .Ignored)).Returns(true);

            // Act
            var result = await controller.Body(FakeArticleName).ConfigureAwait(false);

            // Assert
            var okObjectResult     = result as OkObjectResult;
            var resultViewModel    = Assert.IsAssignableFrom <BodyViewModel>(okObjectResult?.Value);
            var nonCriticalSegment = segments.FirstOrDefault(s => s.Segment != JobProfileSegment.Overview && s.Segment != JobProfileSegment.HowToBecome && s.Segment != JobProfileSegment.WhatItTakes);
            var resultSegmentModel = resultViewModel.Segments.FirstOrDefault(s => s.Segment == nonCriticalSegment?.Segment);

            Assert.Equal((int)HttpStatusCode.OK, okObjectResult.StatusCode);
            A.CallTo(() => FakeSegmentService.GetOfflineSegment(A <JobProfileSegment> .Ignored)).MustHaveHappenedOnceExactly();
            Assert.Equal(offlineSegmentModel.OfflineMarkup.Value, resultSegmentModel?.Markup.Value);

            controller.Dispose();
        }