mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-06 11:24:00 +00:00
fix(search): keep a missed location query in the field so it can be corrected (#1420)
A location search that found nothing or failed now keeps its query, the open field and focus (text selected), and shows a persistent role=alert message under the search row instead of a toast. Typing, a new search or closing the emptied field clears it. HAL-727.
This commit is contained in:
1 parent
3d9f153bc0
commit
6152f9f311
17 files changed
+207
-10
No files matched your search
@@ -0,0 +1,110 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
import { NavigationController } from './navigationController.js';
|
||||
import { LocationNavigation } from './locationNavigation.js';
|
||||
|
||||
function input() {
|
||||
const classes = new Set(['expanded', 'searching']);
|
||||
const attributes = new Map();
|
||||
return {
|
||||
id: 'location-search',
|
||||
value: 'Pariss',
|
||||
focused: false,
|
||||
selected: false,
|
||||
classList: {
|
||||
remove: (...names) => names.forEach((name) => classes.delete(name)),
|
||||
contains: (name) => classes.has(name),
|
||||
},
|
||||
focus() {
|
||||
this.focused = true;
|
||||
},
|
||||
blur() {
|
||||
this.focused = false;
|
||||
},
|
||||
select() {
|
||||
this.selected = true;
|
||||
},
|
||||
setAttribute: (name, value) => attributes.set(name, value),
|
||||
removeAttribute: (name) => attributes.delete(name),
|
||||
getAttribute: (name) => attributes.get(name) ?? null,
|
||||
};
|
||||
}
|
||||
|
||||
function settle(searchInput, options) {
|
||||
const owner = { _activeLocationSearchGeneration: 4, searchInput };
|
||||
NavigationController.prototype._settleLocationSearchUi.call(
|
||||
owner,
|
||||
4,
|
||||
options,
|
||||
);
|
||||
return owner;
|
||||
}
|
||||
|
||||
test('a search that found nothing keeps its query, the open field and focus', () => {
|
||||
const field = input();
|
||||
const owner = settle(field, { keepQuery: true });
|
||||
assert.equal(owner._activeLocationSearchGeneration, null);
|
||||
assert.equal(field.value, 'Pariss');
|
||||
assert.equal(field.classList.contains('expanded'), true);
|
||||
assert.equal(field.classList.contains('searching'), false);
|
||||
assert.equal(field.focused, true);
|
||||
assert.equal(field.selected, true);
|
||||
});
|
||||
|
||||
test('a search that arrived still clears and closes the field', () => {
|
||||
const field = input();
|
||||
field.focused = true;
|
||||
settle(field);
|
||||
assert.equal(field.value, '');
|
||||
assert.equal(field.classList.contains('expanded'), false);
|
||||
assert.equal(field.focused, false);
|
||||
});
|
||||
|
||||
function navigation() {
|
||||
const field = input();
|
||||
const error = { id: 'location-search-error', textContent: '' };
|
||||
const settled = [];
|
||||
const toasts = [];
|
||||
const owner = {
|
||||
_disposed: false,
|
||||
_locationSearch: field,
|
||||
_locationSearchError: error,
|
||||
_activeLocationSearchGeneration: null,
|
||||
_settleLocationSearchUi: (generation, options) =>
|
||||
settled.push([generation, options]),
|
||||
_showToast: (message) => toasts.push(message),
|
||||
_setLocationSearchError:
|
||||
LocationNavigation.prototype._setLocationSearchError,
|
||||
};
|
||||
const handle = (status, type) =>
|
||||
LocationNavigation.prototype._handleLocationSearchState.call(
|
||||
owner,
|
||||
{ status, query: field.value },
|
||||
{ type, generation: 7 },
|
||||
);
|
||||
return { owner, field, error, settled, toasts, handle };
|
||||
}
|
||||
|
||||
for (const [status, text] of [
|
||||
['missing', 'Location not found'],
|
||||
['failed', 'Search failed'],
|
||||
]) {
|
||||
test(`a ${status} search announces a lasting error on the field instead of a toast`, () => {
|
||||
const n = navigation();
|
||||
n.handle('searching', 'started');
|
||||
n.handle(status, status);
|
||||
n.handle(status, 'settled');
|
||||
assert.match(n.error.textContent, new RegExp(`^${text}\\. `));
|
||||
assert.equal(n.field.getAttribute('aria-invalid'), 'true');
|
||||
assert.equal(
|
||||
n.field.getAttribute('aria-describedby'),
|
||||
'location-search-error',
|
||||
);
|
||||
assert.deepEqual(n.settled, [[7, { keepQuery: true }]]);
|
||||
assert.deepEqual(n.toasts, []);
|
||||
n.handle('searching', 'started');
|
||||
assert.equal(n.error.textContent, '');
|
||||
assert.equal(n.field.getAttribute('aria-invalid'), null);
|
||||
assert.equal(n.field.getAttribute('aria-describedby'), null);
|
||||
});
|
||||
}
|
||||
Reference in new issue
Block a user