diff --git a/tests/acceptance/search-test.js b/tests/acceptance/search-test.js
index fd642b5..acaa648 100644
--- a/tests/acceptance/search-test.js
+++ b/tests/acceptance/search-test.js
@@ -155,4 +155,65 @@ module('Acceptance | search', function (hooks) {
assert.dom('.places-list li').exists({ count: 1 });
assert.dom('.places-list li .place-name').hasText('My Secret Base');
});
+
+ test('visiting /search with category parameter performs category search', async function (assert) {
+ // Mock Osm Service
+ class MockOsmService extends Service {
+ async getCategoryPois(bounds, categoryId) {
+ if (categoryId === 'coffee') {
+ return [
+ {
+ title: 'Latte Art Cafe',
+ lat: 52.52,
+ lon: 13.405,
+ osmId: '101',
+ osmType: 'N',
+ description: 'Best Coffee',
+ },
+ ];
+ }
+ return [];
+ }
+ }
+ this.owner.register('service:osm', MockOsmService);
+
+ // Mock Storage Service (empty)
+ class MockStorageService extends Service {
+ savedPlaces = [];
+ findPlaceById() {
+ return null;
+ }
+ isPlaceSaved() {
+ return false;
+ }
+ rs = { on: () => {} };
+ placesInView = [];
+ loadPlacesInBounds() {
+ return Promise.resolve();
+ }
+ }
+ this.owner.register('service:storage', MockStorageService);
+
+ // Mock Map Service (needed for bounds)
+ class MockMapService extends Service {
+ getBounds() {
+ return {
+ minLat: 52.5,
+ minLon: 13.4,
+ maxLat: 52.6,
+ maxLon: 13.5,
+ };
+ }
+ }
+ this.owner.register('service:map', MockMapService);
+
+ await visit('/search?category=coffee&lat=52.52&lon=13.405');
+
+ assert.strictEqual(
+ currentURL(),
+ '/search?category=coffee&lat=52.52&lon=13.405'
+ );
+ assert.dom('.places-list li').exists({ count: 1 });
+ assert.dom('.places-list li .place-name').hasText('Latte Art Cafe');
+ });
});
diff --git a/tests/integration/components/app-header-test.gjs b/tests/integration/components/app-header-test.gjs
index ffb822e..a994d85 100644
--- a/tests/integration/components/app-header-test.gjs
+++ b/tests/integration/components/app-header-test.gjs
@@ -1,13 +1,25 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'marco/tests/helpers';
-import { render } from '@ember/test-helpers';
+import { render, fillIn } from '@ember/test-helpers';
import AppHeader from 'marco/components/app-header';
+import Service from '@ember/service';
module('Integration | Component | app-header', function (hooks) {
setupRenderingTest(hooks);
test('it renders the search box', async function (assert) {
this.noop = () => {};
+
+ class MockPhotonService extends Service {}
+ class MockRouterService extends Service {}
+ class MockMapUiService extends Service {}
+ class MockMapService extends Service {}
+
+ this.owner.register('service:photon', MockPhotonService);
+ this.owner.register('service:router', MockRouterService);
+ this.owner.register('service:map-ui', MockMapUiService);
+ this.owner.register('service:map', MockMapService);
+
await render(
);
@@ -16,4 +28,39 @@ module('Integration | Component | app-header', function (hooks) {
assert.dom('.search-box').exists('Search box is present in the header');
assert.dom('.menu-btn-integrated').exists('Menu button is integrated');
});
+
+ test('typing in search box toggles .searching class on header-center', async function (assert) {
+ this.noop = () => {};
+
+ class MockPhotonService extends Service {
+ search() {
+ return [];
+ }
+ }
+ class MockRouterService extends Service {}
+ class MockMapUiService extends Service {
+ setSearchBoxFocus() {}
+ currentCenter = null;
+ }
+ class MockMapService extends Service {}
+
+ this.owner.register('service:photon', MockPhotonService);
+ this.owner.register('service:router', MockRouterService);
+ this.owner.register('service:map-ui', MockMapUiService);
+ this.owner.register('service:map', MockMapService);
+
+ await render(
+
+ );
+
+ assert.dom('.header-center').doesNotHaveClass('searching');
+
+ await fillIn('.search-input', 'test');
+
+ assert.dom('.header-center').hasClass('searching');
+
+ await fillIn('.search-input', '');
+
+ assert.dom('.header-center').doesNotHaveClass('searching');
+ });
});
diff --git a/tests/integration/components/category-chips-test.gjs b/tests/integration/components/category-chips-test.gjs
new file mode 100644
index 0000000..100a664
--- /dev/null
+++ b/tests/integration/components/category-chips-test.gjs
@@ -0,0 +1,56 @@
+import { module, test } from 'qunit';
+import { setupRenderingTest } from 'marco/tests/helpers';
+import { render, click } from '@ember/test-helpers';
+import CategoryChips from 'marco/components/category-chips';
+import Service from '@ember/service';
+import { POI_CATEGORIES } from 'marco/utils/poi-categories';
+
+module('Integration | Component | category-chips', function (hooks) {
+ setupRenderingTest(hooks);
+
+ test('it renders the correct number of chips', async function (assert) {
+ class MockRouterService extends Service {}
+ class MockMapUiService extends Service {}
+
+ this.owner.register('service:router', MockRouterService);
+ this.owner.register('service:map-ui', MockMapUiService);
+
+ await render();
+
+ assert.dom('.category-chip').exists({ count: 5 });
+
+ // Check for some expected labels
+ assert.dom(this.element).includesText('Restaurants');
+ assert.dom(this.element).includesText('Coffee');
+ });
+
+ test('clicking a chip triggers the @onSelect action', async function (assert) {
+ let selectedCategory;
+ this.handleSelect = (category) => {
+ selectedCategory = category;
+ };
+
+ class MockRouterService extends Service {
+ transitionTo() {}
+ }
+ class MockMapUiService extends Service {}
+
+ this.owner.register('service:router', MockRouterService);
+ this.owner.register('service:map-ui', MockMapUiService);
+
+ await render(
+
+ );
+
+ // Find the chip for "Coffee"
+ const coffeeCategory = POI_CATEGORIES.find((c) => c.id === 'coffee');
+ const chip = Array.from(
+ this.element.querySelectorAll('.category-chip')
+ ).find((el) => el.textContent.includes(coffeeCategory.label));
+
+ await click(chip);
+
+ assert.strictEqual(selectedCategory.id, 'coffee');
+ assert.strictEqual(selectedCategory.label, 'Coffee');
+ });
+});