Files
Jyotisha/frontend/tests/feature-pricing-contract.test.ts
T
Jesse_Chen afb8305ca1
Independent Staging Quality Gate / validate (push) Failing after 26m23s
Independent Staging Quality Gate / publish (push) Has been skipped
fix admin feature pricing visibility
2026-08-31 19:57:08 +08:00

72 lines
2.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import { fileURLToPath } from "node:url";
import test from "node:test";
const management = readFileSync(
fileURLToPath(new URL("../src/components/admin/feature-pricing-management.tsx", import.meta.url)),
"utf8",
);
const simulator = readFileSync(
fileURLToPath(new URL("../src/components/admin/pricing-simulator.tsx", import.meta.url)),
"utf8",
);
const labels = readFileSync(
fileURLToPath(new URL("../src/lib/admin/feature-pricing-labels.ts", import.meta.url)),
"utf8",
);
const readPolicyMigration = readFileSync(
fileURLToPath(new URL("../supabase/migrations/20260831020000_feature_pricing_admin_runtime_read_policy.sql", import.meta.url)),
"utf8",
);
const source = readFileSync(
fileURLToPath(new URL("../src/lib/feature-pricing.ts", import.meta.url)),
"utf8",
);
test("feature pricing resolver calls the server-side RPC and validates its row", () => {
assert.match(source, /rpc\("resolve_feature_pricing"/);
assert.match(source, /p_feature_key: featureKey/);
assert.match(source, /p_model_id: modelId/);
assert.match(source, /feature_pricing_invalid_response/);
});
test("feature pricing resolver has explicit fail-closed errors", () => {
assert.match(source, /error\.message/);
assert.match(source, /feature_pricing_unavailable/);
assert.match(source, /class FeaturePricingError/);
});
test("feature pricing admin uses readable labels while preserving stable values", () => {
for (const [value, label] of [
["chat.standard", "标准咨询"],
["chat.premium", "高级咨询"],
["rectification", "生时校正"],
["report.full", "完整报告"],
["report.export", "报告导出"],
["profile.extra", "额外档案"],
["standard", "标准模型"],
["premium", "高级模型"],
["internal", "内部模型"],
]) {
assert.match(labels, new RegExp(`value: "${value.replace(".", "\\.")}"`));
assert.match(labels, new RegExp(label));
}
assert.match(management, /FEATURE_PRICING_OPTIONS/);
assert.match(management, /MODEL_TIER_OPTIONS/);
assert.match(management, /featurePricingLabel/);
assert.match(management, /modelTierLabel/);
assert.match(management, /草稿(draft/);
assert.match(management, /已发布(published/);
assert.match(simulator, /featurePricingLabel/);
assert.match(simulator, /modelTierLabel/);
});
test("admin runtime can list feature pricing rows through an explicit read-only RLS policy", () => {
assert.match(readPolicyMigration, /grant select on table public\.feature_pricing to admin_runtime/);
assert.match(readPolicyMigration, /create policy feature_pricing_admin_read on public\.feature_pricing/);
assert.match(readPolicyMigration, /for select to admin_runtime using \(true\)/);
assert.doesNotMatch(readPolicyMigration, /for (?:insert|update|delete|all)/);
});