import supertest from 'supertest' ; import test from 'unit.js' ; import { VEHICLE_EVENTS , Timestamp , Device , VehicleEvent , Telemetry } from '@mds-core/mds-types' ; import db from '@mds-core/mds-db' ; import cache from '@mds-core/mds-agency-cache' ; import { makeDevices } from '@mds-core/mds-test-data' ; import { ApiServer } from '@mds-core/mds-api-server' ; import { TEST1_PROVIDER_ID } from '@mds-core/mds-providers' ; import Sinon from 'sinon' ; import { agencyMiddleware , api } from '../api' ; import { dbHelperFail } from '../request-handlers' ; const log = console . log . bind ( console ) ; const request = supertest ( ApiServer ( api ) ) ; function now ( ) { return Date . now ( ) ; } const APP_JSON = 'application/json; charset=utf-8' ; const PROVIDER_SCOPES = 'admin:all' ; const DEVICE_UUID = 'ec551174-f324-4251-bfed-28d9f3f473fc' ; const TRIP_UUID = '1f981864-cc17-40cf-aea3-70fd985e2ea7' ; const TEST_TELEMETRY = { provider_id : TEST1_PROVIDER_ID , device_id : DEVICE_UUID , gps : { lat : 37.3382 , lng : - 121.8863 , speed : 0 , hdop : 1 , heading : 180 } , charge : 0.5 , timestamp : now ( ) } ; const AUTH = `basic ${ Buffer . from ( `${ TEST1_PROVIDER_ID }|${ PROVIDER_SCOPES }` ) . toString ( 'base64' ) }` ; before ( done => { const testTimestampNow = now ( ) ; const devices = makeDevices ( 3 , now ( ) - 1000 ) ; const events = [ { provider_id : TEST1_PROVIDER_ID , device_id : devices [ 0 ] . device_id , event_type : VEHICLE_EVENTS . provider_pick_up , recorded : testTimestampNow - 90 , timestamp : testTimestampNow - 90 , telemetry : TEST_TELEMETRY } , { provider_id : TEST1_PROVIDER_ID , device_id : devices [ 0 ] . device_id , event_type : VEHICLE_EVENTS . trip_enter , trip_id : TRIP_UUID , recorded : testTimestampNow - 80 , timestamp : testTimestampNow - 80 , telemetry : TEST_TELEMETRY } , { provider_id : TEST1_PROVIDER_ID , device_id : devices [ 0 ] . device_id , event_type : VEHICLE_EVENTS . trip_leave , trip_id : TRIP_UUID , recorded : testTimestampNow - 70 , timestamp : testTimestampNow - 70 , telemetry : TEST_TELEMETRY } , { provider_id : TEST1_PROVIDER_ID , device_id : devices [ 0 ] . device_id , event_type : VEHICLE_EVENTS . provider_pick_up , recorded : testTimestampNow - 60 , timestamp : testTimestampNow - 60 , telemetry : TEST_TELEMETRY } , { provider_id : TEST1_PROVIDER_ID , device_id : devices [ 0 ] . device_id , event_type : VEHICLE_EVENTS . service_start , recorded : testTimestampNow - 50 , timestamp : testTimestampNow - 50 , telemetry : TEST_TELEMETRY } , { provider_id : TEST1_PROVIDER_ID , device_id : devices [ 0 ] . device_id , event_type : VEHICLE_EVENTS . trip_leave , trip_id : TRIP_UUID , recorded : testTimestampNow - 40 , timestamp : testTimestampNow - 40 , telemetry : TEST_TELEMETRY } , { provider_id : TEST1_PROVIDER_ID , device_id : devices [ 0 ] . device_id , event_type : VEHICLE_EVENTS . trip_start , trip_id : TRIP_UUID , recorded : testTimestampNow - 30 , timestamp : testTimestampNow - 30 , telemetry : TEST_TELEMETRY } , { provider_id : TEST1_PROVIDER_ID , device_id : devices [ 0 ] . device_id , event_type : VEHICLE_EVENTS . provider_pick_up , recorded : testTimestampNow - 20 , timestamp : testTimestampNow - 20 , telemetry : TEST_TELEMETRY } ] ; const telemetry = [ ] ; const seedData = { devices , events , telemetry } ; Promise . all ( [ db . initialize ( ) , cache . initialize ( ) ] ) . then ( ( ) => { Promise . all ( [ cache . seed ( seedData ) , db . seed ( seedData ) ] ) . then ( ( ) => { done ( ) ; } ) ; } ) ; } ) ; after ( async ( ) => { await Promise . all ( [ db . shutdown ( ) , cache . shutdown ( ) ] ) ; } ) ; describe ( 'Tests API' , ( ) => { it ( 'gets vehicle counts per provider' , done => { request . get ( '/admin/vehicle_counts' ) . set ( 'Authorization' , AUTH ) . expect ( 200 ) . end ( ( err , result ) => { test . value ( result ) . hasHeader ( 'content-type' , APP_JSON ) ; done ( err ) ; } ) ; } ) ; describe ( 'Agency-specific middleware' , ( ) => { it ( 'calls next()' , async ( ) => { const nextSpy = Sinon . spy ( ) ; await agencyMiddleware ( { path : '/health' } as any , { } as any , nextSpy ) ; test . assert ( nextSpy . calledOnce ) ; } ) ; it ( 'rejects an unauthorized user' , async ( ) => { const statusSpy = Sinon . spy ( statusCode => { return { send : ( ) => { return statusCode ; } } ; } ) ; await agencyMiddleware ( { path : '/foobar' } as any , { locals : { } , status : statusSpy } as any , ( ) => { return null ; } ) ; test . assert ( statusSpy . calledOnceWithExactly ( 401 ) ) ; } ) ; } ) ; it ( 'verifies 8 total events, and 4 are non-conformant' , done => { request . get ( '/admin/last_day_stats_by_provider' ) . set ( 'Authorization' , AUTH ) . expect ( 200 ) . end ( ( err , result ) => { log ( '----' , JSON . stringify ( result . body ) ) ; test . assert ( result . body [ TEST1_PROVIDER_ID ] . events_not_in_conformance === 4 ) ; test . assert ( result . body [ TEST1_PROVIDER_ID ] . events_last_24h === 8 ) ; done ( err ) ; } ) ; } ) ; it ( 'gets recent stats by provider' , done => { request . get ( '/admin/last_day_stats_by_provider' ) . set ( 'Authorization' , AUTH ) . expect ( 200 ) . end ( ( err , result ) => { test . value ( result ) . hasHeader ( 'content-type' , APP_JSON ) ; const testObject = test . object ( result . body ) ; testObject . hasProperty ( TEST1_PROVIDER_ID ) ; const providerTestObject1 = test . object ( result . body [ TEST1_PROVIDER_ID ] ) ; providerTestObject1 . hasProperty ( 'ms_since_last_event' ) ; providerTestObject1 . hasProperty ( 'registered_last_24h' ) ; providerTestObject1 . hasProperty ( 'events_last_24h' ) ; done ( err ) ; } ) ; } ) ; it ( 'handles a db helper failure' , async ( ) => { await dbHelperFail ( new Error ( 'fake-error' ) ) ; await dbHelperFail ( 'fake-error-string' ) ; } ) ; } ) ;