Testing Policies
The Testing Policies workflow helps you validate that compiled policies continue to enforce the exact business and governance decisions you expect.
This is one of the most important production confidence layers in the JavaScript SDK.
The real Policy APIs that power testing are:
policy.assertEffect()policy.evaluate()policy.evaluateAction()policy.policyHash()policy.explain()
Core Mental Model
Input fixture -> policy -> expected decision -> regression safety
Policy tests should be treated like authorization contracts.
Fastest Assertion Pattern
The strongest testing primitive is assertEffect().
policy.assertEffect(
{
action: {
type: "deploy",
environment: "production",
},
actor: {
role: "developer",
},
snapshot: {
active_incident: false,
},
},
"require_approval",
)
If the effect changes unexpectedly, the SDK throws ActraPolicyError with:
- expected effect
- actual effect
- full evaluation context
This makes failures highly actionable.
Table-Driven Tests
A highly scalable enterprise pattern.
const cases = [
{
name: "developer deploy requires approval",
input: {
action: { type: "deploy", environment: "production" },
actor: { role: "developer" },
snapshot: {},
},
expected: "require_approval",
},
{
name: "sre deploy allowed",
input: {
action: { type: "deploy", environment: "production" },
actor: { role: "sre_admin" },
snapshot: {},
},
expected: "allow",
},
]
for (const test of cases) {
policy.assertEffect(test.input, test.expected)
}
Excellent for:
- CI regression suites
- approval matrix validation
- policy migrations
- large governance programs
Direct Evaluation Tests
For full decision assertions.
const decision = policy.evaluate({
action: { type: "refund", amount: 5000 },
actor: { role: "finance" },
snapshot: { is_locked: false },
})
expect(decision.effect).toBe("allow")
expect(decision.matched_rule).toBe("finance_refund_allow")
Best when testing:
- matched rule identity
- approval metadata
- analytics labels
- audit workflows
Domain-Oriented Tests
evaluateAction() is perfect for compact fixtures.
const decision = policy.evaluateAction(
{ type: "refund", amount: 1000 },
{ role: "support" },
{ is_locked: false },
)
This keeps test inputs easy to read.
Debugging Failed Tests
Use policy.explain() immediately after assertion failures.
try {
policy.assertEffect(input, "allow")
} catch {
policy.explain(input)
throw new Error("policy regression")
}
This is the fastest way to diagnose:
- wrong actor role
- missing snapshot fields
- schema drift
- incorrect action mapping
- changed governance behavior
Policy Hash Regression Safety
A very strong rollout technique.
const hash = policy.policyHash()
expect(hash).toBe(expectedHash)
Useful for:
- deployment verification
- artifact integrity
- CI drift detection
- cache invalidation
- release promotion
Approval Workflow Tests
A critical enterprise pattern.
policy.assertEffect(
{
action: {
type: "transfer_funds",
amount: 500000,
},
actor: {
role: "finance_analyst",
},
snapshot: {
already_approved: false,
},
},
"require_approval",
)
This should be mandatory for:
- finance systems
- HR approvals
- production deploys
- destructive operations
CI Recommendations
Recommended CI layers:
- table-driven rule tests
- approval boundary tests
- policy hash checks
- explain on failure
- shadow rollout with
audit()
This creates extremely safe governance rollouts.
Best Practices
Test business boundaries
Always test:
- threshold values
- role boundaries
- tenant isolation
- production environments
- destructive actions
Test negative paths
Include:
- explicit blocks
- missing snapshot state
- invalid roles
- approval-required flows
Track policy hash in CI
This is excellent for detecting accidental policy drift.
Production Mental Model
Policy fixture
-> assert expected effect
-> explain failures
-> track hash
-> ship safely
This is how teams build trust in governed runtime decisions.
Next Steps
- Add CI Governance Validation
- Use Observability & Audit
- Combine with Explain & Debugging
- Roll out using audit() shadow mode