-
Notifications
You must be signed in to change notification settings - Fork 187
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Tests: Cover DSA fields and validation (#2939)
- Loading branch information
1 parent
062a7b2
commit bcc291c
Showing
7 changed files
with
378 additions
and
0 deletions.
There are no files selected for viewing
16 changes: 16 additions & 0 deletions
16
src/test/groovy/org/prebid/server/functional/model/request/auction/DsaTransparency.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package org.prebid.server.functional.model.request.auction | ||
|
||
import groovy.transform.ToString | ||
import org.prebid.server.functional.util.PBSUtils | ||
|
||
@ToString(includeNames = true, ignoreNulls = true) | ||
class DsaTransparency { | ||
|
||
String domain | ||
List<Integer> params | ||
|
||
static DsaTransparency getDefaultRegsDsaTransparency() { | ||
new DsaTransparency(domain: PBSUtils.randomString) | ||
} | ||
} | ||
|
25 changes: 25 additions & 0 deletions
25
src/test/groovy/org/prebid/server/functional/model/request/auction/RegsDsa.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package org.prebid.server.functional.model.request.auction | ||
|
||
import com.fasterxml.jackson.databind.PropertyNamingStrategies | ||
import com.fasterxml.jackson.databind.annotation.JsonNaming | ||
import groovy.transform.ToString | ||
import org.prebid.server.functional.util.PBSUtils | ||
|
||
@JsonNaming(PropertyNamingStrategies.LowerCaseStrategy) | ||
@ToString(includeNames = true, ignoreNulls = true) | ||
class RegsDsa { | ||
|
||
Integer required | ||
Integer pubRender | ||
Integer dataToPub | ||
List<DsaTransparency> transparency | ||
|
||
static RegsDsa getDefaultRegsDsa(ReqsDsaRequiredType required) { | ||
new RegsDsa( | ||
required: required.value, | ||
pubRender: PBSUtils.getRandomNumber(0, 2), | ||
dataToPub: PBSUtils.getRandomNumber(0, 2), | ||
transparency: [DsaTransparency.defaultRegsDsaTransparency] | ||
) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,4 +11,6 @@ class RegsExt { | |
Integer gdpr | ||
String usPrivacy | ||
String gpc | ||
RegsDsa dsa | ||
|
||
} |
15 changes: 15 additions & 0 deletions
15
...test/groovy/org/prebid/server/functional/model/request/auction/ReqsDsaRequiredType.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package org.prebid.server.functional.model.request.auction | ||
|
||
import com.fasterxml.jackson.annotation.JsonValue | ||
|
||
enum ReqsDsaRequiredType { | ||
|
||
NOT_REQUIRED(0), SUPPORTED(1), REQUIRED(2), REQUIRED_PUBLISHER_ONLINE_PLATFORM(3) | ||
|
||
@JsonValue | ||
final Integer value | ||
|
||
ReqsDsaRequiredType(Integer value) { | ||
this.value = value | ||
} | ||
} |
4 changes: 4 additions & 0 deletions
4
src/test/groovy/org/prebid/server/functional/model/response/auction/BidExt.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,14 @@ | ||
package org.prebid.server.functional.model.response.auction | ||
|
||
import groovy.transform.ToString | ||
import org.prebid.server.functional.model.Currency | ||
|
||
@ToString(includeNames = true, ignoreNulls = true) | ||
class BidExt { | ||
|
||
Prebid prebid | ||
BigDecimal origbidcpm | ||
Currency origbidcur | ||
BidExtDsa dsa | ||
|
||
} |
23 changes: 23 additions & 0 deletions
23
src/test/groovy/org/prebid/server/functional/model/response/auction/BidExtDsa.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package org.prebid.server.functional.model.response.auction | ||
|
||
import groovy.transform.ToString | ||
import org.prebid.server.functional.model.request.auction.DsaTransparency | ||
import org.prebid.server.functional.util.PBSUtils | ||
|
||
@ToString(includeNames = true, ignoreNulls = true) | ||
class BidExtDsa { | ||
|
||
String behalf | ||
String paid | ||
List<DsaTransparency> transparency | ||
Integer adrender | ||
|
||
static BidExtDsa getDefaultBidExtDsa() { | ||
new BidExtDsa( | ||
behalf: PBSUtils.randomString, | ||
paid: PBSUtils.randomString, | ||
adrender: PBSUtils.getRandomNumber(0, 2), | ||
transparency: [DsaTransparency.defaultRegsDsaTransparency] | ||
) | ||
} | ||
} |
293 changes: 293 additions & 0 deletions
293
src/test/groovy/org/prebid/server/functional/tests/DsaSpec.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,293 @@ | ||
package org.prebid.server.functional.tests | ||
|
||
import org.prebid.server.functional.model.bidder.BidderName | ||
import org.prebid.server.functional.model.db.StoredRequest | ||
import org.prebid.server.functional.model.request.amp.AmpRequest | ||
import org.prebid.server.functional.model.request.auction.BidRequest | ||
import org.prebid.server.functional.model.request.auction.RegsDsa | ||
import org.prebid.server.functional.model.request.auction.ReqsDsaRequiredType | ||
import org.prebid.server.functional.model.response.auction.BidExt | ||
import org.prebid.server.functional.model.response.auction.BidExtDsa | ||
import org.prebid.server.functional.model.response.auction.BidResponse | ||
|
||
import static org.prebid.server.functional.model.response.auction.ErrorType.GENERIC | ||
|
||
class DsaSpec extends BaseSpec { | ||
|
||
def "AMP request should send DSA to bidder and succeed when DSA is not required"() { | ||
given: "Default AmpRequest" | ||
def ampRequest = AmpRequest.defaultAmpRequest | ||
def dsa = RegsDsa.getDefaultRegsDsa(dsaRequired) | ||
|
||
and: "Stored default bid request with DSA" | ||
def ampStoredRequest = BidRequest.defaultBidRequest.tap { | ||
regs.ext.dsa = dsa | ||
setAccountId(ampRequest.account) | ||
} | ||
|
||
and: "Save storedRequest into DB" | ||
def storedRequest = StoredRequest.getStoredRequest(ampRequest, ampStoredRequest) | ||
storedRequestDao.save(storedRequest) | ||
|
||
and: "Default bidder response with DSA" | ||
def bidResponse = BidResponse.getDefaultBidResponse(ampStoredRequest).tap { | ||
seatbid[0].bid[0].ext = bidExt | ||
} | ||
|
||
and: "Set bidder response" | ||
bidder.setResponse(ampStoredRequest.id, bidResponse) | ||
|
||
when: "PBS processes amp request" | ||
def response = defaultPbsService.sendAmpRequest(ampRequest) | ||
|
||
then: "Bidder request should contain DSA" | ||
def bidderRequests = bidder.getBidderRequest(ampStoredRequest.id) | ||
verifyAll { | ||
bidderRequests.regs.ext.dsa.required == dsa.required | ||
bidderRequests.regs.ext.dsa.dataToPub == dsa.dataToPub | ||
bidderRequests.regs.ext.dsa.pubRender == dsa.pubRender | ||
bidderRequests.regs.ext.dsa.transparency[0].domain == dsa.transparency[0].domain | ||
bidderRequests.regs.ext.dsa.transparency[0].params == dsa.transparency[0].params | ||
} | ||
|
||
and: "Bidder response should not contain DSA" | ||
def bidderResponse = decode(response.ext.debug.httpcalls.get(BidderName.GENERIC.value)[0].responseBody, BidResponse) | ||
assert !bidderResponse.seatbid[0].bid[0].ext?.dsa | ||
|
||
and: "PBS should not log warning" | ||
assert !response.ext.warnings | ||
assert !response.ext.errors | ||
|
||
where: | ||
dsaRequired | bidExt | ||
ReqsDsaRequiredType.NOT_REQUIRED | null | ||
ReqsDsaRequiredType.SUPPORTED | new BidExt(dsa: null) | ||
} | ||
|
||
def "AMP request should send DSA to bidder and always succeed when bidder returns DSA"() { | ||
given: "Default AmpRequest" | ||
def ampRequest = AmpRequest.defaultAmpRequest | ||
def dsa = RegsDsa.getDefaultRegsDsa(dsaRequired) | ||
|
||
and: "Stored default bid request with DSA" | ||
def ampStoredRequest = BidRequest.defaultBidRequest.tap { | ||
regs.ext.dsa = dsa | ||
setAccountId(ampRequest.account) | ||
} | ||
|
||
and: "Save storedRequest into DB" | ||
def storedRequest = StoredRequest.getStoredRequest(ampRequest, ampStoredRequest) | ||
storedRequestDao.save(storedRequest) | ||
|
||
and: "Default bidder response with DSA" | ||
def bidDsa = BidExtDsa.getDefaultBidExtDsa() | ||
def bidResponse = BidResponse.getDefaultBidResponse(ampStoredRequest).tap { | ||
seatbid[0].bid[0].ext = new BidExt(dsa: bidDsa) | ||
} | ||
|
||
and: "Set bidder response" | ||
bidder.setResponse(ampStoredRequest.id, bidResponse) | ||
|
||
when: "PBS processes amp request" | ||
def response = defaultPbsService.sendAmpRequest(ampRequest) | ||
|
||
then: "Bidder request should contain DSA" | ||
def bidderRequests = bidder.getBidderRequest(ampStoredRequest.id) | ||
verifyAll { | ||
bidderRequests.regs.ext.dsa.required == dsa.required | ||
bidderRequests.regs.ext.dsa.dataToPub == dsa.dataToPub | ||
bidderRequests.regs.ext.dsa.pubRender == dsa.pubRender | ||
bidderRequests.regs.ext.dsa.transparency[0].domain == dsa.transparency[0].domain | ||
bidderRequests.regs.ext.dsa.transparency[0].params == dsa.transparency[0].params | ||
} | ||
|
||
and: "Bidder response should contain DSA" | ||
def bidderResponse = decode(response.ext.debug.httpcalls.get(BidderName.GENERIC.value)[0].responseBody, BidResponse) | ||
def actualDsa = bidderResponse.seatbid[0].bid[0].ext.dsa | ||
verifyAll { | ||
actualDsa.transparency[0].domain == bidDsa.transparency[0].domain | ||
actualDsa.transparency[0].params == bidDsa.transparency[0].params | ||
actualDsa.adrender == bidDsa.adrender | ||
actualDsa.behalf == bidDsa.behalf | ||
actualDsa.paid == bidDsa.paid | ||
} | ||
|
||
and: "PBS should not log warning" | ||
assert !response.ext.warnings | ||
assert !response.ext.errors | ||
|
||
where: | ||
dsaRequired << ReqsDsaRequiredType.values() | ||
} | ||
|
||
def "AMP request should send DSA to bidder and fail on response when DSA is required and bidder does not return DSA"() { | ||
given: "Default AmpRequest" | ||
def ampRequest = AmpRequest.defaultAmpRequest | ||
def dsa = RegsDsa.getDefaultRegsDsa(dsaRequired) | ||
|
||
and: "Stored default bid request with DSA" | ||
def ampStoredRequest = BidRequest.defaultBidRequest.tap { | ||
regs.ext.dsa = dsa | ||
setAccountId(ampRequest.account) | ||
} | ||
|
||
and: "Save storedRequest into DB" | ||
def storedRequest = StoredRequest.getStoredRequest(ampRequest, ampStoredRequest) | ||
storedRequestDao.save(storedRequest) | ||
|
||
and: "Default bidder response with DSA" | ||
def bidResponse = BidResponse.getDefaultBidResponse(ampStoredRequest).tap { | ||
seatbid[0].bid[0].ext = bidExt | ||
} | ||
|
||
and: "Set bidder response" | ||
bidder.setResponse(ampStoredRequest.id, bidResponse) | ||
|
||
when: "PBS processes amp request" | ||
def response = defaultPbsService.sendAmpRequest(ampRequest) | ||
|
||
then: "Bidder request should contain DSA" | ||
def bidderRequests = bidder.getBidderRequest(ampStoredRequest.id) | ||
verifyAll { | ||
bidderRequests.regs.ext.dsa.required == dsa.required | ||
bidderRequests.regs.ext.dsa.dataToPub == dsa.dataToPub | ||
bidderRequests.regs.ext.dsa.pubRender == dsa.pubRender | ||
bidderRequests.regs.ext.dsa.transparency[0].domain == dsa.transparency[0].domain | ||
bidderRequests.regs.ext.dsa.transparency[0].params == dsa.transparency[0].params | ||
} | ||
|
||
and: "Bidder response should not contain DSA" | ||
def bidderResponse = decode(response.ext.debug.httpcalls.get(BidderName.GENERIC.value)[0].responseBody, BidResponse) | ||
assert !bidderResponse.seatbid[0].bid[0].ext?.dsa | ||
|
||
and: "Response should contain error" | ||
def expectedBidId = bidResponse.seatbid[0].bid[0].id | ||
assert response.ext?.errors[GENERIC]*.code == [5] | ||
assert response.ext?.errors[GENERIC]*.message == ["BidId `$expectedBidId` validation messages: Error: Bid \"$expectedBidId\" missing DSA"] | ||
|
||
where: | ||
dsaRequired | bidExt | ||
ReqsDsaRequiredType.REQUIRED | new BidExt(dsa: null) | ||
ReqsDsaRequiredType.REQUIRED_PUBLISHER_ONLINE_PLATFORM | null | ||
} | ||
|
||
def "Auction request should send DSA to bidder and succeeds when DSA is not required and bidder does not return DSA"() { | ||
given: "Default bid request with DSA" | ||
def dsa = RegsDsa.getDefaultRegsDsa(dsaRequired) | ||
def bidRequest = BidRequest.defaultBidRequest.tap { | ||
regs.ext.dsa = dsa | ||
} | ||
|
||
and: "Default bidder response with DSA" | ||
def bidResponse = BidResponse.getDefaultBidResponse(bidRequest).tap { | ||
seatbid[0].bid[0].ext = new BidExt(dsa: null) | ||
} | ||
|
||
and: "Set bidder response" | ||
bidder.setResponse(bidRequest.id, bidResponse) | ||
|
||
when: "PBS processes auction request" | ||
def response = defaultPbsService.sendAuctionRequest(bidRequest) | ||
|
||
then: "Bidder request should contain DSA" | ||
def bidderRequests = bidder.getBidderRequest(bidRequest.id) | ||
verifyAll { | ||
bidderRequests.regs.ext.dsa.required == dsa.required | ||
bidderRequests.regs.ext.dsa.dataToPub == dsa.dataToPub | ||
bidderRequests.regs.ext.dsa.pubRender == dsa.pubRender | ||
bidderRequests.regs.ext.dsa.transparency[0].domain == dsa.transparency[0].domain | ||
bidderRequests.regs.ext.dsa.transparency[0].params == dsa.transparency[0].params | ||
} | ||
|
||
and: "DSA is not returned" | ||
assert !response.seatbid[0].bid[0].ext.dsa | ||
|
||
where: | ||
dsaRequired << [ReqsDsaRequiredType.NOT_REQUIRED, ReqsDsaRequiredType.SUPPORTED] | ||
} | ||
|
||
def "Auction request should send DSA to bidder and always succeed when bidder returns DSA"() { | ||
given: "Default bid request with DSA" | ||
def dsa = RegsDsa.getDefaultRegsDsa(dsaRequired) | ||
def bidRequest = BidRequest.defaultBidRequest.tap { | ||
regs.ext.dsa = dsa | ||
} | ||
|
||
and: "Default bidder response with DSA" | ||
def bidDsa = BidExtDsa.getDefaultBidExtDsa() | ||
def bidResponse = BidResponse.getDefaultBidResponse(bidRequest).tap { | ||
seatbid[0].bid[0].ext = new BidExt(dsa: bidDsa) | ||
} | ||
|
||
and: "Set bidder response" | ||
bidder.setResponse(bidRequest.id, bidResponse) | ||
|
||
when: "PBS processes auction request" | ||
def response = defaultPbsService.sendAuctionRequest(bidRequest) | ||
|
||
then: "Bidder request should contain DSA" | ||
def bidderRequests = bidder.getBidderRequest(bidRequest.id) | ||
verifyAll { | ||
bidderRequests.regs.ext.dsa.required == dsa.required | ||
bidderRequests.regs.ext.dsa.dataToPub == dsa.dataToPub | ||
bidderRequests.regs.ext.dsa.pubRender == dsa.pubRender | ||
bidderRequests.regs.ext.dsa.transparency[0].domain == dsa.transparency[0].domain | ||
bidderRequests.regs.ext.dsa.transparency[0].params == dsa.transparency[0].params | ||
} | ||
|
||
and: "DSA is not returned" | ||
def actualDsa = response.seatbid[0].bid[0].ext.dsa | ||
verifyAll { | ||
actualDsa.transparency[0].domain == bidDsa.transparency[0].domain | ||
actualDsa.transparency[0].params == bidDsa.transparency[0].params | ||
actualDsa.adrender == bidDsa.adrender | ||
actualDsa.behalf == bidDsa.behalf | ||
actualDsa.paid == bidDsa.paid | ||
} | ||
|
||
where: | ||
dsaRequired << ReqsDsaRequiredType.values() | ||
} | ||
|
||
def "Auction request should send DSA to bidder and fail on response when DSA is required and bidder does not return DSA"() { | ||
given: "Default bid request with DSA" | ||
def dsa = RegsDsa.getDefaultRegsDsa(dsaRequired) | ||
def bidRequest = BidRequest.defaultBidRequest.tap { | ||
regs.ext.dsa = dsa | ||
} | ||
|
||
and: "Default bidder response with DSA" | ||
def bidResponse = BidResponse.getDefaultBidResponse(bidRequest).tap { | ||
seatbid[0].bid[0].ext = bidExt | ||
} | ||
|
||
and: "Set bidder response" | ||
bidder.setResponse(bidRequest.id, bidResponse) | ||
|
||
when: "PBS processes auction request" | ||
def response = defaultPbsService.sendAuctionRequest(bidRequest) | ||
|
||
then: "Bidder request should contain DSA" | ||
def bidderRequests = bidder.getBidderRequest(bidRequest.id) | ||
verifyAll { | ||
bidderRequests.regs.ext.dsa.required == dsa.required | ||
bidderRequests.regs.ext.dsa.dataToPub == dsa.dataToPub | ||
bidderRequests.regs.ext.dsa.pubRender == dsa.pubRender | ||
bidderRequests.regs.ext.dsa.transparency[0].domain == dsa.transparency[0].domain | ||
bidderRequests.regs.ext.dsa.transparency[0].params == dsa.transparency[0].params | ||
} | ||
|
||
and: "Response should contain error" | ||
def expectedBidId = bidResponse.seatbid[0].bid[0].id | ||
verifyAll { | ||
response.seatbid.isEmpty() | ||
response.ext?.errors[GENERIC]*.code == [5] | ||
response.ext?.errors[GENERIC]*.message == ["BidId `$expectedBidId` validation messages: Error: Bid \"$expectedBidId\" missing DSA"] | ||
} | ||
|
||
where: | ||
dsaRequired | bidExt | ||
ReqsDsaRequiredType.REQUIRED | new BidExt(dsa: null) | ||
ReqsDsaRequiredType.REQUIRED_PUBLISHER_ONLINE_PLATFORM | null | ||
} | ||
} |