import { describe, expect, it } from "bun:test"; import { FLOW_DISPLAY_CUSTOMER_OCCURRENCE_TRIGGER_CAPABILITY, FLOW_DISPLAY_NAMED_BUDGET_CLAIM_CAPABILITY, flowDisplayClaimBroadcastRequestSchema, flowDisplayClaimBroadcastResponseSchema, flowDisplaySyncRequestSchema, flowDisplaySyncResponseSchema, resolveFlowDisplayAttentionPolicyConfig, runtimeDisplayEligibilitySchema, runtimeDisplayTriggerSchema, } from "./flow-display"; describe("flow display sync contracts", () => { it("accepts assignment claim input plus broadcast manifest version", () => { const result = flowDisplaySyncRequestSchema.parse({ holdOwnerKey: "inst_1", identities: [{ type: "anonymousId", value: "anon_1" }], context: { page: { path: "/pricing" }, capabilities: [{ key: "checkout.drawer" }], }, assignmentLimit: 2, protocolCapabilities: [FLOW_DISPLAY_NAMED_BUDGET_CLAIM_CAPABILITY], knownBroadcastManifestVersion: "broadcasts_1", }); expect(result).toEqual({ holdOwnerKey: "inst_1", identities: [{ type: "anonymousId", value: "anon_1" }], context: { page: { path: "/pricing" }, capabilities: [{ key: "checkout.drawer" }], }, assignmentLimit: 2, protocolCapabilities: [FLOW_DISPLAY_NAMED_BUDGET_CLAIM_CAPABILITY], knownBroadcastManifestVersion: "broadcasts_1", }); }); it("accepts claimed assignments with an empty broadcast manifest", () => { const result = flowDisplaySyncResponseSchema.parse({ fetchedAt: "2026-06-18T00:00:00.000Z", assignments: { claimed: [ { flowAssignmentId: "fa_1", flowId: "sur_1", holdGroupToken: "hold_1", latestFlowVersionId: "flv_1", status: "held", assignedAt: "2026-06-18T00:00:00.000Z", }, ], }, broadcasts: { version: "empty", opportunities: [], }, }); expect(result.assignments.claimed[0]?.flowAssignmentId).toBe("fa_1"); expect(result.broadcasts.opportunities).toEqual([]); expect(result.attentionPolicy).toBeUndefined(); }); it("keeps the legacy attention policy response shape backward compatible", () => { const result = flowDisplaySyncResponseSchema.parse({ fetchedAt: "2026-06-18T00:00:00.000Z", attentionPolicy: { version: "attention-policy-organization-override-v1", source: "custom", recentFlowCooldownMs: 45_000, exclusiveSurfaceStrategy: "queue", blockedBroadcastStrategy: "queue", }, attentionPolicyV2: { version: "attention-policy-organization-override-v1", source: "custom", recentFlowCooldownMs: 45_000, recentInAppCooldownMs: 60_000, exclusiveSurfaceStrategy: "queue", blockedBroadcastStrategy: "queue", }, assignments: { claimed: [], }, broadcasts: { version: "empty", opportunities: [], }, }); expect(result.attentionPolicy).toEqual({ version: "attention-policy-organization-override-v1", source: "custom", recentFlowCooldownMs: 45_000, exclusiveSurfaceStrategy: "queue", blockedBroadcastStrategy: "queue", }); expect(result.attentionPolicyV2).toEqual({ version: "attention-policy-organization-override-v1", source: "custom", recentFlowCooldownMs: 45_000, recentInAppCooldownMs: 60_000, exclusiveSurfaceStrategy: "queue", blockedBroadcastStrategy: "queue", }); }); it("rejects new attention policy fields on the legacy response field", () => { expect(() => flowDisplaySyncResponseSchema.parse({ fetchedAt: "2026-06-18T00:00:00.000Z", attentionPolicy: { version: "attention-policy-organization-override-v1", source: "custom", recentFlowCooldownMs: 45_000, recentInAppCooldownMs: 60_000, exclusiveSurfaceStrategy: "queue", blockedBroadcastStrategy: "queue", }, assignments: { claimed: [], }, broadcasts: { version: "empty", opportunities: [], }, }), ).toThrow(); }); it("accepts future additive fields on the v2 attention policy envelope", () => { const result = flowDisplaySyncResponseSchema.parse({ fetchedAt: "2026-06-18T00:00:00.000Z", attentionPolicyV2: { version: "attention-policy-organization-override-v1", source: "custom", recentFlowCooldownMs: 45_000, recentInAppCooldownMs: 60_000, exclusiveSurfaceStrategy: "queue", blockedBroadcastStrategy: "queue", futureChannelStrategy: "digest", }, assignments: { claimed: [], }, broadcasts: { version: "empty", opportunities: [], }, }); expect(result.attentionPolicyV2).toEqual({ version: "attention-policy-organization-override-v1", source: "custom", recentFlowCooldownMs: 45_000, recentInAppCooldownMs: 60_000, exclusiveSurfaceStrategy: "queue", blockedBroadcastStrategy: "queue", futureChannelStrategy: "digest", }); expect(resolveFlowDisplayAttentionPolicyConfig(result)).toEqual({ automaticInAppWeeklyLimit: 3, version: "attention-policy-organization-override-v1", source: "custom", recentFlowCooldownMs: 45_000, recentInAppCooldownMs: 60_000, exclusiveSurfaceStrategy: "queue", blockedBroadcastStrategy: "queue", }); }); it("resolves the v2 attention policy before the legacy fallback", () => { const result = flowDisplaySyncResponseSchema.parse({ fetchedAt: "2026-06-18T00:00:00.000Z", attentionPolicy: { version: "attention-policy-legacy-v1", source: "custom", recentFlowCooldownMs: 45_000, exclusiveSurfaceStrategy: "queue", blockedBroadcastStrategy: "queue", }, attentionPolicyV2: { version: "attention-policy-v2-v1", source: "custom", recentFlowCooldownMs: 90_000, recentInAppCooldownMs: 30_000, exclusiveSurfaceStrategy: "queue", blockedBroadcastStrategy: "queue", }, assignments: { claimed: [], }, broadcasts: { version: "empty", opportunities: [], }, }); expect(resolveFlowDisplayAttentionPolicyConfig(result)).toEqual({ automaticInAppWeeklyLimit: 3, version: "attention-policy-v2-v1", source: "custom", recentFlowCooldownMs: 90_000, recentInAppCooldownMs: 30_000, exclusiveSurfaceStrategy: "queue", blockedBroadcastStrategy: "queue", }); }); it("rejects an explicit null weekly limit", () => { expect(() => flowDisplaySyncResponseSchema.parse({ fetchedAt: "2026-06-18T00:00:00.000Z", attentionPolicyV2: { version: "attention-policy-organization-override-v1", source: "custom", recentFlowCooldownMs: 300_000, recentInAppCooldownMs: 0, automaticInAppWeeklyLimit: null, exclusiveSurfaceStrategy: "queue", blockedBroadcastStrategy: "queue", }, assignments: { claimed: [] }, broadcasts: { version: "empty", opportunities: [] }, }), ).toThrow(); }); it("resolves legacy attention policy with default v2-only fields", () => { const result = flowDisplaySyncResponseSchema.parse({ fetchedAt: "2026-06-18T00:00:00.000Z", attentionPolicy: { version: "attention-policy-legacy-v1", source: "custom", recentFlowCooldownMs: 45_000, exclusiveSurfaceStrategy: "queue", blockedBroadcastStrategy: "queue", }, assignments: { claimed: [], }, broadcasts: { version: "empty", opportunities: [], }, }); expect(resolveFlowDisplayAttentionPolicyConfig(result)).toEqual({ automaticInAppWeeklyLimit: 3, version: "attention-policy-legacy-v1", source: "custom", recentFlowCooldownMs: 45_000, recentInAppCooldownMs: 0, exclusiveSurfaceStrategy: "queue", blockedBroadcastStrategy: "queue", }); }); it("accepts runtime broadcast opportunities", () => { const result = flowDisplaySyncResponseSchema.parse({ fetchedAt: "2026-06-18T00:00:00.000Z", assignments: { claimed: [], }, broadcasts: { version: "broadcasts_1", opportunities: [ { opportunityId: "rtb_daver_1", flowId: "sur_1", flowVersionId: "flv_1", source: { kind: "runtime_broadcast", automationId: "dauto_1", automationVersionId: "daver_1", }, runtimeEligibility: { hostActionRequirementsVersion: 3, requiredCapabilities: ["checkout.drawer"], requiredHostActions: [{ key: "enable-feature", version: 1 }], requiredHostActionSettlement: { kind: "link", transport: "browser_http", }, requiredPage: { path: "/checkout/*" }, }, runtimeTrigger: { kind: "immediate", }, }, ], }, }); expect(result.broadcasts.opportunities[0]).toEqual({ opportunityId: "rtb_daver_1", flowId: "sur_1", flowVersionId: "flv_1", source: { kind: "runtime_broadcast", automationId: "dauto_1", automationVersionId: "daver_1", }, runtimeEligibility: { hostActionRequirementsVersion: 3, requiredCapabilities: ["checkout.drawer"], requiredHostActions: [{ key: "enable-feature", version: 1 }], requiredHostActionSettlement: { kind: "link", transport: "browser_http", }, requiredPage: { path: "/checkout/*" }, }, runtimeTrigger: { kind: "immediate", }, }); }); it("preserves unknown host-action requirement versions for Core admission", () => { const result = flowDisplaySyncResponseSchema.parse({ fetchedAt: "2026-06-18T00:00:00.000Z", assignments: { claimed: [], }, broadcasts: { version: "broadcasts_2", opportunities: [ { opportunityId: "rtb_daver_2", flowId: "sur_2", flowVersionId: "flv_2", source: { kind: "runtime_broadcast", automationId: "dauto_2", automationVersionId: "daver_2", }, runtimeEligibility: { hostActionRequirementsVersion: 4, requiredCapabilities: [], }, runtimeTrigger: { kind: "immediate", }, }, ], }, }); expect( result.broadcasts.opportunities[0]?.runtimeEligibility .hostActionRequirementsVersion, ).toBe(4); }); it("parses legacy v2 action references without invalidating the sync", () => { const result = runtimeDisplayEligibilitySchema.parse({ hostActionRequirementsVersion: 2, requiredHostActions: [ { key: "enable-feature", contractVersion: "legacy-v1" }, ], }); expect(result.requiredHostActions).toEqual([ { key: "enable-feature", contractVersion: "legacy-v1" }, ]); }); it("accepts runtime broadcast attention policy metadata", () => { const result = flowDisplaySyncResponseSchema.parse({ fetchedAt: "2026-06-18T00:00:00.000Z", assignments: { claimed: [], }, broadcasts: { version: "broadcasts_1", opportunities: [ { opportunityId: "rtb_daver_1", flowId: "sur_1", flowVersionId: "flv_1", source: { kind: "runtime_broadcast", }, runtimeEligibility: { requiredCapabilities: [], }, attentionPolicy: { priority: "high", attentionMode: "concurrent", cooldown: { key: "automation:dauto_1", afterDisplayMs: 60_000, }, }, }, ], }, }); expect(result.broadcasts.opportunities[0]?.attentionPolicy).toEqual({ priority: "high", attentionMode: "concurrent", cooldown: { key: "automation:dauto_1", afterDisplayMs: 60_000, }, }); }); it("rejects invalid runtime broadcast attention policy metadata", () => { expect(() => flowDisplaySyncResponseSchema.parse({ fetchedAt: "2026-06-18T00:00:00.000Z", assignments: { claimed: [], }, broadcasts: { version: "broadcasts_1", opportunities: [ { opportunityId: "rtb_daver_1", flowId: "sur_1", flowVersionId: "flv_1", source: { kind: "runtime_broadcast", }, runtimeEligibility: { requiredCapabilities: [], }, attentionPolicy: { priority: "urgent", cooldown: { key: "automation:dauto_1", afterDisplayMs: -1, }, }, }, ], }, }), ).toThrow(); }); it("defaults legacy runtime broadcast opportunities to an immediate runtime trigger", () => { const result = flowDisplaySyncResponseSchema.parse({ fetchedAt: "2026-06-18T00:00:00.000Z", assignments: { claimed: [], }, broadcasts: { version: "broadcasts_1", opportunities: [ { opportunityId: "rtb_daver_1", flowId: "sur_1", flowVersionId: "flv_1", source: { kind: "runtime_broadcast", }, runtimeEligibility: { requiredCapabilities: [], }, }, ], }, }); expect(result.broadcasts.opportunities[0]?.runtimeTrigger).toEqual({ kind: "immediate", }); }); it("accepts exit-intent runtime broadcast opportunities", () => { const result = flowDisplaySyncResponseSchema.parse({ fetchedAt: "2026-06-18T00:00:00.000Z", assignments: { claimed: [], }, broadcasts: { version: "broadcasts_1", opportunities: [ { opportunityId: "rtb_daver_1", flowId: "sur_1", flowVersionId: "flv_1", source: { kind: "runtime_broadcast", }, runtimeEligibility: { requiredCapabilities: [], }, runtimeTrigger: { kind: "exit_intent", }, }, ], }, }); expect(result.broadcasts.opportunities[0]?.runtimeTrigger).toEqual({ kind: "exit_intent", }); }); it("round-trips customer occurrence runtime triggers", () => { const trigger = { event: "Settings Opened", kind: "customer_occurrence" as const, type: "screen" as const, }; expect(runtimeDisplayTriggerSchema.parse(trigger)).toEqual(trigger); const result = flowDisplaySyncResponseSchema.parse({ fetchedAt: "2026-06-18T00:00:00.000Z", assignments: { claimed: [] }, broadcasts: { version: "broadcasts_2", opportunities: [ { opportunityId: "rtb_daver_2", flowId: "sur_2", flowVersionId: "flv_2", source: { kind: "runtime_broadcast" }, runtimeEligibility: { requiredCapabilities: [] }, runtimeTrigger: trigger, }, ], }, }); expect(result.broadcasts.opportunities[0]?.runtimeTrigger).toEqual(trigger); }); it("rejects customer occurrence names the SDK cannot emit", () => { for (const event of ["Flow Viewed", "x".repeat(256)]) { expect( runtimeDisplayTriggerSchema.safeParse({ event, kind: "customer_occurrence", type: "track", }).success, ).toBeFalse(); } }); it("accepts a claim-broadcast request and defaults identities", () => { const result = flowDisplayClaimBroadcastRequestSchema.parse({ automationId: "dauto_1", automationVersionId: "daver_1", holdOwnerKey: "inst_1", protocolCapabilities: [ FLOW_DISPLAY_CUSTOMER_OCCURRENCE_TRIGGER_CAPABILITY, ], }); expect(result).toEqual({ automationId: "dauto_1", automationVersionId: "daver_1", holdOwnerKey: "inst_1", identities: [], protocolCapabilities: [ FLOW_DISPLAY_CUSTOMER_OCCURRENCE_TRIGGER_CAPABILITY, ], }); }); it("round-trips claimed and ineligible claim-broadcast responses", () => { expect( flowDisplayClaimBroadcastResponseSchema.parse({ outcome: "claimed", assignment: { flowAssignmentId: "flasn_1", flowVersionId: "flv_1", holdGroupToken: "fahold_1", status: "held", }, }), ).toEqual({ outcome: "claimed", assignment: { flowAssignmentId: "flasn_1", flowVersionId: "flv_1", holdGroupToken: "fahold_1", status: "held", }, }); // A hold-less existing claim (presented, or held by another instance). expect( flowDisplayClaimBroadcastResponseSchema.parse({ outcome: "existing", assignment: { flowAssignmentId: "flasn_1", flowVersionId: "flv_1", holdGroupToken: null, status: "presented", }, }).outcome, ).toBe("existing"); expect( flowDisplayClaimBroadcastResponseSchema.parse({ outcome: "ineligible" }), ).toEqual({ outcome: "ineligible" }); expect( flowDisplayClaimBroadcastResponseSchema.parse({ outcome: "ineligible", reason: "recent_flow_cooldown", }), ).toEqual({ outcome: "ineligible", reason: "recent_flow_cooldown", }); }); });