AAE-22577 Improve DataTable widget to support single object reference (e.g. only 1st element from array) - Case 3 (#9690)

* AAE-22577 Add single object path reference support

* AAE-22577 Update

* AAE-22577 Fix unit tests
This commit is contained in:
Wiktor Danielewski
2024-05-21 15:25:28 +02:00
committed by GitHub
parent 5218e7e928
commit 07370d963f
6 changed files with 104 additions and 62 deletions

View File

@@ -196,18 +196,6 @@ describe('DataTableWidgetComponent', () => {
assertData(mockCountryColumns, mockEuropeCountriesRows);
});
it('should NOT display error if form is in preview state', () => {
widget.field = getDataVariable(mockVariableConfig, mockSchemaDefinition, [], mockJsonFormVariableWithIncorrectData);
spyOn(formCloudService, 'getPreviewState').and.returnValue(true);
fixture.detectChanges();
const failedErrorMsgElement = fixture.debugElement.query(By.css('.adf-data-table-widget-failed-message'));
const previewDataTable = getPreview();
expect(failedErrorMsgElement).toBeNull();
expect(previewDataTable).toBeTruthy();
});
it('should NOT display data table with data source if form is in preview state', () => {
widget.field = getDataVariable(mockVariableConfig, mockSchemaDefinition, [], mockJsonFormVariable);
spyOn(formCloudService, 'getPreviewState').and.returnValue(true);
@@ -220,7 +208,33 @@ describe('DataTableWidgetComponent', () => {
expect(dataTable).toBeNull();
});
it('should display error if data source is not linked to every column', () => {
describe('should NOT display error message if', () => {
it('form is in preview state', () => {
widget.field = getDataVariable(mockVariableConfig, mockSchemaDefinition, [], mockJsonFormVariableWithIncorrectData);
spyOn(formCloudService, 'getPreviewState').and.returnValue(true);
fixture.detectChanges();
const failedErrorMsgElement = fixture.debugElement.query(By.css('.adf-data-table-widget-failed-message'));
const previewDataTable = getPreview();
expect(failedErrorMsgElement).toBeNull();
expect(previewDataTable).toBeTruthy();
});
it('path points to single object with appropriate schema definition', () => {
widget.field = getDataVariable({ ...mockVariableConfig, optionsPath: 'response.single-object' }, mockSchemaDefinition, [], []);
widget.field.value = mockJsonNestedResponseEuropeCountriesData;
fixture.detectChanges();
const failedErrorMsgElement = fixture.debugElement.query(By.css('.adf-data-table-widget-failed-message'));
assertData(mockCountryColumns, [mockEuropeCountriesRows[1]]);
expect(failedErrorMsgElement).toBeNull();
});
});
describe('should display error message if', () => {
it('data source is NOT linked to every column', () => {
widget.field = getDataVariable(mockVariableConfig, mockSchemaDefinition, [], mockJsonFormVariableWithIncorrectData);
fixture.detectChanges();
@@ -228,7 +242,7 @@ describe('DataTableWidgetComponent', () => {
expect(widget.dataSource.getRows()).toEqual([]);
});
it('should display error if data source has invalid column structure', () => {
it('data source has invalid column structure', () => {
widget.field = getDataVariable(mockVariableConfig, mockInvalidSchemaDefinition, [], mockJsonFormVariableWithIncorrectData);
fixture.detectChanges();
@@ -236,15 +250,20 @@ describe('DataTableWidgetComponent', () => {
expect(widget.dataSource.getRows()).toEqual([]);
});
it('should display error if data source is not found', () => {
widget.field = getDataVariable({ variableName: 'not-found-data-source' }, mockSchemaDefinition, [], mockJsonFormVariableWithIncorrectData);
it('data source is NOT found', () => {
widget.field = getDataVariable(
{ variableName: 'not-found-data-source' },
mockSchemaDefinition,
[],
mockJsonFormVariableWithIncorrectData
);
fixture.detectChanges();
checkDataTableErrorMessage();
expect(widget.dataSource).toBeUndefined();
});
it('should display error if path is incorrect', () => {
it('path is incorrect', () => {
widget.field = getDataVariable(
{ ...mockVariableConfig, optionsPath: 'wrong.path' },
mockSchemaDefinition,
@@ -257,9 +276,9 @@ describe('DataTableWidgetComponent', () => {
expect(widget.dataSource).toBeUndefined();
});
it('should display error if provided data by path is not an array', () => {
it('provided data by path is NOT an array or object', () => {
widget.field = getDataVariable(
{ ...mockVariableConfig, optionsPath: 'response.no-array' },
{ ...mockVariableConfig, optionsPath: 'response.no-array-or-object' },
mockSchemaDefinition,
mockJsonNestedResponseFormVariable,
[]
@@ -270,3 +289,4 @@ describe('DataTableWidgetComponent', () => {
expect(widget.dataSource).toBeUndefined();
});
});
});

View File

@@ -83,7 +83,7 @@ export class DataTableWidgetComponent extends WidgetComponent implements OnInit
this.handleError('Data source has corrupted model or structure');
}
} else {
this.handleError('Data source not found or it is not an array');
this.handleError('Data source not found or it is not an array/object');
}
}

View File

@@ -16,7 +16,7 @@
*/
import { DataTablePathParserHelper } from './data-table-path-parser.helper';
import { mockResponseResultData, mockResponseResultDataWithNestedArray, mockResultData } from '../mocks/data-table-path-parser.helper.mock';
import { mockResponseResultData, mockResponseResultDataWithArrayInsideArray, mockResultData } from '../mocks/data-table-path-parser.helper.mock';
interface DataTablePathParserTestCase {
description: string;
@@ -132,20 +132,32 @@ describe('DataTablePathParserHelper', () => {
description: 'with property followed by single index reference',
propertyName: 'users',
path: 'response.users[0].data',
data: mockResponseResultDataWithNestedArray('users')
data: mockResponseResultDataWithArrayInsideArray('users')
},
{
description: 'with property followed by multiple index references',
propertyName: 'users:Array',
path: 'response.[users:Array][0][1][12].data',
data: mockResponseResultDataWithNestedArray('users:Array'),
data: mockResponseResultDataWithArrayInsideArray('users:Array'),
expected: []
},
{
description: 'when path does NOT point to array',
description: 'when path points to array in the middle (incorrect path)',
propertyName: 'users',
path: 'response.users[0]',
data: mockResponseResultDataWithNestedArray('users'),
path: 'response.users.incorrectPath',
data: mockResponseResultDataWithArrayInsideArray('users'),
expected: []
},
{
description: 'when path points to the particular element of the array',
propertyName: 'users',
path: 'response.users[1]',
expected: [mockResultData[1]]
},
{
description: 'when path points to the particular element of the array which does NOT exist',
propertyName: 'users',
path: 'response.users[100]',
expected: []
}
];

View File

@@ -37,8 +37,10 @@ export class DataTablePathParserHelper {
const isPropertyWithSingleIndexReference = propertyIndexReferences.length === 1;
const nestedData = isPropertyWithSingleIndexReference ? data[purePropertyName]?.[propertyIndexReferences[0]] : data[purePropertyName];
if (Array.isArray(nestedData)) {
return nestedData;
if (nestedData && properties.length === 0) {
if (this.isDataArrayOrObject(nestedData)) {
return Array.isArray(nestedData) ? nestedData : [nestedData];
}
}
return this.retrieveDataFromPath(nestedData, properties.join('.'));
@@ -127,4 +129,11 @@ export class DataTablePathParserHelper {
private isPropertyExistsInData(data: any, property: string): boolean {
return Object.prototype.hasOwnProperty.call(data, property);
}
private isDataArrayOrObject(data: any): boolean {
if (data == null) {
return false;
}
return Array.isArray(data) || typeof data === 'object';
}
}

View File

@@ -44,7 +44,7 @@ export const mockResponseResultData = (propertyName?: string) => ({
}
});
export const mockResponseResultDataWithNestedArray = (propertyName?: string) => ({
export const mockResponseResultDataWithArrayInsideArray = (propertyName?: string) => ({
response: {
[propertyName]: [
{

View File

@@ -114,13 +114,14 @@ export const mockJsonNestedResponseEuropeCountriesData = {
response: {
empty: [],
'my-data': mockEuropeCountriesData,
'single-object': mockEuropeCountriesData[0],
'no-array-or-object': 'string-value',
data: [
{
id: 'HR',
name: 'Croatia'
}
],
'no-array': {}
]
}
};