Testing
Decision correctness is verified for you at compile time. You test one thing: your integration.
Decisions are validated automatically
npx ninka compile derives decision vectors from your Tegata, computes expected results with an independent reference evaluator, and runs them against the built WASM. A mismatch fails the build. npx ninka verify re-runs the vectors against the committed WASM in CI.
npx ninka compile # validation runs here
npx ninka verify # re-run in CI
Hand-written "should allow / should deny" tests duplicate the policy and drift from the Tegata. To change what's allowed, change the Tegata.
Test your integration
Test that each handler calls check() with the correct input and enforces the boolean. Mock the boundary so you exercise the handler, not the decision:
import { describe, it, expect, vi, beforeEach } from "vitest";
import { check } from "@/lib/authz";
import { POST } from "./route";
vi.mock("@/lib/authz", async (importOriginal) => ({
...(await importOriginal<typeof import("@/lib/authz")>()),
check: vi.fn(),
}));
const checkMock = vi.mocked(check);
describe("POST /documents/:id/edit", () => {
beforeEach(() => checkMock.mockReset());
it("calls check() with the correct input", async () => {
checkMock.mockResolvedValue(true);
await POST(makeRequest({ id: "doc-1", patch: { title: "New" } }));
expect(checkMock).toHaveBeenCalledWith(
"document-access",
expect.objectContaining({
action: { name: "edit" },
resource: { type: "document", properties: { owner_id: "user-9" } },
}),
);
});
it("returns 403 on deny", async () => {
checkMock.mockResolvedValue(false);
const res = await POST(makeRequest({ id: "doc-1", patch: { title: "New" } }));
expect(res.status).toBe(403);
});
it("proceeds on allow", async () => {
checkMock.mockResolvedValue(true);
const res = await POST(makeRequest({ id: "doc-1", patch: { title: "New" } }));
expect(res.status).toBe(200);
});
});
An end-to-end test that loads the real policy still shouldn't hand-code expected decisions — drive the handler with real inputs and assert the HTTP outcome.