From 34de31195f40f8c68ea0a8d9843bf5d02d8a47bb Mon Sep 17 00:00:00 2001 From: knsv Date: Thu, 12 Sep 2019 12:58:04 -0700 Subject: [PATCH] #931 Aligning with code standard --- src/diagrams/flowchart/flowDb.js | 482 +-- src/diagrams/flowchart/flowRenderer.js | 676 ++-- .../parser/flow-vertice-chaining.spec.js | 55 +- src/diagrams/flowchart/parser/flow.spec.js | 3187 +++++++++-------- .../flowchart/parser/subgraph.spec.js | 342 +- 5 files changed, 2415 insertions(+), 2327 deletions(-) diff --git a/src/diagrams/flowchart/flowDb.js b/src/diagrams/flowchart/flowDb.js index b9e397eca..8928ad42f 100644 --- a/src/diagrams/flowchart/flowDb.js +++ b/src/diagrams/flowchart/flowDb.js @@ -1,33 +1,33 @@ -import * as d3 from 'd3' -import { sanitizeUrl } from '@braintree/sanitize-url' -import { logger } from '../../logger' -import utils from '../../utils' -import { getConfig } from '../../config' +import * as d3 from 'd3'; +import { sanitizeUrl } from '@braintree/sanitize-url'; +import { logger } from '../../logger'; +import utils from '../../utils'; +import { getConfig } from '../../config'; -const config = getConfig() -let vertices = {} -let edges = [] -let classes = [] -let subGraphs = [] -let subGraphLookup = {} -let tooltips = {} -let subCount = 0 -let direction +const config = getConfig(); +let vertices = {}; +let edges = []; +let classes = []; +let subGraphs = []; +let subGraphLookup = {}; +let tooltips = {}; +let subCount = 0; +let direction; // Functions to be run after graph rendering -let funs = [] +let funs = []; const sanitize = text => { - let txt = text + let txt = text; if (config.securityLevel !== 'loose') { - txt = txt.replace(/
/g, '#br#') - txt = txt.replace(//g, '#br#') - txt = txt.replace(//g, '>') - txt = txt.replace(/=/g, '=') - txt = txt.replace(/#br#/g, '
') + txt = txt.replace(/
/g, '#br#'); + txt = txt.replace(//g, '#br#'); + txt = txt.replace(//g, '>'); + txt = txt.replace(/=/g, '='); + txt = txt.replace(/#br#/g, '
'); } - return txt -} + return txt; +}; /** * Function called by parser when a node definition has been found @@ -37,53 +37,53 @@ const sanitize = text => { * @param style * @param classes */ -export const addVertex = function (_id, text, type, style, classes) { - let txt - let id = _id +export const addVertex = function(_id, text, type, style, classes) { + let txt; + let id = _id; if (typeof id === 'undefined') { - return + return; } if (id.trim().length === 0) { - return + return; } - if (id[0].match(/\d/)) id = 's' + id + if (id[0].match(/\d/)) id = 's' + id; if (typeof vertices[id] === 'undefined') { - vertices[id] = { id: id, styles: [], classes: [] } + vertices[id] = { id: id, styles: [], classes: [] }; } if (typeof text !== 'undefined') { - txt = sanitize(text.trim()) + txt = sanitize(text.trim()); // strip quotes if string starts and exnds with a quote if (txt[0] === '"' && txt[txt.length - 1] === '"') { - txt = txt.substring(1, txt.length - 1) + txt = txt.substring(1, txt.length - 1); } - vertices[id].text = txt + vertices[id].text = txt; } else { if (!vertices[id].text) { - vertices[id].text = _id + vertices[id].text = _id; } } if (typeof type !== 'undefined') { - vertices[id].type = type + vertices[id].type = type; } if (typeof style !== 'undefined') { if (style !== null) { - style.forEach(function (s) { - vertices[id].styles.push(s) - }) + style.forEach(function(s) { + vertices[id].styles.push(s); + }); } } if (typeof classes !== 'undefined') { if (classes !== null) { - classes.forEach(function (s) { - vertices[id].classes.push(s) - }) + classes.forEach(function(s) { + vertices[id].classes.push(s); + }); } } -} +}; /** * Function called by parser when a link/edge definition has been found @@ -92,134 +92,138 @@ export const addVertex = function (_id, text, type, style, classes) { * @param type * @param linktext */ -export const addLink = function (_start, _end, type, linktext) { - let start = _start - let end = _end - if (start[0].match(/\d/)) start = 's' + start - if (end[0].match(/\d/)) end = 's' + end - logger.info('Got edge...', start, end) +export const addLink = function(_start, _end, type, linktext) { + let start = _start; + let end = _end; + if (start[0].match(/\d/)) start = 's' + start; + if (end[0].match(/\d/)) end = 's' + end; + logger.info('Got edge...', start, end); - const edge = { start: start, end: end, type: undefined, text: '' } - linktext = type.text + const edge = { start: start, end: end, type: undefined, text: '' }; + linktext = type.text; if (typeof linktext !== 'undefined') { - edge.text = sanitize(linktext.trim()) + edge.text = sanitize(linktext.trim()); // strip quotes if string starts and exnds with a quote if (edge.text[0] === '"' && edge.text[edge.text.length - 1] === '"') { - edge.text = edge.text.substring(1, edge.text.length - 1) + edge.text = edge.text.substring(1, edge.text.length - 1); } } if (typeof type !== 'undefined') { - edge.type = type.type - edge.stroke = type.stroke + edge.type = type.type; + edge.stroke = type.stroke; } - edges.push(edge) -} + edges.push(edge); +}; /** * Updates a link's line interpolation algorithm * @param pos * @param interpolate */ -export const updateLinkInterpolate = function (positions, interp) { - positions.forEach(function (pos) { +export const updateLinkInterpolate = function(positions, interp) { + positions.forEach(function(pos) { if (pos === 'default') { - edges.defaultInterpolate = interp + edges.defaultInterpolate = interp; } else { - edges[pos].interpolate = interp + edges[pos].interpolate = interp; } - }) -} + }); +}; /** * Updates a link with a style * @param pos * @param style */ -export const updateLink = function (positions, style) { - positions.forEach(function (pos) { +export const updateLink = function(positions, style) { + positions.forEach(function(pos) { if (pos === 'default') { - edges.defaultStyle = style + edges.defaultStyle = style; } else { if (utils.isSubstringInArray('fill', style) === -1) { - style.push('fill:none') + style.push('fill:none'); } - edges[pos].style = style + edges[pos].style = style; } - }) -} + }); +}; -export const addClass = function (id, style) { +export const addClass = function(id, style) { if (typeof classes[id] === 'undefined') { - classes[id] = { id: id, styles: [] } + classes[id] = { id: id, styles: [] }; } if (typeof style !== 'undefined') { if (style !== null) { - style.forEach(function (s) { - classes[id].styles.push(s) - }) + style.forEach(function(s) { + classes[id].styles.push(s); + }); } } -} +}; /** * Called by parser when a graph definition is found, stores the direction of the chart. * @param dir */ -export const setDirection = function (dir) { - direction = dir -} +export const setDirection = function(dir) { + direction = dir; +}; /** * Called by parser when a special node is found, e.g. a clickable element. * @param ids Comma separated list of ids * @param className Class to add */ -export const setClass = function (ids, className) { - ids.split(',').forEach(function (_id) { - let id = _id - if (_id[0].match(/\d/)) id = 's' + id +export const setClass = function(ids, className) { + ids.split(',').forEach(function(_id) { + let id = _id; + if (_id[0].match(/\d/)) id = 's' + id; if (typeof vertices[id] !== 'undefined') { - vertices[id].classes.push(className) + vertices[id].classes.push(className); } if (typeof subGraphLookup[id] !== 'undefined') { - subGraphLookup[id].classes.push(className) + subGraphLookup[id].classes.push(className); } - }) -} + }); +}; -const setTooltip = function (ids, tooltip) { - ids.split(',').forEach(function (id) { +const setTooltip = function(ids, tooltip) { + ids.split(',').forEach(function(id) { if (typeof tooltip !== 'undefined') { - tooltips[id] = sanitize(tooltip) + tooltips[id] = sanitize(tooltip); } - }) -} + }); +}; -const setClickFun = function (_id, functionName) { - let id = _id - if (_id[0].match(/\d/)) id = 's' + id +const setClickFun = function(_id, functionName) { + let id = _id; + if (_id[0].match(/\d/)) id = 's' + id; if (config.securityLevel !== 'loose') { - return + return; } if (typeof functionName === 'undefined') { - return + return; } if (typeof vertices[id] !== 'undefined') { - funs.push(function (element) { - const elem = document.querySelector(`[id="${id}"]`) + funs.push(function(element) { + const elem = document.querySelector(`[id="${id}"]`); if (elem !== null) { - elem.addEventListener('click', function () { - window[functionName](id) - }, false) + elem.addEventListener( + 'click', + function() { + window[functionName](id); + }, + false + ); } - }) + }); } -} +}; /** * Called by parser when a link is found. Adds the URL to the vertex data. @@ -227,24 +231,24 @@ const setClickFun = function (_id, functionName) { * @param linkStr URL to create a link for * @param tooltip Tooltip for the clickable element */ -export const setLink = function (ids, linkStr, tooltip) { - ids.split(',').forEach(function (_id) { - let id = _id - if (_id[0].match(/\d/)) id = 's' + id +export const setLink = function(ids, linkStr, tooltip) { + ids.split(',').forEach(function(_id) { + let id = _id; + if (_id[0].match(/\d/)) id = 's' + id; if (typeof vertices[id] !== 'undefined') { if (config.securityLevel !== 'loose') { - vertices[id].link = sanitizeUrl(linkStr) // .replace(/javascript:.*/g, '') + vertices[id].link = sanitizeUrl(linkStr); // .replace(/javascript:.*/g, '') } else { - vertices[id].link = linkStr + vertices[id].link = linkStr; } } - }) - setTooltip(ids, tooltip) - setClass(ids, 'clickable') -} -export const getTooltip = function (id) { - return tooltips[id] -} + }); + setTooltip(ids, tooltip); + setClass(ids, 'clickable'); +}; +export const getTooltip = function(id) { + return tooltips[id]; +}; /** * Called by parser when a click definition is found. Registers an event handler. @@ -252,209 +256,219 @@ export const getTooltip = function (id) { * @param functionName Function to be called on click * @param tooltip Tooltip for the clickable element */ -export const setClickEvent = function (ids, functionName, tooltip) { - ids.split(',').forEach(function (id) { setClickFun(id, functionName) }) - setTooltip(ids, tooltip) - setClass(ids, 'clickable') -} +export const setClickEvent = function(ids, functionName, tooltip) { + ids.split(',').forEach(function(id) { + setClickFun(id, functionName); + }); + setTooltip(ids, tooltip); + setClass(ids, 'clickable'); +}; -export const bindFunctions = function (element) { - funs.forEach(function (fun) { - fun(element) - }) -} -export const getDirection = function () { - return direction -} +export const bindFunctions = function(element) { + funs.forEach(function(fun) { + fun(element); + }); +}; +export const getDirection = function() { + return direction; +}; /** * Retrieval function for fetching the found nodes after parsing has completed. * @returns {{}|*|vertices} */ -export const getVertices = function () { - return vertices -} +export const getVertices = function() { + return vertices; +}; /** * Retrieval function for fetching the found links after parsing has completed. * @returns {{}|*|edges} */ -export const getEdges = function () { - return edges -} +export const getEdges = function() { + return edges; +}; /** * Retrieval function for fetching the found class definitions after parsing has completed. * @returns {{}|*|classes} */ -export const getClasses = function () { - return classes -} +export const getClasses = function() { + return classes; +}; -const setupToolTips = function (element) { - let tooltipElem = d3.select('.mermaidTooltip') +const setupToolTips = function(element) { + let tooltipElem = d3.select('.mermaidTooltip'); if ((tooltipElem._groups || tooltipElem)[0][0] === null) { - tooltipElem = d3.select('body') + tooltipElem = d3 + .select('body') .append('div') .attr('class', 'mermaidTooltip') - .style('opacity', 0) + .style('opacity', 0); } - const svg = d3.select(element).select('svg') + const svg = d3.select(element).select('svg'); - const nodes = svg.selectAll('g.node') + const nodes = svg.selectAll('g.node'); nodes - .on('mouseover', function () { - const el = d3.select(this) - const title = el.attr('title') + .on('mouseover', function() { + const el = d3.select(this); + const title = el.attr('title'); // Dont try to draw a tooltip if no data is provided if (title === null) { - return + return; } - const rect = this.getBoundingClientRect() + const rect = this.getBoundingClientRect(); - tooltipElem.transition() + tooltipElem + .transition() .duration(200) - .style('opacity', '.9') - tooltipElem.html(el.attr('title')) - .style('left', (rect.left + (rect.right - rect.left) / 2) + 'px') - .style('top', (rect.top - 14 + document.body.scrollTop) + 'px') - el.classed('hover', true) + .style('opacity', '.9'); + tooltipElem + .html(el.attr('title')) + .style('left', rect.left + (rect.right - rect.left) / 2 + 'px') + .style('top', rect.top - 14 + document.body.scrollTop + 'px'); + el.classed('hover', true); }) - .on('mouseout', function () { - tooltipElem.transition() + .on('mouseout', function() { + tooltipElem + .transition() .duration(500) - .style('opacity', 0) - const el = d3.select(this) - el.classed('hover', false) - }) -} -funs.push(setupToolTips) + .style('opacity', 0); + const el = d3.select(this); + el.classed('hover', false); + }); +}; +funs.push(setupToolTips); /** * Clears the internal graph db so that a new graph can be parsed. */ -export const clear = function () { - vertices = {} - classes = {} - edges = [] - funs = [] - funs.push(setupToolTips) - subGraphs = [] - subGraphLookup = {} - subCount = 0 - tooltips = [] -} +export const clear = function() { + vertices = {}; + classes = {}; + edges = []; + funs = []; + funs.push(setupToolTips); + subGraphs = []; + subGraphLookup = {}; + subCount = 0; + tooltips = []; +}; /** * * @returns {string} */ -export const defaultStyle = function () { - return 'fill:#ffa;stroke: #f66; stroke-width: 3px; stroke-dasharray: 5, 5;fill:#ffa;stroke: #666;' -} +export const defaultStyle = function() { + return 'fill:#ffa;stroke: #f66; stroke-width: 3px; stroke-dasharray: 5, 5;fill:#ffa;stroke: #666;'; +}; /** * Clears the internal graph db so that a new graph can be parsed. */ -export const addSubGraph = function (_id, list, _title) { - let id = _id - let title = _title +export const addSubGraph = function(_id, list, _title) { + let id = _id; + let title = _title; if (_id === _title && _title.match(/\s/)) { - id = undefined + id = undefined; } - function uniq (a) { - const prims = { 'boolean': {}, 'number': {}, 'string': {} } - const objs = [] + function uniq(a) { + const prims = { boolean: {}, number: {}, string: {} }; + const objs = []; - return a.filter(function (item) { - const type = typeof item + return a.filter(function(item) { + const type = typeof item; if (item.trim() === '') { - return false + return false; } - if (type in prims) { return prims[type].hasOwnProperty(item) ? false : (prims[type][item] = true) } else { return objs.indexOf(item) >= 0 ? false : objs.push(item) } - }) + if (type in prims) { + return prims[type].hasOwnProperty(item) ? false : (prims[type][item] = true); + } else { + return objs.indexOf(item) >= 0 ? false : objs.push(item); + } + }); } - let nodeList = [] + let nodeList = []; - nodeList = uniq(nodeList.concat.apply(nodeList, list)) + nodeList = uniq(nodeList.concat.apply(nodeList, list)); for (let i = 0; i < nodeList.length; i++) { - if (nodeList[i][0].match(/\d/)) nodeList[i] = 's' + nodeList[i] + if (nodeList[i][0].match(/\d/)) nodeList[i] = 's' + nodeList[i]; } - id = id || ('subGraph' + subCount) - if (id[0].match(/\d/)) id = 's' + id - title = title || '' - title = sanitize(title) - subCount = subCount + 1 - const subGraph = { id: id, nodes: nodeList, title: title.trim(), classes: [] } - subGraphs.push(subGraph) - subGraphLookup[id] = subGraph - return id -} + id = id || 'subGraph' + subCount; + if (id[0].match(/\d/)) id = 's' + id; + title = title || ''; + title = sanitize(title); + subCount = subCount + 1; + const subGraph = { id: id, nodes: nodeList, title: title.trim(), classes: [] }; + subGraphs.push(subGraph); + subGraphLookup[id] = subGraph; + return id; +}; -const getPosForId = function (id) { +const getPosForId = function(id) { for (let i = 0; i < subGraphs.length; i++) { if (subGraphs[i].id === id) { - return i + return i; } } - return -1 -} -let secCount = -1 -const posCrossRef = [] -const indexNodes2 = function (id, pos) { - const nodes = subGraphs[pos].nodes - secCount = secCount + 1 + return -1; +}; +let secCount = -1; +const posCrossRef = []; +const indexNodes2 = function(id, pos) { + const nodes = subGraphs[pos].nodes; + secCount = secCount + 1; if (secCount > 2000) { - return + return; } - posCrossRef[secCount] = pos + posCrossRef[secCount] = pos; // Check if match if (subGraphs[pos].id === id) { return { result: true, count: 0 - } + }; } - let count = 0 - let posCount = 1 + let count = 0; + let posCount = 1; while (count < nodes.length) { - const childPos = getPosForId(nodes[count]) + const childPos = getPosForId(nodes[count]); // Ignore regular nodes (pos will be -1) if (childPos >= 0) { - const res = indexNodes2(id, childPos) + const res = indexNodes2(id, childPos); if (res.result) { return { result: true, count: posCount + res.count - } + }; } else { - posCount = posCount + res.count + posCount = posCount + res.count; } } - count = count + 1 + count = count + 1; } return { result: false, count: posCount - } -} + }; +}; -export const getDepthFirstPos = function (pos) { - return posCrossRef[pos] -} -export const indexNodes = function () { - secCount = -1 +export const getDepthFirstPos = function(pos) { + return posCrossRef[pos]; +}; +export const indexNodes = function() { + secCount = -1; if (subGraphs.length > 0) { - indexNodes2('none', subGraphs.length - 1, 0) + indexNodes2('none', subGraphs.length - 1, 0); } -} +}; -export const getSubGraphs = function () { - return subGraphs -} +export const getSubGraphs = function() { + return subGraphs; +}; export default { addVertex, @@ -478,4 +492,4 @@ export default { getDepthFirstPos, indexNodes, getSubGraphs -} +}; diff --git a/src/diagrams/flowchart/flowRenderer.js b/src/diagrams/flowchart/flowRenderer.js index 3df7a6ad9..ef696a8f7 100644 --- a/src/diagrams/flowchart/flowRenderer.js +++ b/src/diagrams/flowchart/flowRenderer.js @@ -1,274 +1,288 @@ -import graphlib from 'graphlibrary' -import * as d3 from 'd3' +import graphlib from 'graphlibrary'; +import * as d3 from 'd3'; -import flowDb from './flowDb' -import flow from './parser/flow' -import { getConfig } from '../../config' -import dagreD3 from 'dagre-d3-renderer' -import addHtmlLabel from 'dagre-d3-renderer/lib/label/add-html-label.js' -import { logger } from '../../logger' -import { interpolateToCurve } from '../../utils' +import flowDb from './flowDb'; +import flow from './parser/flow'; +import { getConfig } from '../../config'; +import dagreD3 from 'dagre-d3-renderer'; +import addHtmlLabel from 'dagre-d3-renderer/lib/label/add-html-label.js'; +import { logger } from '../../logger'; +import { interpolateToCurve } from '../../utils'; -const conf = { -} -export const setConf = function (cnf) { - const keys = Object.keys(cnf) +const conf = {}; +export const setConf = function(cnf) { + const keys = Object.keys(cnf); for (let i = 0; i < keys.length; i++) { - conf[keys[i]] = cnf[keys[i]] + conf[keys[i]] = cnf[keys[i]]; } -} +}; /** * Function that adds the vertices found in the graph definition to the graph to be rendered. * @param vert Object containing the vertices. * @param g The graph that is to be drawn. */ -export const addVertices = function (vert, g, svgId) { - const svg = d3.select(`[id="${svgId}"]`) - const keys = Object.keys(vert) +export const addVertices = function(vert, g, svgId) { + const svg = d3.select(`[id="${svgId}"]`); + const keys = Object.keys(vert); - const styleFromStyleArr = function (styleStr, arr, { label }) { + const styleFromStyleArr = function(styleStr, arr, { label }) { if (!label) { - // Create a compound style definition from the style definitions found for the node in the graph definition + // Create a compound style definition from the style definitions found for the node in the graph definition for (let i = 0; i < arr.length; i++) { if (typeof arr[i] !== 'undefined') { - styleStr = styleStr + arr[i] + ';' + styleStr = styleStr + arr[i] + ';'; } } } else { for (let i = 0; i < arr.length; i++) { if (typeof arr[i] !== 'undefined') { - if (arr[i].match('^color:')) styleStr = styleStr + arr[i] + ';' + if (arr[i].match('^color:')) styleStr = styleStr + arr[i] + ';'; } } } - return styleStr - } + return styleStr; + }; // Iterate through each item in the vertex object (containing all the vertices found) in the graph definition - keys.forEach(function (id) { - const vertex = vert[id] + keys.forEach(function(id) { + const vertex = vert[id]; /** * Variable for storing the classes for the vertex * @type {string} */ - let classStr = '' + let classStr = ''; if (vertex.classes.length > 0) { - classStr = vertex.classes.join(' ') + classStr = vertex.classes.join(' '); } /** * Variable for storing the extracted style for the vertex * @type {string} */ - let style = '' + let style = ''; // Create a compound style definition from the style definitions found for the node in the graph definition - style = styleFromStyleArr(style, vertex.styles, { label: false }) - let labelStyle = '' - labelStyle = styleFromStyleArr(labelStyle, vertex.styles, { label: true }) + style = styleFromStyleArr(style, vertex.styles, { label: false }); + let labelStyle = ''; + labelStyle = styleFromStyleArr(labelStyle, vertex.styles, { label: true }); // Use vertex id as text in the box if no text is provided by the graph definition - let vertexText = vertex.text !== undefined ? vertex.text : vertex.id + let vertexText = vertex.text !== undefined ? vertex.text : vertex.id; // We create a SVG label, either by delegating to addHtmlLabel or manually - let vertexNode + let vertexNode; if (getConfig().flowchart.htmlLabels) { // TODO: addHtmlLabel accepts a labelStyle. Do we possibly have that? - const node = { label: vertexText.replace(/fa[lrsb]?:fa-[\w-]+/g, s => ``) } - vertexNode = addHtmlLabel(svg, node).node() - vertexNode.parentNode.removeChild(vertexNode) + const node = { + label: vertexText.replace( + /fa[lrsb]?:fa-[\w-]+/g, + s => `` + ) + }; + vertexNode = addHtmlLabel(svg, node).node(); + vertexNode.parentNode.removeChild(vertexNode); } else { - const svgLabel = document.createElementNS('http://www.w3.org/2000/svg', 'text') + const svgLabel = document.createElementNS('http://www.w3.org/2000/svg', 'text'); - const rows = vertexText.split(//) + const rows = vertexText.split(//); for (let j = 0; j < rows.length; j++) { - const tspan = document.createElementNS('http://www.w3.org/2000/svg', 'tspan') - tspan.setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:space', 'preserve') - tspan.setAttribute('dy', '1em') - tspan.setAttribute('x', '1') - tspan.textContent = rows[j] - svgLabel.appendChild(tspan) + const tspan = document.createElementNS('http://www.w3.org/2000/svg', 'tspan'); + tspan.setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:space', 'preserve'); + tspan.setAttribute('dy', '1em'); + tspan.setAttribute('x', '1'); + tspan.textContent = rows[j]; + svgLabel.appendChild(tspan); } - vertexNode = svgLabel + vertexNode = svgLabel; } // If the node has a link, we wrap it in a SVG link if (vertex.link) { - const link = document.createElementNS('http://www.w3.org/2000/svg', 'a') - link.setAttributeNS('http://www.w3.org/2000/svg', 'href', vertex.link) - link.setAttributeNS('http://www.w3.org/2000/svg', 'rel', 'noopener') - link.appendChild(vertexNode) - vertexNode = link + const link = document.createElementNS('http://www.w3.org/2000/svg', 'a'); + link.setAttributeNS('http://www.w3.org/2000/svg', 'href', vertex.link); + link.setAttributeNS('http://www.w3.org/2000/svg', 'rel', 'noopener'); + link.appendChild(vertexNode); + vertexNode = link; } - let radious = 0 - let _shape = '' + let radious = 0; + let _shape = ''; // Set the shape based parameters switch (vertex.type) { case 'round': - radious = 5 - _shape = 'rect' - break + radious = 5; + _shape = 'rect'; + break; case 'square': - _shape = 'rect' - break + _shape = 'rect'; + break; case 'diamond': - _shape = 'question' - break + _shape = 'question'; + break; case 'odd': - _shape = 'rect_left_inv_arrow' - break + _shape = 'rect_left_inv_arrow'; + break; case 'lean_right': - _shape = 'lean_right' - break + _shape = 'lean_right'; + break; case 'lean_left': - _shape = 'lean_left' - break + _shape = 'lean_left'; + break; case 'trapezoid': - _shape = 'trapezoid' - break + _shape = 'trapezoid'; + break; case 'inv_trapezoid': - _shape = 'inv_trapezoid' - break + _shape = 'inv_trapezoid'; + break; case 'odd_right': - _shape = 'rect_left_inv_arrow' - break + _shape = 'rect_left_inv_arrow'; + break; case 'circle': - _shape = 'circle' - break + _shape = 'circle'; + break; case 'ellipse': - _shape = 'ellipse' - break + _shape = 'ellipse'; + break; case 'group': - _shape = 'rect' - break + _shape = 'rect'; + break; default: - _shape = 'rect' + _shape = 'rect'; } // Add the node - g.setNode(vertex.id, { labelType: 'svg', labelStyle: labelStyle, shape: _shape, label: vertexNode, rx: radious, ry: radious, 'class': classStr, style: style, id: vertex.id }) - }) -} + g.setNode(vertex.id, { + labelType: 'svg', + labelStyle: labelStyle, + shape: _shape, + label: vertexNode, + rx: radious, + ry: radious, + class: classStr, + style: style, + id: vertex.id + }); + }); +}; /** * Add edges to graph based on parsed graph defninition * @param {Object} edges The edges to add to the graph * @param {Object} g The graph object */ -export const addEdges = function (edges, g) { - let cnt = 0 +export const addEdges = function(edges, g) { + let cnt = 0; - let defaultStyle + let defaultStyle; if (typeof edges.defaultStyle !== 'undefined') { - defaultStyle = edges.defaultStyle.toString().replace(/,/g, ';') + defaultStyle = edges.defaultStyle.toString().replace(/,/g, ';'); } - edges.forEach(function (edge) { - cnt++ - const edgeData = {} + edges.forEach(function(edge) { + cnt++; + const edgeData = {}; // Set link type for rendering if (edge.type === 'arrow_open') { - edgeData.arrowhead = 'none' + edgeData.arrowhead = 'none'; } else { - edgeData.arrowhead = 'normal' + edgeData.arrowhead = 'normal'; } - let style = '' + let style = ''; if (typeof edge.style !== 'undefined') { - edge.style.forEach(function (s) { - style = style + s + ';' - }) + edge.style.forEach(function(s) { + style = style + s + ';'; + }); } else { switch (edge.stroke) { case 'normal': - style = 'fill:none' + style = 'fill:none'; if (typeof defaultStyle !== 'undefined') { - style = defaultStyle + style = defaultStyle; } - break + break; case 'dotted': - style = 'stroke: #333; fill:none;stroke-width:2px;stroke-dasharray:3;' - break + style = 'stroke: #333; fill:none;stroke-width:2px;stroke-dasharray:3;'; + break; case 'thick': - style = 'stroke: #333; stroke-width: 3.5px;fill:none' - break + style = 'stroke: #333; stroke-width: 3.5px;fill:none'; + break; } } - edgeData.style = style + edgeData.style = style; if (typeof edge.interpolate !== 'undefined') { - edgeData.curve = interpolateToCurve(edge.interpolate, d3.curveLinear) + edgeData.curve = interpolateToCurve(edge.interpolate, d3.curveLinear); } else if (typeof edges.defaultInterpolate !== 'undefined') { - edgeData.curve = interpolateToCurve(edges.defaultInterpolate, d3.curveLinear) + edgeData.curve = interpolateToCurve(edges.defaultInterpolate, d3.curveLinear); } else { - edgeData.curve = interpolateToCurve(conf.curve, d3.curveLinear) + edgeData.curve = interpolateToCurve(conf.curve, d3.curveLinear); } if (typeof edge.text === 'undefined') { if (typeof edge.style !== 'undefined') { - edgeData.arrowheadStyle = 'fill: #333' + edgeData.arrowheadStyle = 'fill: #333'; } } else { - edgeData.arrowheadStyle = 'fill: #333' + edgeData.arrowheadStyle = 'fill: #333'; if (typeof edge.style === 'undefined') { - edgeData.labelpos = 'c' + edgeData.labelpos = 'c'; if (getConfig().flowchart.htmlLabels) { - edgeData.labelType = 'html' - edgeData.label = '' + edge.text + '' + edgeData.labelType = 'html'; + edgeData.label = '' + edge.text + ''; } else { - edgeData.labelType = 'text' - edgeData.style = edgeData.style || 'stroke: #333; stroke-width: 1.5px;fill:none' - edgeData.label = edge.text.replace(/
/g, '\n') + edgeData.labelType = 'text'; + edgeData.style = edgeData.style || 'stroke: #333; stroke-width: 1.5px;fill:none'; + edgeData.label = edge.text.replace(/
/g, '\n'); } } else { - edgeData.label = edge.text.replace(/
/g, '\n') + edgeData.label = edge.text.replace(/
/g, '\n'); } } // Add the edge to the graph - g.setEdge(edge.start, edge.end, edgeData, cnt) - }) -} + g.setEdge(edge.start, edge.end, edgeData, cnt); + }); +}; /** * Returns the all the styles from classDef statements in the graph definition. * @returns {object} classDef styles */ -export const getClasses = function (text) { - logger.info('Extracting classes') - flowDb.clear() - const parser = flow.parser - parser.yy = flowDb +export const getClasses = function(text) { + logger.info('Extracting classes'); + flowDb.clear(); + const parser = flow.parser; + parser.yy = flowDb; // Parse the graph definition - parser.parse(text) - return flowDb.getClasses() -} + parser.parse(text); + return flowDb.getClasses(); +}; /** * Draws a flowchart in the tag with id: id based on the graph definition in text. * @param text * @param id */ -export const draw = function (text, id) { - logger.info('Drawing flowchart') - flowDb.clear() - const parser = flow.parser - parser.yy = flowDb +export const draw = function(text, id) { + logger.info('Drawing flowchart'); + flowDb.clear(); + const parser = flow.parser; + parser.yy = flowDb; // Parse the graph definition try { - parser.parse(text) + parser.parse(text); } catch (err) { - logger.debug('Parsing failed') + logger.debug('Parsing failed'); } // Fetch the default direction, use TD if none was found - let dir = flowDb.getDirection() + let dir = flowDb.getDirection(); if (typeof dir === 'undefined') { - dir = 'TD' + dir = 'TD'; } // Create the input mermaid.graph @@ -280,196 +294,238 @@ export const draw = function (text, id) { rankdir: dir, marginx: 20, marginy: 20 - - }) - .setDefaultEdgeLabel(function () { - return {} }) + .setDefaultEdgeLabel(function() { + return {}; + }); - let subG - const subGraphs = flowDb.getSubGraphs() + let subG; + const subGraphs = flowDb.getSubGraphs(); for (let i = subGraphs.length - 1; i >= 0; i--) { - subG = subGraphs[i] - flowDb.addVertex(subG.id, subG.title, 'group', undefined, subG.classes) + subG = subGraphs[i]; + flowDb.addVertex(subG.id, subG.title, 'group', undefined, subG.classes); } // Fetch the verices/nodes and edges/links from the parsed graph definition - const vert = flowDb.getVertices() + const vert = flowDb.getVertices(); - const edges = flowDb.getEdges() + const edges = flowDb.getEdges(); - let i = 0 + let i = 0; for (i = subGraphs.length - 1; i >= 0; i--) { - subG = subGraphs[i] + subG = subGraphs[i]; - d3.selectAll('cluster').append('text') + d3.selectAll('cluster').append('text'); for (let j = 0; j < subG.nodes.length; j++) { - g.setParent(subG.nodes[j], subG.id) + g.setParent(subG.nodes[j], subG.id); } } - addVertices(vert, g, id) - addEdges(edges, g) + addVertices(vert, g, id); + addEdges(edges, g); // Create the renderer - const Render = dagreD3.render - const render = new Render() + const Render = dagreD3.render; + const render = new Render(); // Add custom shape for rhombus type of boc (decision) - render.shapes().question = function (parent, bbox, node) { - const w = bbox.width - const h = bbox.height - const s = (w + h) * 0.9 + render.shapes().question = function(parent, bbox, node) { + const w = bbox.width; + const h = bbox.height; + const s = (w + h) * 0.9; const points = [ { x: s / 2, y: 0 }, { x: s, y: -s / 2 }, { x: s / 2, y: -s }, { x: 0, y: -s / 2 } - ] - const shapeSvg = parent.insert('polygon', ':first-child') - .attr('points', points.map(function (d) { - return d.x + ',' + d.y - }).join(' ')) + ]; + const shapeSvg = parent + .insert('polygon', ':first-child') + .attr( + 'points', + points + .map(function(d) { + return d.x + ',' + d.y; + }) + .join(' ') + ) .attr('rx', 5) .attr('ry', 5) - .attr('transform', 'translate(' + (-s / 2) + ',' + (s * 2 / 4) + ')') - node.intersect = function (point) { - return dagreD3.intersect.polygon(node, points, point) - } - return shapeSvg - } + .attr('transform', 'translate(' + -s / 2 + ',' + (s * 2) / 4 + ')'); + node.intersect = function(point) { + return dagreD3.intersect.polygon(node, points, point); + }; + return shapeSvg; + }; // Add custom shape for box with inverted arrow on left side - render.shapes().rect_left_inv_arrow = function (parent, bbox, node) { - const w = bbox.width - const h = bbox.height + render.shapes().rect_left_inv_arrow = function(parent, bbox, node) { + const w = bbox.width; + const h = bbox.height; const points = [ { x: -h / 2, y: 0 }, { x: w, y: 0 }, { x: w, y: -h }, { x: -h / 2, y: -h }, { x: 0, y: -h / 2 } - ] - const shapeSvg = parent.insert('polygon', ':first-child') - .attr('points', points.map(function (d) { - return d.x + ',' + d.y - }).join(' ')) - .attr('transform', 'translate(' + (-w / 2) + ',' + (h * 2 / 4) + ')') - node.intersect = function (point) { - return dagreD3.intersect.polygon(node, points, point) - } - return shapeSvg - } + ]; + const shapeSvg = parent + .insert('polygon', ':first-child') + .attr( + 'points', + points + .map(function(d) { + return d.x + ',' + d.y; + }) + .join(' ') + ) + .attr('transform', 'translate(' + -w / 2 + ',' + (h * 2) / 4 + ')'); + node.intersect = function(point) { + return dagreD3.intersect.polygon(node, points, point); + }; + return shapeSvg; + }; // Add custom shape for box with inverted arrow on left side - render.shapes().lean_right = function (parent, bbox, node) { - const w = bbox.width - const h = bbox.height + render.shapes().lean_right = function(parent, bbox, node) { + const w = bbox.width; + const h = bbox.height; const points = [ - { x: -2 * h / 6, y: 0 }, + { x: (-2 * h) / 6, y: 0 }, { x: w - h / 6, y: 0 }, - { x: w + 2 * h / 6, y: -h }, + { x: w + (2 * h) / 6, y: -h }, { x: h / 6, y: -h } - ] - const shapeSvg = parent.insert('polygon', ':first-child') - .attr('points', points.map(function (d) { - return d.x + ',' + d.y - }).join(' ')) - .attr('transform', 'translate(' + (-w / 2) + ',' + (h * 2 / 4) + ')') - node.intersect = function (point) { - return dagreD3.intersect.polygon(node, points, point) - } - return shapeSvg - } + ]; + const shapeSvg = parent + .insert('polygon', ':first-child') + .attr( + 'points', + points + .map(function(d) { + return d.x + ',' + d.y; + }) + .join(' ') + ) + .attr('transform', 'translate(' + -w / 2 + ',' + (h * 2) / 4 + ')'); + node.intersect = function(point) { + return dagreD3.intersect.polygon(node, points, point); + }; + return shapeSvg; + }; // Add custom shape for box with inverted arrow on left side - render.shapes().lean_left = function (parent, bbox, node) { - const w = bbox.width - const h = bbox.height + render.shapes().lean_left = function(parent, bbox, node) { + const w = bbox.width; + const h = bbox.height; const points = [ - { x: 2 * h / 6, y: 0 }, + { x: (2 * h) / 6, y: 0 }, { x: w + h / 6, y: 0 }, - { x: w - 2 * h / 6, y: -h }, + { x: w - (2 * h) / 6, y: -h }, { x: -h / 6, y: -h } - ] - const shapeSvg = parent.insert('polygon', ':first-child') - .attr('points', points.map(function (d) { - return d.x + ',' + d.y - }).join(' ')) - .attr('transform', 'translate(' + (-w / 2) + ',' + (h * 2 / 4) + ')') - node.intersect = function (point) { - return dagreD3.intersect.polygon(node, points, point) - } - return shapeSvg - } + ]; + const shapeSvg = parent + .insert('polygon', ':first-child') + .attr( + 'points', + points + .map(function(d) { + return d.x + ',' + d.y; + }) + .join(' ') + ) + .attr('transform', 'translate(' + -w / 2 + ',' + (h * 2) / 4 + ')'); + node.intersect = function(point) { + return dagreD3.intersect.polygon(node, points, point); + }; + return shapeSvg; + }; // Add custom shape for box with inverted arrow on left side - render.shapes().trapezoid = function (parent, bbox, node) { - const w = bbox.width - const h = bbox.height + render.shapes().trapezoid = function(parent, bbox, node) { + const w = bbox.width; + const h = bbox.height; const points = [ - { x: -2 * h / 6, y: 0 }, - { x: w + 2 * h / 6, y: 0 }, + { x: (-2 * h) / 6, y: 0 }, + { x: w + (2 * h) / 6, y: 0 }, { x: w - h / 6, y: -h }, { x: h / 6, y: -h } - ] - const shapeSvg = parent.insert('polygon', ':first-child') - .attr('points', points.map(function (d) { - return d.x + ',' + d.y - }).join(' ')) - .attr('transform', 'translate(' + (-w / 2) + ',' + (h * 2 / 4) + ')') - node.intersect = function (point) { - return dagreD3.intersect.polygon(node, points, point) - } - return shapeSvg - } + ]; + const shapeSvg = parent + .insert('polygon', ':first-child') + .attr( + 'points', + points + .map(function(d) { + return d.x + ',' + d.y; + }) + .join(' ') + ) + .attr('transform', 'translate(' + -w / 2 + ',' + (h * 2) / 4 + ')'); + node.intersect = function(point) { + return dagreD3.intersect.polygon(node, points, point); + }; + return shapeSvg; + }; // Add custom shape for box with inverted arrow on left side - render.shapes().inv_trapezoid = function (parent, bbox, node) { - const w = bbox.width - const h = bbox.height + render.shapes().inv_trapezoid = function(parent, bbox, node) { + const w = bbox.width; + const h = bbox.height; const points = [ { x: h / 6, y: 0 }, { x: w - h / 6, y: 0 }, - { x: w + 2 * h / 6, y: -h }, - { x: -2 * h / 6, y: -h } - ] - const shapeSvg = parent.insert('polygon', ':first-child') - .attr('points', points.map(function (d) { - return d.x + ',' + d.y - }).join(' ')) - .attr('transform', 'translate(' + (-w / 2) + ',' + (h * 2 / 4) + ')') - node.intersect = function (point) { - return dagreD3.intersect.polygon(node, points, point) - } - return shapeSvg - } + { x: w + (2 * h) / 6, y: -h }, + { x: (-2 * h) / 6, y: -h } + ]; + const shapeSvg = parent + .insert('polygon', ':first-child') + .attr( + 'points', + points + .map(function(d) { + return d.x + ',' + d.y; + }) + .join(' ') + ) + .attr('transform', 'translate(' + -w / 2 + ',' + (h * 2) / 4 + ')'); + node.intersect = function(point) { + return dagreD3.intersect.polygon(node, points, point); + }; + return shapeSvg; + }; // Add custom shape for box with inverted arrow on right side - render.shapes().rect_right_inv_arrow = function (parent, bbox, node) { - const w = bbox.width - const h = bbox.height + render.shapes().rect_right_inv_arrow = function(parent, bbox, node) { + const w = bbox.width; + const h = bbox.height; const points = [ { x: 0, y: 0 }, { x: w + h / 2, y: 0 }, { x: w, y: -h / 2 }, { x: w + h / 2, y: -h }, { x: 0, y: -h } - ] - const shapeSvg = parent.insert('polygon', ':first-child') - .attr('points', points.map(function (d) { - return d.x + ',' + d.y - }).join(' ')) - .attr('transform', 'translate(' + (-w / 2) + ',' + (h * 2 / 4) + ')') - node.intersect = function (point) { - return dagreD3.intersect.polygon(node, points, point) - } - return shapeSvg - } + ]; + const shapeSvg = parent + .insert('polygon', ':first-child') + .attr( + 'points', + points + .map(function(d) { + return d.x + ',' + d.y; + }) + .join(' ') + ) + .attr('transform', 'translate(' + -w / 2 + ',' + (h * 2) / 4 + ')'); + node.intersect = function(point) { + return dagreD3.intersect.polygon(node, points, point); + }; + return shapeSvg; + }; // Add our custom arrow - an empty arrowhead - render.arrows().none = function normal (parent, id, edge, type) { - const marker = parent.append('marker') + render.arrows().none = function normal(parent, id, edge, type) { + const marker = parent + .append('marker') .attr('id', id) .attr('viewBox', '0 0 10 10') .attr('refX', 9) @@ -477,16 +533,16 @@ export const draw = function (text, id) { .attr('markerUnits', 'strokeWidth') .attr('markerWidth', 8) .attr('markerHeight', 6) - .attr('orient', 'auto') + .attr('orient', 'auto'); - const path = marker.append('path') - .attr('d', 'M 0 0 L 0 0 L 0 0 z') - dagreD3.util.applyStyle(path, edge[type + 'Style']) - } + const path = marker.append('path').attr('d', 'M 0 0 L 0 0 L 0 0 z'); + dagreD3.util.applyStyle(path, edge[type + 'Style']); + }; // Override normal arrowhead defined in d3. Remove style & add class to allow css styling. - render.arrows().normal = function normal (parent, id, edge, type) { - const marker = parent.append('marker') + render.arrows().normal = function normal(parent, id, edge, type) { + const marker = parent + .append('marker') .attr('id', id) .attr('viewBox', '0 0 10 10') .attr('refX', 9) @@ -494,76 +550,76 @@ export const draw = function (text, id) { .attr('markerUnits', 'strokeWidth') .attr('markerWidth', 8) .attr('markerHeight', 6) - .attr('orient', 'auto') + .attr('orient', 'auto'); - marker.append('path') + marker + .append('path') .attr('d', 'M 0 0 L 10 5 L 0 10 z') .attr('class', 'arrowheadPath') .style('stroke-width', 1) - .style('stroke-dasharray', '1,0') - } + .style('stroke-dasharray', '1,0'); + }; // Set up an SVG group so that we can translate the final graph. - const svg = d3.select(`[id="${id}"]`) + const svg = d3.select(`[id="${id}"]`); // Run the renderer. This is what draws the final graph. - const element = d3.select('#' + id + ' g') - render(element, g) + const element = d3.select('#' + id + ' g'); + render(element, g); - element.selectAll('g.node') - .attr('title', function () { - return flowDb.getTooltip(this.id) - }) + element.selectAll('g.node').attr('title', function() { + return flowDb.getTooltip(this.id); + }); - const padding = 8 - const width = g.maxX - g.minX + padding * 2 - const height = g.maxY - g.minY + padding * 2 - svg.attr('width', '100%') - svg.attr('style', `max-width: ${width}px;`) - svg.attr('viewBox', `0 0 ${width} ${height}`) - svg.select('g').attr('transform', `translate(${padding - g.minX}, ${padding - g.minY})`) + const padding = 8; + const width = g.maxX - g.minX + padding * 2; + const height = g.maxY - g.minY + padding * 2; + svg.attr('width', '100%'); + svg.attr('style', `max-width: ${width}px;`); + svg.attr('viewBox', `0 0 ${width} ${height}`); + svg.select('g').attr('transform', `translate(${padding - g.minX}, ${padding - g.minY})`); // Index nodes - flowDb.indexNodes('subGraph' + i) + flowDb.indexNodes('subGraph' + i); // reposition labels for (i = 0; i < subGraphs.length; i++) { - subG = subGraphs[i] + subG = subGraphs[i]; if (subG.title !== 'undefined') { - const clusterRects = document.querySelectorAll('#' + id + ' #' + subG.id + ' rect') - const clusterEl = document.querySelectorAll('#' + id + ' #' + subG.id) + const clusterRects = document.querySelectorAll('#' + id + ' #' + subG.id + ' rect'); + const clusterEl = document.querySelectorAll('#' + id + ' #' + subG.id); - const xPos = clusterRects[0].x.baseVal.value - const yPos = clusterRects[0].y.baseVal.value - const width = clusterRects[0].width.baseVal.value - const cluster = d3.select(clusterEl[0]) - const te = cluster.select('.label') - te.attr('transform', `translate(${xPos + width / 2}, ${yPos + 14})`) - te.attr('id', id + 'Text') + const xPos = clusterRects[0].x.baseVal.value; + const yPos = clusterRects[0].y.baseVal.value; + const width = clusterRects[0].width.baseVal.value; + const cluster = d3.select(clusterEl[0]); + const te = cluster.select('.label'); + te.attr('transform', `translate(${xPos + width / 2}, ${yPos + 14})`); + te.attr('id', id + 'Text'); } } // Add label rects for non html labels if (!getConfig().flowchart.htmlLabels) { - const labels = document.querySelectorAll('#' + id + ' .edgeLabel .label') + const labels = document.querySelectorAll('#' + id + ' .edgeLabel .label'); for (let k = 0; k < labels.length; k++) { - const label = labels[k] + const label = labels[k]; // Get dimensions of label - const dim = label.getBBox() + const dim = label.getBBox(); - const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect') - rect.setAttribute('rx', 0) - rect.setAttribute('ry', 0) - rect.setAttribute('width', dim.width) - rect.setAttribute('height', dim.height) - rect.setAttribute('style', 'fill:#e8e8e8;') + const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect'); + rect.setAttribute('rx', 0); + rect.setAttribute('ry', 0); + rect.setAttribute('width', dim.width); + rect.setAttribute('height', dim.height); + rect.setAttribute('style', 'fill:#e8e8e8;'); - label.insertBefore(rect, label.firstChild) + label.insertBefore(rect, label.firstChild); } } -} +}; export default { setConf, @@ -571,4 +627,4 @@ export default { addEdges, getClasses, draw -} +}; diff --git a/src/diagrams/flowchart/parser/flow-vertice-chaining.spec.js b/src/diagrams/flowchart/parser/flow-vertice-chaining.spec.js index e2247418c..db8cfadfe 100644 --- a/src/diagrams/flowchart/parser/flow-vertice-chaining.spec.js +++ b/src/diagrams/flowchart/parser/flow-vertice-chaining.spec.js @@ -1,38 +1,37 @@ -import flowDb from '../flowDb' -import flow from './flow' -import { setConfig } from '../../../config' +import flowDb from '../flowDb'; +import flow from './flow'; +import { setConfig } from '../../../config'; setConfig({ - securityLevel: 'strict', -}) + securityLevel: 'strict' +}); -describe('when parsing flowcharts', function () { - beforeEach(function () { - flow.parser.yy = flowDb - flow.parser.yy.clear() - }) +describe('when parsing flowcharts', function() { + beforeEach(function() { + flow.parser.yy = flowDb; + flow.parser.yy.clear(); + }); - it('should handle chaining of vertices', function () { + it('should handle chaining of vertices', function() { const res = flow.parser.parse(` graph TD A-->B-->C; `); - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); - expect(vert['A'].id).toBe('A') - expect(vert['B'].id).toBe('B') - expect(vert['C'].id).toBe('C') - expect(edges.length).toBe(2) - expect(edges[0].start).toBe('A') - expect(edges[0].end).toBe('B') - expect(edges[0].type).toBe('arrow') - expect(edges[0].text).toBe('') - expect(edges[1].start).toBe('B') - expect(edges[1].end).toBe('C') - expect(edges[1].type).toBe('arrow') - expect(edges[1].text).toBe('') - }) - -}) + expect(vert['A'].id).toBe('A'); + expect(vert['B'].id).toBe('B'); + expect(vert['C'].id).toBe('C'); + expect(edges.length).toBe(2); + expect(edges[0].start).toBe('A'); + expect(edges[0].end).toBe('B'); + expect(edges[0].type).toBe('arrow'); + expect(edges[0].text).toBe(''); + expect(edges[1].start).toBe('B'); + expect(edges[1].end).toBe('C'); + expect(edges[1].type).toBe('arrow'); + expect(edges[1].text).toBe(''); + }); +}); diff --git a/src/diagrams/flowchart/parser/flow.spec.js b/src/diagrams/flowchart/parser/flow.spec.js index 8cb91f21d..5b99fcc3d 100644 --- a/src/diagrams/flowchart/parser/flow.spec.js +++ b/src/diagrams/flowchart/parser/flow.spec.js @@ -1,361 +1,366 @@ -import flowDb from '../flowDb' -import flow from './flow' -import { setConfig } from '../../../config' +import flowDb from '../flowDb'; +import flow from './flow'; +import { setConfig } from '../../../config'; setConfig({ - securityLevel: 'strict', -}) - -describe('when parsing ', function () { - beforeEach(function () { - flow.parser.yy = flowDb - flow.parser.yy.clear() - }) - - it('should handle a nodes and edges', function () { - const res = flow.parser.parse('graph TD;\nA-->B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(vert['A'].id).toBe('A') - expect(vert['B'].id).toBe('B') - expect(edges.length).toBe(1) - expect(edges[0].start).toBe('A') - expect(edges[0].end).toBe('B') - expect(edges[0].type).toBe('arrow') - expect(edges[0].text).toBe('') - }) - - it("should handle angle bracket ' > ' as direction LR", function () { - const res = flow.parser.parse('graph >;A-->B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - const direction = flow.parser.yy.getDirection() - - expect(direction).toBe('LR') - - expect(vert['A'].id).toBe('A') - expect(vert['B'].id).toBe('B') - expect(edges.length).toBe(1) - expect(edges[0].start).toBe('A') - expect(edges[0].end).toBe('B') - expect(edges[0].type).toBe('arrow') - expect(edges[0].text).toBe('') - }) - - it("should handle angle bracket ' < ' as direction RL", function () { - const res = flow.parser.parse('graph <;A-->B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - const direction = flow.parser.yy.getDirection() - - expect(direction).toBe('RL') - - expect(vert['A'].id).toBe('A') - expect(vert['B'].id).toBe('B') - expect(edges.length).toBe(1) - expect(edges[0].start).toBe('A') - expect(edges[0].end).toBe('B') - expect(edges[0].type).toBe('arrow') - expect(edges[0].text).toBe('') - }) - - it("should handle caret ' ^ ' as direction BT", function () { - const res = flow.parser.parse('graph ^;A-->B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - const direction = flow.parser.yy.getDirection() - - expect(direction).toBe('BT') - - expect(vert['A'].id).toBe('A') - expect(vert['B'].id).toBe('B') - expect(edges.length).toBe(1) - expect(edges[0].start).toBe('A') - expect(edges[0].end).toBe('B') - expect(edges[0].type).toBe('arrow') - expect(edges[0].text).toBe('') - }) - - it('should handle lower-case \'v\' as direction TB', function () { - const res = flow.parser.parse('graph v;A-->B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - const direction = flow.parser.yy.getDirection() - - expect(direction).toBe('TB') - - expect(vert['A'].id).toBe('A') - expect(vert['B'].id).toBe('B') - expect(edges.length).toBe(1) - expect(edges[0].start).toBe('A') - expect(edges[0].end).toBe('B') - expect(edges[0].type).toBe('arrow') - expect(edges[0].text).toBe('') - }) - - it('should handle a nodes and edges and a space between link and node', function () { - const res = flow.parser.parse('graph TD;A --> B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(vert['A'].id).toBe('A') - expect(vert['B'].id).toBe('B') - expect(edges.length).toBe(1) - expect(edges[0].start).toBe('A') - expect(edges[0].end).toBe('B') - expect(edges[0].type).toBe('arrow') - expect(edges[0].text).toBe('') - }) - - it('should handle a nodes and edges, a space between link and node and each line ending without semicolon', function () { - const res = flow.parser.parse('graph TD\nA --> B\n style e red') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(vert['A'].id).toBe('A') - expect(vert['B'].id).toBe('B') - expect(edges.length).toBe(1) - expect(edges[0].start).toBe('A') - expect(edges[0].end).toBe('B') - expect(edges[0].type).toBe('arrow') - expect(edges[0].text).toBe('') - }) - it('should handle statements ending without semicolon', function () { - const res = flow.parser.parse('graph TD\nA-->B\nB-->C') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(vert['A'].id).toBe('A') - expect(vert['B'].id).toBe('B') - expect(edges.length).toBe(2) - expect(edges[1].start).toBe('B') - expect(edges[1].end).toBe('C') - expect(edges[0].type).toBe('arrow') - expect(edges[0].text).toBe('') - }) - - it('should handle a comments', function () { - const res = flow.parser.parse('graph TD;\n%% CComment\n A-->B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(vert['A'].id).toBe('A') - expect(vert['B'].id).toBe('B') - expect(edges.length).toBe(1) - expect(edges[0].start).toBe('A') - expect(edges[0].end).toBe('B') - expect(edges[0].type).toBe('arrow') - expect(edges[0].text).toBe('') - }) - it('should handle comments a at the start', function () { - const res = flow.parser.parse('%% Comment\ngraph TD;\n A-->B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(vert['A'].id).toBe('A') - expect(vert['B'].id).toBe('B') - expect(edges.length).toBe(1) - expect(edges[0].start).toBe('A') - expect(edges[0].end).toBe('B') - expect(edges[0].type).toBe('arrow') - expect(edges[0].text).toBe('') - }) - it('should handle comments at the end', function () { - const res = flow.parser.parse('graph TD;\n A-->B\n %% Comment at the find\n') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(vert['A'].id).toBe('A') - expect(vert['B'].id).toBe('B') - expect(edges.length).toBe(1) - expect(edges[0].start).toBe('A') - expect(edges[0].end).toBe('B') - expect(edges[0].type).toBe('arrow') - expect(edges[0].text).toBe('') - }) - it('should handle comments at the end no trailing newline', function () { - const res = flow.parser.parse('graph TD;\n A-->B\n%% Commento') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(vert['A'].id).toBe('A') - expect(vert['B'].id).toBe('B') - expect(edges.length).toBe(1) - expect(edges[0].start).toBe('A') - expect(edges[0].end).toBe('B') - expect(edges[0].type).toBe('arrow') - expect(edges[0].text).toBe('') - }) - it('should handle comments at the end many trailing newlines', function () { - const res = flow.parser.parse('graph TD;\n A-->B\n%% Commento\n\n\n') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(vert['A'].id).toBe('A') - expect(vert['B'].id).toBe('B') - expect(edges.length).toBe(1) - expect(edges[0].start).toBe('A') - expect(edges[0].end).toBe('B') - expect(edges[0].type).toBe('arrow') - expect(edges[0].text).toBe('') - }) - it('should handle no trailing newlines', function () { - const res = flow.parser.parse('graph TD;\n A-->B') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(vert['A'].id).toBe('A') - expect(vert['B'].id).toBe('B') - expect(edges.length).toBe(1) - expect(edges[0].start).toBe('A') - expect(edges[0].end).toBe('B') - expect(edges[0].type).toBe('arrow') - expect(edges[0].text).toBe('') - }) - it('should handle many trailing newlines', function () { - const res = flow.parser.parse('graph TD;\n A-->B\n\n') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(vert['A'].id).toBe('A') - expect(vert['B'].id).toBe('B') - expect(edges.length).toBe(1) - expect(edges[0].start).toBe('A') - expect(edges[0].end).toBe('B') - expect(edges[0].type).toBe('arrow') - expect(edges[0].text).toBe('') - }) - it('should handle a comments with blank rows in-between', function () { - const res = flow.parser.parse('graph TD;\n\n\n %% Comment\n A-->B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(vert['A'].id).toBe('A') - expect(vert['B'].id).toBe('B') - expect(edges.length).toBe(1) - expect(edges[0].start).toBe('A') - expect(edges[0].end).toBe('B') - expect(edges[0].type).toBe('arrow') - expect(edges[0].text).toBe('') - }) - - it('should handle a comments mermaid flowchart code in them', function () { - const res = flow.parser.parse('graph TD;\n\n\n %% Test od>Odd shape]-->|Two line
edge comment|ro;\n A-->B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(vert['A'].id).toBe('A') - expect(vert['B'].id).toBe('B') - expect(edges.length).toBe(1) - expect(edges[0].start).toBe('A') - expect(edges[0].end).toBe('B') - expect(edges[0].type).toBe('arrow') - expect(edges[0].text).toBe('') - }) - - it('it should handle a trailing whitespaces after statememnts', function () { - const res = flow.parser.parse('graph TD;\n\n\n %% Comment\n A-->B; \n B-->C;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(vert['A'].id).toBe('A') - expect(vert['B'].id).toBe('B') - expect(edges.length).toBe(2) - expect(edges[0].start).toBe('A') - expect(edges[0].end).toBe('B') - expect(edges[0].type).toBe('arrow') - expect(edges[0].text).toBe('') - }) - - it('should handle node names with "end" substring', function () { - const res = flow.parser.parse('graph TD\nendpoint --> sender') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(vert['endpoint'].id).toBe('endpoint') - expect(vert['sender'].id).toBe('sender') - expect(edges[0].start).toBe('endpoint') - expect(edges[0].end).toBe('sender') - }) - - it('should handle node names ending with keywords', function () { - const res = flow.parser.parse('graph TD\nblend --> monograph') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(vert['blend'].id).toBe('blend') - expect(vert['monograph'].id).toBe('monograph') - expect(edges[0].start).toBe('blend') - expect(edges[0].end).toBe('monograph') - }) - - it('should handle open ended edges', function () { - const res = flow.parser.parse('graph TD;A---B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(edges[0].type).toBe('arrow_open') - }) - - it('should handle cross ended edges', function () { - const res = flow.parser.parse('graph TD;A--xB;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(edges[0].type).toBe('arrow_cross') - }) - - it('should handle open ended edges', function () { - const res = flow.parser.parse('graph TD;A--oB;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(edges[0].type).toBe('arrow_circle') - }) - it('should handle classDefs with style in classes', function () { - const res = flow.parser.parse('graph TD\nA-->B\nclassDef exClass font-style:bold;') + securityLevel: 'strict' +}); + +describe('when parsing ', function() { + beforeEach(function() { + flow.parser.yy = flowDb; + flow.parser.yy.clear(); + }); + + it('should handle a nodes and edges', function() { + const res = flow.parser.parse('graph TD;\nA-->B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['A'].id).toBe('A'); + expect(vert['B'].id).toBe('B'); + expect(edges.length).toBe(1); + expect(edges[0].start).toBe('A'); + expect(edges[0].end).toBe('B'); + expect(edges[0].type).toBe('arrow'); + expect(edges[0].text).toBe(''); + }); + + it("should handle angle bracket ' > ' as direction LR", function() { + const res = flow.parser.parse('graph >;A-->B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + const direction = flow.parser.yy.getDirection(); + + expect(direction).toBe('LR'); + + expect(vert['A'].id).toBe('A'); + expect(vert['B'].id).toBe('B'); + expect(edges.length).toBe(1); + expect(edges[0].start).toBe('A'); + expect(edges[0].end).toBe('B'); + expect(edges[0].type).toBe('arrow'); + expect(edges[0].text).toBe(''); + }); + + it("should handle angle bracket ' < ' as direction RL", function() { + const res = flow.parser.parse('graph <;A-->B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + const direction = flow.parser.yy.getDirection(); + + expect(direction).toBe('RL'); + + expect(vert['A'].id).toBe('A'); + expect(vert['B'].id).toBe('B'); + expect(edges.length).toBe(1); + expect(edges[0].start).toBe('A'); + expect(edges[0].end).toBe('B'); + expect(edges[0].type).toBe('arrow'); + expect(edges[0].text).toBe(''); + }); + + it("should handle caret ' ^ ' as direction BT", function() { + const res = flow.parser.parse('graph ^;A-->B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + const direction = flow.parser.yy.getDirection(); + + expect(direction).toBe('BT'); + + expect(vert['A'].id).toBe('A'); + expect(vert['B'].id).toBe('B'); + expect(edges.length).toBe(1); + expect(edges[0].start).toBe('A'); + expect(edges[0].end).toBe('B'); + expect(edges[0].type).toBe('arrow'); + expect(edges[0].text).toBe(''); + }); + + it("should handle lower-case 'v' as direction TB", function() { + const res = flow.parser.parse('graph v;A-->B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + const direction = flow.parser.yy.getDirection(); + + expect(direction).toBe('TB'); + + expect(vert['A'].id).toBe('A'); + expect(vert['B'].id).toBe('B'); + expect(edges.length).toBe(1); + expect(edges[0].start).toBe('A'); + expect(edges[0].end).toBe('B'); + expect(edges[0].type).toBe('arrow'); + expect(edges[0].text).toBe(''); + }); + + it('should handle a nodes and edges and a space between link and node', function() { + const res = flow.parser.parse('graph TD;A --> B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['A'].id).toBe('A'); + expect(vert['B'].id).toBe('B'); + expect(edges.length).toBe(1); + expect(edges[0].start).toBe('A'); + expect(edges[0].end).toBe('B'); + expect(edges[0].type).toBe('arrow'); + expect(edges[0].text).toBe(''); + }); + + it('should handle a nodes and edges, a space between link and node and each line ending without semicolon', function() { + const res = flow.parser.parse('graph TD\nA --> B\n style e red'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['A'].id).toBe('A'); + expect(vert['B'].id).toBe('B'); + expect(edges.length).toBe(1); + expect(edges[0].start).toBe('A'); + expect(edges[0].end).toBe('B'); + expect(edges[0].type).toBe('arrow'); + expect(edges[0].text).toBe(''); + }); + it('should handle statements ending without semicolon', function() { + const res = flow.parser.parse('graph TD\nA-->B\nB-->C'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['A'].id).toBe('A'); + expect(vert['B'].id).toBe('B'); + expect(edges.length).toBe(2); + expect(edges[1].start).toBe('B'); + expect(edges[1].end).toBe('C'); + expect(edges[0].type).toBe('arrow'); + expect(edges[0].text).toBe(''); + }); + + it('should handle a comments', function() { + const res = flow.parser.parse('graph TD;\n%% CComment\n A-->B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['A'].id).toBe('A'); + expect(vert['B'].id).toBe('B'); + expect(edges.length).toBe(1); + expect(edges[0].start).toBe('A'); + expect(edges[0].end).toBe('B'); + expect(edges[0].type).toBe('arrow'); + expect(edges[0].text).toBe(''); + }); + it('should handle comments a at the start', function() { + const res = flow.parser.parse('%% Comment\ngraph TD;\n A-->B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['A'].id).toBe('A'); + expect(vert['B'].id).toBe('B'); + expect(edges.length).toBe(1); + expect(edges[0].start).toBe('A'); + expect(edges[0].end).toBe('B'); + expect(edges[0].type).toBe('arrow'); + expect(edges[0].text).toBe(''); + }); + it('should handle comments at the end', function() { + const res = flow.parser.parse('graph TD;\n A-->B\n %% Comment at the find\n'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['A'].id).toBe('A'); + expect(vert['B'].id).toBe('B'); + expect(edges.length).toBe(1); + expect(edges[0].start).toBe('A'); + expect(edges[0].end).toBe('B'); + expect(edges[0].type).toBe('arrow'); + expect(edges[0].text).toBe(''); + }); + it('should handle comments at the end no trailing newline', function() { + const res = flow.parser.parse('graph TD;\n A-->B\n%% Commento'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['A'].id).toBe('A'); + expect(vert['B'].id).toBe('B'); + expect(edges.length).toBe(1); + expect(edges[0].start).toBe('A'); + expect(edges[0].end).toBe('B'); + expect(edges[0].type).toBe('arrow'); + expect(edges[0].text).toBe(''); + }); + it('should handle comments at the end many trailing newlines', function() { + const res = flow.parser.parse('graph TD;\n A-->B\n%% Commento\n\n\n'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['A'].id).toBe('A'); + expect(vert['B'].id).toBe('B'); + expect(edges.length).toBe(1); + expect(edges[0].start).toBe('A'); + expect(edges[0].end).toBe('B'); + expect(edges[0].type).toBe('arrow'); + expect(edges[0].text).toBe(''); + }); + it('should handle no trailing newlines', function() { + const res = flow.parser.parse('graph TD;\n A-->B'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['A'].id).toBe('A'); + expect(vert['B'].id).toBe('B'); + expect(edges.length).toBe(1); + expect(edges[0].start).toBe('A'); + expect(edges[0].end).toBe('B'); + expect(edges[0].type).toBe('arrow'); + expect(edges[0].text).toBe(''); + }); + it('should handle many trailing newlines', function() { + const res = flow.parser.parse('graph TD;\n A-->B\n\n'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['A'].id).toBe('A'); + expect(vert['B'].id).toBe('B'); + expect(edges.length).toBe(1); + expect(edges[0].start).toBe('A'); + expect(edges[0].end).toBe('B'); + expect(edges[0].type).toBe('arrow'); + expect(edges[0].text).toBe(''); + }); + it('should handle a comments with blank rows in-between', function() { + const res = flow.parser.parse('graph TD;\n\n\n %% Comment\n A-->B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['A'].id).toBe('A'); + expect(vert['B'].id).toBe('B'); + expect(edges.length).toBe(1); + expect(edges[0].start).toBe('A'); + expect(edges[0].end).toBe('B'); + expect(edges[0].type).toBe('arrow'); + expect(edges[0].text).toBe(''); + }); + + it('should handle a comments mermaid flowchart code in them', function() { + const res = flow.parser.parse( + 'graph TD;\n\n\n %% Test od>Odd shape]-->|Two line
edge comment|ro;\n A-->B;' + ); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['A'].id).toBe('A'); + expect(vert['B'].id).toBe('B'); + expect(edges.length).toBe(1); + expect(edges[0].start).toBe('A'); + expect(edges[0].end).toBe('B'); + expect(edges[0].type).toBe('arrow'); + expect(edges[0].text).toBe(''); + }); + + it('it should handle a trailing whitespaces after statememnts', function() { + const res = flow.parser.parse('graph TD;\n\n\n %% Comment\n A-->B; \n B-->C;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['A'].id).toBe('A'); + expect(vert['B'].id).toBe('B'); + expect(edges.length).toBe(2); + expect(edges[0].start).toBe('A'); + expect(edges[0].end).toBe('B'); + expect(edges[0].type).toBe('arrow'); + expect(edges[0].text).toBe(''); + }); + + it('should handle node names with "end" substring', function() { + const res = flow.parser.parse('graph TD\nendpoint --> sender'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['endpoint'].id).toBe('endpoint'); + expect(vert['sender'].id).toBe('sender'); + expect(edges[0].start).toBe('endpoint'); + expect(edges[0].end).toBe('sender'); + }); + + it('should handle node names ending with keywords', function() { + const res = flow.parser.parse('graph TD\nblend --> monograph'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['blend'].id).toBe('blend'); + expect(vert['monograph'].id).toBe('monograph'); + expect(edges[0].start).toBe('blend'); + expect(edges[0].end).toBe('monograph'); + }); + + it('should handle open ended edges', function() { + const res = flow.parser.parse('graph TD;A---B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(edges[0].type).toBe('arrow_open'); + }); + + it('should handle cross ended edges', function() { + const res = flow.parser.parse('graph TD;A--xB;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(edges[0].type).toBe('arrow_cross'); + }); + + it('should handle open ended edges', function() { + const res = flow.parser.parse('graph TD;A--oB;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(edges[0].type).toBe('arrow_circle'); + }); + it('should handle classDefs with style in classes', function() { + const res = flow.parser.parse('graph TD\nA-->B\nclassDef exClass font-style:bold;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() + expect(edges[0].type).toBe('arrow'); + }); - expect(edges[0].type).toBe('arrow') - }) + it('should handle classDefs with % in classes', function() { + const res = flow.parser.parse( + 'graph TD\nA-->B\nclassDef exClass fill:#f96,stroke:#333,stroke-width:4px,font-size:50%,font-style:bold;' + ); - it('should handle classDefs with % in classes', function () { - const res = flow.parser.parse('graph TD\nA-->B\nclassDef exClass fill:#f96,stroke:#333,stroke-width:4px,font-size:50%,font-style:bold;') + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() + expect(edges[0].type).toBe('arrow'); + }); - expect(edges[0].type).toBe('arrow') - }) - - it('should handle style definitions with more then 1 digit in a row', function () { - const res = flow.parser.parse('graph TD\n' + + it('should handle style definitions with more then 1 digit in a row', function() { + const res = flow.parser.parse( + 'graph TD\n' + 'A-->B1\n' + 'A-->B2\n' + 'A-->B3\n' + @@ -367,16 +372,18 @@ describe('when parsing ', function () { 'A-->B9\n' + 'A-->B10\n' + 'A-->B11\n' + - 'linkStyle 10 stroke-width:1px;') + 'linkStyle 10 stroke-width:1px;' + ); - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); - expect(edges[0].type).toBe('arrow') - }) + expect(edges[0].type).toBe('arrow'); + }); - it('should handle multi-numbered style definitons with more then 1 digit in a row', function () { - const res = flow.parser.parse('graph TD\n' + + it('should handle multi-numbered style definitons with more then 1 digit in a row', function() { + const res = flow.parser.parse( + 'graph TD\n' + 'A-->B1\n' + 'A-->B2\n' + 'A-->B3\n' + @@ -389,1360 +396,1372 @@ describe('when parsing ', function () { 'A-->B10\n' + 'A-->B11\n' + 'A-->B12\n' + - 'linkStyle 10,11 stroke-width:1px;') + 'linkStyle 10,11 stroke-width:1px;' + ); - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); - expect(edges[0].type).toBe('arrow') - }) + expect(edges[0].type).toBe('arrow'); + }); - it('should handle line interpolation default definitions', function () { - const res = flow.parser.parse('graph TD\n' + - 'A-->B\n' + - 'linkStyle default interpolate basis') + it('should handle line interpolation default definitions', function() { + const res = flow.parser.parse('graph TD\n' + 'A-->B\n' + 'linkStyle default interpolate basis'); - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); - expect(edges.defaultInterpolate).toBe('basis') - }) + expect(edges.defaultInterpolate).toBe('basis'); + }); - it('should handle line interpolation numbered definitions', function () { - const res = flow.parser.parse('graph TD\n' + + it('should handle line interpolation numbered definitions', function() { + const res = flow.parser.parse( + 'graph TD\n' + 'A-->B\n' + 'A-->C\n' + 'linkStyle 0 interpolate basis\n' + - 'linkStyle 1 interpolate cardinal') + 'linkStyle 1 interpolate cardinal' + ); - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); - expect(edges[0].interpolate).toBe('basis') - expect(edges[1].interpolate).toBe('cardinal') - }) + expect(edges[0].interpolate).toBe('basis'); + expect(edges[1].interpolate).toBe('cardinal'); + }); - it('should handle line interpolation multi-numbered definitions', function () { - const res = flow.parser.parse('graph TD\n' + - 'A-->B\n' + - 'A-->C\n' + - 'linkStyle 0,1 interpolate basis') + it('should handle line interpolation multi-numbered definitions', function() { + const res = flow.parser.parse( + 'graph TD\n' + 'A-->B\n' + 'A-->C\n' + 'linkStyle 0,1 interpolate basis' + ); - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); - expect(edges[0].interpolate).toBe('basis') - expect(edges[1].interpolate).toBe('basis') - }) + expect(edges[0].interpolate).toBe('basis'); + expect(edges[1].interpolate).toBe('basis'); + }); - it('should handle line interpolation default with style', function () { - const res = flow.parser.parse('graph TD\n' + - 'A-->B\n' + - 'linkStyle default interpolate basis stroke-width:1px;') + it('should handle line interpolation default with style', function() { + const res = flow.parser.parse( + 'graph TD\n' + 'A-->B\n' + 'linkStyle default interpolate basis stroke-width:1px;' + ); - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); - expect(edges.defaultInterpolate).toBe('basis') - }) + expect(edges.defaultInterpolate).toBe('basis'); + }); - it('should handle line interpolation numbered with style', function () { - const res = flow.parser.parse('graph TD\n' + + it('should handle line interpolation numbered with style', function() { + const res = flow.parser.parse( + 'graph TD\n' + 'A-->B\n' + 'A-->C\n' + 'linkStyle 0 interpolate basis stroke-width:1px;\n' + - 'linkStyle 1 interpolate cardinal stroke-width:1px;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(edges[0].interpolate).toBe('basis') - expect(edges[1].interpolate).toBe('cardinal') - }) - - it('should handle line interpolation multi-numbered with style', function () { - const res = flow.parser.parse('graph TD\n' + - 'A-->B\n' + - 'A-->C\n' + - 'linkStyle 0,1 interpolate basis stroke-width:1px;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(edges[0].interpolate).toBe('basis') - expect(edges[1].interpolate).toBe('basis') - }) - - describe('it should handle interaction, ', function () { - it('it should be possible to use click to a callback', function () { - spyOn(flowDb, 'setClickEvent') - const res = flow.parser.parse('graph TD\nA-->B\nclick A callback') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(flowDb.setClickEvent).toHaveBeenCalledWith('A', 'callback', undefined) - }) - - it('it should be possible to use click to a callback with toolip', function () { - spyOn(flowDb, 'setClickEvent') - const res = flow.parser.parse('graph TD\nA-->B\nclick A callback "tooltip"') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(flowDb.setClickEvent).toHaveBeenCalledWith('A', 'callback', 'tooltip') - }) - - it('should handle interaction - click to a link', function () { - spyOn(flowDb, 'setLink') - const res = flow.parser.parse('graph TD\nA-->B\nclick A "click.html"') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(flowDb.setLink).toHaveBeenCalledWith('A', 'click.html', undefined) - }) - it('should handle interaction - click to a link with tooltip', function () { - spyOn(flowDb, 'setLink') - const res = flow.parser.parse('graph TD\nA-->B\nclick A "click.html" "tooltip"') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(flowDb.setLink).toHaveBeenCalledWith('A', 'click.html', 'tooltip') - }) - }) - - describe('it should multi directional arrows', function () { - describe('point', function () { - it('should handle double edged nodes and edges', function () { - const res = flow.parser.parse('graph TD;\nA<-->B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(vert['A'].id).toBe('A') - expect(vert['B'].id).toBe('B') - expect(edges.length).toBe(1) - expect(edges[0].start).toBe('A') - expect(edges[0].end).toBe('B') - expect(edges[0].type).toBe('double_arrow_point') - expect(edges[0].text).toBe('') - }) - it('should handle double edged nodes with text', function () { - const res = flow.parser.parse('graph TD;\nA<-- text -->B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(vert['A'].id).toBe('A') - expect(vert['B'].id).toBe('B') - expect(edges.length).toBe(1) - expect(edges[0].start).toBe('A') - expect(edges[0].end).toBe('B') - expect(edges[0].type).toBe('double_arrow_point') - expect(edges[0].stroke).toBe('normal') - expect(edges[0].text).toBe('text') - }) - it('should handle double edged nodes and edges on thick arrows', function () { - const res = flow.parser.parse('graph TD;\nA<==>B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(vert['A'].id).toBe('A') - expect(vert['B'].id).toBe('B') - expect(edges.length).toBe(1) - expect(edges[0].start).toBe('A') - expect(edges[0].end).toBe('B') - expect(edges[0].type).toBe('double_arrow_point') - expect(edges[0].stroke).toBe('thick') - expect(edges[0].text).toBe('') - }) - it('should handle double edged nodes with text on thick arrows', function () { - const res = flow.parser.parse('graph TD;\nA<== text ==>B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(vert['A'].id).toBe('A') - expect(vert['B'].id).toBe('B') - expect(edges.length).toBe(1) - expect(edges[0].start).toBe('A') - expect(edges[0].end).toBe('B') - expect(edges[0].type).toBe('double_arrow_point') - expect(edges[0].stroke).toBe('thick') - expect(edges[0].text).toBe('text') - }) - it('should handle double edged nodes and edges on dotted arrows', function () { - const res = flow.parser.parse('graph TD;\nA<-.->B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(vert['A'].id).toBe('A') - expect(vert['B'].id).toBe('B') - expect(edges.length).toBe(1) - expect(edges[0].start).toBe('A') - expect(edges[0].end).toBe('B') - expect(edges[0].type).toBe('double_arrow_point') - expect(edges[0].stroke).toBe('dotted') - expect(edges[0].text).toBe('') - }) - it('should handle double edged nodes with text on dotted arrows', function () { - const res = flow.parser.parse('graph TD;\nA<-. text .->B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(vert['A'].id).toBe('A') - expect(vert['B'].id).toBe('B') - expect(edges.length).toBe(1) - expect(edges[0].start).toBe('A') - expect(edges[0].end).toBe('B') - expect(edges[0].type).toBe('double_arrow_point') - expect(edges[0].stroke).toBe('dotted') - expect(edges[0].text).toBe('text') - }) - }) - describe('cross', function () { - it('should handle double edged nodes and edges', function () { - const res = flow.parser.parse('graph TD;\nA x--x B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(vert['A'].id).toBe('A') - expect(vert['B'].id).toBe('B') - expect(edges.length).toBe(1) - expect(edges[0].start).toBe('A') - expect(edges[0].end).toBe('B') - expect(edges[0].type).toBe('double_arrow_cross') - expect(edges[0].text).toBe('') - }) - it('should handle double edged nodes with text', function () { - const res = flow.parser.parse('graph TD;\nA x-- text --x B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(vert['A'].id).toBe('A') - expect(vert['B'].id).toBe('B') - expect(edges.length).toBe(1) - expect(edges[0].start).toBe('A') - expect(edges[0].end).toBe('B') - expect(edges[0].type).toBe('double_arrow_cross') - expect(edges[0].stroke).toBe('normal') - expect(edges[0].text).toBe('text') - }) - it('should handle double edged nodes and edges on thick arrows', function () { - const res = flow.parser.parse('graph TD;\nA x==x B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(vert['A'].id).toBe('A') - expect(vert['B'].id).toBe('B') - expect(edges.length).toBe(1) - expect(edges[0].start).toBe('A') - expect(edges[0].end).toBe('B') - expect(edges[0].type).toBe('double_arrow_cross') - expect(edges[0].stroke).toBe('thick') - expect(edges[0].text).toBe('') - }) - it('should handle double edged nodes with text on thick arrows', function () { - const res = flow.parser.parse('graph TD;\nA x== text ==x B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(vert['A'].id).toBe('A') - expect(vert['B'].id).toBe('B') - expect(edges.length).toBe(1) - expect(edges[0].start).toBe('A') - expect(edges[0].end).toBe('B') - expect(edges[0].type).toBe('double_arrow_cross') - expect(edges[0].stroke).toBe('thick') - expect(edges[0].text).toBe('text') - }) - it('should handle double edged nodes and edges on dotted arrows', function () { - const res = flow.parser.parse('graph TD;\nA x-.-x B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(vert['A'].id).toBe('A') - expect(vert['B'].id).toBe('B') - expect(edges.length).toBe(1) - expect(edges[0].start).toBe('A') - expect(edges[0].end).toBe('B') - expect(edges[0].type).toBe('double_arrow_cross') - expect(edges[0].stroke).toBe('dotted') - expect(edges[0].text).toBe('') - }) - it('should handle double edged nodes with text on dotted arrows', function () { - const res = flow.parser.parse('graph TD;\nA x-. text .-x B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(vert['A'].id).toBe('A') - expect(vert['B'].id).toBe('B') - expect(edges.length).toBe(1) - expect(edges[0].start).toBe('A') - expect(edges[0].end).toBe('B') - expect(edges[0].type).toBe('double_arrow_cross') - expect(edges[0].stroke).toBe('dotted') - expect(edges[0].text).toBe('text') - }) - }) - describe('circle', function () { - it('should handle double edged nodes and edges', function () { - const res = flow.parser.parse('graph TD;\nA o--o B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(vert['A'].id).toBe('A') - expect(vert['B'].id).toBe('B') - expect(edges.length).toBe(1) - expect(edges[0].start).toBe('A') - expect(edges[0].end).toBe('B') - expect(edges[0].type).toBe('double_arrow_circle') - expect(edges[0].text).toBe('') - }) - it('should handle double edged nodes with text', function () { - const res = flow.parser.parse('graph TD;\nA o-- text --o B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(vert['A'].id).toBe('A') - expect(vert['B'].id).toBe('B') - expect(edges.length).toBe(1) - expect(edges[0].start).toBe('A') - expect(edges[0].end).toBe('B') - expect(edges[0].type).toBe('double_arrow_circle') - expect(edges[0].stroke).toBe('normal') - expect(edges[0].text).toBe('text') - }) - it('should handle double edged nodes and edges on thick arrows', function () { - const res = flow.parser.parse('graph TD;\nA o==o B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(vert['A'].id).toBe('A') - expect(vert['B'].id).toBe('B') - expect(edges.length).toBe(1) - expect(edges[0].start).toBe('A') - expect(edges[0].end).toBe('B') - expect(edges[0].type).toBe('double_arrow_circle') - expect(edges[0].stroke).toBe('thick') - expect(edges[0].text).toBe('') - }) - it('should handle double edged nodes with text on thick arrows', function () { - const res = flow.parser.parse('graph TD;\nA o== text ==o B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(vert['A'].id).toBe('A') - expect(vert['B'].id).toBe('B') - expect(edges.length).toBe(1) - expect(edges[0].start).toBe('A') - expect(edges[0].end).toBe('B') - expect(edges[0].type).toBe('double_arrow_circle') - expect(edges[0].stroke).toBe('thick') - expect(edges[0].text).toBe('text') - }) - it('should handle double edged nodes and edges on dotted arrows', function () { - const res = flow.parser.parse('graph TD;\nA o-.-o B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(vert['A'].id).toBe('A') - expect(vert['B'].id).toBe('B') - expect(edges.length).toBe(1) - expect(edges[0].start).toBe('A') - expect(edges[0].end).toBe('B') - expect(edges[0].type).toBe('double_arrow_circle') - expect(edges[0].stroke).toBe('dotted') - expect(edges[0].text).toBe('') - }) - it('should handle double edged nodes with text on dotted arrows', function () { - const res = flow.parser.parse('graph TD;\nA o-. text .-o B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(vert['A'].id).toBe('A') - expect(vert['B'].id).toBe('B') - expect(edges.length).toBe(1) - expect(edges[0].start).toBe('A') - expect(edges[0].end).toBe('B') - expect(edges[0].type).toBe('double_arrow_circle') - expect(edges[0].stroke).toBe('dotted') - expect(edges[0].text).toBe('text') - }) - }) - - }) - describe('it should handle text on edges', function () { - it('it should handle text without space', function () { - const res = flow.parser.parse('graph TD;A--x|textNoSpace|B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(edges[0].type).toBe('arrow_cross') - }) - - it('should handle with space', function () { - const res = flow.parser.parse('graph TD;A--x|text including space|B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(edges[0].type).toBe('arrow_cross') - }) - - it('it should handle text with /', function () { - const res = flow.parser.parse('graph TD;A--x|text with / should work|B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(edges[0].text).toBe('text with / should work') - }) - - it('it should handle space and space between vertices and link', function () { - const res = flow.parser.parse('graph TD;A --x|textNoSpace| B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(edges[0].type).toBe('arrow_cross') - }) - - it('should handle space and CAPS', function () { - const res = flow.parser.parse('graph TD;A--x|text including CAPS space|B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(edges[0].type).toBe('arrow_cross') - }) - - it('should handle space and dir', function () { - const res = flow.parser.parse('graph TD;A--x|text including URL space|B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(edges[0].type).toBe('arrow_cross') - expect(edges[0].text).toBe('text including URL space') - }) - - it('should handle space and send', function () { - const res = flow.parser.parse('graph TD;A--text including URL space and send-->B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(edges[0].type).toBe('arrow') - expect(edges[0].text).toBe('text including URL space and send') - }) - it('should handle space and send', function () { - const res = flow.parser.parse('graph TD;A-- text including URL space and send -->B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(edges[0].type).toBe('arrow') - expect(edges[0].text).toBe('text including URL space and send') - }) - - it('should handle space and dir (TD)', function () { - const res = flow.parser.parse('graph TD;A--x|text including R TD space|B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(edges[0].type).toBe('arrow_cross') - expect(edges[0].text).toBe('text including R TD space') - }) - it('should handle `', function () { - const res = flow.parser.parse('graph TD;A--x|text including `|B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(edges[0].type).toBe('arrow_cross') - expect(edges[0].text).toBe('text including `') - }) - it('should handle v in node ids only v', function () { - // only v - const res = flow.parser.parse('graph TD;A--xv(my text);') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(edges[0].type).toBe('arrow_cross') - expect(vert['v'].text).toBe('my text') - }) - it('should handle v in node ids v at end', function () { - // v at end - const res = flow.parser.parse('graph TD;A--xcsv(my text);') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(edges[0].type).toBe('arrow_cross') - expect(vert['csv'].text).toBe('my text') - }) - it('should handle v in node ids v in middle', function () { - // v in middle - const res = flow.parser.parse('graph TD;A--xava(my text);') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(edges[0].type).toBe('arrow_cross') - expect(vert['ava'].text).toBe('my text') - }) - it('should handle v in node ids, v at start', function () { - // v at start - const res = flow.parser.parse('graph TD;A--xva(my text);') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(edges[0].type).toBe('arrow_cross') - expect(vert['va'].text).toBe('my text') - }) - it('should handle keywords', function () { - const res = flow.parser.parse('graph TD;A--x|text including graph space|B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(edges[0].text).toBe('text including graph space') - }) - it('should handle keywords', function () { - const res = flow.parser.parse('graph TD;V-->a[v]') - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - expect(vert['a'].text).toBe('v') - }) - it('should handle keywords', function () { - const res = flow.parser.parse('graph TD;V-->a[v]') - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - expect(vert['a'].text).toBe('v') - }) - it('should handle quoted text', function () { - const res = flow.parser.parse('graph TD;V-- "test string()" -->a[v]') - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - expect(edges[0].text).toBe('test string()') - }) - }) - - describe('it should handle new line type notation', function () { - it('it should handle regular lines', function () { - const res = flow.parser.parse('graph TD;A-->B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(edges[0].stroke).toBe('normal') - }) - it('it should handle dotted lines', function () { - const res = flow.parser.parse('graph TD;A-.->B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(edges[0].stroke).toBe('dotted') - }) - it('it should handle dotted lines', function () { - const res = flow.parser.parse('graph TD;A==>B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(edges[0].stroke).toBe('thick') - }) - it('it should handle text on lines', function () { - const res = flow.parser.parse('graph TD;A-- test text with == -->B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(edges[0].stroke).toBe('normal') - }) - it('it should handle text on lines', function () { - const res = flow.parser.parse('graph TD;A-. test text with == .->B;') + 'linkStyle 1 interpolate cardinal stroke-width:1px;' + ); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(edges[0].interpolate).toBe('basis'); + expect(edges[1].interpolate).toBe('cardinal'); + }); + + it('should handle line interpolation multi-numbered with style', function() { + const res = flow.parser.parse( + 'graph TD\n' + 'A-->B\n' + 'A-->C\n' + 'linkStyle 0,1 interpolate basis stroke-width:1px;' + ); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(edges[0].interpolate).toBe('basis'); + expect(edges[1].interpolate).toBe('basis'); + }); + + describe('it should handle interaction, ', function() { + it('it should be possible to use click to a callback', function() { + spyOn(flowDb, 'setClickEvent'); + const res = flow.parser.parse('graph TD\nA-->B\nclick A callback'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(flowDb.setClickEvent).toHaveBeenCalledWith('A', 'callback', undefined); + }); + + it('it should be possible to use click to a callback with toolip', function() { + spyOn(flowDb, 'setClickEvent'); + const res = flow.parser.parse('graph TD\nA-->B\nclick A callback "tooltip"'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(flowDb.setClickEvent).toHaveBeenCalledWith('A', 'callback', 'tooltip'); + }); + + it('should handle interaction - click to a link', function() { + spyOn(flowDb, 'setLink'); + const res = flow.parser.parse('graph TD\nA-->B\nclick A "click.html"'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(flowDb.setLink).toHaveBeenCalledWith('A', 'click.html', undefined); + }); + it('should handle interaction - click to a link with tooltip', function() { + spyOn(flowDb, 'setLink'); + const res = flow.parser.parse('graph TD\nA-->B\nclick A "click.html" "tooltip"'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(flowDb.setLink).toHaveBeenCalledWith('A', 'click.html', 'tooltip'); + }); + }); + + describe('it should multi directional arrows', function() { + describe('point', function() { + it('should handle double edged nodes and edges', function() { + const res = flow.parser.parse('graph TD;\nA<-->B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['A'].id).toBe('A'); + expect(vert['B'].id).toBe('B'); + expect(edges.length).toBe(1); + expect(edges[0].start).toBe('A'); + expect(edges[0].end).toBe('B'); + expect(edges[0].type).toBe('double_arrow_point'); + expect(edges[0].text).toBe(''); + }); + it('should handle double edged nodes with text', function() { + const res = flow.parser.parse('graph TD;\nA<-- text -->B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['A'].id).toBe('A'); + expect(vert['B'].id).toBe('B'); + expect(edges.length).toBe(1); + expect(edges[0].start).toBe('A'); + expect(edges[0].end).toBe('B'); + expect(edges[0].type).toBe('double_arrow_point'); + expect(edges[0].stroke).toBe('normal'); + expect(edges[0].text).toBe('text'); + }); + it('should handle double edged nodes and edges on thick arrows', function() { + const res = flow.parser.parse('graph TD;\nA<==>B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['A'].id).toBe('A'); + expect(vert['B'].id).toBe('B'); + expect(edges.length).toBe(1); + expect(edges[0].start).toBe('A'); + expect(edges[0].end).toBe('B'); + expect(edges[0].type).toBe('double_arrow_point'); + expect(edges[0].stroke).toBe('thick'); + expect(edges[0].text).toBe(''); + }); + it('should handle double edged nodes with text on thick arrows', function() { + const res = flow.parser.parse('graph TD;\nA<== text ==>B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['A'].id).toBe('A'); + expect(vert['B'].id).toBe('B'); + expect(edges.length).toBe(1); + expect(edges[0].start).toBe('A'); + expect(edges[0].end).toBe('B'); + expect(edges[0].type).toBe('double_arrow_point'); + expect(edges[0].stroke).toBe('thick'); + expect(edges[0].text).toBe('text'); + }); + it('should handle double edged nodes and edges on dotted arrows', function() { + const res = flow.parser.parse('graph TD;\nA<-.->B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['A'].id).toBe('A'); + expect(vert['B'].id).toBe('B'); + expect(edges.length).toBe(1); + expect(edges[0].start).toBe('A'); + expect(edges[0].end).toBe('B'); + expect(edges[0].type).toBe('double_arrow_point'); + expect(edges[0].stroke).toBe('dotted'); + expect(edges[0].text).toBe(''); + }); + it('should handle double edged nodes with text on dotted arrows', function() { + const res = flow.parser.parse('graph TD;\nA<-. text .->B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['A'].id).toBe('A'); + expect(vert['B'].id).toBe('B'); + expect(edges.length).toBe(1); + expect(edges[0].start).toBe('A'); + expect(edges[0].end).toBe('B'); + expect(edges[0].type).toBe('double_arrow_point'); + expect(edges[0].stroke).toBe('dotted'); + expect(edges[0].text).toBe('text'); + }); + }); + describe('cross', function() { + it('should handle double edged nodes and edges', function() { + const res = flow.parser.parse('graph TD;\nA x--x B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['A'].id).toBe('A'); + expect(vert['B'].id).toBe('B'); + expect(edges.length).toBe(1); + expect(edges[0].start).toBe('A'); + expect(edges[0].end).toBe('B'); + expect(edges[0].type).toBe('double_arrow_cross'); + expect(edges[0].text).toBe(''); + }); + it('should handle double edged nodes with text', function() { + const res = flow.parser.parse('graph TD;\nA x-- text --x B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['A'].id).toBe('A'); + expect(vert['B'].id).toBe('B'); + expect(edges.length).toBe(1); + expect(edges[0].start).toBe('A'); + expect(edges[0].end).toBe('B'); + expect(edges[0].type).toBe('double_arrow_cross'); + expect(edges[0].stroke).toBe('normal'); + expect(edges[0].text).toBe('text'); + }); + it('should handle double edged nodes and edges on thick arrows', function() { + const res = flow.parser.parse('graph TD;\nA x==x B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['A'].id).toBe('A'); + expect(vert['B'].id).toBe('B'); + expect(edges.length).toBe(1); + expect(edges[0].start).toBe('A'); + expect(edges[0].end).toBe('B'); + expect(edges[0].type).toBe('double_arrow_cross'); + expect(edges[0].stroke).toBe('thick'); + expect(edges[0].text).toBe(''); + }); + it('should handle double edged nodes with text on thick arrows', function() { + const res = flow.parser.parse('graph TD;\nA x== text ==x B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['A'].id).toBe('A'); + expect(vert['B'].id).toBe('B'); + expect(edges.length).toBe(1); + expect(edges[0].start).toBe('A'); + expect(edges[0].end).toBe('B'); + expect(edges[0].type).toBe('double_arrow_cross'); + expect(edges[0].stroke).toBe('thick'); + expect(edges[0].text).toBe('text'); + }); + it('should handle double edged nodes and edges on dotted arrows', function() { + const res = flow.parser.parse('graph TD;\nA x-.-x B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['A'].id).toBe('A'); + expect(vert['B'].id).toBe('B'); + expect(edges.length).toBe(1); + expect(edges[0].start).toBe('A'); + expect(edges[0].end).toBe('B'); + expect(edges[0].type).toBe('double_arrow_cross'); + expect(edges[0].stroke).toBe('dotted'); + expect(edges[0].text).toBe(''); + }); + it('should handle double edged nodes with text on dotted arrows', function() { + const res = flow.parser.parse('graph TD;\nA x-. text .-x B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['A'].id).toBe('A'); + expect(vert['B'].id).toBe('B'); + expect(edges.length).toBe(1); + expect(edges[0].start).toBe('A'); + expect(edges[0].end).toBe('B'); + expect(edges[0].type).toBe('double_arrow_cross'); + expect(edges[0].stroke).toBe('dotted'); + expect(edges[0].text).toBe('text'); + }); + }); + describe('circle', function() { + it('should handle double edged nodes and edges', function() { + const res = flow.parser.parse('graph TD;\nA o--o B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['A'].id).toBe('A'); + expect(vert['B'].id).toBe('B'); + expect(edges.length).toBe(1); + expect(edges[0].start).toBe('A'); + expect(edges[0].end).toBe('B'); + expect(edges[0].type).toBe('double_arrow_circle'); + expect(edges[0].text).toBe(''); + }); + it('should handle double edged nodes with text', function() { + const res = flow.parser.parse('graph TD;\nA o-- text --o B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['A'].id).toBe('A'); + expect(vert['B'].id).toBe('B'); + expect(edges.length).toBe(1); + expect(edges[0].start).toBe('A'); + expect(edges[0].end).toBe('B'); + expect(edges[0].type).toBe('double_arrow_circle'); + expect(edges[0].stroke).toBe('normal'); + expect(edges[0].text).toBe('text'); + }); + it('should handle double edged nodes and edges on thick arrows', function() { + const res = flow.parser.parse('graph TD;\nA o==o B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['A'].id).toBe('A'); + expect(vert['B'].id).toBe('B'); + expect(edges.length).toBe(1); + expect(edges[0].start).toBe('A'); + expect(edges[0].end).toBe('B'); + expect(edges[0].type).toBe('double_arrow_circle'); + expect(edges[0].stroke).toBe('thick'); + expect(edges[0].text).toBe(''); + }); + it('should handle double edged nodes with text on thick arrows', function() { + const res = flow.parser.parse('graph TD;\nA o== text ==o B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['A'].id).toBe('A'); + expect(vert['B'].id).toBe('B'); + expect(edges.length).toBe(1); + expect(edges[0].start).toBe('A'); + expect(edges[0].end).toBe('B'); + expect(edges[0].type).toBe('double_arrow_circle'); + expect(edges[0].stroke).toBe('thick'); + expect(edges[0].text).toBe('text'); + }); + it('should handle double edged nodes and edges on dotted arrows', function() { + const res = flow.parser.parse('graph TD;\nA o-.-o B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['A'].id).toBe('A'); + expect(vert['B'].id).toBe('B'); + expect(edges.length).toBe(1); + expect(edges[0].start).toBe('A'); + expect(edges[0].end).toBe('B'); + expect(edges[0].type).toBe('double_arrow_circle'); + expect(edges[0].stroke).toBe('dotted'); + expect(edges[0].text).toBe(''); + }); + it('should handle double edged nodes with text on dotted arrows', function() { + const res = flow.parser.parse('graph TD;\nA o-. text .-o B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['A'].id).toBe('A'); + expect(vert['B'].id).toBe('B'); + expect(edges.length).toBe(1); + expect(edges[0].start).toBe('A'); + expect(edges[0].end).toBe('B'); + expect(edges[0].type).toBe('double_arrow_circle'); + expect(edges[0].stroke).toBe('dotted'); + expect(edges[0].text).toBe('text'); + }); + }); + }); + describe('it should handle text on edges', function() { + it('it should handle text without space', function() { + const res = flow.parser.parse('graph TD;A--x|textNoSpace|B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(edges[0].type).toBe('arrow_cross'); + }); + + it('should handle with space', function() { + const res = flow.parser.parse('graph TD;A--x|text including space|B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(edges[0].type).toBe('arrow_cross'); + }); + + it('it should handle text with /', function() { + const res = flow.parser.parse('graph TD;A--x|text with / should work|B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(edges[0].text).toBe('text with / should work'); + }); + + it('it should handle space and space between vertices and link', function() { + const res = flow.parser.parse('graph TD;A --x|textNoSpace| B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(edges[0].type).toBe('arrow_cross'); + }); + + it('should handle space and CAPS', function() { + const res = flow.parser.parse('graph TD;A--x|text including CAPS space|B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(edges[0].type).toBe('arrow_cross'); + }); + + it('should handle space and dir', function() { + const res = flow.parser.parse('graph TD;A--x|text including URL space|B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(edges[0].type).toBe('arrow_cross'); + expect(edges[0].text).toBe('text including URL space'); + }); + + it('should handle space and send', function() { + const res = flow.parser.parse('graph TD;A--text including URL space and send-->B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(edges[0].type).toBe('arrow'); + expect(edges[0].text).toBe('text including URL space and send'); + }); + it('should handle space and send', function() { + const res = flow.parser.parse('graph TD;A-- text including URL space and send -->B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(edges[0].type).toBe('arrow'); + expect(edges[0].text).toBe('text including URL space and send'); + }); + + it('should handle space and dir (TD)', function() { + const res = flow.parser.parse('graph TD;A--x|text including R TD space|B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(edges[0].type).toBe('arrow_cross'); + expect(edges[0].text).toBe('text including R TD space'); + }); + it('should handle `', function() { + const res = flow.parser.parse('graph TD;A--x|text including `|B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(edges[0].type).toBe('arrow_cross'); + expect(edges[0].text).toBe('text including `'); + }); + it('should handle v in node ids only v', function() { + // only v + const res = flow.parser.parse('graph TD;A--xv(my text);'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(edges[0].type).toBe('arrow_cross'); + expect(vert['v'].text).toBe('my text'); + }); + it('should handle v in node ids v at end', function() { + // v at end + const res = flow.parser.parse('graph TD;A--xcsv(my text);'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(edges[0].type).toBe('arrow_cross'); + expect(vert['csv'].text).toBe('my text'); + }); + it('should handle v in node ids v in middle', function() { + // v in middle + const res = flow.parser.parse('graph TD;A--xava(my text);'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(edges[0].type).toBe('arrow_cross'); + expect(vert['ava'].text).toBe('my text'); + }); + it('should handle v in node ids, v at start', function() { + // v at start + const res = flow.parser.parse('graph TD;A--xva(my text);'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(edges[0].type).toBe('arrow_cross'); + expect(vert['va'].text).toBe('my text'); + }); + it('should handle keywords', function() { + const res = flow.parser.parse('graph TD;A--x|text including graph space|B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(edges[0].text).toBe('text including graph space'); + }); + it('should handle keywords', function() { + const res = flow.parser.parse('graph TD;V-->a[v]'); + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + expect(vert['a'].text).toBe('v'); + }); + it('should handle keywords', function() { + const res = flow.parser.parse('graph TD;V-->a[v]'); + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + expect(vert['a'].text).toBe('v'); + }); + it('should handle quoted text', function() { + const res = flow.parser.parse('graph TD;V-- "test string()" -->a[v]'); + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + expect(edges[0].text).toBe('test string()'); + }); + }); + + describe('it should handle new line type notation', function() { + it('it should handle regular lines', function() { + const res = flow.parser.parse('graph TD;A-->B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(edges[0].stroke).toBe('normal'); + }); + it('it should handle dotted lines', function() { + const res = flow.parser.parse('graph TD;A-.->B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(edges[0].stroke).toBe('dotted'); + }); + it('it should handle dotted lines', function() { + const res = flow.parser.parse('graph TD;A==>B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(edges[0].stroke).toBe('thick'); + }); + it('it should handle text on lines', function() { + const res = flow.parser.parse('graph TD;A-- test text with == -->B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(edges[0].stroke).toBe('normal'); + }); + it('it should handle text on lines', function() { + const res = flow.parser.parse('graph TD;A-. test text with == .->B;'); - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); - expect(edges[0].stroke).toBe('dotted') - }) - it('it should handle text on lines', function () { - const res = flow.parser.parse('graph TD;A== test text with - ==>B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(edges[0].stroke).toBe('thick') - }) - }) - - describe('it should handle text on edges using the new notation', function () { - it('it should handle text without space', function () { - const res = flow.parser.parse('graph TD;A-- textNoSpace --xB;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(edges[0].type).toBe('arrow_cross') - }) - - it('it should handle text with multiple leading space', function () { - const res = flow.parser.parse('graph TD;A-- textNoSpace --xB;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(edges[0].type).toBe('arrow_cross') - }) - - it('should handle with space', function () { - const res = flow.parser.parse('graph TD;A-- text including space --xB;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(edges[0].type).toBe('arrow_cross') - }) - - it('it should handle text with /', function () { - const res = flow.parser.parse('graph TD;A -- text with / should work --x B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(edges[0].text).toBe('text with / should work') - }) - - it('it should handle space and space between vertices and link', function () { - const res = flow.parser.parse('graph TD;A -- textNoSpace --x B;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(edges[0].type).toBe('arrow_cross') - }) - - it('should handle space and CAPS', function () { - const res = flow.parser.parse('graph TD;A-- text including CAPS space --xB;') + expect(edges[0].stroke).toBe('dotted'); + }); + it('it should handle text on lines', function() { + const res = flow.parser.parse('graph TD;A== test text with - ==>B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(edges[0].stroke).toBe('thick'); + }); + }); + + describe('it should handle text on edges using the new notation', function() { + it('it should handle text without space', function() { + const res = flow.parser.parse('graph TD;A-- textNoSpace --xB;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(edges[0].type).toBe('arrow_cross'); + }); + + it('it should handle text with multiple leading space', function() { + const res = flow.parser.parse('graph TD;A-- textNoSpace --xB;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(edges[0].type).toBe('arrow_cross'); + }); + + it('should handle with space', function() { + const res = flow.parser.parse('graph TD;A-- text including space --xB;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(edges[0].type).toBe('arrow_cross'); + }); + + it('it should handle text with /', function() { + const res = flow.parser.parse('graph TD;A -- text with / should work --x B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(edges[0].text).toBe('text with / should work'); + }); + + it('it should handle space and space between vertices and link', function() { + const res = flow.parser.parse('graph TD;A -- textNoSpace --x B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(edges[0].type).toBe('arrow_cross'); + }); + + it('should handle space and CAPS', function() { + const res = flow.parser.parse('graph TD;A-- text including CAPS space --xB;'); - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); - expect(edges[0].type).toBe('arrow_cross') - }) + expect(edges[0].type).toBe('arrow_cross'); + }); - it('should handle space and dir', function () { - const res = flow.parser.parse('graph TD;A-- text including URL space --xB;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() + it('should handle space and dir', function() { + const res = flow.parser.parse('graph TD;A-- text including URL space --xB;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); - expect(edges[0].type).toBe('arrow_cross') - expect(edges[0].text).toBe('text including URL space') - }) - - it('should handle space and dir (TD)', function () { - const res = flow.parser.parse('graph TD;A-- text including R TD space --xB;') + expect(edges[0].type).toBe('arrow_cross'); + expect(edges[0].text).toBe('text including URL space'); + }); + + it('should handle space and dir (TD)', function() { + const res = flow.parser.parse('graph TD;A-- text including R TD space --xB;'); - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); - expect(edges[0].type).toBe('arrow_cross') - expect(edges[0].text).toBe('text including R TD space') - }) - it('should handle keywords', function () { - const res = flow.parser.parse('graph TD;A-- text including graph space and v --xB;') + expect(edges[0].type).toBe('arrow_cross'); + expect(edges[0].text).toBe('text including R TD space'); + }); + it('should handle keywords', function() { + const res = flow.parser.parse('graph TD;A-- text including graph space and v --xB;'); - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); - expect(edges[0].text).toBe('text including graph space and v') - }) - it('should handle keywords', function () { - const res = flow.parser.parse('graph TD;A-- text including graph space and v --xB[blav]') + expect(edges[0].text).toBe('text including graph space and v'); + }); + it('should handle keywords', function() { + const res = flow.parser.parse('graph TD;A-- text including graph space and v --xB[blav]'); - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); - expect(edges[0].text).toBe('text including graph space and v') - }) - // xit('should handle text on open links',function(){ - // const res = flow.parser.parse('graph TD;A-- text including graph space --B'); - // - // const vert = flow.parser.yy.getVertices(); - // const edges = flow.parser.yy.getEdges(); - // - // expect(edges[0].text).toBe('text including graph space'); - // - // }); - }) + expect(edges[0].text).toBe('text including graph space and v'); + }); + // xit('should handle text on open links',function(){ + // const res = flow.parser.parse('graph TD;A-- text including graph space --B'); + // + // const vert = flow.parser.yy.getVertices(); + // const edges = flow.parser.yy.getEdges(); + // + // expect(edges[0].text).toBe('text including graph space'); + // + // }); + }); - it('should handle multi-line text', function () { - const res = flow.parser.parse('graph TD;A--o|text space|B;\n B-->|more text with space|C;') + it('should handle multi-line text', function() { + const res = flow.parser.parse('graph TD;A--o|text space|B;\n B-->|more text with space|C;'); - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); - expect(edges[0].type).toBe('arrow_circle') - expect(edges[1].type).toBe('arrow') - expect(vert['A'].id).toBe('A') - expect(vert['B'].id).toBe('B') - expect(vert['C'].id).toBe('C') - expect(edges.length).toBe(2) - expect(edges[0].start).toBe('A') - expect(edges[0].end).toBe('B') - // expect(edges[0].text).toBe('text space'); - expect(edges[1].start).toBe('B') - expect(edges[1].end).toBe('C') - expect(edges[1].text).toBe('more text with space') - }) + expect(edges[0].type).toBe('arrow_circle'); + expect(edges[1].type).toBe('arrow'); + expect(vert['A'].id).toBe('A'); + expect(vert['B'].id).toBe('B'); + expect(vert['C'].id).toBe('C'); + expect(edges.length).toBe(2); + expect(edges[0].start).toBe('A'); + expect(edges[0].end).toBe('B'); + // expect(edges[0].text).toBe('text space'); + expect(edges[1].start).toBe('B'); + expect(edges[1].end).toBe('C'); + expect(edges[1].text).toBe('more text with space'); + }); - it('should handle multiple edges', function () { - const res = flow.parser.parse('graph TD;A---|This is the 123 s text|B;\nA---|This is the second edge|B;') - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() + it('should handle multiple edges', function() { + const res = flow.parser.parse( + 'graph TD;A---|This is the 123 s text|B;\nA---|This is the second edge|B;' + ); + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); - expect(vert['A'].id).toBe('A') - expect(vert['B'].id).toBe('B') - expect(edges.length).toBe(2) - expect(edges[0].start).toBe('A') - expect(edges[0].end).toBe('B') - expect(edges[0].text).toBe('This is the 123 s text') - expect(edges[1].start).toBe('A') - expect(edges[1].end).toBe('B') - expect(edges[1].text).toBe('This is the second edge') - }) + expect(vert['A'].id).toBe('A'); + expect(vert['B'].id).toBe('B'); + expect(edges.length).toBe(2); + expect(edges[0].start).toBe('A'); + expect(edges[0].end).toBe('B'); + expect(edges[0].text).toBe('This is the 123 s text'); + expect(edges[1].start).toBe('A'); + expect(edges[1].end).toBe('B'); + expect(edges[1].text).toBe('This is the second edge'); + }); + + it('should handle text in vertices with space', function() { + const res = flow.parser.parse('graph TD;A[chimpansen hoppar]-->C;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['A'].type).toBe('square'); + expect(vert['A'].text).toBe('chimpansen hoppar'); + }); + + it('should handle text in vertices with space with spaces between vertices and link', function() { + const res = flow.parser.parse('graph TD;A[chimpansen hoppar] --> C;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['A'].type).toBe('square'); + expect(vert['A'].text).toBe('chimpansen hoppar'); + }); + it('should handle text including _ in vertices', function() { + const res = flow.parser.parse('graph TD;A[chimpansen_hoppar] --> C;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['A'].type).toBe('square'); + expect(vert['A'].text).toBe('chimpansen_hoppar'); + }); + + it('should handle quoted text in vertices ', function() { + const res = flow.parser.parse('graph TD;A["chimpansen hoppar ()[]"] --> C;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['A'].type).toBe('square'); + expect(vert['A'].text).toBe('chimpansen hoppar ()[]'); + }); + + it('should handle text in circle vertices with space', function() { + const res = flow.parser.parse('graph TD;A((chimpansen hoppar))-->C;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['A'].type).toBe('circle'); + expect(vert['A'].text).toBe('chimpansen hoppar'); + }); + + it('should handle text in ellipse vertices', function() { + const res = flow.parser.parse('graph TD\nA(-this is an ellipse-)-->B'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['A'].type).toBe('ellipse'); + expect(vert['A'].text).toBe('this is an ellipse'); + }); + + it('should handle text in diamond vertices with space', function() { + const res = flow.parser.parse('graph TD;A(chimpansen hoppar)-->C;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['A'].type).toBe('round'); + expect(vert['A'].text).toBe('chimpansen hoppar'); + }); + + it('should handle text in with ?', function() { + const res = flow.parser.parse('graph TD;A(?)-->|?|C;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['A'].text).toBe('?'); + expect(edges[0].text).toBe('?'); + }); + it('should handle text in with éèêàçô', function() { + const res = flow.parser.parse('graph TD;A(éèêàçô)-->|éèêàçô|C;'); - it('should handle text in vertices with space', function () { - const res = flow.parser.parse('graph TD;A[chimpansen hoppar]-->C;') + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['A'].text).toBe('éèêàçô'); + expect(edges[0].text).toBe('éèêàçô'); + }); - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() + it('should handle text in with ,.?!+-*', function() { + const res = flow.parser.parse('graph TD;A(,.?!+-*)-->|,.?!+-*|C;'); - expect(vert['A'].type).toBe('square') - expect(vert['A'].text).toBe('chimpansen hoppar') - }) - - it('should handle text in vertices with space with spaces between vertices and link', function () { - const res = flow.parser.parse('graph TD;A[chimpansen hoppar] --> C;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(vert['A'].type).toBe('square') - expect(vert['A'].text).toBe('chimpansen hoppar') - }) - it('should handle text including _ in vertices', function () { - const res = flow.parser.parse('graph TD;A[chimpansen_hoppar] --> C;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(vert['A'].type).toBe('square') - expect(vert['A'].text).toBe('chimpansen_hoppar') - }) - - it('should handle quoted text in vertices ', function () { - const res = flow.parser.parse('graph TD;A["chimpansen hoppar ()[]"] --> C;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(vert['A'].type).toBe('square') - expect(vert['A'].text).toBe('chimpansen hoppar ()[]') - }) - - it('should handle text in circle vertices with space', function () { - const res = flow.parser.parse('graph TD;A((chimpansen hoppar))-->C;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(vert['A'].type).toBe('circle') - expect(vert['A'].text).toBe('chimpansen hoppar') - }) - - it('should handle text in ellipse vertices', function () { - const res = flow.parser.parse('graph TD\nA(-this is an ellipse-)-->B') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(vert['A'].type).toBe('ellipse') - expect(vert['A'].text).toBe('this is an ellipse') - }) - - it('should handle text in diamond vertices with space', function () { - const res = flow.parser.parse('graph TD;A(chimpansen hoppar)-->C;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(vert['A'].type).toBe('round') - expect(vert['A'].text).toBe('chimpansen hoppar') - }) - - it('should handle text in with ?', function () { - const res = flow.parser.parse('graph TD;A(?)-->|?|C;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(vert['A'].text).toBe('?') - expect(edges[0].text).toBe('?') - }) - it('should handle text in with éèêàçô', function () { - const res = flow.parser.parse('graph TD;A(éèêàçô)-->|éèêàçô|C;') + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() + expect(vert['A'].text).toBe(',.?!+-*'); + expect(edges[0].text).toBe(',.?!+-*'); + }); - expect(vert['A'].text).toBe('éèêàçô') - expect(edges[0].text).toBe('éèêàçô') - }) + describe('it should handle text in vertices, ', function() { + it('it should handle space', function() { + const res = flow.parser.parse('graph TD;A-->C(Chimpansen hoppar);'); - it('should handle text in with ,.?!+-*', function () { - const res = flow.parser.parse('graph TD;A(,.?!+-*)-->|,.?!+-*|C;') + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() + expect(vert['C'].type).toBe('round'); + expect(vert['C'].text).toBe('Chimpansen hoppar'); + }); + it('it should handle åäö and minus', function() { + const res = flow.parser.parse('graph TD;A-->C{Chimpansen hoppar åäö-ÅÄÖ};'); - expect(vert['A'].text).toBe(',.?!+-*') - expect(edges[0].text).toBe(',.?!+-*') - }) + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); - describe('it should handle text in vertices, ', function () { - it('it should handle space', function () { - const res = flow.parser.parse('graph TD;A-->C(Chimpansen hoppar);') + expect(vert['C'].type).toBe('diamond'); + expect(vert['C'].text).toBe('Chimpansen hoppar åäö-ÅÄÖ'); + }); - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() + it('it should handle with åäö, minus and space and br', function() { + const res = flow.parser.parse('graph TD;A-->C(Chimpansen hoppar åäö
- ÅÄÖ);'); - expect(vert['C'].type).toBe('round') - expect(vert['C'].text).toBe('Chimpansen hoppar') - }) - it('it should handle åäö and minus', function () { - const res = flow.parser.parse('graph TD;A-->C{Chimpansen hoppar åäö-ÅÄÖ};') + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(vert['C'].type).toBe('diamond') - expect(vert['C'].text).toBe('Chimpansen hoppar åäö-ÅÄÖ') - }) - - it('it should handle with åäö, minus and space and br', function () { - const res = flow.parser.parse('graph TD;A-->C(Chimpansen hoppar åäö
- ÅÄÖ);') + expect(vert['C'].type).toBe('round'); + expect(vert['C'].text).toBe('Chimpansen hoppar åäö
- ÅÄÖ'); + }); + // xit('it should handle åäö, minus and space and br',function(){ + // const res = flow.parser.parse('graph TD; A[Object(foo,bar)]-->B(Thing);'); + // + // const vert = flow.parser.yy.getVertices(); + // const edges = flow.parser.yy.getEdges(); + // + // expect(vert['C'].type).toBe('round'); + // expect(vert['C'].text).toBe(' A[Object(foo,bar)]-->B(Thing);'); + // }); + it('it should handle unicode chars', function() { + const res = flow.parser.parse('graph TD;A-->C(Начало);'); - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(vert['C'].type).toBe('round') - expect(vert['C'].text).toBe('Chimpansen hoppar åäö
- ÅÄÖ') - }) - // xit('it should handle åäö, minus and space and br',function(){ - // const res = flow.parser.parse('graph TD; A[Object(foo,bar)]-->B(Thing);'); - // - // const vert = flow.parser.yy.getVertices(); - // const edges = flow.parser.yy.getEdges(); - // - // expect(vert['C'].type).toBe('round'); - // expect(vert['C'].text).toBe(' A[Object(foo,bar)]-->B(Thing);'); - // }); - it('it should handle unicode chars', function () { - const res = flow.parser.parse('graph TD;A-->C(Начало);') - - const vert = flow.parser.yy.getVertices() - - expect(vert['C'].text).toBe('Начало') - }) - it('it should handle backslask', function () { - const res = flow.parser.parse('graph TD;A-->C(c:\\windows);') - - const vert = flow.parser.yy.getVertices() - - expect(vert['C'].text).toBe('c:\\windows') - }) - it('it should handle CAPS', function () { - const res = flow.parser.parse('graph TD;A-->C(some CAPS);') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(vert['C'].type).toBe('round') - expect(vert['C'].text).toBe('some CAPS') - }) - it('it should handle directions', function () { - const res = flow.parser.parse('graph TD;A-->C(some URL);') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(vert['C'].type).toBe('round') - expect(vert['C'].text).toBe('some URL') - }) - }) - - it('should handle a single node', function () { - // Silly but syntactically correct - const res = flow.parser.parse('graph TD;A;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(edges.length).toBe(0) - expect(vert['A'].styles.length).toBe(0) - }) - - it('should handle a single square node', function () { - // Silly but syntactically correct - const res = flow.parser.parse('graph TD;a[A];') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(edges.length).toBe(0) - expect(vert['a'].styles.length).toBe(0) - expect(vert['a'].type).toBe('square') - }) - it('should handle a single round square node', function () { - // Silly but syntactically correct - const res = flow.parser.parse('graph TD;a[A];') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(edges.length).toBe(0) - expect(vert['a'].styles.length).toBe(0) - expect(vert['a'].type).toBe('square') - }) - it('should handle a single circle node', function () { - // Silly but syntactically correct - const res = flow.parser.parse('graph TD;a((A));') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(edges.length).toBe(0) - expect(vert['a'].type).toBe('circle') - }) - it('should handle a single round node', function () { - // Silly but syntactically correct - const res = flow.parser.parse('graph TD;a(A);') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(edges.length).toBe(0) - expect(vert['a'].type).toBe('round') - }) - it('should handle a single odd node', function () { - // Silly but syntactically correct - const res = flow.parser.parse('graph TD;a>A];') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(edges.length).toBe(0) - expect(vert['a'].type).toBe('odd') - }) - it('should handle a single diamond node', function () { - // Silly but syntactically correct - const res = flow.parser.parse('graph TD;a{A};') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(edges.length).toBe(0) - expect(vert['a'].type).toBe('diamond') - }) - it('should handle a single diamond node with html in it', function () { - // Silly but syntactically correct - const res = flow.parser.parse('graph TD;a{A
end};') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(edges.length).toBe(0) - expect(vert['a'].type).toBe('diamond') - expect(vert['a'].text).toBe('A
end') - }) - it('should handle a single round node with html in it', function () { - // Silly but syntactically correct - const res = flow.parser.parse('graph TD;a(A
end);') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(edges.length).toBe(0) - expect(vert['a'].type).toBe('round') - expect(vert['a'].text).toBe('A
end') - }) - it('should handle a single node with alphanumerics starting on a char', function () { - // Silly but syntactically correct - const res = flow.parser.parse('graph TD;id1;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(edges.length).toBe(0) - expect(vert['id1'].styles.length).toBe(0) - }) - it('should handle a single node with a single digit', function () { + const vert = flow.parser.yy.getVertices(); + + expect(vert['C'].text).toBe('Начало'); + }); + it('it should handle backslask', function() { + const res = flow.parser.parse('graph TD;A-->C(c:\\windows);'); + + const vert = flow.parser.yy.getVertices(); + + expect(vert['C'].text).toBe('c:\\windows'); + }); + it('it should handle CAPS', function() { + const res = flow.parser.parse('graph TD;A-->C(some CAPS);'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['C'].type).toBe('round'); + expect(vert['C'].text).toBe('some CAPS'); + }); + it('it should handle directions', function() { + const res = flow.parser.parse('graph TD;A-->C(some URL);'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['C'].type).toBe('round'); + expect(vert['C'].text).toBe('some URL'); + }); + }); + + it('should handle a single node', function() { // Silly but syntactically correct - const res = flow.parser.parse('graph TD;1;') + const res = flow.parser.parse('graph TD;A;'); - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); - expect(edges.length).toBe(0) - expect(vert['s1'].text).toBe('1') - }) - it('should handle a single node with a single digit in a subgraph', function () { + expect(edges.length).toBe(0); + expect(vert['A'].styles.length).toBe(0); + }); + + it('should handle a single square node', function() { + // Silly but syntactically correct + const res = flow.parser.parse('graph TD;a[A];'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(edges.length).toBe(0); + expect(vert['a'].styles.length).toBe(0); + expect(vert['a'].type).toBe('square'); + }); + it('should handle a single round square node', function() { + // Silly but syntactically correct + const res = flow.parser.parse('graph TD;a[A];'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(edges.length).toBe(0); + expect(vert['a'].styles.length).toBe(0); + expect(vert['a'].type).toBe('square'); + }); + it('should handle a single circle node', function() { + // Silly but syntactically correct + const res = flow.parser.parse('graph TD;a((A));'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(edges.length).toBe(0); + expect(vert['a'].type).toBe('circle'); + }); + it('should handle a single round node', function() { + // Silly but syntactically correct + const res = flow.parser.parse('graph TD;a(A);'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(edges.length).toBe(0); + expect(vert['a'].type).toBe('round'); + }); + it('should handle a single odd node', function() { + // Silly but syntactically correct + const res = flow.parser.parse('graph TD;a>A];'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(edges.length).toBe(0); + expect(vert['a'].type).toBe('odd'); + }); + it('should handle a single diamond node', function() { + // Silly but syntactically correct + const res = flow.parser.parse('graph TD;a{A};'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(edges.length).toBe(0); + expect(vert['a'].type).toBe('diamond'); + }); + it('should handle a single diamond node with html in it', function() { + // Silly but syntactically correct + const res = flow.parser.parse('graph TD;a{A
end};'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(edges.length).toBe(0); + expect(vert['a'].type).toBe('diamond'); + expect(vert['a'].text).toBe('A
end'); + }); + it('should handle a single round node with html in it', function() { + // Silly but syntactically correct + const res = flow.parser.parse('graph TD;a(A
end);'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(edges.length).toBe(0); + expect(vert['a'].type).toBe('round'); + expect(vert['a'].text).toBe('A
end'); + }); + it('should handle a single node with alphanumerics starting on a char', function() { + // Silly but syntactically correct + const res = flow.parser.parse('graph TD;id1;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(edges.length).toBe(0); + expect(vert['id1'].styles.length).toBe(0); + }); + it('should handle a single node with a single digit', function() { + // Silly but syntactically correct + const res = flow.parser.parse('graph TD;1;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(edges.length).toBe(0); + expect(vert['s1'].text).toBe('1'); + }); + it('should handle a single node with a single digit in a subgraph', function() { // Silly but syntactically correct - const res = flow.parser.parse('graph TD;subgraph "hello";1;end;') + const res = flow.parser.parse('graph TD;subgraph "hello";1;end;'); - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); - expect(edges.length).toBe(0) - expect(vert['s1'].text).toBe('1') - }) - it('should handle a single node with alphanumerics starting on a num', function () { - // Silly but syntactically correct - const res = flow.parser.parse('graph TD;1id;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(edges.length).toBe(0) - expect(vert['s1id'].styles.length).toBe(0) - }) - it('should handle a single node with alphanumerics containing a minus sign', function () { - // Silly but syntactically correct - const res = flow.parser.parse('graph TD;i-d;') - - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() - - expect(edges.length).toBe(0) - expect(vert['i-d'].styles.length).toBe(0) - }) - it('should handle a single node with alphanumerics containing a underscore sign', function () { + expect(edges.length).toBe(0); + expect(vert['s1'].text).toBe('1'); + }); + it('should handle a single node with alphanumerics starting on a num', function() { // Silly but syntactically correct - const res = flow.parser.parse('graph TD;i_d;') + const res = flow.parser.parse('graph TD;1id;'); - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); - expect(edges.length).toBe(0) - expect(vert['i_d'].styles.length).toBe(0) - }) + expect(edges.length).toBe(0); + expect(vert['s1id'].styles.length).toBe(0); + }); + it('should handle a single node with alphanumerics containing a minus sign', function() { + // Silly but syntactically correct + const res = flow.parser.parse('graph TD;i-d;'); - // log.debug(flow.parser.parse('graph TD;style Q background:#fff;')); - it('should handle styles for vertices', function () { - const res = flow.parser.parse('graph TD;style Q background:#fff;') + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() + expect(edges.length).toBe(0); + expect(vert['i-d'].styles.length).toBe(0); + }); + it('should handle a single node with alphanumerics containing a underscore sign', function() { + // Silly but syntactically correct + const res = flow.parser.parse('graph TD;i_d;'); - const style = vert['Q'].styles[0] + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); - expect(vert['Q'].styles.length).toBe(1) - expect(vert['Q'].styles[0]).toBe('background:#fff') - }) + expect(edges.length).toBe(0); + expect(vert['i_d'].styles.length).toBe(0); + }); - // log.debug(flow.parser.parse('graph TD;style Q background:#fff;')); - it('should handle styles for edges', function () { - const res = flow.parser.parse('graph TD;a-->b;\nstyle #0 stroke: #f66;') + // log.debug(flow.parser.parse('graph TD;style Q background:#fff;')); + it('should handle styles for vertices', function() { + const res = flow.parser.parse('graph TD;style Q background:#fff;'); - const edges = flow.parser.yy.getEdges() + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); - expect(edges.length).toBe(1) - }) + const style = vert['Q'].styles[0]; - it('should handle multiple styles for a vortex', function () { - const res = flow.parser.parse('graph TD;style R background:#fff,border:1px solid red;') + expect(vert['Q'].styles.length).toBe(1); + expect(vert['Q'].styles[0]).toBe('background:#fff'); + }); - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() + // log.debug(flow.parser.parse('graph TD;style Q background:#fff;')); + it('should handle styles for edges', function() { + const res = flow.parser.parse('graph TD;a-->b;\nstyle #0 stroke: #f66;'); - expect(vert['R'].styles.length).toBe(2) - expect(vert['R'].styles[0]).toBe('background:#fff') - expect(vert['R'].styles[1]).toBe('border:1px solid red') - }) + const edges = flow.parser.yy.getEdges(); - it('should handle multiple styles in a graph', function () { - const res = flow.parser.parse('graph TD;style S background:#aaa;\nstyle T background:#bbb,border:1px solid red;') + expect(edges.length).toBe(1); + }); - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() + it('should handle multiple styles for a vortex', function() { + const res = flow.parser.parse('graph TD;style R background:#fff,border:1px solid red;'); - expect(vert['S'].styles.length).toBe(1) - expect(vert['T'].styles.length).toBe(2) - expect(vert['S'].styles[0]).toBe('background:#aaa') - expect(vert['T'].styles[0]).toBe('background:#bbb') - expect(vert['T'].styles[1]).toBe('border:1px solid red') - }) + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); - it('should handle styles and graph definitons in a graph', function () { - const res = flow.parser.parse('graph TD;S-->T;\nstyle S background:#aaa;\nstyle T background:#bbb,border:1px solid red;') + expect(vert['R'].styles.length).toBe(2); + expect(vert['R'].styles[0]).toBe('background:#fff'); + expect(vert['R'].styles[1]).toBe('border:1px solid red'); + }); - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() + it('should handle multiple styles in a graph', function() { + const res = flow.parser.parse( + 'graph TD;style S background:#aaa;\nstyle T background:#bbb,border:1px solid red;' + ); - expect(vert['S'].styles.length).toBe(1) - expect(vert['T'].styles.length).toBe(2) - expect(vert['S'].styles[0]).toBe('background:#aaa') - expect(vert['T'].styles[0]).toBe('background:#bbb') - expect(vert['T'].styles[1]).toBe('border:1px solid red') - }) - it('should handle styles and graph definitons in a graph', function () { - const res = flow.parser.parse('graph TD;style T background:#bbb,border:1px solid red;') - // const res = flow.parser.parse('graph TD;style T background: #bbb;'); + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); - const vert = flow.parser.yy.getVertices() + expect(vert['S'].styles.length).toBe(1); + expect(vert['T'].styles.length).toBe(2); + expect(vert['S'].styles[0]).toBe('background:#aaa'); + expect(vert['T'].styles[0]).toBe('background:#bbb'); + expect(vert['T'].styles[1]).toBe('border:1px solid red'); + }); - expect(vert['T'].styles.length).toBe(2) - expect(vert['T'].styles[0]).toBe('background:#bbb') - expect(vert['T'].styles[1]).toBe('border:1px solid red') - }) + it('should handle styles and graph definitons in a graph', function() { + const res = flow.parser.parse( + 'graph TD;S-->T;\nstyle S background:#aaa;\nstyle T background:#bbb,border:1px solid red;' + ); - describe('special characters should be be handled.', function () { - const charTest = function (char, result) { - const res = flow.parser.parse('graph TD;A(' + char + ')-->B;') + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() + expect(vert['S'].styles.length).toBe(1); + expect(vert['T'].styles.length).toBe(2); + expect(vert['S'].styles[0]).toBe('background:#aaa'); + expect(vert['T'].styles[0]).toBe('background:#bbb'); + expect(vert['T'].styles[1]).toBe('border:1px solid red'); + }); + it('should handle styles and graph definitons in a graph', function() { + const res = flow.parser.parse('graph TD;style T background:#bbb,border:1px solid red;'); + // const res = flow.parser.parse('graph TD;style T background: #bbb;'); - expect(vert['A'].id).toBe('A') - expect(vert['B'].id).toBe('B') - if(result){ - expect(vert['A'].text).toBe(result) - }else{ - expect(vert['A'].text).toBe(char) + const vert = flow.parser.yy.getVertices(); + + expect(vert['T'].styles.length).toBe(2); + expect(vert['T'].styles[0]).toBe('background:#bbb'); + expect(vert['T'].styles[1]).toBe('border:1px solid red'); + }); + + describe('special characters should be be handled.', function() { + const charTest = function(char, result) { + const res = flow.parser.parse('graph TD;A(' + char + ')-->B;'); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['A'].id).toBe('A'); + expect(vert['B'].id).toBe('B'); + if (result) { + expect(vert['A'].text).toBe(result); + } else { + expect(vert['A'].text).toBe(char); } - } + }; - it('it should be able to parse a \'.\'', function () { - charTest('.') - charTest('Start 103a.a1') - }) + it("it should be able to parse a '.'", function() { + charTest('.'); + charTest('Start 103a.a1'); + }); // it('it should be able to parse text containing \'_\'', function () { // charTest('_') // }) - it('it should be able to parse a \':\'', function () { - charTest(':') - }) + it("it should be able to parse a ':'", function() { + charTest(':'); + }); - it('it should be able to parse a \',\'', function () { - charTest(',') - }) + it("it should be able to parse a ','", function() { + charTest(','); + }); - it('it should be able to parse text containing \'-\'', function () { - charTest('a-b') - }) + it("it should be able to parse text containing '-'", function() { + charTest('a-b'); + }); - it('it should be able to parse a \'+\'', function () { - charTest('+') - }) + it("it should be able to parse a '+'", function() { + charTest('+'); + }); - it('it should be able to parse a \'*\'', function () { - charTest('*') - }) + it("it should be able to parse a '*'", function() { + charTest('*'); + }); - it('it should be able to parse a \'<\'', function () { - charTest('<','<') - }) + it("it should be able to parse a '<'", function() { + charTest('<', '<'); + }); - it('it should be able to parse a \'>\'', function () { - charTest('>','>') - }) + it("it should be able to parse a '>'", function() { + charTest('>', '>'); + }); - it('it should be able to parse a \'=\'', function () { - charTest('=','=') - }) - it('it should be able to parse a \'&\'', function () { - charTest('&') - }) - }) + it("it should be able to parse a '='", function() { + charTest('=', '='); + }); + it("it should be able to parse a '&'", function() { + charTest('&'); + }); + }); - it('should be possible to declare a class', function () { - const res = flow.parser.parse('graph TD;classDef exClass background:#bbb,border:1px solid red;') - // const res = flow.parser.parse('graph TD;style T background: #bbb;'); + it('should be possible to declare a class', function() { + const res = flow.parser.parse( + 'graph TD;classDef exClass background:#bbb,border:1px solid red;' + ); + // const res = flow.parser.parse('graph TD;style T background: #bbb;'); - const classes = flow.parser.yy.getClasses() + const classes = flow.parser.yy.getClasses(); - expect(classes['exClass'].styles.length).toBe(2) - expect(classes['exClass'].styles[0]).toBe('background:#bbb') - expect(classes['exClass'].styles[1]).toBe('border:1px solid red') - }) + expect(classes['exClass'].styles.length).toBe(2); + expect(classes['exClass'].styles[0]).toBe('background:#bbb'); + expect(classes['exClass'].styles[1]).toBe('border:1px solid red'); + }); - it('should be possible to declare a class with a dot in the style', function () { - const res = flow.parser.parse('graph TD;classDef exClass background:#bbb,border:1.5px solid red;') - // const res = flow.parser.parse('graph TD;style T background: #bbb;'); + it('should be possible to declare a class with a dot in the style', function() { + const res = flow.parser.parse( + 'graph TD;classDef exClass background:#bbb,border:1.5px solid red;' + ); + // const res = flow.parser.parse('graph TD;style T background: #bbb;'); - const classes = flow.parser.yy.getClasses() + const classes = flow.parser.yy.getClasses(); - expect(classes['exClass'].styles.length).toBe(2) - expect(classes['exClass'].styles[0]).toBe('background:#bbb') - expect(classes['exClass'].styles[1]).toBe('border:1.5px solid red') - }) - it('should be possible to declare a class with a space in the style', function () { - const res = flow.parser.parse('graph TD;classDef exClass background: #bbb,border:1.5px solid red;') - // const res = flow.parser.parse('graph TD;style T background : #bbb;'); + expect(classes['exClass'].styles.length).toBe(2); + expect(classes['exClass'].styles[0]).toBe('background:#bbb'); + expect(classes['exClass'].styles[1]).toBe('border:1.5px solid red'); + }); + it('should be possible to declare a class with a space in the style', function() { + const res = flow.parser.parse( + 'graph TD;classDef exClass background: #bbb,border:1.5px solid red;' + ); + // const res = flow.parser.parse('graph TD;style T background : #bbb;'); - const classes = flow.parser.yy.getClasses() + const classes = flow.parser.yy.getClasses(); - expect(classes['exClass'].styles.length).toBe(2) - expect(classes['exClass'].styles[0]).toBe('background: #bbb') - expect(classes['exClass'].styles[1]).toBe('border:1.5px solid red') - }) - it('should be possible to apply a class to a vertex', function () { - let statement = '' + expect(classes['exClass'].styles.length).toBe(2); + expect(classes['exClass'].styles[0]).toBe('background: #bbb'); + expect(classes['exClass'].styles[1]).toBe('border:1.5px solid red'); + }); + it('should be possible to apply a class to a vertex', function() { + let statement = ''; - statement = statement + 'graph TD;' + '\n' - statement = statement + 'classDef exClass background:#bbb,border:1px solid red;' + '\n' - statement = statement + 'a-->b;' + '\n' - statement = statement + 'class a exClass;' + statement = statement + 'graph TD;' + '\n'; + statement = statement + 'classDef exClass background:#bbb,border:1px solid red;' + '\n'; + statement = statement + 'a-->b;' + '\n'; + statement = statement + 'class a exClass;'; - const res = flow.parser.parse(statement) + const res = flow.parser.parse(statement); - const classes = flow.parser.yy.getClasses() + const classes = flow.parser.yy.getClasses(); - expect(classes['exClass'].styles.length).toBe(2) - expect(classes['exClass'].styles[0]).toBe('background:#bbb') - expect(classes['exClass'].styles[1]).toBe('border:1px solid red') - }) - it('should be possible to apply a class to a vertex with an id containing _', function () { - let statement = '' + expect(classes['exClass'].styles.length).toBe(2); + expect(classes['exClass'].styles[0]).toBe('background:#bbb'); + expect(classes['exClass'].styles[1]).toBe('border:1px solid red'); + }); + it('should be possible to apply a class to a vertex with an id containing _', function() { + let statement = ''; - statement = statement + 'graph TD;' + '\n' - statement = statement + 'classDef exClass background:#bbb,border:1px solid red;' + '\n' - statement = statement + 'a_a-->b_b;' + '\n' - statement = statement + 'class a_a exClass;' + statement = statement + 'graph TD;' + '\n'; + statement = statement + 'classDef exClass background:#bbb,border:1px solid red;' + '\n'; + statement = statement + 'a_a-->b_b;' + '\n'; + statement = statement + 'class a_a exClass;'; - const res = flow.parser.parse(statement) + const res = flow.parser.parse(statement); - const classes = flow.parser.yy.getClasses() + const classes = flow.parser.yy.getClasses(); - expect(classes['exClass'].styles.length).toBe(2) - expect(classes['exClass'].styles[0]).toBe('background:#bbb') - expect(classes['exClass'].styles[1]).toBe('border:1px solid red') - }) - it('should be possible to apply a class to a vertex directly', function () { - let statement = '' + expect(classes['exClass'].styles.length).toBe(2); + expect(classes['exClass'].styles[0]).toBe('background:#bbb'); + expect(classes['exClass'].styles[1]).toBe('border:1px solid red'); + }); + it('should be possible to apply a class to a vertex directly', function() { + let statement = ''; - statement = statement + 'graph TD;' + '\n' - statement = statement + 'classDef exClass background:#bbb,border:1px solid red;' + '\n' - statement = statement + 'a-->b[test]:::exClass;' + '\n' + statement = statement + 'graph TD;' + '\n'; + statement = statement + 'classDef exClass background:#bbb,border:1px solid red;' + '\n'; + statement = statement + 'a-->b[test]:::exClass;' + '\n'; - const res = flow.parser.parse(statement) - const vertices = flow.parser.yy.getVertices() - const classes = flow.parser.yy.getClasses() + const res = flow.parser.parse(statement); + const vertices = flow.parser.yy.getVertices(); + const classes = flow.parser.yy.getClasses(); - expect(classes['exClass'].styles.length).toBe(2) - expect(vertices['b'].classes[0]).toBe('exClass') - expect(classes['exClass'].styles[0]).toBe('background:#bbb') - expect(classes['exClass'].styles[1]).toBe('border:1px solid red') - }) + expect(classes['exClass'].styles.length).toBe(2); + expect(vertices['b'].classes[0]).toBe('exClass'); + expect(classes['exClass'].styles[0]).toBe('background:#bbb'); + expect(classes['exClass'].styles[1]).toBe('border:1px solid red'); + }); - it('should be possible to apply a class to a vertex directly : usecase A[text].class ', function () { - let statement = '' + it('should be possible to apply a class to a vertex directly : usecase A[text].class ', function() { + let statement = ''; - statement = statement + 'graph TD;' + '\n' - statement = statement + 'classDef exClass background:#bbb,border:1px solid red;' + '\n' - statement = statement + 'b[test]:::exClass;' + '\n' + statement = statement + 'graph TD;' + '\n'; + statement = statement + 'classDef exClass background:#bbb,border:1px solid red;' + '\n'; + statement = statement + 'b[test]:::exClass;' + '\n'; - const res = flow.parser.parse(statement) - const vertices = flow.parser.yy.getVertices() - const classes = flow.parser.yy.getClasses() + const res = flow.parser.parse(statement); + const vertices = flow.parser.yy.getVertices(); + const classes = flow.parser.yy.getClasses(); - expect(classes['exClass'].styles.length).toBe(2) - expect(vertices['b'].classes[0]).toBe('exClass') - expect(classes['exClass'].styles[0]).toBe('background:#bbb') - expect(classes['exClass'].styles[1]).toBe('border:1px solid red') - }) + expect(classes['exClass'].styles.length).toBe(2); + expect(vertices['b'].classes[0]).toBe('exClass'); + expect(classes['exClass'].styles[0]).toBe('background:#bbb'); + expect(classes['exClass'].styles[1]).toBe('border:1px solid red'); + }); - it('should be possible to apply a class to a vertex directly : usecase A[text].class-->B[test2] ', function () { - let statement = '' + it('should be possible to apply a class to a vertex directly : usecase A[text].class-->B[test2] ', function() { + let statement = ''; - statement = statement + 'graph TD;' + '\n' - statement = statement + 'classDef exClass background:#bbb,border:1px solid red;' + '\n' - statement = statement + 'A[test]:::exClass-->B[test2];' + '\n' + statement = statement + 'graph TD;' + '\n'; + statement = statement + 'classDef exClass background:#bbb,border:1px solid red;' + '\n'; + statement = statement + 'A[test]:::exClass-->B[test2];' + '\n'; - const res = flow.parser.parse(statement) - const vertices = flow.parser.yy.getVertices() - const classes = flow.parser.yy.getClasses() + const res = flow.parser.parse(statement); + const vertices = flow.parser.yy.getVertices(); + const classes = flow.parser.yy.getClasses(); - expect(classes['exClass'].styles.length).toBe(2) - expect(vertices['A'].classes[0]).toBe('exClass') - expect(classes['exClass'].styles[0]).toBe('background:#bbb') - expect(classes['exClass'].styles[1]).toBe('border:1px solid red') - }) + expect(classes['exClass'].styles.length).toBe(2); + expect(vertices['A'].classes[0]).toBe('exClass'); + expect(classes['exClass'].styles[0]).toBe('background:#bbb'); + expect(classes['exClass'].styles[1]).toBe('border:1px solid red'); + }); - it('should be possible to apply a class to a vertex directly 2', function () { - let statement = '' + it('should be possible to apply a class to a vertex directly 2', function() { + let statement = ''; - statement = statement + 'graph TD;' + '\n' - statement = statement + 'classDef exClass background:#bbb,border:1px solid red;' + '\n' - statement = statement + 'a-->b[1 a a text!.]:::exClass;' + '\n' + statement = statement + 'graph TD;' + '\n'; + statement = statement + 'classDef exClass background:#bbb,border:1px solid red;' + '\n'; + statement = statement + 'a-->b[1 a a text!.]:::exClass;' + '\n'; - const res = flow.parser.parse(statement) - const vertices = flow.parser.yy.getVertices() - const classes = flow.parser.yy.getClasses() + const res = flow.parser.parse(statement); + const vertices = flow.parser.yy.getVertices(); + const classes = flow.parser.yy.getClasses(); - expect(classes['exClass'].styles.length).toBe(2) - expect(vertices['b'].classes[0]).toBe('exClass') - expect(classes['exClass'].styles[0]).toBe('background:#bbb') - expect(classes['exClass'].styles[1]).toBe('border:1px solid red') - }) - it('should be possible to apply a class to a comma separated list of vertices', function () { - let statement = '' + expect(classes['exClass'].styles.length).toBe(2); + expect(vertices['b'].classes[0]).toBe('exClass'); + expect(classes['exClass'].styles[0]).toBe('background:#bbb'); + expect(classes['exClass'].styles[1]).toBe('border:1px solid red'); + }); + it('should be possible to apply a class to a comma separated list of vertices', function() { + let statement = ''; - statement = statement + 'graph TD;' + '\n' - statement = statement + 'classDef exClass background:#bbb,border:1px solid red;' + '\n' - statement = statement + 'a-->b;' + '\n' - statement = statement + 'class a,b exClass;' + statement = statement + 'graph TD;' + '\n'; + statement = statement + 'classDef exClass background:#bbb,border:1px solid red;' + '\n'; + statement = statement + 'a-->b;' + '\n'; + statement = statement + 'class a,b exClass;'; - const res = flow.parser.parse(statement) + const res = flow.parser.parse(statement); - const classes = flow.parser.yy.getClasses() - const vertices = flow.parser.yy.getVertices() + const classes = flow.parser.yy.getClasses(); + const vertices = flow.parser.yy.getVertices(); - expect(classes['exClass'].styles.length).toBe(2) - expect(classes['exClass'].styles[0]).toBe('background:#bbb') - expect(classes['exClass'].styles[1]).toBe('border:1px solid red') - expect(vertices['a'].classes[0]).toBe('exClass') - expect(vertices['b'].classes[0]).toBe('exClass') - }) -}) + expect(classes['exClass'].styles.length).toBe(2); + expect(classes['exClass'].styles[0]).toBe('background:#bbb'); + expect(classes['exClass'].styles[1]).toBe('border:1px solid red'); + expect(vertices['a'].classes[0]).toBe('exClass'); + expect(vertices['b'].classes[0]).toBe('exClass'); + }); +}); diff --git a/src/diagrams/flowchart/parser/subgraph.spec.js b/src/diagrams/flowchart/parser/subgraph.spec.js index 6a33c30be..0bf3e63d6 100644 --- a/src/diagrams/flowchart/parser/subgraph.spec.js +++ b/src/diagrams/flowchart/parser/subgraph.spec.js @@ -1,223 +1,223 @@ -import flowDb from '../flowDb' -import flow from './flow' -import { setConfig } from '../../../config' +import flowDb from '../flowDb'; +import flow from './flow'; +import { setConfig } from '../../../config'; setConfig({ - securityLevel: 'strict', -}) + securityLevel: 'strict' +}); -describe('when parsing subgraphs', function () { - beforeEach(function () { - flow.parser.yy = flowDb - flow.parser.yy.clear() - }) - it('should handle subgraph with tab indentation', function () { - const res = flow.parser.parse('graph TB\nsubgraph One\n\ta1-->a2\nend') - const subgraphs = flow.parser.yy.getSubGraphs() - expect(subgraphs.length).toBe(1) - const subgraph = subgraphs[0] - expect(subgraph.nodes.length).toBe(2) - expect(subgraph.nodes[0]).toBe('a2') - expect(subgraph.nodes[1]).toBe('a1') - expect(subgraph.title).toBe('One') - expect(subgraph.id).toBe('One') - }) - it('should handle subgraph with chaining nodes indentation', function () { - const res = flow.parser.parse('graph TB\nsubgraph One\n\ta1-->a2-->a3\nend') - const subgraphs = flow.parser.yy.getSubGraphs() - expect(subgraphs.length).toBe(1) - const subgraph = subgraphs[0] - expect(subgraph.nodes.length).toBe(3) - expect(subgraph.nodes[0]).toBe('a3') - expect(subgraph.nodes[1]).toBe('a2') - expect(subgraph.nodes[2]).toBe('a1') - expect(subgraph.title).toBe('One') - expect(subgraph.id).toBe('One') - }) - - it('should handle subgraph with multiple words in title', function () { - const res = flow.parser.parse('graph TB\nsubgraph "Some Title"\n\ta1-->a2\nend') - const subgraphs = flow.parser.yy.getSubGraphs() - expect(subgraphs.length).toBe(1) - const subgraph = subgraphs[0] - expect(subgraph.nodes.length).toBe(2) - expect(subgraph.nodes[0]).toBe('a2') - expect(subgraph.nodes[1]).toBe('a1') - expect(subgraph.title).toBe('Some Title') - expect(subgraph.id).toBe('subGraph0') +describe('when parsing subgraphs', function() { + beforeEach(function() { + flow.parser.yy = flowDb; + flow.parser.yy.clear(); + }); + it('should handle subgraph with tab indentation', function() { + const res = flow.parser.parse('graph TB\nsubgraph One\n\ta1-->a2\nend'); + const subgraphs = flow.parser.yy.getSubGraphs(); + expect(subgraphs.length).toBe(1); + const subgraph = subgraphs[0]; + expect(subgraph.nodes.length).toBe(2); + expect(subgraph.nodes[0]).toBe('a2'); + expect(subgraph.nodes[1]).toBe('a1'); + expect(subgraph.title).toBe('One'); + expect(subgraph.id).toBe('One'); + }); + it('should handle subgraph with chaining nodes indentation', function() { + const res = flow.parser.parse('graph TB\nsubgraph One\n\ta1-->a2-->a3\nend'); + const subgraphs = flow.parser.yy.getSubGraphs(); + expect(subgraphs.length).toBe(1); + const subgraph = subgraphs[0]; + expect(subgraph.nodes.length).toBe(3); + expect(subgraph.nodes[0]).toBe('a3'); + expect(subgraph.nodes[1]).toBe('a2'); + expect(subgraph.nodes[2]).toBe('a1'); + expect(subgraph.title).toBe('One'); + expect(subgraph.id).toBe('One'); }); - it('should handle subgraph with id and title notation', function () { - const res = flow.parser.parse('graph TB\nsubgraph some-id[Some Title]\n\ta1-->a2\nend') - const subgraphs = flow.parser.yy.getSubGraphs() - expect(subgraphs.length).toBe(1) - const subgraph = subgraphs[0] - expect(subgraph.nodes.length).toBe(2) - expect(subgraph.nodes[0]).toBe('a2') - expect(subgraph.nodes[1]).toBe('a1') - expect(subgraph.title).toBe('Some Title') - expect(subgraph.id).toBe('some-id') + it('should handle subgraph with multiple words in title', function() { + const res = flow.parser.parse('graph TB\nsubgraph "Some Title"\n\ta1-->a2\nend'); + const subgraphs = flow.parser.yy.getSubGraphs(); + expect(subgraphs.length).toBe(1); + const subgraph = subgraphs[0]; + expect(subgraph.nodes.length).toBe(2); + expect(subgraph.nodes[0]).toBe('a2'); + expect(subgraph.nodes[1]).toBe('a1'); + expect(subgraph.title).toBe('Some Title'); + expect(subgraph.id).toBe('subGraph0'); }); - xit('should handle subgraph without id and space in title', function () { - const res = flow.parser.parse('graph TB\nsubgraph Some Title\n\ta1-->a2\nend') - const subgraphs = flow.parser.yy.getSubGraphs() - expect(subgraphs.length).toBe(1) - const subgraph = subgraphs[0] - expect(subgraph.nodes.length).toBe(2) - expect(subgraph.nodes[0]).toBe('a1') - expect(subgraph.nodes[1]).toBe('a2') - expect(subgraph.title).toBe('Some Title') - expect(subgraph.id).toBe('some-id') + it('should handle subgraph with id and title notation', function() { + const res = flow.parser.parse('graph TB\nsubgraph some-id[Some Title]\n\ta1-->a2\nend'); + const subgraphs = flow.parser.yy.getSubGraphs(); + expect(subgraphs.length).toBe(1); + const subgraph = subgraphs[0]; + expect(subgraph.nodes.length).toBe(2); + expect(subgraph.nodes[0]).toBe('a2'); + expect(subgraph.nodes[1]).toBe('a1'); + expect(subgraph.title).toBe('Some Title'); + expect(subgraph.id).toBe('some-id'); }); - it('should handle subgraph id starting with a number', function () { + xit('should handle subgraph without id and space in title', function() { + const res = flow.parser.parse('graph TB\nsubgraph Some Title\n\ta1-->a2\nend'); + const subgraphs = flow.parser.yy.getSubGraphs(); + expect(subgraphs.length).toBe(1); + const subgraph = subgraphs[0]; + expect(subgraph.nodes.length).toBe(2); + expect(subgraph.nodes[0]).toBe('a1'); + expect(subgraph.nodes[1]).toBe('a2'); + expect(subgraph.title).toBe('Some Title'); + expect(subgraph.id).toBe('some-id'); + }); + + it('should handle subgraph id starting with a number', function() { const res = flow.parser.parse(`graph TD A[Christmas] -->|Get money| B(Go shopping) subgraph 1test A - end`) + end`); - const subgraphs = flow.parser.yy.getSubGraphs() - expect(subgraphs.length).toBe(1) - const subgraph = subgraphs[0] - expect(subgraph.nodes.length).toBe(1) - expect(subgraph.nodes[0]).toBe('A') - expect(subgraph.id).toBe('s1test') + const subgraphs = flow.parser.yy.getSubGraphs(); + expect(subgraphs.length).toBe(1); + const subgraph = subgraphs[0]; + expect(subgraph.nodes.length).toBe(1); + expect(subgraph.nodes[0]).toBe('A'); + expect(subgraph.id).toBe('s1test'); }); - it('should handle subgraphs1', function () { - const res = flow.parser.parse('graph TD;A-->B;subgraph myTitle;c-->d;end;') + it('should handle subgraphs1', function() { + const res = flow.parser.parse('graph TD;A-->B;subgraph myTitle;c-->d;end;'); - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); - expect(edges[0].type).toBe('arrow') - }) - it('should handle subgraphs with title in quotes', function () { - const res = flow.parser.parse('graph TD;A-->B;subgraph "title in quotes";c-->d;end;') + expect(edges[0].type).toBe('arrow'); + }); + it('should handle subgraphs with title in quotes', function() { + const res = flow.parser.parse('graph TD;A-->B;subgraph "title in quotes";c-->d;end;'); - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); - const subgraphs = flow.parser.yy.getSubGraphs() - expect(subgraphs.length).toBe(1) - const subgraph = subgraphs[0] + const subgraphs = flow.parser.yy.getSubGraphs(); + expect(subgraphs.length).toBe(1); + const subgraph = subgraphs[0]; - expect(subgraph.title).toBe('title in quotes') + expect(subgraph.title).toBe('title in quotes'); - expect(edges[0].type).toBe('arrow') - }) - it('should handle subgraphs in old style that was broken', function () { - const res = flow.parser.parse('graph TD;A-->B;subgraph old style that is broken;c-->d;end;') + expect(edges[0].type).toBe('arrow'); + }); + it('should handle subgraphs in old style that was broken', function() { + const res = flow.parser.parse('graph TD;A-->B;subgraph old style that is broken;c-->d;end;'); - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); - const subgraphs = flow.parser.yy.getSubGraphs() - expect(subgraphs.length).toBe(1) - const subgraph = subgraphs[0] + const subgraphs = flow.parser.yy.getSubGraphs(); + expect(subgraphs.length).toBe(1); + const subgraph = subgraphs[0]; - expect(subgraph.title).toBe('old style that is broken') + expect(subgraph.title).toBe('old style that is broken'); - expect(edges[0].type).toBe('arrow') - }) - it('should handle subgraphs with dashes in the title', function () { - const res = flow.parser.parse('graph TD;A-->B;subgraph a-b-c;c-->d;end;') + expect(edges[0].type).toBe('arrow'); + }); + it('should handle subgraphs with dashes in the title', function() { + const res = flow.parser.parse('graph TD;A-->B;subgraph a-b-c;c-->d;end;'); - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); - const subgraphs = flow.parser.yy.getSubGraphs() - expect(subgraphs.length).toBe(1) - const subgraph = subgraphs[0] + const subgraphs = flow.parser.yy.getSubGraphs(); + expect(subgraphs.length).toBe(1); + const subgraph = subgraphs[0]; - expect(subgraph.title).toBe('a-b-c') + expect(subgraph.title).toBe('a-b-c'); - expect(edges[0].type).toBe('arrow') - }) - it('should handle subgraphs with id and title in brackets', function () { - const res = flow.parser.parse('graph TD;A-->B;subgraph uid1[text of doom];c-->d;end;') + expect(edges[0].type).toBe('arrow'); + }); + it('should handle subgraphs with id and title in brackets', function() { + const res = flow.parser.parse('graph TD;A-->B;subgraph uid1[text of doom];c-->d;end;'); - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); - const subgraphs = flow.parser.yy.getSubGraphs() - expect(subgraphs.length).toBe(1) - const subgraph = subgraphs[0] + const subgraphs = flow.parser.yy.getSubGraphs(); + expect(subgraphs.length).toBe(1); + const subgraph = subgraphs[0]; - expect(subgraph.title).toBe('text of doom') - expect(subgraph.id).toBe('uid1') + expect(subgraph.title).toBe('text of doom'); + expect(subgraph.id).toBe('uid1'); - expect(edges[0].type).toBe('arrow') - }) - it('should handle subgraphs with id and title in brackets and quotes', function () { - const res = flow.parser.parse('graph TD;A-->B;subgraph uid2["text of doom"];c-->d;end;') + expect(edges[0].type).toBe('arrow'); + }); + it('should handle subgraphs with id and title in brackets and quotes', function() { + const res = flow.parser.parse('graph TD;A-->B;subgraph uid2["text of doom"];c-->d;end;'); - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); - const subgraphs = flow.parser.yy.getSubGraphs() - expect(subgraphs.length).toBe(1) - const subgraph = subgraphs[0] + const subgraphs = flow.parser.yy.getSubGraphs(); + expect(subgraphs.length).toBe(1); + const subgraph = subgraphs[0]; - expect(subgraph.title).toBe('text of doom') - expect(subgraph.id).toBe('uid2') + expect(subgraph.title).toBe('text of doom'); + expect(subgraph.id).toBe('uid2'); - expect(edges[0].type).toBe('arrow') - }) - it('should handle subgraphs with id and title in brackets without spaces', function () { - const res = flow.parser.parse('graph TD;A-->B;subgraph uid2[textofdoom];c-->d;end;') + expect(edges[0].type).toBe('arrow'); + }); + it('should handle subgraphs with id and title in brackets without spaces', function() { + const res = flow.parser.parse('graph TD;A-->B;subgraph uid2[textofdoom];c-->d;end;'); - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); - const subgraphs = flow.parser.yy.getSubGraphs() - expect(subgraphs.length).toBe(1) - const subgraph = subgraphs[0] + const subgraphs = flow.parser.yy.getSubGraphs(); + expect(subgraphs.length).toBe(1); + const subgraph = subgraphs[0]; - expect(subgraph.title).toBe('textofdoom') - expect(subgraph.id).toBe('uid2') + expect(subgraph.title).toBe('textofdoom'); + expect(subgraph.id).toBe('uid2'); - expect(edges[0].type).toBe('arrow') - }) + expect(edges[0].type).toBe('arrow'); + }); - it('should handle subgraphs2', function () { - const res = flow.parser.parse('graph TD\nA-->B\nsubgraph myTitle\n\n c-->d \nend\n') + it('should handle subgraphs2', function() { + const res = flow.parser.parse('graph TD\nA-->B\nsubgraph myTitle\n\n c-->d \nend\n'); - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); - expect(edges[0].type).toBe('arrow') - }) + expect(edges[0].type).toBe('arrow'); + }); - it('should handle nested subgraphs', function () { - const str = 'graph TD\n' + - 'A-->B\n' + - 'subgraph myTitle\n\n' + - ' c-->d \n\n' + - ' subgraph inner\n\n e-->f \n end \n\n' + - ' subgraph inner\n\n h-->i \n end \n\n' + - 'end\n' - const res = flow.parser.parse(str) - }) + it('should handle nested subgraphs', function() { + const str = + 'graph TD\n' + + 'A-->B\n' + + 'subgraph myTitle\n\n' + + ' c-->d \n\n' + + ' subgraph inner\n\n e-->f \n end \n\n' + + ' subgraph inner\n\n h-->i \n end \n\n' + + 'end\n'; + const res = flow.parser.parse(str); + }); - it('should handle subgraphs4', function () { - const res = flow.parser.parse('graph TD\nA-->B\nsubgraph myTitle\nc-->d\nend;') + it('should handle subgraphs4', function() { + const res = flow.parser.parse('graph TD\nA-->B\nsubgraph myTitle\nc-->d\nend;'); - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); - expect(edges[0].type).toBe('arrow') - }) + expect(edges[0].type).toBe('arrow'); + }); - it('should handle subgraphs5', function () { - const res = flow.parser.parse('graph TD\nA-->B\nsubgraph myTitle\nc-- text -->d\nd-->e\n end;') + it('should handle subgraphs5', function() { + const res = flow.parser.parse('graph TD\nA-->B\nsubgraph myTitle\nc-- text -->d\nd-->e\n end;'); - const vert = flow.parser.yy.getVertices() - const edges = flow.parser.yy.getEdges() + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); - expect(edges[0].type).toBe('arrow') - }) - -}) + expect(edges[0].type).toBe('arrow'); + }); +});