Commit 90a03402 authored by Esmael El-Moslimany's avatar Esmael El-Moslimany Committed by Commit Bot

Settings WebUI: when text changes in settings, redo search

Bug: 711156
Cq-Include-Trybots: master.tryserver.chromium.linux:closure_compilation
Change-Id: Ic2847a86c7ec3671db79e524a25fa15c08193455
Reviewed-on: https://chromium-review.googlesource.com/996768Reviewed-by: default avatarHector Carmona <hcarmona@chromium.org>
Commit-Queue: Esmael El-Moslimany <aee@chromium.org>
Cr-Commit-Position: refs/heads/master@{#548689}
parent a34d11a6
...@@ -170,34 +170,15 @@ Polymer({ ...@@ -170,34 +170,15 @@ Polymer({
* sections. * sections.
* @param {string} query The text to search for. * @param {string} query The text to search for.
* @return {!Promise<!settings.SearchResult>} A signal indicating that * @return {!Promise<!settings.SearchResult>} A signal indicating that
* searching finished. * searching finished.
*/ */
searchContents: function(query) { searchContents: function(query) {
const whenSearchDone = [ const nodes = [assert(this.$$('#basicPage'))];
settings.getSearchManager().search(query, assert(this.$$('#basicPage'))), if (this.pageVisibility.advancedSettings !== false)
]; nodes.push(this.$$('#advancedPageTemplate').get());
if (this.pageVisibility.advancedSettings !== false) {
whenSearchDone.push(
this.$$('#advancedPageTemplate').get().then(function(advancedPage) {
return settings.getSearchManager().search(query, advancedPage);
}));
}
return Promise.all(whenSearchDone).then(function(requests) { return Promise.all(nodes).then(
// Combine the SearchRequests results to a single SearchResult object. nodes => settings.getSearchManager().search(query, nodes));
return {
canceled: requests.some(function(r) {
return r.canceled;
}),
didFindMatches: requests.some(function(r) {
return r.didFindMatches();
}),
// All requests correspond to the same user query, so only need to check
// one of them.
wasClearSearch: requests[0].isSame(''),
};
});
}, },
// <if expr="chromeos"> // <if expr="chromeos">
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
<div class="settings-box first two-line"> <div class="settings-box first two-line">
<div class="start"> <div class="start">
<div>$i18n{downloadLocation}</div> <div>$i18n{downloadLocation}</div>
<div class="secondary" no-search> <div class="secondary">
<if expr="not chromeos"> <if expr="not chromeos">
[[prefs.download.default_directory.value]] [[prefs.download.default_directory.value]]
</if> </if>
......
...@@ -87,6 +87,7 @@ Polymer({ ...@@ -87,6 +87,7 @@ Polymer({
attached: function() { attached: function() {
this.listen(this, 'freeze-scroll', 'onFreezeScroll_'); this.listen(this, 'freeze-scroll', 'onFreezeScroll_');
this.listen(this, 'lazy-loaded', 'onLazyLoaded_'); this.listen(this, 'lazy-loaded', 'onLazyLoaded_');
this.registerSearchManagerObserver_();
}, },
/** @private */ /** @private */
...@@ -250,42 +251,56 @@ Polymer({ ...@@ -250,42 +251,56 @@ Polymer({
assertNotReached(); assertNotReached();
}, },
/** @private */
registerSearchManagerObserver_: function() {
const observer = /** @type {!settings.SearchManagerObserver} */ ({
onSearchStart: () => {
// Trigger rendering of the basic and advanced pages and search once
// ready.
this.inSearchMode_ = true;
this.toolbarSpinnerActive = true;
},
onSearchComplete: searchResult => {
if (searchResult.canceled) {
// Nothing to do here. A previous search request was canceled
// because a new search request was issued with a different query
// before the previous completed.
return;
}
this.toolbarSpinnerActive = false;
this.inSearchMode_ = !searchResult.wasClearSearch;
this.showNoResultsFound_ =
this.inSearchMode_ && !searchResult.didFindMatches;
if (this.showNoResultsFound_ &&
settings.getCurrentRoute().isSubpage()) {
settings.navigateTo(settings.routes.BASIC);
this.searchContents(searchResult.rawQuery);
return;
}
if (this.inSearchMode_) {
Polymer.IronA11yAnnouncer.requestAvailability();
this.fire('iron-announce', {
text: this.showNoResultsFound_ ?
loadTimeData.getString('searchNoResults') :
loadTimeData.getStringF('searchResults', searchResult.rawQuery)
});
}
},
});
settings.getSearchManager().registerObserver(observer);
},
/** /**
* @param {string} query * @param {string} query
* @return {!Promise} A promise indicating that searching finished. * @return {!Promise<!settings.SearchResult>} A promise indicating that
* searching finished.
*/ */
searchContents: function(query) { searchContents: function(query) {
// Trigger rendering of the basic and advanced pages and search once ready.
this.inSearchMode_ = true;
this.toolbarSpinnerActive = true;
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
setTimeout(() => { setTimeout(() => {
const whenSearchDone = const basicPage = assert(this.getPage_(settings.routes.BASIC));
assert(this.getPage_(settings.routes.BASIC)).searchContents(query); basicPage.searchContents(query).then(resolve);
whenSearchDone.then(result => {
resolve();
if (result.canceled) {
// Nothing to do here. A previous search request was canceled
// because a new search request was issued with a different query
// before the previous completed.
return;
}
this.toolbarSpinnerActive = false;
this.inSearchMode_ = !result.wasClearSearch;
this.showNoResultsFound_ =
this.inSearchMode_ && !result.didFindMatches;
if (this.inSearchMode_) {
Polymer.IronA11yAnnouncer.requestAvailability();
this.fire('iron-announce', {
text: this.showNoResultsFound_ ?
loadTimeData.getString('searchNoResults') :
loadTimeData.getStringF('searchResults', query)
});
}
});
}, 0); }, 0);
}); });
}, },
......
...@@ -45,8 +45,7 @@ TEST_F('SettingsBasicPageBrowserTest', 'DISABLED_Load', function() { ...@@ -45,8 +45,7 @@ TEST_F('SettingsBasicPageBrowserTest', 'DISABLED_Load', function() {
/** @override */ /** @override */
search(text, page) { search(text, page) {
if (this.searchRequest_ == null || !this.searchRequest_.isSame(text)) { if (this.searchRequest_ == null || !this.searchRequest_.isSame(text)) {
this.searchRequest_ = new settings.SearchRequest( this.searchRequest_ = new settings.SearchRequest(text);
text, document.createElement('div'));
this.searchRequest_.finished = true; this.searchRequest_.finished = true;
this.searchRequest_.updateMatches(false); this.searchRequest_.updateMatches(false);
...@@ -66,6 +65,9 @@ TEST_F('SettingsBasicPageBrowserTest', 'DISABLED_Load', function() { ...@@ -66,6 +65,9 @@ TEST_F('SettingsBasicPageBrowserTest', 'DISABLED_Load', function() {
} }
return this.searchRequest_.resolver.promise; return this.searchRequest_.resolver.promise;
} }
/** @override */
registerObserver(observer) {}
} }
// Register mocha tests. // Register mocha tests.
......
...@@ -37,29 +37,32 @@ cr.define('settings_test', function() { ...@@ -37,29 +37,32 @@ cr.define('settings_test', function() {
const div = document.querySelector('#mydiv'); const div = document.querySelector('#mydiv');
assertTrue(section.hiddenBySearch); assertTrue(section.hiddenBySearch);
return searchManager.search('settings', section).then(function() { return searchManager.search('settings', [section])
assertFalse(section.hiddenBySearch); .then(function() {
assertFalse(section.hiddenBySearch);
const highlightWrapper = div.querySelector('.search-highlight-wrapper');
assertTrue(!!highlightWrapper); const highlightWrapper =
div.querySelector('.search-highlight-wrapper');
const originalContent = highlightWrapper.querySelector( assertTrue(!!highlightWrapper);
'.search-highlight-original-content');
assertTrue(!!originalContent); const originalContent = highlightWrapper.querySelector(
assertEquals(optionText, originalContent.textContent); '.search-highlight-original-content');
assertTrue(!!originalContent);
const searchHits = highlightWrapper.querySelectorAll( assertEquals(optionText, originalContent.textContent);
'.search-highlight-hit');
assertEquals(1, searchHits.length); const searchHits =
assertEquals('Settings', searchHits[0].textContent); highlightWrapper.querySelectorAll('.search-highlight-hit');
assertEquals(1, searchHits.length);
// Check that original DOM structure is restored when search assertEquals('Settings', searchHits[0].textContent);
// highlights are cleared.
return searchManager.search('', section); // Check that original DOM structure is restored when search
}).then(function() { // highlights are cleared.
assertEquals(0, div.children.length); return searchManager.search('', [section]);
assertEquals(optionText, div.textContent); })
}); .then(function() {
assertEquals(0, div.children.length);
assertEquals(optionText, div.textContent);
});
}); });
/** /**
...@@ -81,23 +84,25 @@ cr.define('settings_test', function() { ...@@ -81,23 +84,25 @@ cr.define('settings_test', function() {
const select = section.querySelector('select'); const select = section.querySelector('select');
assertTrue(section.hiddenBySearch); assertTrue(section.hiddenBySearch);
return searchManager.search('settings', section).then(function() { return searchManager.search('settings', [section])
assertFalse(section.hiddenBySearch); .then(function() {
assertFalse(section.hiddenBySearch);
const highlightWrapper = select.querySelector(
'.search-highlight-wrapper'); const highlightWrapper =
assertFalse(!!highlightWrapper); select.querySelector('.search-highlight-wrapper');
assertFalse(!!highlightWrapper);
// Check that original DOM structure is present even after search
// highlights are cleared. // Check that original DOM structure is present even after search
return searchManager.search('', section); // highlights are cleared.
}).then(function() { return searchManager.search('', [section]);
const options = select.querySelectorAll('option'); })
assertEquals(3, options.length); .then(function() {
assertEquals('Foo', options[0].textContent); const options = select.querySelectorAll('option');
assertEquals('Settings', options[1].textContent); assertEquals(3, options.length);
assertEquals('Baz', options[2].textContent); assertEquals('Foo', options[0].textContent);
}); assertEquals('Settings', options[1].textContent);
assertEquals('Baz', options[2].textContent);
});
}); });
test('ignored elements are ignored', function() { test('ignored elements are ignored', function() {
...@@ -119,7 +124,7 @@ cr.define('settings_test', function() { ...@@ -119,7 +124,7 @@ cr.define('settings_test', function() {
const section = document.querySelector('settings-section'); const section = document.querySelector('settings-section');
assertTrue(section.hiddenBySearch); assertTrue(section.hiddenBySearch);
return searchManager.search(text, section).then(function() { return searchManager.search(text, [section]).then(function() {
assertTrue(section.hiddenBySearch); assertTrue(section.hiddenBySearch);
}); });
}); });
...@@ -141,15 +146,95 @@ cr.define('settings_test', function() { ...@@ -141,15 +146,95 @@ cr.define('settings_test', function() {
const sections = Array.prototype.slice.call( const sections = Array.prototype.slice.call(
document.querySelectorAll('settings-section')); document.querySelectorAll('settings-section'));
return Promise.all(sections.map(s => searchManager.search('there', s))) return Promise.all(sections.map(s => searchManager.search('there', [s])))
.then(function(requests) { .then(function(results) {
assertTrue(requests[0].didFindMatches()); assertTrue(results[0].didFindMatches);
assertFalse(sections[0].hiddenBySearch); assertFalse(sections[0].hiddenBySearch);
assertTrue(requests[1].didFindMatches()); assertTrue(results[1].didFindMatches);
assertFalse(sections[1].hiddenBySearch); assertFalse(sections[1].hiddenBySearch);
assertFalse(requests[2].didFindMatches()); assertFalse(results[2].didFindMatches);
assertTrue(sections[2].hiddenBySearch); assertTrue(sections[2].hiddenBySearch);
}); });
}); });
test('search is redone when text is changed', function() {
const observer = /** @type {!settings.SearchManagerObserver} */ ((() => {
let resolver;
return {
onSearchStart() {},
onSearchComplete(searchResult) {
resolver.resolve(searchResult);
},
waitForSearchComplete(doSearch) {
resolver = new PromiseResolver();
doSearch();
return resolver.promise;
}
};
})());
searchManager.registerObserver(observer);
const originalText = 'FooSettingsFoo';
document.body.innerHTML = `<settings-section hidden-by-search>
<div id="mydiv">${originalText}</div>
</settings-section>`;
const section = document.querySelector('settings-section');
const div = document.querySelector('#mydiv');
assertTrue(section.hiddenBySearch);
return observer
.waitForSearchComplete(() => {
searchManager.search('settings', [document.body]);
})
.then(searchResult => {
assertFalse(section.hiddenBySearch);
const expected = {
canceled: false,
didFindMatches: true,
rawQuery: 'settings',
wasClearSearch: false,
};
assertDeepEquals(expected, searchResult);
const highlightWrapper =
div.querySelector('.search-highlight-wrapper');
assertTrue(!!highlightWrapper);
const originalContent = highlightWrapper.querySelector(
'.search-highlight-original-content');
assertTrue(!!originalContent);
return observer.waitForSearchComplete(() => {
originalContent.childNodes[0].nodeValue = 'Foo';
});
})
.then(searchResult => {
assertTrue(section.hiddenBySearch);
const expected = {
canceled: false,
didFindMatches: false,
rawQuery: 'settings',
wasClearSearch: false,
};
assertDeepEquals(expected, searchResult);
const highlightWrapper =
div.querySelector('.search-highlight-wrapper');
assertTrue(!highlightWrapper);
return observer.waitForSearchComplete(() => {
div.childNodes[0].nodeValue = originalText;
});
})
.then(searchResult => {
assertFalse(section.hiddenBySearch);
const expected = {
canceled: false,
didFindMatches: true,
rawQuery: 'settings',
wasClearSearch: false,
};
assertDeepEquals(expected, searchResult);
const highlightWrapper =
div.querySelector('.search-highlight-wrapper');
assertTrue(!!highlightWrapper);
});
});
}); });
}); });
...@@ -22,6 +22,9 @@ cr.define('settings_main_page', function() { ...@@ -22,6 +22,9 @@ cr.define('settings_main_page', function() {
/** @private {?settings.SearchRequest} */ /** @private {?settings.SearchRequest} */
this.searchRequest_ = null; this.searchRequest_ = null;
/** @private {?settings.SearchManagerObserver} */
this.observer_ = null;
} }
/** /**
...@@ -33,6 +36,7 @@ cr.define('settings_main_page', function() { ...@@ -33,6 +36,7 @@ cr.define('settings_main_page', function() {
/** @override */ /** @override */
search(text, page) { search(text, page) {
this.observer_.onSearchStart();
this.methodCalled('search', text); this.methodCalled('search', text);
if (this.searchRequest_ == null || !this.searchRequest_.isSame(text)) { if (this.searchRequest_ == null || !this.searchRequest_.isSame(text)) {
...@@ -40,9 +44,15 @@ cr.define('settings_main_page', function() { ...@@ -40,9 +44,15 @@ cr.define('settings_main_page', function() {
this.searchRequest_.finished = true; this.searchRequest_.finished = true;
this.searchRequest_.updateMatches(this.matchesFound_); this.searchRequest_.updateMatches(this.matchesFound_);
this.searchRequest_.resolver.resolve(this.searchRequest_); this.searchRequest_.resolver.resolve(this.searchRequest_);
this.observer_.onSearchComplete(this.searchRequest_.result());
} }
return this.searchRequest_.resolver.promise; return this.searchRequest_.resolver.promise;
} }
/** @override */
registerObserver(observer) {
this.observer_ = observer;
}
} }
let settingsPrefs = null; let settingsPrefs = null;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment