Skip to content

Commit

Permalink
fix(schema): throw an error when enum values are corrupted in the sch…
Browse files Browse the repository at this point in the history
…ema (#877)
  • Loading branch information
Scra3 committed Nov 15, 2023
1 parent 0c614cd commit d4488c9
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 1 deletion.
15 changes: 15 additions & 0 deletions packages/agent/src/utils/forest-schema/column-schema-validation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { ColumnSchema, ValidationError } from '@forestadmin/datasource-toolkit';

export default class ColumnSchemaValidation {
static validate(column: ColumnSchema, name: string): void {
if (!column.enumValues) return;

if (!Array.isArray(column.enumValues) || !column.enumValues.every(v => typeof v === 'string')) {
throw new ValidationError(
`The enumValues of column '${name}' must be an array of string instead of ${JSON.stringify(
column.enumValues,
)}`,
);
}
}
}
6 changes: 5 additions & 1 deletion packages/agent/src/utils/forest-schema/generator-fields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@ import {
PrimitiveTypes,
RelationSchema,
SchemaUtils,
ValidationError,
} from '@forestadmin/datasource-toolkit';
import { ForestServerColumnType, ForestServerField } from '@forestadmin/forestadmin-client';

import ColumnSchemaValidation from './column-schema-validation';
import FrontendFilterableUtils from './filterable';
import FrontendValidationUtils from './validation';

Expand Down Expand Up @@ -43,7 +45,7 @@ export default class SchemaGeneratorFields {
break;

default:
throw new Error('Invalid field type');
throw new ValidationError('Invalid field type');
}

return Object.entries(schema)
Expand All @@ -57,6 +59,8 @@ export default class SchemaGeneratorFields {

private static buildColumnSchema(collection: Collection, name: string): ForestServerField {
const column = collection.schema.fields[name] as ColumnSchema;
ColumnSchemaValidation.validate(column, name);

const isForeignKey = SchemaUtils.isForeignKey(collection.schema, name);

return {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import ColumnSchemaValidation from '../../../src/utils/forest-schema/column-schema-validation';
import * as factories from '../../__factories__';

describe('ColumnSchemaValidation', () => {
describe('enumValues', () => {
describe('when enumValues is empty', () => {
it('should not throw', () => {
const column = factories.columnSchema.build({
columnType: 'Enum',
enumValues: [],
});
expect(() => ColumnSchemaValidation.validate(column, 'isbn')).not.toThrow();
});
});

describe('when enumValues is not an array', () => {
it('should throw', () => {
const column = factories.columnSchema.build({
columnType: 'Enum',
enumValues: 'not an array' as unknown as string[],
});
expect(() => ColumnSchemaValidation.validate(column, 'isbn')).toThrow(
'The enumValues of column \'isbn\' must be an array of string instead of "not an array"',
);
});
});

describe('when enumValues is not an array of strings', () => {
it('should throw', () => {
const column = factories.columnSchema.build({
columnType: 'Enum',
enumValues: [1, 2, 3] as unknown as string[],
});
expect(() => ColumnSchemaValidation.validate(column, 'isbn')).toThrow(
"The enumValues of column 'isbn' must be an array of string instead of [1,2,3]",
);
});
});

describe('when enumValues is an array of strings', () => {
it('should not throw', () => {
const column = factories.columnSchema.build({
columnType: 'Enum',
enumValues: ['a', 'b', 'c'],
});
expect(() => ColumnSchemaValidation.validate(column, 'isbn')).not.toThrow();
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,29 @@ describe('SchemaGeneratorFields > Column', () => {
});
});

describe('invalid enum values', () => {
const collection = factories.collection.build({
name: 'books',
schema: factories.collectionSchema.build({
fields: {
isbn: factories.columnSchema.build({
columnType: 'Enum',
enumValues: [['ArrayOfArray']] as unknown as string[],
filterOperators: new Set(['Equal']),
}),
},
}),
});

test('should throw if an invalid field is passed', () => {
const fn = () => SchemaGeneratorFields.buildSchema(collection, 'isbn');
expect(fn).toThrow(
"The enumValues of column 'isbn' must be an array of string " +
'instead of [["ArrayOfArray"]]',
);
});
});

describe('required/filterable/readonly/pk/sortable', () => {
const collection = factories.collection.build({
name: 'books',
Expand Down

0 comments on commit d4488c9

Please sign in to comment.