diff --git a/packages/browser/src/browser/__tests__/integration.test.ts b/packages/browser/src/browser/__tests__/integration.test.ts index 5ff09ce05..5017c8b20 100644 --- a/packages/browser/src/browser/__tests__/integration.test.ts +++ b/packages/browser/src/browser/__tests__/integration.test.ts @@ -213,6 +213,57 @@ describe('Initialization', () => { }) }) + describe('bufferKey', () => { + const overrideKey = 'myKey' + const buffer = { + foo: 'bar', + } + + beforeEach(() => { + ;(window as any)[overrideKey] = buffer + }) + afterEach(() => { + delete (window as any)[overrideKey] + }) + it('should default to window.analytics', async () => { + const defaultObj = { original: 'default' } + ;(window as any)['analytics'] = defaultObj + + await AnalyticsBrowser.load({ + writeKey, + plugins: [ + { + ...xt, + load: async () => { + expect(getGlobalAnalytics()).toBe(defaultObj) + }, + }, + ], + }) + expect.assertions(1) + }) + + it('should set the global window key for the analytics buffer with the setting option', async () => { + await AnalyticsBrowser.load( + { + writeKey, + plugins: [ + { + ...xt, + load: async () => { + expect(getGlobalAnalytics()).toBe(buffer) + }, + }, + ], + }, + { + bufferKey: overrideKey, + } + ) + expect.assertions(1) + }) + }) + describe('Load options', () => { it('gets high entropy client hints if set', async () => { ;(window.navigator as any).userAgentData = { diff --git a/packages/browser/src/browser/index.ts b/packages/browser/src/browser/index.ts index c4fcd939c..e859e8866 100644 --- a/packages/browser/src/browser/index.ts +++ b/packages/browser/src/browser/index.ts @@ -26,7 +26,7 @@ import { popSnippetWindowBuffer } from '../core/buffer/snippet' import { ClassicIntegrationSource } from '../plugins/ajs-destination/types' import { attachInspector } from '../core/inspector' import { Stats } from '../core/stats' -import { getGlobalAnalytics } from './utils' +import { getGlobalAnalytics, setGlobalAnalyticsKey } from './utils' export interface LegacyIntegrationConfiguration { /* @deprecated - This does not indicate browser types anymore */ @@ -149,10 +149,9 @@ function hasTsubMiddleware(settings: LegacySettings): boolean { */ function flushPreBuffer( analytics: Analytics, - buffer: PreInitMethodCallBuffer, - bufferKey?: string + buffer: PreInitMethodCallBuffer ): void { - const calls = getGlobalAnalytics(bufferKey) + const calls = getGlobalAnalytics() buffer.push(...popSnippetWindowBuffer(calls)) flushSetAnonymousID(analytics, buffer) flushOn(analytics, buffer) @@ -163,10 +162,9 @@ function flushPreBuffer( */ async function flushFinalBuffer( analytics: Analytics, - buffer: PreInitMethodCallBuffer, - bufferKey?: string + buffer: PreInitMethodCallBuffer ): Promise { - const calls = getGlobalAnalytics(bufferKey) + const calls = getGlobalAnalytics() // Call popSnippetWindowBuffer before each flush task since there may be // analytics calls during async function calls. buffer.push(...popSnippetWindowBuffer(calls)) @@ -293,6 +291,7 @@ async function loadAnalytics( options: InitOptions = {}, preInitBuffer: PreInitMethodCallBuffer ): Promise<[Analytics, Context]> { + if (options.bufferKey) setGlobalAnalyticsKey(options.bufferKey) // this is an ugly side-effect, but it's for the benefits of the plugins that get their cdn via getCDN() if (settings.cdnURL) setGlobalCDNUrl(settings.cdnURL) @@ -317,7 +316,7 @@ async function loadAnalytics( Stats.initRemoteMetrics(legacySettings.metrics) // needs to be flushed before plugins are registered - flushPreBuffer(analytics, preInitBuffer, options.bufferKey) + flushPreBuffer(analytics, preInitBuffer) const ctx = await registerPlugins( settings.writeKey, @@ -345,7 +344,7 @@ async function loadAnalytics( analytics.page().catch(console.error) } - await flushFinalBuffer(analytics, preInitBuffer, options.bufferKey) + await flushFinalBuffer(analytics, preInitBuffer) return [analytics, ctx] } diff --git a/packages/browser/src/browser/utils.ts b/packages/browser/src/browser/utils.ts index 2051aed38..6bd1dae1b 100644 --- a/packages/browser/src/browser/utils.ts +++ b/packages/browser/src/browser/utils.ts @@ -1,12 +1,23 @@ import { AnalyticsSnippet } from './standalone-interface' +/** + * Stores the global window analytics key + */ +let _globalAnalyticsKey = 'analytics' + /** * Gets the global analytics instance/buffer * @param key name of the window property where the buffer is stored (default: analytics) * @returns AnalyticsSnippet */ -export function getGlobalAnalytics( - key = 'analytics' -): AnalyticsSnippet | undefined { - return (window as any)[key] +export function getGlobalAnalytics(): AnalyticsSnippet | undefined { + return (window as any)[_globalAnalyticsKey] +} + +/** + * Replaces the global window key for the analytics/buffer object + * @param key key name + */ +export function setGlobalAnalyticsKey(key: string) { + _globalAnalyticsKey = key } diff --git a/packages/consent/consent-tools-integration-tests/src/page-bundles/onetrust/index.ts b/packages/consent/consent-tools-integration-tests/src/page-bundles/onetrust/index.ts index 4da0704ff..91a851283 100644 --- a/packages/consent/consent-tools-integration-tests/src/page-bundles/onetrust/index.ts +++ b/packages/consent/consent-tools-integration-tests/src/page-bundles/onetrust/index.ts @@ -12,4 +12,4 @@ oneTrust(analytics, { ;(window as any).analytics = analytics analytics.load({ writeKey: '9lSrez3BlfLAJ7NOChrqWtILiATiycoc' }) -void getGlobalAnalytics().page().then(console.log) +void getGlobalAnalytics()?.page().then(console.log) diff --git a/packages/core/src/task/__tests__/task-group.test.ts b/packages/core/src/task/__tests__/task-group.test.ts new file mode 100644 index 000000000..e484b95ef --- /dev/null +++ b/packages/core/src/task/__tests__/task-group.test.ts @@ -0,0 +1,26 @@ +import { createTaskGroup } from '../task-group' + +function sleep(ms: number) { + return new Promise((resolve) => setTimeout(resolve, ms)) +} + +describe('TaskGroup', () => { + it('works with concurrent operations', async () => { + const group = createTaskGroup() + const a = jest.fn() + const b = jest.fn() + + void group.run(async () => { + await sleep(100) + a() + }) + void group.run(async () => { + await sleep(1000) + b() + }) + + await group.done() + expect(a).toBeCalled() + expect(b).toBeCalled() + }) +})