import { CriteriaParser } from '../builders/CriteriaParser' import { AudienceCriteria } from '../types' describe('CriteriaParser', () => { describe('parse', () => { it('parses a valid JSON string into criteria object', () => { const json = JSON.stringify({ groups: [{ rules: [{ field: 'email', op: 'equals', value: 'a@b.com' }] }] }) const result = CriteriaParser.parse(json) expect(result.groups).toBeDefined() expect(result.groups![0].rules![0].value).toBe('a@b.com') }) it('throws on invalid JSON string', () => { expect(() => CriteriaParser.parse('not-json')).toThrow('Critérios inválidos') }) it('passes through an object unchanged if it has groups', () => { const criteria: AudienceCriteria = { groups: [{ operator: 'AND', rules: [{ kind: 'property', field: 'email', op: 'equals', value: 'x' }] }] } const result = CriteriaParser.parse(criteria) expect(result).toEqual(criteria) }) it('normalizes filters format into conditions', () => { const criteria: AudienceCriteria = { filters: [ { id: 'f1', operator: 'AND', conditions: [ { id: 'c1', field: 'email', operator: 'equals', value: 'test@x.com', logicalOperator: 'AND' } ] } ] } const result = CriteriaParser.parse(criteria) expect(result.conditions).toBeDefined() expect(result.conditions!.length).toBe(1) expect(result.conditions![0].groupId).toBe('f1') expect(result.conditions![0].operator).toBe('AND') expect(result.conditions![0].conditions![0].field).toBe('email') }) it('normalizes filter conditions with customFieldKey', () => { const criteria: AudienceCriteria = { filters: [{ id: 'f1', operator: 'OR', conditions: [{ id: 'c1', field: 'custom_field', operator: 'contains', value: 'vip', logicalOperator: 'OR', customFieldKey: 'plan_type' }] }] } const result = CriteriaParser.parse(criteria) expect(result.conditions![0].conditions![0].customFieldKey).toBe('plan_type') }) it('passes through conditions format unchanged', () => { const criteria: AudienceCriteria = { conditions: [{ groupId: 'g1', operator: 'AND', conditions: [{ field: 'name', operator: 'equals', value: 'John' }] }] } const result = CriteriaParser.parse(criteria) expect(result.conditions).toEqual(criteria.conditions) }) }) describe('getAudienceType', () => { it('returns "static" for criteria without type', () => { expect(CriteriaParser.getAudienceType({})).toBe('static') }) it('returns "static" for unknown type', () => { expect(CriteriaParser.getAudienceType({ type: 'past-behavior' })).toBe('static') }) it.each([ 'live-actions', 'live-page-visit', 'live-referrer', 'live-page-count', ])('returns "live" for type "%s"', (type) => { expect(CriteriaParser.getAudienceType({ type })).toBe('live') }) }) describe('validate', () => { it('returns valid for criteria with groups', () => { const result = CriteriaParser.validate({ groups: [] }) expect(result.valid).toBe(true) expect(result.errors).toHaveLength(0) }) it('returns valid for criteria with filters', () => { const result = CriteriaParser.validate({ filters: [{ id: '1', operator: 'AND', conditions: [] }] } as AudienceCriteria) expect(result.valid).toBe(true) }) it('returns valid for criteria with conditions', () => { const result = CriteriaParser.validate({ conditions: [{ groupId: 'g1', operator: 'AND', conditions: [] }] }) expect(result.valid).toBe(true) }) it('returns invalid when no conditions, filters, or groups exist', () => { const result = CriteriaParser.validate({ type: 'static' }) expect(result.valid).toBe(false) expect(result.errors).toContain('Critérios devem conter conditions, filters ou groups') }) it('returns invalid for null-ish input', () => { const result = CriteriaParser.validate(null as any) expect(result.valid).toBe(false) expect(result.errors).toContain('Critérios devem ser um objeto') }) it('returns invalid for non-object input', () => { const result = CriteriaParser.validate('string' as any) expect(result.valid).toBe(false) }) }) })