Skip to content

Commit 3de3997

Browse files
committed
Simplify url creation
1 parent 96a787b commit 3de3997

File tree

3 files changed

+87
-75
lines changed

3 files changed

+87
-75
lines changed

src/cookieSyncManager.ts

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
} from './utils';
77
import Constants from './constants';
88
import { MParticleWebSDK } from './sdkRuntimeModels';
9-
import { MPID } from '@mparticle/web-sdk';
9+
import { Logger, MPID } from '@mparticle/web-sdk';
1010
import { IConsentRules } from './consent';
1111

1212
const { Messages } = Constants;
@@ -66,10 +66,10 @@ export default function CookieSyncManager(
6666
const self = this;
6767

6868
// Public
69-
this.attemptCookieSync = async (
69+
this.attemptCookieSync = (
7070
mpid: MPID,
7171
mpidIsNotInCookies?: boolean
72-
): Promise<void> => {
72+
): void => {
7373
const { pixelConfigurations, webviewBridgeEnabled } = mpInstance._Store;
7474

7575
if (!mpid || webviewBridgeEnabled) {
@@ -82,7 +82,7 @@ export default function CookieSyncManager(
8282
return;
8383
}
8484

85-
for (const pixelSettings of pixelConfigurations as IPixelConfiguration[]) {
85+
pixelConfigurations.forEach(async (pixelSettings: IPixelConfiguration) => {
8686
// set requiresConsent to false to start each additional pixel configuration
8787
// set to true only if filteringConsenRuleValues.values.length exists
8888
let requiresConsent = false;
@@ -129,14 +129,23 @@ export default function CookieSyncManager(
129129
const cookieSyncUrl = createCookieSyncUrl(mpid, pixelUrl, redirectUrl)
130130
const moduleIdString = moduleId.toString();
131131

132-
const fullUrl: string = isTcfApiAvailable() ? await getGdprConsentUrl(cookieSyncUrl) : cookieSyncUrl;
132+
// fullUrl will be the cookieSyncUrl if an error is thrown, or there if TcfApi is not available
133+
let fullUrl: string;
134+
try {
135+
fullUrl = isTcfApiAvailable() ? await appendGdprConsentUrl(cookieSyncUrl, mpInstance.Logger) : cookieSyncUrl;
136+
} catch (error) {
137+
fullUrl = cookieSyncUrl;
138+
const errorMessage = (error as Error).message || error.toString();
139+
mpInstance.Logger.error(errorMessage);
140+
}
141+
133142
self.performCookieSync(
134143
fullUrl,
135144
moduleIdString,
136145
mpid,
137146
cookieSyncDates
138147
);
139-
}
148+
})
140149
};
141150

142151
// Private
@@ -146,6 +155,10 @@ export default function CookieSyncManager(
146155
mpid: MPID,
147156
cookieSyncDates: CookieSyncDates,
148157
): void => {
158+
console.log(url)
159+
console.log(moduleId);
160+
console.log(mpid);
161+
console.log(cookieSyncDates)
149162
const img = document.createElement('img');
150163

151164
mpInstance.Logger.verbose(InformationMessages.CookieSync);
@@ -179,19 +192,26 @@ export const isLastSyncDateExpired = (
179192

180193
export const isTcfApiAvailable = (): boolean => isFunction(window.__tcfapi);
181194

182-
async function getGdprConsentUrl(url: string): Promise<string> {
195+
export async function appendGdprConsentUrl(url: string, logger: Logger): Promise<string> {
183196
return new Promise((resolve, reject) => {
184197
try {
185-
window.__tcfapi('getInAppTCData', 2, (inAppTCData: TCData, success: boolean) => {
198+
const tcfAPICallBack = (inAppTCData: TCData, success: boolean) => {
186199
if (success && inAppTCData) {
187200
const gdprApplies = inAppTCData.gdprApplies ? 1 : 0;
188201
const tcString = inAppTCData.tcString;
189202
resolve(`${url}&gdpr=${gdprApplies}&gdpr_consent=${tcString}`);
190203
} else {
191204
resolve(url); // No GDPR data; fallback to original URL
192205
}
193-
});
206+
}
207+
208+
// `getInAppTCData` is the function name
209+
// 2 is the version of TCF (2.2 as of 1/22/2025)
210+
// callback
211+
window.__tcfapi('getInAppTCData', 2, tcfAPICallBack);
194212
} catch (error) {
213+
const errorMessage = (error as Error).message || error.toString();
214+
logger.error(errorMessage);
195215
reject(error);
196216
}
197217
});

test/jest/cookieSyncManager.spec.ts

Lines changed: 57 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import CookieSyncManager, {
33
IPixelConfiguration,
44
CookieSyncDates,
55
isLastSyncDateExpired,
6-
isTcfApiAvailable
6+
isTcfApiAvailable,
7+
appendGdprConsentUrl
78
} from '../../src/cookieSyncManager';
89
import { MParticleWebSDK } from '../../src/sdkRuntimeModels';
910
import { testMPID } from '../src/config/constants';
@@ -563,9 +564,10 @@ describe('CookieSyncManager', () => {
563564
});
564565
});
565566

566-
describe('#performCookieSyncWithGDPR', () => {
567+
describe('#appendGdprConsentUrl', () => {
567568
const verboseLoggerSpy = jest.fn();
568569
const errorLoggerSpy = jest.fn();
570+
const mockUrl = 'https://example.com/cookie-sync';
569571

570572
let cookieSyncManager: any;
571573
const mockMpInstance = ({
@@ -590,12 +592,7 @@ describe('CookieSyncManager', () => {
590592
jest.clearAllMocks();
591593
})
592594

593-
it('should append GDPR parameters to the URL if __tcfapi callback succeeds', () => {
594-
const mockCookieSyncDates = {};
595-
const mockUrl = 'https://example.com/cookie-sync';
596-
const moduleId = 'module1';
597-
const mpid = '12345';
598-
595+
it('should append GDPR parameters to the URL if __tcfapi callback succeeds', async () => {
599596
// Mock __tcfapi to call the callback with success
600597
(window.__tcfapi as jest.Mock).mockImplementation((
601598
command,
@@ -611,82 +608,77 @@ describe('CookieSyncManager', () => {
611608
);
612609
});
613610

614-
const performCookieSyncSpy = jest.spyOn(cookieSyncManager, 'performCookieSync');
615-
616-
// Call the function under test
617-
cookieSyncManager.performCookieSyncWithGDPR(
618-
mockUrl,
619-
moduleId,
620-
mpid,
621-
mockCookieSyncDates
622-
);
611+
const fullUrl = await appendGdprConsentUrl(mockUrl, mockMpInstance.Logger);
623612

624-
expect(performCookieSyncSpy).toHaveBeenCalledWith(
613+
expect(fullUrl).toBe(
625614
`${mockUrl}&gdpr=1&gdpr_consent=test-consent-string`,
626-
moduleId,
627-
mpid,
628-
mockCookieSyncDates
629615
);
630616
});
631617

632-
it('should fall back to performCookieSync if __tcfapi callback fails', () => {
633-
const mockCookieSyncDates = {};
634-
const mockUrl = 'https://example.com/cookie-sync';
635-
const moduleId = 'module1';
636-
const mpid = '12345';
637-
618+
it('should return only the base url if the __tcfapi callback fails to get tcData', async () => {
638619
// Mock __tcfapi to call the callback with failure
639620
(window.__tcfapi as jest.Mock).mockImplementation((command, version, callback) => {
640621
callback(null, false); // Simulate a failure
641622
});
642623

643-
// Spy on the `performCookieSync` method
644-
const performCookieSyncSpy = jest.spyOn(cookieSyncManager, 'performCookieSync');
645-
646-
// Call the function under test
647-
cookieSyncManager.performCookieSyncWithGDPR(
648-
mockUrl,
649-
moduleId,
650-
mpid,
651-
mockCookieSyncDates
652-
);
653-
624+
const fullUrl = await appendGdprConsentUrl(mockUrl, mockMpInstance.Logger);
654625
// Assert that the fallback method was called with the original URL
655-
expect(performCookieSyncSpy).toHaveBeenCalledWith(
656-
mockUrl,
657-
moduleId,
658-
mpid,
659-
mockCookieSyncDates
660-
);
626+
expect(fullUrl).toBe(mockUrl);
661627
});
662628

663-
it('should handle exceptions thrown by __tcfapi gracefully', () => {
664-
const mockCookieSyncDates = {};
665-
const mockUrl = 'https://example.com/cookie-sync';
666-
const moduleId = 'module1';
667-
const mpid = '12345';
668-
629+
it('should handle exceptions thrown by __tcfapi gracefully', async () => {
669630
// Mock __tcfapi to throw an error
670631
(window.__tcfapi as jest.Mock).mockImplementation(() => {
671632
throw new Error('Test Error');
672633
});
673634

674-
// Spy on the `performCookieSync` method
675-
const performCookieSyncSpy = jest.spyOn(cookieSyncManager, 'performCookieSync');
676-
677-
// Call the function under test
678-
cookieSyncManager.performCookieSyncWithGDPR(
679-
mockUrl,
680-
moduleId,
681-
mpid,
682-
mockCookieSyncDates
683-
);
684-
685-
// Assert that the fallback method was called with the original URL
686-
expect(performCookieSyncSpy).not.toHaveBeenCalled();
635+
try {
636+
await appendGdprConsentUrl(mockUrl, mockMpInstance.Logger);
637+
} catch(e) {
638+
expect(errorLoggerSpy).toHaveBeenCalledWith('Test Error');
639+
}
640+
});
687641

688-
// Ensure the error was logged (if applicable)
689-
expect(errorLoggerSpy).toHaveBeenCalledWith('Test Error');
642+
describe.only('#integration test', () => {
643+
it('should handle errors properly when calling attemptCookieSync and the callback fails', () => {
644+
(window.__tcfapi as jest.Mock).mockImplementation(() => {
645+
throw new Error('Test Error');
646+
});
647+
const mockMPInstance = ({
648+
_Store: {
649+
webviewBridgeEnabled: false,
650+
pixelConfigurations: [pixelSettings],
651+
},
652+
_Persistence: {
653+
getPersistence: () => ({testMPID: {}}),
654+
},
655+
_Consent: {
656+
isEnabledForUserConsent: jest.fn().mockReturnValue(true),
657+
},
658+
Identity: {
659+
getCurrentUser: jest.fn().mockReturnValue({
660+
getMPID: () => testMPID,
661+
}),
662+
},
663+
Logger: {
664+
verbose: jest.fn(),
665+
error: jest.fn()
666+
},
667+
} as unknown) as MParticleWebSDK;
668+
669+
const cookieSyncManager = new CookieSyncManager(mockMPInstance);
670+
cookieSyncManager.performCookieSync = jest.fn();
671+
672+
cookieSyncManager.attemptCookieSync(testMPID, true);
673+
674+
expect(cookieSyncManager.performCookieSync).toHaveBeenCalledWith(
675+
pixelUrlAndRedirectUrl,
676+
'5',
677+
testMPID,
678+
{},
679+
);
680+
});
690681
});
682+
691683
});
692684
});

test/src/tests-cookie-syncing.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1204,7 +1204,7 @@ describe('cookie syncing', function() {
12041204
})
12051205
});
12061206

1207-
it.only('should allow some cookie syncs to occur and others to not occur if there are multiple pixels with varying consent levels', function(done) {
1207+
it('should allow some cookie syncs to occur and others to not occur if there are multiple pixels with varying consent levels', function(done) {
12081208
// This test has 2 pixelSettings. pixelSettings1 requires consent pixelSettings2 does not. When mparticle initializes, the pixelSettings2 should fire and pixelSettings1 shouldn't.
12091209
// After the appropriate consent is saved to the user, pixelSettings1 will fire.
12101210

0 commit comments

Comments
 (0)