Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,26 @@ diff --git a/node_modules/react-native-onetrust-cmp/android/src/main/java/com/on
index 23e6beb..8c85220 100644
--- a/node_modules/react-native-onetrust-cmp/android/src/main/java/com/onetrust/OneTrust.java
+++ b/node_modules/react-native-onetrust-cmp/android/src/main/java/com/onetrust/OneTrust.java
@@ -313,6 +313,39 @@ public class OneTrust extends ReactContextBaseJavaModule {
@@ -313,6 +313,52 @@ public class OneTrust extends ReactContextBaseJavaModule {
promise.resolve(googleConsentData.toString());
}

+ @ReactMethod
+ public void fetchPreferencesCmpApiData(Promise promise){
+ promise.resolve(null);
+ ot.fetchPreferencesCmpApiData(new OTCallback() {
+ @Override
+ public void onSuccess(@NonNull OTResponse otResponse) {
+ promise.resolve(null);
+ }
+
+ @Override
+ public void onFailure(@NonNull OTResponse otResponse) {
+ promise.reject(
+ "OT_FETCH_PREFERENCE_CENTER_DATA",
+ otResponse.getResponseMessage()
+ );
+ }
+ });
+ }
+
+ @ReactMethod
Expand Down
12 changes: 12 additions & 0 deletions packages/react-native-contentpass-cmp-onetrust/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
# @contentpass/react-native-contentpass-cmp-onetrust

## 0.4.3

### Patch Changes

- Fetch Android preference-center data before creating the adapter.

## 0.4.2

### Patch Changes

- Handle OneTrust's short banner-state delay after accepting all consent from either the Contentpass layer or the OneTrust preference center.

## 0.4.1

### Patch Changes
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@contentpass/react-native-contentpass-cmp-onetrust",
"version": "0.4.1",
"version": "0.4.3",
"description": "Contentpass OneTrust CMP adapter",
"source": "./src/index.ts",
"main": "./lib/commonjs/index.js",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,16 @@ describe('createOnetrustCmpAdapter', () => {
expect(sdk.getBannerData).toHaveBeenCalled();
expect(sdk.getPreferenceCenterData).toHaveBeenCalled();
});

it('should fail clearly when OneTrust returns no preference center data', async () => {
const { sdk } = createMockSdk({
getPreferenceCenterData: jest.fn().mockResolvedValue(null),
});

await expect(createOnetrustCmpAdapter(sdk)).rejects.toThrow(
'OneTrust returned no preference center data after fetching CMP API data'
);
});
});

describe('OnetrustCmpAdapter', () => {
Expand Down Expand Up @@ -266,6 +276,55 @@ describe('OnetrustCmpAdapter', () => {
expect(listener).toHaveBeenCalledWith(false);
});

it('should accept consent during the banner settlement period after accepting all in the preference center', async () => {
const { sdk, eventHandlers } = createMockSdk({
shouldShowBanner: jest.fn().mockResolvedValue(true),
});
const adapter = await createOnetrustCmpAdapter(sdk);
const listener = jest.fn();

adapter.onConsentStatusChange(listener);
await flushPromises();
listener.mockClear();

eventHandlers.get(OTEventName.preferenceCenterAcceptAll)?.();
await flushPromises();

expect(listener).toHaveBeenCalledWith(true);
});

it('should refresh consent after the preference center closes', async () => {
jest.useFakeTimers();
try {
let bannerReads = 0;
let statusReads = 0;
const { sdk, eventHandlers } = createMockSdk({
shouldShowBanner: jest.fn(() =>
Promise.resolve(bannerReads++ >= 3 ? false : true)
),
getConsentStatusForCategory: jest.fn(() =>
Promise.resolve(Math.floor(statusReads++ / 2) >= 3 ? 1 : 0)
),
});
const adapter = await createOnetrustCmpAdapter(sdk);
const listener = jest.fn();

adapter.onConsentStatusChange(listener);
await jest.advanceTimersByTimeAsync(0);
listener.mockClear();

const secondLayer = adapter.showSecondLayer('purpose');
eventHandlers.get(OTEventName.preferenceCenterConfirmChoices)?.();
await secondLayer;
await jest.advanceTimersByTimeAsync(100);

expect(listener).toHaveBeenCalledWith(true);
} finally {
jest.clearAllTimers();
jest.useRealTimers();
}
});

it('should emit consent status when OneTrust rejects all in the preference center', async () => {
const { sdk, eventHandlers } = createMockSdk({
getConsentStatusForCategory: jest.fn().mockResolvedValue(0),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,15 @@ export async function createOnetrustCmpAdapter(
await sdk.fetchPreferencesCmpApiData();

const bannerData = await sdk.getBannerData();
const preferenceCenterData: PreferenceCenterData =
const preferenceCenterData: PreferenceCenterData | null =
await sdk.getPreferenceCenterData();

if (!Array.isArray(preferenceCenterData?.purposes)) {
throw new Error(
'OneTrust returned no preference center data after fetching CMP API data'
);
}

console.debug('[OnetrustCmpAdapter::create] CMP API data fetched', {
purposeCount: preferenceCenterData?.purposes?.length ?? 0,
shouldResetLocalState:
Expand Down Expand Up @@ -216,6 +222,18 @@ export default class OnetrustCmpAdapter implements CmpAdapter {
eventName,
});
remove();
const revision = this.beginConsentStatusOperation(
`showSecondLayer: closed:${eventName}`
);
this.logConsentSnapshot(`showSecondLayer: closed:${eventName}`);
this.scheduleConsentStatusRefreshes(
revision,
`showSecondLayer: closed:${eventName}`
);
this.emitConsentStatusForRevision(
revision,
`showSecondLayer: closed:${eventName}`
);
resolve();
break;
default:
Expand Down Expand Up @@ -304,6 +322,17 @@ export default class OnetrustCmpAdapter implements CmpAdapter {
});
if (CONSENT_CHANGE_EVENTS.has(eventName)) {
const revision = this.beginConsentStatusOperation(`event:${eventName}`);
if (eventName === OTEventName.preferenceCenterAcceptAll) {
this.bannerAcknowledgedUntil =
Date.now() + BANNER_SETTLEMENT_TIMEOUT_MS;
console.debug(
'[OnetrustCmpAdapter::onEvent] started banner settlement',
{
eventName,
bannerAcknowledgedUntil: this.bannerAcknowledgedUntil,
}
);
}
this.emitConsentStatusForRevision(revision, `event:${eventName}`);
}

Expand Down
Loading