feat(aio): include more API results in search

By adding a more relaxed search on the title
of docs, we are more likely to catch API docs.

The additional search terms match anything
with a word in the title that starts with the
characters of the first term in the search.

E.g. if the search is "ngCont guide" then
search for "ngCont guide titleWords:ngCont*"
This commit is contained in:
Peter Bacon Darwin 2017-09-08 11:57:33 +01:00 committed by Matias Niemelä
parent 917d0870e8
commit 4a0466e574
3 changed files with 47 additions and 16 deletions

View File

@ -92,4 +92,10 @@ describe('site App', function() {
// Todo: add test to confirm tracking URL when navigate.
});
describe('search', () => {
it('should find pages when searching by a partial word in the title', () => {
page.enterSearch('ngCont');
expect(page.getSearchResults().map(link => link.getText())).toContain('NgControl');
});
});
});

View File

@ -1,4 +1,4 @@
import { browser, element, by, promise, ElementFinder } from 'protractor';
import { browser, element, by, promise, ElementFinder, ExpectedConditions } from 'protractor';
const githubRegex = /https:\/\/github.com\/angular\/angular\//;
@ -50,6 +50,16 @@ export class SitePage {
return browser.executeScript('window.scrollTo(0, document.body.scrollHeight)');
}
enterSearch(query: string) {
element(by.css('.search-container input[type=search]')).sendKeys(query);
}
getSearchResults() {
const results = element.all(by.css('.search-results li'));
browser.wait(ExpectedConditions.presenceOf(results.first()), 8000);
return results;
}
/**
* Replace the ambient Google Analytics tracker with homebrew spy
* don't send commands to GA during e2e testing!

View File

@ -9,7 +9,18 @@ var SEARCH_TERMS_URL = '/generated/docs/app/search-data.json';
importScripts('/assets/js/lunr.min.js');
var index;
var pages = {};
var pages /* : SearchInfo */ = {};
// interface SearchInfo {
// [key: string]: PageInfo;
// }
// interface PageInfo {
// path: string;
// type: string,
// titleWords: string;
// keyWords: string;
// }
self.onmessage = handleMessage;
@ -49,15 +60,7 @@ function handleMessage(message) {
// Use XHR to make a request to the server
function makeRequest(url, callback) {
// The JSON file that is loaded should be an array of SearchTerms:
//
// export interface SearchTerms {
// path: string;
// type: string,
// titleWords: string;
// keyWords: string;
// }
// The JSON file that is loaded should be an array of PageInfo:
var searchDataRequest = new XMLHttpRequest();
searchDataRequest.onload = function() {
callback(JSON.parse(this.responseText));
@ -68,11 +71,11 @@ function makeRequest(url, callback) {
// Create the search index from the searchInfo which contains the information about each page to be indexed
function loadIndex(searchInfo) {
function loadIndex(searchInfo /*: SearchInfo */) {
return function(index) {
// Store the pages data to be used in mapping query results back to pages
// Add search terms from each page to the search index
searchInfo.forEach(function(page) {
searchInfo.forEach(function(page /*: PageInfo */) {
index.add(page);
pages[page.path] = page;
});
@ -81,7 +84,19 @@ function loadIndex(searchInfo) {
// Query the index and return the processed results
function queryIndex(query) {
var results = index.search(query);
// Only return the array of paths to pages
return results.map(function(hit) { return pages[hit.ref]; });
try {
if (query.length) {
// Add a relaxed search in the title for the first word in the query
// E.g. if the search is "ngCont guide" then we search for "ngCont guide titleWords:ngCont*"
var titleQuery = 'titleWords:' + query.split(' ', 1)[0] + '*';
var results = index.search(query + ' ' + titleQuery);
// Map the hits into info about each page to be returned as results
return results.map(function(hit) { return pages[hit.ref]; });
}
} catch(e) {
// If the search query cannot be parsed the index throws an error
// Log it and recover
console.log(e);
}
return [];
}