diff --git a/examples/react/cypress/components/utils/adopt-user-nodes.cy.ts b/examples/react/cypress/components/utils/adopt-user-nodes.cy.ts index acc3c8a3..58157167 100644 --- a/examples/react/cypress/components/utils/adopt-user-nodes.cy.ts +++ b/examples/react/cypress/components/utils/adopt-user-nodes.cy.ts @@ -1,6 +1,5 @@ -import { adoptUserNodes } from '@xyflow/system'; - -import type { Node, NodeLookup, ParentLookup } from '@xyflow/react'; +import { adoptUserNodes, type NodeLookup, type ParentLookup } from '@xyflow/system'; +import type { CoordinateExtent, Node, NodeOrigin } from '@xyflow/react'; describe('adoptUserNodes Testing', () => { it('builds node lookup', () => { @@ -35,10 +34,40 @@ describe('adoptUserNodes Testing', () => { adoptUserNodes([userNode], nodeLookup, parentLookup, { nodeOrigin: [0.5, 0.5], }); + const internalNode = nodeLookup.get('1'); - expect(internalNode.internals.positionAbsolute.x).to.equal(userNode.position.x - userNode.measured.width / 2); - expect(internalNode.internals.positionAbsolute.y).to.equal(userNode.position.y - userNode.measured.height / 2); + expect(internalNode?.internals.positionAbsolute.x).to.equal( + userNode.position.x - (userNode.measured?.width ?? 0) / 2 + ); + expect(internalNode?.internals.positionAbsolute.y).to.equal( + userNode.position.y - (userNode.measured?.height ?? 0) / 2 + ); + }); + + it('calculates positionAbsolute with nodeExtent', () => { + const nodeLookup: NodeLookup = new Map(); + const parentLookup: ParentLookup = new Map(); + const nodeExtent: CoordinateExtent = [ + [0, 0], + [100, 100], + ]; + + const userNode: Node = { + id: '1', + data: { label: 'node' }, + position: { x: 500, y: 500 }, + measured: { width: 50, height: 25 }, + }; + + adoptUserNodes([userNode], nodeLookup, parentLookup, { + nodeExtent, + }); + + const internalNode = nodeLookup.get('1'); + + expect(internalNode?.internals.positionAbsolute.x).to.equal(nodeExtent[1][0] - userNode.measured!.width!); + expect(internalNode?.internals.positionAbsolute.y).to.equal(nodeExtent[1][1] - userNode.measured!.height!); }); it('calculates positionAbsolute for sub flow', () => { @@ -62,15 +91,14 @@ describe('adoptUserNodes Testing', () => { adoptUserNodes([userParentNode, userChildNode], nodeLookup, parentLookup); - const internalParentNode = nodeLookup.get('1'); const internalChildNode = nodeLookup.get('2'); expect(nodeLookup.size).to.equal(2); - expect(internalChildNode.internals.positionAbsolute.x).to.equal( + expect(internalChildNode?.internals.positionAbsolute.x).to.equal( userChildNode.position.x + userParentNode.position.x ); - expect(internalChildNode.internals.positionAbsolute.y).to.equal( + expect(internalChildNode?.internals.positionAbsolute.y).to.equal( userChildNode.position.y + userParentNode.position.y ); }); @@ -78,7 +106,7 @@ describe('adoptUserNodes Testing', () => { it('calculates positionAbsolute for sub flow with nodeOrigin', () => { const nodeLookup: NodeLookup = new Map(); const parentLookup: ParentLookup = new Map(); - const nodeOrigin = [0.5, 0.5]; + const nodeOrigin: NodeOrigin = [0.5, 0.5]; const userParentNode: Node = { id: '1', @@ -102,17 +130,74 @@ describe('adoptUserNodes Testing', () => { const internalParentNode = nodeLookup.get('1'); const internalChildNode = nodeLookup.get('2'); - const expectedParentX = userParentNode.position.x - userParentNode.measured.width * nodeOrigin[0]; - const expectedParentY = userParentNode.position.y - userParentNode.measured.height * nodeOrigin[1]; + const expectedParentX = userParentNode.position.x - userParentNode.measured!.width! * nodeOrigin[0]; + const expectedParentY = userParentNode.position.y - userParentNode.measured!.height! * nodeOrigin[1]; - expect(internalParentNode.internals.positionAbsolute.x).to.equal(expectedParentX); - expect(internalParentNode.internals.positionAbsolute.y).to.equal(expectedParentY); + expect(internalParentNode?.internals.positionAbsolute.x).to.equal(expectedParentX); + expect(internalParentNode?.internals.positionAbsolute.y).to.equal(expectedParentY); - const expectedChildX = userChildNode.position.x - userChildNode.measured.width * nodeOrigin[0] + expectedParentX; - const expectedChildY = userChildNode.position.y - userChildNode.measured.height * nodeOrigin[1] + expectedParentY; + const expectedChildX = userChildNode.position.x - userChildNode.measured!.width! * nodeOrigin[0] + expectedParentX; + const expectedChildY = userChildNode.position.y - userChildNode.measured!.height! * nodeOrigin[1] + expectedParentY; - expect(internalChildNode.internals.positionAbsolute.x).to.equal(expectedChildX); - expect(internalChildNode.internals.positionAbsolute.y).to.equal(expectedChildY); + expect(internalChildNode?.internals.positionAbsolute.x).to.equal(expectedChildX); + expect(internalChildNode?.internals.positionAbsolute.y).to.equal(expectedChildY); + }); + + it('calculates positionAbsolute for sub flow with nodeExtent', () => { + const nodeLookup: NodeLookup = new Map(); + const parentLookup: ParentLookup = new Map(); + const nodeExtent: CoordinateExtent = [ + [0, 0], + [200, 200], + ]; + + const userParentNodeA: Node = { + id: 'a', + data: { label: 'node' }, + position: { x: 500, y: 500 }, + measured: { width: 100, height: 50 }, + }; + + const userParentNodeB: Node = { + id: 'b', + data: { label: 'node' }, + position: { x: 0, y: 0 }, + measured: { width: 100, height: 50 }, + }; + + const userChildNode: Node = { + id: 'c', + data: { label: 'child' }, + position: { x: 1000, y: 1000 }, + measured: { width: 100, height: 50 }, + parentId: 'a', + }; + + adoptUserNodes([userParentNodeA, userParentNodeB, userChildNode], nodeLookup, parentLookup, { + nodeExtent, + }); + + const internalParentNodeA = nodeLookup.get('a'); + const internalParentNodeB = nodeLookup.get('b'); + + const internalChildNode = nodeLookup.get('c'); + + const expectedParentX = nodeExtent[1][0] - userParentNodeA.measured!.width!; + const expectedParentY = nodeExtent[1][1] - userParentNodeA.measured!.height!; + + // this node is inside the nodeExtent and should be restricted to it + expect(internalParentNodeA?.internals.positionAbsolute.x).to.equal(expectedParentX); + expect(internalParentNodeA?.internals.positionAbsolute.y).to.equal(expectedParentY); + + // this node is inside the nodeExtent and should not be affected by it + expect(internalParentNodeB?.internals.positionAbsolute.x).to.equal(userParentNodeB.position.x); + expect(internalParentNodeB?.internals.positionAbsolute.y).to.equal(userParentNodeB.position.y); + + const expectedChildX = nodeExtent[1][0] - userChildNode.measured!.width!; + const expectedChildY = nodeExtent[1][1] - userChildNode.measured!.height!; + + expect(internalChildNode?.internals.positionAbsolute.x).to.equal(expectedChildX); + expect(internalChildNode?.internals.positionAbsolute.y).to.equal(expectedChildY); }); });