diff --git a/app/components/search-box.gjs b/app/components/search-box.gjs index 515ecbc..8b822cb 100644 --- a/app/components/search-box.gjs +++ b/app/components/search-box.gjs @@ -35,23 +35,26 @@ export default class SearchBoxComponent extends Component { @action handleInput(event) { - this.query = event.target.value; + const value = event.target.value; + this.query = value; if (this.args.onQueryChange) { - this.args.onQueryChange(this.query); + this.args.onQueryChange(value); } - if (this.query.length < 2) { + if (value.length < 2) { this.results = []; return; } - this.searchTask.perform(); + this.searchTask.perform(value); } - searchTask = task({ restartable: true }, async () => { + searchTask = task({ restartable: true }, async (term) => { await timeout(300); - if (this.query.length < 2) return; + const query = typeof term === 'string' ? term : this.query; + + if (query.length < 2) return; this.isLoading = true; try { @@ -62,7 +65,7 @@ export default class SearchBoxComponent extends Component { } // Filter categories - const q = this.query.toLowerCase(); + const q = query.toLowerCase(); const categoryMatches = POI_CATEGORIES.filter((c) => c.label.toLowerCase().includes(q) ).map((c) => ({ @@ -72,7 +75,7 @@ export default class SearchBoxComponent extends Component { icon: 'search', })); - const results = await this.photon.search(this.query, lat, lon); + const results = await this.photon.search(query, lat, lon); this.results = [...categoryMatches, ...results]; } catch (e) { console.error('Search failed', e); diff --git a/tests/integration/components/search-box-test.gjs b/tests/integration/components/search-box-test.gjs index 2f53aa1..a67705a 100644 --- a/tests/integration/components/search-box-test.gjs +++ b/tests/integration/components/search-box-test.gjs @@ -134,4 +134,45 @@ module('Integration | Component | search-box', function (hooks) { assert.verifySteps(['search: cafe, 52.52, 13.405']); }); + + test('it allows typing even when controlled by parent with a query argument', async function (assert) { + class MockPhotonService extends Service { + async search() { + return []; + } + } + this.owner.register('service:photon', MockPhotonService); + + this.query = ''; + this.updateQuery = (val) => { + this.set('query', val); + }; + this.noop = () => {}; + + await render( + + ); + + // Initial state + assert.dom('.search-input').hasValue(''); + + // Simulate typing + await fillIn('.search-input', 't'); + assert.dom('.search-input').hasValue('t', 'Input should show "t"'); + + await fillIn('.search-input', 'te'); + assert.dom('.search-input').hasValue('te', 'Input should show "te"'); + + // Simulate external update (e.g. chip click) + this.set('query', 'restaurant'); + // wait for re-render + await click('.search-input'); // just to trigger a change cycle or ensure stability + assert.dom('.search-input').hasValue('restaurant', 'Input should update from external change'); + }); });