Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions lib/addons/abTestAssignment.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,24 @@ describe("setupAB - override via flags", () => {
expect(result.variant.id).toBe("production");
expect(result.isControl).toBe(false);
});

it("forces treatment when optableDebug flag is set", () => {
sessionStorage.setItem("optableDebug", "1");
resetFlags();
jest.spyOn(Math, "random").mockReturnValue(0.97); // would normally land in control
const result = setupAB({ variants: [{ id: "production" }, { id: "test", trafficPercentage: 5 }] });
expect(result.variant.id).toBe("production");
expect(result.isControl).toBe(false);
});

it("optableControlGroup=1 takes priority over optableDebug", () => {
sessionStorage.setItem("optableDebug", "1");
sessionStorage.setItem("optableControlGroup", "1");
resetFlags();
const result = setupAB({ variants: [{ id: "production" }, { id: "test", trafficPercentage: 5 }] });
expect(result.variant.id).toBe("test");
expect(result.isControl).toBe(true);
});
});

describe("setupAB - custom variant ids", () => {
Expand Down
5 changes: 3 additions & 2 deletions lib/addons/abTestAssignment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,11 @@ export function setupAB(config: SetupABConfig): ABTestSetupResult {
// Priority 1 — QA/debug override via URL param or sessionStorage flag.
// ?optableControlGroup=1 forces the control variant; =0 forces treatment.
// This lets QA verify both branches without clearing localStorage.
const controlGroupFlag = getFlags().optableControlGroup;
const flags = getFlags();
const controlGroupFlag = flags.optableControlGroup;
if (controlGroupFlag === "1") {
selected = filled.find((v) => v.id === controlId) ?? { id: controlId, trafficPercentage: 0 };
} else if (controlGroupFlag === "0") {
} else if (controlGroupFlag === "0" || flags.optableDebug) {
selected = filled.find((v) => v.id === treatmentId) ?? { id: treatmentId, trafficPercentage: 0 };
}

Expand Down
10 changes: 10 additions & 0 deletions lib/addons/prebid/analytics.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import OptablePrebidAnalytics, { initPrebidAnalytics } from "./analytics";
import type OptableSDK from "../../sdk";
import { resetFlags } from "../../core/flags";

// Mock the SDK_WRAPPER_VERSION global
declare global {
Expand Down Expand Up @@ -31,6 +32,8 @@ describe("OptablePrebidAnalytics", () => {
document.removeEventListener("visibilitychange", (analytics as any).handleVisibilityChange);
}
jest.clearAllMocks();
sessionStorage.clear();
resetFlags();
});

describe("Class instantiation", () => {
Expand Down Expand Up @@ -147,6 +150,13 @@ describe("OptablePrebidAnalytics", () => {

mockRandom.mockRestore();
});

it("should return true when optableDebug flag is set, even with samplingRate 0", () => {
sessionStorage.setItem("optableDebug", "1");
resetFlags();
analytics = new OptablePrebidAnalytics(mockOptableInstance, { samplingRate: 0 });
expect(analytics.shouldSample()).toBe(true);
});
});

describe("toWitness", () => {
Expand Down
2 changes: 2 additions & 0 deletions lib/addons/prebid/analytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import type { WitnessProperties } from "../../edge/witness";
import type OptableSDK from "../../sdk";
import { buildRequest } from "../../core/network";
import { getFlags } from "../../core/flags";

import * as Bowser from "bowser";

Expand Down Expand Up @@ -137,6 +138,7 @@ class OptablePrebidAnalytics {
* @returns true if the event should be sampled and analytics calls may proceed.
*/
shouldSample(): boolean {
if (getFlags().optableDebug) return true;
if (this.config.samplingRate! <= 0) return false;
if (this.config.samplingRate! >= 1) return true;

Expand Down
2 changes: 2 additions & 0 deletions lib/edge/targeting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { determineABTest } from "./abTest";
import { fetch } from "../core/network";
import { LocalStorage } from "../core/storage";
import { isBot } from "../addons/botDetection";
import { getFlags } from "../core/flags";
import * as ortb2 from "iab-openrtb/v26";
import * as adcom from "iab-adcom";
import { sendTargetingUpdateEvent } from "../core/events/cache-refresh";
Expand Down Expand Up @@ -102,6 +103,7 @@ function TargetingClearCache(config: ResolvedConfig) {
* Returns whether the request was identified as a bot.
*/
export function SkipTargetingForBots(): boolean {
if (getFlags().optableDebug) return false;
try {
if (typeof isBot === "function" && isBot()) {
sessionStorage.setItem(TARGETING_DONE_KEY, "1");
Expand Down
Loading