Add full-text search
Add a search box with a quick results popover, as well full results in the sidebar on pressing enter.
This commit is contained in:
128
tests/integration/components/search-box-test.gjs
Normal file
128
tests/integration/components/search-box-test.gjs
Normal file
@@ -0,0 +1,128 @@
|
||||
import { module, test } from 'qunit';
|
||||
import { setupRenderingTest } from 'marco/tests/helpers';
|
||||
import { render, fillIn, click, waitFor } from '@ember/test-helpers';
|
||||
import SearchBox from 'marco/components/search-box';
|
||||
import Service from '@ember/service';
|
||||
|
||||
module('Integration | Component | search-box', function (hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
|
||||
test('it renders and handles search input', async function (assert) {
|
||||
// Mock Photon Service
|
||||
class MockPhotonService extends Service {
|
||||
async search(query) {
|
||||
if (query === 'test') {
|
||||
return [
|
||||
{
|
||||
title: 'Test Place',
|
||||
description: 'A test description',
|
||||
lat: 10,
|
||||
lon: 20,
|
||||
osmId: '123',
|
||||
osmType: 'node',
|
||||
},
|
||||
];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
}
|
||||
this.owner.register('service:photon', MockPhotonService);
|
||||
|
||||
// Mock Router Service
|
||||
class MockRouterService extends Service {
|
||||
transitionTo(routeName, ...args) {
|
||||
assert.step(`transitionTo: ${routeName} ${JSON.stringify(args)}`);
|
||||
}
|
||||
}
|
||||
this.owner.register('service:router', MockRouterService);
|
||||
|
||||
await render(<template><SearchBox /></template>);
|
||||
|
||||
assert.dom('.search-input').exists();
|
||||
assert.dom('.search-results-popover').doesNotExist();
|
||||
|
||||
// Type 'test'
|
||||
await fillIn('.search-input', 'test');
|
||||
|
||||
// Wait for debounce and async search
|
||||
await waitFor('.search-results-popover', { timeout: 2000 });
|
||||
|
||||
assert.dom('.search-result-item').exists({ count: 1 });
|
||||
assert.dom('.result-title').hasText('Test Place');
|
||||
assert.dom('.result-desc').hasText('A test description');
|
||||
|
||||
// Click result
|
||||
await click('.search-result-item');
|
||||
|
||||
assert.verifySteps(['transitionTo: place ["osm:node:123"]']);
|
||||
assert
|
||||
.dom('.search-results-popover')
|
||||
.doesNotExist('Popover closes after selection');
|
||||
});
|
||||
|
||||
test('it handles submit for full search', async function (assert) {
|
||||
// Mock Photon Service
|
||||
class MockPhotonService extends Service {
|
||||
async search() {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
this.owner.register('service:photon', MockPhotonService);
|
||||
|
||||
// Mock MapUi Service
|
||||
class MockMapUiService extends Service {
|
||||
currentCenter = { lat: 52.52, lon: 13.405 };
|
||||
}
|
||||
this.owner.register('service:map-ui', MockMapUiService);
|
||||
|
||||
// Mock Router Service
|
||||
class MockRouterService extends Service {
|
||||
transitionTo(routeName, options) {
|
||||
assert.step(
|
||||
`transitionTo: ${routeName} ${JSON.stringify(options)}`
|
||||
);
|
||||
}
|
||||
}
|
||||
this.owner.register('service:router', MockRouterService);
|
||||
|
||||
await render(<template><SearchBox /></template>);
|
||||
|
||||
await fillIn('.search-input', 'berlin');
|
||||
await click('.search-input'); // Focus
|
||||
// Trigger submit event on the form
|
||||
await this.element
|
||||
.querySelector('form')
|
||||
.dispatchEvent(new Event('submit', { bubbles: true, cancelable: true }));
|
||||
|
||||
assert.verifySteps([
|
||||
'transitionTo: search {"queryParams":{"q":"berlin","selected":null,"lat":"52.5200","lon":"13.4050"}}',
|
||||
]);
|
||||
});
|
||||
|
||||
test('it uses map center for biased search', async function (assert) {
|
||||
// Mock MapUi Service
|
||||
class MockMapUiService extends Service {
|
||||
currentCenter = { lat: 52.52, lon: 13.405 };
|
||||
}
|
||||
this.owner.register('service:map-ui', MockMapUiService);
|
||||
|
||||
// Mock Photon Service
|
||||
class MockPhotonService extends Service {
|
||||
async search(query, lat, lon) {
|
||||
assert.step(`search: ${query}, ${lat}, ${lon}`);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
this.owner.register('service:photon', MockPhotonService);
|
||||
|
||||
await render(<template><SearchBox /></template>);
|
||||
|
||||
await fillIn('.search-input', 'cafe');
|
||||
|
||||
// Wait for debounce (300ms) + execution
|
||||
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
||||
await delay(400);
|
||||
|
||||
assert.verifySteps(['search: cafe, 52.52, 13.405']);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user