mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
AAE-22222 Fix JSON path doesn't work for square bracekts (#9611)
* AAE-22222 Fix JSON path doesn't work for square bracekts * remove comment * remove test description duplications * remove duplications
This commit is contained in:
@@ -21,7 +21,7 @@ import {
|
|||||||
mockCountriesIncorrectData,
|
mockCountriesIncorrectData,
|
||||||
mockInvalidSchemaDefinition,
|
mockInvalidSchemaDefinition,
|
||||||
mockSchemaDefinition
|
mockSchemaDefinition
|
||||||
} from '../../../mocks/data-table-widget.mock';
|
} from './mocks/data-table-widget.mock';
|
||||||
import { ObjectDataRow } from '@alfresco/adf-core';
|
import { ObjectDataRow } from '@alfresco/adf-core';
|
||||||
|
|
||||||
describe('WidgetDataTableAdapter', () => {
|
describe('WidgetDataTableAdapter', () => {
|
||||||
|
@@ -35,7 +35,7 @@ import {
|
|||||||
mockJsonResponseFormVariable,
|
mockJsonResponseFormVariable,
|
||||||
mockJsonNestedResponseFormVariable,
|
mockJsonNestedResponseFormVariable,
|
||||||
mockJsonNestedResponseEuropeCountriesData
|
mockJsonNestedResponseEuropeCountriesData
|
||||||
} from '../../../mocks/data-table-widget.mock';
|
} from './mocks/data-table-widget.mock';
|
||||||
|
|
||||||
describe('DataTableWidgetComponent', () => {
|
describe('DataTableWidgetComponent', () => {
|
||||||
let widget: DataTableWidgetComponent;
|
let widget: DataTableWidgetComponent;
|
||||||
|
@@ -16,12 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { DataTablePathParserHelper } from './data-table-path-parser.helper';
|
import { DataTablePathParserHelper } from './data-table-path-parser.helper';
|
||||||
import {
|
import { mockResponseResultData, mockResultData } from '../mocks/data-table-path-parser.helper.mock';
|
||||||
mockEuropeCountriesData,
|
|
||||||
mockJsonNestedResponseEuropeCountriesDataWithSeparatorInPropertyName,
|
|
||||||
mockJsonNestedResponseEuropeCountriesDataWithMultipleSpecialCharacters,
|
|
||||||
mockJsonNestedResponseEuropeCountriesData
|
|
||||||
} from '../../../../mocks/data-table-widget.mock';
|
|
||||||
|
|
||||||
describe('DataTablePathParserHelper', () => {
|
describe('DataTablePathParserHelper', () => {
|
||||||
let helper: DataTablePathParserHelper;
|
let helper: DataTablePathParserHelper;
|
||||||
@@ -30,59 +25,89 @@ describe('DataTablePathParserHelper', () => {
|
|||||||
helper = new DataTablePathParserHelper();
|
helper = new DataTablePathParserHelper();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return the correct data for path with separator in nested brackets', () => {
|
describe('should return the correct data for path', () => {
|
||||||
const data = mockJsonNestedResponseEuropeCountriesDataWithSeparatorInPropertyName;
|
const testCases = [
|
||||||
const path = 'response.[my.data].[country[data].country]';
|
{
|
||||||
const result = helper.retrieveDataFromPath(data, path);
|
description: 'not existent',
|
||||||
expect(result).toEqual(mockEuropeCountriesData);
|
data: {},
|
||||||
});
|
path: 'nonexistent.path',
|
||||||
|
expected: []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'nested',
|
||||||
|
data: { level1: { level2: { level3: { level4: ['parrot', 'fish'] } } } },
|
||||||
|
propertyName: 'level4',
|
||||||
|
path: 'level1.level2.level3.level4',
|
||||||
|
expected: ['parrot', 'fish']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'NOT nested',
|
||||||
|
data: { pets: ['cat', 'dog'] },
|
||||||
|
propertyName: 'pets',
|
||||||
|
path: 'pets',
|
||||||
|
expected: ['cat', 'dog']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'NOT nested with separator (.) in property name',
|
||||||
|
data: { 'my.pets': ['cat', 'dog'] },
|
||||||
|
propertyName: 'my.pets',
|
||||||
|
path: '[my.pets]',
|
||||||
|
expected: ['cat', 'dog']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'with nested brackets followed by an additional part of property name',
|
||||||
|
propertyName: 'file.file[data]file',
|
||||||
|
path: 'response.[file.file[data]file]'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'with nested brackets',
|
||||||
|
propertyName: 'file.file[data]',
|
||||||
|
path: 'response.[file.file[data]]'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'with separator before nested brackets in property name',
|
||||||
|
propertyName: 'file.[data]file',
|
||||||
|
path: 'response.[file.[data]file]'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'with separator before and no separator after nested brackets in property name',
|
||||||
|
propertyName: 'file.[data]',
|
||||||
|
path: 'response.[file.[data]]'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'with separator after nested brackets',
|
||||||
|
propertyName: 'file[data].file',
|
||||||
|
path: 'response.[file[data].file]'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'with multiple brackets in property name',
|
||||||
|
propertyName: 'file.file[data]file[data]',
|
||||||
|
path: 'response.[file.file[data]file[data]]'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'with special characters except separator (.) in brackets',
|
||||||
|
propertyName: 'xyz:abc,xyz-abc,xyz_abc,abc+xyz',
|
||||||
|
path: 'response.[xyz:abc,xyz-abc,xyz_abc,abc+xyz]'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'with special characters except separator (.) without brackets',
|
||||||
|
propertyName: 'xyz:abc,xyz-abc,xyz_abc,abc+xyz',
|
||||||
|
path: 'response.xyz:abc,xyz-abc,xyz_abc,abc+xyz'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'without separator in brackets',
|
||||||
|
propertyName: 'my-data',
|
||||||
|
path: '[response].[my-data]'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
it('should return the correct data for path with special characters except separator (.) in brackets', () => {
|
testCases.forEach((testCase) => {
|
||||||
const data = mockJsonNestedResponseEuropeCountriesDataWithMultipleSpecialCharacters;
|
it(testCase.description, () => {
|
||||||
const path = 'response.[xyz:abc,xyz-abc,xyz_abc,abc+xyz]';
|
const data = testCase.data ?? mockResponseResultData(testCase.propertyName);
|
||||||
const result = helper.retrieveDataFromPath(data, path);
|
const result = helper.retrieveDataFromPath(data, testCase.path);
|
||||||
expect(result).toEqual(mockEuropeCountriesData);
|
const expectedResult = testCase.expected ?? mockResultData;
|
||||||
});
|
expect(result).toEqual(expectedResult);
|
||||||
|
});
|
||||||
it('should return the correct data for path with special characters except separator (.) without brackets', () => {
|
});
|
||||||
const data = mockJsonNestedResponseEuropeCountriesDataWithMultipleSpecialCharacters;
|
|
||||||
const path = 'response.xyz:abc,xyz-abc,xyz_abc,abc+xyz';
|
|
||||||
const result = helper.retrieveDataFromPath(data, path);
|
|
||||||
expect(result).toEqual(mockEuropeCountriesData);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return the correct data for path without separator in brackets', () => {
|
|
||||||
const data = mockJsonNestedResponseEuropeCountriesData;
|
|
||||||
const path = '[response].[my-data]';
|
|
||||||
const result = helper.retrieveDataFromPath(data, path);
|
|
||||||
expect(result).toEqual(mockEuropeCountriesData);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return an empty array if the path does not exist in the data', () => {
|
|
||||||
const data = {};
|
|
||||||
const path = 'nonexistent.path';
|
|
||||||
const result = helper.retrieveDataFromPath(data, path);
|
|
||||||
expect(result).toEqual([]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return the correct data if the path is nested', () => {
|
|
||||||
const data = { level1: { level2: { level3: { level4: ['parrot', 'fish'] } } } };
|
|
||||||
const path = 'level1.level2.level3.level4';
|
|
||||||
const result = helper.retrieveDataFromPath(data, path);
|
|
||||||
expect(result).toEqual(['parrot', 'fish']);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return the correct data if the path is NOT nested', () => {
|
|
||||||
const data = { pets: ['cat', 'dog'] };
|
|
||||||
const path = 'pets';
|
|
||||||
const result = helper.retrieveDataFromPath(data, path);
|
|
||||||
expect(result).toEqual(['cat', 'dog']);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return the correct data if the path is NOT nested with separator (.) in property name', () => {
|
|
||||||
const data = { 'my.pets': ['cat', 'dog'] };
|
|
||||||
const path = '[my.pets]';
|
|
||||||
const result = helper.retrieveDataFromPath(data, path);
|
|
||||||
expect(result).toEqual(['cat', 'dog']);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -16,7 +16,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export class DataTablePathParserHelper {
|
export class DataTablePathParserHelper {
|
||||||
private readonly splitPathRegEx = /\.(?![^[]*\])/g;
|
|
||||||
private readonly removeSquareBracketsRegEx = /^\[(.*)\]$/;
|
private readonly removeSquareBracketsRegEx = /^\[(.*)\]$/;
|
||||||
|
|
||||||
retrieveDataFromPath(data: any, path: string): any[] {
|
retrieveDataFromPath(data: any, path: string): any[] {
|
||||||
@@ -37,11 +36,48 @@ export class DataTablePathParserHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private splitPathIntoProperties(path: string): string[] {
|
private splitPathIntoProperties(path: string): string[] {
|
||||||
return path.split(this.splitPathRegEx);
|
const properties: string[] = [];
|
||||||
|
const separator = '.';
|
||||||
|
const openBracket = '[';
|
||||||
|
const closeBracket = ']';
|
||||||
|
|
||||||
|
let currentPropertyBuffer = '';
|
||||||
|
let bracketCount = 0;
|
||||||
|
const isPropertySeparatorOutsideBrackets = () => bracketCount === 0;
|
||||||
|
|
||||||
|
for (const char of path) {
|
||||||
|
switch (char) {
|
||||||
|
case separator:
|
||||||
|
if (isPropertySeparatorOutsideBrackets()) {
|
||||||
|
properties.push(currentPropertyBuffer);
|
||||||
|
currentPropertyBuffer = '';
|
||||||
|
} else {
|
||||||
|
currentPropertyBuffer += char;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case openBracket:
|
||||||
|
bracketCount++;
|
||||||
|
currentPropertyBuffer += char;
|
||||||
|
break;
|
||||||
|
case closeBracket:
|
||||||
|
bracketCount--;
|
||||||
|
currentPropertyBuffer += char;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
currentPropertyBuffer += char;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentPropertyBuffer) {
|
||||||
|
properties.push(currentPropertyBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
private removeSquareBracketsFromProperty(property: string): string {
|
private removeSquareBracketsFromProperty(property: string): string {
|
||||||
return property.replace(this.removeSquareBracketsRegEx, '$1');
|
return property?.replace(this.removeSquareBracketsRegEx, '$1');
|
||||||
}
|
}
|
||||||
|
|
||||||
private isPropertyExistsInData(data: any, property: string): boolean {
|
private isPropertyExistsInData(data: any, property: string): boolean {
|
||||||
|
@@ -0,0 +1,45 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright © 2005-2023 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const mockResultData = [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
decimal: '1.0',
|
||||||
|
name: 'test1',
|
||||||
|
date: '1-12-2023',
|
||||||
|
amount: '0.12',
|
||||||
|
data: '{ "result": "positive" }',
|
||||||
|
trust: 'true',
|
||||||
|
image: 'check_circle'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
decimal: '2.2',
|
||||||
|
name: 'test2',
|
||||||
|
date: '2-13-2023',
|
||||||
|
amount: '2.2',
|
||||||
|
data: '{ "result": "negative" }',
|
||||||
|
trust: 'true',
|
||||||
|
image: 'bookmark'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
export const mockResponseResultData = (propertyName: string) => ({
|
||||||
|
response: {
|
||||||
|
[propertyName]: mockResultData
|
||||||
|
}
|
||||||
|
});
|
@@ -16,7 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { DataColumn } from '@alfresco/adf-core';
|
import { DataColumn } from '@alfresco/adf-core';
|
||||||
import { TaskVariableCloud } from '../models/task-variable-cloud.model';
|
import { TaskVariableCloud } from '../../../../models/task-variable-cloud.model';
|
||||||
|
|
||||||
export const mockSchemaDefinition: DataColumn[] = [
|
export const mockSchemaDefinition: DataColumn[] = [
|
||||||
{
|
{
|
||||||
@@ -85,28 +85,6 @@ export const mockJsonNestedResponseEuropeCountriesData = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const mockJsonNestedResponseEuropeCountriesDataWithSeparatorInPropertyName = {
|
|
||||||
response: {
|
|
||||||
empty: [],
|
|
||||||
'my.data': {
|
|
||||||
'country[data].country': mockEuropeCountriesData
|
|
||||||
},
|
|
||||||
data: [
|
|
||||||
{
|
|
||||||
id: 'HR',
|
|
||||||
name: 'Croatia'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
'no-array': {}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const mockJsonNestedResponseEuropeCountriesDataWithMultipleSpecialCharacters = {
|
|
||||||
response: {
|
|
||||||
'xyz:abc,xyz-abc,xyz_abc,abc+xyz': mockEuropeCountriesData
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const mockAmericaCountriesData = [
|
export const mockAmericaCountriesData = [
|
||||||
{
|
{
|
||||||
id: 'CA',
|
id: 'CA',
|
Reference in New Issue
Block a user