From 5d3d1047a4e733409befb30e551ffe54cd4b085c Mon Sep 17 00:00:00 2001 From: saurabhg772244 Date: Wed, 15 Jan 2025 15:37:33 +0530 Subject: [PATCH 1/8] convert sequenceDb to class. --- .../src/diagrams/sequence/sequenceDb.ts | 1242 ++++++++--------- .../diagrams/sequence/sequenceDiagram.spec.js | 29 +- .../src/diagrams/sequence/sequenceDiagram.ts | 11 +- 3 files changed, 643 insertions(+), 639 deletions(-) diff --git a/packages/mermaid/src/diagrams/sequence/sequenceDb.ts b/packages/mermaid/src/diagrams/sequence/sequenceDb.ts index 69ddeaf18..e71177b1f 100644 --- a/packages/mermaid/src/diagrams/sequence/sequenceDb.ts +++ b/packages/mermaid/src/diagrams/sequence/sequenceDb.ts @@ -1,4 +1,5 @@ import { getConfig } from '../../diagram-api/diagramAPI.js'; +import type { DiagramDB } from '../../diagram-api/types.js'; import { log } from '../../logger.js'; import { ImperativeState } from '../../utils/imperativeState.js'; import { sanitizeText } from '../common/common.js'; @@ -28,641 +29,612 @@ interface SequenceState { lastDestroyed?: Actor; } -const state = new ImperativeState(() => ({ - prevActor: undefined, - actors: new Map(), - createdActors: new Map(), - destroyedActors: new Map(), - boxes: [], - messages: [], - notes: [], - sequenceNumbersEnabled: false, - wrapEnabled: undefined, - currentBox: undefined, - lastCreated: undefined, - lastDestroyed: undefined, -})); +export class SequenceDB implements DiagramDB { + private readonly state = new ImperativeState(() => ({ + prevActor: undefined, + actors: new Map(), + createdActors: new Map(), + destroyedActors: new Map(), + boxes: [], + messages: [], + notes: [], + sequenceNumbersEnabled: false, + wrapEnabled: undefined, + currentBox: undefined, + lastCreated: undefined, + lastDestroyed: undefined, + })); -export const addBox = function (data: { text: string; color: string; wrap: boolean }) { - state.records.boxes.push({ - name: data.text, - wrap: data.wrap ?? autoWrap(), - fill: data.color, - actorKeys: [], - }); - state.records.currentBox = state.records.boxes.slice(-1)[0]; -}; - -export const addActor = function ( - id: string, - name: string, - description: { text: string; wrap?: boolean | null; type: string }, - type: string -) { - let assignedBox = state.records.currentBox; - const old = state.records.actors.get(id); - if (old) { - // If already set and trying to set to a new one throw error - if (state.records.currentBox && old.box && state.records.currentBox !== old.box) { - throw new Error( - `A same participant should only be defined in one Box: ${old.name} can't be in '${old.box.name}' and in '${state.records.currentBox.name}' at the same time.` - ); - } - - // Don't change the box if already - assignedBox = old.box ? old.box : state.records.currentBox; - old.box = assignedBox; - - // Don't allow description nulling - if (old && name === old.name && description == null) { - return; - } - } - - // Don't allow null descriptions, either - if (description?.text == null) { - description = { text: name, type }; - } - if (type == null || description.text == null) { - description = { text: name, type }; - } - - state.records.actors.set(id, { - box: assignedBox, - name: name, - description: description.text, - wrap: description.wrap ?? autoWrap(), - prevActor: state.records.prevActor, - links: {}, - properties: {}, - actorCnt: null, - rectData: null, - type: type ?? 'participant', - }); - if (state.records.prevActor) { - const prevActorInRecords = state.records.actors.get(state.records.prevActor); - if (prevActorInRecords) { - prevActorInRecords.nextActor = id; - } - } - - if (state.records.currentBox) { - state.records.currentBox.actorKeys.push(id); - } - state.records.prevActor = id; -}; - -const activationCount = (part: string) => { - let i; - let count = 0; - if (!part) { - return 0; - } - for (i = 0; i < state.records.messages.length; i++) { - if ( - state.records.messages[i].type === LINETYPE.ACTIVE_START && - state.records.messages[i].from === part - ) { - count++; - } - if ( - state.records.messages[i].type === LINETYPE.ACTIVE_END && - state.records.messages[i].from === part - ) { - count--; - } - } - return count; -}; - -export const addMessage = function ( - idFrom: Message['from'], - idTo: Message['to'], - message: { text: string; wrap?: boolean }, - answer: Message['answer'] -) { - state.records.messages.push({ - from: idFrom, - to: idTo, - message: message.text, - wrap: message.wrap ?? autoWrap(), - answer: answer, - }); -}; - -export const addSignal = function ( - idFrom?: Message['from'], - idTo?: Message['to'], - message?: { text: string; wrap: boolean }, - messageType?: number, - activate = false -) { - if (messageType === LINETYPE.ACTIVE_END) { - const cnt = activationCount(idFrom ?? ''); - if (cnt < 1) { - // Bail out as there is an activation signal from an inactive participant - const error = new Error('Trying to inactivate an inactive participant (' + idFrom + ')'); - - // @ts-ignore: we are passing hash param to the error object, however we should define our own custom error class to make it type safe - error.hash = { - text: '->>-', - token: '->>-', - line: '1', - loc: { first_line: 1, last_line: 1, first_column: 1, last_column: 1 }, - expected: ["'ACTIVE_PARTICIPANT'"], - }; - throw error; - } - } - state.records.messages.push({ - from: idFrom, - to: idTo, - message: message?.text ?? '', - wrap: message?.wrap ?? autoWrap(), - type: messageType, - activate, - }); - return true; -}; - -export const hasAtLeastOneBox = function () { - return state.records.boxes.length > 0; -}; - -export const hasAtLeastOneBoxWithTitle = function () { - return state.records.boxes.some((b) => b.name); -}; - -export const getMessages = function () { - return state.records.messages; -}; - -export const getBoxes = function () { - return state.records.boxes; -}; -export const getActors = function () { - return state.records.actors; -}; -export const getCreatedActors = function () { - return state.records.createdActors; -}; -export const getDestroyedActors = function () { - return state.records.destroyedActors; -}; -export const getActor = function (id: string) { - // TODO: do we ever use this function in a way that it might return undefined? - return state.records.actors.get(id)!; -}; -export const getActorKeys = function () { - return [...state.records.actors.keys()]; -}; -export const enableSequenceNumbers = function () { - state.records.sequenceNumbersEnabled = true; -}; -export const disableSequenceNumbers = function () { - state.records.sequenceNumbersEnabled = false; -}; -export const showSequenceNumbers = () => state.records.sequenceNumbersEnabled; - -export const setWrap = function (wrapSetting?: boolean) { - state.records.wrapEnabled = wrapSetting; -}; - -const extractWrap = (text?: string): { cleanedText?: string; wrap?: boolean } => { - if (text === undefined) { - return {}; - } - text = text.trim(); - const wrap = - /^:?wrap:/.exec(text) !== null ? true : /^:?nowrap:/.exec(text) !== null ? false : undefined; - const cleanedText = (wrap === undefined ? text : text.replace(/^:?(?:no)?wrap:/, '')).trim(); - return { cleanedText, wrap }; -}; - -export const autoWrap = () => { - // if setWrap has been called, use that value, otherwise use the value from the config - // TODO: refactor, always use the config value let setWrap update the config value - if (state.records.wrapEnabled !== undefined) { - return state.records.wrapEnabled; - } - return getConfig().sequence?.wrap ?? false; -}; - -export const clear = function () { - state.reset(); - commonClear(); -}; - -export const parseMessage = function (str: string) { - const trimmedStr = str.trim(); - const { wrap, cleanedText } = extractWrap(trimmedStr); - const message = { - text: cleanedText, - wrap, - }; - log.debug(`parseMessage: ${JSON.stringify(message)}`); - return message; -}; - -// We expect the box statement to be color first then description -// The color can be rgb,rgba,hsl,hsla, or css code names #hex codes are not supported for now because of the way the char # is handled -// We extract first segment as color, the rest of the line is considered as text -export const parseBoxData = function (str: string) { - const match = /^((?:rgba?|hsla?)\s*\(.*\)|\w*)(.*)$/.exec(str); - let color = match?.[1] ? match[1].trim() : 'transparent'; - let title = match?.[2] ? match[2].trim() : undefined; - - // check that the string is a color - if (window?.CSS) { - if (!window.CSS.supports('color', color)) { - color = 'transparent'; - title = str.trim(); - } - } else { - const style = new Option().style; - style.color = color; - if (style.color !== color) { - color = 'transparent'; - title = str.trim(); - } - } - const { wrap, cleanedText } = extractWrap(title); - return { - text: cleanedText ? sanitizeText(cleanedText, getConfig()) : undefined, - color, - wrap, - }; -}; - -export const LINETYPE = { - SOLID: 0, - DOTTED: 1, - NOTE: 2, - SOLID_CROSS: 3, - DOTTED_CROSS: 4, - SOLID_OPEN: 5, - DOTTED_OPEN: 6, - LOOP_START: 10, - LOOP_END: 11, - ALT_START: 12, - ALT_ELSE: 13, - ALT_END: 14, - OPT_START: 15, - OPT_END: 16, - ACTIVE_START: 17, - ACTIVE_END: 18, - PAR_START: 19, - PAR_AND: 20, - PAR_END: 21, - RECT_START: 22, - RECT_END: 23, - SOLID_POINT: 24, - DOTTED_POINT: 25, - AUTONUMBER: 26, - CRITICAL_START: 27, - CRITICAL_OPTION: 28, - CRITICAL_END: 29, - BREAK_START: 30, - BREAK_END: 31, - PAR_OVER_START: 32, - BIDIRECTIONAL_SOLID: 33, - BIDIRECTIONAL_DOTTED: 34, -}; - -export const ARROWTYPE = { - FILLED: 0, - OPEN: 1, -}; - -export const PLACEMENT = { - LEFTOF: 0, - RIGHTOF: 1, - OVER: 2, -}; - -export const addNote = function ( - actor: { actor: string }, - placement: Message['placement'], - message: { text: string; wrap?: boolean } -) { - const note: Note = { - actor: actor, - placement: placement, - message: message.text, - wrap: message.wrap ?? autoWrap(), - }; - - //@ts-ignore: Coerce actor into a [to, from, ...] array - // eslint-disable-next-line unicorn/prefer-spread - const actors = [].concat(actor, actor); - state.records.notes.push(note); - state.records.messages.push({ - from: actors[0], - to: actors[1], - message: message.text, - wrap: message.wrap ?? autoWrap(), - type: LINETYPE.NOTE, - placement: placement, - }); -}; - -export const addLinks = function (actorId: string, text: { text: string }) { - // find the actor - const actor = getActor(actorId); - // JSON.parse the text - try { - let sanitizedText = sanitizeText(text.text, getConfig()); - sanitizedText = sanitizedText.replace(/&/g, '&'); - sanitizedText = sanitizedText.replace(/=/g, '='); - const links = JSON.parse(sanitizedText); - // add the deserialized text to the actor's links field. - insertLinks(actor, links); - } catch (e) { - log.error('error while parsing actor link text', e); - } -}; - -export const addALink = function (actorId: string, text: { text: string }) { - // find the actor - const actor = getActor(actorId); - try { - const links: Record = {}; - let sanitizedText = sanitizeText(text.text, getConfig()); - const sep = sanitizedText.indexOf('@'); - sanitizedText = sanitizedText.replace(/&/g, '&'); - sanitizedText = sanitizedText.replace(/=/g, '='); - const label = sanitizedText.slice(0, sep - 1).trim(); - const link = sanitizedText.slice(sep + 1).trim(); - - links[label] = link; - // add the deserialized text to the actor's links field. - insertLinks(actor, links); - } catch (e) { - log.error('error while parsing actor link text', e); - } -}; - -/** - * @param actor - the actor to add the links to - * @param links - the links to add to the actor - */ -function insertLinks(actor: Actor, links: Record) { - if (actor.links == null) { - actor.links = links; - } else { - for (const key in links) { - actor.links[key] = links[key]; - } - } -} - -export const addProperties = function (actorId: string, text: { text: string }) { - // find the actor - const actor = getActor(actorId); - // JSON.parse the text - try { - const sanitizedText = sanitizeText(text.text, getConfig()); - const properties: Record = JSON.parse(sanitizedText); - // add the deserialized text to the actor's property field. - insertProperties(actor, properties); - } catch (e) { - log.error('error while parsing actor properties text', e); - } -}; - -/** - * @param actor - the actor to add the properties to - * @param properties - the properties to add to the actor's properties - */ -function insertProperties(actor: Actor, properties: Record) { - if (actor.properties == null) { - actor.properties = properties; - } else { - for (const key in properties) { - actor.properties[key] = properties[key]; - } - } -} - -function boxEnd() { - state.records.currentBox = undefined; -} - -export const addDetails = function (actorId: string, text: { text: string }) { - // find the actor - const actor = getActor(actorId); - const elem = document.getElementById(text.text)!; - - // JSON.parse the text - try { - const text = elem.innerHTML; - const details = JSON.parse(text); - // add the deserialized text to the actor's property field. - if (details.properties) { - insertProperties(actor, details.properties); - } - - if (details.links) { - insertLinks(actor, details.links); - } - } catch (e) { - log.error('error while parsing actor details text', e); - } -}; - -export const getActorProperty = function (actor: Actor, key: string) { - if (actor?.properties !== undefined) { - return actor.properties[key]; - } - - return undefined; -}; - -// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-redundant-type-constituents -export const apply = function (param: any | AddMessageParams | AddMessageParams[]) { - if (Array.isArray(param)) { - param.forEach(function (item) { - apply(item); + public addBox = (data: { text: string; color: string; wrap: boolean }) => { + this.state.records.boxes.push({ + name: data.text, + wrap: data.wrap ?? this.autoWrap(), + fill: data.color, + actorKeys: [], }); - } else { - switch (param.type) { - case 'sequenceIndex': - state.records.messages.push({ - from: undefined, - to: undefined, - message: { - start: param.sequenceIndex, - step: param.sequenceIndexStep, - visible: param.sequenceVisible, - }, - wrap: false, - type: param.signalType, - }); - break; - case 'addParticipant': - addActor(param.actor, param.actor, param.description, param.draw); - break; - case 'createParticipant': - if (state.records.actors.has(param.actor)) { - throw new Error( - "It is not possible to have actors with the same id, even if one is destroyed before the next is created. Use 'AS' aliases to simulate the behavior" - ); - } - state.records.lastCreated = param.actor; - addActor(param.actor, param.actor, param.description, param.draw); - state.records.createdActors.set(param.actor, state.records.messages.length); - break; - case 'destroyParticipant': - state.records.lastDestroyed = param.actor; - state.records.destroyedActors.set(param.actor, state.records.messages.length); - break; - case 'activeStart': - addSignal(param.actor, undefined, undefined, param.signalType); - break; - case 'activeEnd': - addSignal(param.actor, undefined, undefined, param.signalType); - break; - case 'addNote': - addNote(param.actor, param.placement, param.text); - break; - case 'addLinks': - addLinks(param.actor, param.text); - break; - case 'addALink': - addALink(param.actor, param.text); - break; - case 'addProperties': - addProperties(param.actor, param.text); - break; - case 'addDetails': - addDetails(param.actor, param.text); - break; - case 'addMessage': - if (state.records.lastCreated) { - if (param.to !== state.records.lastCreated) { - throw new Error( - 'The created participant ' + - state.records.lastCreated.name + - ' does not have an associated creating message after its declaration. Please check the sequence diagram.' - ); - } else { - state.records.lastCreated = undefined; - } - } else if (state.records.lastDestroyed) { - if ( - param.to !== state.records.lastDestroyed && - param.from !== state.records.lastDestroyed - ) { - throw new Error( - 'The destroyed participant ' + - state.records.lastDestroyed.name + - ' does not have an associated destroying message after its declaration. Please check the sequence diagram.' - ); - } else { - state.records.lastDestroyed = undefined; - } - } - addSignal(param.from, param.to, param.msg, param.signalType, param.activate); - break; - case 'boxStart': - addBox(param.boxData); - break; - case 'boxEnd': - boxEnd(); - break; - case 'loopStart': - addSignal(undefined, undefined, param.loopText, param.signalType); - break; - case 'loopEnd': - addSignal(undefined, undefined, undefined, param.signalType); - break; - case 'rectStart': - addSignal(undefined, undefined, param.color, param.signalType); - break; - case 'rectEnd': - addSignal(undefined, undefined, undefined, param.signalType); - break; - case 'optStart': - addSignal(undefined, undefined, param.optText, param.signalType); - break; - case 'optEnd': - addSignal(undefined, undefined, undefined, param.signalType); - break; - case 'altStart': - addSignal(undefined, undefined, param.altText, param.signalType); - break; - case 'else': - addSignal(undefined, undefined, param.altText, param.signalType); - break; - case 'altEnd': - addSignal(undefined, undefined, undefined, param.signalType); - break; - case 'setAccTitle': - setAccTitle(param.text); - break; - case 'parStart': - addSignal(undefined, undefined, param.parText, param.signalType); - break; - case 'and': - addSignal(undefined, undefined, param.parText, param.signalType); - break; - case 'parEnd': - addSignal(undefined, undefined, undefined, param.signalType); - break; - case 'criticalStart': - addSignal(undefined, undefined, param.criticalText, param.signalType); - break; - case 'option': - addSignal(undefined, undefined, param.optionText, param.signalType); - break; - case 'criticalEnd': - addSignal(undefined, undefined, undefined, param.signalType); - break; - case 'breakStart': - addSignal(undefined, undefined, param.breakText, param.signalType); - break; - case 'breakEnd': - addSignal(undefined, undefined, undefined, param.signalType); - break; - } - } -}; + this.state.records.currentBox = this.state.records.boxes.slice(-1)[0]; + }; -export default { - addActor, - addMessage, - addSignal, - addLinks, - addDetails, - addProperties, - autoWrap, - setWrap, - enableSequenceNumbers, - disableSequenceNumbers, - showSequenceNumbers, - getMessages, - getActors, - getCreatedActors, - getDestroyedActors, - getActor, - getActorKeys, - getActorProperty, - getAccTitle, - getBoxes, - getDiagramTitle, - setDiagramTitle, - getConfig: () => getConfig().sequence, - clear, - parseMessage, - parseBoxData, - LINETYPE, - ARROWTYPE, - PLACEMENT, - addNote, - setAccTitle, - apply, - setAccDescription, - getAccDescription, - hasAtLeastOneBox, - hasAtLeastOneBoxWithTitle, -}; + public addActor = ( + id: string, + name: string, + description: { text: string; wrap?: boolean | null; type: string }, + type: string + ) => { + let assignedBox = this.state.records.currentBox; + const old = this.state.records.actors.get(id); + if (old) { + // If already set and trying to set to a new one throw error + if (this.state.records.currentBox && old.box && this.state.records.currentBox !== old.box) { + throw new Error( + `A same participant should only be defined in one Box: ${old.name} can't be in '${old.box.name}' and in '${this.state.records.currentBox.name}' at the same time.` + ); + } + + // Don't change the box if already + assignedBox = old.box ? old.box : this.state.records.currentBox; + old.box = assignedBox; + + // Don't allow description nulling + if (old && name === old.name && description == null) { + return; + } + } + + // Don't allow null descriptions, either + if (description?.text == null) { + description = { text: name, type }; + } + if (type == null || description.text == null) { + description = { text: name, type }; + } + + this.state.records.actors.set(id, { + box: assignedBox, + name: name, + description: description.text, + wrap: description.wrap ?? this.autoWrap(), + prevActor: this.state.records.prevActor, + links: {}, + properties: {}, + actorCnt: null, + rectData: null, + type: type ?? 'participant', + }); + if (this.state.records.prevActor) { + const prevActorInRecords = this.state.records.actors.get(this.state.records.prevActor); + if (prevActorInRecords) { + prevActorInRecords.nextActor = id; + } + } + + if (this.state.records.currentBox) { + this.state.records.currentBox.actorKeys.push(id); + } + this.state.records.prevActor = id; + }; + + private readonly activationCount = (part: string) => { + let i; + let count = 0; + if (!part) { + return 0; + } + for (i = 0; i < this.state.records.messages.length; i++) { + if ( + this.state.records.messages[i].type === this.LINETYPE.ACTIVE_START && + this.state.records.messages[i].from === part + ) { + count++; + } + if ( + this.state.records.messages[i].type === this.LINETYPE.ACTIVE_END && + this.state.records.messages[i].from === part + ) { + count--; + } + } + return count; + }; + + public addMessage = ( + idFrom: Message['from'], + idTo: Message['to'], + message: { text: string; wrap?: boolean }, + answer: Message['answer'] + ) => { + this.state.records.messages.push({ + from: idFrom, + to: idTo, + message: message.text, + wrap: message.wrap ?? this.autoWrap(), + answer: answer, + }); + }; + + public addSignal = ( + idFrom?: Message['from'], + idTo?: Message['to'], + message?: { text: string; wrap: boolean }, + messageType?: number, + activate = false + ) => { + if (messageType === this.LINETYPE.ACTIVE_END) { + const cnt = this.activationCount(idFrom ?? ''); + if (cnt < 1) { + // Bail out as there is an activation signal from an inactive participant + const error = new Error('Trying to inactivate an inactive participant (' + idFrom + ')'); + + // @ts-ignore: we are passing hash param to the error object, however we should define our own custom error class to make it type safe + error.hash = { + text: '->>-', + token: '->>-', + line: '1', + loc: { first_line: 1, last_line: 1, first_column: 1, last_column: 1 }, + expected: ["'ACTIVE_PARTICIPANT'"], + }; + throw error; + } + } + this.state.records.messages.push({ + from: idFrom, + to: idTo, + message: message?.text ?? '', + wrap: message?.wrap ?? this.autoWrap(), + type: messageType, + activate, + }); + return true; + }; + + public hasAtLeastOneBox = () => { + return this.state.records.boxes.length > 0; + }; + + public hasAtLeastOneBoxWithTitle = () => { + return this.state.records.boxes.some((b) => b.name); + }; + + public getMessages = () => { + return this.state.records.messages; + }; + + public getBoxes = () => { + return this.state.records.boxes; + }; + public getActors = () => { + return this.state.records.actors; + }; + public getCreatedActors = () => { + return this.state.records.createdActors; + }; + public getDestroyedActors = () => { + return this.state.records.destroyedActors; + }; + public getActor = (id: string) => { + // TODO: do we ever use this function in a way that it might return undefined? + return this.state.records.actors.get(id)!; + }; + public getActorKeys = () => { + return [...this.state.records.actors.keys()]; + }; + public enableSequenceNumbers = () => { + this.state.records.sequenceNumbersEnabled = true; + }; + public disableSequenceNumbers = () => { + this.state.records.sequenceNumbersEnabled = false; + }; + public showSequenceNumbers = () => this.state.records.sequenceNumbersEnabled; + + public setWrap = (wrapSetting?: boolean) => { + this.state.records.wrapEnabled = wrapSetting; + }; + + private readonly extractWrap = (text?: string): { cleanedText?: string; wrap?: boolean } => { + if (text === undefined) { + return {}; + } + text = text.trim(); + const wrap = + /^:?wrap:/.exec(text) !== null ? true : /^:?nowrap:/.exec(text) !== null ? false : undefined; + const cleanedText = (wrap === undefined ? text : text.replace(/^:?(?:no)?wrap:/, '')).trim(); + return { cleanedText, wrap }; + }; + + public autoWrap = () => { + // if setWrap has been called, use that value, otherwise use the value from the config + // TODO: refactor, always use the config value let setWrap update the config value + if (this.state.records.wrapEnabled !== undefined) { + return this.state.records.wrapEnabled; + } + return getConfig().sequence?.wrap ?? false; + }; + + public clear = () => { + this.state.reset(); + commonClear(); + }; + + public parseMessage = (str: string) => { + const trimmedStr = str.trim(); + const { wrap, cleanedText } = this.extractWrap(trimmedStr); + const message = { + text: cleanedText, + wrap, + }; + log.debug(`parseMessage: ${JSON.stringify(message)}`); + return message; + }; + + // We expect the box statement to be color first then description + // The color can be rgb,rgba,hsl,hsla, or css code names #hex codes are not supported for now because of the way the char # is handled + // We extract first segment as color, the rest of the line is considered as text + public parseBoxData = (str: string) => { + const match = /^((?:rgba?|hsla?)\s*\(.*\)|\w*)(.*)$/.exec(str); + let color = match?.[1] ? match[1].trim() : 'transparent'; + let title = match?.[2] ? match[2].trim() : undefined; + + // check that the string is a color + if (window?.CSS) { + if (!window.CSS.supports('color', color)) { + color = 'transparent'; + title = str.trim(); + } + } else { + const style = new Option().style; + style.color = color; + if (style.color !== color) { + color = 'transparent'; + title = str.trim(); + } + } + const { wrap, cleanedText } = this.extractWrap(title); + return { + text: cleanedText ? sanitizeText(cleanedText, getConfig()) : undefined, + color, + wrap, + }; + }; + + public LINETYPE = { + SOLID: 0, + DOTTED: 1, + NOTE: 2, + SOLID_CROSS: 3, + DOTTED_CROSS: 4, + SOLID_OPEN: 5, + DOTTED_OPEN: 6, + LOOP_START: 10, + LOOP_END: 11, + ALT_START: 12, + ALT_ELSE: 13, + ALT_END: 14, + OPT_START: 15, + OPT_END: 16, + ACTIVE_START: 17, + ACTIVE_END: 18, + PAR_START: 19, + PAR_AND: 20, + PAR_END: 21, + RECT_START: 22, + RECT_END: 23, + SOLID_POINT: 24, + DOTTED_POINT: 25, + AUTONUMBER: 26, + CRITICAL_START: 27, + CRITICAL_OPTION: 28, + CRITICAL_END: 29, + BREAK_START: 30, + BREAK_END: 31, + PAR_OVER_START: 32, + BIDIRECTIONAL_SOLID: 33, + BIDIRECTIONAL_DOTTED: 34, + }; + + public ARROWTYPE = { + FILLED: 0, + OPEN: 1, + }; + + public PLACEMENT = { + LEFTOF: 0, + RIGHTOF: 1, + OVER: 2, + }; + + public addNote = ( + actor: { actor: string }, + placement: Message['placement'], + message: { text: string; wrap?: boolean } + ) => { + const note: Note = { + actor: actor, + placement: placement, + message: message.text, + wrap: message.wrap ?? this.autoWrap(), + }; + + //@ts-ignore: Coerce actor into a [to, from, ...] array + // eslint-disable-next-line unicorn/prefer-spread + const actors = [].concat(actor, actor); + this.state.records.notes.push(note); + this.state.records.messages.push({ + from: actors[0], + to: actors[1], + message: message.text, + wrap: message.wrap ?? this.autoWrap(), + type: this.LINETYPE.NOTE, + placement: placement, + }); + }; + + public addLinks = (actorId: string, text: { text: string }) => { + // find the actor + const actor = this.getActor(actorId); + // JSON.parse the text + try { + let sanitizedText = sanitizeText(text.text, getConfig()); + sanitizedText = sanitizedText.replace(/&/g, '&'); + sanitizedText = sanitizedText.replace(/=/g, '='); + const links = JSON.parse(sanitizedText); + // add the deserialized text to the actor's links field. + this.insertLinks(actor, links); + } catch (e) { + log.error('error while parsing actor link text', e); + } + }; + + public addALink = (actorId: string, text: { text: string }) => { + // find the actor + const actor = this.getActor(actorId); + try { + const links: Record = {}; + let sanitizedText = sanitizeText(text.text, getConfig()); + const sep = sanitizedText.indexOf('@'); + sanitizedText = sanitizedText.replace(/&/g, '&'); + sanitizedText = sanitizedText.replace(/=/g, '='); + const label = sanitizedText.slice(0, sep - 1).trim(); + const link = sanitizedText.slice(sep + 1).trim(); + + links[label] = link; + // add the deserialized text to the actor's links field. + this.insertLinks(actor, links); + } catch (e) { + log.error('error while parsing actor link text', e); + } + }; + + /** + * @param actor - the actor to add the links to + * @param links - the links to add to the actor + */ + private readonly insertLinks = (actor: Actor, links: Record) => { + if (actor.links == null) { + actor.links = links; + } else { + for (const key in links) { + actor.links[key] = links[key]; + } + } + }; + + public addProperties = (actorId: string, text: { text: string }) => { + // find the actor + const actor = this.getActor(actorId); + // JSON.parse the text + try { + const sanitizedText = sanitizeText(text.text, getConfig()); + const properties: Record = JSON.parse(sanitizedText); + // add the deserialized text to the actor's property field. + this.insertProperties(actor, properties); + } catch (e) { + log.error('error while parsing actor properties text', e); + } + }; + + /** + * @param actor - the actor to add the properties to + * @param properties - the properties to add to the actor's properties + */ + private readonly insertProperties = (actor: Actor, properties: Record) => { + if (actor.properties == null) { + actor.properties = properties; + } else { + for (const key in properties) { + actor.properties[key] = properties[key]; + } + } + }; + + private readonly boxEnd = () => { + this.state.records.currentBox = undefined; + }; + + public addDetails = (actorId: string, text: { text: string }) => { + // find the actor + const actor = this.getActor(actorId); + const elem = document.getElementById(text.text)!; + + // JSON.parse the text + try { + const text = elem.innerHTML; + const details = JSON.parse(text); + // add the deserialized text to the actor's property field. + if (details.properties) { + this.insertProperties(actor, details.properties); + } + + if (details.links) { + this.insertLinks(actor, details.links); + } + } catch (e) { + log.error('error while parsing actor details text', e); + } + }; + + public getActorProperty = (actor: Actor, key: string) => { + if (actor?.properties !== undefined) { + return actor.properties[key]; + } + + return undefined; + }; + + // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-redundant-type-constituents + public apply = (param: any | AddMessageParams | AddMessageParams[]) => { + if (Array.isArray(param)) { + param.forEach((item) => { + this.apply(item); + }); + } else { + switch (param.type) { + case 'sequenceIndex': + this.state.records.messages.push({ + from: undefined, + to: undefined, + message: { + start: param.sequenceIndex, + step: param.sequenceIndexStep, + visible: param.sequenceVisible, + }, + wrap: false, + type: param.signalType, + }); + break; + case 'addParticipant': + this.addActor(param.actor, param.actor, param.description, param.draw); + break; + case 'createParticipant': + if (this.state.records.actors.has(param.actor)) { + throw new Error( + "It is not possible to have actors with the same id, even if one is destroyed before the next is created. Use 'AS' aliases to simulate the behavior" + ); + } + this.state.records.lastCreated = param.actor; + this.addActor(param.actor, param.actor, param.description, param.draw); + this.state.records.createdActors.set(param.actor, this.state.records.messages.length); + break; + case 'destroyParticipant': + this.state.records.lastDestroyed = param.actor; + this.state.records.destroyedActors.set(param.actor, this.state.records.messages.length); + break; + case 'activeStart': + this.addSignal(param.actor, undefined, undefined, param.signalType); + break; + case 'activeEnd': + this.addSignal(param.actor, undefined, undefined, param.signalType); + break; + case 'addNote': + this.addNote(param.actor, param.placement, param.text); + break; + case 'addLinks': + this.addLinks(param.actor, param.text); + break; + case 'addALink': + this.addALink(param.actor, param.text); + break; + case 'addProperties': + this.addProperties(param.actor, param.text); + break; + case 'addDetails': + this.addDetails(param.actor, param.text); + break; + case 'addMessage': + if (this.state.records.lastCreated) { + if (param.to !== this.state.records.lastCreated) { + throw new Error( + 'The created participant ' + + this.state.records.lastCreated.name + + ' does not have an associated creating message after its declaration. Please check the sequence diagram.' + ); + } else { + this.state.records.lastCreated = undefined; + } + } else if (this.state.records.lastDestroyed) { + if ( + param.to !== this.state.records.lastDestroyed && + param.from !== this.state.records.lastDestroyed + ) { + throw new Error( + 'The destroyed participant ' + + this.state.records.lastDestroyed.name + + ' does not have an associated destroying message after its declaration. Please check the sequence diagram.' + ); + } else { + this.state.records.lastDestroyed = undefined; + } + } + this.addSignal(param.from, param.to, param.msg, param.signalType, param.activate); + break; + case 'boxStart': + this.addBox(param.boxData); + break; + case 'boxEnd': + this.boxEnd(); + break; + case 'loopStart': + this.addSignal(undefined, undefined, param.loopText, param.signalType); + break; + case 'loopEnd': + this.addSignal(undefined, undefined, undefined, param.signalType); + break; + case 'rectStart': + this.addSignal(undefined, undefined, param.color, param.signalType); + break; + case 'rectEnd': + this.addSignal(undefined, undefined, undefined, param.signalType); + break; + case 'optStart': + this.addSignal(undefined, undefined, param.optText, param.signalType); + break; + case 'optEnd': + this.addSignal(undefined, undefined, undefined, param.signalType); + break; + case 'altStart': + this.addSignal(undefined, undefined, param.altText, param.signalType); + break; + case 'else': + this.addSignal(undefined, undefined, param.altText, param.signalType); + break; + case 'altEnd': + this.addSignal(undefined, undefined, undefined, param.signalType); + break; + case 'setAccTitle': + setAccTitle(param.text); + break; + case 'parStart': + this.addSignal(undefined, undefined, param.parText, param.signalType); + break; + case 'and': + this.addSignal(undefined, undefined, param.parText, param.signalType); + break; + case 'parEnd': + this.addSignal(undefined, undefined, undefined, param.signalType); + break; + case 'criticalStart': + this.addSignal(undefined, undefined, param.criticalText, param.signalType); + break; + case 'option': + this.addSignal(undefined, undefined, param.optionText, param.signalType); + break; + case 'criticalEnd': + this.addSignal(undefined, undefined, undefined, param.signalType); + break; + case 'breakStart': + this.addSignal(undefined, undefined, param.breakText, param.signalType); + break; + case 'breakEnd': + this.addSignal(undefined, undefined, undefined, param.signalType); + break; + } + } + }; + + public getAccTitle = getAccTitle; + public getDiagramTitle = getDiagramTitle; + public setDiagramTitle = setDiagramTitle; + public getConfig = () => getConfig().sequence; + public setAccTitle = setAccTitle; + public setAccDescription = setAccDescription; + public getAccDescription = getAccDescription; +} diff --git a/packages/mermaid/src/diagrams/sequence/sequenceDiagram.spec.js b/packages/mermaid/src/diagrams/sequence/sequenceDiagram.spec.js index fde813cef..474668edf 100644 --- a/packages/mermaid/src/diagrams/sequence/sequenceDiagram.spec.js +++ b/packages/mermaid/src/diagrams/sequence/sequenceDiagram.spec.js @@ -3,6 +3,7 @@ import { setSiteConfig } from '../../diagram-api/diagramAPI.js'; import mermaidAPI from '../../mermaidAPI.js'; import { Diagram } from '../../Diagram.js'; import { addDiagrams } from '../../diagram-api/diagram-orchestration.js'; +import { SequenceDB } from './sequenceDb.js'; beforeAll(async () => { // Is required to load the sequence diagram @@ -97,8 +98,8 @@ let diagram; describe('more than one sequence diagram', () => { it('should not have duplicated messages', async () => { const diagram1 = await Diagram.fromText(` - sequenceDiagram - Alice->Bob:Hello Bob, how are you? + sequenceDiagram + Alice->Bob:Hello Bob, how are you? Bob-->Alice: I am good thanks!`); expect(diagram1.db.getMessages()).toMatchInlineSnapshot(` [ @@ -2071,3 +2072,27 @@ ${prop}-->>A: Hello, how are you?`) ).resolves.toBeDefined(); }); }); + +describe('sequence db class', () => { + let sequenceDb; + beforeEach(() => { + sequenceDb = new SequenceDB(); + }); + // This is to ensure that functions used in sequence JISON are exposed as function from SequenceDB + it('should have functions used in sequence JISON as own property', () => { + const functionsUsedInParser = [ + 'apply', + 'parseBoxData', + 'LINETYPE', + 'setDiagramTitle', + 'setAccTitle', + 'setAccDescription', + 'parseMessage', + 'PLACEMENT', + ]; + + for (const fun of functionsUsedInParser) { + expect(Object.hasOwn(sequenceDb, fun)).toBe(true); + } + }); +}); diff --git a/packages/mermaid/src/diagrams/sequence/sequenceDiagram.ts b/packages/mermaid/src/diagrams/sequence/sequenceDiagram.ts index f8d71c95e..80ccda5f9 100644 --- a/packages/mermaid/src/diagrams/sequence/sequenceDiagram.ts +++ b/packages/mermaid/src/diagrams/sequence/sequenceDiagram.ts @@ -1,13 +1,20 @@ import type { DiagramDefinition } from '../../diagram-api/types.js'; // @ts-ignore: JISON doesn't support types import parser from './parser/sequenceDiagram.jison'; -import db from './sequenceDb.js'; +import { SequenceDB } from './sequenceDb.js'; import styles from './styles.js'; import renderer from './sequenceRenderer.js'; +let db: SequenceDB; + export const diagram: DiagramDefinition = { parser, - db, + get db() { + if (!db) { + db = new SequenceDB(); + } + return db; + }, renderer, styles, init: ({ wrap }) => { From d83b1a5dbce9cb6da17ec8e8589610f9d9eaebe0 Mon Sep 17 00:00:00 2001 From: saurabhg772244 Date: Wed, 12 Feb 2025 15:54:51 +0530 Subject: [PATCH 2/8] Refactored arrow function to regular function and assigned unique ID to messages during parsing. --- .../src/diagrams/sequence/sequenceDb.ts | 300 +++++++++++------- .../src/diagrams/sequence/sequenceDiagram.ts | 19 +- .../src/diagrams/sequence/sequenceRenderer.ts | 1 - .../mermaid/src/diagrams/sequence/types.ts | 1 + 4 files changed, 190 insertions(+), 131 deletions(-) diff --git a/packages/mermaid/src/diagrams/sequence/sequenceDb.ts b/packages/mermaid/src/diagrams/sequence/sequenceDb.ts index e71177b1f..ba5d464c5 100644 --- a/packages/mermaid/src/diagrams/sequence/sequenceDb.ts +++ b/packages/mermaid/src/diagrams/sequence/sequenceDb.ts @@ -45,7 +45,63 @@ export class SequenceDB implements DiagramDB { lastDestroyed: undefined, })); - public addBox = (data: { text: string; color: string; wrap: boolean }) => { + constructor() { + // Needed for JISON since it only supports direct properties + this.apply = this.apply.bind(this); + this.parseBoxData = this.parseBoxData.bind(this); + this.parseMessage = this.parseMessage.bind(this); + this.setWrap(getConfig().wrap); + + this.clear(); + + this.LINETYPE = { + SOLID: 0, + DOTTED: 1, + NOTE: 2, + SOLID_CROSS: 3, + DOTTED_CROSS: 4, + SOLID_OPEN: 5, + DOTTED_OPEN: 6, + LOOP_START: 10, + LOOP_END: 11, + ALT_START: 12, + ALT_ELSE: 13, + ALT_END: 14, + OPT_START: 15, + OPT_END: 16, + ACTIVE_START: 17, + ACTIVE_END: 18, + PAR_START: 19, + PAR_AND: 20, + PAR_END: 21, + RECT_START: 22, + RECT_END: 23, + SOLID_POINT: 24, + DOTTED_POINT: 25, + AUTONUMBER: 26, + CRITICAL_START: 27, + CRITICAL_OPTION: 28, + CRITICAL_END: 29, + BREAK_START: 30, + BREAK_END: 31, + PAR_OVER_START: 32, + BIDIRECTIONAL_SOLID: 33, + BIDIRECTIONAL_DOTTED: 34, + }; + + this.ARROWTYPE = { + FILLED: 0, + OPEN: 1, + }; + + this.PLACEMENT = { + LEFTOF: 0, + RIGHTOF: 1, + OVER: 2, + }; + } + + public addBox(data: { text: string; color: string; wrap: boolean }) { this.state.records.boxes.push({ name: data.text, wrap: data.wrap ?? this.autoWrap(), @@ -53,14 +109,14 @@ export class SequenceDB implements DiagramDB { actorKeys: [], }); this.state.records.currentBox = this.state.records.boxes.slice(-1)[0]; - }; + } - public addActor = ( + public addActor( id: string, name: string, description: { text: string; wrap?: boolean | null; type: string }, type: string - ) => { + ) { let assignedBox = this.state.records.currentBox; const old = this.state.records.actors.get(id); if (old) { @@ -112,9 +168,9 @@ export class SequenceDB implements DiagramDB { this.state.records.currentBox.actorKeys.push(id); } this.state.records.prevActor = id; - }; + } - private readonly activationCount = (part: string) => { + private activationCount(part: string) { let i; let count = 0; if (!part) { @@ -135,30 +191,31 @@ export class SequenceDB implements DiagramDB { } } return count; - }; + } - public addMessage = ( + public addMessage( idFrom: Message['from'], idTo: Message['to'], message: { text: string; wrap?: boolean }, answer: Message['answer'] - ) => { + ) { this.state.records.messages.push({ + id: this.state.records.messages.length.toString(), from: idFrom, to: idTo, message: message.text, wrap: message.wrap ?? this.autoWrap(), answer: answer, }); - }; + } - public addSignal = ( + public addSignal( idFrom?: Message['from'], idTo?: Message['to'], message?: { text: string; wrap: boolean }, messageType?: number, activate = false - ) => { + ) { if (messageType === this.LINETYPE.ACTIVE_END) { const cnt = this.activationCount(idFrom ?? ''); if (cnt < 1) { @@ -177,6 +234,7 @@ export class SequenceDB implements DiagramDB { } } this.state.records.messages.push({ + id: this.state.records.messages.length.toString(), from: idFrom, to: idTo, message: message?.text ?? '', @@ -185,52 +243,54 @@ export class SequenceDB implements DiagramDB { activate, }); return true; - }; + } - public hasAtLeastOneBox = () => { + public hasAtLeastOneBox() { return this.state.records.boxes.length > 0; - }; + } - public hasAtLeastOneBoxWithTitle = () => { + public hasAtLeastOneBoxWithTitle() { return this.state.records.boxes.some((b) => b.name); - }; + } - public getMessages = () => { + public getMessages() { return this.state.records.messages; - }; + } - public getBoxes = () => { + public getBoxes() { return this.state.records.boxes; - }; - public getActors = () => { + } + public getActors() { return this.state.records.actors; - }; - public getCreatedActors = () => { + } + public getCreatedActors() { return this.state.records.createdActors; - }; - public getDestroyedActors = () => { + } + public getDestroyedActors() { return this.state.records.destroyedActors; - }; - public getActor = (id: string) => { + } + public getActor(id: string) { // TODO: do we ever use this function in a way that it might return undefined? return this.state.records.actors.get(id)!; - }; - public getActorKeys = () => { + } + public getActorKeys() { return [...this.state.records.actors.keys()]; - }; - public enableSequenceNumbers = () => { + } + public enableSequenceNumbers() { this.state.records.sequenceNumbersEnabled = true; - }; - public disableSequenceNumbers = () => { + } + public disableSequenceNumbers() { this.state.records.sequenceNumbersEnabled = false; - }; - public showSequenceNumbers = () => this.state.records.sequenceNumbersEnabled; + } + public showSequenceNumbers() { + return this.state.records.sequenceNumbersEnabled; + } - public setWrap = (wrapSetting?: boolean) => { + public setWrap(wrapSetting?: boolean) { this.state.records.wrapEnabled = wrapSetting; - }; + } - private readonly extractWrap = (text?: string): { cleanedText?: string; wrap?: boolean } => { + private extractWrap(text?: string): { cleanedText?: string; wrap?: boolean } { if (text === undefined) { return {}; } @@ -239,23 +299,23 @@ export class SequenceDB implements DiagramDB { /^:?wrap:/.exec(text) !== null ? true : /^:?nowrap:/.exec(text) !== null ? false : undefined; const cleanedText = (wrap === undefined ? text : text.replace(/^:?(?:no)?wrap:/, '')).trim(); return { cleanedText, wrap }; - }; + } - public autoWrap = () => { + public autoWrap() { // if setWrap has been called, use that value, otherwise use the value from the config // TODO: refactor, always use the config value let setWrap update the config value if (this.state.records.wrapEnabled !== undefined) { return this.state.records.wrapEnabled; } return getConfig().sequence?.wrap ?? false; - }; + } - public clear = () => { + public clear() { this.state.reset(); commonClear(); - }; + } - public parseMessage = (str: string) => { + public parseMessage(str: string) { const trimmedStr = str.trim(); const { wrap, cleanedText } = this.extractWrap(trimmedStr); const message = { @@ -264,12 +324,12 @@ export class SequenceDB implements DiagramDB { }; log.debug(`parseMessage: ${JSON.stringify(message)}`); return message; - }; + } // We expect the box statement to be color first then description // The color can be rgb,rgba,hsl,hsla, or css code names #hex codes are not supported for now because of the way the char # is handled // We extract first segment as color, the rest of the line is considered as text - public parseBoxData = (str: string) => { + public parseBoxData(str: string) { const match = /^((?:rgba?|hsla?)\s*\(.*\)|\w*)(.*)$/.exec(str); let color = match?.[1] ? match[1].trim() : 'transparent'; let title = match?.[2] ? match[2].trim() : undefined; @@ -294,59 +354,59 @@ export class SequenceDB implements DiagramDB { color, wrap, }; + } + + public LINETYPE: { + SOLID: 0; + DOTTED: 1; + NOTE: 2; + SOLID_CROSS: 3; + DOTTED_CROSS: 4; + SOLID_OPEN: 5; + DOTTED_OPEN: 6; + LOOP_START: 10; + LOOP_END: 11; + ALT_START: 12; + ALT_ELSE: 13; + ALT_END: 14; + OPT_START: 15; + OPT_END: 16; + ACTIVE_START: 17; + ACTIVE_END: 18; + PAR_START: 19; + PAR_AND: 20; + PAR_END: 21; + RECT_START: 22; + RECT_END: 23; + SOLID_POINT: 24; + DOTTED_POINT: 25; + AUTONUMBER: 26; + CRITICAL_START: 27; + CRITICAL_OPTION: 28; + CRITICAL_END: 29; + BREAK_START: 30; + BREAK_END: 31; + PAR_OVER_START: 32; + BIDIRECTIONAL_SOLID: 33; + BIDIRECTIONAL_DOTTED: 34; }; - public LINETYPE = { - SOLID: 0, - DOTTED: 1, - NOTE: 2, - SOLID_CROSS: 3, - DOTTED_CROSS: 4, - SOLID_OPEN: 5, - DOTTED_OPEN: 6, - LOOP_START: 10, - LOOP_END: 11, - ALT_START: 12, - ALT_ELSE: 13, - ALT_END: 14, - OPT_START: 15, - OPT_END: 16, - ACTIVE_START: 17, - ACTIVE_END: 18, - PAR_START: 19, - PAR_AND: 20, - PAR_END: 21, - RECT_START: 22, - RECT_END: 23, - SOLID_POINT: 24, - DOTTED_POINT: 25, - AUTONUMBER: 26, - CRITICAL_START: 27, - CRITICAL_OPTION: 28, - CRITICAL_END: 29, - BREAK_START: 30, - BREAK_END: 31, - PAR_OVER_START: 32, - BIDIRECTIONAL_SOLID: 33, - BIDIRECTIONAL_DOTTED: 34, + public ARROWTYPE: { + FILLED: 0; + OPEN: 1; }; - public ARROWTYPE = { - FILLED: 0, - OPEN: 1, + public PLACEMENT: { + LEFTOF: 0; + RIGHTOF: 1; + OVER: 2; }; - public PLACEMENT = { - LEFTOF: 0, - RIGHTOF: 1, - OVER: 2, - }; - - public addNote = ( + public addNote( actor: { actor: string }, placement: Message['placement'], message: { text: string; wrap?: boolean } - ) => { + ) { const note: Note = { actor: actor, placement: placement, @@ -359,6 +419,7 @@ export class SequenceDB implements DiagramDB { const actors = [].concat(actor, actor); this.state.records.notes.push(note); this.state.records.messages.push({ + id: this.state.records.messages.length.toString(), from: actors[0], to: actors[1], message: message.text, @@ -366,9 +427,9 @@ export class SequenceDB implements DiagramDB { type: this.LINETYPE.NOTE, placement: placement, }); - }; + } - public addLinks = (actorId: string, text: { text: string }) => { + public addLinks(actorId: string, text: { text: string }) { // find the actor const actor = this.getActor(actorId); // JSON.parse the text @@ -382,9 +443,9 @@ export class SequenceDB implements DiagramDB { } catch (e) { log.error('error while parsing actor link text', e); } - }; + } - public addALink = (actorId: string, text: { text: string }) => { + public addALink(actorId: string, text: { text: string }) { // find the actor const actor = this.getActor(actorId); try { @@ -402,13 +463,9 @@ export class SequenceDB implements DiagramDB { } catch (e) { log.error('error while parsing actor link text', e); } - }; + } - /** - * @param actor - the actor to add the links to - * @param links - the links to add to the actor - */ - private readonly insertLinks = (actor: Actor, links: Record) => { + private insertLinks(actor: Actor, links: Record) { if (actor.links == null) { actor.links = links; } else { @@ -416,9 +473,9 @@ export class SequenceDB implements DiagramDB { actor.links[key] = links[key]; } } - }; + } - public addProperties = (actorId: string, text: { text: string }) => { + public addProperties(actorId: string, text: { text: string }) { // find the actor const actor = this.getActor(actorId); // JSON.parse the text @@ -430,13 +487,9 @@ export class SequenceDB implements DiagramDB { } catch (e) { log.error('error while parsing actor properties text', e); } - }; + } - /** - * @param actor - the actor to add the properties to - * @param properties - the properties to add to the actor's properties - */ - private readonly insertProperties = (actor: Actor, properties: Record) => { + private insertProperties(actor: Actor, properties: Record) { if (actor.properties == null) { actor.properties = properties; } else { @@ -444,13 +497,13 @@ export class SequenceDB implements DiagramDB { actor.properties[key] = properties[key]; } } - }; + } - private readonly boxEnd = () => { + private boxEnd() { this.state.records.currentBox = undefined; - }; + } - public addDetails = (actorId: string, text: { text: string }) => { + public addDetails(actorId: string, text: { text: string }) { // find the actor const actor = this.getActor(actorId); const elem = document.getElementById(text.text)!; @@ -470,18 +523,18 @@ export class SequenceDB implements DiagramDB { } catch (e) { log.error('error while parsing actor details text', e); } - }; + } - public getActorProperty = (actor: Actor, key: string) => { + public getActorProperty(actor: Actor, key: string) { if (actor?.properties !== undefined) { return actor.properties[key]; } return undefined; - }; + } // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-redundant-type-constituents - public apply = (param: any | AddMessageParams | AddMessageParams[]) => { + public apply(param: any | AddMessageParams | AddMessageParams[]) { if (Array.isArray(param)) { param.forEach((item) => { this.apply(item); @@ -490,6 +543,7 @@ export class SequenceDB implements DiagramDB { switch (param.type) { case 'sequenceIndex': this.state.records.messages.push({ + id: this.state.records.messages.length.toString(), from: undefined, to: undefined, message: { @@ -628,13 +682,15 @@ export class SequenceDB implements DiagramDB { break; } } - }; + } - public getAccTitle = getAccTitle; - public getDiagramTitle = getDiagramTitle; - public setDiagramTitle = setDiagramTitle; - public getConfig = () => getConfig().sequence; public setAccTitle = setAccTitle; public setAccDescription = setAccDescription; + public setDiagramTitle = setDiagramTitle; + public getAccTitle = getAccTitle; public getAccDescription = getAccDescription; + public getDiagramTitle = getDiagramTitle; + public getConfig() { + return getConfig().sequence; + } } diff --git a/packages/mermaid/src/diagrams/sequence/sequenceDiagram.ts b/packages/mermaid/src/diagrams/sequence/sequenceDiagram.ts index 80ccda5f9..f2b701712 100644 --- a/packages/mermaid/src/diagrams/sequence/sequenceDiagram.ts +++ b/packages/mermaid/src/diagrams/sequence/sequenceDiagram.ts @@ -3,21 +3,24 @@ import type { DiagramDefinition } from '../../diagram-api/types.js'; import parser from './parser/sequenceDiagram.jison'; import { SequenceDB } from './sequenceDb.js'; import styles from './styles.js'; +import { setConfig } from '../../diagram-api/diagramAPI.js'; import renderer from './sequenceRenderer.js'; - -let db: SequenceDB; +import type { MermaidConfig } from '../../config.type.js'; export const diagram: DiagramDefinition = { parser, get db() { - if (!db) { - db = new SequenceDB(); - } - return db; + return new SequenceDB(); }, renderer, styles, - init: ({ wrap }) => { - db.setWrap(wrap); + init: (cnf: MermaidConfig) => { + if (!cnf.sequence) { + cnf.sequence = {}; + } + if (cnf.wrap) { + cnf.sequence.wrap = cnf.wrap; + setConfig({ sequence: { wrap: cnf.wrap } }); + } }, }; diff --git a/packages/mermaid/src/diagrams/sequence/sequenceRenderer.ts b/packages/mermaid/src/diagrams/sequence/sequenceRenderer.ts index 951d84b86..389171d3c 100644 --- a/packages/mermaid/src/diagrams/sequence/sequenceRenderer.ts +++ b/packages/mermaid/src/diagrams/sequence/sequenceRenderer.ts @@ -1538,7 +1538,6 @@ const calculateLoopBounds = async function (messages, actors, _maxWidthPerActor, let current, noteModel, msgModel; for (const msg of messages) { - msg.id = utils.random({ length: 10 }); switch (msg.type) { case diagObj.db.LINETYPE.LOOP_START: case diagObj.db.LINETYPE.ALT_START: diff --git a/packages/mermaid/src/diagrams/sequence/types.ts b/packages/mermaid/src/diagrams/sequence/types.ts index 10c1c8ed3..7cf2ead9c 100644 --- a/packages/mermaid/src/diagrams/sequence/types.ts +++ b/packages/mermaid/src/diagrams/sequence/types.ts @@ -20,6 +20,7 @@ export interface Actor { } export interface Message { + id: string; from?: string; to?: string; message: From f454865b9773ce3843e42f3da929a0a907bfa1af Mon Sep 17 00:00:00 2001 From: saurabhg772244 Date: Wed, 12 Feb 2025 16:00:14 +0530 Subject: [PATCH 3/8] Updated unit tests to reflect new DB instance per parse. --- .../diagrams/sequence/sequenceDiagram.spec.js | 795 ++++++++---------- 1 file changed, 364 insertions(+), 431 deletions(-) diff --git a/packages/mermaid/src/diagrams/sequence/sequenceDiagram.spec.js b/packages/mermaid/src/diagrams/sequence/sequenceDiagram.spec.js index 474668edf..7fbf4f4e3 100644 --- a/packages/mermaid/src/diagrams/sequence/sequenceDiagram.spec.js +++ b/packages/mermaid/src/diagrams/sequence/sequenceDiagram.spec.js @@ -98,14 +98,15 @@ let diagram; describe('more than one sequence diagram', () => { it('should not have duplicated messages', async () => { const diagram1 = await Diagram.fromText(` - sequenceDiagram - Alice->Bob:Hello Bob, how are you? + sequenceDiagram + Alice->Bob:Hello Bob, how are you? Bob-->Alice: I am good thanks!`); expect(diagram1.db.getMessages()).toMatchInlineSnapshot(` [ { "activate": false, "from": "Alice", + "id": "0", "message": "Hello Bob, how are you?", "to": "Bob", "type": 5, @@ -114,6 +115,7 @@ describe('more than one sequence diagram', () => { { "activate": false, "from": "Bob", + "id": "1", "message": "I am good thanks!", "to": "Alice", "type": 6, @@ -131,6 +133,7 @@ describe('more than one sequence diagram', () => { { "activate": false, "from": "Alice", + "id": "0", "message": "Hello Bob, how are you?", "to": "Bob", "type": 5, @@ -139,6 +142,7 @@ describe('more than one sequence diagram', () => { { "activate": false, "from": "Bob", + "id": "1", "message": "I am good thanks!", "to": "Alice", "type": 6, @@ -158,6 +162,7 @@ describe('more than one sequence diagram', () => { { "activate": false, "from": "Alice", + "id": "0", "message": "Hello John, how are you?", "to": "John", "type": 5, @@ -166,6 +171,7 @@ describe('more than one sequence diagram', () => { { "activate": false, "from": "John", + "id": "1", "message": "I am good thanks!", "to": "Alice", "type": 6, @@ -221,27 +227,27 @@ Alice->Bob:Hello Bob, how are you? Note right of Bob: Bob thinks Bob-->Alice: I am good thanks!`; - await mermaidAPI.parse(str); - await diagram.renderer.draw(str, 'tst', '1.2.3', diagram); // needs to be rendered for the correct value of visibility auto numbers - expect(diagram.db.showSequenceNumbers()).toBe(true); + const diagram1 = await Diagram.fromText(str); + + await diagram1.renderer.draw(str, 'tst', '1.2.3', diagram1); // needs to be rendered for the correct value of visibility auto numbers + expect(diagram1.db.showSequenceNumbers()).toBe(true); }); it('should handle a sequenceDiagram definition with a title:', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram title: Diagram Title Alice->Bob:Hello Bob, how are you? Note right of Bob: Bob thinks -Bob-->Alice: I am good thanks!`; +Bob-->Alice: I am good thanks!`); - await mermaidAPI.parse(str); - const actors = diagram.db.getActors(); + const actors = diagram1.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); actors.get('Bob').description = 'Bob'; - expect(diagram.db.getAccDescription()).toBe(''); - const messages = diagram.db.getMessages(); - const title = diagram.db.getDiagramTitle(); + expect(diagram1.db.getAccDescription()).toBe(''); + const messages = diagram1.db.getMessages(); + const title = diagram1.db.getDiagramTitle(); expect(messages.length).toBe(3); expect(messages[0].from).toBe('Alice'); @@ -250,21 +256,20 @@ Bob-->Alice: I am good thanks!`; }); it('should handle a sequenceDiagram definition with a title without a :', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram title Diagram Title Alice->Bob:Hello Bob, how are you? Note right of Bob: Bob thinks -Bob-->Alice: I am good thanks!`; +Bob-->Alice: I am good thanks!`); - await mermaidAPI.parse(str); - const actors = diagram.db.getActors(); + const actors = diagram1.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); actors.get('Bob').description = 'Bob'; - expect(diagram.db.getAccDescription()).toBe(''); - const messages = diagram.db.getMessages(); - const title = diagram.db.getDiagramTitle(); + expect(diagram1.db.getAccDescription()).toBe(''); + const messages = diagram1.db.getMessages(); + const title = diagram1.db.getDiagramTitle(); expect(messages.length).toBe(3); expect(messages[0].from).toBe('Alice'); @@ -273,22 +278,20 @@ Bob-->Alice: I am good thanks!`; }); it('should handle a sequenceDiagram definition with a accessibility title and description (accDescr)', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram title: Diagram Title accTitle: This is the title accDescr: Accessibility Description Alice->Bob:Hello Bob, how are you? -`; +`); - await mermaidAPI.parse(str); - expect(diagram.db.getDiagramTitle()).toBe('Diagram Title'); - expect(diagram.db.getAccTitle()).toBe('This is the title'); - expect(diagram.db.getAccDescription()).toBe('Accessibility Description'); - const messages = diagram.db.getMessages(); + expect(diagram1.db.getDiagramTitle()).toBe('Diagram Title'); + expect(diagram1.db.getAccTitle()).toBe('This is the title'); + expect(diagram1.db.getAccDescription()).toBe('Accessibility Description'); }); it('should handle a sequenceDiagram definition with a accessibility title and multiline description (accDescr)', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram accTitle: This is the title accDescr { @@ -296,43 +299,39 @@ Accessibility Description } Alice->Bob:Hello Bob, how are you? -`; +`); - await mermaidAPI.parse(str); - expect(diagram.db.getAccTitle()).toBe('This is the title'); - expect(diagram.db.getAccDescription()).toBe('Accessibility\nDescription'); - const messages = diagram.db.getMessages(); + expect(diagram1.db.getAccTitle()).toBe('This is the title'); + expect(diagram1.db.getAccDescription()).toBe('Accessibility\nDescription'); }); it('should space in actor names', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram Alice->Bob:Hello Bob, how are - you? -Bob-->Alice: I am good thanks!`; +Bob-->Alice: I am good thanks!`); - await mermaidAPI.parse(str); - const actors = diagram.db.getActors(); + const actors = diagram1.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); actors.get('Bob').description = 'Bob'; - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages.length).toBe(2); expect(messages[0].from).toBe('Alice'); expect(messages[1].from).toBe('Bob'); }); it('should handle dashes in actor names', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram Alice-in-Wonderland->Bob:Hello Bob, how are - you? -Bob-->Alice-in-Wonderland:I am good thanks!`; +Bob-->Alice-in-Wonderland:I am good thanks!`); - await mermaidAPI.parse(str); - const actors = diagram.db.getActors(); + const actors = diagram1.db.getActors(); expect(actors.get('Alice-in-Wonderland').description).toBe('Alice-in-Wonderland'); expect(actors.get('Bob').description).toBe('Bob'); - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages.length).toBe(2); expect(messages[0].from).toBe('Alice-in-Wonderland'); @@ -340,20 +339,19 @@ Bob-->Alice-in-Wonderland:I am good thanks!`; }); it('should handle dashes in participant names', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram participant Alice-in-Wonderland participant Bob Alice-in-Wonderland->Bob:Hello Bob, how are - you? -Bob-->Alice-in-Wonderland:I am good thanks!`; +Bob-->Alice-in-Wonderland:I am good thanks!`); - await mermaidAPI.parse(str); - const actors = diagram.db.getActors(); + const actors = diagram1.db.getActors(); expect([...actors.keys()]).toEqual(['Alice-in-Wonderland', 'Bob']); expect(actors.get('Alice-in-Wonderland').description).toBe('Alice-in-Wonderland'); expect(actors.get('Bob').description).toBe('Bob'); - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages.length).toBe(2); expect(messages[0].from).toBe('Alice-in-Wonderland'); @@ -361,28 +359,26 @@ Bob-->Alice-in-Wonderland:I am good thanks!`; }); it('should alias participants', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram participant A as Alice participant B as Bob A->B:Hello Bob, how are you? -B-->A: I am good thanks!`; +B-->A: I am good thanks!`); - await mermaidAPI.parse(str); - - const actors = diagram.db.getActors(); + const actors = diagram1.db.getActors(); expect([...actors.keys()]).toEqual(['A', 'B']); expect(actors.get('A').description).toBe('Alice'); expect(actors.get('B').description).toBe('Bob'); - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages.length).toBe(2); expect(messages[0].from).toBe('A'); expect(messages[1].from).toBe('B'); }); it('should alias a mix of actors and participants apa12', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram actor Alice as Alice2 actor Bob @@ -392,11 +388,9 @@ sequenceDiagram Bob->>Alice: Hi Alice Alice->>John: Hi John John->>Mandy: Hi Mandy - Mandy ->>Joan: Hi Joan`; + Mandy ->>Joan: Hi Joan`); - await mermaidAPI.parse(str); - - const actors = diagram.db.getActors(); + const actors = diagram1.db.getActors(); expect([...actors.keys()]).toEqual(['Alice', 'Bob', 'John', 'Mandy', 'Joan']); expect(actors.get('Alice').description).toBe('Alice2'); expect(actors.get('Alice').type).toBe('actor'); @@ -404,219 +398,212 @@ sequenceDiagram expect(actors.get('John').type).toBe('participant'); expect(actors.get('Joan').type).toBe('participant'); - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages.length).toBe(5); expect(messages[0].from).toBe('Alice'); expect(messages[4].to).toBe('Joan'); }); it('should alias actors apa13', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram actor A as Alice actor B as Bob A->B:Hello Bob, how are you? -B-->A: I am good thanks!`; +B-->A: I am good thanks!`); - await mermaidAPI.parse(str); - - const actors = diagram.db.getActors(); + const actors = diagram1.db.getActors(); expect([...actors.keys()]).toEqual(['A', 'B']); expect(actors.get('A').description).toBe('Alice'); expect(actors.get('B').description).toBe('Bob'); - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages.length).toBe(2); expect(messages[0].from).toBe('A'); expect(messages[1].from).toBe('B'); }); it('should handle in async messages', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram -Alice-xBob:Hello Bob, how are you?`; +Alice-xBob:Hello Bob, how are you?`); - await mermaidAPI.parse(str); - const actors = diagram.db.getActors(); + const actors = diagram1.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); expect(actors.get('Bob').description).toBe('Bob'); - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages.length).toBe(1); - expect(messages[0].type).toBe(diagram.db.LINETYPE.SOLID_CROSS); + expect(messages[0].type).toBe(diagram1.db.LINETYPE.SOLID_CROSS); }); it('should handle in async dotted messages', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram -Alice--xBob:Hello Bob, how are you?`; +Alice--xBob:Hello Bob, how are you?`); - await mermaidAPI.parse(str); - const actors = diagram.db.getActors(); + const actors = diagram1.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); expect(actors.get('Bob').description).toBe('Bob'); - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages.length).toBe(1); - expect(messages[0].type).toBe(diagram.db.LINETYPE.DOTTED_CROSS); + expect(messages[0].type).toBe(diagram1.db.LINETYPE.DOTTED_CROSS); }); it('should handle in sync messages', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram -Alice-)Bob:Hello Bob, how are you?`; +Alice-)Bob:Hello Bob, how are you?`); - await mermaidAPI.parse(str); - const actors = diagram.db.getActors(); + const actors = diagram1.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); expect(actors.get('Bob').description).toBe('Bob'); - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages.length).toBe(1); - expect(messages[0].type).toBe(diagram.db.LINETYPE.SOLID_POINT); + expect(messages[0].type).toBe(diagram1.db.LINETYPE.SOLID_POINT); }); it('should handle in sync dotted messages', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram -Alice--)Bob:Hello Bob, how are you?`; +Alice--)Bob:Hello Bob, how are you?`); - await mermaidAPI.parse(str); - const actors = diagram.db.getActors(); + const actors = diagram1.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); expect(actors.get('Bob').description).toBe('Bob'); - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages.length).toBe(1); - expect(messages[0].type).toBe(diagram.db.LINETYPE.DOTTED_POINT); + expect(messages[0].type).toBe(diagram1.db.LINETYPE.DOTTED_POINT); }); it('should handle in arrow messages', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram -Alice->>Bob:Hello Bob, how are you?`; +Alice->>Bob:Hello Bob, how are you?`); - await mermaidAPI.parse(str); - const actors = diagram.db.getActors(); + const actors = diagram1.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); expect(actors.get('Bob').description).toBe('Bob'); - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages.length).toBe(1); - expect(messages[0].type).toBe(diagram.db.LINETYPE.SOLID); + expect(messages[0].type).toBe(diagram1.db.LINETYPE.SOLID); }); it('should handle in arrow messages', async () => { - const str = 'sequenceDiagram\n' + 'Alice-->>Bob:Hello Bob, how are you?'; + const diagram1 = await Diagram.fromText( + 'sequenceDiagram\n' + 'Alice-->>Bob:Hello Bob, how are you?' + ); - await mermaidAPI.parse(str); - const actors = diagram.db.getActors(); + const actors = diagram1.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); expect(actors.get('Bob').description).toBe('Bob'); - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages.length).toBe(1); - expect(messages[0].type).toBe(diagram.db.LINETYPE.DOTTED); + expect(messages[0].type).toBe(diagram1.db.LINETYPE.DOTTED); }); it('should handle bidirectional arrow messages', async () => { - const str = ` + const diagram1 = await Diagram.fromText( + ` sequenceDiagram -Alice<<->>Bob:Hello Bob, how are you?`; +Alice<<->>Bob:Hello Bob, how are you?` + ); - await mermaidAPI.parse(str); - const actors = diagram.db.getActors(); + const actors = diagram1.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); expect(actors.get('Bob').description).toBe('Bob'); - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages.length).toBe(1); - expect(messages[0].type).toBe(diagram.db.LINETYPE.BIDIRECTIONAL_SOLID); + expect(messages[0].type).toBe(diagram1.db.LINETYPE.BIDIRECTIONAL_SOLID); }); it('should handle bidirectional dotted arrow messages', async () => { - const str = ` + const diagram1 = await Diagram.fromText( + ` sequenceDiagram - Alice<<-->>Bob:Hello Bob, how are you?`; + Alice<<-->>Bob:Hello Bob, how are you?` + ); - await mermaidAPI.parse(str); - const actors = diagram.db.getActors(); + const actors = diagram1.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); expect(actors.get('Bob').description).toBe('Bob'); - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages.length).toBe(1); - expect(messages[0].type).toBe(diagram.db.LINETYPE.BIDIRECTIONAL_DOTTED); + expect(messages[0].type).toBe(diagram1.db.LINETYPE.BIDIRECTIONAL_DOTTED); }); it('should handle actor activation', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram Alice-->>Bob:Hello Bob, how are you? activate Bob Bob-->>Alice:Hello Alice, I'm fine and you? -deactivate Bob`; +deactivate Bob`); - await mermaidAPI.parse(str); - const actors = diagram.db.getActors(); + const actors = diagram1.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); expect(actors.get('Bob').description).toBe('Bob'); - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages.length).toBe(4); - expect(messages[0].type).toBe(diagram.db.LINETYPE.DOTTED); - expect(messages[1].type).toBe(diagram.db.LINETYPE.ACTIVE_START); + expect(messages[0].type).toBe(diagram1.db.LINETYPE.DOTTED); + expect(messages[1].type).toBe(diagram1.db.LINETYPE.ACTIVE_START); expect(messages[1].from).toBe('Bob'); - expect(messages[2].type).toBe(diagram.db.LINETYPE.DOTTED); - expect(messages[3].type).toBe(diagram.db.LINETYPE.ACTIVE_END); + expect(messages[2].type).toBe(diagram1.db.LINETYPE.DOTTED); + expect(messages[3].type).toBe(diagram1.db.LINETYPE.ACTIVE_END); expect(messages[3].from).toBe('Bob'); }); it('should handle actor one line notation activation', async () => { - const str = ` - sequenceDiagram - Alice-->>+Bob:Hello Bob, how are you? - Bob-->>- Alice:Hello Alice, I'm fine and you?`; + const diagram1 = await Diagram.fromText(` + sequenceDiagram + Alice-->>+Bob:Hello Bob, how are you? + Bob-->>- Alice:Hello Alice, I'm fine and you?`); - await mermaidAPI.parse(str); - const actors = diagram.db.getActors(); + const actors = diagram1.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); expect(actors.get('Bob').description).toBe('Bob'); - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages.length).toBe(4); - expect(messages[0].type).toBe(diagram.db.LINETYPE.DOTTED); + expect(messages[0].type).toBe(diagram1.db.LINETYPE.DOTTED); expect(messages[0].activate).toBeTruthy(); - expect(messages[1].type).toBe(diagram.db.LINETYPE.ACTIVE_START); + expect(messages[1].type).toBe(diagram1.db.LINETYPE.ACTIVE_START); expect(messages[1].from).toBe('Bob'); - expect(messages[2].type).toBe(diagram.db.LINETYPE.DOTTED); - expect(messages[3].type).toBe(diagram.db.LINETYPE.ACTIVE_END); + expect(messages[2].type).toBe(diagram1.db.LINETYPE.DOTTED); + expect(messages[3].type).toBe(diagram1.db.LINETYPE.ACTIVE_END); expect(messages[3].from).toBe('Bob'); }); it('should handle stacked activations', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram Alice-->>+Bob:Hello Bob, how are you? Bob-->>+Carol:Carol, let me introduce Alice? Bob-->>- Alice:Hello Alice, please meet Carol? - Carol->>- Bob:Oh Bob, I'm so happy to be here!`; + Carol->>- Bob:Oh Bob, I'm so happy to be here!`); - await mermaidAPI.parse(str); - const actors = diagram.db.getActors(); + const actors = diagram1.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); expect(actors.get('Bob').description).toBe('Bob'); - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages.length).toBe(8); - expect(messages[0].type).toBe(diagram.db.LINETYPE.DOTTED); - expect(messages[1].type).toBe(diagram.db.LINETYPE.ACTIVE_START); + expect(messages[0].type).toBe(diagram1.db.LINETYPE.DOTTED); + expect(messages[1].type).toBe(diagram1.db.LINETYPE.ACTIVE_START); expect(messages[1].from).toBe('Bob'); - expect(messages[2].type).toBe(diagram.db.LINETYPE.DOTTED); - expect(messages[3].type).toBe(diagram.db.LINETYPE.ACTIVE_START); + expect(messages[2].type).toBe(diagram1.db.LINETYPE.DOTTED); + expect(messages[3].type).toBe(diagram1.db.LINETYPE.ACTIVE_START); expect(messages[3].from).toBe('Carol'); - expect(messages[5].type).toBe(diagram.db.LINETYPE.ACTIVE_END); + expect(messages[5].type).toBe(diagram1.db.LINETYPE.ACTIVE_END); expect(messages[5].from).toBe('Bob'); - expect(messages[7].type).toBe(diagram.db.LINETYPE.ACTIVE_END); + expect(messages[7].type).toBe(diagram1.db.LINETYPE.ACTIVE_END); expect(messages[7].from).toBe('Carol'); }); it('should handle fail parsing when activating an inactive participant', async () => { @@ -646,102 +633,97 @@ deactivate Bob`; }); it('should handle comments in a sequenceDiagram', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram Alice->Bob: Hello Bob, how are you? %% Comment Note right of Bob: Bob thinks - Bob-->Alice: I am good thanks!`; + Bob-->Alice: I am good thanks!`); - await mermaidAPI.parse(str); - const actors = diagram.db.getActors(); + const actors = diagram1.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); actors.get('Bob').description = 'Bob'; - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages.length).toBe(3); expect(messages[0].from).toBe('Alice'); expect(messages[2].from).toBe('Bob'); }); it('should handle new lines in a sequenceDiagram', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram Alice->Bob: Hello Bob, how are you? %% Comment Note right of Bob: Bob thinks Bob-->Alice: I am good thanks! - `; + `); - await mermaidAPI.parse(str); - const actors = diagram.db.getActors(); + const actors = diagram1.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); actors.get('Bob').description = 'Bob'; - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages.length).toBe(3); expect(messages[0].from).toBe('Alice'); expect(messages[2].from).toBe('Bob'); }); it('should handle semicolons', async () => { - const str = ` -sequenceDiagram;Alice->Bob: Hello Bob, how are you?;Note right of Bob: Bob thinks;Bob-->Alice: I am good thanks!;`; + const diagram1 = await Diagram.fromText(` +sequenceDiagram;Alice->Bob: Hello Bob, how are you?;Note right of Bob: Bob thinks;Bob-->Alice: I am good thanks!;`); - await mermaidAPI.parse(str); - const actors = diagram.db.getActors(); + const actors = diagram1.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); actors.get('Bob').description = 'Bob'; - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages.length).toBe(3); expect(messages[0].from).toBe('Alice'); expect(messages[2].from).toBe('Bob'); }); it('should handle one leading space in lines in a sequenceDiagram', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram Alice->Bob: Hello Bob, how are you? %% Comment Note right of Bob: Bob thinks -Bob-->Alice: I am good thanks!`; +Bob-->Alice: I am good thanks!`); - await mermaidAPI.parse(str); - const actors = diagram.db.getActors(); + const actors = diagram1.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); actors.get('Bob').description = 'Bob'; - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages.length).toBe(3); expect(messages[0].from).toBe('Alice'); expect(messages[2].from).toBe('Bob'); }); it('should handle several leading spaces in lines in a sequenceDiagram', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram Alice->Bob: Hello Bob, how are you? %% Comment Note right of Bob: Bob thinks -Bob-->Alice: I am good thanks!`; +Bob-->Alice: I am good thanks!`); - await mermaidAPI.parse(str); - const actors = diagram.db.getActors(); + const actors = diagram1.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); actors.get('Bob').description = 'Bob'; - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages.length).toBe(3); expect(messages[0].from).toBe('Alice'); expect(messages[2].from).toBe('Bob'); }); it('should handle several leading spaces in lines in a sequenceDiagram', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram participant Alice participant Bob @@ -752,21 +734,20 @@ John->John: Fight against hypochondria Note right of John: Rational thoughts
prevail... John-->Alice: Great! John->Bob: How about you? -Bob-->John: Jolly good!`; +Bob-->John: Jolly good!`); - await mermaidAPI.parse(str); - const actors = diagram.db.getActors(); + const actors = diagram1.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); actors.get('Bob').description = 'Bob'; - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages.length).toBe(8); expect(messages[0].from).toBe('Alice'); expect(messages[2].from).toBe('John'); }); it('should handle different line breaks', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram participant 1 as multiline
text participant 2 as multiline
text @@ -780,17 +761,15 @@ note right of 3: multiline
text note right of 4: multiline
text 4->>1: multiline
text note right of 1: multiline
text -`; +`); - await mermaidAPI.parse(str); - - const actors = diagram.db.getActors(); + const actors = diagram1.db.getActors(); expect(actors.get('1').description).toBe('multiline
text'); expect(actors.get('2').description).toBe('multiline
text'); expect(actors.get('3').description).toBe('multiline
text'); expect(actors.get('4').description).toBe('multiline
text'); - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages[0].message).toBe('multiline
text'); expect(messages[1].message).toBe('multiline
text'); expect(messages[2].message).toBe('multiline
text'); @@ -801,7 +780,7 @@ note right of 1: multiline
text expect(messages[7].message).toBe('multiline
text'); }); it('should handle notes and messages without wrap specified', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram participant 1 participant 2 @@ -815,11 +794,9 @@ note right of 3:nowrap: single-line text note right of 4: multiline
text 4->>1:nowrap: multiline
text note right of 1:nowrap: multiline
text -`; +`); - await mermaidAPI.parse(str); - - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages[0].message).toBe('single-line text'); expect(messages[1].message).toBe('single-line text'); expect(messages[2].message).toBe('single-line text'); @@ -840,7 +817,7 @@ note right of 1:nowrap: multiline
text expect(messages[7].wrap).toBe(false); }); it('should handle notes and messages with wrap specified', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram participant 1 participant 2 @@ -850,11 +827,9 @@ participant 4 note right of 2:wrap: single-line text 2->>3:wrap: multiline
text note right of 3:wrap: multiline
text -`; +`); - await mermaidAPI.parse(str); - - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages[0].message).toBe('single-line text'); expect(messages[1].message).toBe('single-line text'); expect(messages[2].message).toBe('multiline
text'); @@ -865,53 +840,47 @@ note right of 3:wrap: multiline
text expect(messages[3].wrap).toBe(true); }); it('should handle notes and messages with nowrap or line breaks', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram participant 1 participant 2 1->>2: single-line text note right of 2: single-line text -`; +`); - await mermaidAPI.parse(str); - - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages[0].message).toBe('single-line text'); expect(messages[1].message).toBe('single-line text'); expect(messages[0].wrap).toBe(false); expect(messages[1].wrap).toBe(false); }); it('should handle notes over a single actor', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram Alice->Bob: Hello Bob, how are you? Note over Bob: Bob thinks -`; +`); - await mermaidAPI.parse(str); - - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages[1].from).toBe('Bob'); expect(messages[1].to).toBe('Bob'); }); it('should handle notes over multiple actors', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram Alice->Bob: Hello Bob, how are you? Note over Alice,Bob: confusion Note over Bob,Alice: resolution -`; +`); - await mermaidAPI.parse(str); - - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages[1].from).toBe('Alice'); expect(messages[1].to).toBe('Bob'); expect(messages[2].from).toBe('Bob'); expect(messages[2].to).toBe('Alice'); }); it('should handle loop statements', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram Alice->Bob: Hello Bob, how are you? @@ -920,21 +889,20 @@ Note right of Bob: Bob thinks loop Multiple happy responses Bob-->Alice: I am good thanks! -end`; +end`); - await mermaidAPI.parse(str); - const actors = diagram.db.getActors(); + const actors = diagram1.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); actors.get('Bob').description = 'Bob'; - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages.length).toBe(5); expect(messages[0].from).toBe('Alice'); expect(messages[1].from).toBe('Bob'); }); it('should add a rect around sequence', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram Alice->Bob: Hello Bob, how are you? %% Comment @@ -942,23 +910,22 @@ end`; Note right of Bob: Bob thinks Bob-->Alice: I am good thanks end - `; + `); - await mermaidAPI.parse(str); - const actors = diagram.db.getActors(); + const actors = diagram1.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); actors.get('Bob').description = 'Bob'; - const messages = diagram.db.getMessages(); - expect(messages[1].type).toEqual(diagram.db.LINETYPE.RECT_START); + const messages = diagram1.db.getMessages(); + expect(messages[1].type).toEqual(diagram1.db.LINETYPE.RECT_START); expect(messages[1].message).toBe('rgb(200, 255, 200)'); - expect(messages[2].type).toEqual(diagram.db.LINETYPE.NOTE); - expect(messages[3].type).toEqual(diagram.db.LINETYPE.DOTTED_OPEN); - expect(messages[4].type).toEqual(diagram.db.LINETYPE.RECT_END); + expect(messages[2].type).toEqual(diagram1.db.LINETYPE.NOTE); + expect(messages[3].type).toEqual(diagram1.db.LINETYPE.DOTTED_OPEN); + expect(messages[4].type).toEqual(diagram1.db.LINETYPE.RECT_END); }); it('should allow for nested rects', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram Alice->Bob: Hello Bob, how are you? %% Comment @@ -968,24 +935,24 @@ end`; end Bob-->Alice: I am good thanks end - `; - await mermaidAPI.parse(str); - const actors = diagram.db.getActors(); + `); + + const actors = diagram1.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); actors.get('Bob').description = 'Bob'; - const messages = diagram.db.getMessages(); - expect(messages[1].type).toEqual(diagram.db.LINETYPE.RECT_START); + const messages = diagram1.db.getMessages(); + expect(messages[1].type).toEqual(diagram1.db.LINETYPE.RECT_START); expect(messages[1].message).toBe('rgb(200, 255, 200)'); - expect(messages[2].type).toEqual(diagram.db.LINETYPE.RECT_START); + expect(messages[2].type).toEqual(diagram1.db.LINETYPE.RECT_START); expect(messages[2].message).toBe('rgb(0, 0, 0)'); - expect(messages[3].type).toEqual(diagram.db.LINETYPE.NOTE); - expect(messages[4].type).toEqual(diagram.db.LINETYPE.RECT_END); - expect(messages[5].type).toEqual(diagram.db.LINETYPE.DOTTED_OPEN); - expect(messages[6].type).toEqual(diagram.db.LINETYPE.RECT_END); + expect(messages[3].type).toEqual(diagram1.db.LINETYPE.NOTE); + expect(messages[4].type).toEqual(diagram1.db.LINETYPE.RECT_END); + expect(messages[5].type).toEqual(diagram1.db.LINETYPE.DOTTED_OPEN); + expect(messages[6].type).toEqual(diagram1.db.LINETYPE.RECT_END); }); it('should handle opt statements', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram Alice->Bob: Hello Bob, how are you? @@ -994,21 +961,20 @@ Note right of Bob: Bob thinks opt Perhaps a happy response Bob-->Alice: I am good thanks! -end`; +end`); - await mermaidAPI.parse(str); - const actors = diagram.db.getActors(); + const actors = diagram1.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); actors.get('Bob').description = 'Bob'; - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages.length).toBe(5); expect(messages[0].from).toBe('Alice'); expect(messages[1].from).toBe('Bob'); }); it('should handle alt statements', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram Alice->Bob: Hello Bob, how are you? @@ -1019,22 +985,21 @@ alt isWell Bob-->Alice: I am good thanks! else isSick Bob-->Alice: Feel sick... -end`; +end`); - await mermaidAPI.parse(str); - const actors = diagram.db.getActors(); + const actors = diagram1.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); actors.get('Bob').description = 'Bob'; - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages.length).toBe(7); expect(messages[0].from).toBe('Alice'); expect(messages[1].from).toBe('Bob'); }); it('should handle alt statements with multiple elses', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram Alice->Bob: Hello Bob, how are you? @@ -1047,41 +1012,40 @@ else isSick Bob-->Alice: Feel sick... else default Bob-->Alice: :-) -end`; - await mermaidAPI.parse(str); - const messages = diagram.db.getMessages(); +end`); + + const messages = diagram1.db.getMessages(); expect(messages.length).toBe(9); expect(messages[1].from).toBe('Bob'); - expect(messages[2].type).toBe(diagram.db.LINETYPE.ALT_START); + expect(messages[2].type).toBe(diagram1.db.LINETYPE.ALT_START); expect(messages[3].from).toBe('Bob'); - expect(messages[4].type).toBe(diagram.db.LINETYPE.ALT_ELSE); + expect(messages[4].type).toBe(diagram1.db.LINETYPE.ALT_ELSE); expect(messages[5].from).toBe('Bob'); - expect(messages[6].type).toBe(diagram.db.LINETYPE.ALT_ELSE); + expect(messages[6].type).toBe(diagram1.db.LINETYPE.ALT_ELSE); expect(messages[7].from).toBe('Bob'); - expect(messages[8].type).toBe(diagram.db.LINETYPE.ALT_END); + expect(messages[8].type).toBe(diagram1.db.LINETYPE.ALT_END); }); it('should handle critical statements without options', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram critical Establish a connection to the DB Service-->DB: connect - end`; + end`); - await mermaidAPI.parse(str); - const actors = diagram.db.getActors(); + const actors = diagram1.db.getActors(); expect(actors.get('Service').description).toBe('Service'); expect(actors.get('DB').description).toBe('DB'); - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages.length).toBe(3); - expect(messages[0].type).toBe(diagram.db.LINETYPE.CRITICAL_START); + expect(messages[0].type).toBe(diagram1.db.LINETYPE.CRITICAL_START); expect(messages[1].from).toBe('Service'); - expect(messages[2].type).toBe(diagram.db.LINETYPE.CRITICAL_END); + expect(messages[2].type).toBe(diagram1.db.LINETYPE.CRITICAL_END); }); it('should handle critical statements with options', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram critical Establish a connection to the DB Service-->DB: connect @@ -1089,53 +1053,51 @@ sequenceDiagram Service-->Service: Log error option Credentials rejected Service-->Service: Log different error - end`; + end`); - await mermaidAPI.parse(str); - const actors = diagram.db.getActors(); + const actors = diagram1.db.getActors(); expect(actors.get('Service').description).toBe('Service'); expect(actors.get('DB').description).toBe('DB'); - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages.length).toBe(7); - expect(messages[0].type).toBe(diagram.db.LINETYPE.CRITICAL_START); + expect(messages[0].type).toBe(diagram1.db.LINETYPE.CRITICAL_START); expect(messages[1].from).toBe('Service'); - expect(messages[2].type).toBe(diagram.db.LINETYPE.CRITICAL_OPTION); + expect(messages[2].type).toBe(diagram1.db.LINETYPE.CRITICAL_OPTION); expect(messages[3].from).toBe('Service'); - expect(messages[4].type).toBe(diagram.db.LINETYPE.CRITICAL_OPTION); + expect(messages[4].type).toBe(diagram1.db.LINETYPE.CRITICAL_OPTION); expect(messages[5].from).toBe('Service'); - expect(messages[6].type).toBe(diagram.db.LINETYPE.CRITICAL_END); + expect(messages[6].type).toBe(diagram1.db.LINETYPE.CRITICAL_END); }); it('should handle break statements', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram Consumer-->API: Book something API-->BookingService: Start booking process break when the booking process fails API-->Consumer: show failure end - API-->BillingService: Start billing process`; + API-->BillingService: Start billing process`); - await mermaidAPI.parse(str); - const actors = diagram.db.getActors(); + const actors = diagram1.db.getActors(); expect(actors.get('Consumer').description).toBe('Consumer'); expect(actors.get('API').description).toBe('API'); - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages.length).toBe(6); expect(messages[0].from).toBe('Consumer'); expect(messages[1].from).toBe('API'); - expect(messages[2].type).toBe(diagram.db.LINETYPE.BREAK_START); + expect(messages[2].type).toBe(diagram1.db.LINETYPE.BREAK_START); expect(messages[3].from).toBe('API'); - expect(messages[4].type).toBe(diagram.db.LINETYPE.BREAK_END); + expect(messages[4].type).toBe(diagram1.db.LINETYPE.BREAK_END); expect(messages[5].from).toBe('API'); }); it('should handle par statements a sequenceDiagram', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram par Parallel one Alice->>Bob: Hello Bob, how are you? @@ -1146,15 +1108,14 @@ Bob-->>Alice: Fine! and Parallel three Alice->>Bob: What do you think about it? Bob-->>Alice: It's good! -end`; +end`); - await mermaidAPI.parse(str); - const actors = diagram.db.getActors(); + const actors = diagram1.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); expect(actors.get('Bob').description).toBe('Bob'); - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages.length).toBe(10); expect(messages[0].message).toBe('Parallel one'); @@ -1162,21 +1123,20 @@ end`; expect(messages[2].from).toBe('Bob'); }); it('it should handle par_over statements', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram par_over Parallel overlap Alice ->> Bob: Message Note left of Alice: Alice note Note right of Bob: Bob note -end`; +end`); - await mermaidAPI.parse(str); - const actors = diagram.db.getActors(); + const actors = diagram1.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); expect(actors.get('Bob').description).toBe('Bob'); - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages.length).toBe(5); expect(messages[0].message).toBe('Parallel overlap'); @@ -1185,139 +1145,119 @@ end`; expect(messages[3].from).toBe('Bob'); }); it('should handle special characters in signals', async () => { - const str = 'sequenceDiagram\n' + 'Alice->Bob: -:<>,;# comment'; + const diagram1 = await Diagram.fromText('sequenceDiagram\n' + 'Alice->Bob: -:<>,;# comment'); - await mermaidAPI.parse(str); - - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages[0].message).toBe('-:<>,'); }); it('should handle special characters in notes', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram Alice->Bob: Hello Bob, how are you? -Note right of Bob: -:<>,;# comment`; +Note right of Bob: -:<>,;# comment`); - await mermaidAPI.parse(str); - - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages[1].message).toBe('-:<>,'); }); it('should handle special characters in loop', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram Alice->Bob: Hello Bob, how are you? loop -:<>,;# comment Bob-->Alice: I am good thanks! -end`; +end`); - await mermaidAPI.parse(str); - - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages[1].message).toBe('-:<>,'); }); it('should handle special characters in opt', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram Alice->Bob: Hello Bob, how are you? opt -:<>,;# comment Bob-->Alice: I am good thanks! -end`; +end`); - await mermaidAPI.parse(str); - - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages[1].message).toBe('-:<>,'); }); it('should handle special characters in alt', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram Alice->Bob: Hello Bob, how are you? alt -:<>,;# comment Bob-->Alice: I am good thanks! else ,<>:-#; comment Bob-->Alice: I am good thanks! -end`; +end`); - await mermaidAPI.parse(str); - - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages[1].message).toBe('-:<>,'); expect(messages[3].message).toBe(',<>:-'); }); it('should handle special characters in par', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram Alice->Bob: Hello Bob, how are you? par -:<>,;# comment Bob-->Alice: I am good thanks! and ,<>:-#; comment Bob-->Alice: I am good thanks! -end`; +end`); - await mermaidAPI.parse(str); - - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages[1].message).toBe('-:<>,'); expect(messages[3].message).toBe(',<>:-'); }); it('should handle no-label loop', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram Alice->Bob: Hello Bob, how are you? loop Bob-->Alice: I am good thanks! -end`; +end`); - await mermaidAPI.parse(str); - - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages[1].message).toBe(''); expect(messages[2].message).toBe('I am good thanks!'); }); it('should handle no-label opt', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram Alice->Bob: Hello Bob, how are you? opt # comment Bob-->Alice: I am good thanks! -end`; +end`); - await mermaidAPI.parse(str); - - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages[1].message).toBe(''); expect(messages[2].message).toBe('I am good thanks!'); }); it('should handle no-label alt', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram Alice->Bob: Hello Bob, how are you? alt;Bob-->Alice: I am good thanks! else # comment Bob-->Alice: I am good thanks! -end`; +end`); - await mermaidAPI.parse(str); - - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages[1].message).toBe(''); expect(messages[2].message).toBe('I am good thanks!'); expect(messages[3].message).toBe(''); expect(messages[4].message).toBe('I am good thanks!'); }); it('should handle no-label par', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram Alice->Bob: Hello Bob, how are you? par;Bob-->Alice: I am good thanks! and # comment Bob-->Alice: I am good thanks! -end`; +end`); - await mermaidAPI.parse(str); - - const messages = diagram.db.getMessages(); + const messages = diagram1.db.getMessages(); expect(messages[1].message).toBe(''); expect(messages[2].message).toBe('I am good thanks!'); expect(messages[3].message).toBe(''); @@ -1325,7 +1265,7 @@ end`; }); it('should handle links', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram participant a as Alice participant b as Bob @@ -1336,10 +1276,9 @@ links a: { "On-Call": "https://oncall.contoso.com/?svc=alice" } link a: Endpoint @ https://alice.contoso.com link a: Swagger @ https://swagger.contoso.com link a: Tests @ https://tests.contoso.com/?svc=alice@contoso.com -`; +`); - await mermaidAPI.parse(str); - const actors = diagram.db.getActors(); + const actors = diagram1.db.getActors(); expect(actors.get('a').links.Repo).toBe('https://repo.contoso.com/'); expect(actors.get('b').links.Repo).toBe(undefined); expect(actors.get('a').links.Dashboard).toBe('https://dashboard.contoso.com/'); @@ -1353,17 +1292,16 @@ link a: Tests @ https://tests.contoso.com/?svc=alice@contoso.com it('should handle properties EXPERIMENTAL: USE WITH CAUTION', async () => { //Be aware that the syntax for "properties" is likely to be changed. - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram participant a as Alice participant b as Bob participant c as Charlie properties a: {"class": "internal-service-actor", "icon": "@clock"} properties b: {"class": "external-service-actor", "icon": "@computer"} -`; +`); - await mermaidAPI.parse(str); - const actors = diagram.db.getActors(); + const actors = diagram1.db.getActors(); expect(actors.get('a').properties.class).toBe('internal-service-actor'); expect(actors.get('b').properties.class).toBe('external-service-actor'); expect(actors.get('a').properties.icon).toBe('@clock'); @@ -1372,7 +1310,7 @@ properties b: {"class": "external-service-actor", "icon": "@computer"} }); it('should handle box', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram box green Group 1 participant a as Alice @@ -1385,17 +1323,16 @@ links a: { "On-Call": "https://oncall.contoso.com/?svc=alice" } link a: Endpoint @ https://alice.contoso.com link a: Swagger @ https://swagger.contoso.com link a: Tests @ https://tests.contoso.com/?svc=alice@contoso.com -`; +`); - await mermaidAPI.parse(str); - const boxes = diagram.db.getBoxes(); + const boxes = diagram1.db.getBoxes(); expect(boxes[0].name).toEqual('Group 1'); expect(boxes[0].actorKeys).toEqual(['a', 'b']); expect(boxes[0].fill).toEqual('green'); }); it('should handle box without color', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram box Group 1 participant a as Alice @@ -1408,17 +1345,16 @@ link a: Tests @ https://tests.contoso.com/?svc=alice@contoso.com link a: Endpoint @ https://alice.contoso.com link a: Swagger @ https://swagger.contoso.com link a: Tests @ https://tests.contoso.com/?svc=alice@contoso.com - `; + `); - await mermaidAPI.parse(str); - const boxes = diagram.db.getBoxes(); + const boxes = diagram1.db.getBoxes(); expect(boxes[0].name).toEqual('Group 1'); expect(boxes[0].actorKeys).toEqual(['a', 'b']); expect(boxes[0].fill).toEqual('transparent'); }); it('should handle box without description', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram box Aqua participant a as Alice @@ -1431,17 +1367,16 @@ link a: Tests @ https://tests.contoso.com/?svc=alice@contoso.com link a: Endpoint @ https://alice.contoso.com link a: Swagger @ https://swagger.contoso.com link a: Tests @ https://tests.contoso.com/?svc=alice@contoso.com - `; + `); - await mermaidAPI.parse(str); - const boxes = diagram.db.getBoxes(); + const boxes = diagram1.db.getBoxes(); expect(boxes[0].name).toBeFalsy(); expect(boxes[0].actorKeys).toEqual(['a', 'b']); expect(boxes[0].fill).toEqual('Aqua'); }); it('should handle simple actor creation', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram participant a as Alice a ->>b: Hello Bob? @@ -1450,10 +1385,9 @@ link a: Tests @ https://tests.contoso.com/?svc=alice@contoso.com c ->> b: Hello b? create actor d as Donald a ->> d: Hello Donald? - `; - await mermaidAPI.parse(str); - const actors = diagram.db.getActors(); - const createdActors = diagram.db.getCreatedActors(); + `); + const actors = diagram1.db.getActors(); + const createdActors = diagram1.db.getCreatedActors(); expect(actors.get('c').name).toEqual('c'); expect(actors.get('c').description).toEqual('c'); expect(actors.get('c').type).toEqual('participant'); @@ -1464,7 +1398,7 @@ link a: Tests @ https://tests.contoso.com/?svc=alice@contoso.com expect(createdActors.get('d')).toEqual(3); }); it('should handle simple actor destruction', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram participant a as Alice a ->>b: Hello Bob? @@ -1473,14 +1407,13 @@ link a: Tests @ https://tests.contoso.com/?svc=alice@contoso.com b ->> c: Where is Alice? destroy c b ->> c: Where are you? - `; - await mermaidAPI.parse(str); - const destroyedActors = diagram.db.getDestroyedActors(); + `); + const destroyedActors = diagram1.db.getDestroyedActors(); expect(destroyedActors.get('a')).toEqual(1); expect(destroyedActors.get('c')).toEqual(3); }); it('should handle the creation and destruction of the same actor', async () => { - const str = ` + const diagram2 = await Diagram.fromText(` sequenceDiagram a ->>b: Hello Bob? create participant c @@ -1488,10 +1421,9 @@ link a: Tests @ https://tests.contoso.com/?svc=alice@contoso.com c ->> b: Hello b? destroy c b ->> c : Bye c ! - `; - await mermaidAPI.parse(str); - const createdActors = diagram.db.getCreatedActors(); - const destroyedActors = diagram.db.getDestroyedActors(); + `); + const createdActors = diagram2.db.getCreatedActors(); + const destroyedActors = diagram2.db.getDestroyedActors(); expect(createdActors.get('c')).toEqual(1); expect(destroyedActors.get('c')).toEqual(3); }); @@ -1571,7 +1503,7 @@ describe('when checking the bounds in a sequenceDiagram', function () { expect(bounds.stopx).toBe(300); expect(bounds.stopy).toBe(400); }); - it('should handle multiple loops withtout expanding the bounds', () => { + it('should handle multiple loops without expanding the bounds', () => { diagram.renderer.bounds.insert(100, 100, 1000, 1000); diagram.renderer.bounds.verticalPos = 200; diagram.renderer.bounds.newLoop(); @@ -1676,11 +1608,11 @@ it should handle one actor, when textPlacement is ${textPlacement}`, async () => sequenceDiagram participant Alice`; - await mermaidAPI.parse(str); + const diagram1 = await Diagram.fromText(str); // diagram.renderer.setConf(mermaidAPI.getConfig().sequence); - await diagram.renderer.draw(str, 'tst', '1.2.3', diagram); + await diagram1.renderer.draw(str, 'tst', '1.2.3', diagram1); - const { bounds } = diagram.renderer.bounds.getBounds(); + const { bounds } = diagram1.renderer.bounds.getBounds(); expect(bounds.startx).toBe(0); expect(bounds.starty).toBe(0); expect(bounds.stopx).toBe(conf.width); @@ -1688,16 +1620,14 @@ participant Alice`; }); }); it('should handle same actor with different whitespace properly', async () => { - const str = ` + const diagram1 = await Diagram.fromText(` sequenceDiagram participant Alice participant Alice participant Alice -`; +`); - await mermaidAPI.parse(str); - - const actors = diagram.db.getActors(); + const actors = diagram1.db.getActors(); expect([...actors.keys()]).toEqual(['Alice']); }); it('should handle one actor and a centered note', async () => { @@ -1706,12 +1636,12 @@ sequenceDiagram participant Alice Note over Alice: Alice thinks `; + const diagram1 = await Diagram.fromText(str); expect(mermaidAPI.getConfig().sequence.mirrorActors).toBeFalsy(); - await mermaidAPI.parse(str); - await diagram.renderer.draw(str, 'tst', '1.2.3', diagram); + await diagram1.renderer.draw(str, 'tst', '1.2.3', diagram1); - const { bounds, models } = diagram.renderer.bounds.getBounds(); + const { bounds, models } = diagram1.renderer.bounds.getBounds(); expect(bounds.startx).toBe(0); expect(bounds.starty).toBe(0); expect(bounds.stopx).toBe(conf.width); @@ -1724,10 +1654,10 @@ sequenceDiagram participant Alice Note left of Alice: Alice thinks`; - await mermaidAPI.parse(str); - await diagram.renderer.draw(str, 'tst', '1.2.3', diagram); + const diagram1 = await Diagram.fromText(str); + await diagram1.renderer.draw(str, 'tst', '1.2.3', diagram1); - const { bounds, models } = diagram.renderer.bounds.getBounds(); + const { bounds, models } = diagram1.renderer.bounds.getBounds(); expect(bounds.startx).toBe(-(conf.width / 2) - conf.actorMargin / 2); expect(bounds.starty).toBe(0); expect(bounds.stopx).toBe(conf.width); @@ -1740,10 +1670,10 @@ sequenceDiagram participant Alice Note right of Alice: Alice thinks`; - await mermaidAPI.parse(str); - await diagram.renderer.draw(str, 'tst', '1.2.3', diagram); + const diagram1 = await Diagram.fromText(str); + await diagram1.renderer.draw(str, 'tst', '1.2.3', diagram1); - const { bounds, models } = diagram.renderer.bounds.getBounds(); + const { bounds, models } = diagram1.renderer.bounds.getBounds(); expect(bounds.startx).toBe(0); expect(bounds.starty).toBe(0); expect(bounds.stopx).toBe(conf.width / 2 + conf.actorMargin / 2 + conf.width); @@ -1755,10 +1685,10 @@ Note right of Alice: Alice thinks`; sequenceDiagram Alice->Bob: Hello Bob, how are you?`; - await mermaidAPI.parse(str); - await diagram.renderer.draw(str, 'tst', '1.2.3', diagram); + const diagram1 = await Diagram.fromText(str); + await diagram1.renderer.draw(str, 'tst', '1.2.3', diagram1); - const { bounds, models } = diagram.renderer.bounds.getBounds(); + const { bounds, models } = diagram1.renderer.bounds.getBounds(); expect(bounds.startx).toBe(0); expect(bounds.starty).toBe(0); expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin); @@ -1773,10 +1703,10 @@ participant Bob end Alice->Bob: Hello Bob, how are you?`; - await mermaidAPI.parse(str); - await diagram.renderer.draw(str, 'tst', '1.2.3', diagram); + const diagram1 = await Diagram.fromText(str); + await diagram1.renderer.draw(str, 'tst', '1.2.3', diagram1); - const { bounds, models } = diagram.renderer.bounds.getBounds(); + const { bounds, models } = diagram1.renderer.bounds.getBounds(); expect(bounds.startx).toBe(0); expect(bounds.starty).toBe(0); expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin + conf.boxTextMargin * 2); @@ -1787,11 +1717,11 @@ Alice->Bob: Hello Bob, how are you?`; %%{init: {'logLevel': 0}}%% sequenceDiagram Alice->Bob: Hello Bob, how are you?`; - await mermaidAPI.parse(str); - await diagram.renderer.draw(str, 'tst', '1.2.3', diagram); + const diagram1 = await Diagram.fromText(str); + await diagram1.renderer.draw(str, 'tst', '1.2.3', diagram1); - const { bounds, models } = diagram.renderer.bounds.getBounds(); + const { bounds, models } = diagram1.renderer.bounds.getBounds(); const mermaid = mermaidAPI.getConfig(); expect(mermaid.logLevel).toBe(0); expect(bounds.startx).toBe(0); @@ -1803,16 +1733,15 @@ Alice->Bob: Hello Bob, how are you?`; const str = ` %%{init: { 'logLevel': 0}}%% sequenceDiagram -%%{ -wrap -}%% +%%{wrap}%% Alice->Bob: Hello Bob, how are you?`; await mermaidAPI.parse(str); - await diagram.renderer.draw(str, 'tst', '1.2.3', diagram); + const diagram1 = await Diagram.fromText(str); + await diagram1.renderer.draw(str, 'tst', '1.2.3', diagram1); - const msgs = diagram.db.getMessages(); - const { bounds, models } = diagram.renderer.bounds.getBounds(); + const msgs = diagram1.db.getMessages(); + const { bounds, models } = diagram1.renderer.bounds.getBounds(); const mermaid = mermaidAPI.getConfig(); expect(mermaid.logLevel).toBe(0); expect(bounds.startx).toBe(0); @@ -1828,11 +1757,11 @@ Alice->Bob: Hello Bob, how are you? Note over Alice,Bob: Looks Note over Bob,Alice: Looks back `; + const diagram1 = await Diagram.fromText(str); // mermaidAPI.initialize({logLevel:0}) - await mermaidAPI.parse(str); - await diagram.renderer.draw(str, 'tst', '1.2.3', diagram); + await diagram1.renderer.draw(str, 'tst', '1.2.3', diagram1); - const { bounds, models } = diagram.renderer.bounds.getBounds(); + const { bounds, models } = diagram1.renderer.bounds.getBounds(); expect(bounds.startx).toBe(0); expect(bounds.starty).toBe(0); expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin); @@ -1844,10 +1773,10 @@ sequenceDiagram Alice->Bob: Hello Bob, how are you? Bob->Alice: Fine!`; - await mermaidAPI.parse(str); - await diagram.renderer.draw(str, 'tst', '1.2.3', diagram); + const diagram1 = await Diagram.fromText(str); + await diagram1.renderer.draw(str, 'tst', '1.2.3', diagram1); - const { bounds, models } = diagram.renderer.bounds.getBounds(); + const { bounds, models } = diagram1.renderer.bounds.getBounds(); expect(bounds.startx).toBe(0); expect(bounds.starty).toBe(0); expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin); @@ -1860,10 +1789,10 @@ Alice->Bob: Hello Bob, how are you? Note right of Bob: Bob thinks Bob->Alice: Fine!`; - await mermaidAPI.parse(str); - await diagram.renderer.draw(str, 'tst', '1.2.3', diagram); + const diagram1 = await Diagram.fromText(str); + await diagram1.renderer.draw(str, 'tst', '1.2.3', diagram1); - const { bounds, models } = diagram.renderer.bounds.getBounds(); + const { bounds, models } = diagram1.renderer.bounds.getBounds(); expect(bounds.startx).toBe(0); expect(bounds.starty).toBe(0); @@ -1879,10 +1808,10 @@ Alice->Bob: Hello Bob, how are you? Note left of Alice: Bob thinks Bob->Alice: Fine!`; - await mermaidAPI.parse(str); - await diagram.renderer.draw(str, 'tst', '1.2.3', diagram); + const diagram1 = await Diagram.fromText(str); + await diagram1.renderer.draw(str, 'tst', '1.2.3', diagram1); - const { bounds, models } = diagram.renderer.bounds.getBounds(); + const { bounds, models } = diagram1.renderer.bounds.getBounds(); expect(bounds.startx).toBe(-(conf.width / 2) - conf.actorMargin / 2); expect(bounds.starty).toBe(0); @@ -1896,11 +1825,11 @@ Alice->>Bob:wrap: Hello Bob, how are you? If you are not available right now, I Note left of Alice: Bob thinks Bob->>Alice: Fine!`; - await mermaidAPI.parse(str); - await diagram.renderer.draw(str, 'tst', '1.2.3', diagram); + const diagram1 = await Diagram.fromText(str); + await diagram1.renderer.draw(str, 'tst', '1.2.3', diagram1); - const { bounds, models } = diagram.renderer.bounds.getBounds(); - const msgs = diagram.db.getMessages(); + const { bounds, models } = diagram1.renderer.bounds.getBounds(); + const msgs = diagram1.db.getMessages(); expect(bounds.startx).toBe(-(conf.width / 2) - conf.actorMargin / 2); expect(bounds.starty).toBe(0); expect(msgs[0].wrap).toBe(true); @@ -1918,10 +1847,11 @@ Note left of Alice: Bob thinks Bob->>Alice: Fine!`; await mermaidAPI.parse(str); - await diagram.renderer.draw(str, 'tst', '1.2.3', diagram); + const diagram1 = await Diagram.fromText(str); + await diagram1.renderer.draw(str, 'tst', '1.2.3', diagram1); - const { bounds, models } = diagram.renderer.bounds.getBounds(); - const msgs = diagram.db.getMessages(); + const { bounds, models } = diagram1.renderer.bounds.getBounds(); + const msgs = diagram1.db.getMessages(); const mermaid = mermaidAPI.getConfig(); expect(bounds.startx).toBe(-(conf.width / 2) - conf.actorMargin / 2); expect(bounds.starty).toBe(0); @@ -1941,10 +1871,12 @@ Note left of Alice: Bob thinks Bob->>Alice: Fine!`; await mermaidAPI.parse(str); - await diagram.renderer.draw(str, 'tst', '1.2.3', diagram); + const diagram1 = await Diagram.fromText(str); - const { bounds, models } = diagram.renderer.bounds.getBounds(); - const msgs = diagram.db.getMessages(); + await diagram1.renderer.draw(str, 'tst', '1.2.3', diagram1); + + const { bounds, models } = diagram1.renderer.bounds.getBounds(); + const msgs = diagram1.db.getMessages(); const mermaid = mermaidAPI.getConfig(); expect(bounds.startx).toBe(-(conf.width / 2) - conf.actorMargin / 2); expect(bounds.starty).toBe(0); @@ -1963,10 +1895,11 @@ Note left of Alice: Bob thinks Bob->>Alice: Fine!`; // mermaidAPI.initialize({ logLevel: 0 }); await mermaidAPI.parse(str); - await diagram.renderer.draw(str, 'tst', '1.2.3', diagram); + const diagram1 = await Diagram.fromText(str); + await diagram1.renderer.draw(str, 'tst', '1.2.3', diagram1); - const { bounds, models } = diagram.renderer.bounds.getBounds(); - const msgs = diagram.db.getMessages(); + const { bounds, models } = diagram1.renderer.bounds.getBounds(); + const msgs = diagram1.db.getMessages(); const mermaid = mermaidAPI.getConfig(); expect(bounds.startx).toBe(-(conf.width / 2) - conf.actorMargin / 2); expect(bounds.starty).toBe(0); @@ -1986,10 +1919,10 @@ Alice->Bob: Hello Bob, how are you? loop Cheers Bob->Alice: Fine! end`; - await mermaidAPI.parse(str); - await diagram.renderer.draw(str, 'tst', '1.2.3', diagram); - const { bounds, models } = diagram.renderer.bounds.getBounds(); + const diagram1 = await Diagram.fromText(str); + await diagram1.renderer.draw(str, 'tst', '1.2.3', diagram1); + const { bounds, models } = diagram1.renderer.bounds.getBounds(); expect(bounds.startx).toBe(0); expect(bounds.starty).toBe(0); @@ -2004,9 +1937,9 @@ end`; Bob->Alice: I feel surrounded by darkness end `; - await mermaidAPI.parse(str); - await diagram.renderer.draw(str, 'tst', '1.2.3', diagram); - const { bounds, models } = diagram.renderer.bounds.getBounds(); + const diagram1 = await Diagram.fromText(str); + await diagram1.renderer.draw(str, 'tst', '1.2.3', diagram1); + const { bounds, models } = diagram1.renderer.bounds.getBounds(); expect(bounds.startx).toBe(0); expect(bounds.starty).toBe(0); @@ -2050,11 +1983,11 @@ describe('when rendering a sequenceDiagram with actor mirror activated', () => { const str = ` sequenceDiagram participant Alice`; - diagram.renderer.bounds.init(); - await mermaidAPI.parse(str); - await diagram.renderer.draw(str, 'tst', '1.2.3', diagram); + const diagram1 = await Diagram.fromText(str); + diagram1.renderer.bounds.init(); + await diagram1.renderer.draw(str, 'tst', '1.2.3', diagram1); - const { bounds, models } = diagram.renderer.bounds.getBounds(); + const { bounds, models } = diagram1.renderer.bounds.getBounds(); expect(bounds.startx).toBe(0); expect(bounds.starty).toBe(0); expect(bounds.stopx).toBe(conf.width); From ffa7804af0701b3d044d6794e36bd9132d6c7e8d Mon Sep 17 00:00:00 2001 From: saurabhg772244 Date: Wed, 12 Feb 2025 16:04:22 +0530 Subject: [PATCH 4/8] added changeset --- .changeset/silver-olives-marry.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/silver-olives-marry.md diff --git a/.changeset/silver-olives-marry.md b/.changeset/silver-olives-marry.md new file mode 100644 index 000000000..d709b17ba --- /dev/null +++ b/.changeset/silver-olives-marry.md @@ -0,0 +1,5 @@ +--- +'mermaid': patch +--- + +fix: `mermaidAPI.getDiagramFromText()` now returns a new different db for each sequence diagram. Added unique IDs for messages. From 6ca8f46d3710e32972544716c9de6f19ad106bae Mon Sep 17 00:00:00 2001 From: saurabhg772244 Date: Wed, 12 Feb 2025 16:15:06 +0530 Subject: [PATCH 5/8] Updated unit tests. --- packages/mermaid/src/mermaidAPI.spec.ts | 29 +++++++++---------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/packages/mermaid/src/mermaidAPI.spec.ts b/packages/mermaid/src/mermaidAPI.spec.ts index e51d419d3..1a2289df2 100644 --- a/packages/mermaid/src/mermaidAPI.spec.ts +++ b/packages/mermaid/src/mermaidAPI.spec.ts @@ -67,10 +67,11 @@ vi.mock('stylis', () => { import { compile, serialize } from 'stylis'; import { Diagram } from './Diagram.js'; -import { decodeEntities, encodeEntities } from './utils.js'; -import { toBase64 } from './utils/base64.js'; import { ClassDB } from './diagrams/class/classDb.js'; import { FlowDB } from './diagrams/flowchart/flowDb.js'; +import { SequenceDB } from './diagrams/sequence/sequenceDb.js'; +import { decodeEntities, encodeEntities } from './utils.js'; +import { toBase64 } from './utils/base64.js'; /** * @see https://vitest.dev/guide/mocking.html Mock part of a module @@ -899,28 +900,18 @@ graph TD;A--x|text including URL space|B;`) ); const sequenceDiagram2 = await mermaidAPI.getDiagramFromText( `sequenceDiagram + actor A1 Alice->>+John: Hello John, how are you? Alice->>+John: John, can you hear me? John-->>-Alice: Hi Alice, I can hear you! John-->>-Alice: I feel great!` ); - // Since sequenceDiagram will return same Db object each time, we can compare the db to be same. - expect(sequenceDiagram1.db).toBe(sequenceDiagram2.db); + + // Since sequenceDiagram will return new Db object each time, we can compare the db to be different. + expect(sequenceDiagram1.db).not.toBe(sequenceDiagram2.db); + assert(sequenceDiagram1.db instanceof SequenceDB); + assert(sequenceDiagram2.db instanceof SequenceDB); + expect(sequenceDiagram1.db.getActors()).not.toEqual(sequenceDiagram2.db.getActors()); }); }); - - // Sequence Diagram currently uses a singleton DB, so this test will fail - it.fails('should not modify db when rendering different sequence diagrams', async () => { - const sequenceDiagram1 = await mermaidAPI.getDiagramFromText( - `sequenceDiagram - Alice->>Bob: Hello Bob, how are you? - Bob-->>John: How about you John?` - ); - const sequenceDiagram2 = await mermaidAPI.getDiagramFromText( - `sequenceDiagram - Alice->>Bob: Hello Bob, how are you? - Bob-->>John: How about you John?` - ); - expect(sequenceDiagram1.db).not.toBe(sequenceDiagram2.db); - }); }); From 0a1a11260597d07161298ce2f09620d06bbac4b5 Mon Sep 17 00:00:00 2001 From: saurabhg772244 Date: Fri, 14 Feb 2025 17:51:17 +0530 Subject: [PATCH 6/8] Move setWrap below clear in constructor. --- packages/mermaid/src/diagrams/sequence/sequenceDb.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/mermaid/src/diagrams/sequence/sequenceDb.ts b/packages/mermaid/src/diagrams/sequence/sequenceDb.ts index ba5d464c5..410d48e33 100644 --- a/packages/mermaid/src/diagrams/sequence/sequenceDb.ts +++ b/packages/mermaid/src/diagrams/sequence/sequenceDb.ts @@ -50,10 +50,11 @@ export class SequenceDB implements DiagramDB { this.apply = this.apply.bind(this); this.parseBoxData = this.parseBoxData.bind(this); this.parseMessage = this.parseMessage.bind(this); - this.setWrap(getConfig().wrap); this.clear(); + this.setWrap(getConfig().wrap); + this.LINETYPE = { SOLID: 0, DOTTED: 1, From 451c886f506056420a2851311df149a003427d20 Mon Sep 17 00:00:00 2001 From: saurabhg772244 Date: Fri, 14 Feb 2025 19:17:09 +0530 Subject: [PATCH 7/8] Code refactor. --- .../src/diagrams/sequence/sequenceDb.ts | 143 +++++++----------- 1 file changed, 52 insertions(+), 91 deletions(-) diff --git a/packages/mermaid/src/diagrams/sequence/sequenceDb.ts b/packages/mermaid/src/diagrams/sequence/sequenceDb.ts index 410d48e33..e83c85684 100644 --- a/packages/mermaid/src/diagrams/sequence/sequenceDb.ts +++ b/packages/mermaid/src/diagrams/sequence/sequenceDb.ts @@ -29,6 +29,52 @@ interface SequenceState { lastDestroyed?: Actor; } +const LINETYPE = { + SOLID: 0, + DOTTED: 1, + NOTE: 2, + SOLID_CROSS: 3, + DOTTED_CROSS: 4, + SOLID_OPEN: 5, + DOTTED_OPEN: 6, + LOOP_START: 10, + LOOP_END: 11, + ALT_START: 12, + ALT_ELSE: 13, + ALT_END: 14, + OPT_START: 15, + OPT_END: 16, + ACTIVE_START: 17, + ACTIVE_END: 18, + PAR_START: 19, + PAR_AND: 20, + PAR_END: 21, + RECT_START: 22, + RECT_END: 23, + SOLID_POINT: 24, + DOTTED_POINT: 25, + AUTONUMBER: 26, + CRITICAL_START: 27, + CRITICAL_OPTION: 28, + CRITICAL_END: 29, + BREAK_START: 30, + BREAK_END: 31, + PAR_OVER_START: 32, + BIDIRECTIONAL_SOLID: 33, + BIDIRECTIONAL_DOTTED: 34, +} as const; + +const ARROWTYPE = { + FILLED: 0, + OPEN: 1, +} as const; + +const PLACEMENT = { + LEFTOF: 0, + RIGHTOF: 1, + OVER: 2, +} as const; + export class SequenceDB implements DiagramDB { private readonly state = new ImperativeState(() => ({ prevActor: undefined, @@ -54,52 +100,9 @@ export class SequenceDB implements DiagramDB { this.clear(); this.setWrap(getConfig().wrap); - - this.LINETYPE = { - SOLID: 0, - DOTTED: 1, - NOTE: 2, - SOLID_CROSS: 3, - DOTTED_CROSS: 4, - SOLID_OPEN: 5, - DOTTED_OPEN: 6, - LOOP_START: 10, - LOOP_END: 11, - ALT_START: 12, - ALT_ELSE: 13, - ALT_END: 14, - OPT_START: 15, - OPT_END: 16, - ACTIVE_START: 17, - ACTIVE_END: 18, - PAR_START: 19, - PAR_AND: 20, - PAR_END: 21, - RECT_START: 22, - RECT_END: 23, - SOLID_POINT: 24, - DOTTED_POINT: 25, - AUTONUMBER: 26, - CRITICAL_START: 27, - CRITICAL_OPTION: 28, - CRITICAL_END: 29, - BREAK_START: 30, - BREAK_END: 31, - PAR_OVER_START: 32, - BIDIRECTIONAL_SOLID: 33, - BIDIRECTIONAL_DOTTED: 34, - }; - - this.ARROWTYPE = { - FILLED: 0, - OPEN: 1, - }; - - this.PLACEMENT = { - LEFTOF: 0, - RIGHTOF: 1, - OVER: 2, - }; + this.LINETYPE = LINETYPE; + this.ARROWTYPE = ARROWTYPE; + this.PLACEMENT = PLACEMENT; } public addBox(data: { text: string; color: string; wrap: boolean }) { @@ -357,51 +360,9 @@ export class SequenceDB implements DiagramDB { }; } - public LINETYPE: { - SOLID: 0; - DOTTED: 1; - NOTE: 2; - SOLID_CROSS: 3; - DOTTED_CROSS: 4; - SOLID_OPEN: 5; - DOTTED_OPEN: 6; - LOOP_START: 10; - LOOP_END: 11; - ALT_START: 12; - ALT_ELSE: 13; - ALT_END: 14; - OPT_START: 15; - OPT_END: 16; - ACTIVE_START: 17; - ACTIVE_END: 18; - PAR_START: 19; - PAR_AND: 20; - PAR_END: 21; - RECT_START: 22; - RECT_END: 23; - SOLID_POINT: 24; - DOTTED_POINT: 25; - AUTONUMBER: 26; - CRITICAL_START: 27; - CRITICAL_OPTION: 28; - CRITICAL_END: 29; - BREAK_START: 30; - BREAK_END: 31; - PAR_OVER_START: 32; - BIDIRECTIONAL_SOLID: 33; - BIDIRECTIONAL_DOTTED: 34; - }; - - public ARROWTYPE: { - FILLED: 0; - OPEN: 1; - }; - - public PLACEMENT: { - LEFTOF: 0; - RIGHTOF: 1; - OVER: 2; - }; + public readonly LINETYPE: typeof LINETYPE; + public readonly ARROWTYPE: typeof ARROWTYPE; + public readonly PLACEMENT: typeof PLACEMENT; public addNote( actor: { actor: string }, From 3233c63fc034b8b89b78b3ae3892dd05542dae85 Mon Sep 17 00:00:00 2001 From: saurabhg772244 Date: Tue, 18 Feb 2025 16:59:35 +0530 Subject: [PATCH 8/8] Updated variable name --- .../diagrams/sequence/sequenceDiagram.spec.js | 595 +++++++++--------- 1 file changed, 295 insertions(+), 300 deletions(-) diff --git a/packages/mermaid/src/diagrams/sequence/sequenceDiagram.spec.js b/packages/mermaid/src/diagrams/sequence/sequenceDiagram.spec.js index 7fbf4f4e3..1fb35bce6 100644 --- a/packages/mermaid/src/diagrams/sequence/sequenceDiagram.spec.js +++ b/packages/mermaid/src/diagrams/sequence/sequenceDiagram.spec.js @@ -93,15 +93,14 @@ function addConf(conf, key, value) { } // const parser = sequence.parser; -let diagram; describe('more than one sequence diagram', () => { it('should not have duplicated messages', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram Alice->Bob:Hello Bob, how are you? Bob-->Alice: I am good thanks!`); - expect(diagram1.db.getMessages()).toMatchInlineSnapshot(` + expect(diagram.db.getMessages()).toMatchInlineSnapshot(` [ { "activate": false, @@ -183,6 +182,7 @@ describe('more than one sequence diagram', () => { }); describe('when parsing a sequenceDiagram', function () { + let diagram; beforeEach(async function () { diagram = await Diagram.fromText(` sequenceDiagram @@ -190,14 +190,7 @@ Alice->Bob:Hello Bob, how are you? Note right of Bob: Bob thinks Bob-->Alice: I am good thanks!`); }); - it('should handle a sequenceDiagram definition', async function () { - const str = ` -sequenceDiagram -Alice->Bob:Hello Bob, how are you? -Note right of Bob: Bob thinks -Bob-->Alice: I am good thanks!`; - - await mermaidAPI.parse(str); + it('should handle a sequenceDiagram definition', function () { const actors = diagram.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); actors.get('Bob').description = 'Bob'; @@ -215,7 +208,6 @@ Alice->Bob:Hello Bob, how are you? Note right of Bob: Bob thinks Bob-->Alice: I am good thanks!`; - await mermaidAPI.parse(str); await diagram.renderer.draw(str, 'tst', '1.2.3', diagram); // needs to be rendered for the correct value of visibility auto numbers expect(diagram.db.showSequenceNumbers()).toBe(false); }); @@ -227,27 +219,27 @@ Alice->Bob:Hello Bob, how are you? Note right of Bob: Bob thinks Bob-->Alice: I am good thanks!`; - const diagram1 = await Diagram.fromText(str); + const diagram = await Diagram.fromText(str); - await diagram1.renderer.draw(str, 'tst', '1.2.3', diagram1); // needs to be rendered for the correct value of visibility auto numbers - expect(diagram1.db.showSequenceNumbers()).toBe(true); + await diagram.renderer.draw(str, 'tst', '1.2.3', diagram); // needs to be rendered for the correct value of visibility auto numbers + expect(diagram.db.showSequenceNumbers()).toBe(true); }); it('should handle a sequenceDiagram definition with a title:', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram title: Diagram Title Alice->Bob:Hello Bob, how are you? Note right of Bob: Bob thinks Bob-->Alice: I am good thanks!`); - const actors = diagram1.db.getActors(); + const actors = diagram.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); actors.get('Bob').description = 'Bob'; - expect(diagram1.db.getAccDescription()).toBe(''); - const messages = diagram1.db.getMessages(); - const title = diagram1.db.getDiagramTitle(); + expect(diagram.db.getAccDescription()).toBe(''); + const messages = diagram.db.getMessages(); + const title = diagram.db.getDiagramTitle(); expect(messages.length).toBe(3); expect(messages[0].from).toBe('Alice'); @@ -256,20 +248,20 @@ Bob-->Alice: I am good thanks!`); }); it('should handle a sequenceDiagram definition with a title without a :', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram title Diagram Title Alice->Bob:Hello Bob, how are you? Note right of Bob: Bob thinks Bob-->Alice: I am good thanks!`); - const actors = diagram1.db.getActors(); + const actors = diagram.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); actors.get('Bob').description = 'Bob'; - expect(diagram1.db.getAccDescription()).toBe(''); - const messages = diagram1.db.getMessages(); - const title = diagram1.db.getDiagramTitle(); + expect(diagram.db.getAccDescription()).toBe(''); + const messages = diagram.db.getMessages(); + const title = diagram.db.getDiagramTitle(); expect(messages.length).toBe(3); expect(messages[0].from).toBe('Alice'); @@ -278,7 +270,7 @@ Bob-->Alice: I am good thanks!`); }); it('should handle a sequenceDiagram definition with a accessibility title and description (accDescr)', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram title: Diagram Title accTitle: This is the title @@ -286,12 +278,12 @@ accDescr: Accessibility Description Alice->Bob:Hello Bob, how are you? `); - expect(diagram1.db.getDiagramTitle()).toBe('Diagram Title'); - expect(diagram1.db.getAccTitle()).toBe('This is the title'); - expect(diagram1.db.getAccDescription()).toBe('Accessibility Description'); + expect(diagram.db.getDiagramTitle()).toBe('Diagram Title'); + expect(diagram.db.getAccTitle()).toBe('This is the title'); + expect(diagram.db.getAccDescription()).toBe('Accessibility Description'); }); it('should handle a sequenceDiagram definition with a accessibility title and multiline description (accDescr)', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram accTitle: This is the title accDescr { @@ -301,37 +293,37 @@ Description Alice->Bob:Hello Bob, how are you? `); - expect(diagram1.db.getAccTitle()).toBe('This is the title'); - expect(diagram1.db.getAccDescription()).toBe('Accessibility\nDescription'); + expect(diagram.db.getAccTitle()).toBe('This is the title'); + expect(diagram.db.getAccDescription()).toBe('Accessibility\nDescription'); }); it('should space in actor names', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram Alice->Bob:Hello Bob, how are - you? Bob-->Alice: I am good thanks!`); - const actors = diagram1.db.getActors(); + const actors = diagram.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); actors.get('Bob').description = 'Bob'; - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(2); expect(messages[0].from).toBe('Alice'); expect(messages[1].from).toBe('Bob'); }); it('should handle dashes in actor names', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram Alice-in-Wonderland->Bob:Hello Bob, how are - you? Bob-->Alice-in-Wonderland:I am good thanks!`); - const actors = diagram1.db.getActors(); + const actors = diagram.db.getActors(); expect(actors.get('Alice-in-Wonderland').description).toBe('Alice-in-Wonderland'); expect(actors.get('Bob').description).toBe('Bob'); - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(2); expect(messages[0].from).toBe('Alice-in-Wonderland'); @@ -339,19 +331,19 @@ Bob-->Alice-in-Wonderland:I am good thanks!`); }); it('should handle dashes in participant names', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram participant Alice-in-Wonderland participant Bob Alice-in-Wonderland->Bob:Hello Bob, how are - you? Bob-->Alice-in-Wonderland:I am good thanks!`); - const actors = diagram1.db.getActors(); + const actors = diagram.db.getActors(); expect([...actors.keys()]).toEqual(['Alice-in-Wonderland', 'Bob']); expect(actors.get('Alice-in-Wonderland').description).toBe('Alice-in-Wonderland'); expect(actors.get('Bob').description).toBe('Bob'); - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(2); expect(messages[0].from).toBe('Alice-in-Wonderland'); @@ -359,26 +351,26 @@ Bob-->Alice-in-Wonderland:I am good thanks!`); }); it('should alias participants', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram participant A as Alice participant B as Bob A->B:Hello Bob, how are you? B-->A: I am good thanks!`); - const actors = diagram1.db.getActors(); + const actors = diagram.db.getActors(); expect([...actors.keys()]).toEqual(['A', 'B']); expect(actors.get('A').description).toBe('Alice'); expect(actors.get('B').description).toBe('Bob'); - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(2); expect(messages[0].from).toBe('A'); expect(messages[1].from).toBe('B'); }); it('should alias a mix of actors and participants apa12', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram actor Alice as Alice2 actor Bob @@ -390,7 +382,7 @@ sequenceDiagram John->>Mandy: Hi Mandy Mandy ->>Joan: Hi Joan`); - const actors = diagram1.db.getActors(); + const actors = diagram.db.getActors(); expect([...actors.keys()]).toEqual(['Alice', 'Bob', 'John', 'Mandy', 'Joan']); expect(actors.get('Alice').description).toBe('Alice2'); expect(actors.get('Alice').type).toBe('actor'); @@ -398,212 +390,212 @@ sequenceDiagram expect(actors.get('John').type).toBe('participant'); expect(actors.get('Joan').type).toBe('participant'); - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(5); expect(messages[0].from).toBe('Alice'); expect(messages[4].to).toBe('Joan'); }); it('should alias actors apa13', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram actor A as Alice actor B as Bob A->B:Hello Bob, how are you? B-->A: I am good thanks!`); - const actors = diagram1.db.getActors(); + const actors = diagram.db.getActors(); expect([...actors.keys()]).toEqual(['A', 'B']); expect(actors.get('A').description).toBe('Alice'); expect(actors.get('B').description).toBe('Bob'); - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(2); expect(messages[0].from).toBe('A'); expect(messages[1].from).toBe('B'); }); it('should handle in async messages', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram Alice-xBob:Hello Bob, how are you?`); - const actors = diagram1.db.getActors(); + const actors = diagram.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); expect(actors.get('Bob').description).toBe('Bob'); - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(1); - expect(messages[0].type).toBe(diagram1.db.LINETYPE.SOLID_CROSS); + expect(messages[0].type).toBe(diagram.db.LINETYPE.SOLID_CROSS); }); it('should handle in async dotted messages', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram Alice--xBob:Hello Bob, how are you?`); - const actors = diagram1.db.getActors(); + const actors = diagram.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); expect(actors.get('Bob').description).toBe('Bob'); - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(1); - expect(messages[0].type).toBe(diagram1.db.LINETYPE.DOTTED_CROSS); + expect(messages[0].type).toBe(diagram.db.LINETYPE.DOTTED_CROSS); }); it('should handle in sync messages', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram Alice-)Bob:Hello Bob, how are you?`); - const actors = diagram1.db.getActors(); + const actors = diagram.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); expect(actors.get('Bob').description).toBe('Bob'); - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(1); - expect(messages[0].type).toBe(diagram1.db.LINETYPE.SOLID_POINT); + expect(messages[0].type).toBe(diagram.db.LINETYPE.SOLID_POINT); }); it('should handle in sync dotted messages', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram Alice--)Bob:Hello Bob, how are you?`); - const actors = diagram1.db.getActors(); + const actors = diagram.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); expect(actors.get('Bob').description).toBe('Bob'); - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(1); - expect(messages[0].type).toBe(diagram1.db.LINETYPE.DOTTED_POINT); + expect(messages[0].type).toBe(diagram.db.LINETYPE.DOTTED_POINT); }); it('should handle in arrow messages', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram Alice->>Bob:Hello Bob, how are you?`); - const actors = diagram1.db.getActors(); + const actors = diagram.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); expect(actors.get('Bob').description).toBe('Bob'); - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(1); - expect(messages[0].type).toBe(diagram1.db.LINETYPE.SOLID); + expect(messages[0].type).toBe(diagram.db.LINETYPE.SOLID); }); it('should handle in arrow messages', async () => { - const diagram1 = await Diagram.fromText( + const diagram = await Diagram.fromText( 'sequenceDiagram\n' + 'Alice-->>Bob:Hello Bob, how are you?' ); - const actors = diagram1.db.getActors(); + const actors = diagram.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); expect(actors.get('Bob').description).toBe('Bob'); - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(1); - expect(messages[0].type).toBe(diagram1.db.LINETYPE.DOTTED); + expect(messages[0].type).toBe(diagram.db.LINETYPE.DOTTED); }); it('should handle bidirectional arrow messages', async () => { - const diagram1 = await Diagram.fromText( + const diagram = await Diagram.fromText( ` sequenceDiagram Alice<<->>Bob:Hello Bob, how are you?` ); - const actors = diagram1.db.getActors(); + const actors = diagram.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); expect(actors.get('Bob').description).toBe('Bob'); - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(1); - expect(messages[0].type).toBe(diagram1.db.LINETYPE.BIDIRECTIONAL_SOLID); + expect(messages[0].type).toBe(diagram.db.LINETYPE.BIDIRECTIONAL_SOLID); }); it('should handle bidirectional dotted arrow messages', async () => { - const diagram1 = await Diagram.fromText( + const diagram = await Diagram.fromText( ` sequenceDiagram Alice<<-->>Bob:Hello Bob, how are you?` ); - const actors = diagram1.db.getActors(); + const actors = diagram.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); expect(actors.get('Bob').description).toBe('Bob'); - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(1); - expect(messages[0].type).toBe(diagram1.db.LINETYPE.BIDIRECTIONAL_DOTTED); + expect(messages[0].type).toBe(diagram.db.LINETYPE.BIDIRECTIONAL_DOTTED); }); it('should handle actor activation', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram Alice-->>Bob:Hello Bob, how are you? activate Bob Bob-->>Alice:Hello Alice, I'm fine and you? deactivate Bob`); - const actors = diagram1.db.getActors(); + const actors = diagram.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); expect(actors.get('Bob').description).toBe('Bob'); - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(4); - expect(messages[0].type).toBe(diagram1.db.LINETYPE.DOTTED); - expect(messages[1].type).toBe(diagram1.db.LINETYPE.ACTIVE_START); + expect(messages[0].type).toBe(diagram.db.LINETYPE.DOTTED); + expect(messages[1].type).toBe(diagram.db.LINETYPE.ACTIVE_START); expect(messages[1].from).toBe('Bob'); - expect(messages[2].type).toBe(diagram1.db.LINETYPE.DOTTED); - expect(messages[3].type).toBe(diagram1.db.LINETYPE.ACTIVE_END); + expect(messages[2].type).toBe(diagram.db.LINETYPE.DOTTED); + expect(messages[3].type).toBe(diagram.db.LINETYPE.ACTIVE_END); expect(messages[3].from).toBe('Bob'); }); it('should handle actor one line notation activation', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram Alice-->>+Bob:Hello Bob, how are you? Bob-->>- Alice:Hello Alice, I'm fine and you?`); - const actors = diagram1.db.getActors(); + const actors = diagram.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); expect(actors.get('Bob').description).toBe('Bob'); - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(4); - expect(messages[0].type).toBe(diagram1.db.LINETYPE.DOTTED); + expect(messages[0].type).toBe(diagram.db.LINETYPE.DOTTED); expect(messages[0].activate).toBeTruthy(); - expect(messages[1].type).toBe(diagram1.db.LINETYPE.ACTIVE_START); + expect(messages[1].type).toBe(diagram.db.LINETYPE.ACTIVE_START); expect(messages[1].from).toBe('Bob'); - expect(messages[2].type).toBe(diagram1.db.LINETYPE.DOTTED); - expect(messages[3].type).toBe(diagram1.db.LINETYPE.ACTIVE_END); + expect(messages[2].type).toBe(diagram.db.LINETYPE.DOTTED); + expect(messages[3].type).toBe(diagram.db.LINETYPE.ACTIVE_END); expect(messages[3].from).toBe('Bob'); }); it('should handle stacked activations', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram Alice-->>+Bob:Hello Bob, how are you? Bob-->>+Carol:Carol, let me introduce Alice? Bob-->>- Alice:Hello Alice, please meet Carol? Carol->>- Bob:Oh Bob, I'm so happy to be here!`); - const actors = diagram1.db.getActors(); + const actors = diagram.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); expect(actors.get('Bob').description).toBe('Bob'); - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(8); - expect(messages[0].type).toBe(diagram1.db.LINETYPE.DOTTED); - expect(messages[1].type).toBe(diagram1.db.LINETYPE.ACTIVE_START); + expect(messages[0].type).toBe(diagram.db.LINETYPE.DOTTED); + expect(messages[1].type).toBe(diagram.db.LINETYPE.ACTIVE_START); expect(messages[1].from).toBe('Bob'); - expect(messages[2].type).toBe(diagram1.db.LINETYPE.DOTTED); - expect(messages[3].type).toBe(diagram1.db.LINETYPE.ACTIVE_START); + expect(messages[2].type).toBe(diagram.db.LINETYPE.DOTTED); + expect(messages[3].type).toBe(diagram.db.LINETYPE.ACTIVE_START); expect(messages[3].from).toBe('Carol'); - expect(messages[5].type).toBe(diagram1.db.LINETYPE.ACTIVE_END); + expect(messages[5].type).toBe(diagram.db.LINETYPE.ACTIVE_END); expect(messages[5].from).toBe('Bob'); - expect(messages[7].type).toBe(diagram1.db.LINETYPE.ACTIVE_END); + expect(messages[7].type).toBe(diagram.db.LINETYPE.ACTIVE_END); expect(messages[7].from).toBe('Carol'); }); it('should handle fail parsing when activating an inactive participant', async () => { @@ -633,25 +625,25 @@ deactivate Bob`); }); it('should handle comments in a sequenceDiagram', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram Alice->Bob: Hello Bob, how are you? %% Comment Note right of Bob: Bob thinks Bob-->Alice: I am good thanks!`); - const actors = diagram1.db.getActors(); + const actors = diagram.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); actors.get('Bob').description = 'Bob'; - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(3); expect(messages[0].from).toBe('Alice'); expect(messages[2].from).toBe('Bob'); }); it('should handle new lines in a sequenceDiagram', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram Alice->Bob: Hello Bob, how are you? @@ -660,32 +652,32 @@ deactivate Bob`); Bob-->Alice: I am good thanks! `); - const actors = diagram1.db.getActors(); + const actors = diagram.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); actors.get('Bob').description = 'Bob'; - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(3); expect(messages[0].from).toBe('Alice'); expect(messages[2].from).toBe('Bob'); }); it('should handle semicolons', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram;Alice->Bob: Hello Bob, how are you?;Note right of Bob: Bob thinks;Bob-->Alice: I am good thanks!;`); - const actors = diagram1.db.getActors(); + const actors = diagram.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); actors.get('Bob').description = 'Bob'; - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(3); expect(messages[0].from).toBe('Alice'); expect(messages[2].from).toBe('Bob'); }); it('should handle one leading space in lines in a sequenceDiagram', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram Alice->Bob: Hello Bob, how are you? @@ -693,18 +685,18 @@ sequenceDiagram Note right of Bob: Bob thinks Bob-->Alice: I am good thanks!`); - const actors = diagram1.db.getActors(); + const actors = diagram.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); actors.get('Bob').description = 'Bob'; - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(3); expect(messages[0].from).toBe('Alice'); expect(messages[2].from).toBe('Bob'); }); it('should handle several leading spaces in lines in a sequenceDiagram', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram Alice->Bob: Hello Bob, how are you? @@ -712,18 +704,18 @@ sequenceDiagram Note right of Bob: Bob thinks Bob-->Alice: I am good thanks!`); - const actors = diagram1.db.getActors(); + const actors = diagram.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); actors.get('Bob').description = 'Bob'; - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(3); expect(messages[0].from).toBe('Alice'); expect(messages[2].from).toBe('Bob'); }); it('should handle several leading spaces in lines in a sequenceDiagram', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram participant Alice participant Bob @@ -736,18 +728,18 @@ Note right of John: Rational thoughts
prevail... John->Bob: How about you? Bob-->John: Jolly good!`); - const actors = diagram1.db.getActors(); + const actors = diagram.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); actors.get('Bob').description = 'Bob'; - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(8); expect(messages[0].from).toBe('Alice'); expect(messages[2].from).toBe('John'); }); it('should handle different line breaks', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram participant 1 as multiline
text participant 2 as multiline
text @@ -763,13 +755,13 @@ note right of 4: multiline
text note right of 1: multiline
text `); - const actors = diagram1.db.getActors(); + const actors = diagram.db.getActors(); expect(actors.get('1').description).toBe('multiline
text'); expect(actors.get('2').description).toBe('multiline
text'); expect(actors.get('3').description).toBe('multiline
text'); expect(actors.get('4').description).toBe('multiline
text'); - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages[0].message).toBe('multiline
text'); expect(messages[1].message).toBe('multiline
text'); expect(messages[2].message).toBe('multiline
text'); @@ -780,7 +772,7 @@ note right of 1: multiline
text expect(messages[7].message).toBe('multiline
text'); }); it('should handle notes and messages without wrap specified', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram participant 1 participant 2 @@ -796,7 +788,7 @@ note right of 4: multiline
text note right of 1:nowrap: multiline
text `); - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages[0].message).toBe('single-line text'); expect(messages[1].message).toBe('single-line text'); expect(messages[2].message).toBe('single-line text'); @@ -817,7 +809,7 @@ note right of 1:nowrap: multiline
text expect(messages[7].wrap).toBe(false); }); it('should handle notes and messages with wrap specified', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram participant 1 participant 2 @@ -829,7 +821,7 @@ note right of 2:wrap: single-line text note right of 3:wrap: multiline
text `); - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages[0].message).toBe('single-line text'); expect(messages[1].message).toBe('single-line text'); expect(messages[2].message).toBe('multiline
text'); @@ -840,7 +832,7 @@ note right of 3:wrap: multiline
text expect(messages[3].wrap).toBe(true); }); it('should handle notes and messages with nowrap or line breaks', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram participant 1 participant 2 @@ -848,39 +840,39 @@ participant 2 note right of 2: single-line text `); - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages[0].message).toBe('single-line text'); expect(messages[1].message).toBe('single-line text'); expect(messages[0].wrap).toBe(false); expect(messages[1].wrap).toBe(false); }); it('should handle notes over a single actor', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram Alice->Bob: Hello Bob, how are you? Note over Bob: Bob thinks `); - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages[1].from).toBe('Bob'); expect(messages[1].to).toBe('Bob'); }); it('should handle notes over multiple actors', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram Alice->Bob: Hello Bob, how are you? Note over Alice,Bob: confusion Note over Bob,Alice: resolution `); - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages[1].from).toBe('Alice'); expect(messages[1].to).toBe('Bob'); expect(messages[2].from).toBe('Bob'); expect(messages[2].to).toBe('Alice'); }); it('should handle loop statements', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram Alice->Bob: Hello Bob, how are you? @@ -891,18 +883,18 @@ loop Multiple happy responses Bob-->Alice: I am good thanks! end`); - const actors = diagram1.db.getActors(); + const actors = diagram.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); actors.get('Bob').description = 'Bob'; - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(5); expect(messages[0].from).toBe('Alice'); expect(messages[1].from).toBe('Bob'); }); it('should add a rect around sequence', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram Alice->Bob: Hello Bob, how are you? %% Comment @@ -912,20 +904,20 @@ end`); end `); - const actors = diagram1.db.getActors(); + const actors = diagram.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); actors.get('Bob').description = 'Bob'; - const messages = diagram1.db.getMessages(); - expect(messages[1].type).toEqual(diagram1.db.LINETYPE.RECT_START); + const messages = diagram.db.getMessages(); + expect(messages[1].type).toEqual(diagram.db.LINETYPE.RECT_START); expect(messages[1].message).toBe('rgb(200, 255, 200)'); - expect(messages[2].type).toEqual(diagram1.db.LINETYPE.NOTE); - expect(messages[3].type).toEqual(diagram1.db.LINETYPE.DOTTED_OPEN); - expect(messages[4].type).toEqual(diagram1.db.LINETYPE.RECT_END); + expect(messages[2].type).toEqual(diagram.db.LINETYPE.NOTE); + expect(messages[3].type).toEqual(diagram.db.LINETYPE.DOTTED_OPEN); + expect(messages[4].type).toEqual(diagram.db.LINETYPE.RECT_END); }); it('should allow for nested rects', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram Alice->Bob: Hello Bob, how are you? %% Comment @@ -937,22 +929,22 @@ end`); end `); - const actors = diagram1.db.getActors(); + const actors = diagram.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); actors.get('Bob').description = 'Bob'; - const messages = diagram1.db.getMessages(); - expect(messages[1].type).toEqual(diagram1.db.LINETYPE.RECT_START); + const messages = diagram.db.getMessages(); + expect(messages[1].type).toEqual(diagram.db.LINETYPE.RECT_START); expect(messages[1].message).toBe('rgb(200, 255, 200)'); - expect(messages[2].type).toEqual(diagram1.db.LINETYPE.RECT_START); + expect(messages[2].type).toEqual(diagram.db.LINETYPE.RECT_START); expect(messages[2].message).toBe('rgb(0, 0, 0)'); - expect(messages[3].type).toEqual(diagram1.db.LINETYPE.NOTE); - expect(messages[4].type).toEqual(diagram1.db.LINETYPE.RECT_END); - expect(messages[5].type).toEqual(diagram1.db.LINETYPE.DOTTED_OPEN); - expect(messages[6].type).toEqual(diagram1.db.LINETYPE.RECT_END); + expect(messages[3].type).toEqual(diagram.db.LINETYPE.NOTE); + expect(messages[4].type).toEqual(diagram.db.LINETYPE.RECT_END); + expect(messages[5].type).toEqual(diagram.db.LINETYPE.DOTTED_OPEN); + expect(messages[6].type).toEqual(diagram.db.LINETYPE.RECT_END); }); it('should handle opt statements', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram Alice->Bob: Hello Bob, how are you? @@ -963,18 +955,18 @@ opt Perhaps a happy response Bob-->Alice: I am good thanks! end`); - const actors = diagram1.db.getActors(); + const actors = diagram.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); actors.get('Bob').description = 'Bob'; - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(5); expect(messages[0].from).toBe('Alice'); expect(messages[1].from).toBe('Bob'); }); it('should handle alt statements', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram Alice->Bob: Hello Bob, how are you? @@ -987,19 +979,19 @@ else isSick Bob-->Alice: Feel sick... end`); - const actors = diagram1.db.getActors(); + const actors = diagram.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); actors.get('Bob').description = 'Bob'; - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(7); expect(messages[0].from).toBe('Alice'); expect(messages[1].from).toBe('Bob'); }); it('should handle alt statements with multiple elses', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram Alice->Bob: Hello Bob, how are you? @@ -1014,38 +1006,38 @@ else default Bob-->Alice: :-) end`); - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(9); expect(messages[1].from).toBe('Bob'); - expect(messages[2].type).toBe(diagram1.db.LINETYPE.ALT_START); + expect(messages[2].type).toBe(diagram.db.LINETYPE.ALT_START); expect(messages[3].from).toBe('Bob'); - expect(messages[4].type).toBe(diagram1.db.LINETYPE.ALT_ELSE); + expect(messages[4].type).toBe(diagram.db.LINETYPE.ALT_ELSE); expect(messages[5].from).toBe('Bob'); - expect(messages[6].type).toBe(diagram1.db.LINETYPE.ALT_ELSE); + expect(messages[6].type).toBe(diagram.db.LINETYPE.ALT_ELSE); expect(messages[7].from).toBe('Bob'); - expect(messages[8].type).toBe(diagram1.db.LINETYPE.ALT_END); + expect(messages[8].type).toBe(diagram.db.LINETYPE.ALT_END); }); it('should handle critical statements without options', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram critical Establish a connection to the DB Service-->DB: connect end`); - const actors = diagram1.db.getActors(); + const actors = diagram.db.getActors(); expect(actors.get('Service').description).toBe('Service'); expect(actors.get('DB').description).toBe('DB'); - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(3); - expect(messages[0].type).toBe(diagram1.db.LINETYPE.CRITICAL_START); + expect(messages[0].type).toBe(diagram.db.LINETYPE.CRITICAL_START); expect(messages[1].from).toBe('Service'); - expect(messages[2].type).toBe(diagram1.db.LINETYPE.CRITICAL_END); + expect(messages[2].type).toBe(diagram.db.LINETYPE.CRITICAL_END); }); it('should handle critical statements with options', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram critical Establish a connection to the DB Service-->DB: connect @@ -1055,24 +1047,24 @@ sequenceDiagram Service-->Service: Log different error end`); - const actors = diagram1.db.getActors(); + const actors = diagram.db.getActors(); expect(actors.get('Service').description).toBe('Service'); expect(actors.get('DB').description).toBe('DB'); - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(7); - expect(messages[0].type).toBe(diagram1.db.LINETYPE.CRITICAL_START); + expect(messages[0].type).toBe(diagram.db.LINETYPE.CRITICAL_START); expect(messages[1].from).toBe('Service'); - expect(messages[2].type).toBe(diagram1.db.LINETYPE.CRITICAL_OPTION); + expect(messages[2].type).toBe(diagram.db.LINETYPE.CRITICAL_OPTION); expect(messages[3].from).toBe('Service'); - expect(messages[4].type).toBe(diagram1.db.LINETYPE.CRITICAL_OPTION); + expect(messages[4].type).toBe(diagram.db.LINETYPE.CRITICAL_OPTION); expect(messages[5].from).toBe('Service'); - expect(messages[6].type).toBe(diagram1.db.LINETYPE.CRITICAL_END); + expect(messages[6].type).toBe(diagram.db.LINETYPE.CRITICAL_END); }); it('should handle break statements', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram Consumer-->API: Book something API-->BookingService: Start booking process @@ -1081,23 +1073,23 @@ sequenceDiagram end API-->BillingService: Start billing process`); - const actors = diagram1.db.getActors(); + const actors = diagram.db.getActors(); expect(actors.get('Consumer').description).toBe('Consumer'); expect(actors.get('API').description).toBe('API'); - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(6); expect(messages[0].from).toBe('Consumer'); expect(messages[1].from).toBe('API'); - expect(messages[2].type).toBe(diagram1.db.LINETYPE.BREAK_START); + expect(messages[2].type).toBe(diagram.db.LINETYPE.BREAK_START); expect(messages[3].from).toBe('API'); - expect(messages[4].type).toBe(diagram1.db.LINETYPE.BREAK_END); + expect(messages[4].type).toBe(diagram.db.LINETYPE.BREAK_END); expect(messages[5].from).toBe('API'); }); it('should handle par statements a sequenceDiagram', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram par Parallel one Alice->>Bob: Hello Bob, how are you? @@ -1110,12 +1102,12 @@ Alice->>Bob: What do you think about it? Bob-->>Alice: It's good! end`); - const actors = diagram1.db.getActors(); + const actors = diagram.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); expect(actors.get('Bob').description).toBe('Bob'); - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(10); expect(messages[0].message).toBe('Parallel one'); @@ -1123,7 +1115,7 @@ end`); expect(messages[2].from).toBe('Bob'); }); it('it should handle par_over statements', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram par_over Parallel overlap Alice ->> Bob: Message @@ -1131,12 +1123,12 @@ Note left of Alice: Alice note Note right of Bob: Bob note end`); - const actors = diagram1.db.getActors(); + const actors = diagram.db.getActors(); expect(actors.get('Alice').description).toBe('Alice'); expect(actors.get('Bob').description).toBe('Bob'); - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages.length).toBe(5); expect(messages[0].message).toBe('Parallel overlap'); @@ -1145,44 +1137,44 @@ end`); expect(messages[3].from).toBe('Bob'); }); it('should handle special characters in signals', async () => { - const diagram1 = await Diagram.fromText('sequenceDiagram\n' + 'Alice->Bob: -:<>,;# comment'); + const diagram = await Diagram.fromText('sequenceDiagram\n' + 'Alice->Bob: -:<>,;# comment'); - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages[0].message).toBe('-:<>,'); }); it('should handle special characters in notes', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram Alice->Bob: Hello Bob, how are you? Note right of Bob: -:<>,;# comment`); - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages[1].message).toBe('-:<>,'); }); it('should handle special characters in loop', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram Alice->Bob: Hello Bob, how are you? loop -:<>,;# comment Bob-->Alice: I am good thanks! end`); - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages[1].message).toBe('-:<>,'); }); it('should handle special characters in opt', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram Alice->Bob: Hello Bob, how are you? opt -:<>,;# comment Bob-->Alice: I am good thanks! end`); - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages[1].message).toBe('-:<>,'); }); it('should handle special characters in alt', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram Alice->Bob: Hello Bob, how are you? alt -:<>,;# comment @@ -1191,12 +1183,12 @@ else ,<>:-#; comment Bob-->Alice: I am good thanks! end`); - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages[1].message).toBe('-:<>,'); expect(messages[3].message).toBe(',<>:-'); }); it('should handle special characters in par', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram Alice->Bob: Hello Bob, how are you? par -:<>,;# comment @@ -1205,36 +1197,36 @@ and ,<>:-#; comment Bob-->Alice: I am good thanks! end`); - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages[1].message).toBe('-:<>,'); expect(messages[3].message).toBe(',<>:-'); }); it('should handle no-label loop', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram Alice->Bob: Hello Bob, how are you? loop Bob-->Alice: I am good thanks! end`); - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages[1].message).toBe(''); expect(messages[2].message).toBe('I am good thanks!'); }); it('should handle no-label opt', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram Alice->Bob: Hello Bob, how are you? opt # comment Bob-->Alice: I am good thanks! end`); - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages[1].message).toBe(''); expect(messages[2].message).toBe('I am good thanks!'); }); it('should handle no-label alt', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram Alice->Bob: Hello Bob, how are you? alt;Bob-->Alice: I am good thanks! @@ -1242,14 +1234,14 @@ else # comment Bob-->Alice: I am good thanks! end`); - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages[1].message).toBe(''); expect(messages[2].message).toBe('I am good thanks!'); expect(messages[3].message).toBe(''); expect(messages[4].message).toBe('I am good thanks!'); }); it('should handle no-label par', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram Alice->Bob: Hello Bob, how are you? par;Bob-->Alice: I am good thanks! @@ -1257,7 +1249,7 @@ and # comment Bob-->Alice: I am good thanks! end`); - const messages = diagram1.db.getMessages(); + const messages = diagram.db.getMessages(); expect(messages[1].message).toBe(''); expect(messages[2].message).toBe('I am good thanks!'); expect(messages[3].message).toBe(''); @@ -1265,7 +1257,7 @@ end`); }); it('should handle links', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram participant a as Alice participant b as Bob @@ -1278,7 +1270,7 @@ link a: Swagger @ https://swagger.contoso.com link a: Tests @ https://tests.contoso.com/?svc=alice@contoso.com `); - const actors = diagram1.db.getActors(); + const actors = diagram.db.getActors(); expect(actors.get('a').links.Repo).toBe('https://repo.contoso.com/'); expect(actors.get('b').links.Repo).toBe(undefined); expect(actors.get('a').links.Dashboard).toBe('https://dashboard.contoso.com/'); @@ -1292,7 +1284,7 @@ link a: Tests @ https://tests.contoso.com/?svc=alice@contoso.com it('should handle properties EXPERIMENTAL: USE WITH CAUTION', async () => { //Be aware that the syntax for "properties" is likely to be changed. - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram participant a as Alice participant b as Bob @@ -1301,7 +1293,7 @@ properties a: {"class": "internal-service-actor", "icon": "@clock"} properties b: {"class": "external-service-actor", "icon": "@computer"} `); - const actors = diagram1.db.getActors(); + const actors = diagram.db.getActors(); expect(actors.get('a').properties.class).toBe('internal-service-actor'); expect(actors.get('b').properties.class).toBe('external-service-actor'); expect(actors.get('a').properties.icon).toBe('@clock'); @@ -1310,7 +1302,7 @@ properties b: {"class": "external-service-actor", "icon": "@computer"} }); it('should handle box', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram box green Group 1 participant a as Alice @@ -1325,14 +1317,14 @@ link a: Swagger @ https://swagger.contoso.com link a: Tests @ https://tests.contoso.com/?svc=alice@contoso.com `); - const boxes = diagram1.db.getBoxes(); + const boxes = diagram.db.getBoxes(); expect(boxes[0].name).toEqual('Group 1'); expect(boxes[0].actorKeys).toEqual(['a', 'b']); expect(boxes[0].fill).toEqual('green'); }); it('should handle box without color', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram box Group 1 participant a as Alice @@ -1347,14 +1339,14 @@ link a: Tests @ https://tests.contoso.com/?svc=alice@contoso.com link a: Tests @ https://tests.contoso.com/?svc=alice@contoso.com `); - const boxes = diagram1.db.getBoxes(); + const boxes = diagram.db.getBoxes(); expect(boxes[0].name).toEqual('Group 1'); expect(boxes[0].actorKeys).toEqual(['a', 'b']); expect(boxes[0].fill).toEqual('transparent'); }); it('should handle box without description', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram box Aqua participant a as Alice @@ -1369,14 +1361,14 @@ link a: Tests @ https://tests.contoso.com/?svc=alice@contoso.com link a: Tests @ https://tests.contoso.com/?svc=alice@contoso.com `); - const boxes = diagram1.db.getBoxes(); + const boxes = diagram.db.getBoxes(); expect(boxes[0].name).toBeFalsy(); expect(boxes[0].actorKeys).toEqual(['a', 'b']); expect(boxes[0].fill).toEqual('Aqua'); }); it('should handle simple actor creation', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram participant a as Alice a ->>b: Hello Bob? @@ -1386,8 +1378,8 @@ link a: Tests @ https://tests.contoso.com/?svc=alice@contoso.com create actor d as Donald a ->> d: Hello Donald? `); - const actors = diagram1.db.getActors(); - const createdActors = diagram1.db.getCreatedActors(); + const actors = diagram.db.getActors(); + const createdActors = diagram.db.getCreatedActors(); expect(actors.get('c').name).toEqual('c'); expect(actors.get('c').description).toEqual('c'); expect(actors.get('c').type).toEqual('participant'); @@ -1398,7 +1390,7 @@ link a: Tests @ https://tests.contoso.com/?svc=alice@contoso.com expect(createdActors.get('d')).toEqual(3); }); it('should handle simple actor destruction', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram participant a as Alice a ->>b: Hello Bob? @@ -1408,7 +1400,7 @@ link a: Tests @ https://tests.contoso.com/?svc=alice@contoso.com destroy c b ->> c: Where are you? `); - const destroyedActors = diagram1.db.getDestroyedActors(); + const destroyedActors = diagram.db.getDestroyedActors(); expect(destroyedActors.get('a')).toEqual(1); expect(destroyedActors.get('c')).toEqual(3); }); @@ -1447,7 +1439,12 @@ describe('when checking the bounds in a sequenceDiagram', function () { }); let conf; - beforeEach(function () { + let diagram; + beforeEach(async function () { + diagram = await Diagram.fromText(` + sequenceDiagram + Alice->Bob:Hello Bob, how are you? + Bob-->Alice: I am good thanks!`); mermaidAPI.reset(); diagram.renderer.bounds.init(); conf = diagram.db.getConfig(); @@ -1576,7 +1573,7 @@ describe('when rendering a sequenceDiagram APA', function () { setSiteConfig({ logLevel: 5, sequence: conf }); }); let conf; - beforeEach(async function () { + beforeEach(function () { mermaidAPI.reset(); // }); @@ -1595,11 +1592,6 @@ describe('when rendering a sequenceDiagram APA', function () { mirrorActors: false, }; setSiteConfig({ logLevel: 5, sequence: conf }); - diagram = await Diagram.fromText(` -sequenceDiagram -Alice->Bob:Hello Bob, how are you? -Note right of Bob: Bob thinks -Bob-->Alice: I am good thanks!`); }); ['tspan', 'fo', 'old', undefined].forEach(function (textPlacement) { it(` @@ -1608,11 +1600,11 @@ it should handle one actor, when textPlacement is ${textPlacement}`, async () => sequenceDiagram participant Alice`; - const diagram1 = await Diagram.fromText(str); + const diagram = await Diagram.fromText(str); // diagram.renderer.setConf(mermaidAPI.getConfig().sequence); - await diagram1.renderer.draw(str, 'tst', '1.2.3', diagram1); + await diagram.renderer.draw(str, 'tst', '1.2.3', diagram); - const { bounds } = diagram1.renderer.bounds.getBounds(); + const { bounds } = diagram.renderer.bounds.getBounds(); expect(bounds.startx).toBe(0); expect(bounds.starty).toBe(0); expect(bounds.stopx).toBe(conf.width); @@ -1620,14 +1612,14 @@ participant Alice`; }); }); it('should handle same actor with different whitespace properly', async () => { - const diagram1 = await Diagram.fromText(` + const diagram = await Diagram.fromText(` sequenceDiagram participant Alice participant Alice participant Alice `); - const actors = diagram1.db.getActors(); + const actors = diagram.db.getActors(); expect([...actors.keys()]).toEqual(['Alice']); }); it('should handle one actor and a centered note', async () => { @@ -1636,12 +1628,12 @@ sequenceDiagram participant Alice Note over Alice: Alice thinks `; - const diagram1 = await Diagram.fromText(str); + const diagram = await Diagram.fromText(str); expect(mermaidAPI.getConfig().sequence.mirrorActors).toBeFalsy(); - await diagram1.renderer.draw(str, 'tst', '1.2.3', diagram1); + await diagram.renderer.draw(str, 'tst', '1.2.3', diagram); - const { bounds, models } = diagram1.renderer.bounds.getBounds(); + const { bounds, models } = diagram.renderer.bounds.getBounds(); expect(bounds.startx).toBe(0); expect(bounds.starty).toBe(0); expect(bounds.stopx).toBe(conf.width); @@ -1654,10 +1646,10 @@ sequenceDiagram participant Alice Note left of Alice: Alice thinks`; - const diagram1 = await Diagram.fromText(str); - await diagram1.renderer.draw(str, 'tst', '1.2.3', diagram1); + const diagram = await Diagram.fromText(str); + await diagram.renderer.draw(str, 'tst', '1.2.3', diagram); - const { bounds, models } = diagram1.renderer.bounds.getBounds(); + const { bounds, models } = diagram.renderer.bounds.getBounds(); expect(bounds.startx).toBe(-(conf.width / 2) - conf.actorMargin / 2); expect(bounds.starty).toBe(0); expect(bounds.stopx).toBe(conf.width); @@ -1670,10 +1662,10 @@ sequenceDiagram participant Alice Note right of Alice: Alice thinks`; - const diagram1 = await Diagram.fromText(str); - await diagram1.renderer.draw(str, 'tst', '1.2.3', diagram1); + const diagram = await Diagram.fromText(str); + await diagram.renderer.draw(str, 'tst', '1.2.3', diagram); - const { bounds, models } = diagram1.renderer.bounds.getBounds(); + const { bounds, models } = diagram.renderer.bounds.getBounds(); expect(bounds.startx).toBe(0); expect(bounds.starty).toBe(0); expect(bounds.stopx).toBe(conf.width / 2 + conf.actorMargin / 2 + conf.width); @@ -1685,10 +1677,10 @@ Note right of Alice: Alice thinks`; sequenceDiagram Alice->Bob: Hello Bob, how are you?`; - const diagram1 = await Diagram.fromText(str); - await diagram1.renderer.draw(str, 'tst', '1.2.3', diagram1); + const diagram = await Diagram.fromText(str); + await diagram.renderer.draw(str, 'tst', '1.2.3', diagram); - const { bounds, models } = diagram1.renderer.bounds.getBounds(); + const { bounds, models } = diagram.renderer.bounds.getBounds(); expect(bounds.startx).toBe(0); expect(bounds.starty).toBe(0); expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin); @@ -1703,10 +1695,10 @@ participant Bob end Alice->Bob: Hello Bob, how are you?`; - const diagram1 = await Diagram.fromText(str); - await diagram1.renderer.draw(str, 'tst', '1.2.3', diagram1); + const diagram = await Diagram.fromText(str); + await diagram.renderer.draw(str, 'tst', '1.2.3', diagram); - const { bounds, models } = diagram1.renderer.bounds.getBounds(); + const { bounds, models } = diagram.renderer.bounds.getBounds(); expect(bounds.startx).toBe(0); expect(bounds.starty).toBe(0); expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin + conf.boxTextMargin * 2); @@ -1718,10 +1710,10 @@ Alice->Bob: Hello Bob, how are you?`; sequenceDiagram Alice->Bob: Hello Bob, how are you?`; await mermaidAPI.parse(str); - const diagram1 = await Diagram.fromText(str); - await diagram1.renderer.draw(str, 'tst', '1.2.3', diagram1); + const diagram = await Diagram.fromText(str); + await diagram.renderer.draw(str, 'tst', '1.2.3', diagram); - const { bounds, models } = diagram1.renderer.bounds.getBounds(); + const { bounds, models } = diagram.renderer.bounds.getBounds(); const mermaid = mermaidAPI.getConfig(); expect(mermaid.logLevel).toBe(0); expect(bounds.startx).toBe(0); @@ -1737,11 +1729,11 @@ sequenceDiagram Alice->Bob: Hello Bob, how are you?`; await mermaidAPI.parse(str); - const diagram1 = await Diagram.fromText(str); - await diagram1.renderer.draw(str, 'tst', '1.2.3', diagram1); + const diagram = await Diagram.fromText(str); + await diagram.renderer.draw(str, 'tst', '1.2.3', diagram); - const msgs = diagram1.db.getMessages(); - const { bounds, models } = diagram1.renderer.bounds.getBounds(); + const msgs = diagram.db.getMessages(); + const { bounds, models } = diagram.renderer.bounds.getBounds(); const mermaid = mermaidAPI.getConfig(); expect(mermaid.logLevel).toBe(0); expect(bounds.startx).toBe(0); @@ -1757,11 +1749,11 @@ Alice->Bob: Hello Bob, how are you? Note over Alice,Bob: Looks Note over Bob,Alice: Looks back `; - const diagram1 = await Diagram.fromText(str); + const diagram = await Diagram.fromText(str); // mermaidAPI.initialize({logLevel:0}) - await diagram1.renderer.draw(str, 'tst', '1.2.3', diagram1); + await diagram.renderer.draw(str, 'tst', '1.2.3', diagram); - const { bounds, models } = diagram1.renderer.bounds.getBounds(); + const { bounds, models } = diagram.renderer.bounds.getBounds(); expect(bounds.startx).toBe(0); expect(bounds.starty).toBe(0); expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin); @@ -1773,10 +1765,10 @@ sequenceDiagram Alice->Bob: Hello Bob, how are you? Bob->Alice: Fine!`; - const diagram1 = await Diagram.fromText(str); - await diagram1.renderer.draw(str, 'tst', '1.2.3', diagram1); + const diagram = await Diagram.fromText(str); + await diagram.renderer.draw(str, 'tst', '1.2.3', diagram); - const { bounds, models } = diagram1.renderer.bounds.getBounds(); + const { bounds, models } = diagram.renderer.bounds.getBounds(); expect(bounds.startx).toBe(0); expect(bounds.starty).toBe(0); expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin); @@ -1789,10 +1781,10 @@ Alice->Bob: Hello Bob, how are you? Note right of Bob: Bob thinks Bob->Alice: Fine!`; - const diagram1 = await Diagram.fromText(str); - await diagram1.renderer.draw(str, 'tst', '1.2.3', diagram1); + const diagram = await Diagram.fromText(str); + await diagram.renderer.draw(str, 'tst', '1.2.3', diagram); - const { bounds, models } = diagram1.renderer.bounds.getBounds(); + const { bounds, models } = diagram.renderer.bounds.getBounds(); expect(bounds.startx).toBe(0); expect(bounds.starty).toBe(0); @@ -1808,10 +1800,10 @@ Alice->Bob: Hello Bob, how are you? Note left of Alice: Bob thinks Bob->Alice: Fine!`; - const diagram1 = await Diagram.fromText(str); - await diagram1.renderer.draw(str, 'tst', '1.2.3', diagram1); + const diagram = await Diagram.fromText(str); + await diagram.renderer.draw(str, 'tst', '1.2.3', diagram); - const { bounds, models } = diagram1.renderer.bounds.getBounds(); + const { bounds, models } = diagram.renderer.bounds.getBounds(); expect(bounds.startx).toBe(-(conf.width / 2) - conf.actorMargin / 2); expect(bounds.starty).toBe(0); @@ -1825,11 +1817,11 @@ Alice->>Bob:wrap: Hello Bob, how are you? If you are not available right now, I Note left of Alice: Bob thinks Bob->>Alice: Fine!`; - const diagram1 = await Diagram.fromText(str); - await diagram1.renderer.draw(str, 'tst', '1.2.3', diagram1); + const diagram = await Diagram.fromText(str); + await diagram.renderer.draw(str, 'tst', '1.2.3', diagram); - const { bounds, models } = diagram1.renderer.bounds.getBounds(); - const msgs = diagram1.db.getMessages(); + const { bounds, models } = diagram.renderer.bounds.getBounds(); + const msgs = diagram.db.getMessages(); expect(bounds.startx).toBe(-(conf.width / 2) - conf.actorMargin / 2); expect(bounds.starty).toBe(0); expect(msgs[0].wrap).toBe(true); @@ -1847,11 +1839,11 @@ Note left of Alice: Bob thinks Bob->>Alice: Fine!`; await mermaidAPI.parse(str); - const diagram1 = await Diagram.fromText(str); - await diagram1.renderer.draw(str, 'tst', '1.2.3', diagram1); + const diagram = await Diagram.fromText(str); + await diagram.renderer.draw(str, 'tst', '1.2.3', diagram); - const { bounds, models } = diagram1.renderer.bounds.getBounds(); - const msgs = diagram1.db.getMessages(); + const { bounds, models } = diagram.renderer.bounds.getBounds(); + const msgs = diagram.db.getMessages(); const mermaid = mermaidAPI.getConfig(); expect(bounds.startx).toBe(-(conf.width / 2) - conf.actorMargin / 2); expect(bounds.starty).toBe(0); @@ -1871,12 +1863,12 @@ Note left of Alice: Bob thinks Bob->>Alice: Fine!`; await mermaidAPI.parse(str); - const diagram1 = await Diagram.fromText(str); + const diagram = await Diagram.fromText(str); - await diagram1.renderer.draw(str, 'tst', '1.2.3', diagram1); + await diagram.renderer.draw(str, 'tst', '1.2.3', diagram); - const { bounds, models } = diagram1.renderer.bounds.getBounds(); - const msgs = diagram1.db.getMessages(); + const { bounds, models } = diagram.renderer.bounds.getBounds(); + const msgs = diagram.db.getMessages(); const mermaid = mermaidAPI.getConfig(); expect(bounds.startx).toBe(-(conf.width / 2) - conf.actorMargin / 2); expect(bounds.starty).toBe(0); @@ -1895,11 +1887,11 @@ Note left of Alice: Bob thinks Bob->>Alice: Fine!`; // mermaidAPI.initialize({ logLevel: 0 }); await mermaidAPI.parse(str); - const diagram1 = await Diagram.fromText(str); - await diagram1.renderer.draw(str, 'tst', '1.2.3', diagram1); + const diagram = await Diagram.fromText(str); + await diagram.renderer.draw(str, 'tst', '1.2.3', diagram); - const { bounds, models } = diagram1.renderer.bounds.getBounds(); - const msgs = diagram1.db.getMessages(); + const { bounds, models } = diagram.renderer.bounds.getBounds(); + const msgs = diagram.db.getMessages(); const mermaid = mermaidAPI.getConfig(); expect(bounds.startx).toBe(-(conf.width / 2) - conf.actorMargin / 2); expect(bounds.starty).toBe(0); @@ -1920,9 +1912,9 @@ loop Cheers Bob->Alice: Fine! end`; - const diagram1 = await Diagram.fromText(str); - await diagram1.renderer.draw(str, 'tst', '1.2.3', diagram1); - const { bounds, models } = diagram1.renderer.bounds.getBounds(); + const diagram = await Diagram.fromText(str); + await diagram.renderer.draw(str, 'tst', '1.2.3', diagram); + const { bounds, models } = diagram.renderer.bounds.getBounds(); expect(bounds.startx).toBe(0); expect(bounds.starty).toBe(0); @@ -1937,9 +1929,9 @@ end`; Bob->Alice: I feel surrounded by darkness end `; - const diagram1 = await Diagram.fromText(str); - await diagram1.renderer.draw(str, 'tst', '1.2.3', diagram1); - const { bounds, models } = diagram1.renderer.bounds.getBounds(); + const diagram = await Diagram.fromText(str); + await diagram.renderer.draw(str, 'tst', '1.2.3', diagram); + const { bounds, models } = diagram.renderer.bounds.getBounds(); expect(bounds.startx).toBe(0); expect(bounds.starty).toBe(0); @@ -1971,23 +1963,26 @@ describe('when rendering a sequenceDiagram with actor mirror activated', () => { }); let conf; - beforeEach(function () { + let diagram; + beforeEach(async function () { + diagram = await Diagram.fromText(` + sequenceDiagram + Alice->Bob:Hello Bob, how are you? + Bob-->Alice: I am good thanks!`); mermaidAPI.reset(); conf = diagram.db.getConfig(); diagram.renderer.bounds.init(); }); ['tspan', 'fo', 'old', undefined].forEach(function (textPlacement) { it('should handle one actor, when textPlacement is' + textPlacement, async () => { - mermaidAPI.initialize(addConf(conf, 'textPlacement', textPlacement)); - diagram.renderer.bounds.init(); const str = ` sequenceDiagram participant Alice`; - const diagram1 = await Diagram.fromText(str); - diagram1.renderer.bounds.init(); - await diagram1.renderer.draw(str, 'tst', '1.2.3', diagram1); + const diagram = await Diagram.fromText(str); + diagram.renderer.bounds.init(); + await diagram.renderer.draw(str, 'tst', '1.2.3', diagram); - const { bounds, models } = diagram1.renderer.bounds.getBounds(); + const { bounds, models } = diagram.renderer.bounds.getBounds(); expect(bounds.startx).toBe(0); expect(bounds.starty).toBe(0); expect(bounds.stopx).toBe(conf.width);