1import { ExpoConfig } from '@expo/config'; 2import { Middleware } from 'metro-config'; 3 4import { createDebuggerTelemetryMiddleware, findDebugTool } from '../metroDebuggerMiddleware'; 5import { logEventAsync } from '../rudderstackClient'; 6 7jest.mock('../getMetroDebugProperties'); 8jest.mock('../rudderstackClient'); 9 10const FLIPPER_UA = `Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Flipper/0.177.0 Chrome/100.0.4896.143 Electron/18.2.0 Safari/537.36`; 11const CHROME_ORIGIN = `https://chrome-devtools-frontend.appspot.com`; 12 13const fakeExpoConfig = { 14 sdkVersion: '47.0.0', 15 jsEngine: 'hermes', 16} as ExpoConfig; 17 18/** Create a fake request object, based on the provided options */ 19const req = (options: { url: string; userAgent?: string; origin?: string }) => 20 ({ 21 url: options.url, 22 headers: { 23 'user-agent': options.userAgent, 24 origin: options.origin, 25 }, 26 } as Parameters<Middleware>[0]); 27 28describe(findDebugTool, () => { 29 it('returns flipper from user agent', () => { 30 expect(findDebugTool(req({ url: '/json', userAgent: FLIPPER_UA }))).toMatchObject({ 31 name: 'flipper', 32 version: '0.177.0', 33 }); 34 }); 35 36 it('returns chrome from origin', () => { 37 expect(findDebugTool(req({ url: '/index.map', origin: CHROME_ORIGIN }))).toMatchObject({ 38 name: 'chrome', 39 }); 40 }); 41}); 42 43describe(createDebuggerTelemetryMiddleware, () => { 44 it('reports known tool from user agent', () => { 45 const middleware = createDebuggerTelemetryMiddleware('/fake-project', fakeExpoConfig); 46 const next = jest.fn(); 47 48 middleware(req({ url: '/json', userAgent: FLIPPER_UA }), {} as any, next); 49 50 expect(logEventAsync).toHaveBeenCalled(); 51 }); 52 53 it('only reports known tool once', () => { 54 const middleware = createDebuggerTelemetryMiddleware('/fake-project', fakeExpoConfig); 55 const next = jest.fn(); 56 57 middleware(req({ url: '/json', userAgent: FLIPPER_UA }), {} as any, next); 58 middleware(req({ url: '/json', userAgent: FLIPPER_UA }), {} as any, next); 59 60 expect(logEventAsync).toHaveBeenCalledTimes(1); 61 expect(next).toHaveBeenCalledTimes(2); 62 }); 63 64 it('does not report with unknown user agent', () => { 65 const middleware = createDebuggerTelemetryMiddleware('/fake-project', fakeExpoConfig); 66 const next = jest.fn(); 67 68 middleware(req({ url: '/json', userAgent: 'unknown/4.2.0' }), {} as any, next); 69 70 expect(logEventAsync).not.toHaveBeenCalled(); 71 }); 72 73 it('does not report when telemetry is turned off', () => { 74 process.env.EXPO_NO_TELEMETRY = 'true'; 75 76 const middleware = createDebuggerTelemetryMiddleware('/fake-project', fakeExpoConfig); 77 const next = jest.fn(); 78 79 middleware(req({ url: '/json', userAgent: FLIPPER_UA }), {} as any, next); 80 81 expect(logEventAsync).not.toHaveBeenCalled(); 82 83 delete process.env.EXPO_NO_TELEMETRY; 84 }); 85 86 it('does not report when app is not using hermes', () => { 87 const expoConfig = { ...fakeExpoConfig, jsEngine: 'jsc' as const }; 88 const middleware = createDebuggerTelemetryMiddleware('/fake-project', expoConfig); 89 const next = jest.fn(); 90 91 middleware(req({ url: '/json', userAgent: FLIPPER_UA }), {} as any, next); 92 93 expect(logEventAsync).not.toHaveBeenCalled(); 94 }); 95}); 96