diff --git a/packages/core/src/dom_components/index.ts b/packages/core/src/dom_components/index.ts index 8284f7696..8e987c5a4 100644 --- a/packages/core/src/dom_components/index.ts +++ b/packages/core/src/dom_components/index.ts @@ -116,6 +116,8 @@ import { isSymbolInstance, detachSymbolInstance, isSymbolRoot, + isSymbol as isSymbolComponent, + getSymbolTop, } from './model/SymbolUtils'; import { ComponentsEvents, SymbolInfo } from './types'; import Symbols from './model/Symbols'; @@ -840,9 +842,20 @@ export default class ComponentManager extends ItemManagerModule { describe('Main', () => { @@ -47,6 +48,7 @@ describe('DOM Components', () => { var setEm = () => { config.em = editorModel; }; + const createSymbol = (component: Component) => obj.addSymbol(component)!; beforeEach(() => { const editor = new Editor({ @@ -314,6 +316,76 @@ describe('DOM Components', () => { expect(rule.getStyle()).toEqual(newStyle); }); }); + + describe('Custom components with styles', () => { + test('canMove returns false if source is not provided', () => { + const target = obj.addComponent({ type: 'div' }) as Component; + const result = obj.canMove(target); + expect(result.result).toBe(false); + expect(result.reason).toBe(CanMoveReason.InvalidSource); + }); + + test('canMove returns false if target is not provided', () => { + const source = obj.addComponent({ type: 'div' }) as Component; + const result = obj.canMove(undefined as any, source); + expect(result.result).toBe(false); + expect(result.reason).toBe(CanMoveReason.InvalidSource); + }); + + test('canMove returns false when source and target have the same main symbol', () => { + const component = obj.addComponent({ type: 'div' }) as Component; + const mainSymbol = obj.addSymbol(component) as Component; + const target = obj.addSymbol(mainSymbol) as Component; + const source = obj.addSymbol(mainSymbol) as Component; + expect(obj.canMove(mainSymbol, source)).toMatchObject({ + result: false, + reason: CanMoveReason.TargetReject, + }); + + expect(obj.canMove(target, source)).toMatchObject({ + result: false, + reason: CanMoveReason.TargetReject, + }); + }); + + test('canMove returns true when source and target are the same instance', () => { + const component = obj.addComponent('

child

') as Component; + const mainSymbol = obj.addSymbol(component) as Component; + const childSymbol = mainSymbol.components().at(0); + expect(obj.canMove(mainSymbol, childSymbol).result).toBe(true); + }); + + test('canMove returns false when source is not draggable in the target', () => { + const target = obj.addComponent({ type: 'div', droppable: true }) as Component; + const source = obj.addComponent({ type: 'span', draggable: false }) as Component; + const result = obj.canMove(target, source); + expect(result.result).toBe(false); + expect(result.reason).toBe(CanMoveReason.SourceReject); + }); + + test('canMove returns false when target does not accept the source', () => { + const target = obj.addComponent({ type: 'div', droppable: false }) as Component; + const source = obj.addComponent({ type: 'span', draggable: true }) as Component; + const result = obj.canMove(target, source); + expect(result.result).toBe(false); + expect(result.reason).toBe(CanMoveReason.TargetReject); + }); + + test('canMove returns true when source is draggable and target is droppable', () => { + const target = obj.addComponent({ type: 'div', droppable: true }) as Component; + const source = obj.addComponent({ type: 'span', draggable: true }) as Component; + const result = obj.canMove(target, source); + expect(result.result).toBe(true); + }); + + test('canMove returns false when target is inside the source', () => { + const source = obj.addComponent({ type: 'div' }) as Component; + const target = source.append({ type: 'span' })[0]; + const result = obj.canMove(target, source); + expect(result.result).toBe(false); + expect(result.reason).toBe(CanMoveReason.TargetReject); + }); + }); }); describe('Rendered components', () => {