fix(admin): the default map template offers the Amap presets users can pick

In the admin's default user settings, the map template dropdown listed
seven tile presets, while every user's own map settings listed nine: the
same seven plus Amap and Amap Satellite. An admin running an instance for
people in mainland China could not pick the one basemap that works well
there as the default, short of pasting its URL by hand.

The Amap presets (57eac32f9) were added to the two user preset copies and
not to the admin's separate copy; nothing in that change or later gives a
reason, and the server stores any template as a default. The later
refactor kept the gap as DEFAULT_MAP_PRESETS beside MAP_PRESETS. There is
now one MAP_PRESETS list, read by the user settings and the admin defaults
on both desktop and phone.

Regression test FE-ADMIN-DUS-029 (DefaultUserSettingsTab.test.tsx) was red
on the old code: "Unable to find role="button" and name "高德地图 (Amap)"".

Changed assertions:
- useMapSettingsForm.test.ts FE-COMP-MAPFORM-001: it expected the admin list
  DEFAULT_MAP_PRESETS to hold 7 presets and the user list to add Amap on
  top; it now expects the one list to hold 9 presets including both Amap
  templates.
This commit is contained in:
Maurice
2026-10-09 17:53:52 +02:00
parent d6850756c6
commit 24461ecf76
5 changed files with 25 additions and 21 deletions
@@ -1,4 +1,4 @@
// FE-ADMIN-DUS-001 to FE-ADMIN-DUS-028
// FE-ADMIN-DUS-001 to FE-ADMIN-DUS-029
import { render, screen, waitFor, within, fireEvent } from '../../../tests/helpers/render';
import userEvent from '@testing-library/user-event';
import { http, HttpResponse } from 'msw';
@@ -6,6 +6,7 @@ import { server } from '../../../tests/helpers/msw/server';
import { resetAllStores, seedStore } from '../../../tests/helpers/store';
import { buildAdmin } from '../../../tests/helpers/factories';
import { useAuthStore } from '../../store/authStore';
import { AMAP_ROAD } from '../../constants/mapDefaults';
import { ToastContainer } from '../shared/Toast';
import DefaultUserSettingsTab from './DefaultUserSettingsTab';
@@ -220,6 +221,18 @@ describe('DefaultUserSettingsTab', () => {
expect(screen.getByTestId('map-preview')).toHaveAttribute('data-tile', url);
});
it('FE-ADMIN-DUS-029: the Amap presets a user can pick are offered as instance defaults too', async () => {
const user = userEvent.setup();
const { puts } = stubDefaults();
render(<DefaultUserSettingsTab />);
await screen.findByText('Default User Settings');
await pickFromSelect(user, 'Select template...', '高德地图 (Amap)');
await waitFor(() => expect(puts).toEqual([{ map_tile_url: AMAP_ROAD }]));
expect(screen.getByTestId('map-preview')).toHaveAttribute('data-tile', AMAP_ROAD);
});
it('FE-ADMIN-DUS-011: a hand-typed tile URL is saved on blur', async () => {
const user = userEvent.setup();
const { puts } = stubDefaults();
@@ -12,7 +12,7 @@ import type { DistanceUnit, WeekStart } from '../../types'
import { weekStartOptions } from '../../utils/calendarWeek'
import { withTileApiKey } from '../../utils/tileUrl'
import { defaultStyleForProvider } from '../Map/glProviders'
import { DEFAULT_MAP_PRESETS as MAP_PRESETS, type MapProvider } from '../Settings/mapSettingsModel'
import { MAP_PRESETS, type MapProvider } from '../Settings/mapSettingsModel'
import RoutingInstanceFields from './RoutingInstanceFields'
import { useDefaultUserSettings, type Defaults } from './useDefaultUserSettings'
@@ -18,8 +18,11 @@ export interface MapPreset {
url: string;
}
/** The tile presets an admin can make the default for every user. */
export const DEFAULT_MAP_PRESETS: MapPreset[] = [
/**
* The tile presets a user picks from in their own map settings, and the same list
* an admin picks the default for every user from.
*/
export const MAP_PRESETS: MapPreset[] = [
{ name: 'OpenStreetMap', url: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png' },
{ name: 'OpenStreetMap DE', url: 'https://tile.openstreetmap.de/{z}/{x}/{y}.png' },
// The app default, and a vector style rather than a {z}/{x}/{y} template: no
@@ -31,11 +34,6 @@ export const DEFAULT_MAP_PRESETS: MapPreset[] = [
{ name: 'CartoDB Light', url: 'https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png' },
{ name: 'CartoDB Dark', url: 'https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png' },
{ name: 'Stadia Smooth', url: 'https://tiles.stadiamaps.com/tiles/alidade_smooth/{z}/{x}/{y}{r}.png' },
];
/** The tile presets a user picks from in their own map settings. */
export const MAP_PRESETS: MapPreset[] = [
...DEFAULT_MAP_PRESETS,
// Amap (高德). GCJ-02 tiles: the map switches to a shifted projection for
// these so markers still land on the right street (see gcj02Crs.ts). The only
// basemap here that is genuinely good inside mainland China.
@@ -3,18 +3,12 @@ import { act, renderHook } from '@testing-library/react';
import { buildSettings } from '../../../tests/helpers/factories';
import { resetAllStores, seedStore } from '../../../tests/helpers/store';
import { AMAP_ROAD, AMAP_SATELLITE } from '../../constants/mapDefaults';
import { useAuthStore } from '../../store/authStore';
import { useSettingsStore } from '../../store/settingsStore';
import type { Settings } from '../../types';
import { MAPBOX_DEFAULT_STYLE, OPENFREEMAP_DEFAULT_STYLE } from '../Map/glProviders';
import {
DEFAULT_MAP_PRESETS,
MAP_PRESETS,
PREVIEW_CENTER,
normalizeProvider,
slotStyle,
styleForProvider,
} from './mapSettingsModel';
import { MAP_PRESETS, PREVIEW_CENTER, normalizeProvider, slotStyle, styleForProvider } from './mapSettingsModel';
import { useMapSettingsForm } from './useMapSettingsForm';
const toast = vi.hoisted(() => ({ success: vi.fn(), error: vi.fn() }));
@@ -36,10 +30,9 @@ beforeEach(() => {
});
describe('mapSettingsModel', () => {
it('FE-COMP-MAPFORM-001: the user list adds the two Amap presets to the admin list', () => {
expect(MAP_PRESETS.slice(0, DEFAULT_MAP_PRESETS.length)).toEqual(DEFAULT_MAP_PRESETS);
expect(DEFAULT_MAP_PRESETS).toHaveLength(7);
it('FE-COMP-MAPFORM-001: one preset list, the two Amap presets included, serves users and the admin defaults', () => {
expect(MAP_PRESETS).toHaveLength(9);
expect(MAP_PRESETS.map((p) => p.url)).toEqual(expect.arrayContaining([AMAP_ROAD, AMAP_SATELLITE]));
});
it('FE-COMP-MAPFORM-002: provider and style rules', () => {
@@ -7,7 +7,7 @@ import { getApiErrorMessage, type DistanceUnit, type WeekStart } from '../../../
import { weekStartOptions } from '../../../utils/calendarWeek'
import { withTileApiKey } from '../../../utils/tileUrl'
import { defaultStyleForProvider } from '../../../components/Map/glProviders'
import { DEFAULT_MAP_PRESETS as MAP_PRESETS, type MapProvider } from '../../../components/Settings/mapSettingsModel'
import { MAP_PRESETS, type MapProvider } from '../../../components/Settings/mapSettingsModel'
import { useDefaultUserSettings, type Defaults } from '../../../components/Admin/useDefaultUserSettings'
import MToggle from '../../components/MToggle'
import MSegmented from '../../components/MSegmented'