Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 4 additions & 8 deletions .env
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
SKIP_PREFLIGHT_CHECK=true
REACT_APP_VALHALLA_URL=https://valhalla1.openstreetmap.de
REACT_APP_NOMINATIM_URL=https://nominatim.openstreetmap.org
REACT_APP_TILE_SERVER_URL="https://tile.openstreetmap.org/{z}/{x}/{y}.png"
REACT_APP_CENTER_COORDS="52.51831,13.393707"

# uncomment this variable to set boundaries on the leaflet map
# southwest corner, northeast corner
REACT_APP_MAX_BOUNDS="-180,-90,180,90"
VITE_VALHALLA_URL=https://valhalla1.openstreetmap.de
VITE_NOMINATIM_URL=https://nominatim.openstreetmap.org
VITE_TILE_SERVER_URL="https://tile.openstreetmap.org/{z}/{x}/{y}.png"
VITE_CENTER_COORDS="52.51831,13.393707"
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,12 @@ node_modules/
/blob-report/
/playwright/.cache/
tsconfig.tsbuildinfo

# tanstack router
dist
dist-ssr
*.local
count.txt
.nitro
.tanstack
.wrangler
1 change: 1 addition & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
npm run typecheck && npx lint-staged
11 changes: 11 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"files.watcherExclude": {
"**/routeTree.gen.ts": true
},
"search.exclude": {
"**/routeTree.gen.ts": true
},
"files.readonlyInclude": {
"**/routeTree.gen.ts": true
}
}
22 changes: 22 additions & 0 deletions components.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"rsc": false,
"tsx": true,
"tailwind": {
"config": "",
"css": "src/index.css",
"baseColor": "slate",
"cssVariables": true,
"prefix": ""
},
"iconLibrary": "lucide",
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
},
"registries": {}
}
22 changes: 9 additions & 13 deletions e2e/homepage.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,12 @@ test('has default elements in the page', async ({ page }) => {

await expect(page.getByTestId('show-hide-settings-btn')).toBeVisible();

await expect(page.getByRole('button', { name: '1' })).toBeVisible();
await expect(page.getByRole('button', { name: '2' })).toBeVisible();
expect(await page.getByText('Select a waypoint...').count()).toBe(2);

await expect(page.getByTestId('add-waypoint-button')).toBeVisible();
await expect(page.getByTestId('reset-waypoints-button')).toBeVisible();

await expect(page.getByText('Nonspecific timeNonspecific')).toBeVisible();
await expect(page.getByText('Non-specific time')).toBeVisible();
await expect(page.getByTestId('date-time-picker')).toBeVisible();

await expect(
Expand All @@ -45,19 +44,16 @@ test('has default elements in the page', async ({ page }) => {

await page.getByTestId('isochrones-tab-button').click();

await expect(
page.getByRole('textbox', { name: 'Hit enter for search...' })
).toBeVisible();
await page.getByTestId('reset-center-button').click();
await page.getByTestId('remove-waypoint-button').click();

await expect(page.getByText(/^Settings$/)).toBeVisible();
await expect(page.getByText(/^Isochrones Settings$/)).toBeVisible();

await expect(page.getByText('Maximum Rangemins10')).toBeVisible();
await expect(page.getByText('Interval Stepmins10')).toBeVisible();
await expect(page.getByText('Denoise0.1')).toBeVisible();
await expect(page.getByText('Generalizemeters0')).toBeVisible();
await page.getByText(/^Isochrones Settings$/).click();

// await expect(page.getByRole('button', { name: 'Layers' })).toBeVisible();
await expect(page.getByText('Maximum Range', { exact: true })).toBeVisible();
await expect(page.getByText('Interval Step', { exact: true })).toBeVisible();
await expect(page.getByText('Denoise', { exact: true })).toBeVisible();
await expect(page.getByText('Generalize', { exact: true })).toBeVisible();

await expect(page.getByRole('button', { name: 'Zoom in' })).toBeVisible();
await expect(page.getByRole('button', { name: 'Zoom out' })).toBeVisible();
Expand Down
104 changes: 31 additions & 73 deletions e2e/map.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,10 +137,8 @@ test.describe('Map interactions with right context menu', () => {
await expect(page.getByLabel('Map marker').getByRole('img')).toBeVisible();

await expect(
page
.getByTestId('waypoint-input-0')
.getByRole('textbox', { name: 'Hit enter for search...' })
).toHaveValue('Unter den Linden, Mitte, Berlin, Germany');
page.getByTestId('waypoint-input-0').getByText('Unter den Linden, Mitte,')
).toBeVisible();
});

test('should make Nominatim request when clicking "Directions to here"', async ({
Expand Down Expand Up @@ -201,10 +199,8 @@ test.describe('Map interactions with right context menu', () => {
await expect(page.getByLabel('Map marker').getByRole('img')).toBeVisible();

await expect(
page
.getByTestId('waypoint-input-1')
.getByRole('textbox', { name: 'Hit enter for search...' })
).toHaveValue('Unter den Linden, Mitte, Berlin, Germany');
page.getByTestId('waypoint-input-1').getByText('Unter den Linden, Mitte,')
).toBeVisible();
});

test('should make Nominatim request when clicking "Add as via point"', async ({
Expand Down Expand Up @@ -241,10 +237,8 @@ test.describe('Map interactions with right context menu', () => {
await expect(page.getByLabel('Map marker').getByRole('img')).toBeVisible();

await expect(
page
.getByTestId('waypoint-input-1')
.getByRole('textbox', { name: 'Hit enter for search...' })
).toHaveValue('Unter den Linden, Mitte, Berlin, Germany');
page.getByTestId('waypoint-input-1').getByText('Unter den Linden, Mitte,')
).toBeVisible();
});

test('should add multiple via points', async ({ page }) => {
Expand Down Expand Up @@ -272,16 +266,12 @@ test.describe('Map interactions with right context menu', () => {
).toBeVisible();

await expect(
page
.getByTestId('waypoint-input-1')
.getByRole('textbox', { name: 'Hit enter for search...' })
).toHaveValue('Unter den Linden, Mitte, Berlin, Germany');
page.getByTestId('waypoint-input-1').getByText('Unter den Linden, Mitte,')
).toBeVisible();

await expect(
page
.getByTestId('waypoint-input-2')
.getByRole('textbox', { name: 'Hit enter for search...' })
).toHaveValue('Unter den Linden, Mitte, Berlin, Germany');
page.getByTestId('waypoint-input-2').getByText('Unter den Linden, Mitte,')
).toBeVisible();
});

test('should handle at least 9 waypoints', async ({ page }) => {
Expand Down Expand Up @@ -398,7 +388,7 @@ test.describe('Map interactions with right context menu', () => {
).toBeVisible();

await expect(
page.locator('div').filter({ hasText: /^Directions$/ })
page.getByRole('heading', { level: 3, name: 'Directions' })
).toBeVisible();

await expect(
Expand Down Expand Up @@ -566,8 +556,6 @@ test.describe('Map interactions with left context menu', () => {

await page.getByTestId('dd-copy-button').click();

await expect(page.getByText('copied')).toBeVisible();

const clipboardContent = await page.evaluate(() =>
navigator.clipboard.readText()
);
Expand Down Expand Up @@ -638,7 +626,7 @@ https: test.describe('Left drawer', () => {

await page.getByTestId('add-waypoint-button').click();

await expect(page.getByRole('button', { name: '3' })).toBeVisible();
await expect(page.getByRole('button', { name: '3' }).first()).toBeVisible();

// Remove waypoint
await page.getByTestId('reset-waypoints-button').click();
Expand All @@ -652,11 +640,8 @@ https: test.describe('Left drawer', () => {
await setupNominatimMock(page);
const searchRequests = await setupSearchMock(page);

const searchBox = page
.getByTestId('waypoint-input-0')
.getByRole('textbox', { name: 'Hit enter for search...' });

await searchBox.click();
await page.getByTestId('waypoint-input-0').click();
const searchBox = page.getByPlaceholder('Hit enter for search');
await searchBox.fill('Unter den Linden');
await searchBox.press('Enter');

Expand All @@ -679,14 +664,10 @@ https: test.describe('Left drawer', () => {
const searchRequests = await setupSearchMock(page);
const routeRequests = await setupRouteMock(page);

// Add "from" waypoint
const firstSearchBox = page
.getByTestId('waypoint-input-0')
.getByRole('textbox', { name: 'Hit enter for search...' });

await firstSearchBox.click();
await firstSearchBox.fill('Unter den Linden');
await firstSearchBox.press('Enter');
await page.getByTestId('waypoint-input-0').click();
const searchBox = page.getByPlaceholder('Hit enter for search');
await searchBox.fill('Unter den Linden');
await searchBox.press('Enter');

const firstSearchResult = page.getByTestId('search-result');

Expand All @@ -698,15 +679,14 @@ https: test.describe('Left drawer', () => {
).toBeVisible();

// Add "to" waypoint
const secondSearchBox = page
.getByTestId('waypoint-input-1')
.getByRole('textbox', { name: 'Hit enter for search...' });

await secondSearchBox.click();
await page.getByTestId('waypoint-input-1').click();
const secondSearchBox = page.getByPlaceholder('Hit enter for search');
await secondSearchBox.fill('Unter den Linden');
await secondSearchBox.press('Enter');

const secondSearchResult = page.getByTestId('search-result').nth(1);
const secondSearchResult = page
.getByTestId('search-result')
.getByText('Unter den Linden, Mitte,');

await expect(secondSearchResult).toBeVisible();
await secondSearchResult.click();
Expand Down Expand Up @@ -745,49 +725,27 @@ https: test.describe('Left drawer', () => {
).toBeVisible();

await expect(
page
.getByTestId('waypoint-input-1')
.getByRole('textbox', { name: 'Hit enter for search...' })
page.getByTestId('waypoint-input-1').getByText('Unter den Linden, Mitte,')
// .getByRole('textbox', { name: 'Hit enter for search...' })
).toBeVisible();
await expect(
page
.getByTestId('waypoint-input-2')
.getByRole('textbox', { name: 'Hit enter for search...' })
page.getByTestId('waypoint-input-2').getByText('Unter den Linden, Mitte,')
).toBeVisible();

await expect(
page
.getByTestId('waypoint-input-1')
.getByRole('textbox', { name: 'Hit enter for search...' })
).toHaveValue('Unter den Linden, Mitte, Berlin, Germany');

await expect(
page
.getByTestId('waypoint-input-2')
.getByRole('textbox', { name: 'Hit enter for search...' })
).toHaveValue('Unter den Linden, Mitte, Berlin, Germany');

// Remove waypoint 3
await page.getByTestId('remove-waypoint-button').nth(2).click();
await expect(
page
.getByTestId('waypoint-input-2')
.getByRole('textbox', { name: 'Hit enter for search...' })
page.getByTestId('waypoint-input-2').getByText('Unter den Linden, Mitte,')
).not.toBeVisible();

// Remove waypoint (should just clear text without removing actual element)

await page.getByTestId('remove-waypoint-button').nth(1).click();
await expect(
page
.getByTestId('waypoint-input-1')
.getByRole('textbox', { name: 'Hit enter for search...' })
page.getByTestId('waypoint-input-1').getByText('Select a waypoint...')
).toBeVisible();

await expect(
page
.getByTestId('waypoint-input-1')
.getByRole('textbox', { name: 'Hit enter for search...' })
).toHaveValue('');
page.getByTestId('waypoint-input-0').getByText('Select a waypoint...')
).toBeVisible();
});

test('should send the route request again when user changed profile', async ({
Expand Down
7 changes: 5 additions & 2 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import importPlugin from 'eslint-plugin-import';
import jsxA11y from 'eslint-plugin-jsx-a11y';
import tseslint from 'typescript-eslint';
import checkFile from 'eslint-plugin-check-file';
import eslintPluginTanstackQuery from '@tanstack/eslint-plugin-query';
import pluginRouter from '@tanstack/eslint-plugin-router';

export default defineConfig(
{
Expand Down Expand Up @@ -46,7 +48,6 @@ export default defineConfig(
'import/no-anonymous-default-export': 'warn',
'react/no-unknown-property': 'off',
'react/react-in-jsx-scope': 'off',
'react/prop-types': 'off',
'jsx-a11y/alt-text': [
'warn',
{
Expand Down Expand Up @@ -75,8 +76,10 @@ export default defineConfig(
...react.configs.flat['jsx-runtime'],
},
{
...reactHooks.configs['recommended-latest'],
...reactHooks.configs.flat['recommended-latest'],
},
...eslintPluginTanstackQuery.configs['flat/recommended'],
...pluginRouter.configs['flat/recommended'],
{
linterOptions: {
reportUnusedDisableDirectives: true,
Expand Down
36 changes: 6 additions & 30 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,40 +2,16 @@
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" type="image/png" href="%PUBLIC_URL%/favicon.png" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<meta name="theme-color" content="#000000" />
<!--
manifest.json provides metadata used when your web app is added to the
homescreen on Android. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.

Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<meta name="description" content="Valhalla FOSSGIS Server Demo App - Route planning and navigation" />
<link rel="icon" type="image/png" href="/favicon.png" />
<link rel="manifest" href="/manifest.json" />
<title>Valhalla FOSSGIS Server Demo App</title>
<script type="module" src="src/index"></script></head>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="valhalla-app-root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.

You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.

To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
<script type="module" src="/src/index.tsx"></script>
</body>
</html>
Loading