Skip to content

Commit

Permalink
Fixed up tests to cover all cases (#770)
Browse files Browse the repository at this point in the history
  • Loading branch information
benjackwhite authored Aug 10, 2023
1 parent 6e71688 commit fd04266
Show file tree
Hide file tree
Showing 16 changed files with 213 additions and 164 deletions.
2 changes: 1 addition & 1 deletion src/__tests__/autocapture.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import sinon from 'sinon'

import { autocapture } from '../autocapture'
import { shouldCaptureDomEvent } from '../autocapture-utils'
import { AUTOCAPTURE_DISABLED_SERVER_SIDE } from '../posthog-persistence'
import { AUTOCAPTURE_DISABLED_SERVER_SIDE } from '../constants'

const triggerMouseEvent = function (node, eventType) {
node.dispatchEvent(
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/compression.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import sinon from 'sinon'
import { autocapture } from '../autocapture'
import { decideCompression, compressData } from '../compression'
import { Decide } from '../decide'
import { AUTOCAPTURE_DISABLED_SERVER_SIDE } from '../posthog-persistence'
import { AUTOCAPTURE_DISABLED_SERVER_SIDE } from '../constants'

describe('decideCompression()', () => {
given('subject', () => decideCompression(given.compressionSupport))
Expand Down
7 changes: 2 additions & 5 deletions src/__tests__/extensions/sessionrecording.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,8 @@ import {
RECORDING_MAX_EVENT_SIZE,
SessionRecording,
} from '../../extensions/sessionrecording'
import {
PostHogPersistence,
SESSION_RECORDING_ENABLED_SERVER_SIDE,
SESSION_RECORDING_RECORDER_VERSION_SERVER_SIDE,
} from '../../posthog-persistence'
import { PostHogPersistence } from '../../posthog-persistence'
import { SESSION_RECORDING_ENABLED_SERVER_SIDE, SESSION_RECORDING_RECORDER_VERSION_SERVER_SIDE } from '../../constants'
import { SessionIdManager } from '../../sessionid'
import {
INCREMENTAL_SNAPSHOT_EVENT_TYPE,
Expand Down
20 changes: 11 additions & 9 deletions src/__tests__/gdpr-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,17 @@ const TOKENS = [
const DEFAULT_PERSISTENCE_PREFIX = `__ph_opt_in_out_`
const CUSTOM_PERSISTENCE_PREFIX = `𝓶𝓶𝓶𝓬𝓸𝓸𝓴𝓲𝓮𝓼`

function deleteAllCookies() {
var cookies = document.cookie.split(';')

for (var i = 0; i < cookies.length; i++) {
var cookie = cookies[i]
var eqPos = cookie.indexOf('=')
var name = eqPos > -1 ? cookie.substr(0, eqPos) : cookie
document.cookie = name + '=;expires=Thu, 01 Jan 1970 00:00:00 GMT'
}
}

function forPersistenceTypes(runTests) {
;[`cookie`, `localStorage`, `localStorage+cookie`].forEach(function (persistenceType) {
describe(persistenceType, runTests.bind(null, persistenceType))
Expand All @@ -31,16 +42,7 @@ function assertPersistenceValue(persistenceType, token, value, persistencePrefix
}
}
}
function deleteAllCookies() {
var cookies = document.cookie.split(';')

for (var i = 0; i < cookies.length; i++) {
var cookie = cookies[i]
var eqPos = cookie.indexOf('=')
var name = eqPos > -1 ? cookie.substr(0, eqPos) : cookie
document.cookie = name + '=;expires=Thu, 01 Jan 1970 00:00:00 GMT'
}
}
describe(`GDPR utils`, () => {
// these imports must be re-required before each test
// so that they reference the correct jsdom document
Expand Down
217 changes: 123 additions & 94 deletions src/__tests__/posthog-persistence.js
Original file line number Diff line number Diff line change
@@ -1,129 +1,158 @@
import { PostHogPersistence } from '../posthog-persistence'
import { SESSION_ID, USER_STATE } from '../constants'

given('lib', () => new PostHogPersistence({ name: 'bla', persistence: 'cookie' }))

function forPersistenceTypes(runTests) {
;[`cookie`, `localStorage`, `localStorage+cookie`].forEach(function (persistenceType) {
describe(persistenceType, runTests.bind(null, persistenceType))
})
}

let referrer = '' // No referrer by default
Object.defineProperty(document, 'referrer', { get: () => referrer })

describe('persistence', () => {
afterEach(() => {
given.lib.clear()
document.cookie = ''
referrer = ''
})

it('should set direct referrer', () => {
referrer = ''
given.lib.update_referrer_info()

expect(given.lib.props['$referring_domain']).toBe('$direct')
expect(given.lib.props['$referrer']).toBe('$direct')
})
describe.each([`cookie`, `localStorage`, `localStorage+cookie`])('persistence modes: %p', (persistenceMode) => {
// Common tests for all storage modes
beforeEach(() => {
given('lib', () => new PostHogPersistence({ name: 'test', persistence: persistenceMode }))
given.lib.clear()
})

it('should set external referrer', () => {
referrer = 'https://www.google.com'
given.lib.update_referrer_info()
it('should register_once', () => {
given.lib.register_once({ distinct_id: 'hi', test_prop: 'test_val' })

expect(given.lib.props['$referring_domain']).toBe('www.google.com')
expect(given.lib.props['$referrer']).toBe('https://www.google.com')
})
let lib2 = new PostHogPersistence({ name: 'test', persistence: persistenceMode })
expect(lib2.props).toEqual({ distinct_id: 'hi', test_prop: 'test_val' })
})

it('should set internal referrer', () => {
referrer = 'https://hedgebox.net/files/abc.png'
given.lib.update_referrer_info()
it('should save user state', () => {
let lib = new PostHogPersistence({ name: 'bla', persistence: 'cookie' })
lib.set_user_state('identified')
expect(lib.props[USER_STATE]).toEqual('identified')
})

expect(given.lib.props['$referring_domain']).toBe('hedgebox.net')
expect(given.lib.props['$referrer']).toBe('https://hedgebox.net/files/abc.png')
})
it('can load user state', () => {
let lib = new PostHogPersistence({ name: 'bla', persistence: 'cookie' })
lib.set_user_state('identified')
expect(lib.get_user_state()).toEqual('identified')
})

it('extracts enabled feature flags', () => {
given.lib.register({ $enabled_feature_flags: { flag: 'variant', other: true } })
expect(given.lib.props['$enabled_feature_flags']).toEqual({ flag: 'variant', other: true })
expect(given.lib.properties()).toEqual({
'$feature/flag': 'variant',
'$feature/other': true,
it('has user state as a reserved property key', () => {
let lib = new PostHogPersistence({ name: 'bla', persistence: 'cookie' })
lib.register({ distinct_id: 'testy', test_prop: 'test_value' })
lib.set_user_state('identified')
expect(lib.properties()).toEqual({ distinct_id: 'testy', test_prop: 'test_value' })
})
})

it('should migrate data from cookies to localStorage', () => {
let lib = new PostHogPersistence({ name: 'bla', persistence: 'cookie' })
lib.register_once({ distinct_id: 'testy', test_prop: 'test_value' })
expect(document.cookie).toEqual(
'ph__posthog=%7B%22distinct_id%22%3A%22testy%22%2C%22test_prop%22%3A%22test_value%22%7D'
)
let lib2 = new PostHogPersistence({ name: 'bla', persistence: 'localStorage+cookie' })
expect(document.cookie).toEqual('ph__posthog=%7B%22distinct_id%22%3A%22testy%22%7D')
lib2.register({ test_prop2: 'test_val', distinct_id: 'test2' })
expect(document.cookie).toEqual('ph__posthog=%7B%22distinct_id%22%3A%22test2%22%7D')
expect(lib2.props).toEqual({ distinct_id: 'test2', test_prop: 'test_value', test_prop2: 'test_val' })
lib2.remove('ph__posthog')
expect(localStorage.getItem('ph__posthog')).toEqual(null)
expect(document.cookie).toEqual('')
})
it(`should only call save if props changes`, () => {
let lib = new PostHogPersistence({ name: 'test', persistence: 'localStorage+cookie' })
lib.register({ distinct_id: 'hi', test_prop: 'test_val' })
lib.save = jest.fn()

it('should save user state', () => {
let lib = new PostHogPersistence({ name: 'bla', persistence: 'cookie' })
lib.set_user_state('identified')
expect(document.cookie).toEqual('ph__posthog=%7B%22%24user_state%22%3A%22identified%22%7D')
})
lib.register({ distinct_id: 'hi', test_prop: 'test_val' })
lib.register({})
lib.register({ distinct_id: 'hi' })
expect(lib.save).toHaveBeenCalledTimes(0)

it('can load user state', () => {
let lib = new PostHogPersistence({ name: 'bla', persistence: 'cookie' })
lib.set_user_state('identified')
expect(lib.get_user_state()).toEqual('identified')
})
lib.register({ distinct_id: 'hi2' })
expect(lib.save).toHaveBeenCalledTimes(1)
lib.save.mockClear()

it('has user state as a reserved property key', () => {
let lib = new PostHogPersistence({ name: 'bla', persistence: 'cookie' })
lib.register({ distinct_id: 'testy', test_prop: 'test_value' })
lib.set_user_state('identified')
expect(lib.properties()).toEqual({ distinct_id: 'testy', test_prop: 'test_value' })
})
lib.register({ new_key: '1234' })
expect(lib.save).toHaveBeenCalledTimes(1)
lib.save.mockClear()
})

it(`should register once LS`, () => {
let lib = new PostHogPersistence({ name: 'test', persistence: 'localStorage+cookie' })
lib.register_once({ distinct_id: 'hi', test_prop: 'test_val' })
it('should set direct referrer', () => {
referrer = ''
given.lib.update_referrer_info()

let lib2 = new PostHogPersistence({ name: 'test', persistence: 'localStorage+cookie' })
expect(lib2.props).toEqual({ distinct_id: 'hi', test_prop: 'test_val' })
lib.clear()
lib2.clear()
})
expect(given.lib.props['$referring_domain']).toBe('$direct')
expect(given.lib.props['$referrer']).toBe('$direct')
})

it(`should only call save if props changes`, () => {
let lib = new PostHogPersistence({ name: 'test', persistence: 'localStorage+cookie' })
lib.register({ distinct_id: 'hi', test_prop: 'test_val' })
lib.save = jest.fn()
it('should set external referrer', () => {
referrer = 'https://www.google.com'
given.lib.update_referrer_info()

lib.register({ distinct_id: 'hi', test_prop: 'test_val' })
lib.register({})
lib.register({ distinct_id: 'hi' })
expect(lib.save).toHaveBeenCalledTimes(0)
expect(given.lib.props['$referring_domain']).toBe('www.google.com')
expect(given.lib.props['$referrer']).toBe('https://www.google.com')
})

it('should set internal referrer', () => {
referrer = 'https://hedgebox.net/files/abc.png'
given.lib.update_referrer_info()

lib.register({ distinct_id: 'hi2' })
expect(lib.save).toHaveBeenCalledTimes(1)
lib.save.mockClear()
expect(given.lib.props['$referring_domain']).toBe('hedgebox.net')
expect(given.lib.props['$referrer']).toBe('https://hedgebox.net/files/abc.png')
})

lib.register({ new_key: '1234' })
expect(lib.save).toHaveBeenCalledTimes(1)
lib.save.mockClear()
it('extracts enabled feature flags', () => {
given.lib.register({ $enabled_feature_flags: { flag: 'variant', other: true } })
expect(given.lib.props['$enabled_feature_flags']).toEqual({ flag: 'variant', other: true })
expect(given.lib.properties()).toEqual({
'$feature/flag': 'variant',
'$feature/other': true,
})
})
})

forPersistenceTypes(function (persistenceType) {
it(`should register once`, () => {
let lib = new PostHogPersistence({ name: 'test', persistence: persistenceType })
lib.register_once({ distinct_id: 'hi', test_prop: 'test_val' })
describe('localStorage+cookie', () => {
it('should migrate data from cookies to localStorage', () => {
let lib = new PostHogPersistence({ name: 'bla', persistence: 'cookie' })
lib.register_once({ distinct_id: 'testy', test_prop: 'test_value' })
expect(document.cookie).toContain(
'ph__posthog=%7B%22distinct_id%22%3A%22testy%22%2C%22test_prop%22%3A%22test_value%22%7D'
)
let lib2 = new PostHogPersistence({ name: 'bla', persistence: 'localStorage+cookie' })
expect(document.cookie).toContain('ph__posthog=%7B%22distinct_id%22%3A%22testy%22%7D')
lib2.register({ test_prop2: 'test_val', distinct_id: 'test2' })
expect(document.cookie).toContain('ph__posthog=%7B%22distinct_id%22%3A%22test2%22%7D')
expect(lib2.props).toEqual({ distinct_id: 'test2', test_prop: 'test_value', test_prop2: 'test_val' })
lib2.remove('ph__posthog')
expect(localStorage.getItem('ph__posthog')).toEqual(null)
expect(document.cookie).toEqual('')
})

let lib2 = new PostHogPersistence({ name: 'test', persistence: persistenceType })
expect(lib2.props).toEqual({ distinct_id: 'hi', test_prop: 'test_val' })
lib.clear()
lib2.clear()
it(`should additionally store certain values in cookies if localStorage+cookie`, () => {
expect(document.cookie).toEqual('')

const encode = (props) => encodeURIComponent(JSON.stringify(props))

let lib = new PostHogPersistence({ name: 'test', persistence: 'localStorage+cookie' })
lib.register({ distinct_id: 'test', test_prop: 'test_val' })
expect(document.cookie).toContain(
`ph__posthog=${encode({
distinct_id: 'test',
})}`
)

lib.register({ otherProp: 'prop' })
expect(document.cookie).toContain(
`ph__posthog=${encode({
distinct_id: 'test',
})}`
)

lib.register({ [SESSION_ID]: [1000, 'sid', 2000] })
expect(document.cookie).toContain(
`ph__posthog=${encode({
distinct_id: 'test',
$sesid: [1000, 'sid', 2000],
})}`
)

// Clear localstorage to simulate being on a different domain
localStorage.clear()

const newLib = new PostHogPersistence({ name: 'test', persistence: 'localStorage+cookie' })

expect(newLib.props).toEqual({
distinct_id: 'test',
$sesid: [1000, 'sid', 2000],
})
})
// Need to add more tests here
})
})
2 changes: 1 addition & 1 deletion src/__tests__/sessionid.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { SessionIdManager } from '../sessionid'
import { SESSION_ID } from '../posthog-persistence'
import { SESSION_ID } from '../constants'
import { sessionStore } from '../storage'
import { uuidv7 } from '../uuidv7'

Expand Down
2 changes: 1 addition & 1 deletion src/autocapture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import {
import RageClick from './extensions/rageclick'
import { AutocaptureConfig, AutoCaptureCustomProperty, DecideResponse, Properties } from './types'
import { PostHog } from './posthog-core'
import { AUTOCAPTURE_DISABLED_SERVER_SIDE } from './posthog-persistence'
import { AUTOCAPTURE_DISABLED_SERVER_SIDE } from './constants'

const autocapture = {
_initializedTokens: [] as string[],
Expand Down
43 changes: 43 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Constants
*/

/* PROPERTY KEYS */

// This key is deprecated, but we want to check for it to see whether aliasing is allowed.
export const PEOPLE_DISTINCT_ID_KEY = '$people_distinct_id'
export const DISTINCT_ID = 'distinct_id'
export const ALIAS_ID_KEY = '__alias'
export const CAMPAIGN_IDS_KEY = '__cmpns'
export const EVENT_TIMERS_KEY = '__timers'
export const AUTOCAPTURE_DISABLED_SERVER_SIDE = '$autocapture_disabled_server_side'
export const SESSION_RECORDING_ENABLED_SERVER_SIDE = '$session_recording_enabled_server_side'
export const CONSOLE_LOG_RECORDING_ENABLED_SERVER_SIDE = '$console_log_recording_enabled_server_side'
export const SESSION_RECORDING_RECORDER_VERSION_SERVER_SIDE = '$session_recording_recorder_version_server_side' // follows rrweb versioning
export const SESSION_ID = '$sesid'
export const ENABLED_FEATURE_FLAGS = '$enabled_feature_flags'
export const PERSISTENCE_EARLY_ACCESS_FEATURES = '$early_access_features'
export const STORED_PERSON_PROPERTIES_KEY = '$stored_person_properties'
export const STORED_GROUP_PROPERTIES_KEY = '$stored_group_properties'
export const SURVEYS = '$surveys'
export const FLAG_CALL_REPORTED = '$flag_call_reported'
export const USER_STATE = '$user_state'
export const POSTHOG_QUOTA_LIMITED = '$posthog_quota_limited'

// These are propertties that are reserved and will not be automatically included in events
export const PERSISTENCE_RESERVED_PROPERTIES = [
PEOPLE_DISTINCT_ID_KEY,
ALIAS_ID_KEY,
CAMPAIGN_IDS_KEY,
EVENT_TIMERS_KEY,
SESSION_RECORDING_ENABLED_SERVER_SIDE,
SESSION_ID,
ENABLED_FEATURE_FLAGS,
USER_STATE,
POSTHOG_QUOTA_LIMITED,
PERSISTENCE_EARLY_ACCESS_FEATURES,
STORED_GROUP_PROPERTIES_KEY,
STORED_PERSON_PROPERTIES_KEY,
SURVEYS,
FLAG_CALL_REPORTED,
]
2 changes: 1 addition & 1 deletion src/decide.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { autocapture } from './autocapture'
import { _base64Encode, loadScript } from './utils'
import { PostHog } from './posthog-core'
import { Compression, DecideResponse } from './types'
import { STORED_GROUP_PROPERTIES_KEY, STORED_PERSON_PROPERTIES_KEY } from './posthog-persistence'
import { STORED_GROUP_PROPERTIES_KEY, STORED_PERSON_PROPERTIES_KEY } from './constants'

export class Decide {
instance: PostHog
Expand Down
2 changes: 1 addition & 1 deletion src/extensions/sessionrecording.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {
CONSOLE_LOG_RECORDING_ENABLED_SERVER_SIDE,
SESSION_RECORDING_ENABLED_SERVER_SIDE,
SESSION_RECORDING_RECORDER_VERSION_SERVER_SIDE,
} from '../posthog-persistence'
} from '../constants'
import {
ensureMaxMessageSize,
FULL_SNAPSHOT_EVENT_TYPE,
Expand Down
Loading

0 comments on commit fd04266

Please sign in to comment.