Skip to content

Commit

Permalink
WIP - only test object case
Browse files Browse the repository at this point in the history
  • Loading branch information
nick-Ag committed Dec 2, 2024
1 parent 2329819 commit 30a3ad5
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 54 deletions.
73 changes: 44 additions & 29 deletions packages/core/src/__tests__/schema-validation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ describe.only('conditionally required fields', () => {
mockActionFields = {}
})

describe('should validate a single conditional requirement', () => {
describe.skip('should validate a single conditional requirement', () => {
it('should validate b when it is required', async () => {
mockActionFields['a'] = {
label: 'a',
Expand Down Expand Up @@ -128,7 +128,7 @@ describe.only('conditionally required fields', () => {
})
})

describe('should validate multiple conditional requirements on different fields', () => {
describe.skip('should validate multiple conditional requirements on different fields', () => {
it('should validate when both b and c are required', async () => {
mockActionFields['a'] = {
label: 'a',
Expand Down Expand Up @@ -300,7 +300,7 @@ describe.only('conditionally required fields', () => {
})
})

describe('should handle multiple conditions on the same field', () => {
describe.skip('should handle multiple conditions on the same field', () => {
it('should handle when one field has multiple values on another for which it is required, any matcher', async () => {
mockActionFields['a'] = {
label: 'a',
Expand Down Expand Up @@ -563,7 +563,7 @@ describe.only('conditionally required fields', () => {
expect(isValid).toBe(true)
})

it('should validate multiple object conditions', async () => {
it.only('should validate multiple object conditions', async () => {
mockActionFields['a'] = {
type: 'object',
label: 'a',
Expand Down Expand Up @@ -597,35 +597,55 @@ describe.only('conditionally required fields', () => {
console.log('schema:', JSON.stringify(schema, null, 2))

const d_required_mappings = [
{ a: { b: 'b_value', c: 'c_value' } },
{ a: { b: 'b_value', c: 'c_value' }, d: 'd_value' }
[{ a: { b: 'b_value', c: 'c_value' } }, false],
[{ a: { b: 'b_value', c: 'c_value' }, d: 'd_value' }, true]
]

const d_not_required_mappings = [
{ a: { b: 'b_value', c: 'not c_value' } },
{ a: { b: 'not b_value', c: 'c_value' } },
{ a: { b: 'not b_value', c: 'not c_value' } },
{ a: { b: 'b_value' }, d: 'd_value' }
[{ a: { b: 'b_value', c: 'not c_value' } }, true],
[{ a: { b: 'not b_value', c: 'c_value' } }, true],
[{ a: { b: 'not b_value', c: 'not c_value' } }, true],
[{ a: { b: 'b_value' }, d: 'd_value' }, true]
]

let isValid
isValid = validateSchema(d_required_mappings[0], schema, { throwIfInvalid: false })
expect(isValid).toBe(false)
for (const requiredMapping of d_required_mappings) {
const index = 0
const valid = validateSchema(requiredMapping[0], schema, { throwIfInvalid: false })
expect(valid).toBe(
requiredMapping[1],
`expected required mapping ${index} to be ${requiredMapping[1]}\n${JSON.stringify(requiredMapping[0])}`
)
}

isValid = validateSchema(d_required_mappings[1], schema, { throwIfInvalid: false })
expect(isValid).toBe(true)
for (const notRequiredMapping of d_not_required_mappings) {
const index = 0
const valid = validateSchema(notRequiredMapping[0], schema, { throwIfInvalid: false })
expect(valid).toBe(
notRequiredMapping[1],
`expected not required mapping ${index} to be ${notRequiredMapping[1]}\n${JSON.stringify(
notRequiredMapping[0]
)}`
)
}

isValid = validateSchema(d_not_required_mappings[0], schema, { throwIfInvalid: false })
expect(isValid).toBe(true)
// let isValid
// isValid = validateSchema(d_required_mappings[0], schema, { throwIfInvalid: false })
// expect(isValid).toBe(false)

isValid = validateSchema(d_not_required_mappings[1], schema, { throwIfInvalid: false })
expect(isValid).toBe(true)
// isValid = validateSchema(d_required_mappings[1], schema, { throwIfInvalid: false })
// expect(isValid).toBe(true)

isValid = validateSchema(d_not_required_mappings[2], schema, { throwIfInvalid: false })
expect(isValid).toBe(true)
// isValid = validateSchema(d_not_required_mappings[0], schema, { throwIfInvalid: false })
// expect(isValid).toBe(true)

isValid = validateSchema(d_not_required_mappings[3], schema, { throwIfInvalid: false })
expect(isValid).toBe(true)
// isValid = validateSchema(d_not_required_mappings[1], schema, { throwIfInvalid: false })
// expect(isValid).toBe(true)

// isValid = validateSchema(d_not_required_mappings[2], schema, { throwIfInvalid: false })
// expect(isValid).toBe(true)

// isValid = validateSchema(d_not_required_mappings[3], schema, { throwIfInvalid: false })
// expect(isValid).toBe(true)
})

it('should validate multiple object conditions with an any matcher', async () => {
Expand Down Expand Up @@ -874,7 +894,7 @@ describe.only('conditionally required fields', () => {
})
})

describe('should handle different data types', () => {
describe.skip('should handle different data types', () => {
it('should validate number fields', async () => {
mockActionFields['a'] = {
type: 'number',
Expand Down Expand Up @@ -1004,7 +1024,6 @@ describe.only('conditionally required fields', () => {
}

const schema = fieldsToJsonSchema(mockActionFields)
console.log('schema:', JSON.stringify(schema, null, 2))

const b_required_mappings = [{ a: undefined }, { a: undefined, b: 'b_value' }, { c: 'c_value' }, { b: 'b_value' }]
const b_not_required_mappings = [{ a: 'a_value' }, { a: 'a_value', b: 'b_value' }]
Expand Down Expand Up @@ -1056,7 +1075,6 @@ describe.only('conditionally required fields', () => {
}

const schema = fieldsToJsonSchema(mockActionFields)
console.log('schema:', JSON.stringify(schema, null, 2))
const b_required_mappings = [
{ a: undefined },
{ a: undefined, b: undefined },
Expand Down Expand Up @@ -1154,9 +1172,6 @@ describe.only('conditionally required fields', () => {

isValid = validateSchema(b_not_required_mappings[1], schema, { throwIfInvalid: false })
expect(isValid).toBe(true)

isValid = validateSchema(b_not_required_mappings[2], schema, { throwIfInvalid: false })
expect(isValid).toBe(true)
})
})

Expand Down
56 changes: 31 additions & 25 deletions packages/core/src/destination-kit/fields-to-jsonschema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,31 +57,26 @@ export function groupConditionsToJsonSchema(
const undefinedConditionValueToJSONSchema = (
dependantFieldKey: string,
fieldKey: string,
operator: 'is' | 'is_not'
operator: 'is' | 'is_not',
multiple?: boolean
): JSONSchema4 => {
if (operator === 'is') {
return {
if: {
not: {
required: [dependantFieldKey]
}
},
then: {
required: [fieldKey]
}
}
} else if (operator === 'is_not') {
return {
if: {
required: [dependantFieldKey]
},
then: {
required: [fieldKey]
}
}
} else {
if (operator !== 'is' && operator !== 'is_not') {
throw new Error(`Unsupported conditionally required field operator: ${operator}`)
}

const insideIfStatement: JSONSchema4 =
operator === 'is' ? { not: { required: [dependantFieldKey] } } : { required: [dependantFieldKey] }

if (multiple) {
return insideIfStatement
}

return {
if: insideIfStatement,
then: {
required: [fieldKey]
}
}
}

const simpleConditionToJSONSchema = (
Expand Down Expand Up @@ -116,11 +111,21 @@ const objectConditionToJSONSchema = (
objectChildKey: string,
fieldKey: string,
dependantValue: string,
operator: 'is' | 'is_not'
operator: 'is' | 'is_not',
multiple?: boolean
): JSONSchema4 => {
const dependantValueToJSONSchema: JSONSchema4 =
operator === 'is' ? { const: dependantValue } : { not: { const: dependantValue } }

if (multiple) {
return {
properties: {
[objectParentKey]: { properties: { [objectChildKey]: dependantValueToJSONSchema }, required: [objectChildKey] }
},
required: [objectParentKey]
}
}

return {
if: {
properties: {
Expand Down Expand Up @@ -226,7 +231,7 @@ export function singleConditionToJsonSchema(fieldKey: string, condition: Depends

if (innerCondition.operator === 'is') {
if (innerCondition.value === undefined) {
innerConditionArray.push(undefinedConditionValueToJSONSchema(innerCondition.fieldKey, fieldKey, 'is'))
innerConditionArray.push(undefinedConditionValueToJSONSchema(innerCondition.fieldKey, fieldKey, 'is', true))
} else {
const conditionToJSON = simpleConditionToJSONSchema(
dependentFieldKey,
Expand All @@ -239,7 +244,7 @@ export function singleConditionToJsonSchema(fieldKey: string, condition: Depends
}
} else if (innerCondition.operator === 'is_not') {
if (innerCondition.value === undefined) {
innerConditionArray.push(undefinedConditionValueToJSONSchema(innerCondition.fieldKey, fieldKey, 'is_not'))
innerConditionArray.push(undefinedConditionValueToJSONSchema(innerCondition.fieldKey, fieldKey, 'is_not', true))
} else {
const conditionToJSON = simpleConditionToJSONSchema(
dependentFieldKey,
Expand All @@ -254,6 +259,7 @@ export function singleConditionToJsonSchema(fieldKey: string, condition: Depends
throw new Error(`Unsupported conditionally required field operator: ${innerCondition.operator}`)
}
})

const innerIfStatement: JSONSchema4 =
condition.match === 'any' ? { anyOf: innerConditionArray } : { allOf: innerConditionArray }
jsonCondition = { if: innerIfStatement, then: { required: [fieldKey] } }
Expand Down

0 comments on commit 30a3ad5

Please sign in to comment.