106 lines
3.4 KiB
TypeScript
106 lines
3.4 KiB
TypeScript
|
|
import { afterEach, describe, expect, it, vi } from 'vitest'
|
||
|
|
import { publicTransport } from '../../server/utils/transitous'
|
||
|
|
|
||
|
|
const LILLE = { lat: 50.6292, lon: 3.0573 }
|
||
|
|
const BRUXELLES = { lat: 50.8503, lon: 4.3517 }
|
||
|
|
|
||
|
|
const leg = (mode: string, distance: number, minutes: number) => ({
|
||
|
|
mode,
|
||
|
|
distance,
|
||
|
|
duration: minutes * 60,
|
||
|
|
startTime: '',
|
||
|
|
endTime: '',
|
||
|
|
from: LILLE,
|
||
|
|
to: BRUXELLES,
|
||
|
|
})
|
||
|
|
|
||
|
|
const journey = (legs: ReturnType<typeof leg>[], minutes: number, transfers = 0) => ({
|
||
|
|
duration: minutes * 60,
|
||
|
|
transfers,
|
||
|
|
legs,
|
||
|
|
})
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Le vrai code passe deux requetes distinctes, une par famille de mode.
|
||
|
|
* Le faux doit faire la meme distinction, sinon il renvoie un trajet en car
|
||
|
|
* a la requete ferroviaire et le test valide un comportement impossible.
|
||
|
|
*/
|
||
|
|
function mockApi(byFamily: { rail?: unknown[], urban?: unknown[] }) {
|
||
|
|
const spy = vi.fn().mockImplementation((url: string) => {
|
||
|
|
const rail = url.includes('HIGHSPEED_RAIL')
|
||
|
|
return Promise.resolve({ itineraries: (rail ? byFamily.rail : byFamily.urban) ?? [] })
|
||
|
|
})
|
||
|
|
vi.stubGlobal('$fetch', spy)
|
||
|
|
return spy
|
||
|
|
}
|
||
|
|
|
||
|
|
afterEach(() => vi.unstubAllGlobals())
|
||
|
|
|
||
|
|
describe('publicTransport', () => {
|
||
|
|
it('interroge chaque famille de mode separement', async () => {
|
||
|
|
const spy = mockApi({})
|
||
|
|
await publicTransport(LILLE, BRUXELLES, new Date())
|
||
|
|
|
||
|
|
expect(spy).toHaveBeenCalledTimes(2)
|
||
|
|
const urls = spy.mock.calls.map(c => c[0] as string)
|
||
|
|
expect(urls.some(u => u.includes('HIGHSPEED_RAIL'))).toBe(true)
|
||
|
|
expect(urls.some(u => u.includes('COACH') && !u.includes('HIGHSPEED_RAIL'))).toBe(true)
|
||
|
|
})
|
||
|
|
|
||
|
|
it('separe le meilleur trajet ferroviaire du meilleur trajet urbain', async () => {
|
||
|
|
mockApi({
|
||
|
|
rail: [journey([leg('HIGHSPEED_RAIL', 100000, 90)], 90, 1)],
|
||
|
|
urban: [journey([leg('BUS', 95000, 180)], 180, 3)],
|
||
|
|
})
|
||
|
|
|
||
|
|
const r = await publicTransport(LILLE, BRUXELLES, new Date())
|
||
|
|
|
||
|
|
// 100 km de TGV a 2,4 g contre 95 km de bus a 113 g.
|
||
|
|
expect(r.train?.co2Grams).toBe(240)
|
||
|
|
expect(r.bus?.co2Grams).toBe(10735)
|
||
|
|
expect(r.train?.transfers).toBe(1)
|
||
|
|
})
|
||
|
|
|
||
|
|
it('retient le plus rapide quand plusieurs trajets ferroviaires existent', async () => {
|
||
|
|
mockApi({
|
||
|
|
rail: [
|
||
|
|
journey([leg('REGIONAL_RAIL', 100000, 180)], 180, 2),
|
||
|
|
journey([leg('HIGHSPEED_RAIL', 100000, 90)], 90, 0),
|
||
|
|
],
|
||
|
|
})
|
||
|
|
|
||
|
|
const r = await publicTransport(LILLE, BRUXELLES, new Date())
|
||
|
|
|
||
|
|
expect(r.train?.durationMin).toBe(90)
|
||
|
|
expect(r.train?.transfers).toBe(0)
|
||
|
|
})
|
||
|
|
|
||
|
|
it('renvoie null pour un mode absent plutot que d inventer un trajet', async () => {
|
||
|
|
mockApi({ urban: [journey([leg('COACH', 50000, 60)], 60)] })
|
||
|
|
|
||
|
|
const r = await publicTransport(LILLE, BRUXELLES, new Date())
|
||
|
|
|
||
|
|
expect(r.train).toBeNull()
|
||
|
|
expect(r.bus).not.toBeNull()
|
||
|
|
})
|
||
|
|
|
||
|
|
it('ecarte un itineraire entierement pietonnier', async () => {
|
||
|
|
// MOTIS propose parfois de marcher faute de mieux : ce n'est pas
|
||
|
|
// un trajet en transport en commun et il ne doit pas s'afficher.
|
||
|
|
mockApi({ rail: [journey([leg('WALK', 3000, 40)], 40)] })
|
||
|
|
|
||
|
|
const r = await publicTransport(LILLE, BRUXELLES, new Date())
|
||
|
|
|
||
|
|
expect(r.train).toBeNull()
|
||
|
|
})
|
||
|
|
|
||
|
|
it('s identifie aupres de Transitous comme leur politique d usage l exige', async () => {
|
||
|
|
const spy = mockApi({})
|
||
|
|
|
||
|
|
await publicTransport(LILLE, BRUXELLES, new Date())
|
||
|
|
|
||
|
|
const [url, options] = spy.mock.calls[0]
|
||
|
|
expect(url).toContain('fromPlace=50.6292,3.0573')
|
||
|
|
expect(options.headers['User-Agent']).toContain('lecheminvert.tech')
|
||
|
|
})
|
||
|
|
})
|