diff --git a/packages/input_schema/src/input_schema.ts b/packages/input_schema/src/input_schema.ts index 07f42647d..4a77e9936 100644 --- a/packages/input_schema/src/input_schema.ts +++ b/packages/input_schema/src/input_schema.ts @@ -48,12 +48,7 @@ export function parseAjvError( message = m('inputSchema.validation.generic', { rootName, fieldKey, message: error.message }); } else if (error.keyword === 'required') { fieldKey = error.params.missingProperty; - if (fieldKey === 'allowRelative') { - // this is the case, when allowAbsolute is set to false, but allowRelative is not set - message = m('inputSchema.validation.datepickerNoType', { rootName }); - } else { - message = m('inputSchema.validation.required', { rootName, fieldKey }); - } + message = m('inputSchema.validation.required', { rootName, fieldKey }); } else if (error.keyword === 'additionalProperties') { fieldKey = error.params.additionalProperty; message = m('inputSchema.validation.additionalProperty', { rootName, fieldKey }); @@ -63,12 +58,7 @@ export function parseAjvError( message = m('inputSchema.validation.generic', { rootName, fieldKey, message: errorMessage }); } else if (error.keyword === 'const') { fieldKey = error.instancePath.split('/').pop()!; - // This is a special case for datepicker fields, where both allowAbsolute and allowRelative properties are set to false - if (fieldKey === 'allowRelative' || fieldKey === 'allowAbsolute') { - message = m('inputSchema.validation.datepickerNoType', { rootName }); - } else { - message = m('inputSchema.validation.generic', { rootName, fieldKey, message: error.message }); - } + message = m('inputSchema.validation.generic', { rootName, fieldKey, message: error.message }); } else { fieldKey = error.instancePath.split('/').pop()!; message = m('inputSchema.validation.generic', { rootName, fieldKey, message: error.message }); diff --git a/packages/input_schema/src/intl.ts b/packages/input_schema/src/intl.ts index 38a3c2c2e..5ce3c7f11 100644 --- a/packages/input_schema/src/intl.ts +++ b/packages/input_schema/src/intl.ts @@ -33,16 +33,6 @@ const intlStrings = { 'Field schema.properties.{fieldKey} does not exist, but it is specified in schema.required. Either define the field or remove it from schema.required.', 'inputSchema.validation.proxyGroupMustBeArrayOfStrings': 'Field {rootName}.{fieldKey}.apifyProxyGroups must be an array of strings.', - 'inputSchema.validation.datepickerInvalidFormatAbsolute': - 'Field {rootName}.{fieldKey} must be a string in format "YYYY-MM-DD".', - 'inputSchema.validation.datepickerInvalidFormatRelative': - 'Field {rootName}.{fieldKey} must be a string in format "+/- number unit". Supported units are "day", "week", "month" and "year".', - 'inputSchema.validation.datepickerInvalidFormatBoth': - 'Field {rootName}.{fieldKey} must be a string in format "YYYY-MM-DD" or "+/- number unit". Supported units are "day", "week", "month" and "year".', - 'inputSchema.validation.datepickerInvalidDate': - 'Field {rootName}.{fieldKey} must be a valid date.', - 'inputSchema.validation.datepickerNoType': - 'Field {rootName} must accept absolute, relative or both dates. Set "allowAbsolute", "allowRelative" or both properties.', }; /** diff --git a/packages/input_schema/src/schema.json b/packages/input_schema/src/schema.json index 5dd6741e4..c0d979a65 100644 --- a/packages/input_schema/src/schema.json +++ b/packages/input_schema/src/schema.json @@ -123,18 +123,8 @@ "editor": { "enum": ["datepicker"] }, "sectionCaption": { "type": "string" }, "sectionDescription": { "type": "string" }, - "allowAbsolute": { "type": "boolean" }, - "allowRelative": { "type": "boolean" } - }, - "if": { - "required": ["allowAbsolute"], - "properties": { "allowAbsolute": { "const": false } } - }, - "then": { "required": ["type", "title", "description", "editor", "allowRelative"] }, - "anyOf": [ - { "properties": { "allowAbsolute": { "const": true } } }, - { "properties": { "allowRelative": { "const": true } } } - ] + "dateType": { "enum": ["absolute", "relative", "absoluteOrRelative"] } + } }, "else": { "additionalProperties": false, @@ -149,8 +139,8 @@ "nullable": { "type": "boolean" }, "minLength": { "type": "integer" }, "maxLength": { "type": "integer" }, - "editor": { "enum": ["javascript", "python", "textfield", "textarea", "datepicker", "hidden"] }, - "isSecret": { "type": "boolean" }, + "editor": { "enum": ["javascript", "python", "textfield", "textarea", "hidden"] }, + "isSecret": { "enum": [false] }, "sectionCaption": { "type": "string" }, "sectionDescription": { "type": "string" } } @@ -165,7 +155,7 @@ "example": { "type": "string" }, "nullable": { "type": "boolean" }, "editor": { "enum": ["textfield", "textarea", "hidden"] }, - "isSecret": { "type": "boolean" }, + "isSecret": { "enum": [true] }, "sectionCaption": { "type": "string" }, "sectionDescription": { "type": "string" } } diff --git a/packages/input_schema/src/types.ts b/packages/input_schema/src/types.ts index 3c6eadf9b..23466dfb4 100644 --- a/packages/input_schema/src/types.ts +++ b/packages/input_schema/src/types.ts @@ -18,10 +18,8 @@ export type StringFieldDefinition = CommonFieldDefinition & { enum?: readonly string[]; // required if editor is 'select' enumTitles?: readonly string[] isSecret?: boolean; - // Used for 'datepicker' editor, allowAbsolute is considered with default value true - // If only relative time is wanted, allowAbsolute must be explicitly set to false - allowAbsolute?: boolean; - allowRelative?: boolean; + // Used for 'datepicker' editor, absolute is considered as default value + dateType?: 'absolute' | 'relative' | 'absoluteOrRelative'; } export type BooleanFieldDefinition = CommonFieldDefinition & { diff --git a/packages/input_schema/src/utilities.ts b/packages/input_schema/src/utilities.ts index 795193f4d..2108ec65e 100644 --- a/packages/input_schema/src/utilities.ts +++ b/packages/input_schema/src/utilities.ts @@ -248,50 +248,6 @@ export function validateInputUsingValidator( } } - // Check datepicker editor format - // TODO: enable validation for datepicker editor later - /* if (type === 'string' && editor === 'datepicker' && value && typeof value === 'string') { - const acceptAbsolute = allowAbsolute !== false; - const acceptRelative = allowRelative === true; - const isValidAbsolute = /^[0-9]{4}-[0-9]{2}-[0-9]{2}$/.test(value); - const isValidRelative = /^[+-] [0-9]+ (day|week|month|year)s?$/.test(value); - let isValidDate: boolean | undefined; - - if (isValidAbsolute) { - const [year, month, day] = value.split('-').map(Number); - const date = new Date(`${year}-${month}-${day}`); - - // Check if the date object is valid and matches the input string - isValidDate = date.getFullYear() === year - && date.getMonth() + 1 === month - && date.getDate() === day; - } - - if (acceptAbsolute && !acceptRelative && !isValidAbsolute) { - fieldErrors.push(m('inputSchema.validation.datepickerInvalidFormatAbsolute', { - rootName: 'input', - fieldKey: property, - })); - } else if (acceptRelative && !acceptAbsolute && !isValidRelative) { - fieldErrors.push(m('inputSchema.validation.datepickerInvalidFormatRelative', { - rootName: 'input', - fieldKey: property, - })); - } else if ((acceptAbsolute && !acceptRelative && !isValidAbsolute) - || (acceptRelative && !acceptAbsolute && !isValidRelative) - || (acceptRelative && acceptAbsolute && !isValidAbsolute && !isValidRelative)) { - fieldErrors.push(m('inputSchema.validation.datepickerInvalidFormatBoth', { - rootName: 'input', - fieldKey: property, - })); - } else if (isValidDate === false && acceptAbsolute) { - fieldErrors.push(m('inputSchema.validation.datepickerInvalidDate', { - rootName: 'input', - fieldKey: property, - })); - } - } */ - if (fieldErrors.length > 0) { const message = fieldErrors.join(', '); errors.push({ fieldKey: property, message }); diff --git a/test/input_schema.test.ts b/test/input_schema.test.ts index 50e4290df..4e9314935 100644 --- a/test/input_schema.test.ts +++ b/test/input_schema.test.ts @@ -156,7 +156,7 @@ describe('input_schema.json', () => { expect(() => validateInputSchema(validator, schema)).toThrow( 'Input schema is not valid (Field schema.properties.myField.editor must be equal to one of the allowed values: ' - + '"javascript", "python", "textfield", "textarea", "datepicker", "hidden")', + + '"javascript", "python", "textfield", "textarea", "hidden")', ); }); diff --git a/test/input_schema_definition.test.ts b/test/input_schema_definition.test.ts index d23cc3095..b75df9fe1 100644 --- a/test/input_schema_definition.test.ts +++ b/test/input_schema_definition.test.ts @@ -1,4 +1,4 @@ -import { inputSchema, parseAjvError } from '@apify/input_schema'; +import { inputSchema } from '@apify/input_schema'; import Ajv from 'ajv'; /** @@ -301,7 +301,7 @@ describe('input_schema.json', () => { }); describe('special cases for datepicker editor type', () => { - it('should accept allowAbsolute and allowRelative fields omitted', () => { + it('should accept dateType field omitted', () => { expect(ajv.validate(inputSchema, { title: 'Test input schema', type: 'object', @@ -317,96 +317,8 @@ describe('input_schema.json', () => { })).toBe(true); }); - it('should accept allowAbsolute and allowRelative both set to true', () => { - expect(ajv.validate(inputSchema, { - title: 'Test input schema', - type: 'object', - schemaVersion: 1, - properties: { - myField: { - title: 'Field title', - description: 'My test field', - type: 'string', - editor: 'datepicker', - allowAbsolute: true, - allowRelative: true, - }, - }, - })).toBe(true); - }); - - it('should accept allowAbsolute=true and allowRelative=false', () => { - expect(ajv.validate(inputSchema, { - title: 'Test input schema', - type: 'object', - schemaVersion: 1, - properties: { - myField: { - title: 'Field title', - description: 'My test field', - type: 'string', - editor: 'datepicker', - allowAbsolute: true, - allowRelative: false, - }, - }, - })).toBe(true); - }); - - it('should accept allowAbsolute=false and allowRelative=true', () => { - expect(ajv.validate(inputSchema, { - title: 'Test input schema', - type: 'object', - schemaVersion: 1, - properties: { - myField: { - title: 'Field title', - description: 'My test field', - type: 'string', - editor: 'datepicker', - allowAbsolute: false, - allowRelative: true, - }, - }, - })).toBe(true); - }); - - it('should accept allowAbsolute=true', () => { - expect(ajv.validate(inputSchema, { - title: 'Test input schema', - type: 'object', - schemaVersion: 1, - properties: { - myField: { - title: 'Field title', - description: 'My test field', - type: 'string', - editor: 'datepicker', - allowAbsolute: true, - }, - }, - })).toBe(true); - }); - - it('should accept allowRelative=true', () => { - expect(ajv.validate(inputSchema, { - title: 'Test input schema', - type: 'object', - schemaVersion: 1, - properties: { - myField: { - title: 'Field title', - description: 'My test field', - type: 'string', - editor: 'datepicker', - allowRelative: true, - }, - }, - })).toBe(true); - }); - - it('should accept allowRelative=false', () => { - expect(ajv.validate(inputSchema, { + const isSchemaValid = (dateType: string) => { + return ajv.validate(inputSchema, { title: 'Test input schema', type: 'object', schemaVersion: 1, @@ -416,53 +328,22 @@ describe('input_schema.json', () => { description: 'My test field', type: 'string', editor: 'datepicker', - allowRelative: false, + dateType, }, }, - })).toBe(true); - }); + }); + }; - it('should not accept allowAbsolute=false', () => { - expect(ajv.validate(inputSchema, { - title: 'Test input schema', - type: 'object', - schemaVersion: 1, - properties: { - myField: { - title: 'Field title', - description: 'My test field', - type: 'string', - editor: 'datepicker', - allowAbsolute: false, - }, - }, - })).toBe(false); - expect(ajv.errorsText()).toContain('data/properties/myField must have required property \'allowRelative\''); - expect(parseAjvError(ajv.errors![0], 'schema.properties.myField')?.message) - .toEqual('Field schema.properties.myField must accept absolute, relative or both dates. ' - + 'Set "allowAbsolute", "allowRelative" or both properties.'); + it('should accept valid dateType', () => { + ['absolute', 'relative', 'absoluteOrRelative'].forEach((dateType) => { + expect(isSchemaValid(dateType)).toBe(true); + }); }); - it('should not accept allowAbsolute=false allowRelative=false', () => { - expect(ajv.validate(inputSchema, { - title: 'Test input schema', - type: 'object', - schemaVersion: 1, - properties: { - myField: { - title: 'Field title', - description: 'My test field', - type: 'string', - editor: 'datepicker', - allowAbsolute: false, - allowRelative: false, - }, - }, - })).toBe(false); - expect(ajv.errorsText()).toContain('data/properties/myField/allowAbsolute must be equal to constant'); - expect(parseAjvError(ajv.errors![0], 'schema.properties.myField')?.message) - .toEqual('Field schema.properties.myField must accept absolute, relative or both dates. ' - + 'Set "allowAbsolute", "allowRelative" or both properties.'); + it('should not accept invalid dateType', () => { + ['xxx', 'invalid'].forEach((dateType) => { + expect(isSchemaValid(dateType)).toBe(false); + }); }); }); diff --git a/test/utilities.client.test.ts b/test/utilities.client.test.ts index 8511f04ec..637ddb772 100644 --- a/test/utilities.client.test.ts +++ b/test/utilities.client.test.ts @@ -1086,221 +1086,6 @@ describe('utilities.client', () => { }); }); }); - - /* TODO - enable this tests when the datepicker validation is back on - describe('special cases for datepicker string type', () => { - it('should allow absolute dates when allowAbsolute is omitted', () => { - const { inputSchema, validator } = buildInputSchema({ - field: { - title: 'Field title', - description: 'My test field', - type: 'string', - editor: 'datepicker', - nullable: true, - }, - }); - const inputs = [ - // 5 invalid inputs - { field: {} }, - { field: [] }, - { field: 'invalid string' }, - { field: '12.10.2024' }, - { field: '+ 1 day' }, - // Valid - { field: '2022-12-31' }, - { field: '2024-01-31' }, - { field: '1999-02-28' }, - { field: null }, - ]; - - const results = inputs - .map((input) => validateInputUsingValidator(validator, inputSchema, input)) - .filter((errors) => errors.length > 0); - - // There should be 5 invalid inputs - expect(results.length).toEqual(5); - results.forEach((result) => { - // Only one error should be thrown - expect(result.length).toEqual(1); - expect(result[0].fieldKey).toEqual('field'); - }); - }); - - it('should allow absolute dates when allowAbsolute is set to true', () => { - const { inputSchema, validator } = buildInputSchema({ - field: { - title: 'Field title', - description: 'My test field', - type: 'string', - editor: 'datepicker', - allowAbsolute: true, - }, - }); - const inputs = [ - // 6 invalid inputs - { field: {} }, - { field: [] }, - { field: 'invalid string' }, - { field: '12.10.2024' }, - { field: '+ 1 day' }, - { field: null }, - // Valid - { field: '2022-12-31' }, - { field: '2024-01-31' }, - { field: '1999-02-28' }, - ]; - - const results = inputs - .map((input) => validateInputUsingValidator(validator, inputSchema, input)) - .filter((errors) => errors.length > 0); - - // There should be 6 invalid inputs - expect(results.length).toEqual(6); - results.forEach((result) => { - // Only one error should be thrown - expect(result.length).toEqual(1); - expect(result[0].fieldKey).toEqual('field'); - }); - }); - - it('should allow only relative dates when allowRelative is true and allowAbsolute is false', () => { - const { inputSchema, validator } = buildInputSchema({ - field: { - title: 'Field title', - description: 'My test field', - type: 'string', - editor: 'datepicker', - allowAbsolute: false, - allowRelative: true, - }, - }); - const inputs = [ - // 11 invalid inputs - { field: '2022-12-31' }, - { field: '2024-01-31' }, - { field: '1999-02-28' }, - { field: {} }, - { field: [] }, - { field: 'invalid string' }, - { field: '12.10.2024' }, - { field: null }, - { field: '+ 1 minutes' }, - { field: '1 day' }, - { field: '- 11 sec' }, - // Valid - { field: '+ 1 day' }, - { field: '+ 3 days' }, - { field: '+ 5 weeks' }, - { field: '- 10 months' }, - { field: '+ 3 years' }, - { field: '- 0 days' }, - ]; - - const results = inputs - .map((input) => validateInputUsingValidator(validator, inputSchema, input)) - .filter((errors) => errors.length > 0); - - // There should be 11 invalid inputs - expect(results.length).toEqual(11); - results.forEach((result) => { - // Only one error should be thrown - expect(result.length).toEqual(1); - expect(result[0].fieldKey).toEqual('field'); - }); - }); - - it('should allow both dates when allowRelative is true', () => { - const { inputSchema, validator } = buildInputSchema({ - field: { - title: 'Field title', - description: 'My test field', - type: 'string', - editor: 'datepicker', - allowRelative: true, - }, - }); - const inputs = [ - // 8 invalid inputs - { field: {} }, - { field: [] }, - { field: 'invalid string' }, - { field: '12.10.2024' }, - { field: null }, - { field: '+ 1 minutes' }, - { field: '1 day' }, - { field: '- 11 sec' }, - // Valid - { field: '2022-12-31' }, - { field: '2024-01-31' }, - { field: '1999-02-28' }, - { field: '+ 1 day' }, - { field: '+ 3 days' }, - { field: '+ 5 weeks' }, - { field: '- 10 months' }, - { field: '+ 3 years' }, - { field: '- 0 days' }, - ]; - - const results = inputs - .map((input) => validateInputUsingValidator(validator, inputSchema, input)) - .filter((errors) => errors.length > 0); - - // There should be 8 invalid inputs - expect(results.length).toEqual(8); - results.forEach((result) => { - // Only one error should be thrown - expect(result.length).toEqual(1); - expect(result[0].fieldKey).toEqual('field'); - }); - }); - - it('should allow both dates when allowRelative is true and allowAbsolute is true', () => { - const { inputSchema, validator } = buildInputSchema({ - field: { - title: 'Field title', - description: 'My test field', - type: 'string', - editor: 'datepicker', - allowRelative: true, - allowAbsolute: true, - }, - }); - const inputs = [ - // 8 invalid inputs - { field: {} }, - { field: [] }, - { field: 'invalid string' }, - { field: '12.10.2024' }, - { field: null }, - { field: '+ 1 minutes' }, - { field: '1 day' }, - { field: '- 11 sec' }, - // Valid - { field: '2022-12-31' }, - { field: '2024-01-31' }, - { field: '1999-02-28' }, - { field: '+ 1 day' }, - { field: '+ 3 days' }, - { field: '+ 5 weeks' }, - { field: '- 10 months' }, - { field: '+ 3 years' }, - { field: '- 0 days' }, - ]; - - const results = inputs - .map((input) => validateInputUsingValidator(validator, inputSchema, input)) - .filter((errors) => errors.length > 0); - - // There should be 8 invalid inputs - expect(results.length).toEqual(8); - results.forEach((result) => { - // Only one error should be thrown - expect(result.length).toEqual(1); - expect(result[0].fieldKey).toEqual('field'); - }); - }); - }); - */ }); describe('#jsonStringifyExtended()', () => {