mirror of
https://github.com/n8n-io/n8n.git
synced 2024-11-09 22:24:05 -08: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:
parent
47cd411436
commit
24091dfd9b
|
@ -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
|
@ -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;
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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: [
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
],
|
||||
|
|
|
@ -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',
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue