Skip to content
Merged
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
2 changes: 2 additions & 0 deletions lib/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ type ABTestConfig = {
matcher_override?: MatcherOverride[];
// SkipMatchers specifies the list of matchers (node_id)s to skip. To skip 1p, simply send 1p
skipMatchers?: string[];
// SkipResolvers specifies the list of resolvers (node_id)s to skip.
skipResolvers?: string[];
};

type TargetingSignals = {
Expand Down
122 changes: 122 additions & 0 deletions lib/edge/targeting.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,29 @@ describe("determineABTest", () => {
});
});

test("handles tests with skipResolvers", () => {
const { determineABTest } = require("./targeting");
const abTests = [
{
id: "test1",
trafficPercentage: 50,
skipResolvers: ["resolver1"],
},
{
id: "test2",
trafficPercentage: 50,
skipResolvers: ["resolver2"],
},
];

Math.random = jest.fn().mockReturnValue(0.25); // bucket = 25
expect(determineABTest(abTests)).toEqual({
id: "test1",
trafficPercentage: 50,
skipResolvers: ["resolver1"],
});
});

test("handles boundary conditions", () => {
const { determineABTest } = require("./targeting");
const abTests = [
Expand Down Expand Up @@ -451,4 +474,103 @@ describe("Targeting function handles optional params like targeting signals and
})
);
});

test("includes skip_resolvers parameter when abTest.skipResolvers is provided", async () => {
mockFetch.mockResolvedValue(createMockResponse({ audience: [], user: [] }));

await Targeting(
{
...baseConfig,
abTests: [{ id: "test1", trafficPercentage: 100, skipResolvers: ["resolver1"] }],
},
{ ...baseReq }
);

expect(mockFetch).toHaveBeenCalledWith(
expect.objectContaining({
url: expect.stringContaining("skip_resolvers=resolver1"),
})
);
});

test("includes skip_resolvers parameter when abTest.skipResolvers contains multiple resolvers", async () => {
mockFetch.mockResolvedValue(createMockResponse({ audience: [], user: [] }));

await Targeting(
{
...baseConfig,
abTests: [{ id: "test1", trafficPercentage: 100, skipResolvers: ["resolver1", "resolver2"] }],
},
{ ...baseReq }
);

expect(mockFetch).toHaveBeenCalledWith(
expect.objectContaining({
url: expect.stringContaining("skip_resolvers="),
})
);
expect(mockFetch).toHaveBeenCalledWith(
expect.objectContaining({
url: expect.stringContaining(encodeURIComponent("resolver1,resolver2")),
})
);
});

test("does not include skip_resolvers parameter when abTest.skipResolvers is not provided", async () => {
mockFetch.mockResolvedValue(createMockResponse({ audience: [], user: [] }));

await Targeting(
{
...baseConfig,
abTests: [{ id: "test1", trafficPercentage: 100 }],
},
{ ...baseReq }
);

expect(mockFetch).toHaveBeenCalledWith(
expect.objectContaining({
url: expect.not.stringContaining("skip_resolvers="),
})
);
});

test("includes both skip_matchers and skip_resolvers when both are provided", async () => {
mockFetch.mockResolvedValue(createMockResponse({ audience: [], user: [] }));

await Targeting(
{
...baseConfig,
abTests: [
{
id: "test1",
trafficPercentage: 100,
skipMatchers: ["matcher1", "matcher2"],
skipResolvers: ["resolver1", "resolver2"],
},
],
},
{ ...baseReq }
);

expect(mockFetch).toHaveBeenCalledWith(
expect.objectContaining({
url: expect.stringContaining("skip_matchers="),
})
);
expect(mockFetch).toHaveBeenCalledWith(
expect.objectContaining({
url: expect.stringContaining("skip_resolvers="),
})
);
expect(mockFetch).toHaveBeenCalledWith(
expect.objectContaining({
url: expect.stringContaining(encodeURIComponent("matcher1,matcher2")),
})
);
expect(mockFetch).toHaveBeenCalledWith(
expect.objectContaining({
url: expect.stringContaining(encodeURIComponent("resolver1,resolver2")),
})
);
});
});
3 changes: 3 additions & 0 deletions lib/edge/targeting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ async function Targeting(config: ResolvedConfig, req: TargetingRequest): Promise
if (abTest.skipMatchers) {
searchParams.append("skip_matchers", abTest.skipMatchers.join(","));
}
if (abTest.skipResolvers) {
searchParams.append("skip_resolvers", abTest.skipResolvers.join(","));
}
}

if (config.additionalTargetingSignals?.ref) {
Expand Down
Loading