From 660a88b243cffae9f86a34252345d0d0348af972 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Herculano?= Date: Fri, 31 May 2024 15:30:15 +0200 Subject: [PATCH 1/4] feat: standardize actionTypes common interface --- example/src/App.tsx | 4 +++- src/index.ts | 10 ++++++++-- src/types.ts | 13 +++++++++++-- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/example/src/App.tsx b/example/src/App.tsx index 919e8db..4f307a9 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -74,7 +74,9 @@ export default function App() { consentManager.current?.getUserData().then(setUserData); }); - consentManager.current?.onAction((actionType) => console.log(actionType)); + consentManager.current?.onAction(({ actionType }) => + console.warn(`action: ${actionType}`) + ); consentManager.current?.onError((description) => { setSDKStatus(SDKStatus.Errored); diff --git a/src/index.ts b/src/index.ts index 5409deb..2225353 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,11 @@ import { NativeModules, Platform, NativeEventEmitter } from 'react-native'; -import type { Spec, SPCampaigns, SPUserData, LoadMessageParams } from './types'; +import type { + Spec, + SPCampaigns, + SPUserData, + LoadMessageParams, + SPActionType, +} from './types'; const LINKING_ERROR = `The package '@sourcepoint/react-native-cmp' doesn't seem to be linked. Make sure: \n\n` + @@ -61,7 +67,7 @@ export class SPConsentManager implements Spec { RNSourcepointCmp.loadUSNatPrivacyManager(pmId); } - onAction(callback: (action: string) => void): void { + onAction(callback: (body: { actionType: SPActionType }) => void): void { this.emitter.removeAllListeners('onAction'); this.emitter.addListener('onAction', callback); } diff --git a/src/types.ts b/src/types.ts index 0681f81..d730842 100644 --- a/src/types.ts +++ b/src/types.ts @@ -10,6 +10,16 @@ export const enum SPCampaignEnvironment { Stage = 'Stage', } +export const enum SPActionType { + acceptAll = 'acceptAll', + rejectAll = 'rejectAll', + saveAndExit = 'saveAndExit', + showOptions = 'showOptions', + dismiss = 'dismiss', + pmCancel = 'pmCancel', + unknown = 'unknown', +} + export type SPCampaigns = { gdpr?: SPCampaign; usnat?: SPCampaign; @@ -103,8 +113,7 @@ export interface Spec extends TurboModule { loadGDPRPrivacyManager(pmId: string): void; loadUSNatPrivacyManager(pmId: string): void; - // TODO: change action from string to enum - onAction(callback: (action: string) => void): void; + onAction(callback: (body: { actionType: SPActionType }) => void): void; onSPUIReady(callback: () => void): void; onSPUIFinished(callback: () => void): void; onFinished(callback: () => void): void; From 4082a3acb53f38abdaf23759b42a171abe352491 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Herculano?= Date: Fri, 31 May 2024 15:30:28 +0200 Subject: [PATCH 2/4] feat: standardize actionTypes for iOS --- ios/RNSourcepointActionType.swift | 25 +++++++++++++++++++++++++ ios/RNSourcepointCmp.h | 4 ---- ios/RNSourcepointCmp.swift | 4 +--- 3 files changed, 26 insertions(+), 7 deletions(-) create mode 100644 ios/RNSourcepointActionType.swift diff --git a/ios/RNSourcepointActionType.swift b/ios/RNSourcepointActionType.swift new file mode 100644 index 0000000..721d4e6 --- /dev/null +++ b/ios/RNSourcepointActionType.swift @@ -0,0 +1,25 @@ +// +// RNSourcepointActionType.swift +// sourcepoint-react-native-cmp +// +// Created by Andre Herculano on 31/5/24. +// + +import Foundation +import ConsentViewController + +enum RNSourcepointActionType: String, Codable { + case acceptAll, rejectAll, showPrivacyManager, saveAndExit, dismiss, pmCancel, unknown + + init(from actionType: SPActionType){ + switch actionType { + case .AcceptAll: self = .acceptAll + case .RejectAll: self = .rejectAll + case .SaveAndExit: self = .saveAndExit + case .ShowPrivacyManager: self = .showPrivacyManager + case .Dismiss: self = .dismiss + case .PMCancel: self = .pmCancel + default: self = .unknown + } + } +} diff --git a/ios/RNSourcepointCmp.h b/ios/RNSourcepointCmp.h index 04178f4..2613651 100644 --- a/ios/RNSourcepointCmp.h +++ b/ios/RNSourcepointCmp.h @@ -25,15 +25,11 @@ RCT_EXTERN_METHOD(supportedEvents) return YES; } -/// TODO: check if this really can be here or need fixing in the SDK -/// https://reactnative.dev/docs/native-modules-ios -/// https://github.com/OneSignal/react-native-onesignal/issues/749 - (dispatch_queue_t)methodQueue { return dispatch_get_main_queue(); } -// Don't compile this code when we build for the old architecture. #ifdef RCT_NEW_ARCH_ENABLED - (std::shared_ptr)getTurboModule: (const facebook::react::ObjCTurboModule::InitParams &)params diff --git a/ios/RNSourcepointCmp.swift b/ios/RNSourcepointCmp.swift index e3d2498..556b566 100644 --- a/ios/RNSourcepointCmp.swift +++ b/ios/RNSourcepointCmp.swift @@ -41,7 +41,6 @@ import React } func loadMessage(_ params: SPLoadMessageParams) { - print("calling loadMessage with: ", params.authId as Any) consentManager?.loadMessage(forAuthId: params.authId, pubData: nil) } @@ -67,11 +66,10 @@ extension RNSourcepointCmp: SPDelegate { UIApplication.shared.delegate?.window??.rootViewController } - // TODO: standardize action names func onAction(_ action: SPAction, from controller: UIViewController) { RNSourcepointCmp.shared?.sendEvent( withName: "onAction", - body: ["actionType": action.type.description] + body: ["actionType": RNSourcepointActionType(from: action.type).rawValue] ) } From 3f702f6864b3d27ba729e3df3fdbb235932df281 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Herculano?= Date: Fri, 31 May 2024 15:46:11 +0200 Subject: [PATCH 3/4] feat: standardize actionTypes for Android --- .../reactnativecmp/RNSourcepointCmpModule.kt | 4 +++- .../reactnativecmp/RNSourcepointCmpTypes.kt | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/android/src/main/java/com/sourcepoint/reactnativecmp/RNSourcepointCmpModule.kt b/android/src/main/java/com/sourcepoint/reactnativecmp/RNSourcepointCmpModule.kt index cdd1d06..d932ee1 100644 --- a/android/src/main/java/com/sourcepoint/reactnativecmp/RNSourcepointCmpModule.kt +++ b/android/src/main/java/com/sourcepoint/reactnativecmp/RNSourcepointCmpModule.kt @@ -111,7 +111,9 @@ class RNSourcepointCmpModule internal constructor(context: ReactApplicationConte } override fun onAction(view: View, consentAction: ConsentAction): ConsentAction { - sendEvent(SDKEvent.onAction, createMap().apply { putString("actionType", consentAction.actionType.name) }) + sendEvent(SDKEvent.onAction, createMap().apply { + putString("actionType", RNSourcepointActionType.from(consentAction.actionType).name) + }) return consentAction } diff --git a/android/src/main/java/com/sourcepoint/reactnativecmp/RNSourcepointCmpTypes.kt b/android/src/main/java/com/sourcepoint/reactnativecmp/RNSourcepointCmpTypes.kt index 0828653..bb8c6c3 100644 --- a/android/src/main/java/com/sourcepoint/reactnativecmp/RNSourcepointCmpTypes.kt +++ b/android/src/main/java/com/sourcepoint/reactnativecmp/RNSourcepointCmpTypes.kt @@ -2,6 +2,7 @@ package com.sourcepoint.reactnativecmp import com.facebook.react.bridge.ReadableMap import com.sourcepoint.cmplibrary.data.network.util.CampaignsEnv +import com.sourcepoint.cmplibrary.model.exposed.ActionType import com.sourcepoint.cmplibrary.model.exposed.TargetingParam fun campaignsEnvFrom(rawValue: String?): CampaignsEnv? = @@ -24,6 +25,23 @@ data class SPCampaigns( val environment: CampaignsEnv? ) +enum class RNSourcepointActionType { + acceptAll, rejectAll, showPrivacyManager, saveAndExit, dismiss, pmCancel, unknown; + + companion object { + fun from(spAction: ActionType): RNSourcepointActionType = + when (spAction) { + ActionType.ACCEPT_ALL -> acceptAll + ActionType.REJECT_ALL -> rejectAll + ActionType.SHOW_OPTIONS -> showPrivacyManager + ActionType.SAVE_AND_EXIT -> saveAndExit + ActionType.MSG_CANCEL -> dismiss + ActionType.PM_DISMISS -> pmCancel + else -> unknown + } + } +} + fun ReadableMap.SPCampaign() = SPCampaign( rawTargetingParam = this.getMap("targetingParams"), supportLegacyUSPString = if(this.hasKey("supportLegacyUSPString")) this.getBoolean("supportLegacyUSPString") else false From 02222612da534825d460cdd0fb0c1ee2f4aaf09a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Herculano?= Date: Fri, 31 May 2024 15:46:33 +0200 Subject: [PATCH 4/4] chore: implement tests for actionTypes --- e2e/full.test.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/e2e/full.test.ts b/e2e/full.test.ts index 4e5d384..85f616a 100644 --- a/e2e/full.test.ts +++ b/e2e/full.test.ts @@ -55,6 +55,10 @@ const app = { await this.forSDKToBeFinished(); }, + assertActionWarnWith: async function (actionType: string) { + await expect(element(by.text(`action: ${actionType}`))).toExist(); + }, + reloadMessages: async function ({ clearData }: { clearData: boolean }) { if (clearData) await this.clearData(); await this.loadMessagesButton.tap(); @@ -97,7 +101,9 @@ describe('SourcepointSDK', () => { it('Accepting All, works', async () => { await launchApp(); await app.acceptAll(); // GDPR + await app.assertActionWarnWith('acceptAll'); await app.acceptAll(); // USNAT + await app.assertActionWarnWith('saveAndExit'); // USNAT uses saveAndExit for accepting/rejecting all await app.forSDKToBeFinished(); await assertUUIDsDontChangeAfterReloadingMessages(); await expect(app.gdprConsentStatusLabel).toHaveText('consentedAll'); @@ -107,7 +113,9 @@ describe('SourcepointSDK', () => { it('Rejecting All, works', async () => { await launchApp(); await app.rejectAll(); // GDPR + await app.assertActionWarnWith('rejectAll'); await app.rejectAll(); // USNAT + await app.assertActionWarnWith('saveAndExit'); // USNAT uses saveAndExit for accepting/rejecting all await app.forSDKToBeFinished(); await assertUUIDsDontChangeAfterReloadingMessages(); await expect(app.gdprConsentStatusLabel).toHaveText('rejectedAll');