import { describe, expect, it } from 'vitest' import { evaluateConditionalLogic } from '@form-schema/composables/useConditionalLogic' import type { ConditionalLogic } from '@form-schema/types/formBuilder' describe('evaluateConditionalLogic', () => { it('returns true when logic is null or undefined', () => { expect(evaluateConditionalLogic(null, {})).toBe(true) expect(evaluateConditionalLogic(undefined, {})).toBe(true) expect(evaluateConditionalLogic({}, {})).toBe(true) }) it('handles simple equals / not_equals', () => { const logic: ConditionalLogic = { show_when: { all: [{ field_slug: 'foo', operator: 'equals', value: 'bar' }] }, } expect(evaluateConditionalLogic(logic, { foo: 'bar' })).toBe(true) expect(evaluateConditionalLogic(logic, { foo: 'baz' })).toBe(false) const negative: ConditionalLogic = { show_when: { all: [{ field_slug: 'foo', operator: 'not_equals', value: 'bar' }] }, } expect(evaluateConditionalLogic(negative, { foo: 'baz' })).toBe(true) expect(evaluateConditionalLogic(negative, { foo: 'bar' })).toBe(false) }) it('handles in / not_in over single and array values', () => { const logic: ConditionalLogic = { show_when: { all: [{ field_slug: 'tags', operator: 'in', value: ['a', 'b'] }] }, } expect(evaluateConditionalLogic(logic, { tags: 'a' })).toBe(true) expect(evaluateConditionalLogic(logic, { tags: 'c' })).toBe(false) expect(evaluateConditionalLogic(logic, { tags: ['c', 'a'] })).toBe(true) const negative: ConditionalLogic = { show_when: { all: [{ field_slug: 'tags', operator: 'not_in', value: ['a'] }] }, } expect(evaluateConditionalLogic(negative, { tags: 'a' })).toBe(false) expect(evaluateConditionalLogic(negative, { tags: ['b', 'c'] })).toBe(true) }) it('handles empty / not_empty across string, array, null', () => { const empty: ConditionalLogic = { show_when: { all: [{ field_slug: 'x', operator: 'empty' }] } } expect(evaluateConditionalLogic(empty, {})).toBe(true) expect(evaluateConditionalLogic(empty, { x: null })).toBe(true) expect(evaluateConditionalLogic(empty, { x: '' })).toBe(true) expect(evaluateConditionalLogic(empty, { x: [] })).toBe(true) expect(evaluateConditionalLogic(empty, { x: 'hi' })).toBe(false) const notEmpty: ConditionalLogic = { show_when: { all: [{ field_slug: 'x', operator: 'not_empty' }] } } expect(evaluateConditionalLogic(notEmpty, { x: 'hi' })).toBe(true) expect(evaluateConditionalLogic(notEmpty, {})).toBe(false) }) it('evaluates nested all/any groups', () => { const logic: ConditionalLogic = { show_when: { all: [ { field_slug: 'role', operator: 'equals', value: 'admin' }, { any: [ { field_slug: 'region', operator: 'equals', value: 'NL' }, { field_slug: 'region', operator: 'equals', value: 'BE' }, ], }, ], }, } expect(evaluateConditionalLogic(logic, { role: 'admin', region: 'BE' })).toBe(true) expect(evaluateConditionalLogic(logic, { role: 'admin', region: 'DE' })).toBe(false) expect(evaluateConditionalLogic(logic, { role: 'guest', region: 'NL' })).toBe(false) }) it('does not throw on missing field values', () => { const eq: ConditionalLogic = { show_when: { all: [{ field_slug: 'missing', operator: 'equals', value: 'x' }] }, } expect(() => evaluateConditionalLogic(eq, {})).not.toThrow() expect(evaluateConditionalLogic(eq, {})).toBe(false) const emptyCheck: ConditionalLogic = { show_when: { all: [{ field_slug: 'missing', operator: 'empty' }] }, } expect(evaluateConditionalLogic(emptyCheck, {})).toBe(true) }) it('handles greater_than / less_than with non-numeric fallback', () => { const gt: ConditionalLogic = { show_when: { all: [{ field_slug: 'age', operator: 'greater_than', value: 18 }] }, } expect(evaluateConditionalLogic(gt, { age: 20 })).toBe(true) expect(evaluateConditionalLogic(gt, { age: 17 })).toBe(false) expect(evaluateConditionalLogic(gt, { age: 'not-a-number' })).toBe(false) }) })