mirror of
https://github.com/The-Low-Code-Foundation/OpenNoodl.git
synced 2026-01-11 14:52:55 +01:00
Co-Authored-By: Eric Tuvesson <eric.tuvesson@gmail.com> Co-Authored-By: mikaeltellhed <2311083+mikaeltellhed@users.noreply.github.com> Co-Authored-By: kotte <14197736+mrtamagotchi@users.noreply.github.com> Co-Authored-By: Anders Larsson <64838990+anders-topp@users.noreply.github.com> Co-Authored-By: Johan <4934465+joolsus@users.noreply.github.com> Co-Authored-By: Tore Knudsen <18231882+torekndsn@users.noreply.github.com> Co-Authored-By: victoratndl <99176179+victoratndl@users.noreply.github.com>
373 lines
9.7 KiB
JavaScript
373 lines
9.7 KiB
JavaScript
const NodeGraphModel = require('@noodl-models/nodegraphmodel').NodeGraphModel;
|
|
const NodeGraphNode = require('@noodl-models/nodegraphmodel').NodeGraphNode;
|
|
const { ComponentModel } = require('@noodl-models/componentmodel');
|
|
const NodeLibrary = require('@noodl-models/nodelibrary').NodeLibrary;
|
|
const { ProjectModel } = require('@noodl-models/projectmodel');
|
|
|
|
describe('Connecting component inputs and outputs', function () {
|
|
var g1, c1;
|
|
var ci, co, n1, n2, co2;
|
|
var p;
|
|
var con1, con2;
|
|
|
|
beforeEach(() => {
|
|
window.NodeLibraryData = require('../nodegraph/nodelibrary');
|
|
NodeLibrary.instance.loadLibrary();
|
|
|
|
g1 = new NodeGraphModel();
|
|
|
|
c1 = new ComponentModel({
|
|
name: 'c1',
|
|
graph: g1
|
|
});
|
|
|
|
ci = NodeGraphNode.fromJSON({
|
|
type: 'Component Inputs',
|
|
id: 'A'
|
|
});
|
|
g1.addRoot(ci);
|
|
|
|
co = NodeGraphNode.fromJSON({
|
|
type: 'Component Outputs',
|
|
id: 'B'
|
|
});
|
|
g1.addRoot(co);
|
|
|
|
co2 = NodeGraphNode.fromJSON({
|
|
type: 'Component Outputs',
|
|
id: 'B2'
|
|
});
|
|
g1.addRoot(co2);
|
|
|
|
n1 = NodeGraphNode.fromJSON({
|
|
type: 'group',
|
|
id: 'C'
|
|
});
|
|
g1.addRoot(n1);
|
|
|
|
n2 = NodeGraphNode.fromJSON({
|
|
type: 'group',
|
|
id: 'D'
|
|
});
|
|
g1.addRoot(n2);
|
|
|
|
p = new ProjectModel({
|
|
name: 'test'
|
|
});
|
|
p.addComponent(c1);
|
|
|
|
NodeLibrary.instance.registerModule(p);
|
|
});
|
|
|
|
afterEach(() => {
|
|
NodeLibrary.instance.unregisterModule(p);
|
|
});
|
|
|
|
function addPorts() {
|
|
c1.graph.findNodeWithId('B').addPort({
|
|
name: 'p1',
|
|
plug: 'input',
|
|
type: '*',
|
|
index: 0
|
|
});
|
|
|
|
c1.graph.findNodeWithId('B').addPort({
|
|
name: 'p2',
|
|
plug: 'input',
|
|
type: '*',
|
|
index: 1
|
|
});
|
|
|
|
c1.graph.findNodeWithId('A').addPort({
|
|
name: 'p3',
|
|
plug: 'output',
|
|
type: '*',
|
|
index: 2
|
|
});
|
|
|
|
c1.graph.findNodeWithId('B2').addPort({
|
|
name: 'p1',
|
|
plug: 'input',
|
|
type: '*',
|
|
index: 0
|
|
});
|
|
}
|
|
|
|
function addConnections() {
|
|
con1 = {
|
|
fromId: n1.id,
|
|
fromProperty: 'width',
|
|
toId: co.id,
|
|
toProperty: 'p1'
|
|
};
|
|
g1.addConnection(con1);
|
|
|
|
con2 = {
|
|
fromId: ci.id,
|
|
fromProperty: 'p3',
|
|
toId: n1.id,
|
|
toProperty: 'x'
|
|
};
|
|
g1.addConnection(con2);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------------
|
|
it('can add input ports to the component', function () {
|
|
addPorts();
|
|
|
|
var ports = c1.getPorts();
|
|
expect(ports.length).toBe(3);
|
|
expect(ports[0].name).toBe('p1');
|
|
expect(ports[0].plug).toBe('output');
|
|
expect(ports[0].type).toBe('*');
|
|
expect(ports[1].name).toBe('p2');
|
|
expect(ports[1].plug).toBe('output');
|
|
expect(ports[1].type).toBe('*');
|
|
expect(ports[2].name).toBe('p3');
|
|
expect(ports[2].plug).toBe('input');
|
|
expect(ports[2].type).toBe('*');
|
|
});
|
|
|
|
// ------------------------------------------------------------------------------------------------------
|
|
it('can list ports correctly for component input/outputs', function () {
|
|
addPorts();
|
|
|
|
var ports = c1.graph.findNodeWithId('B').getPorts('input');
|
|
|
|
expect(ports[0].name).toBe('p1');
|
|
expect(ports[1].name).toBe('p2');
|
|
expect(ports[0].plug).toBe('input');
|
|
expect(ports[1].plug).toBe('input');
|
|
expect(ports[0].type).toBe('*');
|
|
expect(ports[1].type).toBe('*');
|
|
expect(ports.length).toBe(2);
|
|
|
|
var ports = c1.graph.findNodeWithId('A').getPorts('output');
|
|
expect(ports[0].name).toBe('p3');
|
|
expect(ports[0].plug).toBe('output');
|
|
expect(ports[0].type).toBe('*');
|
|
expect(ports.length).toBe(1);
|
|
});
|
|
|
|
// ------------------------------------------------------------------------------------------------------
|
|
it('reports connection status properly', function () {
|
|
addPorts();
|
|
|
|
// component input
|
|
var status = g1.getConnectionStatus({
|
|
sourceNode: ci,
|
|
sourcePort: 'p1',
|
|
targetNode: n1,
|
|
targetPort: 'width'
|
|
});
|
|
expect(status.connectable).toBe(true);
|
|
|
|
// number to number
|
|
var status = g1.getConnectionStatus({
|
|
sourceNode: n1,
|
|
sourcePort: 'screenX',
|
|
targetNode: n2,
|
|
targetPort: 'width'
|
|
});
|
|
expect(status.connectable).toBe(true);
|
|
|
|
// component outputs
|
|
var status = g1.getConnectionStatus({
|
|
sourceNode: n1,
|
|
sourcePort: 'width',
|
|
targetNode: co,
|
|
targetPort: 'p1'
|
|
});
|
|
expect(status.connectable).toBe(true);
|
|
});
|
|
|
|
// ------------------------------------------------------------------------------------------------------
|
|
it('can rename ports', function () {
|
|
addPorts();
|
|
addConnections();
|
|
|
|
expect(c1.graph.findNodeWithId('B').renamePortWithName('p1', 'p2')).toBe(false);
|
|
expect(c1.graph.findNodeWithId('B').renamePortWithName('p1', 'p1b')).toBe(true);
|
|
expect(c1.graph.findNodeWithId('A').renamePortWithName('p3', 'p3b')).toBe(true);
|
|
|
|
expect(con2.fromProperty).toBe('p3b');
|
|
expect(con1.toProperty).toBe('p1b');
|
|
|
|
expect(c1.graph.findNodeWithId('B').renamePortWithName('p1b', 'p1')).toBe(true);
|
|
expect(c1.graph.findNodeWithId('A').renamePortWithName('p3b', 'p3')).toBe(true);
|
|
});
|
|
|
|
// ------------------------------------------------------------------------------------------------------
|
|
it('cannot remove ports with connections', function () {
|
|
addPorts();
|
|
addConnections();
|
|
|
|
expect(c1.graph.findNodeWithId('B').removePortWithName('p1')).toBe(false);
|
|
expect(c1.graph.findNodeWithId('B').removePortWithName('p2')).toBe(true);
|
|
expect(c1.graph.findNodeWithId('A').removePortWithName('p3')).toBe(false);
|
|
|
|
expect(c1.findPortWithName('p2')).toBe(undefined);
|
|
expect(c1.findPortWithName('p1').name).toBe('p1');
|
|
});
|
|
|
|
// ------------------------------------------------------------------------------------------------------
|
|
it('can add more connections are report type correctly', function () {
|
|
addPorts();
|
|
addConnections();
|
|
|
|
g1.removeConnection(con1);
|
|
g1.removeConnection(con2);
|
|
|
|
// Single type, should just be number
|
|
g1.addConnection({
|
|
fromId: n1.id,
|
|
fromProperty: 'screenX',
|
|
toId: co2.id,
|
|
toProperty: 'p1'
|
|
});
|
|
|
|
expect(NodeLibrary.nameForPortType(c1.findPortWithName('p1').type)).toBe('number');
|
|
|
|
// Connect a number and boolean to the components outputs, but on different
|
|
// nodes
|
|
g1.addConnection({
|
|
fromId: n1.id,
|
|
fromProperty: 'clipOut',
|
|
toId: co.id,
|
|
toProperty: 'p1'
|
|
});
|
|
|
|
// Resulting type should be boolean (the only type that can be converted to from both boolean and number)
|
|
expect(NodeLibrary.nameForPortType(c1.findPortWithName('p1').type)).toBe('boolean');
|
|
|
|
// Adding a connection to a star type should not affect the resulting type
|
|
g1.addConnection({
|
|
fromId: ci.id,
|
|
fromProperty: 'p3',
|
|
toId: co2.id,
|
|
toProperty: 'p1'
|
|
});
|
|
|
|
expect(NodeLibrary.nameForPortType(c1.findPortWithName('p1').type)).toBe('boolean');
|
|
|
|
// Adding a reference type connection will cause it to break down, no type can be found
|
|
g1.addConnection({
|
|
fromId: n1.id,
|
|
fromProperty: 'this',
|
|
toId: co2.id,
|
|
toProperty: 'p1'
|
|
});
|
|
|
|
expect(c1.findPortWithName('p1').type).toBe('*');
|
|
});
|
|
|
|
it('can report plug correctly', function () {
|
|
addPorts();
|
|
|
|
expect(c1.findPortWithName('p1').plug).toBe('output');
|
|
expect(c1.findPortWithName('p3').plug).toBe('input');
|
|
|
|
// Adding an extra port of mixed type for p1 should change the plug
|
|
c1.graph.findNodeWithId('A').addPort({
|
|
name: 'p1',
|
|
plug: 'output',
|
|
type: '*'
|
|
});
|
|
|
|
expect(c1.getPorts().length).toBe(4);
|
|
expect(c1.getPorts()).toContain({
|
|
name: 'p1',
|
|
type: '*',
|
|
default: undefined,
|
|
group: undefined,
|
|
plug: 'output',
|
|
index: 0
|
|
});
|
|
expect(c1.getPorts()).toContain({
|
|
name: 'p1',
|
|
type: '*',
|
|
default: undefined,
|
|
group: undefined,
|
|
plug: 'input',
|
|
index: 1
|
|
});
|
|
});
|
|
|
|
it('can ignore * types', function () {
|
|
addPorts();
|
|
addConnections();
|
|
|
|
// Remove all connections
|
|
while (g1.connections.length > 0) {
|
|
g1.removeConnection(g1.connections[0]);
|
|
}
|
|
|
|
// Number type
|
|
g1.addConnection({
|
|
fromId: n1.id,
|
|
fromProperty: 'screenX',
|
|
toId: co.id,
|
|
toProperty: 'p1'
|
|
});
|
|
|
|
expect(c1.findPortWithName('p1').type).toBe('number');
|
|
|
|
// Add a connection to a * type
|
|
g1.addConnection({
|
|
fromId: ci.id,
|
|
fromProperty: 'p3',
|
|
toId: co.id,
|
|
toProperty: 'p1'
|
|
});
|
|
|
|
// Should just ignore * type and still be number
|
|
expect(c1.findPortWithName('p1').type).toBe('number');
|
|
});
|
|
|
|
it('can support units with default in types', function () {
|
|
addPorts();
|
|
addConnections();
|
|
|
|
// Remove all connections
|
|
while (g1.connections.length > 0) {
|
|
g1.removeConnection(g1.connections[0]);
|
|
}
|
|
|
|
// Add a connection to a type with units
|
|
g1.addConnection({
|
|
fromId: ci.id,
|
|
fromProperty: 'p3',
|
|
toId: n1.id,
|
|
toProperty: 'x'
|
|
});
|
|
|
|
// Should just ignore * type and still be number
|
|
expect(c1.findPortWithName('p3').type.name).toBe('number');
|
|
expect(c1.findPortWithName('p3').type.units).toEqual(['px', '%']);
|
|
expect(c1.findPortWithName('p3').default).toEqual({
|
|
value: 10,
|
|
unit: '%'
|
|
});
|
|
|
|
expect(c1.findPortWithName('p3').group).toBe('test'); // Should inherit from connected port
|
|
|
|
//Change parameter value should propagate to default
|
|
n1.setParameter('x', {
|
|
value: 50,
|
|
unit: 'px'
|
|
});
|
|
expect(c1.findPortWithName('p3').default).toEqual({
|
|
value: 50,
|
|
unit: 'px'
|
|
});
|
|
});
|
|
|
|
it('can rearrange ports', function () {
|
|
addPorts();
|
|
addConnections();
|
|
|
|
ci.arrangePort('p3', undefined, 'G1');
|
|
expect(c1.findPortWithName('p3').group).toBe('G1');
|
|
});
|
|
});
|