Flags guides
05 · Testing with overrides

Test without the network.

Fixed values for local development, a test client for unit tests, and a check of real targeting against the live config.


1

Overrides

Overrides set values locally, from a map, a JSON file or an environment variable. behaviour decides who wins: local_over_remote (the default), remote_over_local, or local_only, which downloads nothing and needs no key. Files and environment variables are Node-only.

flags.ts
import { FlagsClient } from "@productcraft/flags";

// Local development: fixed values, no downloads, no key needed.
export const dev = new FlagsClient({
  overrides: { values: { new_checkout: true, limits: { max: 50 } }, behaviour: "local_only" },
});

// A file next to your code, reloaded when it changes (Node only).
export const local = new FlagsClient({
  sdkKey: process.env.PRODUCTCRAFT_FLAGS_SDK_KEY,
  overrides: { file: "./flags.local.json", watch: true },
});

// An environment variable you control (Node only):
// PRODUCTCRAFT_FLAGS_OVERRIDES='{"new_checkout": false}'
export const ops = new FlagsClient({
  sdkKey: process.env.PRODUCTCRAFT_FLAGS_SDK_KEY,
  overrides: { env: "PRODUCTCRAFT_FLAGS_OVERRIDES" },
});

2

Unit tests

createTestClient from @productcraft/flags/testing is a FlagsClient with fixed values, no network and no timers. set() changes a value mid-test and emits configChanged, as a real change would.

checkout.test.ts
import { createTestClient } from "@productcraft/flags/testing";

async function checkoutVersion(flags: { getValue(key: string, def: boolean): Promise<boolean> }) {
  return (await flags.getValue("new_checkout", false)) ? "v2" : "v1";
}

// Jest or Vitest: the same calls.
declare const test: (name: string, fn: () => Promise<void>) => void;
declare const expect: (v: unknown) => { toBe(x: unknown): void };

test("follows the new_checkout flag", async () => {
  const flags = createTestClient({ values: { new_checkout: true } });
  expect(await checkoutVersion(flags)).toBe("v2");
  flags.set("new_checkout", false); // emits configChanged
  expect(await checkoutVersion(flags)).toBe("v1");
});

3

Check real targeting

Does this user get the new checkout in Production? Ask the API, without deploying anything.

The test evaluation endpoint runs the same engine as the SDK against the published config. The user you send is neither stored nor logged. It allows 30 requests a minute per credential; the console's Test panel calls it too.

evaluate.ts
import { Flags } from "@productcraft/flags";
const flags = new Flags(); // PRODUCTCRAFT_API_KEY + PRODUCTCRAFT_WORKSPACE_ID

declare const configId: string;
declare const productionId: string;

// The same engine as the SDK, against the published config. The user
// is not stored or logged.
const result = await flags.configs.environments.evaluate(configId, productionId, {
  user: { identifier: "user-123", email: "ada@acme.com" },
  keys: ["new_checkout"],
});
for (const r of result.data) console.log(r.key, r.value, r.reason, r.rule_index, r.percentage_index);