Skip to content

Commit

Permalink
feat: allow not operators in survey url targeting (#1219)
Browse files Browse the repository at this point in the history
Co-authored-by: shawnlikescode <shawn@revlogical.com>
  • Loading branch information
shawnlikescode and shawnlikescode committed Jun 14, 2024
1 parent 55fb97d commit b0e1140
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 1 deletion.
59 changes: 59 additions & 0 deletions src/__tests__/surveys.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,17 @@ describe('surveys', () => {
start_date: new Date().toISOString(),
end_date: null,
} as unknown as Survey
const surveyWithUrlDoesNotContainRegex: Survey = {
name: 'survey with url does not contain regex',
description: 'survey with url does not contain regex description',
type: SurveyType.Popover,
questions: [
{ type: SurveyQuestionType.Open, question: 'what is a survey with url does not contain regex?' },
],
conditions: { url: 'regex-url', urlMatchType: 'not_regex' },
start_date: new Date().toISOString(),
end_date: null,
} as unknown as Survey
const surveyWithParamRegexUrl: Survey = {
name: 'survey with param regex url',
description: 'survey with param regex url description',
Expand Down Expand Up @@ -317,6 +328,24 @@ describe('surveys', () => {
start_date: new Date().toISOString(),
end_date: null,
} as unknown as Survey
const surveyWithIsNotUrlMatch: Survey = {
name: 'survey with is not url match',
description: 'survey with is not url match description',
type: SurveyType.Popover,
questions: [{ type: SurveyQuestionType.Open, question: 'what is a survey with is not url match?' }],
conditions: { url: 'https://example.com/exact', urlMatchType: 'is_not' },
start_date: new Date().toISOString(),
end_date: null,
} as unknown as Survey
const surveyWithUrlDoesNotContain: Survey = {
name: 'survey with url does not contain',
description: 'survey with url does not contain description',
type: SurveyType.Popover,
questions: [{ type: SurveyQuestionType.Open, question: 'what is a survey with url does not contain?' }],
conditions: { url: 'posthog.com', urlMatchType: 'not_icontains' },
start_date: new Date().toISOString(),
end_date: null,
} as unknown as Survey
const surveyWithSelector: Survey = {
name: 'survey with selector',
description: 'survey with selector description',
Expand Down Expand Up @@ -498,6 +527,36 @@ describe('surveys', () => {
assignableWindow.location = originalWindowLocation
})

it('returns surveys based on exclusion conditions', () => {
surveysResponse = {
surveys: [surveyWithUrlDoesNotContain, surveyWithIsNotUrlMatch, surveyWithUrlDoesNotContainRegex],
}

// eslint-disable-next-line compat/compat
assignableWindow.location = new URL('https://posthog.com') as unknown as Location
surveys.getActiveMatchingSurveys((data) => {
// returns surveyWithIsNotUrlMatch and surveyWithUrlDoesNotContainRegex because they don't contain posthog.com
expect(data).toEqual([surveyWithIsNotUrlMatch, surveyWithUrlDoesNotContainRegex])
})
assignableWindow.location = originalWindowLocation

// eslint-disable-next-line compat/compat
assignableWindow.location = new URL('https://example.com/exact') as unknown as Location
surveys.getActiveMatchingSurveys((data) => {
// returns surveyWithUrlDoesNotContain and surveyWithUrlDoesNotContainRegex because they are not exact matches
expect(data).toEqual([surveyWithUrlDoesNotContain, surveyWithUrlDoesNotContainRegex])
})
assignableWindow.location = originalWindowLocation

// eslint-disable-next-line compat/compat
assignableWindow.location = new URL('https://regex-url.com/test') as unknown as Location
surveys.getActiveMatchingSurveys((data) => {
// returns surveyWithUrlDoesNotContain and surveyWithIsNotUrlMatch because they are not regex matches
expect(data).toEqual([surveyWithUrlDoesNotContain, surveyWithIsNotUrlMatch])
})
assignableWindow.location = originalWindowLocation
})

it('returns surveys that match linked and targeting feature flags', () => {
surveysResponse = { surveys: [activeSurvey, surveyWithFlags, surveyWithEverything] }
surveys.getActiveMatchingSurveys((data) => {
Expand Down
2 changes: 1 addition & 1 deletion src/posthog-surveys-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ export interface SurveyResponse {

export type SurveyCallback = (surveys: Survey[]) => void

export type SurveyUrlMatchType = 'regex' | 'exact' | 'icontains'
export type SurveyUrlMatchType = 'regex' | 'not_regex' | 'exact' | 'is_not' | 'icontains' | 'not_icontains'

export interface Survey {
// Sync this with the backend's SurveyAPISerializer!
Expand Down
4 changes: 4 additions & 0 deletions src/posthog-surveys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,12 @@ import { isUndefined } from './utils/type-utils'
export const surveyUrlValidationMap: Record<SurveyUrlMatchType, (conditionsUrl: string) => boolean> = {
icontains: (conditionsUrl) =>
!!window && window.location.href.toLowerCase().indexOf(conditionsUrl.toLowerCase()) > -1,
not_icontains: (conditionsUrl) =>
!!window && window.location.href.toLowerCase().indexOf(conditionsUrl.toLowerCase()) === -1,
regex: (conditionsUrl) => !!window && isUrlMatchingRegex(window.location.href, conditionsUrl),
not_regex: (conditionsUrl) => !!window && !isUrlMatchingRegex(window.location.href, conditionsUrl),
exact: (conditionsUrl) => window?.location.href === conditionsUrl,
is_not: (conditionsUrl) => window?.location.href !== conditionsUrl,
}

export class PostHogSurveys {
Expand Down

0 comments on commit b0e1140

Please sign in to comment.