mirror of https://github.com/artf/grapesjs.git
committed by
GitHub
20 changed files with 959 additions and 82 deletions
@ -0,0 +1,46 @@ |
|||||
|
import Component from '../../../dom_components/model/Component'; |
||||
|
import Components from '../../../dom_components/model/Components'; |
||||
|
import { ComponentDefinition, ComponentOptions } from '../../../dom_components/model/types'; |
||||
|
import { toLowerCase } from '../../../utils/mixins'; |
||||
|
import { DataCondition, ConditionalVariableType, Expression, LogicGroup } from './DataCondition'; |
||||
|
|
||||
|
type ConditionalComponentDefinition = { |
||||
|
condition: Expression | LogicGroup | boolean; |
||||
|
ifTrue: any; |
||||
|
ifFalse: any; |
||||
|
}; |
||||
|
|
||||
|
export default class ComponentConditionalVariable extends Component { |
||||
|
dataCondition: DataCondition; |
||||
|
componentDefinition: ConditionalComponentDefinition; |
||||
|
|
||||
|
constructor(componentDefinition: ConditionalComponentDefinition, opt: ComponentOptions) { |
||||
|
const { condition, ifTrue, ifFalse } = componentDefinition; |
||||
|
const dataConditionInstance = new DataCondition(condition, ifTrue, ifFalse, { em: opt.em }); |
||||
|
const initialComponentsProps = dataConditionInstance.getDataValue(); |
||||
|
const conditionalCmptDef = { |
||||
|
type: ConditionalVariableType, |
||||
|
components: initialComponentsProps, |
||||
|
}; |
||||
|
super(conditionalCmptDef, opt); |
||||
|
|
||||
|
this.componentDefinition = componentDefinition; |
||||
|
this.dataCondition = dataConditionInstance; |
||||
|
this.dataCondition.onValueChange = this.handleConditionChange.bind(this); |
||||
|
} |
||||
|
|
||||
|
private handleConditionChange() { |
||||
|
this.dataCondition.reevaluate(); |
||||
|
const updatedComponents = this.dataCondition.getDataValue(); |
||||
|
this.components().reset(); |
||||
|
this.components().add(updatedComponents); |
||||
|
} |
||||
|
|
||||
|
static isComponent(el: HTMLElement) { |
||||
|
return toLowerCase(el.tagName) === ConditionalVariableType; |
||||
|
} |
||||
|
|
||||
|
toJSON(): ComponentDefinition { |
||||
|
return this.dataCondition.toJSON(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,4 @@ |
|||||
|
import ComponentView from '../../dom_components/view/ComponentView'; |
||||
|
import ConditionalComponent from '../model/conditional_variables/ConditionalComponent'; |
||||
|
|
||||
|
export default class ConditionalComponentView extends ComponentView<ConditionalComponent> {} |
||||
@ -0,0 +1,242 @@ |
|||||
|
import { Component, DataSourceManager, Editor } from '../../../../../src'; |
||||
|
import { DataVariableType } from '../../../../../src/data_sources/model/DataVariable'; |
||||
|
import { MissingConditionError } from '../../../../../src/data_sources/model/conditional_variables/DataCondition'; |
||||
|
import { ConditionalVariableType } from '../../../../../src/data_sources/model/conditional_variables/DataCondition'; |
||||
|
import { GenericOperation } from '../../../../../src/data_sources/model/conditional_variables/operators/GenericOperator'; |
||||
|
import { NumberOperation } from '../../../../../src/data_sources/model/conditional_variables/operators/NumberOperator'; |
||||
|
import { DataSourceProps } from '../../../../../src/data_sources/types'; |
||||
|
import ConditionalComponentView from '../../../../../src/data_sources/view/ComponentDynamicView'; |
||||
|
import ComponentWrapper from '../../../../../src/dom_components/model/ComponentWrapper'; |
||||
|
import ComponentTableView from '../../../../../src/dom_components/view/ComponentTableView'; |
||||
|
import ComponentTextView from '../../../../../src/dom_components/view/ComponentTextView'; |
||||
|
import EditorModel from '../../../../../src/editor/model/Editor'; |
||||
|
import { setupTestEditor } from '../../../../common'; |
||||
|
|
||||
|
describe('ComponentConditionalVariable', () => { |
||||
|
let editor: Editor; |
||||
|
let em: EditorModel; |
||||
|
let dsm: DataSourceManager; |
||||
|
let cmpRoot: ComponentWrapper; |
||||
|
|
||||
|
beforeEach(() => { |
||||
|
({ editor, em, dsm, cmpRoot } = setupTestEditor()); |
||||
|
}); |
||||
|
|
||||
|
afterEach(() => { |
||||
|
em.destroy(); |
||||
|
}); |
||||
|
|
||||
|
it('should add a component with a condition that evaluates a component definition', () => { |
||||
|
const component = cmpRoot.append({ |
||||
|
type: ConditionalVariableType, |
||||
|
condition: { |
||||
|
left: 0, |
||||
|
operator: NumberOperation.greaterThan, |
||||
|
right: -1, |
||||
|
}, |
||||
|
ifTrue: { |
||||
|
tagName: 'h1', |
||||
|
type: 'text', |
||||
|
content: 'some text', |
||||
|
}, |
||||
|
})[0]; |
||||
|
expect(component).toBeDefined(); |
||||
|
expect(component.get('type')).toBe(ConditionalVariableType); |
||||
|
expect(component.getInnerHTML()).toBe('<h1>some text</h1>'); |
||||
|
const componentView = component.getView(); |
||||
|
expect(componentView).toBeInstanceOf(ConditionalComponentView); |
||||
|
expect(componentView?.el.textContent).toBe('some text'); |
||||
|
|
||||
|
const childComponent = getFirstChild(component); |
||||
|
const childView = getFirstChildView(component); |
||||
|
expect(childComponent).toBeDefined(); |
||||
|
expect(childComponent.get('type')).toBe('text'); |
||||
|
expect(childComponent.getInnerHTML()).toBe('some text'); |
||||
|
expect(childView).toBeInstanceOf(ComponentTextView); |
||||
|
expect(childView?.el.innerHTML).toBe('some text'); |
||||
|
}); |
||||
|
|
||||
|
it('should add a component with a condition that evaluates a string', () => { |
||||
|
const component = cmpRoot.append({ |
||||
|
type: ConditionalVariableType, |
||||
|
condition: { |
||||
|
left: 0, |
||||
|
operator: NumberOperation.greaterThan, |
||||
|
right: -1, |
||||
|
}, |
||||
|
ifTrue: '<h1>some text</h1>', |
||||
|
})[0]; |
||||
|
expect(component).toBeDefined(); |
||||
|
expect(component.get('type')).toBe(ConditionalVariableType); |
||||
|
expect(component.getInnerHTML()).toBe('<h1>some text</h1>'); |
||||
|
const componentView = component.getView(); |
||||
|
expect(componentView).toBeInstanceOf(ConditionalComponentView); |
||||
|
expect(componentView?.el.textContent).toBe('some text'); |
||||
|
|
||||
|
const childComponent = getFirstChild(component); |
||||
|
const childView = getFirstChildView(component); |
||||
|
expect(childComponent).toBeDefined(); |
||||
|
expect(childComponent.get('type')).toBe('text'); |
||||
|
expect(childComponent.getInnerHTML()).toBe('some text'); |
||||
|
expect(childView).toBeInstanceOf(ComponentTextView); |
||||
|
expect(childView?.el.innerHTML).toBe('some text'); |
||||
|
}); |
||||
|
|
||||
|
it('should test component variable with data-source', () => { |
||||
|
const dataSource: DataSourceProps = { |
||||
|
id: 'ds1', |
||||
|
records: [ |
||||
|
{ id: 'left_id', left: 'Name1' }, |
||||
|
{ id: 'right_id', right: 'Name1' }, |
||||
|
], |
||||
|
}; |
||||
|
dsm.add(dataSource); |
||||
|
|
||||
|
const component = cmpRoot.append({ |
||||
|
type: ConditionalVariableType, |
||||
|
condition: { |
||||
|
left: { |
||||
|
type: DataVariableType, |
||||
|
path: 'ds1.left_id.left', |
||||
|
}, |
||||
|
operator: GenericOperation.equals, |
||||
|
right: { |
||||
|
type: DataVariableType, |
||||
|
path: 'ds1.right_id.right', |
||||
|
}, |
||||
|
}, |
||||
|
ifTrue: { |
||||
|
tagName: 'h1', |
||||
|
type: 'text', |
||||
|
content: 'Some value', |
||||
|
}, |
||||
|
ifFalse: { |
||||
|
tagName: 'h1', |
||||
|
type: 'text', |
||||
|
content: 'False value', |
||||
|
}, |
||||
|
})[0]; |
||||
|
|
||||
|
const childComponent = getFirstChild(component); |
||||
|
expect(childComponent).toBeDefined(); |
||||
|
expect(childComponent.get('type')).toBe('text'); |
||||
|
expect(childComponent.getInnerHTML()).toBe('Some value'); |
||||
|
|
||||
|
/* Test changing datasources */ |
||||
|
updatedsmLeftValue(dsm, 'Diffirent value'); |
||||
|
expect(getFirstChild(component).getInnerHTML()).toBe('False value'); |
||||
|
expect(getFirstChildView(component)?.el.innerHTML).toBe('False value'); |
||||
|
updatedsmLeftValue(dsm, 'Name1'); |
||||
|
expect(getFirstChild(component).getInnerHTML()).toBe('Some value'); |
||||
|
expect(getFirstChildView(component)?.el.innerHTML).toBe('Some value'); |
||||
|
}); |
||||
|
|
||||
|
it('should test a conditional component with a child that is also a conditional component', () => { |
||||
|
const dataSource: DataSourceProps = { |
||||
|
id: 'ds1', |
||||
|
records: [ |
||||
|
{ id: 'left_id', left: 'Name1' }, |
||||
|
{ id: 'right_id', right: 'Name1' }, |
||||
|
], |
||||
|
}; |
||||
|
dsm.add(dataSource); |
||||
|
|
||||
|
const component = cmpRoot.append({ |
||||
|
type: ConditionalVariableType, |
||||
|
condition: { |
||||
|
left: { |
||||
|
type: DataVariableType, |
||||
|
path: 'ds1.left_id.left', |
||||
|
}, |
||||
|
operator: GenericOperation.equals, |
||||
|
right: { |
||||
|
type: DataVariableType, |
||||
|
path: 'ds1.right_id.right', |
||||
|
}, |
||||
|
}, |
||||
|
ifTrue: { |
||||
|
tagName: 'div', |
||||
|
components: [ |
||||
|
{ |
||||
|
type: ConditionalVariableType, |
||||
|
condition: { |
||||
|
left: { |
||||
|
type: DataVariableType, |
||||
|
path: 'ds1.left_id.left', |
||||
|
}, |
||||
|
operator: GenericOperation.equals, |
||||
|
right: { |
||||
|
type: DataVariableType, |
||||
|
path: 'ds1.right_id.right', |
||||
|
}, |
||||
|
}, |
||||
|
ifTrue: { |
||||
|
tagName: 'table', |
||||
|
type: 'table', |
||||
|
}, |
||||
|
}, |
||||
|
], |
||||
|
}, |
||||
|
})[0]; |
||||
|
|
||||
|
const innerComponent = getFirstChild(getFirstChild(component)); |
||||
|
const innerComponentView = getFirstChildView(innerComponent); |
||||
|
const innerHTML = '<table><tbody><tr class="row"><td class="cell"></td></tr></tbody></table>'; |
||||
|
expect(innerComponent.getInnerHTML()).toBe(innerHTML); |
||||
|
expect(innerComponentView).toBeInstanceOf(ComponentTableView); |
||||
|
expect(innerComponentView?.el.tagName).toBe('TABLE'); |
||||
|
}); |
||||
|
|
||||
|
it('should store conditional components', () => { |
||||
|
const conditionalCmptDef = { |
||||
|
type: ConditionalVariableType, |
||||
|
condition: { |
||||
|
left: 0, |
||||
|
operator: NumberOperation.greaterThan, |
||||
|
right: -1, |
||||
|
}, |
||||
|
ifTrue: [ |
||||
|
{ |
||||
|
tagName: 'h1', |
||||
|
type: 'text', |
||||
|
content: 'some text', |
||||
|
}, |
||||
|
], |
||||
|
}; |
||||
|
|
||||
|
cmpRoot.append(conditionalCmptDef)[0]; |
||||
|
|
||||
|
const projectData = editor.getProjectData(); |
||||
|
const page = projectData.pages[0]; |
||||
|
const frame = page.frames[0]; |
||||
|
const storageCmptDef = frame.component.components[0]; |
||||
|
expect(storageCmptDef).toEqual(conditionalCmptDef); |
||||
|
}); |
||||
|
|
||||
|
it('should throw an error if no condition is passed', () => { |
||||
|
const conditionalCmptDef = { |
||||
|
type: ConditionalVariableType, |
||||
|
ifTrue: { |
||||
|
tagName: 'h1', |
||||
|
type: 'text', |
||||
|
content: 'some text', |
||||
|
}, |
||||
|
}; |
||||
|
|
||||
|
expect(() => { |
||||
|
cmpRoot.append(conditionalCmptDef); |
||||
|
}).toThrow(MissingConditionError); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
function updatedsmLeftValue(dsm: DataSourceManager, newValue: string) { |
||||
|
dsm.get('ds1').getRecord('left_id')?.set('left', newValue); |
||||
|
} |
||||
|
|
||||
|
function getFirstChildView(component: Component) { |
||||
|
return getFirstChild(component).getView(); |
||||
|
} |
||||
|
|
||||
|
function getFirstChild(component: Component) { |
||||
|
return component.components().at(0); |
||||
|
} |
||||
@ -0,0 +1,135 @@ |
|||||
|
import { DataSourceManager, Editor } from '../../../../../src'; |
||||
|
import { DataVariableType } from '../../../../../src/data_sources/model/DataVariable'; |
||||
|
import { |
||||
|
ConditionalVariableType, |
||||
|
MissingConditionError, |
||||
|
} from '../../../../../src/data_sources/model/conditional_variables/DataCondition'; |
||||
|
import { GenericOperation } from '../../../../../src/data_sources/model/conditional_variables/operators/GenericOperator'; |
||||
|
import { NumberOperation } from '../../../../../src/data_sources/model/conditional_variables/operators/NumberOperator'; |
||||
|
import { DataSourceProps } from '../../../../../src/data_sources/types'; |
||||
|
import ComponentWrapper from '../../../../../src/dom_components/model/ComponentWrapper'; |
||||
|
import EditorModel from '../../../../../src/editor/model/Editor'; |
||||
|
import { filterObjectForSnapshot, setupTestEditor } from '../../../../common'; |
||||
|
|
||||
|
describe('StyleConditionalVariable', () => { |
||||
|
let editor: Editor; |
||||
|
let em: EditorModel; |
||||
|
let dsm: DataSourceManager; |
||||
|
let cmpRoot: ComponentWrapper; |
||||
|
|
||||
|
beforeEach(() => { |
||||
|
({ editor, em, dsm, cmpRoot } = setupTestEditor()); |
||||
|
}); |
||||
|
|
||||
|
afterEach(() => { |
||||
|
em.destroy(); |
||||
|
}); |
||||
|
|
||||
|
it('should add a component with a conditionally styled attribute', () => { |
||||
|
const component = cmpRoot.append({ |
||||
|
tagName: 'h1', |
||||
|
type: 'text', |
||||
|
content: 'some text', |
||||
|
style: { |
||||
|
color: { |
||||
|
type: ConditionalVariableType, |
||||
|
condition: { |
||||
|
left: 0, |
||||
|
operator: NumberOperation.greaterThan, |
||||
|
right: -1, |
||||
|
}, |
||||
|
ifTrue: 'red', |
||||
|
ifFalse: 'black', |
||||
|
}, |
||||
|
}, |
||||
|
})[0]; |
||||
|
|
||||
|
expect(component).toBeDefined(); |
||||
|
expect(component.getStyle().color).toBe('red'); |
||||
|
}); |
||||
|
|
||||
|
it('should change style based on data source changes', () => { |
||||
|
const dataSource: DataSourceProps = { |
||||
|
id: 'ds1', |
||||
|
records: [ |
||||
|
{ id: 'left_id', left: 'Value1' }, |
||||
|
{ id: 'right_id', right: 'Value2' }, |
||||
|
], |
||||
|
}; |
||||
|
dsm.add(dataSource); |
||||
|
|
||||
|
const component = cmpRoot.append({ |
||||
|
tagName: 'h1', |
||||
|
type: 'text', |
||||
|
content: 'some text', |
||||
|
style: { |
||||
|
color: { |
||||
|
type: ConditionalVariableType, |
||||
|
condition: { |
||||
|
left: { |
||||
|
type: DataVariableType, |
||||
|
path: 'ds1.left_id.left', |
||||
|
}, |
||||
|
operator: GenericOperation.equals, |
||||
|
right: { |
||||
|
type: DataVariableType, |
||||
|
path: 'ds1.right_id.right', |
||||
|
}, |
||||
|
}, |
||||
|
ifTrue: 'green', |
||||
|
ifFalse: 'blue', |
||||
|
}, |
||||
|
}, |
||||
|
})[0]; |
||||
|
|
||||
|
expect(component.getStyle().color).toBe('blue'); |
||||
|
|
||||
|
dsm.get('ds1').getRecord('right_id')?.set('right', 'Value1'); |
||||
|
expect(component.getStyle().color).toBe('green'); |
||||
|
}); |
||||
|
|
||||
|
it('should throw an error if no condition is passed in style', () => { |
||||
|
expect(() => { |
||||
|
cmpRoot.append({ |
||||
|
tagName: 'h1', |
||||
|
type: 'text', |
||||
|
content: 'some text', |
||||
|
style: { |
||||
|
color: { |
||||
|
type: ConditionalVariableType, |
||||
|
ifTrue: 'grey', |
||||
|
ifFalse: 'red', |
||||
|
}, |
||||
|
}, |
||||
|
}); |
||||
|
}).toThrow(MissingConditionError); |
||||
|
}); |
||||
|
|
||||
|
it.skip('should store components with conditional styles correctly', () => { |
||||
|
const conditionalStyleDef = { |
||||
|
tagName: 'h1', |
||||
|
type: 'text', |
||||
|
content: 'some text', |
||||
|
style: { |
||||
|
color: { |
||||
|
type: ConditionalVariableType, |
||||
|
condition: { |
||||
|
left: 0, |
||||
|
operator: NumberOperation.greaterThan, |
||||
|
right: -1, |
||||
|
}, |
||||
|
ifTrue: 'yellow', |
||||
|
ifFalse: 'black', |
||||
|
}, |
||||
|
}, |
||||
|
}; |
||||
|
|
||||
|
cmpRoot.append(conditionalStyleDef)[0]; |
||||
|
|
||||
|
const projectData = filterObjectForSnapshot(editor.getProjectData()); |
||||
|
const page = projectData.pages[0]; |
||||
|
const frame = page.frames[0]; |
||||
|
const storedComponent = frame.component.components[0]; |
||||
|
expect(storedComponent).toEqual(expect.objectContaining(conditionalStyleDef)); |
||||
|
}); |
||||
|
}); |
||||
@ -0,0 +1,283 @@ |
|||||
|
import { DataSourceManager, Editor } from '../../../../../src'; |
||||
|
import { DataVariableType } from '../../../../../src/data_sources/model/DataVariable'; |
||||
|
import { MissingConditionError } from '../../../../../src/data_sources/model/conditional_variables/DataCondition'; |
||||
|
import { ConditionalVariableType } from '../../../../../src/data_sources/model/conditional_variables/DataCondition'; |
||||
|
import { GenericOperation } from '../../../../../src/data_sources/model/conditional_variables/operators/GenericOperator'; |
||||
|
import { NumberOperation } from '../../../../../src/data_sources/model/conditional_variables/operators/NumberOperator'; |
||||
|
import { DataSourceProps } from '../../../../../src/data_sources/types'; |
||||
|
import Component, { dynamicAttrKey } from '../../../../../src/dom_components/model/Component'; |
||||
|
import ComponentWrapper from '../../../../../src/dom_components/model/ComponentWrapper'; |
||||
|
import EditorModel from '../../../../../src/editor/model/Editor'; |
||||
|
import { filterObjectForSnapshot, setupTestEditor } from '../../../../common'; |
||||
|
|
||||
|
describe('TraitConditionalVariable', () => { |
||||
|
let editor: Editor; |
||||
|
let em: EditorModel; |
||||
|
let dsm: DataSourceManager; |
||||
|
let cmpRoot: ComponentWrapper; |
||||
|
|
||||
|
beforeEach(() => { |
||||
|
({ editor, em, dsm, cmpRoot } = setupTestEditor()); |
||||
|
}); |
||||
|
|
||||
|
afterEach(() => { |
||||
|
em.destroy(); |
||||
|
}); |
||||
|
|
||||
|
it('should add a trait with a condition evaluating to a string', () => { |
||||
|
const component = cmpRoot.append({ |
||||
|
tagName: 'h1', |
||||
|
type: 'text', |
||||
|
traits: [ |
||||
|
{ |
||||
|
type: 'text', |
||||
|
name: 'title', |
||||
|
value: { |
||||
|
type: ConditionalVariableType, |
||||
|
condition: { |
||||
|
left: 0, |
||||
|
operator: NumberOperation.greaterThan, |
||||
|
right: -1, |
||||
|
}, |
||||
|
ifTrue: 'Some title', |
||||
|
}, |
||||
|
}, |
||||
|
], |
||||
|
})[0]; |
||||
|
|
||||
|
testComponentAttr(component, 'title', 'Some title'); |
||||
|
}); |
||||
|
|
||||
|
it('should add a trait with a data-source condition', () => { |
||||
|
const dataSource: DataSourceProps = { |
||||
|
id: 'ds1', |
||||
|
records: [{ id: 'left_id', left: 'Name1' }], |
||||
|
}; |
||||
|
dsm.add(dataSource); |
||||
|
|
||||
|
const component = cmpRoot.append({ |
||||
|
tagName: 'h1', |
||||
|
type: 'text', |
||||
|
traits: [ |
||||
|
{ |
||||
|
type: 'text', |
||||
|
name: 'title', |
||||
|
value: { |
||||
|
type: ConditionalVariableType, |
||||
|
condition: { |
||||
|
left: { |
||||
|
type: DataVariableType, |
||||
|
path: 'ds1.left_id.left', |
||||
|
}, |
||||
|
operator: GenericOperation.equals, |
||||
|
right: 'Name1', |
||||
|
}, |
||||
|
ifTrue: 'Valid name', |
||||
|
ifFalse: 'Invalid name', |
||||
|
}, |
||||
|
}, |
||||
|
], |
||||
|
})[0]; |
||||
|
|
||||
|
testComponentAttr(component, 'title', 'Valid name'); |
||||
|
}); |
||||
|
|
||||
|
it('should change trait value with changing data-source value', () => { |
||||
|
const dataSource: DataSourceProps = { |
||||
|
id: 'ds1', |
||||
|
records: [{ id: 'left_id', left: 'Name1' }], |
||||
|
}; |
||||
|
dsm.add(dataSource); |
||||
|
|
||||
|
const component = cmpRoot.append({ |
||||
|
tagName: 'h1', |
||||
|
type: 'text', |
||||
|
traits: [ |
||||
|
{ |
||||
|
type: 'text', |
||||
|
name: 'title', |
||||
|
value: { |
||||
|
type: ConditionalVariableType, |
||||
|
condition: { |
||||
|
left: { |
||||
|
type: DataVariableType, |
||||
|
path: 'ds1.left_id.left', |
||||
|
}, |
||||
|
operator: GenericOperation.equals, |
||||
|
right: 'Name1', |
||||
|
}, |
||||
|
ifTrue: 'Correct name', |
||||
|
ifFalse: 'Incorrect name', |
||||
|
}, |
||||
|
}, |
||||
|
], |
||||
|
})[0]; |
||||
|
|
||||
|
testComponentAttr(component, 'title', 'Correct name'); |
||||
|
dsm.get('ds1').getRecord('left_id')?.set('left', 'Different name'); |
||||
|
testComponentAttr(component, 'title', 'Incorrect name'); |
||||
|
}); |
||||
|
|
||||
|
it('should throw an error if no condition is passed in trait', () => { |
||||
|
expect(() => { |
||||
|
cmpRoot.append({ |
||||
|
tagName: 'h1', |
||||
|
type: 'text', |
||||
|
traits: [ |
||||
|
{ |
||||
|
type: 'text', |
||||
|
name: 'invalidTrait', |
||||
|
value: { |
||||
|
type: ConditionalVariableType, |
||||
|
}, |
||||
|
}, |
||||
|
], |
||||
|
}); |
||||
|
}).toThrow(MissingConditionError); |
||||
|
}); |
||||
|
|
||||
|
it('should store traits with conditional values correctly', () => { |
||||
|
const conditionalTrait = { |
||||
|
type: ConditionalVariableType, |
||||
|
condition: { |
||||
|
left: 0, |
||||
|
operator: NumberOperation.greaterThan, |
||||
|
right: -1, |
||||
|
}, |
||||
|
ifTrue: 'Positive', |
||||
|
}; |
||||
|
cmpRoot.append({ |
||||
|
tagName: 'h1', |
||||
|
type: 'text', |
||||
|
traits: [ |
||||
|
{ |
||||
|
type: 'text', |
||||
|
name: 'dynamicTrait', |
||||
|
value: conditionalTrait, |
||||
|
}, |
||||
|
], |
||||
|
})[0]; |
||||
|
|
||||
|
const projectData = editor.getProjectData(); |
||||
|
const snapshot = filterObjectForSnapshot(projectData); |
||||
|
expect(snapshot).toMatchSnapshot(``); |
||||
|
const page = projectData.pages[0]; |
||||
|
const frame = page.frames[0]; |
||||
|
const storedComponent = frame.component.components[0]; |
||||
|
|
||||
|
expect(storedComponent[dynamicAttrKey]).toEqual({ |
||||
|
dynamicTrait: conditionalTrait, |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
it('should load traits with conditional values correctly', () => { |
||||
|
const projectData = { |
||||
|
pages: [ |
||||
|
{ |
||||
|
frames: [ |
||||
|
{ |
||||
|
component: { |
||||
|
components: [ |
||||
|
{ |
||||
|
attributes: { |
||||
|
dynamicTrait: 'Default', |
||||
|
}, |
||||
|
[dynamicAttrKey]: { |
||||
|
dynamicTrait: { |
||||
|
condition: { |
||||
|
left: 0, |
||||
|
operator: '>', |
||||
|
right: -1, |
||||
|
}, |
||||
|
ifTrue: 'Positive', |
||||
|
type: 'conditional-variable', |
||||
|
}, |
||||
|
}, |
||||
|
type: 'text', |
||||
|
}, |
||||
|
], |
||||
|
type: 'wrapper', |
||||
|
}, |
||||
|
}, |
||||
|
], |
||||
|
type: 'main', |
||||
|
}, |
||||
|
], |
||||
|
}; |
||||
|
|
||||
|
editor.loadProjectData(projectData); |
||||
|
const components = editor.getComponents(); |
||||
|
const component = components.models[0]; |
||||
|
expect(component.getAttributes()).toEqual({ dynamicTrait: 'Positive' }); |
||||
|
}); |
||||
|
|
||||
|
it('should be property on the component with `changeProp:true`', () => { |
||||
|
const dataSource: DataSourceProps = { |
||||
|
id: 'ds1', |
||||
|
records: [{ id: 'left_id', left: 'Name1' }], |
||||
|
}; |
||||
|
dsm.add(dataSource); |
||||
|
|
||||
|
const component = cmpRoot.append({ |
||||
|
tagName: 'h1', |
||||
|
type: 'text', |
||||
|
traits: [ |
||||
|
{ |
||||
|
type: 'text', |
||||
|
name: 'title', |
||||
|
changeProp: true, |
||||
|
value: { |
||||
|
type: ConditionalVariableType, |
||||
|
condition: { |
||||
|
left: { |
||||
|
type: DataVariableType, |
||||
|
path: 'ds1.left_id.left', |
||||
|
}, |
||||
|
operator: GenericOperation.equals, |
||||
|
right: 'Name1', |
||||
|
}, |
||||
|
ifTrue: 'Correct name', |
||||
|
ifFalse: 'Incorrect name', |
||||
|
}, |
||||
|
}, |
||||
|
], |
||||
|
})[0]; |
||||
|
|
||||
|
// TODO: make dynamic values not to change the attributes if `changeProp:true`
|
||||
|
// expect(component.getView()?.el.getAttribute('title')).toBeNull();
|
||||
|
expect(component.get('title')).toBe('Correct name'); |
||||
|
|
||||
|
dsm.get('ds1').getRecord('left_id')?.set('left', 'Different name'); |
||||
|
// expect(component.getView()?.el.getAttribute('title')).toBeNull();
|
||||
|
expect(component.get('title')).toBe('Incorrect name'); |
||||
|
}); |
||||
|
|
||||
|
it('should handle objects as traits (other than dynamic values)', () => { |
||||
|
const traitValue = { |
||||
|
type: 'UNKNOWN_TYPE', |
||||
|
condition: "This's not a condition", |
||||
|
value: 'random value', |
||||
|
}; |
||||
|
|
||||
|
const component = cmpRoot.append({ |
||||
|
tagName: 'h1', |
||||
|
type: 'text', |
||||
|
traits: [ |
||||
|
{ |
||||
|
type: 'text', |
||||
|
name: 'title', |
||||
|
value: traitValue, |
||||
|
}, |
||||
|
], |
||||
|
})[0]; |
||||
|
expect(component.getTrait('title').get('value')).toEqual(traitValue); |
||||
|
expect(component.getAttributes().title).toEqual(traitValue); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
function testComponentAttr(component: Component, trait: string, value: string) { |
||||
|
expect(component).toBeDefined(); |
||||
|
expect(component.getTrait(trait).get('value')).toBe(value); |
||||
|
expect(component.getAttributes()[trait]).toBe(value); |
||||
|
expect(component.getView()?.el.getAttribute(trait)).toBe(value); |
||||
|
} |
||||
@ -0,0 +1,59 @@ |
|||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP |
||||
|
|
||||
|
exports[`TraitConditionalVariable should store traits with conditional values correctly 1`] = ` |
||||
|
{ |
||||
|
"assets": [], |
||||
|
"dataSources": [], |
||||
|
"pages": [ |
||||
|
{ |
||||
|
"frames": [ |
||||
|
{ |
||||
|
"component": { |
||||
|
"components": [ |
||||
|
{ |
||||
|
"attributes": { |
||||
|
"dynamicTrait": "Positive", |
||||
|
}, |
||||
|
"attributes-dynamic-value": { |
||||
|
"dynamicTrait": { |
||||
|
"condition": { |
||||
|
"left": 0, |
||||
|
"operator": ">", |
||||
|
"right": -1, |
||||
|
}, |
||||
|
"ifTrue": "Positive", |
||||
|
"type": "conditional-variable", |
||||
|
}, |
||||
|
}, |
||||
|
"tagName": "h1", |
||||
|
"type": "text", |
||||
|
}, |
||||
|
], |
||||
|
"docEl": { |
||||
|
"tagName": "html", |
||||
|
}, |
||||
|
"head": { |
||||
|
"type": "head", |
||||
|
}, |
||||
|
"stylable": [ |
||||
|
"background", |
||||
|
"background-color", |
||||
|
"background-image", |
||||
|
"background-repeat", |
||||
|
"background-attachment", |
||||
|
"background-position", |
||||
|
"background-size", |
||||
|
], |
||||
|
"type": "wrapper", |
||||
|
}, |
||||
|
"id": "data-variable-id", |
||||
|
}, |
||||
|
], |
||||
|
"id": "data-variable-id", |
||||
|
"type": "main", |
||||
|
}, |
||||
|
], |
||||
|
"styles": [], |
||||
|
"symbols": [], |
||||
|
} |
||||
|
`; |
||||
Loading…
Reference in new issue