forked from zhouruizhe/gmTouringMiniApp
Add check-in feature and update travel planner UI
This commit is contained in:
@@ -10,6 +10,7 @@ import {
|
||||
normalizePlanningRequest,
|
||||
normalizePlanResponse,
|
||||
normalizeTravelPreferences,
|
||||
type Pace,
|
||||
type PlanningRequest,
|
||||
type PlanResponse,
|
||||
resolveCanonicalPoiId,
|
||||
@@ -17,6 +18,7 @@ import {
|
||||
} from '../src/domain/travel'
|
||||
import {
|
||||
createPlan,
|
||||
getSessionPlanningOrigin,
|
||||
loadPlan,
|
||||
loadPlanningRequest,
|
||||
loadPreferences,
|
||||
@@ -191,6 +193,44 @@ describe('canonical POI IDs', () => {
|
||||
describe('deterministic local POC planner', () => {
|
||||
const repository = getPoiRepository()
|
||||
|
||||
it.each([
|
||||
[120, 'relaxed', 1],
|
||||
[120, 'moderate', 1],
|
||||
[120, 'compact', 2],
|
||||
[240, 'relaxed', 3],
|
||||
[240, 'moderate', 3],
|
||||
[240, 'compact', 3],
|
||||
[480, 'relaxed', 4],
|
||||
[480, 'moderate', 5],
|
||||
[480, 'compact', 6],
|
||||
[600, 'relaxed', 5],
|
||||
[600, 'moderate', 6],
|
||||
[600, 'compact', 7],
|
||||
] as const)('packs %i-minute %s quick plans into %i POIs without overflow', (durationMinutes, pace, expectedCount) => {
|
||||
const plan = createLocalPlan({
|
||||
mode: 'quick',
|
||||
preferences: preferences({ pace: pace as Pace }),
|
||||
durationMinutes,
|
||||
selectedPoiIds: [],
|
||||
}, repository)
|
||||
|
||||
expect(plan.itinerary.items).toHaveLength(expectedCount)
|
||||
expect(plan.itinerary.items.length).toBeGreaterThanOrEqual(1)
|
||||
expect(plan.itinerary.items.length).toBeLessThanOrEqual(8)
|
||||
expect(plan.itinerary.totalMinutes).toBeLessThanOrEqual(durationMinutes)
|
||||
expect(plan.itinerary.durationFitStatus).not.toBe('overflow')
|
||||
})
|
||||
|
||||
it('rejects a quick plan when even the first stop cannot fit the budget', () => {
|
||||
expect(() => createLocalPlan({
|
||||
mode: 'quick',
|
||||
preferences: preferences({ pace: 'relaxed', transport: 'walking' }),
|
||||
durationMinutes: 120,
|
||||
selectedPoiIds: [],
|
||||
origin: { longitude: 114.3, latitude: 22.3, coordinateSystem: 'GCJ02' },
|
||||
}, repository)).toThrow('没有可用于规划的地点')
|
||||
})
|
||||
|
||||
it('returns the same route and canonical IDs for equivalent input', () => {
|
||||
const first = createLocalPlan(preferences({ themes: ['研学', '亲子'], interests: ['摄影', '自然风光'] }), repository)
|
||||
const second = createLocalPlan(preferences({ themes: ['亲子', '研学'], interests: ['自然风光', '摄影'] }), repository)
|
||||
@@ -302,6 +342,22 @@ describe('deterministic local POC planner', () => {
|
||||
expect(request).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('exposes the exact origin only from the current in-memory planning session', async () => {
|
||||
const plan = await createPlan(preferences(), {
|
||||
longitude: 113.94,
|
||||
latitude: 22.76,
|
||||
coordinateSystem: 'GCJ02',
|
||||
})
|
||||
|
||||
const first = getSessionPlanningOrigin(plan.conversationId)
|
||||
expect(first).toEqual({ longitude: 113.94, latitude: 22.76, coordinateSystem: 'GCJ02' })
|
||||
if (first)
|
||||
first.longitude = 0
|
||||
expect(getSessionPlanningOrigin(plan.conversationId)?.longitude).toBe(113.94)
|
||||
expect(getSessionPlanningOrigin('unknown-session')).toBeNull()
|
||||
expect(JSON.stringify(loadPlanningRequest())).not.toContain('113.94')
|
||||
})
|
||||
|
||||
it('preserves all custom selections, reports overflow, and retains them during adjustment', () => {
|
||||
const selectedPoiIds = repository.getPublishedPois().slice(0, 8).map(poi => poi.id)
|
||||
const request: PlanningRequest = {
|
||||
@@ -484,6 +540,14 @@ describe('travel storage', () => {
|
||||
expect(loadPlan()).toBeNull()
|
||||
})
|
||||
|
||||
it('does not restore remote plans while AI planning is frozen', () => {
|
||||
const plan = createLocalPlan(preferences(), getPoiRepository())
|
||||
const remotePlan = { ...plan, source: 'remote_ai' as const }
|
||||
values.set(PLAN_STORAGE_KEY, storageEnvelope(remotePlan))
|
||||
|
||||
expect(loadPlan()).toBeNull()
|
||||
})
|
||||
|
||||
it('contains storage read failures and reports write failures', () => {
|
||||
vi.mocked(uni.getStorageSync).mockImplementation(() => {
|
||||
throw new Error('read failed')
|
||||
|
||||
Reference in New Issue
Block a user