import { describe, it, expect } from 'vitest';
import { Guardrail } from '../../src/middleware/guardrail.js';
const guardrail = new Guardrail();
// ─── validatePrice ───
describe('Guardrail.validatePrice', () => {
it('passes when claimed matches actual exactly', () => {
expect(guardrail.validatePrice(1000, 1000)).toBe(true);
});
it('passes when within default tolerance (1%)', () => {
// 1% of 1000 = 10, so 1010 is exactly at the boundary
expect(guardrail.validatePrice(1010, 1000)).toBe(true);
});
it('fails when outside tolerance', () => {
// 1% of 1000 = 10, so 1011 is over the boundary
expect(guardrail.validatePrice(1011, 1000)).toBe(false);
});
it('uses custom tolerance', () => {
// 5% of 1000 = 50
expect(guardrail.validatePrice(1050, 1000, 0.05)).toBe(true);
expect(guardrail.validatePrice(1051, 1000, 0.05)).toBe(false);
});
it('handles zero actual price (claimed must also be 0)', () => {
expect(guardrail.validatePrice(0, 0)).toBe(true);
expect(guardrail.validatePrice(1, 0)).toBe(false);
});
});
// ─── validateInventory ───
describe('Guardrail.validateInventory', () => {
it('passes when stock is sufficient', () => {
expect(guardrail.validateInventory('var-1', 5, 10)).toBe(true);
});
it('passes when request equals stock', () => {
expect(guardrail.validateInventory('var-1', 10, 10)).toBe(true);
});
it('fails when stock is insufficient', () => {
expect(guardrail.validateInventory('var-1', 11, 10)).toBe(false);
});
it('fails when requested quantity is zero', () => {
expect(guardrail.validateInventory('var-1', 0, 10)).toBe(false);
});
it('fails when requested quantity is negative', () => {
expect(guardrail.validateInventory('var-1', -1, 10)).toBe(false);
});
});
// ─── validateCheckoutTransition ───
describe('Guardrail.validateCheckoutTransition', () => {
it('allows incomplete -> requires_escalation', () => {
expect(guardrail.validateCheckoutTransition('incomplete', 'requires_escalation')).toBe(true);
});
it('allows incomplete -> ready_for_complete', () => {
expect(guardrail.validateCheckoutTransition('incomplete', 'ready_for_complete')).toBe(true);
});
it('allows requires_escalation -> incomplete', () => {
expect(guardrail.validateCheckoutTransition('requires_escalation', 'incomplete')).toBe(true);
});
it('allows requires_escalation -> ready_for_complete', () => {
expect(guardrail.validateCheckoutTransition('requires_escalation', 'ready_for_complete')).toBe(
true,
);
});
it('allows no-op transitions (same state)', () => {
expect(guardrail.validateCheckoutTransition('incomplete', 'incomplete')).toBe(true);
expect(guardrail.validateCheckoutTransition('ready_for_complete', 'ready_for_complete')).toBe(
true,
);
});
it('rejects ready_for_complete -> incomplete', () => {
expect(guardrail.validateCheckoutTransition('ready_for_complete', 'incomplete')).toBe(false);
});
it('rejects ready_for_complete -> requires_escalation', () => {
expect(guardrail.validateCheckoutTransition('ready_for_complete', 'requires_escalation')).toBe(
false,
);
});
});