public void DFC5229ForSearchResultsShowingComputedSearchTerm(bool showComputedSearchTerm, bool useRawSearchTerm) { // Arrange var searchView = new _MVC_Views_JobProfileSearchBox_SearchResult_cshtml(); var model = new JobProfileSearchResultViewModel { SearchResults = new List <JobProfileSearchResultItemViewModel>(), ShowSearchedTerm = showComputedSearchTerm, ComputedSearchTerm = useRawSearchTerm ? " plumbing" : " plumbing /.*plumb.*/ plumb~" }; // Act var htmlDom = searchView.RenderAsHtml(model); // Asserts if (showComputedSearchTerm) { GetSearchComputedTermParagraph(htmlDom).Should().Be($"ComputedSearchTerm: {model.ComputedSearchTerm}"); } else { GetSearchComputedTermParagraph(htmlDom).Should().BeNullOrEmpty(); } }
private void SetTotalResultsMessage(JobProfileSearchResultViewModel resultModel) { var totalFound = resultModel.Count; resultModel.TotalResultCount = totalFound; resultModel.TotalResultsMessage = totalFound == 0 ? NoResultsMessage : $"{totalFound} result{(totalFound == 1 ? string.Empty : "s")} found"; }
public void DFC1494ForSearchResultsDidYouMeanTerm(string correctedSearchTerm, bool validSpellcheckResult) { // Arrange var searchView = new _MVC_Views_JobProfileSearchBox_SearchResult_cshtml(); var model = new JobProfileSearchResultViewModel { DidYouMeanUrl = new Uri(validSpellcheckResult ? $"{nameof(JobProfileSearchBoxController.SearchResultsPage)}?searchTerm={HttpUtility.UrlEncode(correctedSearchTerm)}" : string.Empty, UriKind.RelativeOrAbsolute), DidYouMeanTerm = validSpellcheckResult ? correctedSearchTerm : string.Empty, SearchResults = new List <JobProfileSearchResultItemViewModel>() }; // Act var htmlDom = searchView.RenderAsHtml(model); // Asserts if (validSpellcheckResult) { GetDidYouMeanText(htmlDom).Should().Be(model.DidYouMeanTerm); GetDidYouMeanUrl(htmlDom).Should().Be(model.DidYouMeanUrl.OriginalString); } else { GetDidYouMeanText(htmlDom).Should().BeNullOrEmpty(); } }
private async Task <ActionResult> DisplaySearchResultsAsync(string searchTerm, int page) { var resultModel = new JobProfileSearchResultViewModel { PlaceholderText = PlaceholderText, SearchTerm = searchTerm, AutoCompleteMinimumCharacters = AutoCompleteMinimumCharacters, AutoCompleteMaximumCharacters = AutoCompleteMaximumCharacters, MaximumNumberOfDisplayedSuggestions = MaximumNumberOfDisplayedSuggestions, UseFuzzyAutoCompleteMatching = UseFuzzyAutoCompleteMatching, JobProfileCategoryPage = JobProfileCategoryPage, SalaryBlankText = SalaryBlankText, ShowSearchedTerm = ShowComputedSearchTerm }; if (!string.IsNullOrWhiteSpace(searchTerm)) { var pageNumber = page > 0 ? page : 1; var searchTask = searchQueryService.SearchAsync(searchTerm, new SearchProperties { Page = pageNumber, Count = this.PageSize, UseRawSearchTerm = UseRawSearchTerm }); var spellCheckTask = spellcheckService.CheckSpellingAsync(searchTerm); await Task.WhenAll(searchTask, spellCheckTask); var results = searchTask.Result; resultModel.Count = results.Count; resultModel.Coverage = results.Coverage; resultModel.ComputedSearchTerm = results.ComputedSearchTerm; resultModel.PageNumber = pageNumber; resultModel.SearchResults = mapper.Map <IEnumerable <JobProfileSearchResultItemViewModel> >(results.Results); foreach (var resultItem in resultModel.SearchResults) { resultItem.ResultItemUrlName = $"{JobProfileDetailsPage}{resultItem.ResultItemUrlName}"; } SetTotalResultsMessage(resultModel); SetupPagination(searchTerm, resultModel); var spellCheckResult = spellCheckTask.Result; if (spellCheckResult.HasCorrected) { resultModel.DidYouMeanUrl = GetSearchResultsPageUrl(spellCheckResult.CorrectedTerm); resultModel.DidYouMeanTerm = spellCheckResult.CorrectedTerm; } } return(View("SearchResult", resultModel)); }
private void SetupPagination(JobProfileSearchResultViewModel resultModel) { resultModel.TotalPages = (int)Math.Ceiling((double)resultModel.Count / PageSize); if (resultModel.TotalPages > 1 && resultModel.TotalPages >= resultModel.PageNumber) { resultModel.NextPageUrl = new Uri($"{PsfSearchResultsPage}?page={resultModel.PageNumber + 1}", UriKind.RelativeOrAbsolute); resultModel.NextPageUrlText = $"{resultModel.PageNumber + 1} of {resultModel.TotalPages}"; if (resultModel.PageNumber > 1) { resultModel.PreviousPageUrl = new Uri($"{PsfSearchResultsPage}{(resultModel.PageNumber == 2 ? string.Empty : $"?page={resultModel.PageNumber - 1}")}", UriKind.RelativeOrAbsolute); resultModel.PreviousPageUrlText = $"{resultModel.PageNumber - 1} of {resultModel.TotalPages}"; } }
private void SetMatchingSkillsCount(JobProfileSearchResultViewModel resultViewModel, PreSearchFiltersResultsModel preSearchFiltersResultsModel, SearchResult <JobProfileIndex> searchResult) { var fieldFilter = preSearchFiltersResultsModel.Sections?.FirstOrDefault(section => section.SectionDataTypes.Equals("Skills", StringComparison.InvariantCultureIgnoreCase)); if (fieldFilter?.Options.Count > 0) { var selectedSkills = fieldFilter.Options.Where(opt => opt.IsSelected).Select(opt => opt.OptionKey); foreach (var viewItem in resultViewModel.SearchResults) { var resultItem = searchResult.Results.Where(r => r.ResultItem.UrlName == viewItem.ResultItemUrlName).FirstOrDefault().ResultItem; viewItem.MatchingSkillsCount = resultItem.Skills.Count(skill => selectedSkills.Contains(skill)); } } }
public ActionResult Search(string searchTerm, string jobProfileUrl) { if (!string.IsNullOrWhiteSpace(searchTerm)) { return(Redirect($"{SearchResultsPage}?searchTerm={GetUrlEncodedString(searchTerm)}")); } switch (CurrentPageMode) { case SearchWidgetPageMode.SearchResults: var searchModel = new JobProfileSearchResultViewModel { PlaceholderText = PlaceholderText, AutoCompleteMinimumCharacters = AutoCompleteMinimumCharacters, AutoCompleteMaximumCharacters = AutoCompleteMaximumCharacters, MaximumNumberOfDisplayedSuggestions = MaximumNumberOfDisplayedSuggestions, UseFuzzyAutoCompleteMatching = UseFuzzyAutoCompleteMatching, SalaryBlankText = SalaryBlankText }; return(View("SearchResult", searchModel)); case SearchWidgetPageMode.JobProfile: bool isValidUrl = this.webAppContext.IsValidAndFormattedUrl($"{JobProfileDetailsPage}{jobProfileUrl}/"); return(isValidUrl ? (ActionResult) new RedirectResult($"{JobProfileDetailsPage}{jobProfileUrl}") : HttpNotFound()); default: var model = new JobProfileSearchBoxViewModel { PlaceholderText = PlaceholderText, AutoCompleteMinimumCharacters = AutoCompleteMinimumCharacters, AutoCompleteMaximumCharacters = AutoCompleteMaximumCharacters, MaximumNumberOfDisplayedSuggestions = MaximumNumberOfDisplayedSuggestions, UseFuzzyAutoCompleteMatching = UseFuzzyAutoCompleteMatching }; return(View("Index", model)); } }
public void SearchResultsPaginationViewModelTest(string searchTerm, SearchWidgetPageMode mode, int resultsCount, int page, int pageSize) { //Setup Fakes & dummies var queryServiceFake = A.Fake <ISearchQueryService <JobProfileIndex> >(ops => ops.Strict()); var loggerFake = A.Fake <IApplicationLogger>(); var webAppContext = A.Fake <IWebAppContext>(ops => ops.Strict()); var defaultJobProfilePage = "/jobprofile-details/"; var defaultSearchResultsPage = "/search-result"; var defaultJobProfileCateegoryPage = "/job-categories/"; var expectedTotalMessage = "0 results found - try again using a different job title"; var placeholderText = "Enter a job title or keywords"; var salaryBlankText = "Variable"; var fakeSpellChecker = A.Fake <ISpellcheckService>(); var fakeAsyncHelper = new AsyncHelper(); var mapperCfg = new MapperConfiguration(cfg => { cfg.AddProfile <JobProfilesAutoMapperProfile>(); }); var expectedSearchResultsViewModel = Enumerable.Empty <JobProfileSearchResultItemViewModel>(); var dummySearchResult = A.Dummy <SearchResult <JobProfileIndex> >(); var expectedViewModel = new JobProfileSearchResultViewModel { TotalPages = (resultsCount + pageSize - 1) / pageSize, Count = resultsCount, SearchTerm = searchTerm, PlaceholderText = placeholderText, AutoCompleteMinimumCharacters = 2, MaximumNumberOfDisplayedSuggestions = 5, UseFuzzyAutoCompleteMatching = true, JobProfileCategoryPage = defaultJobProfileCateegoryPage, SalaryBlankText = salaryBlankText, AutoCompleteMaximumCharacters = 7 }; if (string.IsNullOrWhiteSpace(searchTerm)) { dummySearchResult.Results = Enumerable.Empty <SearchResultItem <JobProfileIndex> >(); dummySearchResult.Count = 0; } else { var currentPage = page > 0 ? page : 1; var dummyIndex = new JobProfileIndex { Title = searchTerm, AlternativeTitle = new[] { "alt" }, SalaryStarter = 10, SalaryExperienced = 10, Overview = "overview", UrlName = "dummy-url", JobProfileCategoriesWithUrl = new[] { "CatOneURL|Cat One", "CatTwoURL|Cat Two" } }; dummySearchResult.Count = resultsCount; expectedTotalMessage = $"{resultsCount} result{(resultsCount == 1 ? string.Empty : "s")} found"; expectedViewModel.TotalResultsMessage = expectedTotalMessage; if (expectedViewModel.TotalPages > 1) { expectedViewModel.PageNumber = currentPage; expectedViewModel.NextPageUrl = new Uri($"{defaultSearchResultsPage}?searchTerm={HttpUtility.UrlEncode(searchTerm)}&page={currentPage + 1}", UriKind.RelativeOrAbsolute); expectedViewModel.NextPageUrlText = $"{currentPage + 1} of {expectedViewModel.TotalPages}"; if (currentPage > 1) { expectedViewModel.PreviousPageUrl = new Uri($"{defaultSearchResultsPage}?searchTerm={HttpUtility.UrlEncode(searchTerm)}&page={currentPage - 1}", UriKind.RelativeOrAbsolute); expectedViewModel.PreviousPageUrlText = $"{currentPage - 1} of {expectedViewModel.TotalPages}"; } } expectedViewModel.PageNumber = currentPage; dummySearchResult.Results = A.CollectionOfDummy <SearchResultItem <JobProfileIndex> >(resultsCount); var rawResultItems = new List <SearchResultItem <JobProfileIndex> >(); for (int i = 0; i < resultsCount; i++) { rawResultItems.Add(new SearchResultItem <JobProfileIndex> { ResultItem = dummyIndex }); } dummySearchResult.Results = rawResultItems; var expectedSearchResultsRawViewModel = new List <JobProfileSearchResultItemViewModel>(); foreach (var dummyIndexItem in dummySearchResult.Results) { expectedSearchResultsRawViewModel.Add(new JobProfileSearchResultItemViewModel { ResultItemTitle = dummyIndexItem.ResultItem.Title, ResultItemAlternativeTitle = string.Join(", ", dummyIndexItem.ResultItem.AlternativeTitle).Trim().TrimEnd(','), ResultItemSalaryRange = string.Format(new CultureInfo("en-GB", false), "{0:C0} to {1:C0}", dummyIndexItem.ResultItem.SalaryStarter, dummyIndexItem.ResultItem.SalaryExperienced), ResultItemOverview = dummyIndexItem.ResultItem.Overview, ResultItemUrlName = $"{defaultJobProfilePage}{dummyIndexItem.ResultItem.UrlName}", Rank = (int)dummyIndexItem.Rank, Score = dummyIndexItem.Score, JobProfileCategoriesWithUrl = dummyIndexItem.ResultItem.JobProfileCategoriesWithUrl }); } expectedSearchResultsViewModel = expectedSearchResultsRawViewModel.AsEnumerable(); expectedViewModel.SearchResults = expectedSearchResultsViewModel; } //Set-up calls A.CallTo(() => queryServiceFake.SearchAsync(A <string> ._, A <SearchProperties> ._)).Returns(dummySearchResult); //Instantiate var searchController = new JobProfileSearchBoxController(queryServiceFake, webAppContext, mapperCfg.CreateMapper(), loggerFake, fakeAsyncHelper, fakeSpellChecker) { CurrentPageMode = mode, JobProfileDetailsPage = defaultJobProfilePage, PageSize = pageSize, SearchResultsPage = defaultSearchResultsPage, PlaceholderText = placeholderText }; //Act var searchMethodCall = searchController.WithCallTo(c => c.Index(searchTerm, page)); if (mode == SearchWidgetPageMode.SearchResults) { //Assert searchMethodCall .ShouldRenderView("SearchResult") .WithModel <JobProfileSearchResultViewModel>(vm => { vm.Should().BeEquivalentTo(expectedViewModel); }) .AndNoModelErrors() ; A.CallTo(() => queryServiceFake.SearchAsync(A <string> ._, A <SearchProperties> .That.Matches(m => m.Page == page && m.Count == pageSize))).MustHaveHappened(); A.CallTo(() => fakeSpellChecker.CheckSpellingAsync(A <string> ._)).MustHaveHappened(); } }