From fa8ab31ccfe2d10000beaa1c3100a9799b5d7b07 Mon Sep 17 00:00:00 2001 From: Reed Mattos <61750877+rmattos500@users.noreply.github.com> Date: Fri, 5 May 2023 14:04:23 -0400 Subject: [PATCH] CXM-5384 Fix fk validation with arrays of file names (#467) It was recently discovered that even though we can specify an array of file names in the `foreignKey` property of our mvom schemas to validate the foreign key against, it is only ever validating against the first file. This PR changes the file name/entity name separator character from a `,` to a `#` since when an array of file names gets transformed to a string it inserts commas between each of them. Thus, when performing splitting logic later on in the process flow, it was not working correctly. After making this change the file names, were correctly split from the entity name, but additional splitting was needed to split each of the file names back into an array to pass to the u2 subroutine. --------- Co-authored-by: Ken Thompson --- src/Document.ts | 13 ++++--- src/__tests__/Document.test.ts | 34 ++++++++++++++----- src/__tests__/compileModel.test.ts | 6 ++-- .../__tests__/DocumentArrayType.test.ts | 4 +-- 4 files changed, 39 insertions(+), 18 deletions(-) diff --git a/src/Document.ts b/src/Document.ts index 38988392..df0bf3cd 100644 --- a/src/Document.ts +++ b/src/Document.ts @@ -12,7 +12,7 @@ export interface DocumentConstructorOptions { } export interface BuildForeignKeyDefinitionsResult { - filename: string; + filename: string[]; entityName: string; entityIds: string[]; } @@ -130,8 +130,8 @@ class Document { return []; } - // U2 does not allow commas in filenames so we can use it to separate filename/entityName combinations - const separator = ','; + // U2 does not allow pound signs in filenames so we can use it to separate filename/entityName combinations + const separator = '#'; const definitionMap = Array.from(this.#schema.paths).reduce( (foreignKeyDefinitions, [keyPath, schemaType]) => { const value = getIn(this, keyPath, null); @@ -165,8 +165,11 @@ class Document { return Array.from(definitionMap).reduce( (acc, [key, value]) => { const keyParts = key.split(separator); - const filename = keyParts[0]; - // Just incase the entity name included a comma, rejoin + const fileName = keyParts[0]; + // If an array of filenames was provided, when we transformed the array into a string above, commas + // would have been inserted between each filename. Split the string back into an array. + const filename = fileName.split(','); + // Just incase the entity name included a pound sign, rejoin const entityName = keyParts.slice(1).join(separator); acc.push({ filename, entityName, entityIds: Array.from(value) }); return acc; diff --git a/src/__tests__/Document.test.ts b/src/__tests__/Document.test.ts index c9a699a8..929ec51c 100644 --- a/src/__tests__/Document.test.ts +++ b/src/__tests__/Document.test.ts @@ -652,7 +652,7 @@ describe('buildForeignKeyDefinitions', () => { const document = new DocumentSubclass(schema, { data: { prop1: 'foo' } }); const expected: BuildForeignKeyDefinitionsResult[] = [ - { filename: 'FILE', entityName: 'entityName', entityIds: ['foo'] }, + { filename: ['FILE'], entityName: 'entityName', entityIds: ['foo'] }, ]; expect(document.buildForeignKeyDefinitions()).toEqual(expected); }); @@ -675,8 +675,8 @@ describe('buildForeignKeyDefinitions', () => { const document = new DocumentSubclass(schema, { data: { prop1: 'foo', prop2: 'bar' } }); const expected: BuildForeignKeyDefinitionsResult[] = [ - { filename: 'FILE1', entityName: 'entityName1', entityIds: ['foo'] }, - { filename: 'FILE2', entityName: 'entityName2', entityIds: ['bar'] }, + { filename: ['FILE1'], entityName: 'entityName1', entityIds: ['foo'] }, + { filename: ['FILE2'], entityName: 'entityName2', entityIds: ['bar'] }, ]; expect(document.buildForeignKeyDefinitions()).toEqual(expected); }); @@ -691,7 +691,7 @@ describe('buildForeignKeyDefinitions', () => { const document = new DocumentSubclass(schema, { data: { prop1: 'foo', prop2: 'bar' } }); const expected: BuildForeignKeyDefinitionsResult[] = [ - { filename: 'FILE', entityName: 'entityName', entityIds: ['foo', 'bar'] }, + { filename: ['FILE'], entityName: 'entityName', entityIds: ['foo', 'bar'] }, ]; expect(document.buildForeignKeyDefinitions()).toEqual(expected); }); @@ -707,7 +707,7 @@ describe('buildForeignKeyDefinitions', () => { const document = new DocumentSubclass(schema, { data: { prop1: ['foo', 'bar'] } }); const expected: BuildForeignKeyDefinitionsResult[] = [ - { filename: 'FILE', entityName: 'entityName', entityIds: ['foo', 'bar'] }, + { filename: ['FILE'], entityName: 'entityName', entityIds: ['foo', 'bar'] }, ]; expect(document.buildForeignKeyDefinitions()).toEqual(expected); }); @@ -741,8 +741,8 @@ describe('buildForeignKeyDefinitions', () => { }); const expected: BuildForeignKeyDefinitionsResult[] = [ - { filename: 'FILE1', entityName: 'entityName', entityIds: ['foo', 'baz'] }, - { filename: 'FILE2', entityName: 'entityName', entityIds: ['bar', 'qux'] }, + { filename: ['FILE1'], entityName: 'entityName', entityIds: ['foo', 'baz'] }, + { filename: ['FILE2'], entityName: 'entityName', entityIds: ['bar', 'qux'] }, ]; expect(document.buildForeignKeyDefinitions()).toEqual(expected); }); @@ -758,7 +758,25 @@ describe('buildForeignKeyDefinitions', () => { const document = new DocumentSubclass(schema, { data: { _id: 'id', prop1: 'foo' } }); const expected: BuildForeignKeyDefinitionsResult[] = [ - { filename: 'FILE', entityName: 'entityName', entityIds: ['id'] }, + { filename: ['FILE'], entityName: 'entityName', entityIds: ['id'] }, + ]; + expect(document.buildForeignKeyDefinitions()).toEqual(expected); + }); + + test('should build foreign key definitions with multiple filenames', () => { + const definition: SchemaDefinition = { + prop1: { + type: 'string', + path: '1', + foreignKey: { entityName: 'entityName', file: ['FILE1', 'FILE2'] }, + }, + }; + const schema = new Schema(definition); + + const document = new DocumentSubclass(schema, { data: { prop1: 'foo' } }); + + const expected: BuildForeignKeyDefinitionsResult[] = [ + { filename: ['FILE1', 'FILE2'], entityName: 'entityName', entityIds: ['foo'] }, ]; expect(document.buildForeignKeyDefinitions()).toEqual(expected); }); diff --git a/src/__tests__/compileModel.test.ts b/src/__tests__/compileModel.test.ts index f3f0cea7..01357d8d 100644 --- a/src/__tests__/compileModel.test.ts +++ b/src/__tests__/compileModel.test.ts @@ -690,7 +690,7 @@ describe('save', () => { __v: null, record: `prop1-value${am}123`, foreignKeyDefinitions: [ - { entityIds: ['prop1-value'], entityName: 'prop1', filename: 'FK_FILE' }, + { entityIds: ['prop1-value'], entityName: 'prop1', filename: ['FK_FILE'] }, ], }, {}, @@ -723,7 +723,7 @@ describe('save', () => { __v: null, record: `prop1-value${am}123`, foreignKeyDefinitions: [ - { entityIds: ['prop1-value'], entityName: 'prop1', filename: 'FK_FILE' }, + { entityIds: ['prop1-value'], entityName: 'prop1', filename: ['FK_FILE'] }, ], }, {}, @@ -934,7 +934,7 @@ describe('save', () => { __v: null, record: `prop1-value${am}123`, foreignKeyDefinitions: [ - { entityIds: ['prop1-value'], entityName: 'prop1', filename: 'FK_FILE' }, + { entityIds: ['prop1-value'], entityName: 'prop1', filename: ['FK_FILE'] }, ], }, { maxReturnPayloadSize, userDefined, requestId }, diff --git a/src/schemaType/__tests__/DocumentArrayType.test.ts b/src/schemaType/__tests__/DocumentArrayType.test.ts index 40923774..8feaf077 100644 --- a/src/schemaType/__tests__/DocumentArrayType.test.ts +++ b/src/schemaType/__tests__/DocumentArrayType.test.ts @@ -308,8 +308,8 @@ describe('transformForeignKeyDefinitionsToDb', () => { value2.prop2 = 4.56; const expected: ForeignKeyDbDefinition[] = [ - { filename: 'FILE', entityId: 'foo', entityName: 'FK_ENTITY' }, - { filename: 'FILE', entityId: 'bar', entityName: 'FK_ENTITY' }, + { filename: ['FILE'], entityId: 'foo', entityName: 'FK_ENTITY' }, + { filename: ['FILE'], entityId: 'bar', entityName: 'FK_ENTITY' }, ]; expect(documentArrayType.transformForeignKeyDefinitionsToDb([value1, value2])).toEqual( expected,