import * as React from 'react'
import { render, act } from '@testing-library/react'
import { PostHogProvider, PostHog } from '..'
import posthogJs from 'posthog-js'
import { setDefaultPostHogInstance } from '../posthog-default'
// Mock posthog-js
jest.mock('posthog-js', () => ({
__esModule: true,
default: {
init: jest.fn(),
set_config: jest.fn(),
__loaded: false,
},
}))
describe('PostHogProvider component', () => {
beforeEach(() => {
setDefaultPostHogInstance(posthogJs)
})
afterEach(() => {
setDefaultPostHogInstance(undefined)
})
it('should render children components', () => {
const posthog = {} as unknown as PostHog
const { getByText } = render(
Test
)
expect(getByText('Test')).toBeTruthy()
})
describe('when using apiKey initialization', () => {
const apiKey = 'test-api-key'
const initialOptions = { api_host: 'https://app.posthog.com' }
const updatedOptions = { api_host: 'https://eu.posthog.com' }
beforeEach(() => {
jest.clearAllMocks()
})
it('does not initialize when apiKey is missing', () => {
const consoleSpy = jest.spyOn(console, 'warn').mockImplementation()
render(
Test
)
expect(posthogJs.init).not.toHaveBeenCalled()
expect(consoleSpy).toHaveBeenCalledWith(
'[PostHog.js] No `apiKey` or `client` were provided to `PostHogProvider`. Using default global `window.posthog` instance. You must initialize it manually. This is not recommended behavior.'
)
consoleSpy.mockRestore()
})
it('should call set_config when options change', () => {
const { rerender } = render(
Test
)
// First render should initialize
expect(posthogJs.init).toHaveBeenCalledWith(apiKey, initialOptions)
// Rerender with new options
act(() => {
rerender(
Test
)
})
// Should call set_config with new options
expect(posthogJs.set_config).toHaveBeenCalledWith(updatedOptions)
})
it('should NOT call set_config when we pass new options that are the same as the previous options', () => {
const { rerender } = render(
Test
)
// First render should initialize
expect(posthogJs.init).toHaveBeenCalledWith(apiKey, initialOptions)
// Rerender with new options
const sameOptionsButDifferentReference = { ...initialOptions }
act(() => {
rerender(
Test
)
})
// Should NOT call set_config
expect(posthogJs.set_config).not.toHaveBeenCalled()
})
it('should warn when attempting to change apiKey', () => {
const consoleSpy = jest.spyOn(console, 'warn').mockImplementation()
const newApiKey = 'different-api-key'
const { rerender } = render(
Test
)
// First render should initialize
expect(posthogJs.init).toHaveBeenCalledWith(apiKey, initialOptions)
// Rerender with new apiKey
act(() => {
rerender(
Test
)
})
// Should warn about apiKey change
expect(consoleSpy).toHaveBeenCalledWith(
expect.stringContaining('You have provided a different `apiKey` to `PostHogProvider`')
)
consoleSpy.mockRestore()
})
it('warns if posthogJs has been loaded elsewhere', () => {
;(posthogJs as any).__loaded = true
const consoleSpy = jest.spyOn(console, 'warn').mockImplementation()
render(
Test
)
expect(consoleSpy).toHaveBeenCalledWith(
expect.stringContaining('`posthog` was already loaded elsewhere. This may cause issues.')
)
consoleSpy.mockRestore()
;(posthogJs as any).__loaded = false
})
})
})