diff --git a/.changeset/pink-dancers-exist.md b/.changeset/pink-dancers-exist.md new file mode 100644 index 000000000..b9b3e0a93 --- /dev/null +++ b/.changeset/pink-dancers-exist.md @@ -0,0 +1,5 @@ +--- +'@segment/analytics-next': patch +--- + +[LIBWEB-1353] Fix cookie write error diff --git a/packages/browser/src/core/user/__tests__/index.test.ts b/packages/browser/src/core/user/__tests__/index.test.ts index 7f78deab7..287d2e0dc 100644 --- a/packages/browser/src/core/user/__tests__/index.test.ts +++ b/packages/browser/src/core/user/__tests__/index.test.ts @@ -19,6 +19,20 @@ function clear(): void { localStorage.clear() } +/** + * Filters out the calls made for probing cookie availability + */ +const ignoreProbeCookieWrites = ( + fn: jest.SpyInstance< + string | undefined, + [ + name: string, + value: string | object, + options?: jar.CookieAttributes | undefined + ] + > +) => fn.mock.calls.filter((c) => c[0] !== 'ajs_cookies_check') + let store: LocalStorage beforeEach(function () { store = new LocalStorage() @@ -58,7 +72,7 @@ describe('user', () => { assert(user.anonymousId()?.length === 36) expect(jar.get('ajs_anonymous_id')).toBeUndefined() expect(localStorage.getItem('ajs_anonymous_id')).toBeNull() - expect(setCookieSpy.mock.calls.length).toBe(0) + expect(ignoreProbeCookieWrites(setCookieSpy).length).toBe(0) }) it('should not overwrite anonymous id', () => { @@ -218,7 +232,7 @@ describe('user', () => { user.id('foo') assert(user.anonymousId() === prev) - expect(setCookieSpy.mock.calls.length).toBe(0) + expect(ignoreProbeCookieWrites(setCookieSpy).length).toBe(0) }) it('should reset anonymousId if the user id changed', () => { @@ -227,7 +241,7 @@ describe('user', () => { user.id('baz') assert(user.anonymousId() !== prev) assert(user.anonymousId()?.length === 36) - expect(setCookieSpy.mock.calls.length).toBe(0) + expect(ignoreProbeCookieWrites(setCookieSpy).length).toBe(0) }) it('should not reset anonymousId if the user id changed to null', () => { @@ -236,7 +250,7 @@ describe('user', () => { user.id(null) assert(user.anonymousId() === prev) assert(user.anonymousId()?.length === 36) - expect(setCookieSpy.mock.calls.length).toBe(0) + expect(ignoreProbeCookieWrites(setCookieSpy).length).toBe(0) }) }) @@ -795,7 +809,7 @@ describe('group', () => { expect(group.id()).toBe('gid') expect(jar.get('ajs_group_id')).toBeFalsy() expect(store.get('ajs_group_id')).toBeFalsy() - expect(setCookieSpy.mock.calls.length).toBe(0) + expect(ignoreProbeCookieWrites(setCookieSpy).length).toBe(0) }) it('behaves the same as user', () => { diff --git a/packages/browser/src/core/user/__tests__/storage.test.ts b/packages/browser/src/core/user/__tests__/storage.test.ts new file mode 100644 index 000000000..30100a30c --- /dev/null +++ b/packages/browser/src/core/user/__tests__/storage.test.ts @@ -0,0 +1,15 @@ +import { Cookie } from '..' + +describe('Cookie storage', () => { + it('should report cookie storage available when cookies are accessible', () => { + expect(Cookie.available()).toBe(true) + }) + + it('should report cookie storage unavailable when cookies are not accessible', () => { + ;(document as any).__defineGetter__('cookie', function () { + return '' + }) + + expect(Cookie.available()).toBe(false) + }) +}) diff --git a/packages/browser/src/core/user/index.ts b/packages/browser/src/core/user/index.ts index a778ecd21..5949d5fad 100644 --- a/packages/browser/src/core/user/index.ts +++ b/packages/browser/src/core/user/index.ts @@ -62,15 +62,15 @@ const ONE_YEAR = 365 export class Cookie extends Store { static available(): boolean { - let cookieEnabled = window.navigator.cookieEnabled - - if (!cookieEnabled) { - jar.set('ajs:cookies', 'test') - cookieEnabled = document.cookie.includes('ajs:cookies') - jar.remove('ajs:cookies') + try { + const PROBE_COOKIE = 'ajs_cookies_check' + jar.set(PROBE_COOKIE, 'test') + const cookieEnabled = document.cookie.includes(PROBE_COOKIE) + jar.remove(PROBE_COOKIE) + return cookieEnabled + } catch (error) { + return false } - - return cookieEnabled } static get defaults(): CookieOptions { diff --git a/packages/browser/src/plugins/segmentio/__tests__/normalize.test.ts b/packages/browser/src/plugins/segmentio/__tests__/normalize.test.ts index a91a43e5f..cbbd9f5b9 100644 --- a/packages/browser/src/plugins/segmentio/__tests__/normalize.test.ts +++ b/packages/browser/src/plugins/segmentio/__tests__/normalize.test.ts @@ -7,6 +7,20 @@ import { SegmentEvent } from '../../../core/events' import { JSDOM } from 'jsdom' import { version } from '../../../generated/version' +/** + * Filters out the calls made for probing cookie availability + */ +const ignoreProbeCookieWrites = ( + fn: jest.SpyInstance< + string | undefined, + [ + name: string, + value: string | object, + options?: cookie.CookieAttributes | undefined + ] + > +) => fn.mock.calls.filter((c) => c[0] !== 'ajs_cookies_check') + describe('before loading', () => { let jsdom: JSDOM @@ -317,7 +331,7 @@ describe('before loading', () => { expect(object.context.referrer.id).toEqual('medium') assert(object.context.referrer.type === 'millennial-media') expect(cookie.get('s:context.referrer')).toBeUndefined() - expect(setCookieSpy).not.toHaveBeenCalled() + expect(ignoreProbeCookieWrites(setCookieSpy).length).toBe(0) }) it('should add .referrer.id and .referrer.type from cookie', () => {