1 import { test, expect } from './shared.js';
3 test.describe('Search Page', () => {
4 test.skip(() => !!process.env.REVERSE_ONLY, 'Skipped in reverse-only mode');
6 test.describe('No search', () => {
9 test.beforeAll(async ({ browser }) => {
10 page = await browser.newPage();
11 await page.goto('/search.html');
14 test.afterAll(async () => {
18 test('should have a HTML page title', async () => {
19 expect(await page.title()).toBe('Nominatim Demo');
22 test('should have a welcome message', async () => {
23 await expect(page.locator('#welcome h2')).toHaveText(
24 'Welcome to Nominatim'
28 test('should have a last_updated_: ... ago data', async () => {
29 await page.waitForFunction(
31 const el = document.querySelector('abbr[id="data-date"]');
32 return el && el.textContent.includes('ago');
38 test('should show map bounds buttons', async () => {
39 await page.locator('#map').waitFor();
40 await expect(page.locator('#map-position-inner')).toHaveCount(0);
42 await page.locator('#show-map-position').click();
44 let map_pos_details = await page.locator(
47 map_pos_details = map_pos_details.split(' ');
49 const map_center_coords = map_pos_details[0]
50 .split('map center: ')[1].split(' view')[0].split(',');
51 const map_zoom = map_pos_details[1].split('map zoom: ')[1];
52 const map_viewbox = map_pos_details[2]
53 .split('viewbox: ')[1].split(',');
54 const last_click = map_pos_details[3].split('last click: ')[1];
56 expect(map_center_coords.length).toBe(2);
57 expect(map_zoom).toBeTruthy();
58 expect(map_viewbox.length).toBe(4);
59 expect(last_click).toBe('-');
61 await page.locator('#map-position-close a').click();
62 await expect(page.locator('#map-position-inner')).toHaveCount(0);
63 await expect(page.locator('#show-map-position')).toBeVisible();
67 test.describe('Search for Paris', () => {
70 test.beforeAll(async ({ browser }) => {
71 page = await browser.newPage();
72 await page.goto('/search.html');
73 await page.locator('input[name=q]').fill('Paris');
74 await page.locator('button[type=submit]').first().click();
75 await page.locator('#searchresults').waitFor();
78 test.afterAll(async () => {
82 test('should have a HTML page title', async () => {
83 expect(await page.title()).toBe('Result for Paris | Nominatim Demo');
86 test('should have added search params', async () => {
87 const current_url = new URL(page.url());
88 expect(current_url.searchParams.get('q')).toBe('Paris');
91 test('should have at least one result', async () => {
92 const results_count = await page.locator(
93 '#searchresults .result'
95 expect(results_count).toBeGreaterThan(1);
98 test('should display the API request and debug URL', async () => {
99 const link_titles = await page.locator(
101 ).evaluateAll(links => links.map(l => l.innerHTML));
102 expect(link_titles).toEqual(['API request', 'debug output']);
105 test('should not have polygon params in API request and debug URL',
107 const links_href = await page.locator(
109 ).evaluateAll(links => links.map(l => l.href));
110 const api_request_url = new URL(links_href[0]);
111 const debug_url = new URL(links_href[1]);
113 expect(api_request_url.searchParams.has('polygon_geojson')).toBe(
116 expect(debug_url.searchParams.has('polygon_geojson')).toBe(false);
120 test('should display a map', async () => {
121 await expect(page.locator('#map')).toHaveCount(1);
124 test('should default to dedupe=1', async () => {
126 await page.locator('#option_dedupe').isChecked()
129 const links_href = await page.locator(
131 ).evaluateAll(links => links.map(l => l.href));
132 const api_request_url = new URL(links_href[0]);
133 const debug_url = new URL(links_href[1]);
135 expect(api_request_url.searchParams.has('dedupe')).toBe(false);
136 expect(debug_url.searchParams.has('dedupe')).toBe(false);
139 test('should have polygon and marker in map and minimap', async () => {
141 page.locator('#map .leaflet-overlay-pane path')
145 test('should redirect to details page on clicking details button',
147 await page.locator('#searchresults .result a').first().click();
148 await page.locator('table#address').waitFor();
150 const current_url = new URL(page.url());
151 expect(current_url.pathname).toBe('/details.html');
153 await expect(page.locator('.container h1')).toContainText('Paris');
158 test.describe('Structured search for Paris', () => {
161 test.beforeAll(async ({ browser }) => {
162 page = await browser.newPage();
163 await page.goto('/search.html');
164 await page.locator(".nav-link[href='#structured']").click();
165 await page.locator('input[name=city]').fill('Paris');
166 await page.locator('input[name=country]').fill('USA');
167 await page.locator('#structured button[type=submit]').click();
168 await page.locator('#searchresults').waitFor();
171 test.afterAll(async () => {
175 test('should have a HTML page title', async () => {
176 expect(await page.title()).toBe(
177 'Result for Paris, USA | Nominatim Demo'
181 test('should have added search params', async () => {
182 const current_url = new URL(page.url());
183 expect(current_url.searchParams.get('q')).toBeNull();
184 expect(current_url.searchParams.get('city')).toBe('Paris');
185 expect(current_url.searchParams.get('country')).toBe('USA');
188 test('should have at least one result', async () => {
189 const results_count = await page.locator(
190 '#searchresults .result'
192 expect(results_count).toBeGreaterThan(1);
196 test.describe('Search for more results', () => {
200 test.beforeAll(async ({ browser }) => {
201 page = await browser.newPage();
202 await page.goto('/search.html');
203 await page.locator('input[name=q]').fill('Paris');
204 await page.locator('button[type=submit]').first().click();
205 await page.locator('#searchresults').waitFor();
208 test.afterAll(async () => {
212 test('should have show more results button', async () => {
214 page.locator('button', { hasText: 'Search for more results' })
218 test('should append results when clicking more results', async () => {
219 initial_count = await page.locator(
220 '#searchresults .result'
222 expect(initial_count).toBeGreaterThan(0);
225 'button', { hasText: 'Search for more results' }
228 await page.waitForFunction(
229 (prev) => document.querySelectorAll('#searchresults .result').length > prev,
234 const new_count = await page.locator(
235 '#searchresults .result'
237 expect(new_count).toBeGreaterThan(initial_count);
240 test('should add result-previous class to older results', async () => {
241 expect(initial_count).toBeGreaterThan(0);
242 await expect(page.locator('#searchresults .result-previous')).toHaveCount(initial_count);
245 test('should highlight first new result', async () => {
246 const highlighted = page.locator('#searchresults .result.highlight');
247 await expect(highlighted).toHaveCount(1);
248 const position = await highlighted.getAttribute('data-position');
249 expect(Number(position)).toBe(initial_count);
252 test('should display API URL for more results', async () => {
253 const api_div = page.locator('.more-api-request[data-request-num="2"]');
254 await expect(api_div).toBeVisible();
255 const api_link = api_div.locator('a').first();
256 await expect(api_link).toHaveText('API request #2');
257 const href = await api_link.getAttribute('href');
258 expect(href).toContain('exclude_place_ids');
261 test('should update browser URL with exclude_place_ids', async () => {
262 const current_url = new URL(page.url());
263 expect(current_url.searchParams.has('exclude_place_ids')).toBe(true);
266 test('should go back to original search URL on browser back', async () => {
268 const url = new URL(page.url());
269 expect(url.searchParams.has('q')).toBe(true);
270 expect(url.searchParams.has('exclude_place_ids')).toBe(false);
274 test.describe('Search for OSM URL', () => {
277 test.beforeAll(async ({ browser }) => {
278 page = await browser.newPage();
279 await page.goto('/search.html');
280 await page.locator('input[name=q]').fill(
281 'https://www.openstreetmap.org/relation/3459013#map=11/41.2388/-8.3867'
283 await page.locator('button[type=submit]').first().click();
284 await page.locator('table#address').waitFor();
287 test.afterAll(async () => {
291 test('should redirect to detail page search', async () => {
292 expect(await page.title()).toBe(
293 'Details for R3459013 | Nominatim Demo'
295 await expect(page.locator('.container h1')).toContainText('Porto');