/**
 * Tests for the client-safe validation module published at
 * `@actuate-media/cms-core/forms/client`.
 *
 * Two contracts matter here:
 *   1. Behavior parity — for any value, the client validator and the server's
 *      `validateAndNormalizeSubmission` agree on pass/fail, so inline client
 *      feedback never contradicts the server response.
 *   2. Client safety — the module must not import Node built-ins or the
 *      sanitizer (which would drag DOM/Node deps into a public-site bundle).
 */
import { readFileSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
import { describe, expect, it } from 'vitest';
import { FORM_EMAIL_RE, FORM_MAX_TEXT_LEN, FORM_PHONE_RE, validateFormFieldClient, validateFormValuesClient, } from '../../forms/client-validation.js';
import { validateAndNormalizeSubmission } from '../../forms/validation.js';
const field = (overrides) => ({
    label: overrides.key,
    ...overrides,
});
describe('client-validation module safety', () => {
    it('imports nothing besides its own types (no Node deps, no sanitizer)', () => {
        const src = readFileSync(fileURLToPath(new URL('../../forms/client-validation.ts', import.meta.url)), 'utf8');
        const imports = [...src.matchAll(/^import .*?from '(.+?)'/gms)].map((m) => m[1]);
        expect(imports).toEqual(['./types.js']);
    });
});
describe('validateFormFieldClient', () => {
    it('exposes the same email/phone regexes the server enforces', () => {
        expect(FORM_EMAIL_RE.test('a@b.co')).toBe(true);
        expect(FORM_EMAIL_RE.test('not-an-email')).toBe(false);
        expect(FORM_PHONE_RE.test('+1 (555) 123-4567')).toBe(true);
        expect(FORM_PHONE_RE.test('abc')).toBe(false);
    });
    it('validates required, format, and length rules', () => {
        const email = field({ key: 'email', type: 'email', required: true });
        expect(validateFormFieldClient(email, '').ok).toBe(false);
        expect(validateFormFieldClient(email, 'nope').ok).toBe(false);
        expect(validateFormFieldClient(email, 'a@b.co').ok).toBe(true);
        const name = field({ key: 'name', type: 'text', validationRules: { minLength: 3 } });
        expect(validateFormFieldClient(name, 'ab')).toEqual({
            ok: false,
            message: 'name must be at least 3 characters.',
        });
        expect(validateFormFieldClient(name, 'x'.repeat(FORM_MAX_TEXT_LEN + 1)).ok).toBe(false);
    });
    it('skips hidden fields and applies conditional requires, like the server', () => {
        const conditional = field({
            key: 'other',
            type: 'text',
            conditionalLogic: {
                show: [{ fieldKey: 'choice', operator: 'equals', value: 'other' }],
                require: [{ fieldKey: 'choice', operator: 'equals', value: 'other' }],
            },
        });
        // Hidden → always ok even when empty.
        expect(validateFormFieldClient(conditional, '', { choice: 'a' }).ok).toBe(true);
        // Visible + conditionally required → empty fails.
        expect(validateFormFieldClient(conditional, '', { choice: 'other' }).ok).toBe(false);
        expect(validateFormFieldClient(conditional, 'value', { choice: 'other' }).ok).toBe(true);
    });
    it('agrees with the server validator on a representative form', () => {
        const fields = [
            field({ key: 'email', type: 'email', required: true }),
            field({ key: 'phone', type: 'phone' }),
            field({ key: 'count', type: 'number', validationRules: { min: 1, max: 10 } }),
            field({
                key: 'color',
                type: 'select',
                options: [
                    { label: 'Red', value: 'red' },
                    { label: 'Blue', value: 'blue' },
                ],
            }),
            field({ key: 'agree', type: 'consent' }),
            field({ key: 'when', type: 'date' }),
        ];
        const cases = [
            {
                email: 'a@b.co',
                phone: '555-1234',
                count: 5,
                color: 'red',
                agree: true,
                when: '2026-01-01',
            },
            { email: 'bad', phone: 'x', count: 99, color: 'green', agree: false, when: 'not-a-date' },
            { email: '', count: 'NaN', color: 'blue', agree: 'on' },
        ];
        for (const values of cases) {
            const server = validateAndNormalizeSubmission(fields, values);
            const client = validateFormValuesClient(fields, values);
            const serverKeys = [...new Set(server.errors.map((e) => e.key))].sort();
            expect(Object.keys(client).sort()).toEqual(serverKeys);
        }
    });
});
//# sourceMappingURL=client-validation.test.js.map