mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-23 07:26:30 +00:00
Add a contract for place enrichment
This commit is contained in:
@@ -3,6 +3,10 @@ import {
|
||||
mapsAutocompleteRequestSchema,
|
||||
mapsReverseQuerySchema,
|
||||
mapsResolveUrlRequestSchema,
|
||||
mapsPlaceEnrichmentRequestSchema,
|
||||
mapsPlaceEnrichmentResultSchema,
|
||||
placePhotoCandidateSchema,
|
||||
placeDescriptionSchema,
|
||||
} from './maps.schema';
|
||||
|
||||
import { describe, it, expect } from 'vitest';
|
||||
@@ -60,3 +64,94 @@ describe('mapsResolveUrlRequestSchema', () => {
|
||||
expect(mapsResolveUrlRequestSchema.safeParse({ url: '' }).success).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('mapsPlaceEnrichmentRequestSchema', () => {
|
||||
const base = { lat: 52.5, lng: 13.4, name: 'Museum Ludwig' };
|
||||
|
||||
it('needs coordinates and a name, but not a place id', () => {
|
||||
expect(mapsPlaceEnrichmentRequestSchema.safeParse(base).success).toBe(true);
|
||||
expect(mapsPlaceEnrichmentRequestSchema.safeParse({ ...base, placeId: 'ChIJx' }).success).toBe(true);
|
||||
expect(mapsPlaceEnrichmentRequestSchema.safeParse({ lat: 52.5, lng: 13.4 }).success).toBe(false);
|
||||
expect(mapsPlaceEnrichmentRequestSchema.safeParse({ ...base, name: '' }).success).toBe(false);
|
||||
});
|
||||
|
||||
it('rejects coordinates that arrived as strings or null', () => {
|
||||
// The client reads these off a provider blob, where lat can be a string.
|
||||
expect(mapsPlaceEnrichmentRequestSchema.safeParse({ ...base, lat: '52.5' }).success).toBe(false);
|
||||
expect(mapsPlaceEnrichmentRequestSchema.safeParse({ ...base, lng: null }).success).toBe(false);
|
||||
});
|
||||
|
||||
it('caps the free-text fields so a pasted blob cannot reach the providers', () => {
|
||||
expect(mapsPlaceEnrichmentRequestSchema.safeParse({ ...base, name: 'x'.repeat(301) }).success).toBe(false);
|
||||
expect(mapsPlaceEnrichmentRequestSchema.safeParse({ ...base, placeId: 'x'.repeat(301) }).success).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('placePhotoCandidateSchema', () => {
|
||||
const candidate = {
|
||||
key: 'ChIJx~p0',
|
||||
url: '/api/maps/place-photo/ChIJx~p0/bytes',
|
||||
attribution: 'Jane Doe',
|
||||
license: 'CC BY-SA 4.0',
|
||||
licenseUrl: 'https://creativecommons.org/licenses/by-sa/4.0/',
|
||||
sourceUrl: 'https://commons.wikimedia.org/wiki/File:X.jpg',
|
||||
source: 'wikimedia',
|
||||
};
|
||||
|
||||
it('accepts a fully attributed candidate', () => {
|
||||
expect(placePhotoCandidateSchema.safeParse(candidate).success).toBe(true);
|
||||
});
|
||||
|
||||
it('allows every licence field to be null, because Google supplies none of them', () => {
|
||||
expect(
|
||||
placePhotoCandidateSchema.safeParse({
|
||||
...candidate,
|
||||
source: 'google',
|
||||
attribution: null,
|
||||
license: null,
|
||||
licenseUrl: null,
|
||||
sourceUrl: null,
|
||||
}).success,
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('requires the fields to be present even when null, so the column cannot silently skip attribution', () => {
|
||||
const { attribution, ...withoutAttribution } = candidate;
|
||||
void attribution;
|
||||
expect(placePhotoCandidateSchema.safeParse(withoutAttribution).success).toBe(false);
|
||||
});
|
||||
|
||||
it('rejects an unknown source', () => {
|
||||
expect(placePhotoCandidateSchema.safeParse({ ...candidate, source: 'unsplash' }).success).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('placeDescriptionSchema', () => {
|
||||
it('keeps the source alongside the text', () => {
|
||||
expect(
|
||||
placeDescriptionSchema.safeParse({
|
||||
text: 'A museum in Cologne.',
|
||||
source: 'wikipedia',
|
||||
sourceUrl: 'https://de.wikipedia.org/wiki/Museum_Ludwig',
|
||||
license: 'CC BY-SA 4.0',
|
||||
}).success,
|
||||
).toBe(true);
|
||||
expect(placeDescriptionSchema.safeParse({ text: 'A museum.' }).success).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('mapsPlaceEnrichmentResultSchema', () => {
|
||||
it('accepts an empty result, which is what a keyless instance with no Commons hit returns', () => {
|
||||
expect(mapsPlaceEnrichmentResultSchema.safeParse({ photos: [], description: null }).success).toBe(true);
|
||||
});
|
||||
|
||||
it('accepts the kill-switch response', () => {
|
||||
expect(
|
||||
mapsPlaceEnrichmentResultSchema.safeParse({ photos: [], description: null, disabled: true }).success,
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('requires description to be explicitly null rather than absent', () => {
|
||||
expect(mapsPlaceEnrichmentResultSchema.safeParse({ photos: [] }).success).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user