163 lines
5.1 KiB
TypeScript
163 lines
5.1 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import {
|
|
addDescriptionMatchToRuleStructure,
|
|
buildJsonLogic,
|
|
createDescriptionCondition,
|
|
type RuleStructure,
|
|
} from './rule-builder-utils';
|
|
|
|
describe('createDescriptionCondition', () => {
|
|
it('creates a contains condition for transaction descriptions', () => {
|
|
expect(createDescriptionCondition(' Toast Coffee ')).toMatchObject({
|
|
field: 'description',
|
|
operator: 'contains',
|
|
value: 'Toast Coffee',
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('buildJsonLogic', () => {
|
|
it('builds conditions for counterparty fields', () => {
|
|
const structure: RuleStructure = {
|
|
groupOperator: 'or',
|
|
groups: [
|
|
{
|
|
id: 'group-1',
|
|
operator: 'and',
|
|
conditions: [
|
|
{
|
|
id: 'condition-1',
|
|
field: 'creditor_name',
|
|
operator: 'contains',
|
|
value: 'amazon',
|
|
},
|
|
{
|
|
id: 'condition-2',
|
|
field: 'debtor_name',
|
|
operator: 'is_not_empty',
|
|
value: '',
|
|
},
|
|
],
|
|
},
|
|
],
|
|
};
|
|
|
|
expect(buildJsonLogic(structure)).toMatchObject({
|
|
and: [
|
|
{ in: ['amazon', { var: 'creditor_name' }] },
|
|
{ '!=': [{ var: 'debtor_name' }, null] },
|
|
],
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('addDescriptionMatchToRuleStructure', () => {
|
|
it('adds a new description group to a simple rule', () => {
|
|
const structure: RuleStructure = {
|
|
groupOperator: 'or',
|
|
groups: [
|
|
{
|
|
id: 'group-1',
|
|
operator: 'or',
|
|
conditions: [
|
|
{
|
|
id: 'condition-1',
|
|
field: 'bank_name',
|
|
operator: 'contains',
|
|
value: 'bank',
|
|
},
|
|
],
|
|
},
|
|
],
|
|
};
|
|
|
|
const updated = addDescriptionMatchToRuleStructure(
|
|
structure,
|
|
'Toast Coffee',
|
|
);
|
|
|
|
expect(updated.groupOperator).toBe('or');
|
|
expect(updated.groups).toHaveLength(2);
|
|
expect(updated.groups[1].conditions[0]).toMatchObject({
|
|
field: 'description',
|
|
operator: 'contains',
|
|
value: 'Toast Coffee',
|
|
});
|
|
expect(buildJsonLogic(updated)).toMatchObject({
|
|
or: [
|
|
{ in: ['bank', { var: 'bank_name' }] },
|
|
{ in: ['Toast Coffee', { var: 'description' }] },
|
|
],
|
|
});
|
|
});
|
|
|
|
it('preserves top-level AND semantics when adding a description match', () => {
|
|
const structure: RuleStructure = {
|
|
groupOperator: 'and',
|
|
groups: [
|
|
{
|
|
id: 'group-1',
|
|
operator: 'and',
|
|
conditions: [
|
|
{
|
|
id: 'condition-1',
|
|
field: 'bank_name',
|
|
operator: 'contains',
|
|
value: 'bank',
|
|
},
|
|
{
|
|
id: 'condition-2',
|
|
field: 'amount',
|
|
operator: 'less_than',
|
|
value: '0',
|
|
},
|
|
],
|
|
},
|
|
{
|
|
id: 'group-2',
|
|
operator: 'or',
|
|
conditions: [
|
|
{
|
|
id: 'condition-3',
|
|
field: 'account_name',
|
|
operator: 'contains',
|
|
value: 'checking',
|
|
},
|
|
],
|
|
},
|
|
],
|
|
};
|
|
|
|
const updated = addDescriptionMatchToRuleStructure(
|
|
structure,
|
|
'Toast Coffee',
|
|
);
|
|
const jsonLogic = buildJsonLogic(updated);
|
|
|
|
expect(updated.groupOperator).toBe('and');
|
|
expect(updated.groups).toHaveLength(3);
|
|
expect(jsonLogic).toMatchObject({
|
|
and: [
|
|
{
|
|
or: [
|
|
{ in: ['bank', { var: 'bank_name' }] },
|
|
{ in: ['Toast Coffee', { var: 'description' }] },
|
|
],
|
|
},
|
|
{
|
|
or: [
|
|
{ '<': [{ var: 'amount' }, 0] },
|
|
{ in: ['Toast Coffee', { var: 'description' }] },
|
|
],
|
|
},
|
|
{
|
|
or: [
|
|
{ in: ['checking', { var: 'account_name' }] },
|
|
{ in: ['Toast Coffee', { var: 'description' }] },
|
|
],
|
|
},
|
|
],
|
|
});
|
|
});
|
|
});
|