mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-22 06:56:35 +00:00
fix(client): the audit round over the 4.3.1 release
Ride minutes and late marks follow an edited timetable instead of the routing that fetched them; a landing day's join band reads as the ride it is rather than a nine hour drive of no length; the refuel offer is there on the road out of a terminal or a pick-up desk; the phone's stage map draws the ride; the share page numbers its stops the way the planner does; the PDF lists a day the way the day plan lists it, from both shells; a poster-less clip draws its play badge everywhere, not only in the editor; the hero title has room for its descenders and the list card keeps its badge clear; the release notice keeps its close control in reach when it stacks; a link chip's actions are thumb-sized and its delete asks first; the Google retry line and the Google-only switch appear only where Google answers.
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { offersGoogleRetry, sourceLabelFor } from './placeSource'
|
||||
import { googleHoldsSlot, offersGoogleRetry, placesGoogleOnlyHint, selectGoogleHoldsSlot, sourceLabelFor } from './placeSource'
|
||||
|
||||
describe('offersGoogleRetry', () => {
|
||||
it('FE-PLACESOURCE-001: offers Google for a list the index or OpenStreetMap answered, only where a key exists', () => {
|
||||
it('FE-PLACESOURCE-001: offers Google for a list the index or OpenStreetMap answered, only where Google answers', () => {
|
||||
expect(offersGoogleRetry('trek-places+openstreetmap', true)).toBe(true)
|
||||
expect(offersGoogleRetry('openstreetmap', true)).toBe(true)
|
||||
expect(offersGoogleRetry('trek-places+plugin', true)).toBe(true)
|
||||
@@ -17,6 +17,37 @@ describe('offersGoogleRetry', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('googleHoldsSlot', () => {
|
||||
it('FE-PLACESOURCE-004: a key holds the slot under auto and google, not under Amap or OpenStreetMap', () => {
|
||||
expect(googleHoldsSlot(true, 'auto')).toBe(true)
|
||||
expect(googleHoldsSlot(true, 'google')).toBe(true)
|
||||
// A stored key still serves photos and details here, but the server never
|
||||
// walks the Google chain for a search, so a link that offered it would be dead.
|
||||
expect(googleHoldsSlot(true, 'amap')).toBe(false)
|
||||
expect(googleHoldsSlot(true, 'openstreetmap')).toBe(false)
|
||||
expect(googleHoldsSlot(false, 'google')).toBe(false)
|
||||
// Unrecognised reads as auto, as the server reads it.
|
||||
expect(googleHoldsSlot(true, '')).toBe(true)
|
||||
})
|
||||
|
||||
it('FE-PLACESOURCE-005: the store selector asks the same question of the auth state', () => {
|
||||
expect(selectGoogleHoldsSlot({ hasMapsKey: true, placesProvider: 'auto' })).toBe(true)
|
||||
expect(selectGoogleHoldsSlot({ hasMapsKey: true, placesProvider: 'openstreetmap' })).toBe(false)
|
||||
expect(selectGoogleHoldsSlot({ hasMapsKey: false, placesProvider: 'auto' })).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe('placesGoogleOnlyHint', () => {
|
||||
it('FE-PLACESOURCE-006: names what the admin has to do before the switch does anything', () => {
|
||||
expect(placesGoogleOnlyHint(false, 'auto')).toBe('admin.placesGoogleOnly.missingKey')
|
||||
expect(placesGoogleOnlyHint(false, 'openstreetmap')).toBe('admin.placesGoogleOnly.missingKey')
|
||||
expect(placesGoogleOnlyHint(true, 'amap')).toBe('admin.placesGoogleOnly.otherProvider')
|
||||
expect(placesGoogleOnlyHint(true, 'openstreetmap')).toBe('admin.placesGoogleOnly.otherProvider')
|
||||
expect(placesGoogleOnlyHint(true, 'auto')).toBe('admin.placesGoogleOnly.subtitle')
|
||||
expect(placesGoogleOnlyHint(true, 'google')).toBe('admin.placesGoogleOnly.subtitle')
|
||||
})
|
||||
})
|
||||
|
||||
describe('sourceLabelFor', () => {
|
||||
it('FE-PLACESOURCE-003: a row names its own index, else the list it came from', () => {
|
||||
const t = (k: string) => k
|
||||
|
||||
@@ -32,6 +32,52 @@ const SOURCE_KEYS: Record<string, string> = {
|
||||
amap: 'places.source.amap',
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether a search can reach Google on this install at all.
|
||||
*
|
||||
* A stored key is not enough. The server walks the Google key chain only while
|
||||
* the admin's provider choice leaves Google the keyed slot, which is `auto` or
|
||||
* `google`; under Amap or OpenStreetMap the key still serves photos and
|
||||
* details, but a search sent to Google is answered by the index as before.
|
||||
* Anything unrecognised reads as `auto`, the way the server reads it.
|
||||
*/
|
||||
export function googleHoldsSlot(hasMapsKey: boolean, placesProvider: string): boolean {
|
||||
return hasMapsKey && placesProvider !== 'amap' && placesProvider !== 'openstreetmap'
|
||||
}
|
||||
|
||||
/** The same question asked of the auth store, for `useAuthStore(selectGoogleHoldsSlot)`. */
|
||||
export const selectGoogleHoldsSlot = (s: { hasMapsKey: boolean; placesProvider: string }): boolean =>
|
||||
googleHoldsSlot(s.hasMapsKey, s.placesProvider)
|
||||
|
||||
/**
|
||||
* Whether a result list can be sent to Google instead.
|
||||
*
|
||||
* The index and OpenStreetMap answer first, and Google is only asked when they
|
||||
* find nothing, so a list that has the wrong place on it never reaches Google
|
||||
* on its own. The link that sends it there is offered when Google holds the
|
||||
* keyed slot (googleHoldsSlot above) and this list did not already come from
|
||||
* Google: a list Google produced, alone or as the empty-case fallback, has
|
||||
* nowhere further to go, and the offline cache is not a search at all.
|
||||
*/
|
||||
export function offersGoogleRetry(listSource: string, googleAnswers: boolean): boolean {
|
||||
if (!googleAnswers || !listSource) return false
|
||||
return !listSource.split('+').includes('google') && listSource !== 'offline-cache'
|
||||
}
|
||||
|
||||
/**
|
||||
* The line under the admin's "Search with Google only" switch.
|
||||
*
|
||||
* Two ways the switch can be a promise the search cannot keep, and they ask
|
||||
* different things of the admin: paste a key, or hand the keyed slot back to
|
||||
* Google. The subtitle that says what the switch does is only true of the
|
||||
* third state.
|
||||
*/
|
||||
export function placesGoogleOnlyHint(hasMapsKey: boolean, placesProvider: string): string {
|
||||
if (!hasMapsKey) return 'admin.placesGoogleOnly.missingKey'
|
||||
if (!googleHoldsSlot(hasMapsKey, placesProvider)) return 'admin.placesGoogleOnly.otherProvider'
|
||||
return 'admin.placesGoogleOnly.subtitle'
|
||||
}
|
||||
|
||||
/**
|
||||
* The label for one row.
|
||||
*
|
||||
@@ -40,21 +86,6 @@ const SOURCE_KEYS: Record<string, string> = {
|
||||
* answered the call: Google never marks its places, and a merged list marks only
|
||||
* the index side, so an unmarked row in one is OpenStreetMap by elimination.
|
||||
*/
|
||||
/**
|
||||
* Whether a result list can be sent to Google instead.
|
||||
*
|
||||
* The index and OpenStreetMap answer first, and Google is only asked when they
|
||||
* find nothing, so a list that has the wrong place on it never reaches Google
|
||||
* on its own. The link that sends it there is offered when the instance has a
|
||||
* Google key and this list did not already come from Google: a list Google
|
||||
* produced, alone or as the empty-case fallback, has nowhere further to go, and
|
||||
* the offline cache is not a search at all.
|
||||
*/
|
||||
export function offersGoogleRetry(listSource: string, hasMapsKey: boolean): boolean {
|
||||
if (!hasMapsKey || !listSource) return false
|
||||
return !listSource.split('+').includes('google') && listSource !== 'offline-cache'
|
||||
}
|
||||
|
||||
export function sourceLabelFor(place: unknown, listSource: string, t: TranslationFn): string | null {
|
||||
const own = (place as { source?: unknown } | null)?.source
|
||||
const source = typeof own === 'string' && own
|
||||
|
||||
Reference in New Issue
Block a user