diff --git a/src/main/java/org/prebid/server/bidder/flipp/FlippBidder.java b/src/main/java/org/prebid/server/bidder/flipp/FlippBidder.java index 7fc42804347..dedd8399f1b 100644 --- a/src/main/java/org/prebid/server/bidder/flipp/FlippBidder.java +++ b/src/main/java/org/prebid/server/bidder/flipp/FlippBidder.java @@ -70,6 +70,8 @@ public class FlippBidder implements Bidder { private static final Set AD_TYPES = Set.of(4309, 641); private static final Set DTX_TYPES = Set.of(5061); private static final String EXT_REQUEST_TRANSMIT_EIDS = "transmitEids"; + private static final int DEFAULT_STANDARD_HEIGHT = 2400; + private static final int DEFAULT_COMPACT_HEIGHT = 600; private final String endpointUrl; private final JacksonMapper mapper; @@ -144,7 +146,7 @@ private static PrebidRequest createPrebidRequest(Imp imp, ExtImpFlipp extImp) { final Format format = Optional.ofNullable(imp.getBanner()) .map(Banner::getFormat) .filter(CollectionUtils::isNotEmpty) - .map(formats -> formats.getFirst()) + .map(List::getFirst) .orElse(null); return PrebidRequest.builder() @@ -272,32 +274,38 @@ public final Result> makeBids(BidderCall ht } } - private static List extractBids(CampaignResponseBody campaignResponseBody, BidRequest bidRequest) { + private List extractBids(CampaignResponseBody campaignResponseBody, BidRequest bidRequest) { return Optional.ofNullable(campaignResponseBody) .map(CampaignResponseBody::getDecisions) .map(Decisions::getInline) .stream() .flatMap(Collection::stream) - .filter(inline -> isInlineValid(bidRequest, inline)) - .map(inline -> BidderBid.of(constructBid(inline), BidType.banner, "USD")) + .map(inline -> makeBid(inline, getCorrespondingImp(bidRequest, inline))) + .filter(Objects::nonNull) .toList(); } - private static boolean isInlineValid(BidRequest bidRequest, Inline inline) { + private static Imp getCorrespondingImp(BidRequest bidRequest, Inline inline) { final String requestId = Optional.ofNullable(inline) .map(Inline::getPrebid) .map(Prebid::getRequestId) .orElse(null); - return requestId != null && bidRequest.getImp().stream() - .map(Imp::getId) - .anyMatch(impId -> impId.equals(requestId)); + return requestId != null + ? bidRequest.getImp().stream().filter(imp -> imp.getId().equals(requestId)).findFirst().orElse(null) + : null; } - private static Bid constructBid(Inline inline) { + private BidderBid makeBid(Inline inline, Imp imp) { + return imp == null + ? null + : BidderBid.of(constructBid(inline, parseImpExt(imp)), BidType.banner, "USD"); + } + + private static Bid constructBid(Inline inline, ExtImpFlipp extImp) { final Prebid prebid = inline.getPrebid(); final Data data = Optional.ofNullable(inline.getContents()) - .map(content -> content.getFirst()) + .map(List::getFirst) .map(Content::getData) .orElse(null); @@ -308,7 +316,21 @@ private static Bid constructBid(Inline inline) { .id(Integer.toString(inline.getAdId())) .impid(prebid.getRequestId()) .w(data != null ? data.getWidth() : null) - .h(data != null ? 0 : null) + .h(resolveHeight(data, extImp)) .build(); } + + private static Integer resolveHeight(Data data, ExtImpFlipp extImp) { + final boolean startCompact = Optional.ofNullable(extImp) + .map(ExtImpFlipp::getOptions) + .map(ExtImpFlippOptions::getStartCompact) + .orElse(false); + + return Optional.ofNullable(data) + .map(Data::getCustomData) + .map(customData -> customData.get(startCompact ? "compactHeight" : "standardHeight")) + .filter(JsonNode::isNumber) + .map(JsonNode::asInt) + .orElse(startCompact ? DEFAULT_COMPACT_HEIGHT : DEFAULT_STANDARD_HEIGHT); + } } diff --git a/src/test/java/org/prebid/server/bidder/flipp/FlippBidderTest.java b/src/test/java/org/prebid/server/bidder/flipp/FlippBidderTest.java index a0aadb48e92..74bf3474a59 100644 --- a/src/test/java/org/prebid/server/bidder/flipp/FlippBidderTest.java +++ b/src/test/java/org/prebid/server/bidder/flipp/FlippBidderTest.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.node.BooleanNode; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.iab.openrtb.request.Banner; import com.iab.openrtb.request.BidRequest; import com.iab.openrtb.request.Device; @@ -917,15 +918,101 @@ public void makeBidsShouldPopulateBidWidthWithNullWhenInlineContentsDataWidthEmp } @Test - public void makeBidsShouldPopulateBidHeightWithZeroWhenInlineContentsIsPresent() throws JsonProcessingException { + public void makeBidsShouldPopulateBidDefaultStandardHeightWhenInlineCustomDataIsAbsent() + throws JsonProcessingException { + // given - final BidRequest bidRequest = givenBidRequest(identity()); + final BidRequest bidRequest = givenBidRequest(givenImp(identity(), extImp -> extImp + .options(ExtImpFlippOptions.of(false, null, null)))); + + final ObjectNode customData = mapper.createObjectNode() + .put("compactHeight", 20) + .put("standardHeight", 30); - // and final BidderCall httpCall = givenHttpCall(CampaignRequestBody.builder().build(), - mapper.writeValueAsString(givenCampaignResponseBody(inlineBuilder -> - inlineBuilder.contents(singletonList( - Content.of("any", "custom", Data.of(null, 10, 20), "type")))))); + mapper.writeValueAsString(givenCampaignResponseBody(inlineBuilder -> inlineBuilder + .contents(singletonList(Content.of( + "any", "custom", Data.of(null, 10, 20), "type")))))); + + // when + final Result> result = target.makeBids(httpCall, bidRequest); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).hasSize(1) + .extracting(BidderBid::getBid) + .extracting(Bid::getH) + .containsExactly(2400); + } + + @Test + public void makeBidsShouldPopulateBidDefaultCompactHeightWhenInlineCustomDataIsAbsent() + throws JsonProcessingException { + + // given + final BidRequest bidRequest = givenBidRequest(givenImp(identity(), extImp -> extImp + .options(ExtImpFlippOptions.of(true, null, null)))); + + final BidderCall httpCall = givenHttpCall(CampaignRequestBody.builder().build(), + mapper.writeValueAsString(givenCampaignResponseBody(inlineBuilder -> inlineBuilder + .contents(singletonList(Content.of( + "any", "custom", Data.of(null, 10, 20), "type")))))); + + // when + final Result> result = target.makeBids(httpCall, bidRequest); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).hasSize(1) + .extracting(BidderBid::getBid) + .extracting(Bid::getH) + .containsExactly(600); + } + + @Test + public void makeBidsShouldPopulateBidCompactHeightFromCustomDataWhenStartCompactIsTrue() + throws JsonProcessingException { + + // given + final BidRequest bidRequest = givenBidRequest(givenImp(identity(), extImp -> extImp + .options(ExtImpFlippOptions.of(true, null, null)))); + + final ObjectNode customData = mapper.createObjectNode() + .put("compactHeight", 20) + .put("standardHeight", 30); + + final BidderCall httpCall = givenHttpCall(CampaignRequestBody.builder().build(), + mapper.writeValueAsString(givenCampaignResponseBody(inlineBuilder -> inlineBuilder + .contents(singletonList(Content.of( + "any", "custom", Data.of(customData, 10, 20), "type")))))); + + // when + final Result> result = target.makeBids(httpCall, bidRequest); + + // then + assertThat(result.getErrors()).isEmpty(); + assertThat(result.getValue()).hasSize(1) + .extracting(BidderBid::getBid) + .extracting(Bid::getH) + .containsExactly(20); + } + + @Test + public void makeBidsShouldPopulateBidStandardHeightFromCustomDataWhenStartCompactIsFalse() + throws JsonProcessingException { + + // given + final BidRequest bidRequest = givenBidRequest(givenImp(identity(), extImp -> extImp + .options(ExtImpFlippOptions.of(false, null, null)))); + + final ObjectNode customData = mapper.createObjectNode() + .put("compactHeight", 20) + .put("standardHeight", 30); + + final BidderCall httpCall = givenHttpCall(CampaignRequestBody.builder().build(), + mapper.writeValueAsString(givenCampaignResponseBody(inlineBuilder -> inlineBuilder + .contents(singletonList(Content.of( + "any", "custom", Data.of(customData, 10, 20), "type")))))); // when final Result> result = target.makeBids(httpCall, bidRequest); @@ -935,7 +1022,7 @@ public void makeBidsShouldPopulateBidHeightWithZeroWhenInlineContentsIsPresent() assertThat(result.getValue()).hasSize(1) .extracting(BidderBid::getBid) .extracting(Bid::getH) - .containsExactly(0); + .containsExactly(30); } @Test @@ -1011,14 +1098,27 @@ private static BidRequest givenBidRequest(UnaryOperator impCusto return givenBidRequest(identity(), impCustomizer); } + private static BidRequest givenBidRequest(Imp givenImp) { + return BidRequest.builder() + .device(Device.builder().ip("anyId").build()) + .imp(singletonList(givenImp)) + .build(); + } + private static Imp givenImp(UnaryOperator impCustomizer) { + return givenImp(impCustomizer, identity()); + } + + private static Imp givenImp(UnaryOperator impCustomizer, + UnaryOperator extImpBuilder) { + return impCustomizer.apply(Imp.builder() .id("123") .banner(Banner.builder().w(23).h(25).build()) - .ext(mapper.valueToTree(ExtPrebid.of(null, ExtImpFlipp.builder() + .ext(mapper.valueToTree(ExtPrebid.of(null, extImpBuilder.apply(ExtImpFlipp.builder() .publisherNameIdentifier("publisherName") .creativeType("Any") - .zoneIds(List.of(12)) + .zoneIds(List.of(12))) .build())))) .build(); } diff --git a/src/test/resources/org/prebid/server/it/openrtb2/flipp/test-auction-flipp-response.json b/src/test/resources/org/prebid/server/it/openrtb2/flipp/test-auction-flipp-response.json index da840110dcf..a79558cbd9f 100644 --- a/src/test/resources/org/prebid/server/it/openrtb2/flipp/test-auction-flipp-response.json +++ b/src/test/resources/org/prebid/server/it/openrtb2/flipp/test-auction-flipp-response.json @@ -11,7 +11,7 @@ "adm": "creativeContent", "crid": "81325690", "w": 300, - "h": 0, + "h": 600, "ext": { "origbidcpm": 12.34, "origbidcur": "USD",