Skip to content

Commit 65735b1

Browse files
authored
Merge pull request #873 from a13o/clear-stale-search-results
Clear stale search results when version is changed
2 parents e9683b3 + ac3f44d commit 65735b1

File tree

5 files changed

+210
-3
lines changed

5 files changed

+210
-3
lines changed

app/components/search-input.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,13 @@ export default class SearchInput extends Component {
5656
}
5757

5858
@action onfocus() {
59+
if (this.query.length > 0 && this.searchService.hasStaleResults()) {
60+
// clearing the results avoids a flash of stale content while the search
61+
// is performed
62+
this.searchService.clearResults();
63+
this.searchService.search.perform(this.query);
64+
}
65+
5966
this._focused = true;
6067
}
6168

app/services/search.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ export default Service.extend({
99
_projectService: service('project'),
1010
_projectVersion: alias('_projectService.version'),
1111

12+
/** @type {?string} */
13+
_lastQueriedProjectVersion: null,
14+
1215
results: emberArray(),
1316

1417
search: task(function* (query) {
@@ -30,6 +33,8 @@ export default Service.extend({
3033
query,
3134
};
3235

36+
this._lastQueriedProjectVersion = projectVersion;
37+
3338
return set(this, 'results', yield this.doSearch(searchObj, params));
3439
}).restartable(),
3540

@@ -38,4 +43,21 @@ export default Service.extend({
3843
.search(searchObj, params)
3944
.then((results) => results.hits);
4045
},
46+
47+
/**
48+
* Whenever the version changes in service:project, the results in this
49+
* service become stale. Presenting them any further could allow the user to
50+
* undo their version change by clicking a stale link.
51+
* @returns {boolean}
52+
*/
53+
hasStaleResults() {
54+
return (
55+
this._lastQueriedProjectVersion !== null &&
56+
this._projectVersion !== this._lastQueriedProjectVersion
57+
);
58+
},
59+
60+
clearResults() {
61+
set(this, 'results', emberArray());
62+
},
4163
});

tests/acceptance/search-test.js

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import { module, test } from 'qunit';
2-
import { visit, currentURL, fillIn, click } from '@ember/test-helpers';
2+
import { visit, currentURL, fillIn, click, focus } from '@ember/test-helpers';
3+
import { selectChoose } from 'ember-power-select/test-support';
34
import { setupApplicationTest } from 'ember-qunit';
45

5-
import searchResults from 'ember-api-docs/tests/fixtures/searchresult';
6+
import searchResultsV4_1 from 'ember-api-docs/tests/fixtures/searchresult-v-4-1';
7+
import searchResultsV5_1 from 'ember-api-docs/tests/fixtures/searchresult-v-5-1';
68

79
module('Acceptance | search', function (hooks) {
810
setupApplicationTest(hooks);
@@ -13,7 +15,7 @@ module('Acceptance | search', function (hooks) {
1315
const algoliaService = this.owner.lookup('service:algolia');
1416

1517
algoliaService.search = async () => {
16-
return searchResults;
18+
return searchResultsV4_1;
1719
};
1820

1921
await fillIn('[data-test-search-input]', 'forEach');
@@ -25,4 +27,36 @@ module('Acceptance | search', function (hooks) {
2527
'/ember/4.1/classes/EmberArray/methods/forEach?anchor=forEach'
2628
);
2729
});
30+
31+
test('discard stale search results when version changes', async function (assert) {
32+
await visit('/');
33+
34+
const algoliaService = this.owner.lookup('service:algolia');
35+
36+
algoliaService.search = async () => {
37+
return searchResultsV4_1;
38+
};
39+
40+
await selectChoose('.ember-power-select-trigger', '4.1');
41+
42+
await fillIn('[data-test-search-input]', 'forEach');
43+
44+
// the url contains /ember/4.1/
45+
assert
46+
.dom('[data-test-search-result]')
47+
.hasAttribute('href', /\/ember\/4\.1\//);
48+
49+
algoliaService.search = async () => {
50+
return searchResultsV5_1;
51+
};
52+
53+
await selectChoose('.ember-power-select-trigger', '5.1');
54+
55+
await focus('[data-test-search-input]');
56+
57+
// the url contains /ember/5.1/
58+
assert
59+
.dom('[data-test-search-result]')
60+
.hasAttribute('href', /\/ember\/5\.1\//);
61+
});
2862
});
File renamed without changes.

tests/fixtures/searchresult-v-5-1.js

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
export default {
2+
hits: [
3+
{
4+
file: 'packages/@ember/array/index.ts',
5+
line: 447,
6+
module: '@ember/array',
7+
class: 'EmberArray',
8+
name: 'forEach',
9+
access: 'public',
10+
_tags: ['module:@ember/array', 'version:5.1.2'],
11+
hierarchy: { lvl0: '@ember/array', lvl1: 'EmberArray', lvl2: 'forEach' },
12+
objectID: '5215324000',
13+
_highlightResult: {
14+
name: {
15+
value: '<em>forEach</em>',
16+
matchLevel: 'full',
17+
fullyHighlighted: true,
18+
matchedWords: ['foreach'],
19+
},
20+
hierarchy: {
21+
lvl0: { value: '@ember/array', matchLevel: 'none', matchedWords: [] },
22+
lvl1: { value: 'EmberArray', matchLevel: 'none', matchedWords: [] },
23+
lvl2: {
24+
value: '<em>forEach</em>',
25+
matchLevel: 'full',
26+
fullyHighlighted: true,
27+
matchedWords: ['foreach'],
28+
},
29+
},
30+
},
31+
},
32+
{
33+
file: 'packages/@ember/array/index.ts',
34+
line: 447,
35+
module: '@ember/array',
36+
class: 'MutableArray',
37+
name: 'forEach',
38+
access: 'public',
39+
_tags: ['module:@ember/array', 'version:5.1.2'],
40+
hierarchy: {
41+
lvl0: '@ember/array',
42+
lvl1: 'MutableArray',
43+
lvl2: 'forEach',
44+
},
45+
objectID: '5215295000',
46+
_highlightResult: {
47+
name: {
48+
value: '<em>forEach</em>',
49+
matchLevel: 'full',
50+
fullyHighlighted: true,
51+
matchedWords: ['foreach'],
52+
},
53+
hierarchy: {
54+
lvl0: { value: '@ember/array', matchLevel: 'none', matchedWords: [] },
55+
lvl1: { value: 'MutableArray', matchLevel: 'none', matchedWords: [] },
56+
lvl2: {
57+
value: '<em>forEach</em>',
58+
matchLevel: 'full',
59+
fullyHighlighted: true,
60+
matchedWords: ['foreach'],
61+
},
62+
},
63+
},
64+
},
65+
{
66+
file: 'packages/@ember/array/index.ts',
67+
line: 447,
68+
module: '@ember/array',
69+
class: 'Ember.NativeArray',
70+
name: 'forEach',
71+
access: 'public',
72+
_tags: ['module:@ember/array', 'version:5.1.2'],
73+
hierarchy: {
74+
lvl0: '@ember/array',
75+
lvl1: 'Ember.NativeArray',
76+
lvl2: 'forEach',
77+
},
78+
objectID: '5215250000',
79+
_highlightResult: {
80+
name: {
81+
value: '<em>forEach</em>',
82+
matchLevel: 'full',
83+
fullyHighlighted: true,
84+
matchedWords: ['foreach'],
85+
},
86+
hierarchy: {
87+
lvl0: { value: '@ember/array', matchLevel: 'none', matchedWords: [] },
88+
lvl1: {
89+
value: 'Ember.NativeArray',
90+
matchLevel: 'none',
91+
matchedWords: [],
92+
},
93+
lvl2: {
94+
value: '<em>forEach</em>',
95+
matchLevel: 'full',
96+
fullyHighlighted: true,
97+
matchedWords: ['foreach'],
98+
},
99+
},
100+
},
101+
},
102+
{
103+
file: 'packages/@ember/array/index.ts',
104+
line: 447,
105+
module: '@ember/array',
106+
class: 'ArrayProxy',
107+
name: 'forEach',
108+
access: 'public',
109+
_tags: ['module:@ember/array', 'version:5.1.2'],
110+
hierarchy: { lvl0: '@ember/array', lvl1: 'ArrayProxy', lvl2: 'forEach' },
111+
objectID: '5215191000',
112+
_highlightResult: {
113+
name: {
114+
value: '<em>forEach</em>',
115+
matchLevel: 'full',
116+
fullyHighlighted: true,
117+
matchedWords: ['foreach'],
118+
},
119+
hierarchy: {
120+
lvl0: { value: '@ember/array', matchLevel: 'none', matchedWords: [] },
121+
lvl1: { value: 'ArrayProxy', matchLevel: 'none', matchedWords: [] },
122+
lvl2: {
123+
value: '<em>forEach</em>',
124+
matchLevel: 'full',
125+
fullyHighlighted: true,
126+
matchedWords: ['foreach'],
127+
},
128+
},
129+
},
130+
},
131+
],
132+
nbHits: 4,
133+
page: 0,
134+
nbPages: 1,
135+
hitsPerPage: 15,
136+
exhaustiveNbHits: true,
137+
exhaustiveTypo: true,
138+
exhaustive: { nbHits: true, typo: true },
139+
query: 'forEach',
140+
params:
141+
'query=forEach&hitsPerPage=15&restrictSearchableAttributes=%5B%22hierarchy.lvl0%22%2C%22hierarchy.lvl1%22%2C%22hierarchy.lvl2%22%5D&tagFilters=%5B%22version%3A5.1.2%22%5D&facetFilters=%5B%22access%3A-private%22%5D',
142+
processingTimeMS: 1,
143+
processingTimingsMS: { request: { roundTrip: 22 } },
144+
};

0 commit comments

Comments
 (0)