diff --git a/src/__mocks__/mermaidAPI.ts b/src/__mocks__/mermaidAPI.ts new file mode 100644 index 000000000..9531fdc07 --- /dev/null +++ b/src/__mocks__/mermaidAPI.ts @@ -0,0 +1,47 @@ +/** + * Mocks for `./mermaidAPI`. + * + * We can't easily use `jest.spyOn(mermaidAPI, "function")` since the object + * is frozen with `Object.freeze()`. + */ +import * as configApi from '../config'; + +import { addDiagrams } from '../diagram-api/diagram-orchestration'; +import Diagram from '../Diagram'; + +// Normally, we could just do the following to get the original `parse()` +// implementation, however, requireActual isn't currently supported in Jest +// for ESM, see https://github.com/facebook/jest/issues/9430 +// and https://github.com/facebook/jest/pull/10976 +// const {parse} = jest.requireActual("./mermaidAPI"); + +let hasLoadedDiagrams = false; +function parse(text: string, parseError?: Function): boolean { + if (!hasLoadedDiagrams) { + addDiagrams(); + hasLoadedDiagrams = true; + } + const diagram = new Diagram(text, parseError); + return diagram.parse(text, parseError); +} + +// original version cannot be modified since it was frozen with `Object.freeze()` +export const mermaidAPI = { + render: jest.fn(), + parse, + parseDirective: jest.fn(), + initialize: jest.fn(), + getConfig: configApi.getConfig, + setConfig: configApi.setConfig, + getSiteConfig: configApi.getSiteConfig, + updateSiteConfig: configApi.updateSiteConfig, + reset: () => { + configApi.reset(); + }, + globalReset: () => { + configApi.reset(configApi.defaultConfig); + }, + defaultConfig: configApi.defaultConfig, +} + +export default mermaidAPI; diff --git a/src/mermaid.spec.js b/src/mermaid.spec.js index 60b67ad23..c6014dfff 100644 --- a/src/mermaid.spec.js +++ b/src/mermaid.spec.js @@ -1,4 +1,5 @@ import mermaid from './mermaid'; +import { mermaidAPI } from './mermaidAPI'; import flowDb from './diagrams/flowchart/flowDb'; import flowParser from './diagrams/flowchart/parser/flow'; import flowRenderer from './diagrams/flowchart/flowRenderer'; @@ -6,6 +7,13 @@ import Diagram from './Diagram'; const spyOn = jest.spyOn; +// mocks the mermaidAPI.render function (see `./__mocks__/mermaidAPI`) +jest.mock('./mermaidAPI'); + +afterEach(() => { + jest.restoreAllMocks(); +}); + describe('when using mermaid and ', function () { describe('when detecting chart type ', function () { it('should not start rendering with mermaid.startOnLoad set to false', function () { @@ -40,6 +48,16 @@ describe('when using mermaid and ', function () { }); }); + describe('when using #initThrowsErrors', function () { + it('should accept single node', async () => { + const node = document.createElement('div'); + node.appendChild(document.createTextNode('graph TD;\na;')); + + mermaid.initThrowsErrors(undefined, node); + expect(mermaidAPI.render).toHaveBeenCalled(); + }); + }); + describe('when calling addEdges ', function () { beforeEach(function () { flowParser.parser.yy = flowDb; diff --git a/src/mermaid.ts b/src/mermaid.ts index a46103f11..e82597152 100644 --- a/src/mermaid.ts +++ b/src/mermaid.ts @@ -64,14 +64,13 @@ const initThrowsErrors = function ( // if last argument is a function this is the callback function log.debug(`${!callback ? 'No ' : ''}Callback function found`); - let nodesToProcess: NodeListOf; + let nodesToProcess: ArrayLike; if (typeof nodes === 'undefined') { nodesToProcess = document.querySelectorAll('.mermaid'); } else if (typeof nodes === 'string') { nodesToProcess = document.querySelectorAll(nodes); } else if (nodes instanceof HTMLElement) { - nodesToProcess = new NodeList() as NodeListOf; - nodesToProcess[0] = nodes; + nodesToProcess = [nodes]; } else if (nodes instanceof NodeList) { nodesToProcess = nodes; } else {