1
1
mirror of https://github.com/n8n-io/n8n.git synced 2024-10-04 00:28:27 +03:00

ci: Start typechecking n8n-workflow and n8n-core (no-changelog) (#9925)

Co-authored-by: Danny Martini <danny@n8n.io>
This commit is contained in:
कारतोफ्फेलस्क्रिप्ट™ 2024-07-03 18:27:07 +02:00 committed by GitHub
parent 47cd411436
commit 24091dfd9b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 479 additions and 410 deletions

View File

@ -13,7 +13,7 @@
"build": "turbo run build",
"build:backend": "pnpm --filter=!@n8n/chat --filter=!@n8n/codemirror-lang --filter=!n8n-design-system --filter=!n8n-editor-ui build",
"build:frontend": "pnpm --filter=@n8n/chat --filter=@n8n/codemirror-lang --filter=n8n-design-system --filter=n8n-editor-ui build",
"typecheck": "pnpm --filter=!@n8n/storybook --filter=!n8n-core --filter=!n8n-workflow --filter=!n8n typecheck",
"typecheck": "pnpm --filter=!n8n typecheck",
"dev": "turbo run dev --parallel --filter=!n8n-design-system --filter=!@n8n/chat",
"dev:ai": "turbo run dev --parallel --filter=@n8n/nodes-langchain --filter=n8n --filter=n8n-core",
"clean": "turbo run clean --parallel",

File diff suppressed because it is too large Load Diff

View File

@ -23,7 +23,10 @@ const getTargetType = (type: FilterOperatorType) => {
return 'string';
};
const convertToType = (value: NodeParameterValue, type: FilterOperatorType): NodeParameterValue => {
const convertToType = (
value: NodeParameterValue | NodeParameterValue[],
type: FilterOperatorType,
): NodeParameterValue | NodeParameterValue[] => {
if (type === 'any') return value;
const fallback = type === 'boolean' ? false : value;

View File

@ -2474,9 +2474,9 @@ export interface FilterOperatorValue {
export type FilterConditionValue = {
id: string;
leftValue: NodeParameterValue;
leftValue: NodeParameterValue | NodeParameterValue[];
operator: FilterOperatorValue;
rightValue: NodeParameterValue;
rightValue: NodeParameterValue | NodeParameterValue[];
};
export type FilterOptionsValue = {

View File

@ -7,6 +7,12 @@ type DeepPartial<T> = {
[P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
};
type Tests = Array<{
left: FilterConditionValue['leftValue'];
right: FilterConditionValue['rightValue'];
expected: boolean;
}>;
const filterFactory = (data: DeepPartial<FilterValue> = {}): FilterValue =>
merge(
{
@ -832,21 +838,24 @@ describe('FilterParameter', () => {
right: '1-Feb-2024',
expected: false,
},
])('dateTime:after("$left", "$right") === $expected', ({ left, right, expected }) => {
const result = executeFilter(
filterFactory({
conditions: [
{
id: '1',
leftValue: left,
rightValue: right,
operator: { operation: 'after', type: 'dateTime' },
},
],
}),
);
expect(result).toBe(expected);
});
] as Tests)(
'dateTime:after("$left", "$right") === $expected',
({ left, right, expected }) => {
const result = executeFilter(
filterFactory({
conditions: [
{
id: '1',
leftValue: left,
rightValue: right,
operator: { operation: 'after', type: 'dateTime' },
},
],
}),
);
expect(result).toBe(expected);
},
);
it.each([
{ left: '2023-11-15T17:10:49.113Z', right: '2023-11-15T17:10:49.113Z', expected: false },
@ -1035,7 +1044,7 @@ describe('FilterParameter', () => {
it.each([
{ left: ['foo', 'bar'], right: 'foo', expected: true },
{ left: ['foo', 'bar'], right: 'ba', expected: false },
])('array:contains($left,$right) === $expected', ({ left, right, expected }) => {
] as Tests)('array:contains($left,$right) === $expected', ({ left, right, expected }) => {
const result = executeFilter(
filterFactory({
conditions: [
@ -1054,67 +1063,76 @@ describe('FilterParameter', () => {
it.each([
{ left: ['foo', 'bar'], right: 'foo', expected: false },
{ left: ['foo', 'bar'], right: 'ba', expected: true },
])('array:notContains($left,$right) === $expected', ({ left, right, expected }) => {
const result = executeFilter(
filterFactory({
conditions: [
{
id: '1',
leftValue: left,
rightValue: right,
operator: { operation: 'notContains', type: 'array', rightType: 'any' },
},
],
}),
);
expect(result).toBe(expected);
});
] as Tests)(
'array:notContains($left,$right) === $expected',
({ left, right, expected }) => {
const result = executeFilter(
filterFactory({
conditions: [
{
id: '1',
leftValue: left,
rightValue: right,
operator: { operation: 'notContains', type: 'array', rightType: 'any' },
},
],
}),
);
expect(result).toBe(expected);
},
);
it.each([
{ left: ['foo', 'bar'], right: 2, expected: true },
{ left: [], right: 0, expected: true },
{ left: ['foo', 'bar'], right: 1, expected: false },
])('array:lengthEquals($left,$right) === $expected', ({ left, right, expected }) => {
const result = executeFilter(
filterFactory({
conditions: [
{
id: '1',
leftValue: left,
rightValue: right,
operator: { operation: 'lengthEquals', type: 'array', rightType: 'number' },
},
],
}),
);
expect(result).toBe(expected);
});
] as Tests)(
'array:lengthEquals($left,$right) === $expected',
({ left, right, expected }) => {
const result = executeFilter(
filterFactory({
conditions: [
{
id: '1',
leftValue: left,
rightValue: right,
operator: { operation: 'lengthEquals', type: 'array', rightType: 'number' },
},
],
}),
);
expect(result).toBe(expected);
},
);
it.each([
{ left: ['foo', 'bar'], right: 2, expected: false },
{ left: [], right: 0, expected: false },
{ left: ['foo', 'bar'], right: 1, expected: true },
])('array:lengthNotEquals($left,$right) === $expected', ({ left, right, expected }) => {
const result = executeFilter(
filterFactory({
conditions: [
{
id: '1',
leftValue: left,
rightValue: right,
operator: { operation: 'lengthNotEquals', type: 'array', rightType: 'number' },
},
],
}),
);
expect(result).toBe(expected);
});
] as Tests)(
'array:lengthNotEquals($left,$right) === $expected',
({ left, right, expected }) => {
const result = executeFilter(
filterFactory({
conditions: [
{
id: '1',
leftValue: left,
rightValue: right,
operator: { operation: 'lengthNotEquals', type: 'array', rightType: 'number' },
},
],
}),
);
expect(result).toBe(expected);
},
);
it.each([
{ left: ['foo', 'bar'], right: 2, expected: false },
{ left: [], right: 0, expected: false },
{ left: ['foo', 'bar'], right: 1, expected: true },
])('array:lengthGt($left,$right) === $expected', ({ left, right, expected }) => {
] as Tests)('array:lengthGt($left,$right) === $expected', ({ left, right, expected }) => {
const result = executeFilter(
filterFactory({
conditions: [
@ -1135,7 +1153,7 @@ describe('FilterParameter', () => {
{ left: [], right: 0, expected: false },
{ left: ['foo', 'bar'], right: 1, expected: false },
{ left: ['foo', 'bar'], right: 3, expected: true },
])('array:lengthLt($left,$right) === $expected', ({ left, right, expected }) => {
] as Tests)('array:lengthLt($left,$right) === $expected', ({ left, right, expected }) => {
const result = executeFilter(
filterFactory({
conditions: [
@ -1156,7 +1174,7 @@ describe('FilterParameter', () => {
{ left: [], right: 0, expected: true },
{ left: ['foo', 'bar'], right: 1, expected: true },
{ left: ['foo', 'bar'], right: 3, expected: false },
])('array:lengthGte($left,$right) === $expected', ({ left, right, expected }) => {
] as Tests)('array:lengthGte($left,$right) === $expected', ({ left, right, expected }) => {
const result = executeFilter(
filterFactory({
conditions: [
@ -1177,7 +1195,7 @@ describe('FilterParameter', () => {
{ left: [], right: 0, expected: true },
{ left: ['foo', 'bar'], right: 1, expected: false },
{ left: ['foo', 'bar'], right: 3, expected: true },
])('array:lengthLte($left,$right) === $expected', ({ left, right, expected }) => {
] as Tests)('array:lengthLte($left,$right) === $expected', ({ left, right, expected }) => {
const result = executeFilter(
filterFactory({
conditions: [

View File

@ -9,7 +9,7 @@ import {
} from '@/TelemetryHelpers';
import { nodeTypes } from './ExpressionExtensions/Helpers';
import * as nodeHelpers from '@/NodeHelpers';
import type { IWorkflowBase } from '@/Interfaces';
import { NodeConnectionType, type IWorkflowBase } from '@/Interfaces';
import { STICKY_NODE_TYPE } from '@/Constants';
import { ApplicationError } from '@/errors';
import { randomInt } from '@/utils';
@ -111,7 +111,7 @@ describe('generateNodesGraph', () => {
],
connections: {
'When clicking "Execute Workflow"': {
main: [[{ node: 'Google Sheets', type: 'main', index: 0 }]],
main: [[{ node: 'Google Sheets', type: NodeConnectionType.Main, index: 0 }]],
},
},
settings: { executionOrder: 'v1' },
@ -215,7 +215,7 @@ describe('generateNodesGraph', () => {
],
connections: {
'When clicking "Execute Workflow"': {
main: [[{ node: 'Google Sheets', type: 'main', index: 0 }]],
main: [[{ node: 'Google Sheets', type: NodeConnectionType.Main, index: 0 }]],
},
},
settings: { executionOrder: 'v1' },
@ -291,7 +291,7 @@ describe('generateNodesGraph', () => {
],
connections: {
'When clicking "Execute Workflow"': {
main: [[{ node: 'Google Sheets', type: 'main', index: 0 }]],
main: [[{ node: 'Google Sheets', type: NodeConnectionType.Main, index: 0 }]],
},
},
settings: { executionOrder: 'v1' },
@ -369,7 +369,7 @@ describe('generateNodesGraph', () => {
],
connections: {
'When clicking "Execute Workflow"': {
main: [[{ node: 'Google Sheets', type: 'main', index: 0 }]],
main: [[{ node: 'Google Sheets', type: NodeConnectionType.Main, index: 0 }]],
},
},
settings: { executionOrder: 'v1' },
@ -701,7 +701,7 @@ describe('generateNodesGraph', () => {
[
{
node: 'Chain',
type: 'main',
type: NodeConnectionType.Main,
index: 0,
},
],
@ -712,7 +712,7 @@ describe('generateNodesGraph', () => {
[
{
node: 'Chain',
type: 'ai_languageModel',
type: NodeConnectionType.AiLanguageModel,
index: 0,
},
],

View File

@ -1,179 +1,212 @@
import { getValueDescription, validateFieldType } from '@/TypeValidation';
import { DateTime } from 'luxon';
const VALID_ISO_DATES = [
'1994-11-05T08:15:30-05:00',
'1994-11-05T13:15:30Z',
'1997-07-16T19:20+01:00',
'1997-07-16T19:20:30+01:00',
'1997-07-16T19:20:30.45+01:00',
'2018-05-16',
'1972-06-30T23:59:40Z',
'2019-03-26T14:00:00.9Z',
'2019-03-26T14:00:00.4999Z',
'2023-05-17T10:52:32+0000',
'2023-05-17T10:52:32+0000',
];
const VALID_HTTP_DATES = [
'Wed, 21 Oct 2015 07:28:00 GMT',
'Wed, 01 Jun 2022 08:00:00 GMT',
'Tue, 15 Nov 1994 12:45:26 GMT',
'Wed, 1 Jun 2022 08:00:00 GMT',
];
const VALID_RFC_DATES = [
'Tue, 04 Jun 2013 07:40:03 -0400',
'Tue, 4 Jun 2013 02:24:39 +0530',
'Wed, 17 May 2023 10:52:32 +0000',
];
const VALID_SQL_DATES = ['2008-11-11', '2008-11-11 13:23:44'];
const OTHER_VALID_DATES = [
'Wed, 17 May 2023 10:52:32',
'SMT, 17 May 2023 10:52:32',
'1-Feb-2024',
new Date(),
DateTime.now(),
];
const INVALID_DATES = [
'1994-11-05M08:15:30-05:00',
'18-05-2020',
'',
'1685084980', // We are not supporting timestamps
'1685085012135',
1685084980,
1685085012135,
true,
[],
];
import { getValueDescription, validateFieldType } from '@/TypeValidation';
describe('Type Validation', () => {
describe('Dates', () => {
test.each(VALID_ISO_DATES)('should validate and cast ISO date "%s"', (date) => {
const validationResult = validateFieldType('date', date, 'dateTime');
expect(validationResult.valid).toBe(true);
expect((validationResult.newValue as DateTime).isValid).toBe(true);
test('should validate and cast ISO dates', () => {
const VALID_ISO_DATES = [
'1994-11-05T08:15:30-05:00',
'1994-11-05T13:15:30Z',
'1997-07-16T19:20+01:00',
'1997-07-16T19:20:30+01:00',
'1997-07-16T19:20:30.45+01:00',
'2018-05-16',
'1972-06-30T23:59:40Z',
'2019-03-26T14:00:00.9Z',
'2019-03-26T14:00:00.4999Z',
'2023-05-17T10:52:32+0000',
'2023-05-17T10:52:32+0000',
];
VALID_ISO_DATES.forEach((date) =>
expect(validateFieldType('date', date, 'dateTime')).toEqual({
valid: true,
newValue: expect.any(DateTime),
}),
);
});
test.each(VALID_RFC_DATES)('should validate and cast RFC2822 date "%s"', (date) => {
const validationResult = validateFieldType('date', date, 'dateTime');
expect(validationResult.valid).toBe(true);
expect((validationResult.newValue as DateTime).isValid).toBe(true);
test('should validate and cast RFC2822 dates', () => {
const VALID_RFC_DATES = [
'Tue, 04 Jun 2013 07:40:03 -0400',
'Tue, 4 Jun 2013 02:24:39 +0530',
'Wed, 17 May 2023 10:52:32 +0000',
];
VALID_RFC_DATES.forEach((date) =>
expect(validateFieldType('date', date, 'dateTime')).toEqual({
valid: true,
newValue: expect.any(DateTime),
}),
);
});
test.each(VALID_HTTP_DATES)('should validate and cast HTTP date "%s"', (date) => {
const validationResult = validateFieldType('date', date, 'dateTime');
expect(validationResult.valid).toBe(true);
expect((validationResult.newValue as DateTime).isValid).toBe(true);
test('should validate and cast HTTP dates', () => {
const VALID_HTTP_DATES = [
'Wed, 21 Oct 2015 07:28:00 GMT',
'Wed, 01 Jun 2022 08:00:00 GMT',
'Tue, 15 Nov 1994 12:45:26 GMT',
'Wed, 1 Jun 2022 08:00:00 GMT',
];
VALID_HTTP_DATES.forEach((date) =>
expect(validateFieldType('date', date, 'dateTime')).toEqual({
valid: true,
newValue: expect.any(DateTime),
}),
);
});
test.each(VALID_SQL_DATES)('should validate and cast SQL date "%s"', (date) => {
const validationResult = validateFieldType('date', date, 'dateTime');
expect(validationResult.valid).toBe(true);
expect((validationResult.newValue as DateTime).isValid).toBe(true);
test('should validate and cast SQL dates', () => {
const VALID_SQL_DATES = ['2008-11-11', '2008-11-11 13:23:44'];
VALID_SQL_DATES.forEach((date) =>
expect(validateFieldType('date', date, 'dateTime')).toEqual({
valid: true,
newValue: expect.any(DateTime),
}),
);
});
test.each(OTHER_VALID_DATES)('should validate and cast date "%s"', (date) => {
const validationResult = validateFieldType('date', date, 'dateTime');
expect(validationResult.valid).toBe(true);
expect((validationResult.newValue as DateTime).isValid).toBe(true);
test('should validate and cast other valid dates', () => {
const OTHER_VALID_DATES = [
'Wed, 17 May 2023 10:52:32',
'SMT, 17 May 2023 10:52:32',
'1-Feb-2024',
new Date(),
DateTime.now(),
];
OTHER_VALID_DATES.forEach((date) =>
expect(validateFieldType('date', date, 'dateTime')).toEqual({
valid: true,
newValue: expect.any(DateTime),
}),
);
});
test.each(INVALID_DATES)('should not validate invalid date "%s"', (date) => {
const validationResult = validateFieldType('date', date, 'dateTime');
expect(validationResult.valid).toBe(false);
test('should not validate invalid dates', () => {
const INVALID_DATES = [
'1994-11-05M08:15:30-05:00',
'18-05-2020',
'',
'1685084980', // We are not supporting timestamps
'1685085012135',
1685084980,
1685085012135,
true,
[],
];
INVALID_DATES.forEach((date) =>
expect(validateFieldType('date', date, 'dateTime').valid).toBe(false),
);
});
});
it('should validate boolean values properly', () => {
expect(validateFieldType('boolean', 'true', 'boolean').newValue).toBe(true);
expect(validateFieldType('boolean', 'TRUE', 'boolean').newValue).toBe(true);
expect(validateFieldType('boolean', 1, 'boolean').newValue).toBe(true);
expect(validateFieldType('boolean', '1', 'boolean').newValue).toBe(true);
expect(validateFieldType('boolean', '01', 'boolean').newValue).toBe(true);
expect(validateFieldType('boolean', 'false', 'boolean').newValue).toBe(false);
expect(validateFieldType('boolean', 'FALSE', 'boolean').newValue).toBe(false);
expect(validateFieldType('boolean', '0', 'boolean').newValue).toBe(false);
expect(validateFieldType('boolean', '000', 'boolean').newValue).toBe(false);
expect(validateFieldType('boolean', '0000', 'boolean').newValue).toBe(false);
expect(validateFieldType('boolean', 0, 'boolean').newValue).toBe(false);
const TRUE_VALUES = ['true', 'TRUE', 1, '1', '01'];
TRUE_VALUES.forEach((value) =>
expect(validateFieldType('boolean', value, 'boolean')).toEqual({
valid: true,
newValue: true,
}),
);
const FALSE_VALUES = ['false', 'FALSE', 0, '0', '000', '0000'];
FALSE_VALUES.forEach((value) =>
expect(validateFieldType('boolean', value, 'boolean')).toEqual({
valid: true,
newValue: false,
}),
);
});
it('should not validate invalid boolean values', () => {
expect(validateFieldType('boolean', 'tru', 'boolean').valid).toBe(false);
expect(validateFieldType('boolean', 'fals', 'boolean').valid).toBe(false);
expect(validateFieldType('boolean', 1111, 'boolean').valid).toBe(false);
expect(validateFieldType('boolean', 2, 'boolean').valid).toBe(false);
expect(validateFieldType('boolean', -1, 'boolean').valid).toBe(false);
expect(validateFieldType('boolean', 'yes', 'boolean').valid).toBe(false);
expect(validateFieldType('boolean', 'no', 'boolean').valid).toBe(false);
const INVALID_VALUES = ['tru', 'fals', 1111, 2, -1, 'yes', 'no'];
INVALID_VALUES.forEach((value) =>
expect(validateFieldType('boolean', value, 'boolean').valid).toEqual(false),
);
});
it('should validate and cast numbers', () => {
expect(validateFieldType('number', '1', 'number').newValue).toBe(1);
expect(validateFieldType('number', '-1', 'number').newValue).toBe(-1);
expect(validateFieldType('number', '1.1', 'number').newValue).toBe(1.1);
expect(validateFieldType('number', '-1.1', 'number').newValue).toBe(-1.1);
expect(validateFieldType('number', 1, 'number').newValue).toBe(1);
expect(validateFieldType('number', 'A', 'number').valid).toBe(false);
expect(validateFieldType('number', '1,1', 'number').valid).toBe(false);
expect(validateFieldType('number', true, 'number').valid).toBe(true);
expect(validateFieldType('number', '1972-06-30T23:59:40Z', 'number').valid).toBe(false);
expect(validateFieldType('number', [1, 2], 'number').valid).toBe(false);
const VALID_NUMBERS = [
['1', 1],
['-1', -1],
['1.1', 1.1],
['-1.1', -1.1],
[1, 1],
[true, 1],
];
VALID_NUMBERS.forEach(([value, expected]) =>
expect(validateFieldType('number', value, 'number')).toEqual({
valid: true,
newValue: expected,
}),
);
const INVALID_NUMBERS = ['A', '1,1', '1972-06-30T23:59:40Z', [1, 2]];
INVALID_NUMBERS.forEach((value) =>
expect(validateFieldType('number', value, 'number').valid).toEqual(false),
);
});
it('should validate and cast JSON properly', () => {
expect(validateFieldType('json', '{"a": 1}', 'object').newValue).toEqual({ a: 1 });
expect(
validateFieldType('json', '{"a": 1, "b": { "c": 10, "d": "test"}}', 'object').valid,
).toEqual(true);
expect(validateFieldType('json', { name: 'John' }, 'object').valid).toEqual(true);
expect(
validateFieldType(
'json',
const VALID_OBJECTS = [
['{"a": 1}', { a: 1 }],
['{"a": 1, "b": { "c": 10, "d": "test"}}', { a: 1, b: { c: 10, d: 'test' } }],
[{ name: 'John' }, { name: 'John' }],
[
{ name: 'John', address: { street: 'Via Roma', city: 'Milano' } },
'object',
).valid,
).toEqual(true);
// Invalid value:
expect(validateFieldType('json', ['one', 'two'], 'object').valid).toEqual(false);
expect(validateFieldType('json', ['one', 'two'], 'object').valid).toEqual(false);
expect(validateFieldType('json', '1', 'object').valid).toEqual(false);
expect(validateFieldType('json', '[1]', 'object').valid).toEqual(false);
expect(validateFieldType('json', '1.1', 'object').valid).toEqual(false);
expect(validateFieldType('json', 1.1, 'object').valid).toEqual(false);
expect(validateFieldType('json', '"a"', 'object').valid).toEqual(false);
expect(validateFieldType('json', '{a: 1}', 'object').valid).toEqual(false);
expect(validateFieldType('json', '["apples", "oranges"]', 'object').valid).toEqual(false);
expect(validateFieldType('json', [{ name: 'john' }, { name: 'bob' }], 'object').valid).toEqual(
false,
{ name: 'John', address: { street: 'Via Roma', city: 'Milano' } },
],
];
VALID_OBJECTS.forEach(([value, expected]) =>
expect(validateFieldType('json', value, 'object')).toEqual({
valid: true,
newValue: expected,
}),
);
const INVALID_JSON = [
['one', 'two'],
'1',
'[1]',
'1.1',
1.1,
'"a"',
'{a: 1}',
'["apples", "oranges"]',
[{ name: 'john' }, { name: 'bob' }],
'[ { name: "john" }, { name: "bob" } ]',
];
INVALID_JSON.forEach((value) =>
expect(validateFieldType('json', value, 'object').valid).toEqual(false),
);
expect(
validateFieldType('json', '[ { name: "john" }, { name: "bob" } ]', 'object').valid,
).toEqual(false);
});
it('should validate and cast arrays properly', () => {
expect(validateFieldType('array', '["apples", "oranges"]', 'array').newValue).toEqual([
'apples',
'oranges',
]);
expect(validateFieldType('array', '[1]', 'array').newValue).toEqual([1]);
expect(validateFieldType('array', '[1, 2]', 'array').newValue).toEqual([1, 2]);
// Invalid values:
expect(validateFieldType('array', '"apples", "oranges"', 'array').valid).toEqual(false);
expect(validateFieldType('array', '1', 'array').valid).toEqual(false);
expect(validateFieldType('array', '1.1', 'array').valid).toEqual(false);
expect(validateFieldType('array', '1, 2', 'array').valid).toEqual(false);
expect(validateFieldType('array', '1. 2. 3', 'array').valid).toEqual(false);
expect(validateFieldType('array', '[1, 2, 3', 'array').valid).toEqual(false);
expect(validateFieldType('array', '1, 2, 3]', 'array').valid).toEqual(false);
expect(validateFieldType('array', '{1, 2, {3, 4}, 5}', 'array').valid).toEqual(false);
expect(validateFieldType('array', '1, 2, {3, 4}, 5', 'array').valid).toEqual(false);
expect(validateFieldType('array', { name: 'John' }, 'array').valid).toEqual(false);
const VALID_ARRAYS = [
['["apples", "oranges"]', ['apples', 'oranges']],
['[1]', [1]],
['[1, 2]', [1, 2]],
];
VALID_ARRAYS.forEach(([value, expected]) =>
expect(validateFieldType('array', value, 'array')).toEqual({
valid: true,
newValue: expected,
}),
);
const INVALID_ARRAYS = [
'"apples", "oranges"',
'1',
'1.1',
'1, 2',
'1. 2. 3',
'[1, 2, 3',
'1, 2, 3]',
'{1, 2, {3, 4}, 5}',
'1, 2, {3, 4}, 5',
{ name: 'John' },
];
INVALID_ARRAYS.forEach((value) =>
expect(validateFieldType('array', value, 'array').valid).toEqual(false),
);
});
it('should validate options properly', () => {
@ -196,19 +229,27 @@ describe('Type Validation', () => {
});
it('should validate and cast time properly', () => {
expect(validateFieldType('time', '23:23', 'time').valid).toEqual(true);
expect(validateFieldType('time', '23:23:23', 'time').valid).toEqual(true);
expect(validateFieldType('time', '23:23:23+1000', 'time').valid).toEqual(true);
expect(validateFieldType('time', '23:23:23-1000', 'time').valid).toEqual(true);
expect(validateFieldType('time', '22:00:00+01:00', 'time').valid).toEqual(true);
expect(validateFieldType('time', '22:00:00-01:00', 'time').valid).toEqual(true);
expect(validateFieldType('time', '22:00:00+01', 'time').valid).toEqual(true);
expect(validateFieldType('time', '22:00:00-01', 'time').valid).toEqual(true);
expect(validateFieldType('time', '23:23:23:23', 'time').valid).toEqual(false);
expect(validateFieldType('time', '23', 'time').valid).toEqual(false);
expect(validateFieldType('time', 'foo', 'time').valid).toEqual(false);
expect(validateFieldType('time', '23:23:', 'time').valid).toEqual(false);
expect(validateFieldType('time', '23::23::23', 'time').valid).toEqual(false);
const VALID_TIMES = [
['23:23', '23:23'],
['23:23:23', '23:23:23'],
['23:23:23+1000', '23:23:23+1000'],
['23:23:23-1000', '23:23:23-1000'],
['22:00:00+01:00', '22:00:00+01:00'],
['22:00:00-01:00', '22:00:00-01:00'],
['22:00:00+01', '22:00:00+01'],
['22:00:00-01', '22:00:00-01'],
];
VALID_TIMES.forEach(([value, expected]) =>
expect(validateFieldType('time', value, 'time')).toEqual({
valid: true,
newValue: expected,
}),
);
const INVALID_TIMES = ['23:23:23:23', '23', 'foo', '23:23:', '23::23::23'];
INVALID_TIMES.forEach((value) =>
expect(validateFieldType('time', value, 'time').valid).toEqual(false),
);
});
describe('options', () => {
@ -224,9 +265,15 @@ describe('Type Validation', () => {
describe('parseStrings=true', () => {
it('should parse strings from other types', () => {
const options = { parseStrings: true };
expect(validateFieldType('test', 42, 'string').newValue).toBe(42);
expect(validateFieldType('test', 42, 'string', options).newValue).toBe('42');
expect(validateFieldType('test', true, 'string', options).newValue).toBe('true');
expect(validateFieldType('test', 42, 'string')).toEqual({ valid: true, newValue: 42 });
expect(validateFieldType('test', 42, 'string', options)).toEqual({
valid: true,
newValue: '42',
});
expect(validateFieldType('test', true, 'string', options)).toEqual({
valid: true,
newValue: 'true',
});
});
});
});