import Editor from '../../../src/editor'; import DataSourceManager from '../../../src/data_sources'; import ComponentWrapper from '../../../src/dom_components/model/ComponentWrapper'; import { DataVariableType } from '../../../src/data_sources/model/DataVariable'; import EditorModel from '../../../src/editor/model/Editor'; import { ProjectData } from '../../../src/storage_manager'; import { DataSourceProps } from '../../../src/data_sources/types'; // Filter out the unique ids and selectors replaced with 'data-variable-id' // Makes the snapshot more stable function filterObjectForSnapshot(obj: any, parentKey: string = ''): any { const result: any = {}; for (const key in obj) { if (key === 'id') { result[key] = 'data-variable-id'; continue; } if (key === 'selectors') { result[key] = obj[key].map(() => 'data-variable-id'); continue; } if (typeof obj[key] === 'object' && obj[key] !== null) { if (Array.isArray(obj[key])) { result[key] = obj[key].map((item: any) => typeof item === 'object' ? filterObjectForSnapshot(item, key) : item, ); } else { result[key] = filterObjectForSnapshot(obj[key], key); } } else { result[key] = obj[key]; } } return result; } describe('DataSource Serialization', () => { let editor: Editor; let em: EditorModel; let dsm: DataSourceManager; let fixtures: HTMLElement; let cmpRoot: ComponentWrapper; const componentDataSource: DataSourceProps = { id: 'component-serialization', records: [ { id: 'id1', content: 'Hello World' }, { id: 'id2', color: 'red' }, ], }; const styleDataSource: DataSourceProps = { id: 'colors-data', records: [{ id: 'id1', color: 'red' }], }; const traitDataSource: DataSourceProps = { id: 'test-input', records: [{ id: 'id1', value: 'test-value' }], }; beforeEach(() => { editor = new Editor({ mediaCondition: 'max-width', avoidInlineStyle: true, }); em = editor.getModel(); dsm = em.DataSources; document.body.innerHTML = '
'; const { Pages, Components } = em; Pages.onLoad(); cmpRoot = Components.getWrapper()!; const View = Components.getType('wrapper')!.view; const wrapperEl = new View({ model: cmpRoot, config: { ...cmpRoot.config, em }, }); wrapperEl.render(); fixtures = document.body.querySelector('#fixtures')!; fixtures.appendChild(wrapperEl.el); dsm.add(componentDataSource); dsm.add(styleDataSource); dsm.add(traitDataSource); }); afterEach(() => { em.destroy(); }); test('component .getHtml', () => { const cmp = cmpRoot.append({ tagName: 'h1', type: 'text', components: [ { type: DataVariableType, defaultValue: 'default', path: `${componentDataSource.id}.id1.content`, }, ], })[0]; const el = cmp.getEl(); expect(el?.innerHTML).toContain('Hello World'); const html = em.getHtml(); expect(html).toMatchInlineSnapshot('"

Hello World

"'); }); describe('.getProjectData', () => { test('ComponentDataVariable', () => { const dataVariable = { type: DataVariableType, defaultValue: 'default', path: `${componentDataSource.id}.id1.content`, }; cmpRoot.append({ tagName: 'h1', type: 'text', components: [dataVariable], })[0]; const projectData = editor.getProjectData(); const page = projectData.pages[0]; const frame = page.frames[0]; const component = frame.component.components[0]; expect(component.components[0]).toEqual(dataVariable); const snapshot = filterObjectForSnapshot(projectData); expect(snapshot).toMatchSnapshot(``); }); test('StyleDataVariable', () => { const dataVariable = { type: DataVariableType, defaultValue: 'black', path: 'colors-data.id1.color', }; cmpRoot.append({ tagName: 'h1', type: 'text', content: 'Hello World', style: { color: dataVariable, }, })[0]; const projectData = editor.getProjectData(); const page = projectData.pages[0]; const frame = page.frames[0]; const component = frame.component.components[0]; const componentId = component.attributes.id; expect(componentId).toBeDefined(); const styleSelector = projectData.styles.find((style: any) => style.selectors[0] === `#${componentId}`); expect(styleSelector.style).toEqual({ color: dataVariable, }); const snapshot = filterObjectForSnapshot(projectData); expect(snapshot).toMatchSnapshot(``); }); test('TraitDataVariable', () => { const dataVariable = { type: DataVariableType, defaultValue: 'default', path: `${traitDataSource.id}.id1.value`, }; cmpRoot.append({ tagName: 'input', traits: [ 'name', { type: 'text', label: 'Value', name: 'value', value: dataVariable, }, ], })[0]; const projectData = editor.getProjectData(); const page = projectData.pages[0]; const frame = page.frames[0]; const component = frame.component.components[0]; expect(component).toHaveProperty('attributes-data-variable'); expect(component['attributes-data-variable']).toEqual({ value: dataVariable, }); expect(component.attributes).toEqual({ value: 'test-value', }); const snapshot = filterObjectForSnapshot(projectData); expect(snapshot).toMatchSnapshot(``); }); }); describe('.loadProjectData', () => { test('ComponentDataVariable', () => { const componentProjectData: ProjectData = { assets: [], pages: [ { frames: [ { component: { components: [ { components: [ { path: 'component-serialization.id1.content', type: 'data-variable', value: 'default', }, ], 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: [], }; editor.loadProjectData(componentProjectData); const components = editor.getComponents(); const component = components.models[0]; const html = component.toHTML(); expect(html).toContain('Hello World'); }); test('StyleDataVariable', () => { const componentProjectData: ProjectData = { assets: [], pages: [ { frames: [ { component: { components: [ { attributes: { id: 'selectorid', }, content: 'Hello World', 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: 'componentid', }, ], id: 'frameid', type: 'main', }, ], styles: [ { selectors: ['#selectorid'], style: { color: { path: 'colors-data.id1.color', type: 'data-variable', defaultValue: 'black', }, }, }, ], symbols: [], }; editor.loadProjectData(componentProjectData); const components = editor.getComponents(); const component = components.models[0]; const style = component.getStyle(); expect(style).toEqual({ color: 'red', }); }); test('TraitDataVariable', () => { const componentProjectData: ProjectData = { assets: [], pages: [ { frames: [ { component: { components: [ { attributes: { value: 'default', }, 'attributes-data-variable': { value: { path: 'test-input.id1.value', type: 'data-variable', defaultValue: 'default', }, }, tagName: 'input', void: true, }, ], docEl: { tagName: 'html', }, head: { type: 'head', }, stylable: [ 'background', 'background-color', 'background-image', 'background-repeat', 'background-attachment', 'background-position', 'background-size', ], type: 'wrapper', }, id: 'frameid', }, ], id: 'pageid', type: 'main', }, ], styles: [], symbols: [], }; editor.loadProjectData(componentProjectData); const components = editor.getComponents(); const component = components.models[0]; const value = component.getAttributes(); expect(value).toEqual({ value: 'test-value', }); }); }); });