mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-09-21 23:13:05 +00:00
FIX: Api version endpoint page breaking due to STRING changeDescription updated (#22060)
* fix the api version endpoint page breaking due to STRING changeDescription updated * change the logic and use same function which displayName use * added unit test for schemaVersionUtils * change function name to be generic * added support for dataDisplayType diff supported for other supporting entity as well * adde playwright test
This commit is contained in:
parent
cec7dd31ad
commit
307e883b10
@ -22,7 +22,11 @@ import {
|
||||
redirectToHomePage,
|
||||
toastNotification,
|
||||
} from '../../utils/common';
|
||||
import { addMultiOwner, assignTier } from '../../utils/entity';
|
||||
import {
|
||||
addMultiOwner,
|
||||
assignTier,
|
||||
getEntityDataTypeDisplayPatch,
|
||||
} from '../../utils/entity';
|
||||
|
||||
const entityCreationConfig: EntityDataClassCreationConfig = {
|
||||
apiEndpoint: true,
|
||||
@ -78,6 +82,7 @@ test.describe('Entity Version pages', () => {
|
||||
const domain = EntityDataClass.domain1.responseData;
|
||||
|
||||
for (const entity of entities) {
|
||||
const dataTypeDisplayPath = getEntityDataTypeDisplayPatch(entity);
|
||||
await entity.patch({
|
||||
apiContext,
|
||||
patchData: [
|
||||
@ -116,6 +121,15 @@ test.describe('Entity Version pages', () => {
|
||||
description: domain.description,
|
||||
},
|
||||
},
|
||||
...(dataTypeDisplayPath
|
||||
? [
|
||||
{
|
||||
op: 'add' as const,
|
||||
path: dataTypeDisplayPath,
|
||||
value: 'OBJECT',
|
||||
},
|
||||
]
|
||||
: []),
|
||||
],
|
||||
});
|
||||
}
|
||||
|
@ -1728,3 +1728,22 @@ export const checkExploreSearchFilter = async (
|
||||
|
||||
await entity?.visitEntityPage(page);
|
||||
};
|
||||
|
||||
export const getEntityDataTypeDisplayPatch = (entity: EntityClass) => {
|
||||
switch (entity.getType()) {
|
||||
case 'Table':
|
||||
case 'Dashboard Data Model':
|
||||
return '/columns/0/dataTypeDisplay';
|
||||
case 'ApiEndpoint':
|
||||
return '/requestSchema/schemaFields/0/dataTypeDisplay';
|
||||
case 'Topic':
|
||||
return '/messageSchema/schemaFields/0/dataTypeDisplay';
|
||||
case 'Container':
|
||||
return '/dataModel/columns/0/dataTypeDisplay';
|
||||
case 'SearchIndex':
|
||||
return '/fields/0/dataTypeDisplay';
|
||||
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
@ -90,6 +90,7 @@ export enum EntityField {
|
||||
EXPERTS = 'experts',
|
||||
FIELDS = 'fields',
|
||||
PARAMETER_VALUES = 'parameterValues',
|
||||
DATA_TYPE_DISPLAY = 'dataTypeDisplay',
|
||||
}
|
||||
|
||||
export const ANNOUNCEMENT_BG = '#FFFDF8';
|
||||
|
@ -0,0 +1,426 @@
|
||||
/*
|
||||
* Copyright 2025 Collate.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { EntityField } from '../constants/Feeds.constants';
|
||||
import {
|
||||
Column as ContainerColumn,
|
||||
DataType as ContainerDataType,
|
||||
} from '../generated/entity/data/container';
|
||||
import {
|
||||
Column as TableColumn,
|
||||
DataType as TableDataType,
|
||||
} from '../generated/entity/data/table';
|
||||
import { DataTypeTopic, Field } from '../generated/entity/data/topic';
|
||||
import { FieldChange } from '../generated/entity/services/databaseService';
|
||||
import { getStringEntityDiff } from './EntityVersionUtils';
|
||||
|
||||
// Mock data for testing
|
||||
const createMockTableColumn = (
|
||||
name: string,
|
||||
displayName?: string
|
||||
): TableColumn => ({
|
||||
name,
|
||||
displayName,
|
||||
dataType: TableDataType.String,
|
||||
dataTypeDisplay: 'string',
|
||||
fullyQualifiedName: `test.table.${name}`,
|
||||
tags: [],
|
||||
children: [],
|
||||
});
|
||||
|
||||
const createMockContainerColumn = (
|
||||
name: string,
|
||||
displayName?: string
|
||||
): ContainerColumn => ({
|
||||
name,
|
||||
displayName,
|
||||
dataType: ContainerDataType.String,
|
||||
dataTypeDisplay: 'string',
|
||||
fullyQualifiedName: `test.container.${name}`,
|
||||
tags: [],
|
||||
children: [],
|
||||
});
|
||||
|
||||
const createMockField = (name: string, displayName?: string): Field => ({
|
||||
name,
|
||||
displayName,
|
||||
dataType: DataTypeTopic.String,
|
||||
dataTypeDisplay: 'string',
|
||||
fullyQualifiedName: `test.topic.${name}`,
|
||||
tags: [],
|
||||
children: [],
|
||||
});
|
||||
|
||||
const createMockFieldChange = (
|
||||
name: string,
|
||||
oldValue: string,
|
||||
newValue: string
|
||||
): FieldChange => ({
|
||||
name,
|
||||
oldValue,
|
||||
newValue,
|
||||
});
|
||||
|
||||
const createMockEntityDiff = (
|
||||
added?: FieldChange,
|
||||
deleted?: FieldChange,
|
||||
updated?: FieldChange
|
||||
) => ({
|
||||
added,
|
||||
deleted,
|
||||
updated,
|
||||
});
|
||||
|
||||
describe('getStringEntityDiff', () => {
|
||||
describe('TableColumn entity', () => {
|
||||
it('should update displayName with diff when entity name matches', () => {
|
||||
const oldDisplayName = 'Old Display Name';
|
||||
const newDisplayName = 'New Display Name';
|
||||
const entityName = 'testColumn';
|
||||
|
||||
const entityDiff = createMockEntityDiff(
|
||||
undefined,
|
||||
undefined,
|
||||
createMockFieldChange('displayName', oldDisplayName, newDisplayName)
|
||||
);
|
||||
|
||||
const columns = [
|
||||
createMockTableColumn(entityName, oldDisplayName),
|
||||
createMockTableColumn('otherColumn', 'Other Display Name'),
|
||||
];
|
||||
|
||||
const result = getStringEntityDiff(
|
||||
entityDiff,
|
||||
EntityField.DISPLAYNAME,
|
||||
entityName,
|
||||
columns
|
||||
);
|
||||
|
||||
expect(result).toHaveLength(2);
|
||||
expect(result[0].displayName).toContain('diff-removed');
|
||||
expect(result[0].displayName).toContain('diff-added');
|
||||
expect(result[1].displayName).toBe('Other Display Name');
|
||||
});
|
||||
|
||||
it('should update description field when DESCRIPTION field is passed', () => {
|
||||
const oldDescription = 'Old description';
|
||||
const newDescription = 'New description';
|
||||
const entityName = 'testColumn';
|
||||
|
||||
const entityDiff = createMockEntityDiff(
|
||||
undefined,
|
||||
undefined,
|
||||
createMockFieldChange('description', oldDescription, newDescription)
|
||||
);
|
||||
|
||||
const columns = [
|
||||
{ ...createMockTableColumn(entityName), description: oldDescription },
|
||||
createMockTableColumn('otherColumn', 'Other Display Name'),
|
||||
];
|
||||
|
||||
const result = getStringEntityDiff(
|
||||
entityDiff,
|
||||
EntityField.DESCRIPTION,
|
||||
entityName,
|
||||
columns
|
||||
);
|
||||
|
||||
expect(result).toHaveLength(2);
|
||||
expect(result[0].description).toContain('diff-removed');
|
||||
expect(result[0].description).toContain('diff-added');
|
||||
expect(result[1].description).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should handle nested children entities', () => {
|
||||
const oldDisplayName = 'Old Child Display Name';
|
||||
const newDisplayName = 'New Child Display Name';
|
||||
const childEntityName = 'childColumn';
|
||||
|
||||
const entityDiff = createMockEntityDiff(
|
||||
undefined,
|
||||
undefined,
|
||||
createMockFieldChange('displayName', oldDisplayName, newDisplayName)
|
||||
);
|
||||
|
||||
const childColumn = createMockTableColumn(
|
||||
childEntityName,
|
||||
oldDisplayName
|
||||
);
|
||||
const parentColumn = {
|
||||
...createMockTableColumn('parentColumn', 'Parent Display Name'),
|
||||
children: [childColumn],
|
||||
};
|
||||
|
||||
const columns = [parentColumn];
|
||||
|
||||
const result = getStringEntityDiff(
|
||||
entityDiff,
|
||||
EntityField.DISPLAYNAME,
|
||||
childEntityName,
|
||||
columns
|
||||
);
|
||||
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result[0].children?.[0].displayName).toContain('diff-removed');
|
||||
expect(result[0].children?.[0].displayName).toContain('diff-added');
|
||||
expect(result[0].displayName).toBe('Parent Display Name');
|
||||
});
|
||||
|
||||
it('should not modify entities when name does not match', () => {
|
||||
const entityDiff = createMockEntityDiff(
|
||||
undefined,
|
||||
undefined,
|
||||
createMockFieldChange('displayName', 'Old Name', 'New Name')
|
||||
);
|
||||
|
||||
const columns = [
|
||||
createMockTableColumn('differentColumn', 'Original Display Name'),
|
||||
];
|
||||
|
||||
const result = getStringEntityDiff(
|
||||
entityDiff,
|
||||
EntityField.DISPLAYNAME,
|
||||
'nonExistentColumn',
|
||||
columns
|
||||
);
|
||||
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result[0].displayName).toBe('Original Display Name');
|
||||
});
|
||||
});
|
||||
|
||||
describe('ContainerColumn entity', () => {
|
||||
it('should update displayName for ContainerColumn', () => {
|
||||
const oldDisplayName = 'Old Container Display Name';
|
||||
const newDisplayName = 'New Container Display Name';
|
||||
const entityName = 'containerColumn';
|
||||
|
||||
const entityDiff = createMockEntityDiff(
|
||||
undefined,
|
||||
undefined,
|
||||
createMockFieldChange('displayName', oldDisplayName, newDisplayName)
|
||||
);
|
||||
|
||||
const columns = [createMockContainerColumn(entityName, oldDisplayName)];
|
||||
|
||||
const result = getStringEntityDiff(
|
||||
entityDiff,
|
||||
EntityField.DISPLAYNAME,
|
||||
entityName,
|
||||
columns
|
||||
);
|
||||
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result[0].displayName).toContain('diff-removed');
|
||||
expect(result[0].displayName).toContain('diff-added');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Field entity', () => {
|
||||
it('should update displayName for Field', () => {
|
||||
const oldDisplayName = 'Old Field Display Name';
|
||||
const newDisplayName = 'New Field Display Name';
|
||||
const entityName = 'fieldName';
|
||||
|
||||
const entityDiff = createMockEntityDiff(
|
||||
undefined,
|
||||
undefined,
|
||||
createMockFieldChange('displayName', oldDisplayName, newDisplayName)
|
||||
);
|
||||
|
||||
const fields = [createMockField(entityName, oldDisplayName)];
|
||||
|
||||
const result = getStringEntityDiff(
|
||||
entityDiff,
|
||||
EntityField.DISPLAYNAME,
|
||||
entityName,
|
||||
fields
|
||||
);
|
||||
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result[0].displayName).toContain('diff-removed');
|
||||
expect(result[0].displayName).toContain('diff-added');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Edge cases', () => {
|
||||
it('should handle empty entity list', () => {
|
||||
const entityDiff = createMockEntityDiff(
|
||||
undefined,
|
||||
undefined,
|
||||
createMockFieldChange('displayName', 'Old', 'New')
|
||||
);
|
||||
|
||||
const result = getStringEntityDiff(
|
||||
entityDiff,
|
||||
EntityField.DISPLAYNAME,
|
||||
'anyEntity',
|
||||
[]
|
||||
);
|
||||
|
||||
expect(result).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should handle undefined changedEntityName', () => {
|
||||
const entityDiff = createMockEntityDiff(
|
||||
undefined,
|
||||
undefined,
|
||||
createMockFieldChange('displayName', 'Old', 'New')
|
||||
);
|
||||
|
||||
const columns = [
|
||||
createMockTableColumn('testColumn', 'Test Display Name'),
|
||||
];
|
||||
|
||||
const result = getStringEntityDiff(
|
||||
entityDiff,
|
||||
EntityField.DISPLAYNAME,
|
||||
undefined,
|
||||
columns
|
||||
);
|
||||
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result[0].displayName).toBe('Test Display Name');
|
||||
});
|
||||
|
||||
it('should handle empty old and new values', () => {
|
||||
const entityDiff = createMockEntityDiff(
|
||||
undefined,
|
||||
undefined,
|
||||
createMockFieldChange('displayName', '', '')
|
||||
);
|
||||
|
||||
const columns = [
|
||||
createMockTableColumn('testColumn', 'Existing Display Name'),
|
||||
];
|
||||
|
||||
const result = getStringEntityDiff(
|
||||
entityDiff,
|
||||
EntityField.DISPLAYNAME,
|
||||
'testColumn',
|
||||
columns
|
||||
);
|
||||
|
||||
expect(result).toHaveLength(1);
|
||||
// Should preserve the existing display name when both old and new are empty
|
||||
expect(result[0].displayName).toBe('Existing Display Name');
|
||||
});
|
||||
|
||||
it('should handle added field change', () => {
|
||||
const newDisplayName = 'New Added Display Name';
|
||||
const entityName = 'testColumn';
|
||||
|
||||
const entityDiff = createMockEntityDiff(
|
||||
createMockFieldChange('displayName', '', newDisplayName),
|
||||
undefined,
|
||||
undefined
|
||||
);
|
||||
|
||||
const columns = [createMockTableColumn(entityName, '')];
|
||||
|
||||
const result = getStringEntityDiff(
|
||||
entityDiff,
|
||||
EntityField.DISPLAYNAME,
|
||||
entityName,
|
||||
columns
|
||||
);
|
||||
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result[0].displayName).toContain('diff-added');
|
||||
});
|
||||
|
||||
it('should handle deleted field change', () => {
|
||||
const oldDisplayName = 'Deleted Display Name';
|
||||
const entityName = 'testColumn';
|
||||
|
||||
const entityDiff = createMockEntityDiff(
|
||||
undefined,
|
||||
createMockFieldChange('displayName', oldDisplayName, ''),
|
||||
undefined
|
||||
);
|
||||
|
||||
const columns = [createMockTableColumn(entityName, oldDisplayName)];
|
||||
|
||||
const result = getStringEntityDiff(
|
||||
entityDiff,
|
||||
EntityField.DISPLAYNAME,
|
||||
entityName,
|
||||
columns
|
||||
);
|
||||
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result[0].displayName).toContain('diff-removed');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Different EntityField values', () => {
|
||||
it('should handle DATA_TYPE_DISPLAY field', () => {
|
||||
const oldDataTypeDisplay = 'VARCHAR(255)';
|
||||
const newDataTypeDisplay = 'TEXT';
|
||||
const entityName = 'testColumn';
|
||||
|
||||
const entityDiff = createMockEntityDiff(
|
||||
undefined,
|
||||
undefined,
|
||||
createMockFieldChange(
|
||||
EntityField.DATA_TYPE_DISPLAY,
|
||||
oldDataTypeDisplay,
|
||||
newDataTypeDisplay
|
||||
)
|
||||
);
|
||||
|
||||
const columns = [
|
||||
{
|
||||
...createMockTableColumn(entityName),
|
||||
dataTypeDisplay: oldDataTypeDisplay,
|
||||
},
|
||||
];
|
||||
|
||||
const result = getStringEntityDiff(
|
||||
entityDiff,
|
||||
EntityField.DATA_TYPE_DISPLAY,
|
||||
entityName,
|
||||
columns
|
||||
);
|
||||
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result[0].dataTypeDisplay).toContain('diff-removed');
|
||||
expect(result[0].dataTypeDisplay).toContain('diff-added');
|
||||
});
|
||||
|
||||
it('should handle NAME field', () => {
|
||||
const oldName = 'oldColumnName';
|
||||
const newName = 'newColumnName';
|
||||
const entityName = 'oldColumnName';
|
||||
|
||||
const entityDiff = createMockEntityDiff(
|
||||
undefined,
|
||||
undefined,
|
||||
createMockFieldChange('name', oldName, newName)
|
||||
);
|
||||
|
||||
const columns = [{ ...createMockTableColumn(entityName), name: oldName }];
|
||||
|
||||
const result = getStringEntityDiff(
|
||||
entityDiff,
|
||||
EntityField.NAME,
|
||||
entityName,
|
||||
columns
|
||||
);
|
||||
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result[0].name).toContain('diff-removed');
|
||||
expect(result[0].name).toContain('diff-added');
|
||||
});
|
||||
});
|
||||
});
|
@ -70,6 +70,8 @@ import { t } from './i18next/LocalUtil';
|
||||
import { getJSONFromString, isValidJSONString } from './StringsUtils';
|
||||
import { getTagsWithoutTier, getTierTags } from './TableUtils';
|
||||
|
||||
type EntityColumn = TableColumn | ContainerColumn | Field;
|
||||
|
||||
export const getChangedEntityName = (diffObject?: EntityDiffProps) =>
|
||||
diffObject?.added?.name ??
|
||||
diffObject?.deleted?.name ??
|
||||
@ -506,10 +508,9 @@ export function getEntityDescriptionDiff<A extends AssetsChildForVersionPages>(
|
||||
return entityList;
|
||||
}
|
||||
|
||||
export function getEntityDisplayNameDiff<
|
||||
A extends TableColumn | ContainerColumn | Field
|
||||
>(
|
||||
export function getStringEntityDiff<A extends EntityColumn>(
|
||||
entityDiff: EntityDiffProps,
|
||||
key: EntityField,
|
||||
changedEntityName?: string,
|
||||
entityList: A[] = []
|
||||
) {
|
||||
@ -519,11 +520,11 @@ export function getEntityDisplayNameDiff<
|
||||
const formatEntityData = (arr: Array<A>) => {
|
||||
arr?.forEach((i) => {
|
||||
if (isEqual(i.name, changedEntityName)) {
|
||||
i.displayName = getTextDiff(
|
||||
i[key as keyof A] = getTextDiff(
|
||||
oldDisplayName ?? '',
|
||||
newDisplayName ?? '',
|
||||
i.displayName
|
||||
);
|
||||
i[key as keyof typeof i] as unknown as string
|
||||
) as unknown as A[keyof A];
|
||||
} else {
|
||||
formatEntityData(i?.children as Array<A>);
|
||||
}
|
||||
@ -535,9 +536,11 @@ export function getEntityDisplayNameDiff<
|
||||
return entityList;
|
||||
}
|
||||
|
||||
export function getEntityTagDiff<
|
||||
A extends TableColumn | ContainerColumn | Field
|
||||
>(entityDiff: EntityDiffProps, changedEntityName?: string, entityList?: A[]) {
|
||||
export function getEntityTagDiff<A extends EntityColumn>(
|
||||
entityDiff: EntityDiffProps,
|
||||
changedEntityName?: string,
|
||||
entityList?: A[]
|
||||
) {
|
||||
const oldTags: TagLabel[] = JSON.parse(
|
||||
getChangedEntityOldValue(entityDiff) ?? '[]'
|
||||
);
|
||||
@ -822,7 +825,23 @@ export function getColumnsDataWithVersionChanges<
|
||||
];
|
||||
} else if (isEndsWithField(EntityField.DISPLAYNAME, changedEntityName)) {
|
||||
newColumnsList = [
|
||||
...getEntityDisplayNameDiff(columnDiff, changedColName, colList),
|
||||
...getStringEntityDiff(
|
||||
columnDiff,
|
||||
EntityField.DISPLAYNAME,
|
||||
changedColName,
|
||||
colList
|
||||
),
|
||||
];
|
||||
} else if (
|
||||
isEndsWithField(EntityField.DATA_TYPE_DISPLAY, changedEntityName)
|
||||
) {
|
||||
newColumnsList = [
|
||||
...getStringEntityDiff(
|
||||
columnDiff,
|
||||
EntityField.DATA_TYPE_DISPLAY,
|
||||
changedColName,
|
||||
colList
|
||||
),
|
||||
];
|
||||
} else if (!isEndsWithField(EntityField.CONSTRAINT, changedEntityName)) {
|
||||
const changedEntity = changedEntityName
|
||||
|
@ -626,6 +626,7 @@ export const getFeedChangeFieldLabel = (fieldName?: EntityField) => {
|
||||
[EntityField.EXPERTS]: t('label.expert-plural'),
|
||||
[EntityField.FIELDS]: t('label.field-plural'),
|
||||
[EntityField.PARAMETER_VALUES]: t('label.parameter-plural'),
|
||||
[EntityField.DATA_TYPE_DISPLAY]: t('label.data-type-display'),
|
||||
};
|
||||
|
||||
return isUndefined(fieldName) ? '' : fieldNameLabelMapping[fieldName];
|
||||
|
@ -0,0 +1,313 @@
|
||||
/*
|
||||
* Copyright 2023 Collate.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
ChangeDescription,
|
||||
DataTypeTopic,
|
||||
Field,
|
||||
MessageSchemaObject,
|
||||
SchemaType,
|
||||
} from '../generated/entity/data/topic';
|
||||
import { FieldChange } from '../generated/entity/services/databaseService';
|
||||
import { getVersionedSchema } from './SchemaVersionUtils';
|
||||
|
||||
// Mock data for testing
|
||||
const createMockField = (
|
||||
name: string,
|
||||
dataTypeDisplay?: string,
|
||||
dataType: DataTypeTopic = DataTypeTopic.String
|
||||
): Field => ({
|
||||
name,
|
||||
dataType,
|
||||
dataTypeDisplay,
|
||||
fullyQualifiedName: `test.topic.schema.${name}`,
|
||||
tags: [],
|
||||
children: [],
|
||||
});
|
||||
|
||||
const createMockMessageSchema = (fields: Field[]): MessageSchemaObject => ({
|
||||
schemaFields: fields,
|
||||
schemaType: SchemaType.Avro,
|
||||
});
|
||||
|
||||
const createMockFieldChange = (
|
||||
name: string,
|
||||
oldValue: string,
|
||||
newValue: string
|
||||
): FieldChange => ({
|
||||
name,
|
||||
oldValue,
|
||||
newValue,
|
||||
});
|
||||
|
||||
const createMockChangeDescription = (
|
||||
fieldsAdded?: FieldChange[],
|
||||
fieldsDeleted?: FieldChange[],
|
||||
fieldsUpdated?: FieldChange[]
|
||||
): ChangeDescription => ({
|
||||
fieldsAdded: fieldsAdded || [],
|
||||
fieldsDeleted: fieldsDeleted || [],
|
||||
fieldsUpdated: fieldsUpdated || [],
|
||||
});
|
||||
|
||||
describe('SchemaVersionUtils', () => {
|
||||
describe('getVersionedSchema', () => {
|
||||
describe('DATA_TYPE_DISPLAY changes', () => {
|
||||
it('should update dataTypeDisplay with diff highlighting when field is changed', () => {
|
||||
const oldDataTypeDisplay = 'VARCHAR(255)';
|
||||
const newDataTypeDisplay = 'TEXT';
|
||||
const fieldName = 'testField';
|
||||
|
||||
// Create mock schema with a field that has dataTypeDisplay
|
||||
const originalSchema = createMockMessageSchema([
|
||||
createMockField(fieldName, oldDataTypeDisplay),
|
||||
createMockField('otherField', 'INT'),
|
||||
]);
|
||||
|
||||
// Create change description for dataTypeDisplay update
|
||||
const changeDescription = createMockChangeDescription(
|
||||
undefined,
|
||||
undefined,
|
||||
[
|
||||
createMockFieldChange(
|
||||
`schemaFields.${fieldName}.dataTypeDisplay`,
|
||||
oldDataTypeDisplay,
|
||||
newDataTypeDisplay
|
||||
),
|
||||
]
|
||||
);
|
||||
|
||||
// Execute the function
|
||||
const result = getVersionedSchema(originalSchema, changeDescription);
|
||||
|
||||
// Verify the result
|
||||
expect(result.schemaFields).toHaveLength(2);
|
||||
expect(result.schemaFields?.[0].name).toBe(fieldName);
|
||||
expect(result.schemaFields?.[0].dataTypeDisplay).toContain(
|
||||
'diff-removed'
|
||||
);
|
||||
expect(result.schemaFields?.[0].dataTypeDisplay).toContain(
|
||||
'diff-added'
|
||||
);
|
||||
expect(result.schemaFields?.[0].dataTypeDisplay).toContain(
|
||||
oldDataTypeDisplay
|
||||
);
|
||||
expect(result.schemaFields?.[0].dataTypeDisplay).toContain(
|
||||
newDataTypeDisplay
|
||||
);
|
||||
|
||||
// Other field should remain unchanged
|
||||
expect(result.schemaFields?.[1].dataTypeDisplay).toBe('INT');
|
||||
});
|
||||
|
||||
it('should handle nested field dataTypeDisplay changes', () => {
|
||||
const oldDataTypeDisplay = 'STRUCT<id:INT>';
|
||||
const newDataTypeDisplay = 'STRUCT<id:BIGINT>';
|
||||
const parentFieldName = 'parentField';
|
||||
const childFieldName = 'childField';
|
||||
|
||||
// Create mock schema with nested fields
|
||||
const childField = createMockField(childFieldName, oldDataTypeDisplay);
|
||||
const parentField = {
|
||||
...createMockField(parentFieldName, 'STRUCT'),
|
||||
children: [childField],
|
||||
};
|
||||
const originalSchema = createMockMessageSchema([parentField]);
|
||||
|
||||
// Create change description for nested field dataTypeDisplay update
|
||||
const changeDescription = createMockChangeDescription(
|
||||
undefined,
|
||||
undefined,
|
||||
[
|
||||
createMockFieldChange(
|
||||
`schemaFields.${parentFieldName}.children.${childFieldName}.dataTypeDisplay`,
|
||||
oldDataTypeDisplay,
|
||||
newDataTypeDisplay
|
||||
),
|
||||
]
|
||||
);
|
||||
|
||||
// Execute the function
|
||||
const result = getVersionedSchema(originalSchema, changeDescription);
|
||||
|
||||
// Verify the result
|
||||
expect(result.schemaFields).toHaveLength(1);
|
||||
expect(result.schemaFields?.[0].children).toHaveLength(1);
|
||||
expect(
|
||||
result.schemaFields?.[0].children?.[0].dataTypeDisplay
|
||||
).toContain('diff-removed');
|
||||
expect(
|
||||
result.schemaFields?.[0].children?.[0].dataTypeDisplay
|
||||
).toContain('diff-added');
|
||||
});
|
||||
|
||||
it('should not modify fields when dataTypeDisplay change does not match', () => {
|
||||
const fieldName = 'testField';
|
||||
const originalDataTypeDisplay = 'VARCHAR(255)';
|
||||
|
||||
// Create mock schema
|
||||
const originalSchema = createMockMessageSchema([
|
||||
createMockField(fieldName, originalDataTypeDisplay),
|
||||
]);
|
||||
|
||||
// Create change description for a different field
|
||||
const changeDescription = createMockChangeDescription(
|
||||
undefined,
|
||||
undefined,
|
||||
[
|
||||
createMockFieldChange(
|
||||
`schemaFields.differentField.dataTypeDisplay`,
|
||||
'OLD_VALUE',
|
||||
'NEW_VALUE'
|
||||
),
|
||||
]
|
||||
);
|
||||
|
||||
// Execute the function
|
||||
const result = getVersionedSchema(originalSchema, changeDescription);
|
||||
|
||||
// Verify the result - should remain unchanged
|
||||
expect(result.schemaFields).toHaveLength(1);
|
||||
expect(result.schemaFields?.[0].dataTypeDisplay).toBe(
|
||||
originalDataTypeDisplay
|
||||
);
|
||||
});
|
||||
|
||||
it('should handle multiple dataTypeDisplay changes', () => {
|
||||
const field1Name = 'field1';
|
||||
const field2Name = 'field2';
|
||||
const oldDataType1 = 'INT';
|
||||
const newDataType1 = 'BIGINT';
|
||||
const oldDataType2 = 'STRING';
|
||||
const newDataType2 = 'TEXT';
|
||||
|
||||
// Create mock schema with multiple fields
|
||||
const originalSchema = createMockMessageSchema([
|
||||
createMockField(field1Name, oldDataType1),
|
||||
createMockField(field2Name, oldDataType2),
|
||||
]);
|
||||
|
||||
// Create change description for multiple dataTypeDisplay updates
|
||||
const changeDescription = createMockChangeDescription(
|
||||
undefined,
|
||||
undefined,
|
||||
[
|
||||
createMockFieldChange(
|
||||
`schemaFields.${field1Name}.dataTypeDisplay`,
|
||||
oldDataType1,
|
||||
newDataType1
|
||||
),
|
||||
createMockFieldChange(
|
||||
`schemaFields.${field2Name}.dataTypeDisplay`,
|
||||
oldDataType2,
|
||||
newDataType2
|
||||
),
|
||||
]
|
||||
);
|
||||
|
||||
// Execute the function
|
||||
const result = getVersionedSchema(originalSchema, changeDescription);
|
||||
|
||||
// Verify both fields are updated
|
||||
expect(result.schemaFields).toHaveLength(2);
|
||||
expect(result.schemaFields?.[0].dataTypeDisplay).toContain(
|
||||
'diff-removed'
|
||||
);
|
||||
expect(result.schemaFields?.[0].dataTypeDisplay).toContain(
|
||||
'diff-added'
|
||||
);
|
||||
expect(result.schemaFields?.[1].dataTypeDisplay).toContain(
|
||||
'diff-removed'
|
||||
);
|
||||
expect(result.schemaFields?.[1].dataTypeDisplay).toContain(
|
||||
'diff-added'
|
||||
);
|
||||
});
|
||||
|
||||
it('should preserve other schema properties when updating dataTypeDisplay', () => {
|
||||
const fieldName = 'testField';
|
||||
const originalSchema = createMockMessageSchema([
|
||||
createMockField(fieldName, 'VARCHAR(255)'),
|
||||
]);
|
||||
|
||||
// Add additional schema properties
|
||||
const schemaWithExtraProps = {
|
||||
...originalSchema,
|
||||
schemaType: SchemaType.JSON,
|
||||
schemaText: 'original schema text',
|
||||
};
|
||||
|
||||
const changeDescription = createMockChangeDescription(
|
||||
undefined,
|
||||
undefined,
|
||||
[
|
||||
createMockFieldChange(
|
||||
`schemaFields.${fieldName}.dataTypeDisplay`,
|
||||
'VARCHAR(255)',
|
||||
'TEXT'
|
||||
),
|
||||
]
|
||||
);
|
||||
|
||||
// Execute the function
|
||||
const result = getVersionedSchema(
|
||||
schemaWithExtraProps,
|
||||
changeDescription
|
||||
);
|
||||
|
||||
// Verify schema properties are preserved
|
||||
expect(result.schemaType).toBe(SchemaType.JSON);
|
||||
expect(result.schemaText).toBe('original schema text');
|
||||
expect(result.schemaFields?.[0].dataTypeDisplay).toContain(
|
||||
'diff-removed'
|
||||
);
|
||||
expect(result.schemaFields?.[0].dataTypeDisplay).toContain(
|
||||
'diff-added'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Edge cases', () => {
|
||||
it('should handle empty schema fields', () => {
|
||||
const originalSchema = createMockMessageSchema([]);
|
||||
const changeDescription = createMockChangeDescription(
|
||||
undefined,
|
||||
undefined,
|
||||
[
|
||||
createMockFieldChange(
|
||||
'schemaFields.nonExistentField.dataTypeDisplay',
|
||||
'OLD',
|
||||
'NEW'
|
||||
),
|
||||
]
|
||||
);
|
||||
|
||||
const result = getVersionedSchema(originalSchema, changeDescription);
|
||||
|
||||
expect(result.schemaFields).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should handle missing changeDescription fields', () => {
|
||||
const originalSchema = createMockMessageSchema([
|
||||
createMockField('testField', 'VARCHAR(255)'),
|
||||
]);
|
||||
const changeDescription = createMockChangeDescription();
|
||||
|
||||
const result = getVersionedSchema(originalSchema, changeDescription);
|
||||
|
||||
expect(result.schemaFields).toHaveLength(1);
|
||||
expect(result.schemaFields?.[0].dataTypeDisplay).toBe('VARCHAR(255)');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
@ -30,6 +30,7 @@ import {
|
||||
getDiffByFieldName,
|
||||
getEntityDescriptionDiff,
|
||||
getEntityTagDiff,
|
||||
getStringEntityDiff,
|
||||
getTextDiff,
|
||||
isEndsWithField,
|
||||
} from './EntityVersionUtils';
|
||||
@ -83,6 +84,7 @@ export function createAddedSchemasDiff(
|
||||
const newField: Array<Field> = JSON.parse(
|
||||
schemaFieldsDiff.added?.newValue ?? '[]'
|
||||
);
|
||||
|
||||
newField.forEach((field) => {
|
||||
const formatSchemaFieldsData = (arr: Array<Field>, updateAll?: boolean) => {
|
||||
arr?.forEach((i) => {
|
||||
@ -217,6 +219,32 @@ export const getVersionedSchema = (
|
||||
schemaFields
|
||||
);
|
||||
|
||||
clonedMessageSchema = {
|
||||
...clonedMessageSchema,
|
||||
schemaFields: formattedSchema,
|
||||
};
|
||||
} else if (isEndsWithField(EntityField.DISPLAYNAME, changedEntityName)) {
|
||||
const formattedSchema = getStringEntityDiff(
|
||||
schemaFieldDiff,
|
||||
EntityField.DISPLAYNAME,
|
||||
changedSchemaFieldName,
|
||||
schemaFields
|
||||
);
|
||||
|
||||
clonedMessageSchema = {
|
||||
...clonedMessageSchema,
|
||||
schemaFields: formattedSchema,
|
||||
};
|
||||
} else if (
|
||||
isEndsWithField(EntityField.DATA_TYPE_DISPLAY, changedEntityName)
|
||||
) {
|
||||
const formattedSchema = getStringEntityDiff(
|
||||
schemaFieldDiff,
|
||||
EntityField.DATA_TYPE_DISPLAY,
|
||||
changedSchemaFieldName,
|
||||
schemaFields
|
||||
);
|
||||
|
||||
clonedMessageSchema = {
|
||||
...clonedMessageSchema,
|
||||
schemaFields: formattedSchema,
|
||||
|
Loading…
x
Reference in New Issue
Block a user