import { readFileSync } from 'node:fs' import { resolve } from 'node:path' import { describe, it, expect, vi } from 'vitest' import { mountSuspended } from '@nuxt/test-utils/runtime' import KestrelMap from '../../app/components/KestrelMap.vue' vi.mock('leaflet', () => ({ default: {} })) vi.mock('leaflet.offline', () => ({ tileLayerOffline: null, savetiles: null })) describe('KestrelMap', () => { it('renders map container', async () => { const wrapper = await mountSuspended(KestrelMap, { props: { devices: [] }, }) expect(wrapper.find('[data-testid="kestrel-map"]').exists()).toBe(true) }) it('accepts devices prop', async () => { const devices = [ { id: '1', name: 'A', lat: 37.7, lng: -122.4, streamUrl: '', sourceType: 'mjpeg' }, ] const wrapper = await mountSuspended(KestrelMap, { props: { devices }, }) expect(wrapper.props('devices')).toEqual(devices) }) it('has select emit', async () => { const wrapper = await mountSuspended(KestrelMap, { props: { devices: [] }, }) wrapper.vm.$emit('select', { id: 'x', name: 'X', lat: 0, lng: 0 }) expect(wrapper.emitted('select')).toHaveLength(1) }) it('uses dark Carto tile URL with subdomains', async () => { const componentPath = resolve(__dirname, '../../app/components/KestrelMap.vue') const source = readFileSync(componentPath, 'utf-8') expect(source).toContain('basemaps.cartocdn.com/dark_all') expect(source).toContain('{s}.basemaps.cartocdn.com') }) it('requests client location first with maximumAge 0 so browser prompts', async () => { const componentPath = resolve(__dirname, '../../app/components/KestrelMap.vue') const source = readFileSync(componentPath, 'utf-8') expect(source).toContain('getCurrentPosition') expect(source).toContain('enableHighAccuracy: true') expect(source).toContain('maximumAge: 0') expect(source).toContain('createMap([latitude, longitude])') }) it('uses L.tileLayer for base display so tiles load from OSM', async () => { const componentPath = resolve(__dirname, '../../app/components/KestrelMap.vue') const source = readFileSync(componentPath, 'utf-8') expect(source).toContain('L.tileLayer(TILE_URL') expect(source).toContain('baseLayer.addTo(map)') }) it('sets Leaflet default marker icon path to avoid Vue Router intercept', async () => { const componentPath = resolve(__dirname, '../../app/components/KestrelMap.vue') const source = readFileSync(componentPath, 'utf-8') expect(source).toContain('Icon.Default.mergeOptions') expect(source).toContain('marker-icon.png') expect(source).toContain('marker-shadow.png') }) it('accepts pois and canEditPois props', async () => { const wrapper = await mountSuspended(KestrelMap, { props: { devices: [], pois: [{ id: 'p1', lat: 37.7, lng: -122.4, label: 'P', icon_type: 'pin' }], canEditPois: false, }, }) expect(wrapper.props('pois')).toHaveLength(1) expect(wrapper.props('canEditPois')).toBe(false) }) })