mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-22 15:06:32 +00:00
test(mobile): cover the trip screens
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
import { describe, it, expect } from 'vitest'
|
||||
import { filterPool, poolCounts } from './placesBrowserModel'
|
||||
import type { Place } from '../../../../types'
|
||||
import {
|
||||
filterPool, firstPlannedDayNumbers, matchesCategoryFilter, matchesSearch,
|
||||
plannedPlaceIds, poolCounts,
|
||||
} from './placesBrowserModel'
|
||||
import type { AssignmentsMap, Day, Place } from '../../../../types'
|
||||
|
||||
const mkPlace = (id: number, over: Partial<Place> = {}): Place =>
|
||||
({ id, name: `Place ${id}`, lat: 0, lng: 0, address: null, category_id: null, ...over } as Place)
|
||||
@@ -38,3 +41,114 @@ describe('placesBrowserModel — planned pool', () => {
|
||||
expect(c.unplanned).toBe(1)
|
||||
})
|
||||
})
|
||||
|
||||
// FE-MOB-PMODEL-001 to FE-MOB-PMODEL-012
|
||||
|
||||
const mkAssignment = (id: number, placeId: number | null) =>
|
||||
({ id, place: placeId == null ? null : { id: placeId, name: `Place ${placeId}` } })
|
||||
|
||||
const mkDays = (spec: [number, number | null][]): Day[] =>
|
||||
spec.map(([id, dayNumber]) => ({ id, day_number: dayNumber }) as Day)
|
||||
|
||||
describe('placesBrowserModel — assignment lookups', () => {
|
||||
it('FE-MOB-PMODEL-001: plannedPlaceIds collects every assigned place across all days', () => {
|
||||
const assignments = {
|
||||
'1': [mkAssignment(10, 5), mkAssignment(11, 6)],
|
||||
'2': [mkAssignment(12, 5)],
|
||||
} as unknown as AssignmentsMap
|
||||
expect([...plannedPlaceIds(assignments)].sort()).toEqual([5, 6])
|
||||
})
|
||||
|
||||
it('FE-MOB-PMODEL-002: plannedPlaceIds skips assignments whose place did not join', () => {
|
||||
const assignments = { '1': [mkAssignment(10, null), mkAssignment(11, 7)] } as unknown as AssignmentsMap
|
||||
expect([...plannedPlaceIds(assignments)]).toEqual([7])
|
||||
})
|
||||
|
||||
it('FE-MOB-PMODEL-003: plannedPlaceIds is empty without assignments', () => {
|
||||
expect(plannedPlaceIds({} as AssignmentsMap).size).toBe(0)
|
||||
})
|
||||
|
||||
it('FE-MOB-PMODEL-004: firstPlannedDayNumbers keeps the lowest day a place appears on', () => {
|
||||
const assignments = {
|
||||
'30': [mkAssignment(10, 5)],
|
||||
'10': [mkAssignment(11, 5)],
|
||||
'20': [mkAssignment(12, 6)],
|
||||
} as unknown as AssignmentsMap
|
||||
const days = mkDays([[10, 1], [20, 2], [30, 3]])
|
||||
const result = firstPlannedDayNumbers(assignments, days)
|
||||
expect(result.get(5)).toBe(1)
|
||||
expect(result.get(6)).toBe(2)
|
||||
})
|
||||
|
||||
it('FE-MOB-PMODEL-005: firstPlannedDayNumbers falls back to the array position without a day_number', () => {
|
||||
const assignments = { '20': [mkAssignment(10, 5)] } as unknown as AssignmentsMap
|
||||
const days = mkDays([[10, null], [20, null]])
|
||||
expect(firstPlannedDayNumbers(assignments, days).get(5)).toBe(2)
|
||||
})
|
||||
|
||||
it('FE-MOB-PMODEL-006: firstPlannedDayNumbers ignores assignments of a day the trip no longer has', () => {
|
||||
const assignments = {
|
||||
'99': [mkAssignment(10, 5)],
|
||||
'10': [mkAssignment(11, 6), mkAssignment(12, null)],
|
||||
} as unknown as AssignmentsMap
|
||||
const result = firstPlannedDayNumbers(assignments, mkDays([[10, 1]]))
|
||||
expect(result.has(5)).toBe(false)
|
||||
expect(result.get(6)).toBe(1)
|
||||
})
|
||||
})
|
||||
|
||||
describe('placesBrowserModel — predicates', () => {
|
||||
it('FE-MOB-PMODEL-007: an empty category set matches everything', () => {
|
||||
expect(matchesCategoryFilter(mkPlace(1), new Set())).toBe(true)
|
||||
expect(matchesCategoryFilter(mkPlace(2, { category_id: 4 }), new Set())).toBe(true)
|
||||
})
|
||||
|
||||
it('FE-MOB-PMODEL-008: a category set matches on the stringified id', () => {
|
||||
const filters = new Set(['4'])
|
||||
expect(matchesCategoryFilter(mkPlace(1, { category_id: 4 }), filters)).toBe(true)
|
||||
expect(matchesCategoryFilter(mkPlace(2, { category_id: 5 }), filters)).toBe(false)
|
||||
expect(matchesCategoryFilter(mkPlace(3), filters)).toBe(false)
|
||||
})
|
||||
|
||||
it('FE-MOB-PMODEL-009: places without a category need the uncategorized entry', () => {
|
||||
expect(matchesCategoryFilter(mkPlace(1), new Set(['uncategorized']))).toBe(true)
|
||||
expect(matchesCategoryFilter(mkPlace(2, { category_id: 4 }), new Set(['uncategorized']))).toBe(false)
|
||||
})
|
||||
|
||||
it('FE-MOB-PMODEL-010: search is case-insensitive over name and address', () => {
|
||||
const place = mkPlace(1, { name: 'Louvre', address: 'Rue de Rivoli' })
|
||||
expect(matchesSearch(place, '')).toBe(true)
|
||||
expect(matchesSearch(place, 'LOUV')).toBe(true)
|
||||
expect(matchesSearch(place, 'rivoli')).toBe(true)
|
||||
expect(matchesSearch(place, 'eiffel')).toBe(false)
|
||||
// A null address must not blow up the lookup.
|
||||
expect(matchesSearch(mkPlace(2, { name: 'Eiffel' }), 'rivoli')).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe('placesBrowserModel — tracks pool', () => {
|
||||
const places = [
|
||||
mkPlace(1, { name: 'Ridge', route_geometry: 'abc', category_id: 4 }),
|
||||
mkPlace(2, { name: 'Museum', category_id: 4 }),
|
||||
mkPlace(3, { name: 'River', route_geometry: 'def' }),
|
||||
]
|
||||
const plannedIds = new Set([1])
|
||||
|
||||
it('FE-MOB-PMODEL-011: the tracks filter keeps only places carrying a geometry', () => {
|
||||
const out = filterPool(places, { filter: 'tracks', categoryFilters: new Set(), search: '', plannedIds })
|
||||
expect(out.map(p => p.id)).toEqual([1, 3])
|
||||
})
|
||||
|
||||
it('FE-MOB-PMODEL-012: the tracks filter still honors category and search', () => {
|
||||
const out = filterPool(places, { filter: 'tracks', categoryFilters: new Set(['4']), search: 'rid', plannedIds })
|
||||
expect(out.map(p => p.id)).toEqual([1])
|
||||
})
|
||||
|
||||
it('FE-MOB-PMODEL-013: poolCounts counts tracks on the category+search base set', () => {
|
||||
const c = poolCounts(places, new Set(['4']), '', plannedIds)
|
||||
expect(c.all).toBe(2)
|
||||
expect(c.tracks).toBe(1)
|
||||
expect(c.planned).toBe(1)
|
||||
expect(c.unplanned).toBe(1)
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user