Skip to content

Commit 4d23a69

Browse files
fix: dont require double click to show feedback surveys (#1767)
1 parent bc20ab6 commit 4d23a69

File tree

3 files changed

+108
-6
lines changed

3 files changed

+108
-6
lines changed

src/__tests__/extensions/surveys.test.ts

+78-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
/* eslint-disable compat/compat */
22
import { act, fireEvent, render, renderHook } from '@testing-library/preact'
33
import {
4+
SurveyManager,
5+
SurveyPopup,
46
generateSurveys,
57
renderFeedbackWidgetPreview,
68
renderSurveysPreview,
7-
SurveyManager,
89
useHideSurveyOnURLChange,
910
usePopupVisibility,
1011
} from '../../extensions/surveys'
@@ -613,6 +614,7 @@ describe('usePopupVisibility URL changes should hide surveys accordingly', () =>
613614
feature_flag_keys: null,
614615
linked_flag_key: null,
615616
targeting_flag_key: null,
617+
internal_targeting_flag_key: null,
616618
appearance: {},
617619
}) as Survey
618620

@@ -1071,6 +1073,81 @@ describe('useHideSurveyOnURLChange', () => {
10711073
})
10721074
})
10731075

1076+
describe('onPopupSurveyDismissed callback', () => {
1077+
let posthog: PostHog
1078+
1079+
beforeEach(() => {
1080+
document.getElementsByTagName('html')[0].innerHTML = ''
1081+
localStorage.clear()
1082+
jest.clearAllMocks()
1083+
1084+
// Mock PostHog instance
1085+
posthog = {
1086+
capture: jest.fn(),
1087+
get_session_replay_url: jest.fn(),
1088+
} as unknown as PostHog
1089+
})
1090+
1091+
test('onPopupSurveyDismissed is called when Cancel button is clicked in SurveyPopup', () => {
1092+
// Create a simple survey for testing
1093+
const survey = {
1094+
id: 'test-survey',
1095+
name: 'Test Survey',
1096+
description: 'Test Survey Description',
1097+
type: SurveyType.Popover,
1098+
questions: [
1099+
{
1100+
type: SurveyQuestionType.Open,
1101+
question: 'What do you think?',
1102+
description: '',
1103+
originalQuestionIndex: 0,
1104+
},
1105+
],
1106+
start_date: new Date().toISOString(),
1107+
end_date: null,
1108+
feature_flag_keys: null,
1109+
linked_flag_key: null,
1110+
targeting_flag_key: null,
1111+
internal_targeting_flag_key: null,
1112+
appearance: {},
1113+
conditions: {
1114+
events: { values: [] },
1115+
actions: { values: [] },
1116+
},
1117+
current_iteration: 1,
1118+
current_iteration_start_date: new Date().toISOString(),
1119+
} as Survey
1120+
1121+
const onPopupSurveyDismissed = jest.fn()
1122+
const mockRemoveSurveyFromFocus = jest.fn()
1123+
1124+
// Render the SurveyPopup component with our mocked callback
1125+
render(
1126+
h(SurveyPopup, {
1127+
survey: survey,
1128+
removeSurveyFromFocus: mockRemoveSurveyFromFocus,
1129+
isPopup: true,
1130+
onPopupSurveyDismissed: onPopupSurveyDismissed,
1131+
posthog: posthog,
1132+
})
1133+
)
1134+
1135+
// Find the Cancel button
1136+
const cancelButton = document.querySelector('.cancel-btn-wrapper')
1137+
1138+
// Verify the button exists
1139+
expect(cancelButton).not.toBeNull()
1140+
1141+
// Click the Cancel button
1142+
if (cancelButton) {
1143+
fireEvent.click(cancelButton)
1144+
1145+
// Verify our callback was called
1146+
expect(onPopupSurveyDismissed).toHaveBeenCalledTimes(1)
1147+
}
1148+
})
1149+
})
1150+
10741151
describe('preview renders', () => {
10751152
beforeEach(() => {
10761153
// we have to manually reset the DOM before each test

src/extensions/surveys.tsx

+26-3
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,8 @@ interface SurveyPopupProps {
655655
removeSurveyFromFocus: (id: string) => void
656656
isPopup?: boolean
657657
onPreviewSubmit?: (res: string | string[] | number | null) => void
658+
onPopupSurveyDismissed?: () => void
659+
onPopupSurveySent?: () => void
658660
}
659661

660662
export function SurveyPopup({
@@ -666,6 +668,8 @@ export function SurveyPopup({
666668
removeSurveyFromFocus,
667669
isPopup,
668670
onPreviewSubmit = () => {},
671+
onPopupSurveyDismissed = () => {},
672+
onPopupSurveySent = () => {},
669673
}: SurveyPopupProps) {
670674
const isPreviewMode = Number.isInteger(previewPageIndex)
671675
// NB: The client-side code passes the millisecondDelay in seconds, but setTimeout expects milliseconds, so we multiply by 1000
@@ -694,9 +698,15 @@ export function SurveyPopup({
694698
value={{
695699
isPreviewMode,
696700
previewPageIndex: previewPageIndex,
697-
handleCloseSurveyPopup: () => dismissedSurveyEvent(survey, posthog, isPreviewMode),
701+
onPopupSurveyDismissed: () => {
702+
dismissedSurveyEvent(survey, posthog, isPreviewMode)
703+
onPopupSurveyDismissed()
704+
},
698705
isPopup: isPopup || false,
699706
onPreviewSubmit,
707+
onPopupSurveySent: () => {
708+
onPopupSurveySent()
709+
},
700710
}}
701711
>
702712
{!shouldShowConfirmation ? (
@@ -736,7 +746,7 @@ export function Questions({
736746
survey.appearance?.backgroundColor || defaultSurveyAppearance.backgroundColor
737747
)
738748
const [questionsResponses, setQuestionsResponses] = useState({})
739-
const { isPreviewMode, previewPageIndex, handleCloseSurveyPopup, isPopup, onPreviewSubmit } =
749+
const { isPreviewMode, previewPageIndex, onPopupSurveyDismissed, isPopup, onPreviewSubmit, onPopupSurveySent } =
740750
useContext(SurveyContext)
741751
const [currentQuestionIndex, setCurrentQuestionIndex] = useState(previewPageIndex || 0)
742752
const surveyQuestions = useMemo(() => getDisplayOrderQuestions(survey), [survey])
@@ -768,6 +778,7 @@ export function Questions({
768778
const nextStep = getNextSurveyStep(survey, displayQuestionIndex, res)
769779
if (nextStep === SurveyQuestionBranchingType.End) {
770780
sendSurveyEvent({ ...questionsResponses, [responseKey]: res }, survey, posthog)
781+
onPopupSurveySent()
771782
} else {
772783
setCurrentQuestionIndex(nextStep)
773784
}
@@ -806,7 +817,13 @@ export function Questions({
806817
: {}
807818
}
808819
>
809-
{isPopup && <Cancel onClick={() => handleCloseSurveyPopup()} />}
820+
{isPopup && (
821+
<Cancel
822+
onClick={() => {
823+
onPopupSurveyDismissed()
824+
}}
825+
/>
826+
)}
810827
{getQuestionComponent({
811828
question,
812829
forceDisableHtml,
@@ -889,6 +906,10 @@ export function FeedbackWidget({
889906
return null
890907
}
891908

909+
const resetShowSurvey = () => {
910+
setShowSurvey(false)
911+
}
912+
892913
return (
893914
<Preact.Fragment>
894915
{survey.appearance?.widgetType === 'tab' && (
@@ -911,6 +932,8 @@ export function FeedbackWidget({
911932
style={styleOverrides}
912933
removeSurveyFromFocus={removeSurveyFromFocus}
913934
isPopup={true}
935+
onPopupSurveyDismissed={resetShowSurvey}
936+
onPopupSurveySent={resetShowSurvey}
914937
/>
915938
)}
916939
</Preact.Fragment>

src/extensions/surveys/surveys-utils.tsx

+4-2
Original file line numberDiff line numberDiff line change
@@ -733,17 +733,19 @@ export const hasWaitPeriodPassed = (
733733
interface SurveyContextProps {
734734
isPreviewMode: boolean
735735
previewPageIndex: number | undefined
736-
handleCloseSurveyPopup: () => void
736+
onPopupSurveyDismissed: () => void
737737
isPopup: boolean
738738
onPreviewSubmit: (res: string | string[] | number | null) => void
739+
onPopupSurveySent: () => void
739740
}
740741

741742
export const SurveyContext = createContext<SurveyContextProps>({
742743
isPreviewMode: false,
743744
previewPageIndex: 0,
744-
handleCloseSurveyPopup: () => {},
745+
onPopupSurveyDismissed: () => {},
745746
isPopup: true,
746747
onPreviewSubmit: () => {},
748+
onPopupSurveySent: () => {},
747749
})
748750

749751
interface RenderProps {

0 commit comments

Comments
 (0)