import * as React from 'react' import { renderHook, act } from '@testing-library/react' import { PostHogProvider, PostHog } from '../../context' import { useThumbSurvey } from '../useThumbSurvey' import { SurveyEventName, SurveyEventProperties } from 'posthog-js' import { isUndefined } from '../../utils/type-utils' jest.useFakeTimers() describe('useThumbSurvey hook', () => { let posthog: PostHog let captureMock: jest.Mock let displaySurveyMock: jest.Mock let wrapper: React.FC<{ children: React.ReactNode }> beforeEach(() => { captureMock = jest.fn() displaySurveyMock = jest.fn() posthog = { capture: captureMock, get_session_replay_url: () => 'https://app.posthog.com/replay/123', surveys: { displaySurvey: displaySurveyMock }, } as unknown as PostHog wrapper = ({ children }) => {children} }) describe('survey shown tracking', () => { it.each([ [false, true, false], // disableAutoShownTracking, shouldAutoTrack, shouldExposeTrackShown [true, false, true], ])( 'disableAutoShownTracking=%s: auto-tracks=%s, exposes trackShown=%s', (disableAutoShownTracking, shouldAutoTrack, shouldExposeTrackShown) => { const { result } = renderHook( () => useThumbSurvey({ surveyId: 'test-survey', disableAutoShownTracking }), { wrapper } ) expect(captureMock).toHaveBeenCalledTimes(shouldAutoTrack ? 1 : 0) expect(!isUndefined(result.current.trackShown)).toBe(shouldExposeTrackShown) } ) it('should only emit survey shown once when trackShown is called multiple times', () => { const { result } = renderHook( () => useThumbSurvey({ surveyId: 'test-survey', disableAutoShownTracking: true }), { wrapper } ) act(() => { result.current.trackShown?.() result.current.trackShown?.() }) expect(captureMock).toHaveBeenCalledTimes(1) expect(captureMock).toHaveBeenCalledWith(SurveyEventName.SHOWN, { [SurveyEventProperties.SURVEY_ID]: 'test-survey', sessionRecordingUrl: 'https://app.posthog.com/replay/123', }) }) }) describe('respond', () => { it.each([ ['up', 1], ['down', 2], ] as const)('respond("%s") calls displaySurvey with initialResponses: { 0: %d }', (value, expectedResponse) => { const { result } = renderHook(() => useThumbSurvey({ surveyId: 'test-survey' }), { wrapper }) act(() => { result.current.respond(value) }) expect(displaySurveyMock).toHaveBeenCalledWith( 'test-survey', expect.objectContaining({ initialResponses: { 0: expectedResponse } }) ) }) it('should only allow one response', () => { const { result } = renderHook(() => useThumbSurvey({ surveyId: 'test-survey' }), { wrapper }) act(() => { result.current.respond('up') result.current.respond('down') }) expect(displaySurveyMock).toHaveBeenCalledTimes(1) expect(result.current.response).toBe('up') }) it('should call onResponse callback', () => { const onResponse = jest.fn() const { result } = renderHook(() => useThumbSurvey({ surveyId: 'test-survey', onResponse }), { wrapper }) act(() => { result.current.respond('down') }) expect(onResponse).toHaveBeenCalledWith('down') }) }) })