Skip to content

Commit

Permalink
Merge pull request #265 from ditrit/bugfix/required_attributes
Browse files Browse the repository at this point in the history
Bugfix: required attributes
  • Loading branch information
Zorin95670 authored Aug 1, 2024
2 parents 4f4e7b8 + 6804f2c commit 90c1530
Show file tree
Hide file tree
Showing 5 changed files with 170 additions and 34 deletions.
6 changes: 6 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html)

## [Unreleased]

### Fixed

- Fix required attributes error.

## [0.26.1] - 2024/07/31

### Fixed
Expand Down
27 changes: 27 additions & 0 deletions src/models/Component.js
Original file line number Diff line number Diff line change
Expand Up @@ -378,12 +378,39 @@ class Component extends FileInformation {
*/
getErrors(errors = []) {
this.validateDefinition(errors);
this.validateRequiredAttributes(errors);

this.attributes.forEach((attribute) => attribute.getErrors(errors, true, this.id));

return errors;
}

/**
* Set error if is required and value is null.
* @param {ParserLog[]} [errors] - Errors to set, can be null.
* @returns {ParserLog[]} All attributes error.
*/
validateRequiredAttributes(errors = []) {
if (!this.definition) {
return errors;
}

this.definition.definedAttributes.forEach((attributeDefinition) => {
const attribute = this.attributes.find(({ name }) => name === attributeDefinition.name);

if (attributeDefinition.required && (!attribute || attribute.value === null)) {
errors.push(new ParserLog({
componentId: this.id,
severity: ParserLog.SEVERITY_ERROR,
message: 'parser.error.required',
attribute: attributeDefinition.name,
}));
}
});

return errors;
}

/**
* Set error if definition is null.
* @param {ParserLog[]} [errors] - Errors to set, can be null.
Expand Down
47 changes: 27 additions & 20 deletions src/models/ComponentAttribute.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,10 @@ class ComponentAttribute {
getErrors(errors = [], recurse = false, id = null) {
this.validateDefinitionType(errors, id);
this.validateType(errors, id);
this.validateRequired(errors, id);
this.validateRuleMinMax(errors, id);
this.validateRuleValues(errors, id);
this.validateRuleRegex(errors, id);
this.validateRequiredAttributes(errors, id);

if (recurse && this.definition?.type === 'Object' && Array.isArray(this.value)) {
this.value.forEach((attribute) => attribute.getErrors(errors, true, id));
Expand Down Expand Up @@ -190,25 +190,6 @@ class ComponentAttribute {
return errors;
}

/**
* Set error if is required and value is null.
* @param {ParserLog[]} [errors] - Errors to set, can be null.
* @param {string} [id] - Component id.
* @returns {ParserLog[]} All attributes error.
*/
validateRequired(errors = [], id = null) {
if (this.definition?.required && this.value === null) {
errors.push(new ParserLog({
componentId: id,
severity: ParserLog.SEVERITY_ERROR,
message: 'parser.error.required',
attribute: this.name,
}));
}

return errors;
}

/**
* Set error if :
* - Value is a string or array and its length is less than the specify minimum length.
Expand Down Expand Up @@ -302,5 +283,31 @@ class ComponentAttribute {

return errors;
}

/**
* Set error if is required and value is null.
* @param {ParserLog[]} [errors] - Errors to set, can be null.
* @returns {ParserLog[]} All attributes error.
*/
validateRequiredAttributes(errors = [], id = null) {
if (!this.definition || this.definition.type !== 'Object') {
return errors;
}

this.definition.definedAttributes.forEach((attributeDefinition) => {
const attribute = this.value.find(({ name }) => name === attributeDefinition.name);

if (attributeDefinition.required && (!attribute || attribute.value === null)) {
errors.push(new ParserLog({
componentId: id,
severity: ParserLog.SEVERITY_ERROR,
message: 'parser.error.required',
attribute: attributeDefinition.name,
}));
}
});

return errors;
}
}
export default ComponentAttribute;
73 changes: 73 additions & 0 deletions tests/unit/models/Component.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1120,6 +1120,37 @@ describe('Test class: Component', () => {
message: 'parser.error.notNumber',
})]);
});

