Skip to content

Commit

Permalink
Rework evaluation attribute schema validation (#441)
Browse files Browse the repository at this point in the history
  • Loading branch information
denis-rossati authored Nov 14, 2024
1 parent 38a568d commit 83fad07
Show file tree
Hide file tree
Showing 3 changed files with 226 additions and 47 deletions.
45 changes: 43 additions & 2 deletions src/schema/evaluatorSchemas.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,52 @@
import {ObjectType, NumberType, JsonObjectType} from '../validation';
import {
ObjectType,
NumberType,
JsonObjectType,
UnionType,
StringType,
NullType,
BooleanType,
TypeSchema,
ArrayType,
} from '../validation';

function createJsonSchema(maximumDepth: number): TypeSchema {
return new UnionType(
new NullType(),
new NumberType(),
new BooleanType(),
new StringType({maxLength: 255}),
...(maximumDepth > 1
? [
new JsonObjectType({
propertyNames: new UnionType(
new NumberType(),
new StringType({
minLength: 1,
maxLength: 50,
}),
),
properties: createJsonSchema(maximumDepth - 1),
}),
new ArrayType({items: createJsonSchema(maximumDepth - 1)}),
]
: []
),
);
}

export const evaluationOptionsSchema = new ObjectType({
properties: {
timeout: new NumberType({
integer: true,
minimum: 0,
}),
attributes: new JsonObjectType(),
attributes: new JsonObjectType({
propertyNames: new StringType({
minLength: 1,
maxLength: 50,
}),
properties: createJsonSchema(5),
}),
},
});
45 changes: 0 additions & 45 deletions test/schemas/evaluationSchemas.test.ts

This file was deleted.

183 changes: 183 additions & 0 deletions test/schemas/evaluatorSchemas.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
import {evaluationOptionsSchema} from '../../src/schema';
import {EvaluationOptions} from '../../src/facade/evaluatorFacade';

describe('The evaluator options schema', () => {
it.each<EvaluationOptions[]>([
[{}],
[{
timeout: 1,
}],
[{
attributes: {foo: 'bar'},
}],
[{
timeout: 1,
attributes: {foo: 'bar'},
}],
[{
timeout: 1,
attributes: {},
}],
[{
timeout: 1,
attributes: {
['x'.repeat(50)]: 'x'.repeat(255),
'multi-byte character': '♥'.repeat(255),
arr: [
null,
123,
'x'.repeat(255),
true,
false,
],
first: {
second: {
third: {
'nested array': [
null,
123,
'x'.repeat(255),
true,
false,
],
fourth: {
fifth: '',
},
},
},
},
},
}],
])('should allow %s', value => {
function validate(): void {
evaluationOptionsSchema.validate(value);
}

expect(validate).not.toThrow();
});

it.each([
[
{timeout: -1},
'Expected a value greater than or equal to 0 at path \'/timeout\', actual -1.',
],
[
{timeout: 1.2},
'Expected value of type integer at path \'/timeout\', actual number.',
],
[
{attributes: 0},
'Expected a JSON object at path \'/attributes\', actual integer.',
],
[
{
attributes: {
first: {
second: {
third: {
fourth: {
fifth: {},
},
},
},
},
},
},
'Expected value of type null, number, boolean or string'
+ ' at path \'/attributes/first/second/third/fourth/fifth\', actual Object.',
],
[
{
attributes: {
first: [
[
[
[
['fifth level'],
],
],
],
],
},
},
'Expected value of type null, number, boolean or string'
+ ' at path \'/attributes/first/0/0/0/0\', actual array.',
],
[
{
attributes: {
foo: undefined,
},
},
'Expected a JSON object at path \'/attributes\', actual Object.',
],
[
{
attributes: {
'': 'foo',
},
},
'Expected at least 1 character at path \'/attributes/\', actual 0.',
],
[
{
attributes: {
['x'.repeat(51)]: 'foo',
},
},
`Expected at most 50 characters at path '/attributes/${'x'.repeat(51)}', actual 51.`,
],
[
{
attributes: 'foo',
},
'Expected a JSON object at path \'/attributes\', actual string.',
],
[
{
attributes: {
string: 'x'.repeat(256),
},
},
'Expected at most 255 characters at path \'/attributes/string\', actual 256.',
],
[
{
attributes: {
first: {
second: {
third: {
fourth: {
fifth: 'x'.repeat(256),
},
},
},
},
},
},
'Expected at most 255 characters at path \'/attributes/first/second/third/fourth/fifth\', actual 256.',
],
[
{
attributes: {
first: [
[
[
[
'x'.repeat(256),
],
],
],
],
},
},
'Expected at most 255 characters at path \'/attributes/first/0/0/0/0\', actual 256.',
],
])('should not allow %s', (value: Record<string, unknown>, message: string) => {
function validate(): void {
evaluationOptionsSchema.validate(value);
}

expect(validate).toThrowWithMessage(Error, message);
});
});

0 comments on commit 83fad07

Please sign in to comment.