Release: 2.27.0#216
Conversation
|
Skipping CodeAnt AI review — this PR is a back-merge between long-lived branches ( If you want to analyze this anyway (e.g. you resolved conflicts with new logic), comment |
|
Warning Review limit reached
More reviews will be available in 46 minutes and 11 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (3)
📒 Files selected for processing (8)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Review Summary by QodoRelease 2.27.0 with mandatory label support
WalkthroughsDescription• Release version 2.27.0 with mandatory label feature • Added mandatoryLabel field to TCF2Settings across platforms • Implemented mandatory label support in Android and iOS • Updated version numbers in build and package configs • Added comprehensive changelog documenting features and fixes Diagramflowchart LR
A["Version Update<br/>2.26.3 → 2.27.0"] --> B["Add mandatoryLabel<br/>to TCF2Settings"]
B --> C["Android Implementation"]
B --> D["iOS Implementation"]
B --> E["React Native Model"]
C --> F["Update Serialization"]
D --> G["Update Dictionary"]
E --> H["Add Constructor Param"]
F --> I["Release 2.27.0"]
G --> I
H --> I
File Changes1. android/build.gradle.kts
|
Code Review by Qodo
1. Missing mandatoryLabel compat
|
|
PR Summary: Release 2.27.0 — Adds PUR compliance support (mandatory label + hide-vendor-toggles), cross-bridge updates, accessibility fixes, and version/SDK bumps.
|
| @@ -121,6 +122,7 @@ export class TCF2Settings { | |||
| firstLayerMobileVariant?: FirstLayerMobileVariant, | |||
| dataSharedOutsideEUText?: string, | |||
| consentOrPay?: TCF2ConsentOrPaySettings, | |||
| mandatoryLabel: string = 'Mandatory', | |||
There was a problem hiding this comment.
[REFACTORING] You added mandatoryLabel: string (line 62) and a constructor parameter default (line 125). Consider making this field optional/nullable (e.g. mandatoryLabel?: string | null) to make the model tolerant to settings coming from older SDK versions that don't provide the field. Also add/update the exported type definitions (lib/index.d.ts) and any code that constructs TCF2Settings in the repo to ensure callers are intentionally relying on the default. If the intent is to always provide a value, add a short inline comment explaining why a non-null contract is safe.
export class TCF2Settings {
// ...existing fields...
- mandatoryLabel: string
+ mandatoryLabel?: string | null
constructor(
// ...existing params...
- consentOrPay?: TCF2ConsentOrPaySettings,
- mandatoryLabel: string = 'Mandatory',
+ consentOrPay?: TCF2ConsentOrPaySettings,
+ mandatoryLabel?: string | null,
) {
// ...existing assignments...
- this.consentOrPay = consentOrPay
- this.mandatoryLabel = mandatoryLabel
+ this.consentOrPay = consentOrPay
+ this.mandatoryLabel = mandatoryLabel ?? 'Mandatory'
}
}| "selectedATPIds" to listOf(43, 46, 55), | ||
| "mandatoryLabel" to "Mandatory", |
There was a problem hiding this comment.
[NITPICK] You added mandatoryLabel to the expectedTCF2Settings test fixture. Ensure all other platform tests / fixtures (iOS sample mocks, shared unit tests) are updated to expect this new key or remain tolerant to its absence. Also consider adding a small unit test that verifies behavior when mandatoryLabel is missing (to prevent regressions when running tests against older SDKs).
// sample/ios/sampleTests/Mock/CMPData+Mock.swift
extension TCF2Settings {
static func mock() -> TCF2Settings {
return .init(
firstLayerTitle: "firstLayerTitle",
secondLayerTitle: "secondLayerTitle",
tabsPurposeLabel: "tabsPurposeLabel",
tabsVendorsLabel: "tabsVendorsLabel",
labelsFeatures: "labelsFeatures",
labelsIabVendors: "labelsIabVendors",
labelsNonIabPurposes: "labelsNonIabPurposes",
labelsNonIabVendors: "labelsNonIabVendors",
labelsPurposes: "labelsPurposes",
vendorFeatures: "vendorFeatures",
vendorLegitimateInterestPurposes: "vendorLegitimateInterestPurposes",
vendorPurpose: "vendorPurpose",
vendorSpecialFeatures: "vendorSpecialFeatures",
vendorSpecialPurposes: "vendorSpecialPurposes",
togglesConsentToggleLabel: "togglesConsentToggleLabel",
togglesLegIntToggleLabel: "togglesLegIntToggleLabel",
buttonsAcceptAllLabel: "buttonsAcceptAllLabel",
buttonsDenyAllLabel: "buttonsDenyAllLabel",
buttonsSaveLabel: "buttonsSaveLabel",
linksManageSettingsLabel: "linksManageSettingsLabel",
linksVendorListLinkLabel: "linksVendorListLinkLabel",
cmpId: 1,
cmpVersion: 1,
firstLayerHideToggles: false,
secondLayerHideToggles: false,
hideLegitimateInterestToggles: false,
secondLayerHideButtonDeny: false,
publisherCountryCode: "DE",
purposeOneTreatment: false,
selectedVendorIds: [1, 2],
gdprApplies: true,
selectedStacks: [1],
disabledSpecialFeatures: [],
firstLayerShowDescriptions: true,
hideNonIabOnFirstLayer: false,
resurfacePeriod: 0,
resurfacePurposeChanged: false,
resurfaceVendorAdded: false,
firstLayerDescription: "firstLayerDescription",
firstLayerAdditionalInfo: "firstLayerAdditionalInfo",
secondLayerDescription: "secondLayerDescription",
togglesSpecialFeaturesToggleOn: "On",
togglesSpecialFeaturesToggleOff: "Off",
appLayerNoteResurface: "appLayerNoteResurface",
firstLayerNoteResurface: "firstLayerNoteResurface",
categoriesOfDataLabel: "categoriesOfDataLabel",
dataRetentionPeriodLabel: "dataRetentionPeriodLabel",
legitimateInterestLabel: "legitimateInterestLabel",
version: "2.2",
examplesLabel: "examplesLabel",
showDataSharedOutsideEUText: true,
vendorIdsOutsideEUList: [1, 2, 3],
scope: .global,
changedPurposes: .init(purposes: [1, 2, 3], legIntPurposes: [1, 2, 3]),
acmV2Enabled: true,
selectedATPIds: [43, 46, 55],
firstLayerHideButtonDeny: false,
firstLayerMobileVariant: .full,
dataSharedOutsideEUText: "dataSharedOutsideEUText",
consentOrPay: .init(
enableConsentOrPay: true,
showTogglesForVendors: false,
publisherRestrictions: [:],
specialFeatures: [:]
),
mandatoryLabel: "Mandatory"
)
}
}
// src/__tests__/TCF2Settings.test.ts (new test)
import { TCF2Settings, TCF2Scope, TCF2ChangedPurposes } from '../models/TCF2Settings'
describe('TCF2Settings.mandatoryLabel', () => {
it('defaults to "Mandatory" when not provided', () => {
const settings = new TCF2Settings(
'firstLayerTitle',
'secondLayerTitle',
'tabsPurposeLabel',
'tabsVendorsLabel',
'labelsFeatures',
'labelsIabVendors',
'labelsNonIabPurposes',
'labelsNonIabVendors',
'labelsPurposes',
'vendorFeatures',
'vendorLegitimateInterestPurposes',
'vendorPurpose',
'vendorSpecialFeatures',
'vendorSpecialPurposes',
'togglesConsentToggleLabel',
'togglesLegIntToggleLabel',
'buttonsAcceptAllLabel',
'buttonsDenyAllLabel',
'buttonsSaveLabel',
'linksManageSettingsLabel',
'linksVendorListLinkLabel',
1,
1,
false,
false,
false,
false,
'DE',
false,
[1, 2],
true,
[1],
[],
true,
false,
0,
false,
false,
'firstLayerDescription',
'firstLayerAdditionalInfo',
'secondLayerDescription',
'On',
'Off',
'appLayerNoteResurface',
'firstLayerNoteResurface',
'categoriesOfDataLabel',
'dataRetentionPeriodLabel',
'legitimateInterestLabel',
'2.2',
'examplesLabel',
true,
[1, 2, 3],
TCF2Scope.global,
new TCF2ChangedPurposes([1, 2, 3], [1, 2, 3]),
true,
[43, 46, 55],
)
expect(settings.mandatoryLabel).toBe('Mandatory')
})
})| "version": "2.27.0", | ||
| "description": "Usercentrics SDK", | ||
| "homepage": "https://usercentrics.com", | ||
| "main": "lib/index.js", | ||
| "types": "lib/index.d.ts", | ||
| "author": "Usercentrics <developer@usercentrics.com>", | ||
| "iosPackageName": "react-native-usercentrics", | ||
| "iosPackageVersion": "2.26.3", | ||
| "iosPackageVersion": "2.27.0", |
There was a problem hiding this comment.
[NITPICK] You bumped package version and iosPackageVersion to 2.27.0. Confirm that the prepare/compile step, the react-native-usercentrics.podspec and any release scripts (scripts/generate-codegen-jni.js, prepublish hooks) run successfully with this version. Ensure you publish the matching native artifacts (UsercentricsUI 2.27.0) and update changelog/release notes accordingly.
|
Reviewed up to commit:39e5d992a0385bef0bd3ccfadf886ce57044645a Additional SuggestionOthers- Changelog additions look fine. Ensure the wording accurately reflects breaking changes (if any) and that release date/version align with the package.json/podspec changes. - Cross-platform compatibility: you've added a new TCF2 field surfaced to JS/native bridges. Make the native->bridge serialization defensive across Android and iOS (use reflection/runCatching or optional accesses), update or add unit/instrumentation tests on both platforms and the JS side to validate presence/absence of mandatoryLabel, and ensure sample apps/mocks are updated. This prevents runtime crashes when consumers use mixed versions of the native Usercentrics SDK and this bridge package.// Android bridge (defensive read of optional mandatoryLabel via reflection)
private fun TCF2Settings.getMandatoryLabelCompat(): String? {
return runCatching {
javaClass.getMethod("getMandatoryLabel").invoke(this) as? String
}.getOrNull()
}
private fun TCF2Settings.serialize(): WritableMap {
return mapOf(
// ...existing fields...
"selectedATPIds" to selectedATPIds,
"consentOrPay" to consentOrPay?.serialize(),
"mandatoryLabel" to getMandatoryLabelCompat(),
).toWritableMap()
}// iOS bridge (defensive read of optional mandatoryLabel using Key-Value Coding)
extension TCF2Settings {
fileprivate var mandatoryLabelCompat: String? {
// Using value(forKey:) to avoid hard dependency on the property at compile time
return try? self.value(forKey: "mandatoryLabel") as? String ?? nil
}
func toDictionary() -> NSDictionary {
return [
// ...existing fields...
"selectedATPIds": self.selectedATPIds,
"resurfacePeriod": self.resurfacePeriod,
"consentOrPay": self.consentOrPay?.toDictionary() as Any,
"mandatoryLabel": self.mandatoryLabelCompat as Any,
]
}
}// JS model: make mandatoryLabel optional and default it in the constructor
export class TCF2Settings {
// ...existing fields...
mandatoryLabel?: string;
constructor(
// ...existing params...
consentOrPay?: TCF2ConsentOrPaySettings,
mandatoryLabel?: string,
) {
// ...existing assignments...
this.consentOrPay = consentOrPay;
this.mandatoryLabel = mandatoryLabel ?? 'Mandatory';
}
}
// Example Jest assertion on the JS side
expect(cmpData.settings.tcf2.mandatoryLabel ?? 'Mandatory').toBe('Mandatory');// Sample app test mock (iOS) – ensure mandatoryLabel is provided when available
extension TCF2Settings {
static func mock() -> TCF2Settings {
let settings = TCF2Settings(
// existing arguments...
)
settings.setValue("Mandatory", forKey: "mandatoryLabel")
return settings
}
}// Android test mock – set mandatoryLabel when the property exists
val fakeTCF2Settings = TCF2Settings(
// existing args...
).apply {
runCatching {
javaClass.getMethod("setMandatoryLabel", String::class.java)
.invoke(this, "Mandatory")
}
} |
CI Feedback 🧐A test triggered by this PR failed. Here is an AI-generated analysis of the failure:
|
No description provided.