From 304534a137afa07f2bc76863ea897a5d165b1695 Mon Sep 17 00:00:00 2001 From: Li Yi Yu Date: Tue, 11 Jul 2023 14:29:07 -0400 Subject: [PATCH 1/3] add api surveys return --- src/posthog-surveys.ts | 66 ++++++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 28 deletions(-) diff --git a/src/posthog-surveys.ts b/src/posthog-surveys.ts index 7d98b5875..70182070a 100644 --- a/src/posthog-surveys.ts +++ b/src/posthog-surveys.ts @@ -17,6 +17,7 @@ export enum SurveyType { Button = 'Button', Email = 'Email', FullScreen = 'Fullscreen', + API = 'API', } export interface SurveyQuestion { @@ -81,37 +82,46 @@ export class PostHogSurveys { } } + getAllSurveyMatches(surveys: Survey[]) { + const activeSurveys = surveys.filter((survey) => { + return !!(survey.start_date && !survey.end_date) + }) + const conditionMatchedSurveys = activeSurveys.filter((survey) => { + if (!survey.conditions) { + return true + } + const urlCheck = survey.conditions?.url ? window.location.href.indexOf(survey.conditions.url) > -1 : true + const selectorCheck = survey.conditions?.selector + ? document.querySelector(survey.conditions.selector) + : true + return urlCheck && selectorCheck + }) + const targetingMatchedSurveys = conditionMatchedSurveys.filter((survey) => { + if (!survey.linked_flag_key && !survey.targeting_flag_key) { + return true + } + const linkedFlagCheck = survey.linked_flag_key + ? this.instance.featureFlags.isFeatureEnabled(survey.linked_flag_key) + : true + const targetingFlagCheck = survey.targeting_flag_key + ? this.instance.featureFlags.isFeatureEnabled(survey.targeting_flag_key) + : true + return linkedFlagCheck && targetingFlagCheck + }) + return targetingMatchedSurveys + } + getActiveMatchingSurveys(callback: SurveyCallback, forceReload = false) { this.getSurveys((surveys) => { - const activeSurveys = surveys.filter((survey) => { - return !!(survey.start_date && !survey.end_date) - }) - const conditionMatchedSurveys = activeSurveys.filter((survey) => { - if (!survey.conditions) { - return true - } - const urlCheck = survey.conditions?.url - ? window.location.href.indexOf(survey.conditions.url) > -1 - : true - const selectorCheck = survey.conditions?.selector - ? document.querySelector(survey.conditions.selector) - : true - return urlCheck && selectorCheck - }) - const targetingMatchedSurveys = conditionMatchedSurveys.filter((survey) => { - if (!survey.linked_flag_key && !survey.targeting_flag_key) { - return true - } - const linkedFlagCheck = survey.linked_flag_key - ? this.instance.featureFlags.isFeatureEnabled(survey.linked_flag_key) - : true - const targetingFlagCheck = survey.targeting_flag_key - ? this.instance.featureFlags.isFeatureEnabled(survey.targeting_flag_key) - : true - return linkedFlagCheck && targetingFlagCheck - }) + const nonAPISurveys = this.getAllSurveyMatches(surveys).filter((survey) => survey.type !== SurveyType.API) + return callback(nonAPISurveys) + }, forceReload) + } - return callback(targetingMatchedSurveys) + getActiveMatchingAPISurveys(callback: SurveyCallback, forceReload = false) { + this.getSurveys((surveys) => { + const APISurveys = this.getAllSurveyMatches(surveys).filter((survey) => survey.type === SurveyType.API) + return callback(APISurveys) }, forceReload) } } From 023f8be8bf91ccd326d90ecf2f34798961d351b7 Mon Sep 17 00:00:00 2001 From: Li Yi Yu Date: Tue, 11 Jul 2023 14:40:13 -0400 Subject: [PATCH 2/3] update tests and core methods --- src/__tests__/surveys.js | 189 ++++++++++++++++++++++----------------- src/posthog-core.ts | 16 +++- 2 files changed, 120 insertions(+), 85 deletions(-) diff --git a/src/__tests__/surveys.js b/src/__tests__/surveys.js index 47da6e74e..5f7e162c7 100644 --- a/src/__tests__/surveys.js +++ b/src/__tests__/surveys.js @@ -55,6 +55,96 @@ describe('surveys', () => { }, ] + const draftSurvey = { + name: 'draft survey', + description: 'draft survey description', + type: SurveyType.Popover, + questions: [{ type: SurveyQuestionType.Open, question: 'what is a draft survey?' }], + start_date: null, + } + const activeSurvey = { + name: 'active survey', + description: 'active survey description', + type: SurveyType.Popover, + questions: [{ type: SurveyQuestionType.Open, question: 'what is a active survey?' }], + start_date: new Date().toISOString(), + end_date: null, + } + const completedSurvey = { + name: 'completed survey', + description: 'completed survey description', + type: SurveyType.Popover, + questions: [{ type: SurveyQuestionType.Open, question: 'what is a completed survey?' }], + start_date: new Date('09/10/2022').toISOString(), + end_date: new Date('10/10/2022').toISOString(), + } + const surveyWithUrl = { + name: 'survey with url', + description: 'survey with url description', + type: SurveyType.Popover, + questions: [{ type: SurveyQuestionType.Open, question: 'what is a survey with url?' }], + conditions: { url: 'posthog.com' }, + start_date: new Date().toISOString(), + end_date: null, + } + const surveyWithSelector = { + name: 'survey with selector', + description: 'survey with selector description', + type: SurveyType.Popover, + questions: [{ type: SurveyQuestionType.Open, question: 'what is a survey with selector?' }], + conditions: { selector: '.test-selector' }, + start_date: new Date().toISOString(), + end_date: null, + } + const surveyWithUrlAndSelector = { + name: 'survey with url and selector', + description: 'survey with url and selector description', + type: SurveyType.Popover, + questions: [{ type: SurveyQuestionType.Open, question: 'what is a survey with url and selector?' }], + conditions: { url: 'posthogapp.com', selector: '#foo' }, + start_date: new Date().toISOString(), + end_date: null, + } + const surveyWithFlags = { + name: 'survey with flags', + description: 'survey with flags description', + type: SurveyType.Popover, + questions: [{ type: SurveyQuestionType.Open, question: 'what is a survey with flags?' }], + linked_flag_key: 'linked-flag-key', + targeting_flag_key: 'survey-targeting-flag-key', + start_date: new Date().toISOString(), + end_date: null, + } + const surveyWithUnmatchedFlags = { + name: 'survey with flags2', + description: 'survey with flags description', + type: SurveyType.Popover, + questions: [{ type: SurveyQuestionType.Open, question: 'what is a survey with flags?' }], + linked_flag_key: 'linked-flag-key2', + targeting_flag_key: 'survey-targeting-flag-key2', + start_date: new Date().toISOString(), + end_date: null, + } + const surveyWithEverything = { + name: 'survey with everything', + description: 'survey with everything description', + type: SurveyType.Popover, + questions: [{ type: SurveyQuestionType.Open, question: 'what is a survey with everything?' }], + start_date: new Date().toISOString(), + end_date: null, + conditions: { url: 'posthogapp.com', selector: '.test-selector' }, + linked_flag_key: 'linked-flag-key', + targeting_flag_key: 'survey-targeting-flag-key', + } + const APISurvey = { + name: 'custom api survey', + description: '', + type: SurveyType.API, + questions: [], + start_date: new Date().toISOString(), + end_date: null, + } + given('surveysResponse', () => ({ surveys: firstSurveys })) it('getSurveys gets a list of surveys if not present already', () => { @@ -101,88 +191,6 @@ describe('surveys', () => { }) describe('getActiveMatchingSurveys', () => { - const draftSurvey = { - name: 'draft survey', - description: 'draft survey description', - type: SurveyType.Popover, - questions: [{ type: SurveyQuestionType.Open, question: 'what is a draft survey?' }], - start_date: null, - } - const activeSurvey = { - name: 'active survey', - description: 'active survey description', - type: SurveyType.Popover, - questions: [{ type: SurveyQuestionType.Open, question: 'what is a active survey?' }], - start_date: new Date().toISOString(), - end_date: null, - } - const completedSurvey = { - name: 'completed survey', - description: 'completed survey description', - type: SurveyType.Popover, - questions: [{ type: SurveyQuestionType.Open, question: 'what is a completed survey?' }], - start_date: new Date('09/10/2022').toISOString(), - end_date: new Date('10/10/2022').toISOString(), - } - const surveyWithUrl = { - name: 'survey with url', - description: 'survey with url description', - type: SurveyType.Popover, - questions: [{ type: SurveyQuestionType.Open, question: 'what is a survey with url?' }], - conditions: { url: 'posthog.com' }, - start_date: new Date().toISOString(), - end_date: null, - } - const surveyWithSelector = { - name: 'survey with selector', - description: 'survey with selector description', - type: SurveyType.Popover, - questions: [{ type: SurveyQuestionType.Open, question: 'what is a survey with selector?' }], - conditions: { selector: '.test-selector' }, - start_date: new Date().toISOString(), - end_date: null, - } - const surveyWithUrlAndSelector = { - name: 'survey with url and selector', - description: 'survey with url and selector description', - type: SurveyType.Popover, - questions: [{ type: SurveyQuestionType.Open, question: 'what is a survey with url and selector?' }], - conditions: { url: 'posthogapp.com', selector: '#foo' }, - start_date: new Date().toISOString(), - end_date: null, - } - const surveyWithFlags = { - name: 'survey with flags', - description: 'survey with flags description', - type: SurveyType.Popover, - questions: [{ type: SurveyQuestionType.Open, question: 'what is a survey with flags?' }], - linked_flag_key: 'linked-flag-key', - targeting_flag_key: 'survey-targeting-flag-key', - start_date: new Date().toISOString(), - end_date: null, - } - const surveyWithUnmatchedFlags = { - name: 'survey with flags2', - description: 'survey with flags description', - type: SurveyType.Popover, - questions: [{ type: SurveyQuestionType.Open, question: 'what is a survey with flags?' }], - linked_flag_key: 'linked-flag-key2', - targeting_flag_key: 'survey-targeting-flag-key2', - start_date: new Date().toISOString(), - end_date: null, - } - const surveyWithEverything = { - name: 'survey with everything', - description: 'survey with everything description', - type: SurveyType.Popover, - questions: [{ type: SurveyQuestionType.Open, question: 'what is a survey with everything?' }], - start_date: new Date().toISOString(), - end_date: null, - conditions: { url: 'posthogapp.com', selector: '.test-selector' }, - linked_flag_key: 'linked-flag-key', - targeting_flag_key: 'survey-targeting-flag-key', - } - it('returns surveys that are active', () => { given('surveysResponse', () => ({ surveys: [draftSurvey, activeSurvey, completedSurvey] })) @@ -252,5 +260,22 @@ describe('surveys', () => { expect(data).toEqual([activeSurvey, surveyWithSelector, surveyWithEverything]) }) }) + + it('does not return API surveys', () => { + given('surveysResponse', () => ({ surveys: [activeSurvey, APISurvey] })) + given.surveys.getActiveMatchingSurveys((data) => { + expect(data).toEqual([activeSurvey]) + }) + }) + }) + + describe('getActiveMatchingAPISurveys', () => { + it('returns surveys that are API type only', () => { + given('surveysResponse', () => ({ surveys: [draftSurvey, activeSurvey, completedSurvey, APISurvey] })) + + given.surveys.getActiveMatchingAPISurveys((data) => { + expect(data).toEqual([APISurvey]) + }) + }) }) }) diff --git a/src/posthog-core.ts b/src/posthog-core.ts index 1b7b511ff..01519c126 100644 --- a/src/posthog-core.ts +++ b/src/posthog-core.ts @@ -57,7 +57,7 @@ import { SentryIntegration } from './extensions/sentry-integration' import { createSegmentIntegration } from './extensions/segment-integration' import { PageViewIdManager } from './page-view-id' import { ExceptionObserver } from './extensions/exceptions/exception-autocapture' -import { PostHogSurveys, SurveyCallback } from './posthog-surveys' +import { PostHogSurveys, Survey, SurveyCallback } from './posthog-surveys' /* SIMPLE STYLE GUIDE: @@ -1179,16 +1179,26 @@ export class PostHog { return this.sessionManager.onSessionId(callback) } - /** Get list of all surveys. */ + /** Get list of all existing surveys. */ getSurveys(callback: SurveyCallback, forceReload = false): void { this.surveys.getSurveys(callback, forceReload) } - /** Get surveys that should be enabled for the current user. */ + /** Get list of all active matching surveys. */ + getAllSurveyMatches(surveys: Survey[]): Survey[] { + return this.surveys.getAllSurveyMatches(surveys) + } + + /** Get non API surveys that should be enabled for the current user. */ getActiveMatchingSurveys(callback: SurveyCallback, forceReload = false): void { this.surveys.getActiveMatchingSurveys(callback, forceReload) } + /** Get API surveys that should be enabled for the current user. */ + getActiveMatchingAPISurveys(callback: SurveyCallback, forceReload = false): void { + this.surveys.getActiveMatchingAPISurveys(callback, forceReload) + } + /** * Identify a user with a unique ID instead of a PostHog * randomly generated distinct_id. If the method is never called, From 4cf5a150f910dfbb355cc3823475d26a455c73e1 Mon Sep 17 00:00:00 2001 From: Li Yi Yu Date: Tue, 11 Jul 2023 14:43:06 -0400 Subject: [PATCH 3/3] update types to match --- src/posthog-surveys.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/posthog-surveys.ts b/src/posthog-surveys.ts index 70182070a..728fa0788 100644 --- a/src/posthog-surveys.ts +++ b/src/posthog-surveys.ts @@ -7,9 +7,11 @@ import { SURVEYS } from './posthog-persistence' * See https://github.com/PostHog/posthog-js/issues/698 */ export interface SurveyAppearance { - background_color?: string - button_color?: string - text_color?: string + backgroundColor?: string + submitButtonColor?: string + textColor?: string + submitButtonText?: string + descriptionTextColor?: string } export enum SurveyType { @@ -23,6 +25,7 @@ export enum SurveyType { export interface SurveyQuestion { type: SurveyQuestionType question: string + description?: string | null required?: boolean link?: boolean choices?: string[]