diff --git a/.github/workflows/es-check.yml b/.github/workflows/es-check.yml index 16e7ebed5..abc9a408f 100644 --- a/.github/workflows/es-check.yml +++ b/.github/workflows/es-check.yml @@ -21,3 +21,6 @@ jobs: - name: Run es-check to check if our ie11 bundle is ES5 compatible run: npx es-check@7.2.1 es5 dist/array.full.es5.js + + - name: Run es-check to check if our main bundle is ES6 compatible + run: npx es-check@7.2.1 es6 dist/array.full.js diff --git a/package.json b/package.json index e25c963fb..c2d9cccf9 100644 --- a/package.json +++ b/package.json @@ -122,9 +122,20 @@ "eslint cypress --fix" ] }, - "browserslist": [ - "> 0.5%, last 2 versions, Firefox ESR, not dead, IE 11" - ], + "browserslist": { + "production": [ + "defaults", + "chrome > 62", + "firefox > 59", + "ios_saf >= 10.3", + "opera > 50", + "safari > 12" + ], + "es5": [ + "defaults", + "IE 11" + ] + }, "pnpm": { "patchedDependencies": { "@rrweb/rrweb-plugin-console-record@2.0.0-alpha.17": "patches/@rrweb__rrweb-plugin-console-record@2.0.0-alpha.17.patch", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index dd632721b..347bd4e3e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -3777,7 +3777,7 @@ packages: resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} engines: {node: '>=8'} dependencies: - '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-plugin-utils': 7.25.7 '@istanbuljs/load-nyc-config': 1.1.0 '@istanbuljs/schema': 0.1.2 istanbul-lib-instrument: 5.1.0 diff --git a/rollup.config.js b/rollup.config.js index 01cdace3c..3cc57abe2 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -8,6 +8,7 @@ import { visualizer } from 'rollup-plugin-visualizer' import commonjs from '@rollup/plugin-commonjs' import fs from 'fs' import path from 'path' +import { browserslist } from './package.json' const plugins = (es5) => [ json(), @@ -26,7 +27,7 @@ const plugins = (es5) => [ [ '@babel/preset-env', { - targets: es5 ? 'defaults, IE 11' : '>0.5%, last 2 versions, Firefox ESR, not dead', + targets: es5 ? 'defaults, IE 11' : browserslist.production, }, ], ], diff --git a/src/__tests__/decide.ts b/src/__tests__/decide.ts index 534d64c65..974de0984 100644 --- a/src/__tests__/decide.ts +++ b/src/__tests__/decide.ts @@ -41,6 +41,7 @@ describe('Decide', () => { beforeEach(() => { // clean the JSDOM to prevent interdependencies between tests + // eslint-disable-next-line compat/compat document.body.innerHTML = '' document.head.innerHTML = '' jest.spyOn(window.console, 'error').mockImplementation() diff --git a/src/__tests__/extensions/replay/sessionrecording.test.ts b/src/__tests__/extensions/replay/sessionrecording.test.ts index 53199fbf8..5880a118b 100644 --- a/src/__tests__/extensions/replay/sessionrecording.test.ts +++ b/src/__tests__/extensions/replay/sessionrecording.test.ts @@ -2217,6 +2217,7 @@ describe('SessionRecording', () => { // Simulate URL change to blocked URL fakeNavigateTo('https://test.com/blocked') _emit(createIncrementalSnapshot({ data: { source: 3 } })) + // eslint-disable-next-line compat/compat expect(document.body).toHaveClass('ph-no-capture') await waitFor(() => { @@ -2246,6 +2247,7 @@ describe('SessionRecording', () => { // Verify recording resumes with resume event _emit(createIncrementalSnapshot({ data: { source: 5 } })) + // eslint-disable-next-line compat/compat expect(document.body).not.toHaveClass('ph-no-capture') expect(sessionRecording['buffer'].data).toStrictEqual([ diff --git a/src/__tests__/extensions/surveys.test.ts b/src/__tests__/extensions/surveys.test.ts index 3742ade71..ea48fbb0e 100644 --- a/src/__tests__/extensions/surveys.test.ts +++ b/src/__tests__/extensions/surveys.test.ts @@ -345,6 +345,7 @@ describe('SurveyManager', () => { surveyDiv.className = 'PostHogSurvey_test' surveyDiv.attachShadow({ mode: 'open' }) surveyDiv.shadowRoot!.appendChild(document.createElement('style')) + // eslint-disable-next-line compat/compat document.body.appendChild(surveyDiv) expect(surveyManager.getTestAPI().canShowNextEventBasedSurvey()).toBe(true) @@ -409,6 +410,7 @@ describe('SurveyManager', () => { current_iteration: null, current_iteration_start_date: null, } + // eslint-disable-next-line compat/compat document.body.innerHTML = '
' const handleWidgetSelectorMock = jest .spyOn(surveyManager as any, 'handleWidgetSelector') diff --git a/src/__tests__/extensions/toolbar.test.ts b/src/__tests__/extensions/toolbar.test.ts index c1a32aa1b..2f5586a45 100644 --- a/src/__tests__/extensions/toolbar.test.ts +++ b/src/__tests__/extensions/toolbar.test.ts @@ -41,6 +41,7 @@ describe('Toolbar', () => { assignableWindow.ph_load_toolbar = jest.fn(() => { const mockToolbarElement = document.createElement('div') mockToolbarElement.setAttribute('id', TOOLBAR_ID) + // eslint-disable-next-line compat/compat document.body.appendChild(mockToolbarElement) }) }) @@ -188,6 +189,7 @@ describe('Toolbar', () => { expect(toolbar.loadToolbar(toolbarParams)).toBe(true) expect(toolbar.loadToolbar(toolbarParams)).toBe(false) + // eslint-disable-next-line compat/compat document.body.removeChild(document.getElementById(TOOLBAR_ID)!) expect(toolbar.loadToolbar(toolbarParams)).toBe(true) diff --git a/src/__tests__/heatmaps.test.ts b/src/__tests__/heatmaps.test.ts index 95a4c4fb5..be671fbff 100644 --- a/src/__tests__/heatmaps.test.ts +++ b/src/__tests__/heatmaps.test.ts @@ -16,6 +16,7 @@ describe('heatmaps', () => { const createMockMouseEvent = (props: Partial = {}) => ({ + // eslint-disable-next-line compat/compat target: document.body, clientX: 10, clientY: 20, @@ -139,6 +140,7 @@ describe('heatmaps', () => { posthog.heatmaps?.['_onClick']?.( createMockMouseEvent({ + // eslint-disable-next-line compat/compat target: document.body, }) ) diff --git a/src/__tests__/posthog-core.test.ts b/src/__tests__/posthog-core.test.ts index af1ca4b01..48f25d2a0 100644 --- a/src/__tests__/posthog-core.test.ts +++ b/src/__tests__/posthog-core.test.ts @@ -2,36 +2,32 @@ import { defaultPostHog } from './helpers/posthog-instance' import type { PostHogConfig } from '../types' import { uuidv7 } from '../uuidv7' -const mockReferrerGetter = jest.fn() -const mockURLGetter = jest.fn() -jest.mock('../utils/globals', () => { - const orig = jest.requireActual('../utils/globals') - return { - ...orig, - document: { - ...orig.document, - createElement: (...args: any[]) => orig.document.createElement(...args), - get referrer() { - return mockReferrerGetter?.() - }, - get URL() { - return mockURLGetter?.() - }, - }, - get location() { - const url = mockURLGetter?.() - return { - href: url, - toString: () => url, - } - }, - } -}) - describe('posthog core', () => { + const mockURL = jest.fn() + const mockReferrer = jest.fn() + + beforeAll(() => { + // Mock getters using Object.defineProperty + Object.defineProperty(document, 'URL', { + get: mockURL, + }) + Object.defineProperty(document, 'referrer', { + get: mockReferrer, + }) + Object.defineProperty(window, 'location', { + get: () => ({ + href: mockURL(), + toString: () => mockURL(), + }), + configurable: true, + }) + }) + beforeEach(() => { - mockReferrerGetter.mockReturnValue('https://referrer.com') - mockURLGetter.mockReturnValue('https://example.com') + jest.clearAllMocks() + + mockReferrer.mockReturnValue('https://referrer.com') + mockURL.mockReturnValue('https://example.com') console.error = jest.fn() }) @@ -111,7 +107,7 @@ describe('posthog core', () => { it("should send referrer info with the event's properties", () => { // arrange const token = uuidv7() - mockReferrerGetter.mockReturnValue('https://referrer.example.com/some/path') + mockReferrer.mockReturnValue('https://referrer.example.com/some/path') const { posthog, onCapture } = setup({ token, persistence_name: token, @@ -132,14 +128,14 @@ describe('posthog core', () => { it('should not update the referrer within the same session', () => { // arrange const token = uuidv7() - mockReferrerGetter.mockReturnValue('https://referrer1.example.com/some/path') + mockReferrer.mockReturnValue('https://referrer1.example.com/some/path') const { posthog: posthog1 } = setup({ token, persistence_name: token, person_profiles: 'always', }) posthog1.capture(eventName, eventProperties) - mockReferrerGetter.mockReturnValue('https://referrer2.example.com/some/path') + mockReferrer.mockReturnValue('https://referrer2.example.com/some/path') const { posthog: posthog2, onCapture: onCapture2 } = setup({ token, persistence_name: token, @@ -163,14 +159,14 @@ describe('posthog core', () => { it('should use the new referrer in a new session', () => { // arrange const token = uuidv7() - mockReferrerGetter.mockReturnValue('https://referrer1.example.com/some/path') + mockReferrer.mockReturnValue('https://referrer1.example.com/some/path') const { posthog: posthog1 } = setup({ token, persistence_name: token, person_profiles: 'always', }) posthog1.capture(eventName, eventProperties) - mockReferrerGetter.mockReturnValue('https://referrer2.example.com/some/path') + mockReferrer.mockReturnValue('https://referrer2.example.com/some/path') const { posthog: posthog2, onCapture: onCapture2 } = setup({ token, persistence_name: token, @@ -194,7 +190,7 @@ describe('posthog core', () => { it('should use $direct when there is no referrer', () => { // arrange const token = uuidv7() - mockReferrerGetter.mockReturnValue('') + mockReferrer.mockReturnValue('') const { posthog, onCapture } = setup({ token, persistence_name: token, @@ -217,7 +213,7 @@ describe('posthog core', () => { it('should not send campaign params as null if there are no non-null ones', () => { // arrange const token = uuidv7() - mockURLGetter.mockReturnValue('https://www.example.com/some/path') + mockURL.mockReturnValue('https://www.example.com/some/path') const { posthog, onCapture } = setup({ token, persistence_name: token, @@ -234,7 +230,7 @@ describe('posthog core', () => { it('should send present campaign params, and nulls for others', () => { // arrange const token = uuidv7() - mockURLGetter.mockReturnValue('https://www.example.com/some/path?utm_source=source') + mockURL.mockReturnValue('https://www.example.com/some/path?utm_source=source') const { posthog, onCapture } = setup({ token, persistence_name: token, diff --git a/src/__tests__/surveys.test.ts b/src/__tests__/surveys.test.ts index defe94d2b..1627deebd 100644 --- a/src/__tests__/surveys.test.ts +++ b/src/__tests__/surveys.test.ts @@ -491,6 +491,7 @@ describe('surveys', () => { }) assignableWindow.location = originalWindowLocation + // eslint-disable-next-line compat/compat document.body.appendChild(document.createElement('div')).className = 'test-selector' surveys.getActiveMatchingSurveys((data) => { expect(data).toEqual([surveyWithSelector]) @@ -502,6 +503,7 @@ describe('surveys', () => { // eslint-disable-next-line compat/compat assignableWindow.location = new URL('https://posthogapp.com') as unknown as Location + // eslint-disable-next-line compat/compat document.body.appendChild(document.createElement('div')).id = 'foo' surveys.getActiveMatchingSurveys((data) => { @@ -645,6 +647,7 @@ describe('surveys', () => { it('returns surveys that inclusively matches any of the above', () => { // eslint-disable-next-line compat/compat assignableWindow.location = new URL('https://posthogapp.com') as unknown as Location + // eslint-disable-next-line compat/compat document.body.appendChild(document.createElement('div')).className = 'test-selector' surveysResponse = { surveys: [activeSurvey, surveyWithSelector, surveyWithEverything] } // activeSurvey returns because there are no restrictions on conditions or flags on it