mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-24 16:03:02 +00:00
3659297af1
A route planned in Google My Maps or Google Earth can now become a tour without converting it to GPX first. The import button and a file dropped on the tours workspace take .kml and .kmz files beside .gpx, through the same preview, the same import routes and the same transaction as a GPX file. The preview shows every line of the file on its own, numbered, with its distance and heights; two lines of one placemark are numbered after its name and never joined. Heights count only where they are heights: kept for an absolute line, dropped for any other altitude mode and for the all-zero placeholder My Maps writes, so a missing height stays unknown. What the file holds besides its lines (pins, areas, overlays, links to other files) is counted in a dashed card, and nothing is fetched from elsewhere. The KML reading reuses the place import's codec. A KMZ only ever has its KML entry unpacked, counted byte by byte against the decompressed cap whatever its header claims. A file that cannot be read is refused with its reason (damaged, an archive without KML, too large unpacked), and the toast names the file and the reason. A KML or KMZ import keeps the gpx origin of a file import; its provenance names the real format from the stored file name.
50 lines
2.4 KiB
TypeScript
50 lines
2.4 KiB
TypeScript
// FE-W4UTL-001 to FE-W4UTL-008
|
|
import { describe, it, expect } from 'vitest'
|
|
import { getApiErrorCode, getApiErrorMessage } from './apiError'
|
|
|
|
describe('getApiErrorMessage', () => {
|
|
it('FE-W4UTL-001: returns the server-provided error string', () => {
|
|
const err = { response: { data: { error: 'Places API (New) has not been used in project 42' } } }
|
|
expect(getApiErrorMessage(err, 'fallback')).toBe('Places API (New) has not been used in project 42')
|
|
})
|
|
|
|
it('FE-W4UTL-002: falls back when the error field is missing', () => {
|
|
expect(getApiErrorMessage({ response: { data: {} } }, 'fallback')).toBe('fallback')
|
|
expect(getApiErrorMessage({ response: {} }, 'fallback')).toBe('fallback')
|
|
expect(getApiErrorMessage({}, 'fallback')).toBe('fallback')
|
|
})
|
|
|
|
it('FE-W4UTL-003: falls back for null/undefined errors', () => {
|
|
expect(getApiErrorMessage(null, 'fallback')).toBe('fallback')
|
|
expect(getApiErrorMessage(undefined, 'fallback')).toBe('fallback')
|
|
})
|
|
|
|
it('FE-W4UTL-004: falls back for a whitespace-only server message', () => {
|
|
expect(getApiErrorMessage({ response: { data: { error: ' ' } } }, 'fallback')).toBe('fallback')
|
|
expect(getApiErrorMessage({ response: { data: { error: '' } } }, 'fallback')).toBe('fallback')
|
|
})
|
|
|
|
it('FE-W4UTL-005: falls back for a non-string server message', () => {
|
|
expect(getApiErrorMessage({ response: { data: { error: { code: 500 } } } }, 'fallback')).toBe('fallback')
|
|
expect(getApiErrorMessage({ response: { data: { error: 42 } } }, 'fallback')).toBe('fallback')
|
|
})
|
|
|
|
it('FE-W4UTL-006: keeps surrounding whitespace of a real message', () => {
|
|
expect(getApiErrorMessage({ response: { data: { error: ' boom ' } } }, 'fallback')).toBe(' boom ')
|
|
})
|
|
})
|
|
|
|
describe('getApiErrorCode', () => {
|
|
it('FE-W4UTL-007: returns the code a refusal names its reason with', () => {
|
|
expect(getApiErrorCode({ response: { data: { error: 'Invalid KMZ archive.', code: 'archive_invalid' } } })).toBe('archive_invalid')
|
|
})
|
|
|
|
it('FE-W4UTL-008: is null without a code, for an empty or non-string one, and for no error at all', () => {
|
|
expect(getApiErrorCode({ response: { data: { error: 'boom' } } })).toBeNull()
|
|
expect(getApiErrorCode({ response: { data: { code: '' } } })).toBeNull()
|
|
expect(getApiErrorCode({ response: { data: { code: 42 } } })).toBeNull()
|
|
expect(getApiErrorCode(null)).toBeNull()
|
|
expect(getApiErrorCode(undefined)).toBeNull()
|
|
})
|
|
})
|