130 lines
5.1 KiB
TypeScript
130 lines
5.1 KiB
TypeScript
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
|
|
const { amapPlaces } = vi.hoisted(() => ({
|
|
amapPlaces: {
|
|
searchAmapPlaces: vi.fn(),
|
|
autocompleteAmapPlaces: vi.fn(),
|
|
getAmapPlaceDetails: vi.fn(),
|
|
getAmapPlaceDetailsExpanded: vi.fn(),
|
|
reverseAmapGeocode: vi.fn(),
|
|
searchAmapPois: vi.fn(),
|
|
resolveAmapUri: vi.fn(),
|
|
},
|
|
}));
|
|
vi.mock('../../../src/services/amap/amap.places', () => amapPlaces);
|
|
|
|
const { serveFilePath } = vi.hoisted(() => ({ serveFilePath: vi.fn() }));
|
|
vi.mock('../../../src/services/placePhotoCache', () => ({ serveFilePath }));
|
|
|
|
import { MapsService } from '../../../src/nest/maps/maps.service';
|
|
import type { DatabaseService } from '../../../src/nest/database/database.service';
|
|
|
|
/** A DatabaseService stub whose get() returns the row the test wants. */
|
|
function makeDb(row?: { value: string }) {
|
|
const get = vi.fn(() => row);
|
|
const db = { get } as unknown as DatabaseService;
|
|
return { db, get };
|
|
}
|
|
|
|
function svc(row?: { value: string }) {
|
|
return new MapsService(makeDb(row).db);
|
|
}
|
|
|
|
beforeEach(() => vi.clearAllMocks());
|
|
|
|
describe('MapsService', () => {
|
|
describe('kill-switch settings reads', () => {
|
|
it('reports a switch disabled when the stored value is exactly "false"', () => {
|
|
expect(svc({ value: 'false' }).autocompleteDisabled()).toBe(true);
|
|
expect(svc({ value: 'false' }).detailsDisabled()).toBe(true);
|
|
expect(svc({ value: 'false' }).photosDisabled()).toBe(true);
|
|
});
|
|
|
|
it('reports enabled when the value is "true"', () => {
|
|
expect(svc({ value: 'true' }).autocompleteDisabled()).toBe(false);
|
|
expect(svc({ value: 'true' }).detailsDisabled()).toBe(false);
|
|
expect(svc({ value: 'true' }).photosDisabled()).toBe(false);
|
|
});
|
|
|
|
it('reports enabled when the setting row is absent', () => {
|
|
expect(svc(undefined).autocompleteDisabled()).toBe(false);
|
|
expect(svc(undefined).detailsDisabled()).toBe(false);
|
|
expect(svc(undefined).photosDisabled()).toBe(false);
|
|
});
|
|
|
|
it('queries the matching app_settings key', () => {
|
|
const { db, get } = makeDb({ value: 'true' });
|
|
const s = new MapsService(db);
|
|
s.autocompleteDisabled();
|
|
expect(get).toHaveBeenCalledWith(expect.stringContaining('app_settings'), 'places_autocomplete_enabled');
|
|
s.detailsDisabled();
|
|
expect(get).toHaveBeenCalledWith(expect.any(String), 'places_details_enabled');
|
|
s.photosDisabled();
|
|
expect(get).toHaveBeenCalledWith(expect.any(String), 'places_photos_enabled');
|
|
});
|
|
});
|
|
|
|
describe('delegation to the AMap adapter', () => {
|
|
it('search forwards userId, query, lang and bias', () => {
|
|
amapPlaces.searchAmapPlaces.mockResolvedValue({ places: [], source: 'amap' });
|
|
const bias = { lat: 1, lng: 2, radius: 5 };
|
|
svc().search(3, 'berlin', 'de', bias);
|
|
expect(amapPlaces.searchAmapPlaces).toHaveBeenCalledWith(expect.anything(), 'berlin', 'de', bias);
|
|
});
|
|
|
|
it('search works without optional args', () => {
|
|
svc().search(3, 'berlin');
|
|
expect(amapPlaces.searchAmapPlaces).toHaveBeenCalledWith(expect.anything(), 'berlin', undefined, undefined);
|
|
});
|
|
|
|
it('autocomplete forwards through', () => {
|
|
const bias = { low: { lat: 1, lng: 2 }, high: { lat: 3, lng: 4 } };
|
|
svc().autocomplete(3, 'be', 'en', bias);
|
|
expect(amapPlaces.autocompleteAmapPlaces).toHaveBeenCalledWith(expect.anything(), 'be', 'en', bias);
|
|
});
|
|
|
|
it('details forwards through', () => {
|
|
svc().details(3, 'p1', 'de');
|
|
expect(amapPlaces.getAmapPlaceDetails).toHaveBeenCalledWith(expect.anything(), 'p1', 'de');
|
|
});
|
|
|
|
it('detailsExpanded forwards refresh through', () => {
|
|
svc().detailsExpanded(3, 'p1', 'de', true);
|
|
expect(amapPlaces.getAmapPlaceDetailsExpanded).toHaveBeenCalledWith(expect.anything(), 'p1', 'de', true);
|
|
});
|
|
|
|
it('photo returns an empty AMap-compatible result without calling legacy providers', async () => {
|
|
await expect(svc().photo(3, 'p1', 1.5, 2.5, 'Spot')).resolves.toEqual({ photoUrl: null });
|
|
});
|
|
|
|
it('reverse forwards through', () => {
|
|
svc().reverse('1', '2', 'de');
|
|
expect(amapPlaces.reverseAmapGeocode).toHaveBeenCalledWith(expect.anything(), '1', '2', 'de');
|
|
});
|
|
|
|
it('resolveUrl forwards through', () => {
|
|
svc().resolveUrl('https://uri.amap.com/marker?position=116.39747,39.908823');
|
|
expect(amapPlaces.resolveAmapUri).toHaveBeenCalledWith('https://uri.amap.com/marker?position=116.39747,39.908823');
|
|
});
|
|
|
|
it('pois forwards category and bbox through', () => {
|
|
const bbox = { south: 1, west: 2, north: 3, east: 4 };
|
|
svc().pois('cafe', bbox);
|
|
expect(amapPlaces.searchAmapPois).toHaveBeenCalledWith(expect.anything(), 'cafe', bbox);
|
|
});
|
|
});
|
|
|
|
describe('photoBytesPath', () => {
|
|
it('returns the cached file path from placePhotoCache', () => {
|
|
serveFilePath.mockReturnValue('/cache/p1.jpg');
|
|
expect(svc().photoBytesPath('p1')).toBe('/cache/p1.jpg');
|
|
expect(serveFilePath).toHaveBeenCalledWith('p1');
|
|
});
|
|
|
|
it('returns null when nothing is cached', () => {
|
|
serveFilePath.mockReturnValue(null);
|
|
expect(svc().photoBytesPath('p1')).toBeNull();
|
|
});
|
|
});
|
|
});
|