Skip to content

Commit

Permalink
refactor: add and fix tests
Browse files Browse the repository at this point in the history
  • Loading branch information
fbelginetw committed Oct 21, 2024
1 parent 567b39f commit 2514383
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 5 deletions.
4 changes: 1 addition & 3 deletions opentrons-ai-client/src/analytics/mixpanel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@ export type AnalyticsEvent =
| { superProperties: Record<string, unknown> }

// pulled in from environment at build time
const MIXPANEL_ID = getIsProduction()
? process.env.OT_AI_CLIENT_MIXPANEL_ID
: 'process.env.OT_AI_CLIENT_MIXPANEL_DEV_ID'
const MIXPANEL_ID = process.env.OT_AI_CLIENT_MIXPANEL_ID

const MIXPANEL_OPTS = {
// opt out by default
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Landing } from '../index'
import { i18n } from '../../../i18n'

const mockNavigate = vi.fn()
const mockUseTrackEvent = vi.fn()

vi.mock('react-router-dom', async importOriginal => {
const reactRouterDom = await importOriginal<NavigateFunction>()
Expand All @@ -16,6 +17,10 @@ vi.mock('react-router-dom', async importOriginal => {
}
})

vi.mock('../../../hooks/useTrackEvent', () => ({
useTrackEvent: () => mockUseTrackEvent,
}))

const render = () => {
return renderWithProviders(<Landing />, {
i18nInstance: i18n,
Expand Down
5 changes: 4 additions & 1 deletion opentrons-ai-client/src/pages/Landing/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import welcomeImage from '../../assets/images/welcome_dashboard.png'
import { useTranslation } from 'react-i18next'
import { useIsMobile } from '../../resources/hooks/useIsMobile'
import { useNavigate } from 'react-router-dom'
import { useTrackEvent } from '../../resources/hooks/useTrackEvent'

export interface InputType {
userPrompt: string
Expand All @@ -24,13 +25,15 @@ export function Landing(): JSX.Element | null {
const navigate = useNavigate()
const { t } = useTranslation('protocol_generator')
const isMobile = useIsMobile()
const trackEvent = useTrackEvent()

function handleCreateNewProtocol(): void {
// add analytics in these handlers
trackEvent({ name: 'create-new-protocol', properties: {} })
navigate('/new-protocol')
}

function handleUpdateProtocol(): void {
trackEvent({ name: 'update-protocol', properties: {} })
navigate('/update-protocol')
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { describe, it, vi, expect, afterEach } from 'vitest'
import { trackEvent } from '../../../analytics/mixpanel'
import { useTrackEvent } from '../useTrackEvent'
import { renderHook } from '@testing-library/react'
import { mixpanelAtom } from '../../atoms'
import type { AnalyticsEvent } from '../../../analytics/mixpanel'
import type { Mixpanel } from '../../types'
import { TestProvider } from '../../utils/testUtils'

vi.mock('../../../analytics/mixpanel', () => ({
trackEvent: vi.fn(),
}))

describe('useTrackEvent', () => {
afterEach(() => {
vi.resetAllMocks()
})

it('should call trackEvent with the correct arguments when hasOptedIn is true', () => {
const mockMixpanelAtom: Mixpanel = {
analytics: {
hasOptedIn: true,
},
}

const wrapper = ({ children }: { children: React.ReactNode }) => (
<TestProvider initialValues={[[mixpanelAtom, mockMixpanelAtom]]}>
{children}
</TestProvider>
)

const { result } = renderHook(() => useTrackEvent(), { wrapper })

const event: AnalyticsEvent = { name: 'test_event', properties: {} }
result.current(event)

expect(trackEvent).toHaveBeenCalledWith(event, true)
})

it('should call trackEvent with the correct arguments when hasOptedIn is false', () => {
const mockMixpanelAtomFalse: Mixpanel = {
analytics: {
hasOptedIn: false,
},
}

const wrapper = ({ children }: { children: React.ReactNode }) => (
<TestProvider initialValues={[[mixpanelAtom, mockMixpanelAtomFalse]]}>
{children}
</TestProvider>
)

const { result } = renderHook(() => useTrackEvent(), { wrapper })

const event: AnalyticsEvent = { name: 'test_event', properties: {} }
result.current(event)

expect(trackEvent).toHaveBeenCalledWith(event, false)
})
})
2 changes: 1 addition & 1 deletion opentrons-ai-client/src/resources/hooks/useTrackEvent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ import type { AnalyticsEvent } from '../types'
export function useTrackEvent(): (e: AnalyticsEvent) => void {
const [mixpanel] = useAtom(mixpanelAtom)
return event => {
trackEvent(event, mixpanel?.analytics.hasOptedIn ?? false)
trackEvent(event, mixpanel?.analytics?.hasOptedIn ?? false)
}
}
29 changes: 29 additions & 0 deletions opentrons-ai-client/src/resources/utils/testUtils.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Provider } from 'jotai'
import { useHydrateAtoms } from 'jotai/utils'

interface HydrateAtomsProps {
initialValues: Array<[any, any]>
children: React.ReactNode
}

interface TestProviderProps {
initialValues: Array<[any, any]>
children: React.ReactNode
}

export const HydrateAtoms = ({
initialValues,
children,
}: HydrateAtomsProps): React.ReactNode => {
useHydrateAtoms(initialValues)
return children
}

export const TestProvider = ({
initialValues,
children,
}: TestProviderProps): React.ReactNode => (
<Provider>
<HydrateAtoms initialValues={initialValues}>{children}</HydrateAtoms>
</Provider>
)

0 comments on commit 2514383

Please sign in to comment.