fix: fix passing a single Node to mermaid.init()

Passing a single Node to mermaid.init() results in an error, as it
calls `new NodeList()`, which causes `TypeError: Illegal constructor`.

See 5597cf45bf/src/mermaid.ts (L73)

If we instead use the `ArrayLike` interface, we can just use a simple
array, instead of a NodeList.

I've also added a basic test case, by mocking the `mermaidAPI.render()`
function so it isn't called, as the d3 functions don't work in Node.JS.
The mocks are a bit messy, since
 a) Jest doesn't fully support ESM yet, and
 b) mermaidAPI is frozen with `Object.freeze()`,
but the mermaidAPI mocks work as long as we keep them simple.

Fixes: c68ec54fdd
This commit is contained in:
Alois Klink
2022-09-02 04:28:22 +01:00
parent 5597cf45bf
commit b3c0c57c6d
3 changed files with 67 additions and 3 deletions

View File

@@ -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;