import type { Survey } from "posthog-js"; import { describe, expect, it } from "vitest"; import { buildDismissedProperties, buildSentProperties, seenSurveyStorageKey, surveyInteractionKey, } from "../surveys"; // The capture payloads must match what posthog-js's own widget sends — the // Surveys results UI, the internal targeting flags ($survey_dismissed/) // and cross-device dedup all key off these exact shapes. function mkSurvey(overrides: Record = {}): Survey { return { id: "sv1", name: "Test Survey", type: "api", questions: [ { id: "q1", type: "single_choice", question: "Neden?", choices: ["A", "B"] }, { id: "q2", type: "open", question: "Detay?", optional: true }, ], current_iteration: null, current_iteration_start_date: null, ...overrides, } as unknown as Survey; } describe("surveyInteractionKey", () => { it("builds the plain person-property key for one-off surveys", () => { expect(surveyInteractionKey(mkSurvey(), "dismissed")).toBe("$survey_dismissed/sv1"); }); it("appends the iteration for recurring surveys (matches the internal targeting flag)", () => { const s = mkSurvey({ current_iteration: 1 }); expect(surveyInteractionKey(s, "responded")).toBe("$survey_responded/sv1/1"); }); }); describe("seenSurveyStorageKey", () => { it("matches posthog-js seenSurvey_ localStorage convention", () => { expect(seenSurveyStorageKey(mkSurvey())).toBe("seenSurvey_sv1"); expect(seenSurveyStorageKey(mkSurvey({ current_iteration: 2 }))).toBe("seenSurvey_sv1_2"); }); }); describe("buildSentProperties", () => { it("keys responses by question id and marks the responded person property", () => { const props = buildSentProperties(mkSurvey(), { q1: "A", q2: null }, "sub-1"); expect(props.$survey_id).toBe("sv1"); expect(props.$survey_response_q1).toBe("A"); expect(props.$survey_response_q2).toBeNull(); expect(props.$survey_completed).toBe(true); expect(props.$survey_submission_id).toBe("sub-1"); expect(props.$set).toEqual({ "$survey_responded/sv1": true }); expect(props.$survey_questions).toEqual([ { id: "q1", question: "Neden?", response: "A" }, { id: "q2", question: "Detay?", response: null }, ]); }); }); describe("buildDismissedProperties", () => { it("flags partial completion only when something was answered", () => { const empty = buildDismissedProperties(mkSurvey(), { q1: null }); expect(empty.$survey_partially_completed).toBe(false); expect(empty.$set).toEqual({ "$survey_dismissed/sv1": true }); const partial = buildDismissedProperties(mkSurvey(), { q1: "B", q2: null }); expect(partial.$survey_partially_completed).toBe(true); expect(partial.$survey_response_q1).toBe("B"); }); });