chore(svelte-examples): pull out of lib package (#3363)
* chore(svelte-examples): pull out of lib package * chore(svelte-examples): cleanup * chore(examples): add readme files
This commit is contained in:
@@ -0,0 +1,312 @@
|
||||
import { ReactFlow, ReactFlowProps, Viewport, useViewport, SnapGrid, CoordinateExtent, Node } from '@xyflow/react';
|
||||
|
||||
import ControlledFlow from '../../support/ControlledFlow';
|
||||
import * as simpleflow from '../../fixtures/simpleflow';
|
||||
|
||||
const nodesOutsideOfView = [
|
||||
{
|
||||
...simpleflow.nodes[0],
|
||||
position: {
|
||||
x: -500,
|
||||
y: 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
...simpleflow.nodes[1],
|
||||
position: {
|
||||
x: 500,
|
||||
y: 0,
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
describe('<ReactFlow />: View Props', () => {
|
||||
it('uses fitView', () => {
|
||||
cy.mount(<Comp nodes={nodesOutsideOfView} fitView minZoom={0.2} />).wait(200);
|
||||
cy.get('.react-flow__node:first').isWithinViewport();
|
||||
});
|
||||
|
||||
it('uses fitViewOptions', () => {
|
||||
const fitViewOptions = { padding: 0.5 };
|
||||
|
||||
cy.mount(<ReactFlow nodes={[nodesOutsideOfView[0]]} fitView fitViewOptions={fitViewOptions} />).wait(200);
|
||||
cy.get('.react-flow__node:first').isWithinViewport();
|
||||
});
|
||||
|
||||
describe('uses minZoom', () => {
|
||||
it('minZoom: 0.2', () => {
|
||||
const onChangeSpy = cy.spy().as('onChangeSpy');
|
||||
|
||||
cy.mount(<Comp minZoom={0.2} onChange={onChangeSpy} />);
|
||||
cy.zoomPane(10000).then(() => {
|
||||
expect(getLatestViewport(onChangeSpy).zoom).to.be.eq(0.2);
|
||||
});
|
||||
});
|
||||
|
||||
it('minZoom: 1', () => {
|
||||
const onChangeSpy = cy.spy().as('onChangeSpy');
|
||||
|
||||
cy.mount(<Comp minZoom={1} onChange={onChangeSpy} />);
|
||||
cy.zoomPane(10000).then(() => {
|
||||
expect(getLatestViewport(onChangeSpy).zoom).to.be.eq(1);
|
||||
});
|
||||
});
|
||||
|
||||
it('sets invalid defaultZoom', () => {
|
||||
const onChangeSpy = cy.spy().as('onChangeSpy');
|
||||
const defaultViewport = { x: 0, y: 0, zoom: 0.2 };
|
||||
|
||||
cy.mount(<Comp minZoom={1} defaultViewport={defaultViewport} onChange={onChangeSpy} />);
|
||||
cy.zoomPane(10000).then(() => {
|
||||
expect(getLatestViewport(onChangeSpy).zoom).to.be.eq(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('uses maxZoom', () => {
|
||||
it('maxZoom: 1', () => {
|
||||
const onChangeSpy = cy.spy().as('onChangeSpy');
|
||||
|
||||
cy.mount(<Comp maxZoom={1} onChange={onChangeSpy} />);
|
||||
cy.zoomPane(-10000).then(() => {
|
||||
expect(getLatestViewport(onChangeSpy).zoom).to.be.eq(1);
|
||||
});
|
||||
});
|
||||
|
||||
it('maxZoom: 2', () => {
|
||||
const onChangeSpy = cy.spy().as('onChangeSpy');
|
||||
|
||||
cy.mount(<Comp maxZoom={2} onChange={onChangeSpy} />);
|
||||
cy.zoomPane(-10000).then(() => {
|
||||
expect(getLatestViewport(onChangeSpy).zoom).to.be.eq(2);
|
||||
});
|
||||
});
|
||||
|
||||
it('sets invalid defaultZoom', () => {
|
||||
const onChangeSpy = cy.spy().as('onChangeSpy');
|
||||
const defaultViewport = { x: 0, y: 0, zoom: 2 };
|
||||
|
||||
cy.mount(<Comp maxZoom={1.5} defaultViewport={defaultViewport} onChange={onChangeSpy} />);
|
||||
cy.zoomPane(-10000).then(() => {
|
||||
expect(getLatestViewport(onChangeSpy).zoom).to.be.eq(1.5);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('uses defaultViewport', () => {
|
||||
it('defaultViewport: { x: 0, y: 0, zoom: 1 }', () => {
|
||||
const onChangeSpy = cy.spy().as('onChangeSpy');
|
||||
const defaultViewport = { x: 0, y: 0, zoom: 1 };
|
||||
|
||||
cy.mount(<Comp nodes={simpleflow.nodes} defaultViewport={defaultViewport} onChange={onChangeSpy} />).then(() => {
|
||||
expect(getLatestViewport(onChangeSpy)).to.be.eql(defaultViewport);
|
||||
});
|
||||
});
|
||||
|
||||
it('defaultViewport: { x: 0, y: 0, zoom: 1.5 }', () => {
|
||||
const onChangeSpy = cy.spy().as('onChangeSpy');
|
||||
const defaultViewport = { x: 0, y: 0, zoom: 1.5 };
|
||||
|
||||
cy.mount(<Comp nodes={simpleflow.nodes} defaultViewport={defaultViewport} onChange={onChangeSpy} />).then(() => {
|
||||
expect(getLatestViewport(onChangeSpy)).to.be.eql(defaultViewport);
|
||||
});
|
||||
});
|
||||
|
||||
it('defaultViewport: { x: 100, y: 100, zoom: 1.5 }', () => {
|
||||
const onChangeSpy = cy.spy().as('onChangeSpy');
|
||||
const defaultViewport = { x: 100, y: 100, zoom: 1.5 };
|
||||
|
||||
cy.mount(<Comp nodes={simpleflow.nodes} defaultViewport={defaultViewport} onChange={onChangeSpy} />).then(() => {
|
||||
expect(getLatestViewport(onChangeSpy)).to.be.eql(defaultViewport);
|
||||
});
|
||||
});
|
||||
|
||||
it('defaultViewport: invalid { x: 0, y: 0, zoom: -1 }', () => {
|
||||
const onChangeSpy = cy.spy().as('onChangeSpy');
|
||||
const defaultViewport = { x: 0, y: 0, zoom: -1 };
|
||||
|
||||
cy.mount(<Comp nodes={simpleflow.nodes} defaultViewport={defaultViewport} onChange={onChangeSpy} />).then(() => {
|
||||
// this should be min zoom because zoom is clamped
|
||||
expect(getLatestViewport(onChangeSpy).zoom).to.be.eql(0.5);
|
||||
});
|
||||
});
|
||||
|
||||
it('defaultViewport: invalid { x: 0, y: 0, zoom: 100 }', () => {
|
||||
const onChangeSpy = cy.spy().as('onChangeSpy');
|
||||
const defaultViewport = { x: 0, y: 0, zoom: 100 };
|
||||
|
||||
cy.mount(<Comp nodes={simpleflow.nodes} defaultViewport={defaultViewport} onChange={onChangeSpy} />).then(() => {
|
||||
// this should be max zoom because zoom is clamped
|
||||
expect(getLatestViewport(onChangeSpy).zoom).to.be.eql(2);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('uses snapGrid and snapToGrid', () => {
|
||||
const snapGrid: SnapGrid = [100, 100];
|
||||
|
||||
cy.mount(<ControlledFlow initialNodes={simpleflow.nodes} snapGrid={snapGrid} snapToGrid />).then(() => {
|
||||
cy.drag('.react-flow__node:first', { x: 125, y: 125 }).then(($el: any) => {
|
||||
const transformAfterDrag = $el.css('transform');
|
||||
const { m41: nodeX, m42: nodeY } = new DOMMatrixReadOnly(transformAfterDrag);
|
||||
expect([nodeX, nodeY]).to.eql(snapGrid);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('uses onlyRenderVisibleElements', () => {
|
||||
it('displays no nodes', () => {
|
||||
cy.mount(<ControlledFlow initialNodes={nodesOutsideOfView} onlyRenderVisibleElements />).then(() => {
|
||||
cy.get('.react-flow__node').should('have.length', 0);
|
||||
});
|
||||
});
|
||||
|
||||
it('displays one node', () => {
|
||||
const nodes = nodesOutsideOfView.map((n) => {
|
||||
if (n.id === '1') {
|
||||
return { ...n, position: { x: 0, y: 0 } };
|
||||
}
|
||||
return n;
|
||||
});
|
||||
cy.mount(<ControlledFlow initialNodes={nodes} onlyRenderVisibleElements />).then(() => {
|
||||
cy.get('.react-flow__node').should('have.length', 1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('uses translateExtent', () => {
|
||||
const translateExtent: CoordinateExtent = [
|
||||
[0, 0],
|
||||
[1000, 1000],
|
||||
];
|
||||
|
||||
cy.mount(<ControlledFlow translateExtent={translateExtent} />).then(() => {
|
||||
const transformBeforeDrag = Cypress.$('.react-flow__viewport').css('transform');
|
||||
|
||||
cy.dragPane({ from: { x: 0, y: 0 }, to: { x: 100, y: 100 } }).then(() => {
|
||||
const transformAfterDrag = Cypress.$('.react-flow__viewport').css('transform');
|
||||
expect(transformBeforeDrag).to.eql(transformAfterDrag);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('uses nodeExtent', () => {
|
||||
const nodes: Node[] = [
|
||||
{
|
||||
id: '1',
|
||||
position: { x: 200, y: 200 },
|
||||
data: { label: '1' },
|
||||
},
|
||||
];
|
||||
|
||||
const nodeExtent: CoordinateExtent = [
|
||||
[0, 0],
|
||||
[50, 50],
|
||||
];
|
||||
|
||||
cy.mount(<ControlledFlow nodes={nodes} nodeExtent={nodeExtent} />)
|
||||
.wait(500)
|
||||
.then(() => {
|
||||
const transform = Cypress.$('.react-flow__node:first').css('transform');
|
||||
const { m41: nodeX, m42: nodeY } = new DOMMatrixReadOnly(transform);
|
||||
expect(nodeX).to.equal(50);
|
||||
expect(nodeY).to.equal(50);
|
||||
});
|
||||
});
|
||||
|
||||
describe('uses preventScrolling', () => {
|
||||
function ScrollFlow({ preventScrolling }: { preventScrolling: boolean }) {
|
||||
return (
|
||||
<div className="wrapper" style={{ height: 2000 }}>
|
||||
<div className="inner" style={{ height: 500 }}>
|
||||
<ControlledFlow preventScrolling={preventScrolling} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
it('lets user scroll', () => {
|
||||
cy.mount(<ScrollFlow preventScrolling={false} />).then(() => {
|
||||
cy.window().then((window) => {
|
||||
cy.get('.react-flow__pane').trigger('wheel', {
|
||||
wheelDelta: 240,
|
||||
wheelDeltaX: 0,
|
||||
wheelDeltaY: 240,
|
||||
eventConstructor: 'WheelEvent',
|
||||
view: window,
|
||||
});
|
||||
|
||||
// @TODO: why is this not working?
|
||||
// it seems that the event is somehow broken. This works fine when using the mouse.
|
||||
// cy.window().its('scrollY').should('be.gt', 0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('does not user scroll', () => {
|
||||
cy.mount(<ScrollFlow preventScrolling={true} />).then(() => {
|
||||
cy.window().then((window) => {
|
||||
cy.get('.react-flow__pane').trigger('wheel', {
|
||||
wheelDelta: 240,
|
||||
wheelDeltaX: 0,
|
||||
wheelDeltaY: 240,
|
||||
eventConstructor: 'WheelEvent',
|
||||
view: window,
|
||||
});
|
||||
|
||||
cy.window().its('scrollY').should('be.equal', 0);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('uses attributionPosition', () => {
|
||||
it('displays it on the bottom right', () => {
|
||||
cy.mount(<ControlledFlow />).then(() => {
|
||||
cy.get('.react-flow__attribution').then(($el) => {
|
||||
const { left, top, width, height } = $el[0].getBoundingClientRect();
|
||||
|
||||
expect(left).equal(window.innerWidth - width);
|
||||
expect(top).equal(window.innerHeight - height);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('displays it on the top left', () => {
|
||||
cy.mount(<ControlledFlow attributionPosition="top-left" />).then(() => {
|
||||
cy.get('.react-flow__attribution').then(($el) => {
|
||||
const { left, top } = $el[0].getBoundingClientRect();
|
||||
|
||||
expect(left).equal(0);
|
||||
expect(top).equal(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// test specific helpers
|
||||
|
||||
type CompProps = {
|
||||
onChange?: (vp: Viewport) => void;
|
||||
};
|
||||
|
||||
function InnerComp({ onChange }: CompProps) {
|
||||
const viewport = useViewport();
|
||||
|
||||
onChange?.(viewport);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function Comp({ onChange, ...rest }: CompProps & ReactFlowProps) {
|
||||
return (
|
||||
<ReactFlow {...rest}>
|
||||
<InnerComp onChange={onChange} />
|
||||
</ReactFlow>
|
||||
);
|
||||
}
|
||||
|
||||
function getLatestViewport(onChangeSpy: any) {
|
||||
return onChangeSpy.lastCall.args[0] as unknown as Viewport;
|
||||
}
|
||||
Reference in New Issue
Block a user