mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
[AAE-16303] Handle nested property data source in data table (#8895)
This commit is contained in:
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { DataColumn, FormFieldModel, FormFieldTypes, FormModel, LogService } from '@alfresco/adf-core';
|
||||
import { DataColumn, FormFieldModel, FormFieldTypes, FormModel, LogService, VariableConfig } from '@alfresco/adf-core';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { DataTableWidgetComponent } from './data-table.widget';
|
||||
import { ProcessServiceCloudTestingModule } from '../../../../testing/process-service-cloud.testing.module';
|
||||
@@ -32,7 +32,9 @@ import {
|
||||
mockJsonProcessVariables,
|
||||
mockSchemaDefinition,
|
||||
mockJsonResponseEuropeCountriesData,
|
||||
mockJsonResponseFormVariable
|
||||
mockJsonResponseFormVariable,
|
||||
mockJsonNestedResponseFormVariable,
|
||||
mockJsonNestedResponseEuropeCountriesData
|
||||
} from '../../../mocks/data-table-widget.mock';
|
||||
|
||||
describe('DataTableWidgetComponent', () => {
|
||||
@@ -45,7 +47,7 @@ describe('DataTableWidgetComponent', () => {
|
||||
const errorIcon: string = 'error_outline';
|
||||
|
||||
const getDataVariable = (
|
||||
variableName: string,
|
||||
variableConfig: VariableConfig,
|
||||
schemaDefinition: DataColumn[],
|
||||
processVariables?: TaskVariableCloud[],
|
||||
variables?: TaskVariableCloud[]
|
||||
@@ -56,11 +58,19 @@ describe('DataTableWidgetComponent', () => {
|
||||
type: FormFieldTypes.DATA_TABLE,
|
||||
optionType: 'variable',
|
||||
schemaDefinition,
|
||||
variableConfig: {
|
||||
variableName
|
||||
}
|
||||
variableConfig
|
||||
});
|
||||
|
||||
const mockVariableConfig: VariableConfig = {
|
||||
variableName: 'json-form-variable'
|
||||
};
|
||||
|
||||
const checkDataTableErrorMessage = () => {
|
||||
const failedErrorMsgElement = fixture.debugElement.query(By.css('.adf-data-table-widget-failed-message'));
|
||||
|
||||
expect(failedErrorMsgElement.nativeElement.textContent.trim()).toBe(errorIcon.concat('FORM.FIELD.DATA_TABLE_LOAD_FAILED'));
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
@@ -101,7 +111,7 @@ describe('DataTableWidgetComponent', () => {
|
||||
});
|
||||
|
||||
it('should properly initialize column schema', () => {
|
||||
widget.field = getDataVariable('json-form-variable', mockSchemaDefinition, [], mockJsonFormVariable);
|
||||
widget.field = getDataVariable(mockVariableConfig, mockSchemaDefinition, [], mockJsonFormVariable);
|
||||
fixture.detectChanges();
|
||||
|
||||
widget.dataSource.getColumns().forEach((column, index) =>
|
||||
@@ -110,7 +120,7 @@ describe('DataTableWidgetComponent', () => {
|
||||
});
|
||||
|
||||
it('should properly initialize data source with priority on the field value if process and form variables are provided', () => {
|
||||
widget.field = getDataVariable('json-form-variable', mockSchemaDefinition, mockJsonProcessVariables, mockJsonFormVariable);
|
||||
widget.field = getDataVariable(mockVariableConfig, mockSchemaDefinition, mockJsonProcessVariables, mockJsonFormVariable);
|
||||
widget.field.value = mockAmericaCountriesData;
|
||||
fixture.detectChanges();
|
||||
|
||||
@@ -121,7 +131,7 @@ describe('DataTableWidgetComponent', () => {
|
||||
});
|
||||
|
||||
it('should properly initialize data source based on field value', () => {
|
||||
widget.field = getDataVariable('json-form-variable', mockSchemaDefinition, [], []);
|
||||
widget.field = getDataVariable(mockVariableConfig, mockSchemaDefinition, [], []);
|
||||
widget.field.value = mockAmericaCountriesData;
|
||||
fixture.detectChanges();
|
||||
|
||||
@@ -131,8 +141,8 @@ describe('DataTableWidgetComponent', () => {
|
||||
expect(widget.dataSource.getRows()).toEqual(expectedData.getRows());
|
||||
});
|
||||
|
||||
it('should properly initialize json response data source based on field value', () => {
|
||||
widget.field = getDataVariable('json-form-variable', mockSchemaDefinition, [], []);
|
||||
it('should properly initialize default json response data source based on field value if path is NOT provided', () => {
|
||||
widget.field = getDataVariable(mockVariableConfig, mockSchemaDefinition, [], []);
|
||||
widget.field.value = mockJsonResponseEuropeCountriesData;
|
||||
fixture.detectChanges();
|
||||
|
||||
@@ -142,8 +152,29 @@ describe('DataTableWidgetComponent', () => {
|
||||
expect(widget.dataSource.getRows()).toEqual(expectedData.getRows());
|
||||
});
|
||||
|
||||
it('should properly initialize json response data source based on variable', () => {
|
||||
widget.field = getDataVariable('json-form-variable', mockSchemaDefinition, [], mockJsonResponseFormVariable);
|
||||
it('should properly initialize default json response data source based on variable if path is NOT provided', () => {
|
||||
widget.field = getDataVariable(mockVariableConfig, mockSchemaDefinition, [], mockJsonResponseFormVariable);
|
||||
fixture.detectChanges();
|
||||
|
||||
const expectedData = new WidgetDataTableAdapter(mockEuropeCountriesData, mockSchemaDefinition);
|
||||
expectedData.getRows().forEach(row => row.cssClass = '');
|
||||
|
||||
expect(widget.dataSource.getRows()).toEqual(expectedData.getRows());
|
||||
});
|
||||
|
||||
it('should properly initialize json response data source based on field value if path is provided', () => {
|
||||
widget.field = getDataVariable({ ...mockVariableConfig, optionsPath: 'response.my-data' }, mockSchemaDefinition, [], []);
|
||||
widget.field.value = mockJsonNestedResponseEuropeCountriesData;
|
||||
fixture.detectChanges();
|
||||
|
||||
const expectedData = new WidgetDataTableAdapter(mockEuropeCountriesData, mockSchemaDefinition);
|
||||
expectedData.getRows().forEach(row => row.cssClass = '');
|
||||
|
||||
expect(widget.dataSource.getRows()).toEqual(expectedData.getRows());
|
||||
});
|
||||
|
||||
it('should properly initialize json response data source based on variable if path is provided', () => {
|
||||
widget.field = getDataVariable({ ...mockVariableConfig, optionsPath: 'response.my-data' }, mockSchemaDefinition, [], mockJsonNestedResponseFormVariable);
|
||||
fixture.detectChanges();
|
||||
|
||||
const expectedData = new WidgetDataTableAdapter(mockEuropeCountriesData, mockSchemaDefinition);
|
||||
@@ -153,7 +184,7 @@ describe('DataTableWidgetComponent', () => {
|
||||
});
|
||||
|
||||
it('should properly initialize data source based on form variable', () => {
|
||||
widget.field = getDataVariable('json-form-variable', mockSchemaDefinition, [], mockJsonFormVariable);
|
||||
widget.field = getDataVariable(mockVariableConfig, mockSchemaDefinition, [], mockJsonFormVariable);
|
||||
fixture.detectChanges();
|
||||
|
||||
const expectedData = new WidgetDataTableAdapter(mockEuropeCountriesData, mockSchemaDefinition);
|
||||
@@ -163,7 +194,7 @@ describe('DataTableWidgetComponent', () => {
|
||||
});
|
||||
|
||||
it('should properly initialize data source based on process variable', () => {
|
||||
widget.field = getDataVariable('json-variable', mockSchemaDefinition, mockJsonProcessVariables);
|
||||
widget.field = getDataVariable({ variableName: 'json-variable' }, mockSchemaDefinition, mockJsonProcessVariables);
|
||||
fixture.detectChanges();
|
||||
|
||||
const expectedData = new WidgetDataTableAdapter(mockEuropeCountriesData, mockSchemaDefinition);
|
||||
@@ -173,7 +204,7 @@ describe('DataTableWidgetComponent', () => {
|
||||
});
|
||||
|
||||
it('should NOT display error if form is in preview state', () => {
|
||||
widget.field = getDataVariable('json-form-variable', mockSchemaDefinition, [], mockJsonFormVariableWithIncorrectData);
|
||||
widget.field = getDataVariable(mockVariableConfig, mockSchemaDefinition, [], mockJsonFormVariableWithIncorrectData);
|
||||
spyOn(formCloudService, 'getPreviewState').and.returnValue(true);
|
||||
fixture.detectChanges();
|
||||
|
||||
@@ -185,7 +216,7 @@ describe('DataTableWidgetComponent', () => {
|
||||
});
|
||||
|
||||
it('should NOT display data table with data source if form is in preview state', () => {
|
||||
widget.field = getDataVariable('json-form-variable', mockSchemaDefinition, [], mockJsonFormVariable);
|
||||
widget.field = getDataVariable(mockVariableConfig, mockSchemaDefinition, [], mockJsonFormVariable);
|
||||
spyOn(formCloudService, 'getPreviewState').and.returnValue(true);
|
||||
fixture.detectChanges();
|
||||
|
||||
@@ -196,36 +227,48 @@ describe('DataTableWidgetComponent', () => {
|
||||
expect(dataTable).toBeNull();
|
||||
});
|
||||
|
||||
it('should be able to display and log error if data source is not linked to every column', () => {
|
||||
widget.field = getDataVariable('json-form-variable', mockSchemaDefinition, [], mockJsonFormVariableWithIncorrectData);
|
||||
it('should display and log error if data source is not linked to every column', () => {
|
||||
widget.field = getDataVariable(mockVariableConfig, mockSchemaDefinition, [], mockJsonFormVariableWithIncorrectData);
|
||||
fixture.detectChanges();
|
||||
|
||||
const failedErrorMsgElement = fixture.debugElement.query(By.css('.adf-data-table-widget-failed-message'));
|
||||
|
||||
expect(failedErrorMsgElement.nativeElement.textContent.trim()).toBe(errorIcon.concat('FORM.FIELD.DATA_TABLE_LOAD_FAILED'));
|
||||
checkDataTableErrorMessage();
|
||||
expect(logServiceSpy).toHaveBeenCalledWith('Data source has corrupted model or structure');
|
||||
expect(widget.dataSource.getRows()).toEqual([]);
|
||||
});
|
||||
|
||||
it('should be able to display and log error if data source has invalid column structure', () => {
|
||||
widget.field = getDataVariable('json-form-variable', mockInvalidSchemaDefinition, [], mockJsonFormVariableWithIncorrectData);
|
||||
it('should display and log error if data source has invalid column structure', () => {
|
||||
widget.field = getDataVariable(mockVariableConfig, mockInvalidSchemaDefinition, [], mockJsonFormVariableWithIncorrectData);
|
||||
fixture.detectChanges();
|
||||
|
||||
const failedErrorMsgElement = fixture.debugElement.query(By.css('.adf-data-table-widget-failed-message'));
|
||||
|
||||
expect(failedErrorMsgElement.nativeElement.textContent.trim()).toBe(errorIcon.concat('FORM.FIELD.DATA_TABLE_LOAD_FAILED'));
|
||||
checkDataTableErrorMessage();
|
||||
expect(logServiceSpy).toHaveBeenCalledWith('Data source has corrupted model or structure');
|
||||
expect(widget.dataSource.getRows()).toEqual([]);
|
||||
});
|
||||
|
||||
it('should be able to display and log error if data source is not found', () => {
|
||||
widget.field = getDataVariable('not-found-data-source', mockSchemaDefinition, [], mockJsonFormVariableWithIncorrectData);
|
||||
it('should display and log error if data source is not found', () => {
|
||||
widget.field = getDataVariable({ variableName: 'not-found-data-source' }, mockSchemaDefinition, [], mockJsonFormVariableWithIncorrectData);
|
||||
fixture.detectChanges();
|
||||
|
||||
const failedErrorMsgElement = fixture.debugElement.query(By.css('.adf-data-table-widget-failed-message'));
|
||||
checkDataTableErrorMessage();
|
||||
expect(logServiceSpy).toHaveBeenCalledWith('Data source not found or it is not an array');
|
||||
expect(widget.dataSource).toBeUndefined();
|
||||
});
|
||||
|
||||
expect(failedErrorMsgElement.nativeElement.textContent.trim()).toBe(errorIcon.concat('FORM.FIELD.DATA_TABLE_LOAD_FAILED'));
|
||||
expect(logServiceSpy).toHaveBeenCalledWith('Data source not found');
|
||||
it('should display and log error if path is incorrect', () => {
|
||||
widget.field = getDataVariable({ ...mockVariableConfig, optionsPath: 'wrong.path' }, mockSchemaDefinition, mockJsonNestedResponseFormVariable, []);
|
||||
fixture.detectChanges();
|
||||
|
||||
checkDataTableErrorMessage();
|
||||
expect(logServiceSpy).toHaveBeenCalledWith('Data source not found or it is not an array');
|
||||
expect(widget.dataSource).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should display and log error if provided data by path is not an array', () => {
|
||||
widget.field = getDataVariable({ ...mockVariableConfig, optionsPath: 'response.no-array' }, mockSchemaDefinition, mockJsonNestedResponseFormVariable, []);
|
||||
fixture.detectChanges();
|
||||
|
||||
checkDataTableErrorMessage();
|
||||
expect(logServiceSpy).toHaveBeenCalledWith('Data source not found or it is not an array');
|
||||
expect(widget.dataSource).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
@@ -90,7 +90,7 @@ export class DataTableWidgetComponent extends WidgetComponent implements OnInit
|
||||
}
|
||||
|
||||
private initDataTable(): void {
|
||||
if (this.rowsData) {
|
||||
if (this.rowsData?.length) {
|
||||
this.dataSource = new WidgetDataTableAdapter(this.rowsData, this.columnsSchema);
|
||||
|
||||
if (this.dataSource.isDataSourceValid()) {
|
||||
@@ -99,16 +99,18 @@ export class DataTableWidgetComponent extends WidgetComponent implements OnInit
|
||||
this.handleError('Data source has corrupted model or structure');
|
||||
}
|
||||
} else {
|
||||
this.handleError('Data source not found');
|
||||
this.handleError('Data source not found or it is not an array');
|
||||
}
|
||||
}
|
||||
|
||||
private getRowsData(): void {
|
||||
const optionsPath = this.field?.variableConfig?.optionsPath ?? this.defaultResponseProperty;
|
||||
const fieldValue = this.field?.value;
|
||||
const rowsData = fieldValue ? fieldValue : this.getDataFromVariable();
|
||||
const rowsData = fieldValue || this.getDataFromVariable();
|
||||
|
||||
if (rowsData) {
|
||||
this.rowsData = rowsData[this.defaultResponseProperty] || rowsData as DataRow[];
|
||||
const dataFromPath = this.getOptionsFromPath(rowsData, optionsPath);
|
||||
this.rowsData = dataFromPath?.length ? dataFromPath : rowsData as DataRow[];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,6 +124,23 @@ export class DataTableWidgetComponent extends WidgetComponent implements OnInit
|
||||
return processVariableDropdownOptions ?? formVariableDropdownOptions;
|
||||
}
|
||||
|
||||
private getOptionsFromPath(data: any, path: string): DataRow[] {
|
||||
const properties = path.split('.');
|
||||
const currentProperty = properties.shift();
|
||||
|
||||
if (!data.hasOwnProperty(currentProperty)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const nestedData = data[currentProperty];
|
||||
|
||||
if (Array.isArray(nestedData)) {
|
||||
return nestedData;
|
||||
}
|
||||
|
||||
return this.getOptionsFromPath(nestedData, properties.join('.'));
|
||||
}
|
||||
|
||||
private getVariableValueByName(variables: TaskVariableCloud[], variableName: string): any {
|
||||
return variables?.find((variable: TaskVariableCloud) => variable?.name === `variables.${variableName}` || variable?.name === variableName)?.value;
|
||||
}
|
||||
|
@@ -85,20 +85,21 @@ export const mockEuropeCountriesData = [
|
||||
];
|
||||
|
||||
export const mockJsonResponseEuropeCountriesData = {
|
||||
data: [
|
||||
{
|
||||
id: 'PL',
|
||||
name: 'Poland'
|
||||
},
|
||||
{
|
||||
id: 'IT',
|
||||
name: 'Italy'
|
||||
},
|
||||
{
|
||||
id: 'UK',
|
||||
name: 'United Kingdom'
|
||||
}
|
||||
]
|
||||
data: mockEuropeCountriesData
|
||||
};
|
||||
|
||||
export const mockJsonNestedResponseEuropeCountriesData = {
|
||||
response: {
|
||||
empty: [],
|
||||
'my-data': mockEuropeCountriesData,
|
||||
data: [
|
||||
{
|
||||
id: 'HR',
|
||||
name: 'Croatia'
|
||||
}
|
||||
],
|
||||
'no-array': {}
|
||||
}
|
||||
};
|
||||
|
||||
export const mockAmericaCountriesData = [
|
||||
@@ -137,6 +138,10 @@ export const mockJsonResponseFormVariable = [
|
||||
new TaskVariableCloud({ name: 'json-form-variable', value: mockJsonResponseEuropeCountriesData, type: 'json', id: 'fake-id-1' })
|
||||
];
|
||||
|
||||
export const mockJsonNestedResponseFormVariable = [
|
||||
new TaskVariableCloud({ name: 'json-form-variable', value: mockJsonNestedResponseEuropeCountriesData, type: 'json', id: 'fake-id-1' })
|
||||
];
|
||||
|
||||
export const mockJsonProcessVariables = [
|
||||
new TaskVariableCloud({ name: 'variables.json-variable', value: mockEuropeCountriesData, type: 'json', id: 'fake-id-1' }),
|
||||
new TaskVariableCloud({ name: 'variables.different-variable', value: 'fake-value', type: 'json', id: 'fake-id-2' })
|
||||
|
Reference in New Issue
Block a user