Skip to content

Commit 17d7b31

Browse files
sunnywucursoragent
andcommitted
Add test to verify consent passes when PreciseGeolocation special feature is missing
Ensures TCF consent validation does not require SF1 (PreciseGeolocationData) opt-in. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent de4084f commit 17d7b31

1 file changed

Lines changed: 53 additions & 0 deletions

File tree

src/test/java/com/uid2/operator/EUIDOperatorVerticleTest.java

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,17 @@
22

33
import org.junit.jupiter.api.Test;
44

5+
import com.iabtcf.encoder.TCStringEncoder;
6+
import com.iabtcf.utils.BitSetIntIterable;
57
import com.uid2.operator.model.IdentityScope;
68
import com.uid2.shared.auth.Role;
79

810
import io.vertx.core.Vertx;
911
import io.vertx.core.json.JsonObject;
1012
import io.vertx.junit5.VertxTestContext;
1113

14+
import java.time.Instant;
15+
1216
import static org.junit.jupiter.api.Assertions.*;
1317

1418
class EUIDOperatorVerticleTest extends UIDOperatorVerticleTest {
@@ -75,5 +79,54 @@ void noContentOnInsufficientTcfConsent(Vertx vertx, VertxTestContext testContext
7579
testContext.completeNow();
7680
});
7781
}
82+
83+
@Test
84+
void consentPassesWhenPreciseGeolocationSpecialFeatureIsMissing(Vertx vertx, VertxTestContext testContext) {
85+
final int clientSiteId = 201;
86+
fakeAuth(clientSiteId, Role.GENERATOR);
87+
setupSalts();
88+
setupKeys();
89+
90+
final String emailAddress = "test@uid2.com";
91+
final JsonObject v2Payload = new JsonObject();
92+
v2Payload.put("email", emailAddress);
93+
// TCF string with all required purposes but WITHOUT PreciseGeolocation special feature (feature 1)
94+
String tcfStringWithoutPreciseGeolocation = createTcfConsentString(
95+
new int[] { 21 }, // vendor consent
96+
new int[] { 21 }, // vendor LI
97+
new int[] { 1, 3, 4 }, // purpose consents (1, 3, 4)
98+
new int[] { 2, 7, 10 }, // purpose LI (2, 7, 10)
99+
new int[] {} // NO special features - PreciseGeolocation (1) is missing
100+
);
101+
v2Payload.put("tcf_consent_string", tcfStringWithoutPreciseGeolocation);
102+
sendTokenGenerate(vertx, v2Payload, 200, json -> {
103+
assertTrue(json.containsKey("body"));
104+
assertEquals("success", json.getString("status"));
105+
testContext.completeNow();
106+
});
107+
}
108+
109+
private String createTcfConsentString(int[] vendorConsent, int[] vendorLI, int[] purposesConsent, int[] purposesLI, int[] specialFeatureOptIns) {
110+
return TCStringEncoder.newBuilder()
111+
.version(2)
112+
.created(Instant.now())
113+
.lastUpdated(Instant.now())
114+
.cmpId(1)
115+
.cmpVersion(12)
116+
.consentScreen(1)
117+
.consentLanguage("FR")
118+
.vendorListVersion(2)
119+
.tcfPolicyVersion(1)
120+
.isServiceSpecific(true)
121+
.useNonStandardStacks(false)
122+
.addSpecialFeatureOptIns(BitSetIntIterable.from(specialFeatureOptIns))
123+
.publisherCC("DE")
124+
.addVendorConsent(BitSetIntIterable.from(vendorConsent))
125+
.addVendorLegitimateInterest(BitSetIntIterable.from(vendorLI))
126+
.purposeOneTreatment(true)
127+
.addPurposesConsent(BitSetIntIterable.from(purposesConsent))
128+
.addPurposesLITransparency(BitSetIntIterable.from(purposesLI))
129+
.encode();
130+
}
78131
}
79132

0 commit comments

Comments
 (0)