-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #180 from WoodWing/feature/CSH-9935-chart-property
CSH-9935: add chart property
- Loading branch information
Showing
10 changed files
with
280 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
/** | ||
* Validates usage of doc-chart directive | ||
* | ||
* Rules: | ||
* - A component is not allowed to have more than one doc-chart directive. | ||
* - A component with 1 doc-chart directive -must- have a property control type "chart-properties" | ||
* - A component property with a "chart-properties" control type MUST be applied to a "chart" directive | ||
* - A component without a doc-chart directive can't have any "chart-properties" control types | ||
*/ | ||
|
||
import { Validator } from './validator'; | ||
import { ComponentProperty, DirectiveType, Component } from '../models'; | ||
|
||
export class DocChartValidator extends Validator { | ||
async validate(): Promise<void> { | ||
Object.values(this.componentSet.components).forEach((c: Component) => this.validateComponent(c)); | ||
} | ||
|
||
private validateComponent(component: Component) { | ||
const numChartDirectives = this.countChartDirectives(component); | ||
if (numChartDirectives === 0) { | ||
this.validateComponentWithoutChartDirective(component); | ||
return; | ||
} | ||
|
||
if (numChartDirectives > 1) { | ||
this.error(`Component "${component.name}" can only have one "doc-chart" directive in the HTML definition`); | ||
return; | ||
} | ||
|
||
this.validateComponentWithChartDirective(component); | ||
} | ||
|
||
private validateComponentWithoutChartDirective(component: Component) { | ||
if (this.countChartPropertiesProperties(component) > 0) { | ||
this.error( | ||
`Component "${component.name}" has a "chart-properties" control type, but only components with a "doc-chart" directive can have a property with this control type`, | ||
); | ||
} | ||
} | ||
|
||
private validateComponentWithChartDirective(component: Component) { | ||
if (this.countChartPropertiesProperties(component) !== 1) { | ||
this.error( | ||
`Component "${ | ||
component.name | ||
}" with "doc-chart" directive must have exactly one "chart-properties" property (found ${this.countChartPropertiesProperties( | ||
component, | ||
)})`, | ||
); | ||
return; | ||
} | ||
|
||
// Check whether the chart-properties control type property is applied to the doc-chart directive. | ||
for (const chartProperty of Object.values(this.chartPropertiesProperties(component))) { | ||
this.validateChartProperty(component, chartProperty); | ||
} | ||
} | ||
|
||
private validateChartProperty(component: Component, chartProperty: ComponentProperty) { | ||
if (!chartProperty.directiveKey) { | ||
this.error( | ||
`Component "${component.name}" must configure "directiveKey" for the property with control type "chart-properties"`, | ||
); | ||
return; | ||
} | ||
|
||
const directive = component.directives[chartProperty.directiveKey]; | ||
if (!directive || directive.type !== DirectiveType.chart) { | ||
this.error( | ||
`Component "${component.name}" has a control type "chart-properties" applied to the wrong directive, which can only be used with "doc-chart" directives`, | ||
); | ||
} | ||
} | ||
|
||
private countChartDirectives(component: Component): number { | ||
return Object.values(component.directives).filter((directive) => directive.type === DirectiveType.chart).length; | ||
} | ||
|
||
/** Count number of "chart-properties" properties */ | ||
private countChartPropertiesProperties(component: Component): number { | ||
return this.chartPropertiesProperties(component).length; | ||
} | ||
|
||
/** Get "chart-properties" properties definitions (collection of nested properties behaving as a single property) */ | ||
private chartPropertiesProperties(component: Component) { | ||
return Object.values(component.properties).filter((property) => property.control.type === 'chart-properties'); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
import { DocChartValidator } from '../../lib/validators/doc-chart-validator'; | ||
|
||
describe('DocChartValidator', () => { | ||
let definition: any; | ||
let error: jest.Mock; | ||
let validator: DocChartValidator; | ||
|
||
beforeEach(() => { | ||
definition = { | ||
// valid definition (cut) | ||
components: { | ||
infographic: { | ||
name: 'Infographic', | ||
directives: { | ||
d1: { | ||
type: 'chart', | ||
tag: 'div', | ||
}, | ||
}, | ||
properties: [ | ||
{ | ||
name: 'chartproperty', | ||
directiveKey: 'd1', | ||
control: { | ||
type: 'chart-properties', | ||
}, | ||
}, | ||
], | ||
}, | ||
// Do not fail on different components without chart directive | ||
body: { | ||
name: 'body', | ||
directives: { | ||
d1: { | ||
type: 'editable', | ||
tag: 'p', | ||
}, | ||
}, | ||
properties: [], | ||
}, | ||
}, | ||
}; | ||
error = jest.fn(); | ||
validator = new DocChartValidator(error, definition); | ||
}); | ||
|
||
describe('validate', () => { | ||
it('should pass on a valid definition', () => { | ||
validator.validate(); | ||
expect(error).not.toHaveBeenCalled(); | ||
}); | ||
|
||
it('should not pass when there is a chart directive but no chart properties', () => { | ||
definition.components.infographic.properties = []; | ||
|
||
validator.validate(); | ||
expect(error).toHaveBeenCalledWith( | ||
`Component "Infographic" with "doc-chart" directive must have exactly one "chart-properties" property (found 0)`, | ||
); | ||
}); | ||
|
||
it('should pass with one chart directives and other directive types', () => { | ||
definition.components.infographic.directives.d2 = { | ||
type: 'editable', | ||
tag: 'p', | ||
}; | ||
definition.components.infographic.directives.d3 = { | ||
type: 'link', | ||
tag: 'a', | ||
}; | ||
validator.validate(); | ||
expect(error).not.toHaveBeenCalled(); | ||
}); | ||
|
||
it('should not pass with multiple chart type directives', () => { | ||
definition.components.infographic.directives.d2 = { | ||
type: 'chart', | ||
tag: 'div', | ||
}; | ||
validator.validate(); | ||
expect(error).toHaveBeenCalledWith( | ||
`Component "Infographic" can only have one "doc-chart" directive in the HTML definition`, | ||
); | ||
}); | ||
|
||
it('should fail if a component property with a chart-properties control type is not applied to a chart directive', () => { | ||
definition.components.wrongdirectivekey = { | ||
name: 'wrongdirectivekey', | ||
directives: { | ||
d1: { | ||
type: 'editable', | ||
tag: 'p', | ||
}, | ||
d2: { | ||
type: 'chart', | ||
tag: 'div', | ||
}, | ||
}, | ||
properties: [ | ||
{ | ||
name: 'chartproperty', | ||
directiveKey: 'd1', | ||
control: { | ||
type: 'chart-properties', | ||
logo: 'logos/chart.svg', | ||
link: 'www.chart.com', | ||
}, | ||
}, | ||
], | ||
}; | ||
validator.validate(); | ||
expect(error).toHaveBeenCalledWith( | ||
`Component "wrongdirectivekey" has a control type "chart-properties" applied to the wrong directive, which can only be used with "doc-chart" directives`, | ||
); | ||
}); | ||
|
||
it('should fail in case a "chart-properties" property does not have a directive key', () => { | ||
definition.components.nodirectivekey = { | ||
name: 'nodirectivekey', | ||
directives: { | ||
d1: { | ||
type: 'chart', | ||
tag: 'div', | ||
}, | ||
}, | ||
properties: [ | ||
{ | ||
name: 'chartproperty', | ||
control: { | ||
type: 'chart-properties', | ||
}, | ||
}, | ||
], | ||
}; | ||
validator.validate(); | ||
expect(error).toHaveBeenCalledWith( | ||
`Component "nodirectivekey" must configure "directiveKey" for the property with control type "chart-properties"`, | ||
); | ||
}); | ||
|
||
it('should fail in case a component without a chart directive has "chart-properties" property', () => { | ||
definition.components.body.properties = [ | ||
{ | ||
name: 'chartproperty', | ||
directiveKey: 'd1', | ||
control: { | ||
type: 'chart-properties', | ||
logo: 'logos/chart.svg', | ||
link: 'www.chart.com', | ||
}, | ||
}, | ||
]; | ||
|
||
validator.validate(); | ||
expect(error).toHaveBeenCalledWith( | ||
`Component "body" has a "chart-properties" control type, but only components with a "doc-chart" directive can have a property with this control type`, | ||
); | ||
}); | ||
}); | ||
}); |