it('should set error with missing child attribute', () => {
const parentAttributeDefinition = new ComponentAttributeDefinition({
type: 'Object',
name: 'parent',
definedAttributes: [new ComponentAttributeDefinition({
type: 'String',
name: 'child',
required: true,
})],
});
const component = new Component({
id: 'id',
definition: new ComponentDefinition({
definedAttributes: [parentAttributeDefinition],
}),
attributes: [new ComponentAttribute({
definition: parentAttributeDefinition,
type: 'Object',
name: 'parent',
value: [],
})],
});

expect(component.getErrors()).toEqual([new ParserLog({
componentId: 'id',
attribute: 'child',
severity: ParserLog.SEVERITY_ERROR,
message: 'parser.error.required',
})]);
});
});

describe('Test method: validateDefinition', () => {
Expand All @@ -1143,4 +1174,46 @@ describe('Test class: Component', () => {
})]);
});
});

describe('Test method: validateRequiredAttributes', () => {
it('should not set error without definition', () => {
const component = new Component({});

expect(component.validateRequiredAttributes()).toEqual([]);
});

it('should not set errors without required attribute', () => {
const component = new Component({
definition: new ComponentDefinition({
definedAttributes: [new ComponentAttributeDefinition({
required: false,
type: 'String',
name: 'test',
})],
}),
});

expect(component.validateRequiredAttributes()).toEqual([]);
});

it('should set errors with missing required attribute', () => {
const component = new Component({
id: 'id',
definition: new ComponentDefinition({
definedAttributes: [new ComponentAttributeDefinition({
required: true,
type: 'String',
name: 'test',
})],
}),
});

expect(component.validateRequiredAttributes()).toEqual([new ParserLog({
componentId: 'id',
attribute: 'test',
severity: ParserLog.SEVERITY_ERROR,
message: 'parser.error.required',
})]);
});
});
});
51 changes: 37 additions & 14 deletions tests/unit/models/ComponentAttribute.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -314,41 +314,64 @@ describe('Test class: ComponentAttribute', () => {
});
});

describe('Test method: validateRequired', () => {
it('should not set error with not required attribute', () => {
describe('Test method: validateRequiredAttributes', () => {
it('should not set error without definition', () => {
const attribute = new ComponentAttribute({
value: null,
});

expect(attribute.validateRequired()).toEqual([]);
expect(attribute.validateRequiredAttributes()).toEqual([]);
});

attribute.definition = new ComponentAttributeDefinition({
required: false,
it('should not set error with not Object attribute', () => {
const attribute = new ComponentAttribute({
definition: new ComponentAttributeDefinition({
type: 'String',
}),
type: 'String',
value: 'test',
});
expect(attribute.validateRequired()).toEqual([]);

expect(attribute.validateRequiredAttributes()).toEqual([]);
});

it('should not set error with not null value', () => {
it('should set error with not present attribute', () => {
const attribute = new ComponentAttribute({
definition: new ComponentAttributeDefinition({
required: true,
type: 'Object',
definedAttributes: [new ComponentAttributeDefinition({
name: 'test',
required: true,
})],
}),
value: 'test',
type: 'Object',
value: [],
});

expect(attribute.validateRequired()).toEqual([]);
expect(attribute.validateRequiredAttributes()).toEqual([new ParserLog({
severity: ParserLog.SEVERITY_ERROR,
message: 'parser.error.required',
attribute: 'test',
})]);
});

it('should set error with null value', () => {
const attribute = new ComponentAttribute({
definition: new ComponentAttributeDefinition({
required: true,
type: 'Object',
definedAttributes: [new ComponentAttributeDefinition({
name: 'test',
required: true,
})],
}),
name: 'test',
value: null,
type: 'Object',
value: [new ComponentAttribute({
name: 'test',
value: null,
})],
});

expect(attribute.validateRequired()).toEqual([new ParserLog({
expect(attribute.validateRequiredAttributes()).toEqual([new ParserLog({
severity: ParserLog.SEVERITY_ERROR,
message: 'parser.error.required',
attribute: 'test',
Expand Down

0 comments on commit 90c1530

Please sign in to comment.