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'); + }); +});