From f6930803eb5fad240ba17c137dcc46f78b77e2fc Mon Sep 17 00:00:00 2001 From: Anna Beddow Date: Tue, 28 Jul 2026 09:52:12 +0100 Subject: [PATCH 1/4] Bump FAPI to "37.0.0" This version includes the editorial ab test models --- project/Dependencies.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 6e156fdf576..9cfe8266b2f 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -6,7 +6,7 @@ object Dependencies { val identityLibVersion = "4.31" val awsVersion = "2.46.18" val capiVersion = "47.0.0" - val faciaVersion = "34.0.0" + val faciaVersion = "37.0.0" val dispatchVersion = "0.13.1" val romeVersion = "1.0" val jerseyVersion = "1.19.4" From e250cd222c3d03fe42c4ab6a4dfff0d11f2d50cb Mon Sep 17 00:00:00 2001 From: Anna Beddow Date: Tue, 28 Jul 2026 18:59:12 +0100 Subject: [PATCH 2/4] Update fapi and add tests field to content models --- applications/app/services/NewspaperQuery.scala | 1 + common/app/model/PressedProperties.scala | 3 +++ common/app/services/FaciaContentConvert.scala | 1 + common/test/layout/FrontTest.scala | 1 + 4 files changed, 6 insertions(+) diff --git a/applications/app/services/NewspaperQuery.scala b/applications/app/services/NewspaperQuery.scala index ca18510dd47..f0a76fc7dcc 100644 --- a/applications/app/services/NewspaperQuery.scala +++ b/applications/app/services/NewspaperQuery.scala @@ -201,6 +201,7 @@ class NewspaperQuery(contentApiClient: ContentApiClient) extends Dates with GuLo kicker = None, brandingByEdition = Map.empty, mediaAtom = None, + tests = None, ) LinkSnap.make(fapiSnap) } diff --git a/common/app/model/PressedProperties.scala b/common/app/model/PressedProperties.scala index 72f107b79d8..dd4112db92e 100644 --- a/common/app/model/PressedProperties.scala +++ b/common/app/model/PressedProperties.scala @@ -2,6 +2,7 @@ package model.pressed import com.gu.facia.api.utils.FaciaContentUtils import com.gu.facia.api.{models => fapi, utils => fapiutils} +import com.gu.facia.client.models.Test import common.Edition import common.commercial.EditionBranding import services.NewsletterData @@ -34,6 +35,7 @@ final case class PressedProperties( editionBrandings: Option[Seq[EditionBranding]], atomId: Option[String], newsletterData: Option[NewsletterData] = None, + tests: Option[List[Test]] = None, ) { lazy val isPaidFor: Boolean = editionBrandings.exists( _.exists(branding => branding.branding.exists(_.isPaid) && branding.edition == Edition.defaultEdition), @@ -74,6 +76,7 @@ object PressedProperties { Edition.byId(editionId) map (EditionBranding(_, branding)) }.toSeq), atomId = FaciaContentUtils.atomId(content), + tests = content.tests, ) } diff --git a/common/app/services/FaciaContentConvert.scala b/common/app/services/FaciaContentConvert.scala index 88b9676e7c8..494a52c29f9 100644 --- a/common/app/services/FaciaContentConvert.scala +++ b/common/app/services/FaciaContentConvert.scala @@ -41,6 +41,7 @@ object FaciaContentConvert { .toMap, atomId = None, mediaAtom = None, + tests = None, ) PressedContent.make(curated, false) diff --git a/common/test/layout/FrontTest.scala b/common/test/layout/FrontTest.scala index 8e42c247d71..43ac1cb22c6 100644 --- a/common/test/layout/FrontTest.scala +++ b/common/test/layout/FrontTest.scala @@ -64,6 +64,7 @@ class FrontTest extends AnyFlatSpec with Matchers with GuiceOneAppPerSuite { brandingByEdition = Map.empty, atomId = None, mediaAtom = None, + tests = None, ) LatestSnap.make(fapiLatestSnap) From 850f9f5456d0a3d2a935d3504c31b6df4dfbd472 Mon Sep 17 00:00:00 2001 From: Anna Beddow Date: Mon, 3 Aug 2026 15:37:17 +0100 Subject: [PATCH 3/4] Add tests to lite json --- facia/app/controllers/front/FapiFrontJsonMinimal.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/facia/app/controllers/front/FapiFrontJsonMinimal.scala b/facia/app/controllers/front/FapiFrontJsonMinimal.scala index 5bf481df189..1242685f837 100644 --- a/facia/app/controllers/front/FapiFrontJsonMinimal.scala +++ b/facia/app/controllers/front/FapiFrontJsonMinimal.scala @@ -44,6 +44,7 @@ trait FapiFrontJsonMinimal { "group" -> faciaContent.card.group, "frontPublicationDate" -> faciaContent.properties.maybeFrontPublicationDate, "supporting" -> getSupporting(faciaContent), + "tests" -> faciaContent.properties.tests, ) .fields .filterNot { case (_, v) => v == JsNull }, From 724b950d4a7745bace7dca1fc388e7099f2b4c2d Mon Sep 17 00:00:00 2001 From: Anna Beddow Date: Tue, 4 Aug 2026 09:39:49 +0100 Subject: [PATCH 4/4] Add minimal tests to lite json --- .../front/FapiFrontJsonMinimal.scala | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/facia/app/controllers/front/FapiFrontJsonMinimal.scala b/facia/app/controllers/front/FapiFrontJsonMinimal.scala index 1242685f837..9d70542bef3 100644 --- a/facia/app/controllers/front/FapiFrontJsonMinimal.scala +++ b/facia/app/controllers/front/FapiFrontJsonMinimal.scala @@ -1,5 +1,6 @@ package controllers.front +import com.gu.facia.client.models.{Test, VariantMeta} import model.PressedPage import model.facia.PressedCollection import model.pressed._ @@ -44,13 +45,42 @@ trait FapiFrontJsonMinimal { "group" -> faciaContent.card.group, "frontPublicationDate" -> faciaContent.properties.maybeFrontPublicationDate, "supporting" -> getSupporting(faciaContent), - "tests" -> faciaContent.properties.tests, + "tests" -> getMinimalTests(faciaContent.properties.tests), ) .fields .filterNot { case (_, v) => v == JsNull }, ) } + private case class MinimalTest( + testUuid: String, + variantMeta: List[VariantMeta], + startDate: Option[Long], + expiryDate: Option[Long], + hasManuallyEndedOnThisTrail: Boolean, + ) + + implicit private val minimalTestWrites: Writes[MinimalTest] = Json.writes[MinimalTest] + + private def getMinimalTests(tests: Option[List[Test]]): JsValue = + tests.filter(_.nonEmpty) match { + case Some(tests) => + JsArray( + tests.map(test => + Json.toJson( + MinimalTest( + testUuid = test.testUuid, + variantMeta = test.variantMeta, + startDate = test.startDate, + expiryDate = test.expiryDate, + hasManuallyEndedOnThisTrail = test.hasManuallyEndedOnThisTrail, + ), + ), + ), + ) + case None => JsNull + } + private def getSupporting(faciaContent: PressedContent): JsValue = faciaContent match { case curatedContent: CuratedContent if curatedContent.supportingContent.nonEmpty =>