Skip to content

Commit

Permalink
Initial tests for sequential conditions.
Browse files Browse the repository at this point in the history
  • Loading branch information
derekpierre committed Sep 20, 2024
1 parent b440ad9 commit ef53f6c
Show file tree
Hide file tree
Showing 2 changed files with 278 additions and 0 deletions.
264 changes: 264 additions & 0 deletions packages/taco/test/conditions/sequential.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,264 @@
import { describe, expect, it } from 'vitest';

import { CompoundConditionType } from '../../src/conditions/compound-condition';
import { SUPPORTED_CHAIN_IDS } from '../../src/conditions/const';
import {
ConditionVariableProps,
SequentialCondition,
SequentialConditionProps,
sequentialConditionSchema,
SequentialConditionType,
} from '../../src/conditions/sequential';
import {
testCompoundConditionObj,
testContractConditionObj,
testRpcConditionObj,
testSequentialConditionObj,
testTimeConditionObj,
} from '../test-utils';

describe('validation', () => {
const rpcConditionVariable: ConditionVariableProps = {
varName: 'rpc',
condition: testRpcConditionObj,
};
const timeConditionVariable: ConditionVariableProps = {
varName: 'time',
condition: testTimeConditionObj,
};
const contractConditionVariable: ConditionVariableProps = {
varName: 'contract',
condition: testContractConditionObj,
};
const compoundConditionVariable: ConditionVariableProps = {
varName: 'compound',
condition: testCompoundConditionObj,
};
const sequentialConditionVariable: ConditionVariableProps = {
varName: 'nestedSequential',
condition: testSequentialConditionObj,
};

it('rejects no varName', () => {
const result = SequentialCondition.validate(sequentialConditionSchema, {
conditionVariables: [
rpcConditionVariable,
{
condition: testTimeConditionObj,
},
],
});

expect(result.error).toBeDefined();
expect(result.data).toBeUndefined();
expect(result.error?.format()).toMatchObject({
conditionVariables: {
'1': {
varName: {
_errors: ['Required'],
},
},
},
});
});

it('rejects > max number of condition variables', () => {
const tooManyConditionVariables = new Array(6);
for (let i = 0; i < tooManyConditionVariables.length; i++) {
tooManyConditionVariables[i] = {
varName: `var${i}`,
condition: testRpcConditionObj,
};
}
const result = SequentialCondition.validate(sequentialConditionSchema, {
conditionVariables: tooManyConditionVariables,
});

expect(result.error).toBeDefined();
expect(result.data).toBeUndefined();
expect(result.error?.format()).toMatchObject({
conditionVariables: {
_errors: [`Array must contain at most 5 element(s)`],
},
});
});

it('accepts nested compound conditions', () => {
const conditionObj = {
conditionType: SequentialConditionType,
conditionVariables: [
rpcConditionVariable,
timeConditionVariable,
contractConditionVariable,
compoundConditionVariable,
],
};
const result = SequentialCondition.validate(
sequentialConditionSchema,
conditionObj,
);
expect(result.error).toBeUndefined();
expect(result.data).toEqual({
conditionType: SequentialConditionType,
conditionVariables: [
rpcConditionVariable,
timeConditionVariable,
contractConditionVariable,
compoundConditionVariable,
],
});
});

it('accepts nested sequential and compound conditions', () => {
const conditionObj = {
conditionType: SequentialConditionType,
conditionVariables: [
rpcConditionVariable,
timeConditionVariable,
contractConditionVariable,
compoundConditionVariable,
sequentialConditionVariable,
],
};
const result = SequentialCondition.validate(
sequentialConditionSchema,
conditionObj,
);
expect(result.error).toBeUndefined();
expect(result.data).toEqual({
conditionType: SequentialConditionType,
conditionVariables: [
rpcConditionVariable,
timeConditionVariable,
contractConditionVariable,
compoundConditionVariable,
sequentialConditionVariable,
],
});
});

it('limits max depth of nested compound condition', () => {
const result = SequentialCondition.validate(sequentialConditionSchema, {
conditionVariables: [
rpcConditionVariable,
contractConditionVariable,
{
varName: 'compound',
condition: {
conditionType: CompoundConditionType,
operator: 'not',
operands: [
{
conditionType: CompoundConditionType,
operator: 'and',
operands: [testTimeConditionObj, testRpcConditionObj],
},
],
},
},
],
});
expect(result.error).toBeDefined();
expect(result.data).toBeUndefined();
expect(result.error?.format()).toMatchObject({
conditionVariables: {
_errors: [`Exceeded max nested depth of 2 for multi-condition type`],
},
});
});

it('limits max depth of nested sequential condition', () => {
const result = SequentialCondition.validate(sequentialConditionSchema, {
conditionVariables: [
rpcConditionVariable,
contractConditionVariable,
{
varName: 'sequentialNested',
condition: {
conditionType: SequentialConditionType,
conditionVariables: [
timeConditionVariable,
sequentialConditionVariable,
],
},
},
],
});
expect(result.error).toBeDefined();
expect(result.data).toBeUndefined();
expect(result.error?.format()).toMatchObject({
conditionVariables: {
_errors: ['Exceeded max nested depth of 2 for multi-condition type'],
},
});
});

it('accepts on a valid multichain condition schema', () => {
const multichainCondition: SequentialConditionProps = {
conditionType: SequentialConditionType,
conditionVariables: SUPPORTED_CHAIN_IDS.map((chain) => ({
varName: `chain_${chain}`,
condition: {
...testRpcConditionObj,
chain,
},
})),
};

const result = SequentialCondition.validate(
sequentialConditionSchema,
multichainCondition,
);

expect(result.error).toBeUndefined();
expect(result.data).toEqual(multichainCondition);
});

it('rejects an invalid multichain condition schema', () => {
const badMultichainCondition: SequentialConditionProps = {
conditionType: SequentialConditionType,
conditionVariables: [
{
varName: 'chain_1',
condition: {
...testRpcConditionObj,
chain: 1,
},
},
{
varName: 'chain_137',
condition: {
...testRpcConditionObj,
chain: 137,
},
},
{
varName: `invalid_chain`,
condition: {
...testRpcConditionObj,
chain: -1,
},
},
],
};

const result = SequentialCondition.validate(
sequentialConditionSchema,
badMultichainCondition,
);

expect(result.error).toBeDefined();
expect(result.data).toBeUndefined();
});

it('infers default condition type from constructor', () => {
const condition = new SequentialCondition({
conditionVariables: [
contractConditionVariable,
timeConditionVariable,
rpcConditionVariable,
],
});
expect(condition.value.conditionType).toEqual(SequentialConditionType);
});
});
14 changes: 14 additions & 0 deletions packages/taco/test/test-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ import {
TimeConditionProps,
TimeConditionType,
} from '../src/conditions/base/time';
import {
CompoundConditionProps,
CompoundConditionType,
} from '../src/conditions/compound-condition';
import { ConditionExpression } from '../src/conditions/condition-expr';
import { ERC721Balance } from '../src/conditions/predefined/erc721';
import {
Expand Down Expand Up @@ -245,6 +249,16 @@ export const testContractConditionObj: ContractConditionProps = {
returnValueTest: testReturnValueTest,
};

export const testCompoundConditionObj: CompoundConditionProps = {
conditionType: CompoundConditionType,
operator: 'or',
operands: [
testRpcConditionObj,
testTimeConditionObj,
testContractConditionObj,
],
};

export const testSequentialConditionObj: SequentialConditionProps = {
conditionType: SequentialConditionType,
conditionVariables: [
Expand Down

0 comments on commit ef53f6c

Please sign in to comment.