Compare commits

..

2 Commits

Author SHA1 Message Date
Yash Singh
05bdb05a9e chore: code style 2024-05-04 16:37:07 -07:00
Yash Singh
c021f71afc chore: improve types 2024-05-04 16:32:44 -07:00
554 changed files with 24221 additions and 58384 deletions

View File

@@ -1,9 +1,3 @@
export interface PackageOptions {
name: string;
packageName: string;
file: string;
}
/**
* Shared common options for both ESBuild and Vite
*/
@@ -28,9 +22,9 @@ export const packageOptions = {
packageName: 'mermaid-zenuml',
file: 'detector.ts',
},
'mermaid-layout-elk': {
name: 'mermaid-layout-elk',
packageName: 'mermaid-layout-elk',
file: 'layouts.ts',
'mermaid-flowchart-elk': {
name: 'mermaid-flowchart-elk',
packageName: 'mermaid-flowchart-elk',
file: 'detector.ts',
},
} as const satisfies Record<string, PackageOptions>;
} as const;

View File

@@ -1,7 +1,6 @@
import jison from 'jison';
export const transformJison = (src: string): string => {
// @ts-ignore - Jison is not typed properly
const parser = new jison.Generator(src, {
moduleType: 'js',
'token-stack': true,

View File

@@ -19,14 +19,12 @@ const MERMAID_CONFIG_DIAGRAM_KEYS = [
'xyChart',
'requirement',
'mindmap',
'kanban',
'timeline',
'gitGraph',
'c4',
'sankey',
'block',
'packet',
'architecture',
] as const;
/**

View File

@@ -1,4 +1,3 @@
/* eslint-disable no-console */
import { packageOptions } from './common.js';
import { execSync } from 'child_process';
@@ -6,17 +5,11 @@ const buildType = (packageName: string) => {
console.log(`Building types for ${packageName}`);
try {
const out = execSync(`tsc -p ./packages/${packageName}/tsconfig.json --emitDeclarationOnly`);
if (out.length > 0) {
console.log(out.toString());
}
out.length > 0 && console.log(out.toString());
} catch (e) {
console.error(e);
if (e.stdout.length > 0) {
console.error(e.stdout.toString());
}
if (e.stderr.length > 0) {
console.error(e.stderr.toString());
}
e.stdout.length > 0 && console.error(e.stdout.toString());
e.stderr.length > 0 && console.error(e.stderr.toString());
}
};

View File

@@ -1,8 +0,0 @@
# Changesets
Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
with multi-package repos, or single-package repos to help you version and publish your code. You can
find the full documentation for it [in our repository](https://github.com/changesets/changesets)
We have a quick list of common questions to get you started engaging with this project in
[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)

View File

@@ -1,5 +0,0 @@
---
'mermaid': patch
---
fix: architecture diagrams no longer grow to extreme heights due to conflicting alignments

View File

@@ -1,5 +0,0 @@
---
'mermaid': patch
---
Fixes for consistent edge id creation & handling edge cases for animate edge feature

View File

@@ -1,5 +0,0 @@
---
'mermaid': patch
---
Fix for issue #6195 - allowing @ signs inside node labels

View File

@@ -1,5 +0,0 @@
---
'mermaid': patch
---
fix: `mermaidAPI.getDiagramFromText()` now returns a new different db for each class diagram

View File

@@ -1,12 +0,0 @@
{
"$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json",
"changelog": ["@changesets/changelog-github", { "repo": "mermaid-js/mermaid" }],
"commit": false,
"fixed": [],
"linked": [],
"access": "public",
"baseBranch": "master",
"updateInternalDependencies": "patch",
"bumpVersionsWithWorkspaceProtocolOnly": true,
"ignore": ["@mermaid-js/docs", "@mermaid-js/webpack-test", "@mermaid-js/mermaid-example-diagram"]
}

View File

@@ -1,5 +0,0 @@
---
'mermaid': patch
---
fix: revert state db to resolve getData returning empty nodes and edges

View File

@@ -1,8 +0,0 @@
---
'mermaid': minor
---
Flowchart new syntax for node metadata bugs
- Incorrect label mapping for nodes when using `&`
- Syntax error when `}` with trailing spaces before new line

View File

@@ -1,5 +0,0 @@
---
'mermaid': minor
---
Adding support for animation of flowchart edges

View File

@@ -1,5 +0,0 @@
---
'mermaid': patch
---
fix: `mermaidAPI.getDiagramFromText()` now returns a new different db for each flowchart

View File

@@ -1,5 +0,0 @@
---
'mermaid': patch
---
fix: Gantt, Sankey and User Journey diagram are now able to pick font-family from mermaid config.

View File

@@ -1,5 +0,0 @@
---
'mermaid': patch
---
`mermaidAPI.getDiagramFromText()` now returns a new different db for each state diagram

View File

@@ -13,7 +13,6 @@ bqstring
BQUOTE
bramp
BRKT
brotli
callbackargs
callbackname
classdef
@@ -26,10 +25,8 @@ concat
controlx
controly
CSSCLASS
curv
CYLINDEREND
CYLINDERSTART
DAGA
datakey
DEND
descr
@@ -56,7 +53,6 @@ GENERICTYPE
getBoundarys
grammr
graphtype
halign
iife
interp
introdcued
@@ -68,7 +64,6 @@ Kaufmann
keyify
LABELPOS
LABELTYPE
layoutstop
lcov
LEFTOF
Lexa
@@ -94,7 +89,6 @@ reqs
rewritelinks
rgba
RIGHTOF
roughjs
sankey
sequencenumber
shrc
@@ -114,17 +108,13 @@ strikethrough
stringifying
struct
STYLECLASS
STYLEDEF
STYLEOPTS
subcomponent
subcomponents
subconfig
SUBROUTINEEND
SUBROUTINESTART
Subschemas
substr
SVGG
SVGSVG
TAGEND
TAGSTART
techn
@@ -135,13 +125,11 @@ titlevalue
topbar
TRAPEND
TRAPSTART
treemap
ts-nocheck
tsdoc
typeof
typestr
unshift
urlsafe
verifymethod
VERIFYMTHD
WARN_DOCSDIR_DOESNT_MATCH

View File

@@ -4,6 +4,5 @@ cpettitt
Dong Cai
Nikolay Rozhkov
Peng Xiao
Per Brolin
subhash-halder
Vinod Sidharth

View File

@@ -28,9 +28,6 @@ dictionaryDefinitions:
- name: suggestions
words:
- none
- disp
- subproc
- tria
suggestWords:
- seperator:separator
- vertice:vertex

View File

@@ -20,17 +20,14 @@ dagre-d3
Deepdwn
Docsify
Docsy
Doctave
DokuWiki
dompurify
elkjs
fcose
fontawesome
Foswiki
Gitea
graphlib
Grav
icones
iconify
Inkdrop
jiti
@@ -57,17 +54,13 @@ presetAttributify
pyplot
redmine
rehype
roughjs
rscratch
shiki
Slidev
sparkline
sphinxcontrib
ssim
stylis
Swimm
tsbuildinfo
tseslint
Tuleap
Typora
unocss

View File

@@ -1,18 +1,14 @@
Adamiecki
arrowend
Bendpoints
bmatrix
braintree
catmull
compositTitleSize
curv
doublecircle
elems
gantt
gitgraph
gzipped
handDrawn
kanban
knsv
Knut
marginx
@@ -21,12 +17,10 @@ Markdownish
mermaidjs
mindmap
mindmaps
mrtree
multigraph
nodesep
NOTEGROUP
Pinterest
procs
rankdir
ranksep
rect

View File

@@ -1,7 +1 @@
BRANDES
circo
handDrawn
KOEPF
neato
newbranch
validify

View File

@@ -2,17 +2,13 @@ import { build } from 'esbuild';
import { mkdir, writeFile } from 'node:fs/promises';
import { packageOptions } from '../.build/common.js';
import { generateLangium } from '../.build/generateLangium.js';
import type { MermaidBuildOptions } from './util.js';
import { defaultOptions, getBuildConfig } from './util.js';
import { MermaidBuildOptions, defaultOptions, getBuildConfig } from './util.js';
const shouldVisualize = process.argv.includes('--visualize');
const buildPackage = async (entryName: keyof typeof packageOptions) => {
const commonOptions: MermaidBuildOptions = {
...defaultOptions,
options: packageOptions[entryName],
} as const;
const buildConfigs: MermaidBuildOptions[] = [
const commonOptions = { ...defaultOptions, entryName } as const;
const buildConfigs = [
// package.mjs
{ ...commonOptions },
// package.min.mjs
@@ -39,11 +35,11 @@ const buildPackage = async (entryName: keyof typeof packageOptions) => {
if (shouldVisualize) {
for (const { metafile } of results) {
if (!metafile?.outputs) {
if (!metafile) {
continue;
}
const fileName = Object.keys(metafile.outputs)
.find((file) => !file.includes('chunks') && file.endsWith('js'))!
.filter((file) => !file.includes('chunks') && file.endsWith('js'))[0]
.replace('dist/', '');
// Upload metafile into https://esbuild.github.io/analyze/
await writeFile(`stats/${fileName}.meta.json`, JSON.stringify(metafile));
@@ -52,14 +48,13 @@ const buildPackage = async (entryName: keyof typeof packageOptions) => {
};
const handler = (e) => {
// eslint-disable-next-line no-console
console.error(e);
process.exit(1);
};
const main = async () => {
await generateLangium();
await mkdir('stats', { recursive: true });
await mkdir('stats').catch(() => {});
const packageNames = Object.keys(packageOptions) as (keyof typeof packageOptions)[];
// it should build `parser` before `mermaid` because it's a dependency
for (const pkg of packageNames) {

View File

@@ -1,6 +1,6 @@
import { readFile } from 'node:fs/promises';
import { transformJison } from '../.build/jisonTransformer.js';
import type { Plugin } from 'esbuild';
import { Plugin } from 'esbuild';
export const jisonPlugin: Plugin = {
name: 'jison',

View File

@@ -1,52 +1,34 @@
/* eslint-disable no-console */
import chokidar from 'chokidar';
import cors from 'cors';
import { context } from 'esbuild';
import type { Request, Response } from 'express';
import express from 'express';
import { packageOptions } from '../.build/common.js';
import type { NextFunction, Request, Response } from 'express';
import cors from 'cors';
import { getBuildConfig, defaultOptions } from './util.js';
import { context } from 'esbuild';
import chokidar from 'chokidar';
import { generateLangium } from '../.build/generateLangium.js';
import { defaultOptions, getBuildConfig } from './util.js';
import { packageOptions } from '../.build/common.js';
const configs = Object.values(packageOptions).map(({ packageName }) =>
getBuildConfig({
...defaultOptions,
minify: false,
core: false,
options: packageOptions[packageName],
})
getBuildConfig({ ...defaultOptions, minify: false, core: false, entryName: packageName })
);
const mermaidIIFEConfig = getBuildConfig({
...defaultOptions,
minify: false,
core: false,
options: packageOptions.mermaid,
entryName: 'mermaid',
format: 'iife',
});
configs.push(mermaidIIFEConfig);
const contexts = await Promise.all(
configs.map(async (config) => ({ config, context: await context(config) }))
);
const contexts = await Promise.all(configs.map((config) => context(config)));
let rebuildCounter = 1;
const rebuildAll = async () => {
const buildNumber = rebuildCounter++;
const timeLabel = `Rebuild ${buildNumber} Time (total)`;
console.time(timeLabel);
await Promise.all(
contexts.map(async ({ config, context }) => {
const buildVariant = `Rebuild ${buildNumber} Time (${Object.keys(config.entryPoints!)[0]} ${config.format})`;
console.time(buildVariant);
await context.rebuild();
console.timeEnd(buildVariant);
})
).catch((e) => console.error(e));
console.timeEnd(timeLabel);
console.time('Rebuild time');
await Promise.all(contexts.map((ctx) => ctx.rebuild())).catch((e) => console.error(e));
console.timeEnd('Rebuild time');
};
let clients: { id: number; response: Response }[] = [];
function eventsHandler(request: Request, response: Response) {
function eventsHandler(request: Request, response: Response, next: NextFunction) {
const headers = {
'Content-Type': 'text/event-stream',
Connection: 'keep-alive',
@@ -63,20 +45,19 @@ function eventsHandler(request: Request, response: Response) {
});
}
let timeoutID: NodeJS.Timeout | undefined = undefined;
let timeoutId: NodeJS.Timeout | undefined = undefined;
/**
* Debounce file change events to avoid rebuilding multiple times.
*/
function handleFileChange() {
if (timeoutID !== undefined) {
clearTimeout(timeoutID);
if (timeoutId !== undefined) {
clearTimeout(timeoutId);
}
// eslint-disable-next-line @typescript-eslint/no-misused-promises
timeoutID = setTimeout(async () => {
timeoutId = setTimeout(async () => {
await rebuildAll();
sendEventsToAll();
timeoutID = undefined;
timeoutId = undefined;
}, 100);
}
@@ -93,16 +74,15 @@ async function createServer() {
ignoreInitial: true,
ignored: [/node_modules/, /dist/, /docs/, /coverage/],
})
// eslint-disable-next-line @typescript-eslint/no-misused-promises
.on('all', async (event, path) => {
// Ignore other events.
if (!['add', 'change'].includes(event)) {
return;
}
console.log(`${path} changed. Rebuilding...`);
if (path.endsWith('.langium')) {
if (/\.langium$/.test(path)) {
await generateLangium();
}
console.log(`${path} changed. Rebuilding...`);
handleFileChange();
});
@@ -119,4 +99,4 @@ async function createServer() {
});
}
void createServer();
createServer();

View File

@@ -3,20 +3,20 @@ import { fileURLToPath } from 'url';
import type { BuildOptions } from 'esbuild';
import { readFileSync } from 'fs';
import jsonSchemaPlugin from './jsonSchemaPlugin.js';
import type { PackageOptions } from '../.build/common.js';
import { packageOptions } from '../.build/common.js';
import { jisonPlugin } from './jisonPlugin.js';
const __dirname = fileURLToPath(new URL('.', import.meta.url));
export interface MermaidBuildOptions extends BuildOptions {
export interface MermaidBuildOptions {
minify: boolean;
core: boolean;
metafile: boolean;
format: 'esm' | 'iife';
options: PackageOptions;
entryName: keyof typeof packageOptions;
}
export const defaultOptions: Omit<MermaidBuildOptions, 'entryName' | 'options'> = {
export const defaultOptions: Omit<MermaidBuildOptions, 'entryName'> = {
minify: false,
metafile: false,
core: false,
@@ -52,16 +52,11 @@ const getFileName = (fileName: string, { core, format, minify }: MermaidBuildOpt
};
export const getBuildConfig = (options: MermaidBuildOptions): BuildOptions => {
const {
core,
metafile,
format,
minify,
options: { name, file, packageName },
} = options;
const { core, entryName, metafile, format, minify } = options;
const external: string[] = ['require', 'fs', 'path'];
const { name, file, packageName } = packageOptions[entryName];
const outFileName = getFileName(name, options);
const output: BuildOptions = buildOptions({
let output: BuildOptions = buildOptions({
absWorkingDir: resolve(__dirname, `../packages/${packageName}`),
entryPoints: {
[outFileName]: `src/${file}`,

1
.eslintignore Symbolic link
View File

@@ -0,0 +1 @@
.gitignore

190
.eslintrc.cjs Normal file
View File

@@ -0,0 +1,190 @@
module.exports = {
env: {
browser: true,
es6: true,
'jest/globals': true,
node: true,
},
root: true,
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaFeatures: {
experimentalObjectRestSpread: true,
jsx: true,
},
tsconfigRootDir: __dirname,
sourceType: 'module',
ecmaVersion: 2022,
allowAutomaticSingleRunInference: true,
project: ['./tsconfig.eslint.json', './packages/*/tsconfig.json'],
parser: '@typescript-eslint/parser',
},
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:json/recommended',
'plugin:markdown/recommended-legacy',
'plugin:@cspell/recommended',
'prettier',
],
plugins: [
'@typescript-eslint',
'no-only-tests',
'html',
'jest',
'jsdoc',
'json',
'@cspell',
'lodash',
'unicorn',
],
ignorePatterns: [
// this file is automatically generated by `pnpm run --filter mermaid types:build-config`
'packages/mermaid/src/config.type.ts',
],
rules: {
curly: 'error',
'no-console': 'error',
'no-prototype-builtins': 'off',
'no-unused-vars': 'off',
'cypress/no-async-tests': 'off',
'@typescript-eslint/consistent-type-imports': 'error',
'@typescript-eslint/no-explicit-any': 'warn',
'@typescript-eslint/no-floating-promises': 'error',
'@typescript-eslint/no-misused-promises': 'error',
'@typescript-eslint/no-unused-vars': 'warn',
'@typescript-eslint/consistent-type-definitions': 'error',
'@typescript-eslint/ban-ts-comment': [
'error',
{
'ts-expect-error': 'allow-with-description',
'ts-ignore': 'allow-with-description',
'ts-nocheck': 'allow-with-description',
'ts-check': 'allow-with-description',
minimumDescriptionLength: 10,
},
],
'@typescript-eslint/naming-convention': [
'error',
{
selector: 'typeLike',
format: ['PascalCase'],
custom: {
regex: '^I[A-Z]',
match: false,
},
},
],
'json/*': ['error', 'allowComments'],
'@cspell/spellchecker': [
'error',
{
checkIdentifiers: true,
checkStrings: true,
checkStringTemplates: true,
},
],
'no-empty': [
'error',
{
allowEmptyCatch: true,
},
],
'no-only-tests/no-only-tests': 'error',
'lodash/import-scope': ['error', 'method'],
'unicorn/better-regex': 'error',
'unicorn/no-abusive-eslint-disable': 'error',
'unicorn/no-array-push-push': 'error',
'unicorn/no-for-loop': 'error',
'unicorn/no-instanceof-array': 'error',
'unicorn/no-typeof-undefined': 'error',
'unicorn/no-unnecessary-await': 'error',
'unicorn/no-unsafe-regex': 'warn',
'unicorn/no-useless-promise-resolve-reject': 'error',
'unicorn/prefer-array-find': 'error',
'unicorn/prefer-array-flat-map': 'error',
'unicorn/prefer-array-index-of': 'error',
'unicorn/prefer-array-some': 'error',
'unicorn/prefer-default-parameters': 'error',
'unicorn/prefer-includes': 'error',
'unicorn/prefer-negative-index': 'error',
'unicorn/prefer-object-from-entries': 'error',
'unicorn/prefer-string-starts-ends-with': 'error',
'unicorn/prefer-string-trim-start-end': 'error',
'unicorn/string-content': 'error',
'unicorn/prefer-spread': 'error',
'unicorn/no-lonely-if': 'error',
},
overrides: [
{
files: ['cypress/**', 'demos/**'],
rules: {
'no-console': 'off',
},
},
{
files: ['*.{js,jsx,mjs,cjs}'],
extends: ['plugin:jsdoc/recommended'],
rules: {
'jsdoc/check-indentation': 'off',
'jsdoc/check-alignment': 'off',
'jsdoc/check-line-alignment': 'off',
'jsdoc/multiline-blocks': 'off',
'jsdoc/newline-after-description': 'off',
'jsdoc/tag-lines': 'off',
'jsdoc/require-param-description': 'off',
'jsdoc/require-param-type': 'off',
'jsdoc/require-returns': 'off',
'jsdoc/require-returns-description': 'off',
},
},
{
files: ['*.{ts,tsx}'],
plugins: ['tsdoc'],
rules: {
'no-restricted-syntax': [
'error',
{
selector: 'TSEnumDeclaration',
message:
'Prefer using TypeScript union types over TypeScript enum, since TypeScript enums have a bunch of issues, see https://dev.to/dvddpl/whats-the-problem-with-typescript-enums-2okj',
},
],
'tsdoc/syntax': 'error',
},
},
{
files: ['*.spec.{ts,js}', 'cypress/**', 'demos/**', '**/docs/**'],
rules: {
'jsdoc/require-jsdoc': 'off',
'@typescript-eslint/no-unused-vars': 'off',
},
},
{
files: ['*.spec.{ts,js}', 'tests/**', 'cypress/**/*.js'],
rules: {
'@cspell/spellchecker': [
'error',
{
checkIdentifiers: false,
checkStrings: false,
checkStringTemplates: false,
},
],
},
},
{
files: ['*.html', '*.md', '**/*.md/*'],
rules: {
'no-var': 'error',
'no-undef': 'off',
'@typescript-eslint/no-unused-vars': 'off',
'@typescript-eslint/no-floating-promises': 'off',
'@typescript-eslint/no-misused-promises': 'off',
},
parserOptions: {
project: null,
},
},
],
};

8
.github/lychee.toml vendored
View File

@@ -41,13 +41,7 @@ exclude = [
"https://bundlephobia.com",
# Chrome webstore migration issue. Temporary
"https://chromewebstore.google.com",
# Drupal 403
"https://(www.)?drupal.org",
# Swimm returns 404, eventhough the link is valid
"https://docs.swimm.io"
"https://chromewebstore.google.com"
]
# Exclude all private IPs from checking.

View File

@@ -15,4 +15,4 @@ Make sure you
- [ ] :book: have read the [contribution guidelines](https://mermaid.js.org/community/contributing.html)
- [ ] :computer: have added necessary unit/e2e tests.
- [ ] :notebook: have added documentation. Make sure [`MERMAID_RELEASE_VERSION`](https://mermaid.js.org/community/contributing.html#update-documentation) is used for all new features.
- [ ] :butterfly: If your PR makes a change that should be noted in one or more packages' changelogs, generate a changeset by running `pnpm changeset` and following the prompts. Changesets that add features should be `minor` and those that fix bugs should be `patch`. Please prefix changeset messages with `feat:`, `fix:`, or `chore:`.
- [ ] :bookmark: targeted `develop` branch

36
.github/release-drafter.yml vendored Normal file
View File

@@ -0,0 +1,36 @@
name-template: '$NEXT_PATCH_VERSION'
tag-template: '$NEXT_PATCH_VERSION'
categories:
- title: '🚨 **Breaking Changes**'
labels:
- 'Breaking Change'
- title: '🚀 Features'
labels:
- 'Type: Enhancement'
- 'feature' # deprecated, new PRs shouldn't have this
- title: '🐛 Bug Fixes'
labels:
- 'Type: Bug / Error'
- 'fix' # deprecated, new PRs shouldn't have this
- title: '🧰 Maintenance'
labels:
- 'Type: Other'
- 'chore' # deprecated, new PRs shouldn't have this
- title: '⚡️ Performance'
labels:
- 'Type: Performance'
- title: '📚 Documentation'
labels:
- 'Area: Documentation'
change-template: '- $TITLE (#$NUMBER) @$AUTHOR'
sort-by: title
sort-direction: ascending
exclude-labels:
- 'Skip changelog'
no-changes-template: 'This release contains minor changes and bugfixes.'
template: |
# Release Notes
$CHANGES
🎉 **Thanks to all contributors helping with this release!** 🎉

View File

@@ -1,45 +0,0 @@
name: autofix.ci # needed to securely identify the workflow
on:
pull_request:
branches-ignore:
- 'renovate/**'
permissions:
contents: read
concurrency: ${{ github.workflow }}-${{ github.ref }}
jobs:
autofix:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
# uses version from "packageManager" field in package.json
- name: Setup Node.js
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
with:
cache: pnpm
node-version-file: '.node-version'
- name: Install Packages
run: |
pnpm install --frozen-lockfile
env:
CYPRESS_CACHE_FOLDER: .cache/Cypress
- name: Fix Linting
shell: bash
run: pnpm -w run lint:fix
- name: Sync `./src/config.type.ts` with `./src/schemas/config.schema.yaml`
shell: bash
run: pnpm run --filter mermaid types:build-config
- name: Build Docs
working-directory: ./packages/mermaid
run: pnpm run docs:build
- uses: autofix-ci/action@551dded8c6cc8a1054039c8bc0b8b48c51dfc6ef # main

View File

@@ -8,8 +8,6 @@ on:
pull_request:
merge_group:
concurrency: ${{ github.workflow }}-${{ github.ref }}
permissions:
contents: read
@@ -18,12 +16,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
uses: actions/checkout@v4
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
- uses: pnpm/action-setup@v2
- name: Setup Node.js
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
uses: actions/setup-node@v4
with:
cache: pnpm
node-version-file: '.node-version'

49
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,49 @@
name: Build
on:
push: {}
merge_group:
pull_request:
types:
- opened
- synchronize
- ready_for_review
permissions:
contents: read
jobs:
build-mermaid:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v2
# uses version from "packageManager" field in package.json
- name: Setup Node.js
uses: actions/setup-node@v4
with:
cache: pnpm
node-version-file: '.node-version'
- name: Install Packages
run: |
pnpm install --frozen-lockfile
env:
CYPRESS_CACHE_FOLDER: .cache/Cypress
- name: Run Build
run: pnpm run build
- name: Upload Mermaid Build as Artifact
uses: actions/upload-artifact@v4
with:
name: mermaid-build
path: packages/mermaid/dist
- name: Upload Mermaid Mindmap Build as Artifact
uses: actions/upload-artifact@v4
with:
name: mermaid-mindmap-build
path: packages/mermaid-mindmap/dist

View File

@@ -18,7 +18,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
uses: actions/checkout@v4
- name: Check for difference in README.md and docs/README.md
run: |

26
.github/workflows/checks.yml vendored Normal file
View File

@@ -0,0 +1,26 @@
on:
push:
merge_group:
pull_request:
types:
- opened
- synchronize
- ready_for_review
name: Static analysis on Test files
jobs:
check-tests:
runs-on: ubuntu-latest
name: check tests
if: github.repository_owner == 'mermaid-js'
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: testomatio/check-tests@stable
with:
framework: cypress
tests: './cypress/e2e/**/**.spec.js'
token: ${{ secrets.GITHUB_TOKEN }}
has-tests-label: true

View File

@@ -11,9 +11,6 @@ on:
- synchronize
- ready_for_review
permissions: # added using https://github.com/step-security/secure-repo
contents: read
jobs:
analyze:
name: Analyze
@@ -32,11 +29,11 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12
uses: github/codeql-action/init@v3
with:
config-file: ./.github/codeql/codeql-config.yml
languages: ${{ matrix.language }}
@@ -48,7 +45,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12
uses: github/codeql-action/autobuild@v3
# Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
@@ -62,4 +59,4 @@ jobs:
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12
uses: github/codeql-action/analyze@v3

View File

@@ -15,6 +15,6 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: 'Checkout Repository'
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
uses: actions/checkout@v4
- name: 'Dependency Review'
uses: actions/dependency-review-action@5a2ce3f5b92ee19cbb1541a4984c76d921601d7c # v4.3.4
uses: actions/dependency-review-action@v4

View File

@@ -11,8 +11,6 @@ on:
default: master
description: 'Parent branch to use for PRs'
concurrency: ${{ github.workflow }}-${{ github.ref }}
permissions:
contents: read
@@ -32,13 +30,13 @@ jobs:
run: |
echo "::error,title=Not using Applitools::APPLITOOLS_API_KEY is empty, disabling Applitools for this run."
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/checkout@v4
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
- uses: pnpm/action-setup@v2
# uses version from "packageManager" field in package.json
- name: Setup Node.js
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
uses: actions/setup-node@v4
with:
node-version-file: '.node-version'
@@ -54,7 +52,7 @@ jobs:
APPLITOOLS_SERVER_URL: 'https://eyesapi.applitools.com'
- name: Cypress run
uses: cypress-io/github-action@d79d2d530a66e641eb4a5f227e13bc985c60b964 # v4.2.2
uses: cypress-io/github-action@v4
id: cypress
with:
start: pnpm run dev

View File

@@ -1,53 +0,0 @@
name: E2E - Generate Timings
on:
# run this workflow every night at 3am
schedule:
- cron: '28 3 * * *'
# or when the user triggers it from GitHub Actions page
workflow_dispatch:
concurrency: ${{ github.workflow }}-${{ github.ref }}
permissions:
contents: write
jobs:
timings:
runs-on: ubuntu-latest
container:
image: cypress/browsers:node-20.11.0-chrome-121.0.6167.85-1-ff-120.0-edge-121.0.2277.83-1
options: --user 1001
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
- name: Setup Node.js
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
with:
node-version-file: '.node-version'
- name: Install dependencies
uses: cypress-io/github-action@0da3c06ed8217b912deea9d8ee69630baed1737e # v6.7.6
with:
runTests: false
- name: Cypress run
uses: cypress-io/github-action@0da3c06ed8217b912deea9d8ee69630baed1737e # v6.7.6
id: cypress
with:
install: false
start: pnpm run dev:coverage
wait-on: 'http://localhost:9000'
browser: chrome
publish-summary: false
env:
VITEST_COVERAGE: true
CYPRESS_COMMIT: ${{ github.sha }}
SPLIT: 1
SPLIT_INDEX: 0
SPLIT_FILE: 'cypress/timings.json'
- name: Commit changes
uses: EndBug/add-and-commit@a94899bca583c204427a224a7af87c02f9b325d5 # v9.1.4
with:
add: 'cypress/timings.json'
author_name: 'github-actions[bot]'
author_email: '41898282+github-actions[bot]@users.noreply.github.com'
message: 'chore: update E2E timings'

View File

@@ -1,19 +1,18 @@
# We use github cache to save snapshots between runs.
# For PRs and MergeQueues, the target commit is used, and for push events, github.event.previous is used.
# If a snapshot for a given Hash is not found, we checkout that commit, run the tests and cache the snapshots.
# These are then downloaded before running the E2E, providing the reference snapshots.
# If there are any errors, the diff image is uploaded to artifacts, and the user is notified.
name: E2E
on:
push:
branches:
- develop
- master
- release/**
branches-ignore:
- 'gh-readonly-queue/**'
pull_request:
issue_comment:
types:
- created
merge_group:
concurrency: ${{ github.workflow }}-${{ github.ref }}
permissions:
contents: read
@@ -31,26 +30,22 @@ env:
) ||
github.event.before
}}
# Check if this is a new comment with '/visual-test'
RUN_VISUAL_TEST: >-
${{ github.event_name == 'issue_comment' && github.event.action == 'created' && contains(github.event.comment.body, '/visual-test') && github.event.issue.pull_request != null }}
jobs:
cache:
if: ${{ github.event_name != 'issue_comment' || contains(github.event.comment.body, '/visual-test') }}
runs-on: ubuntu-latest
container:
image: cypress/browsers:node-20.11.0-chrome-121.0.6167.85-1-ff-120.0-edge-121.0.2277.83-1
options: --user 1001
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v2
- name: Setup Node.js
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
uses: actions/setup-node@v4
with:
node-version-file: '.node-version'
- name: Cache snapshots
id: cache-snapshot
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
uses: actions/cache@v4
with:
save-always: true
path: ./cypress/snapshots
@@ -59,13 +54,13 @@ jobs:
# If a snapshot for a given Hash is not found, we checkout that commit, run the tests and cache the snapshots.
- name: Switch to base branch
if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }}
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
uses: actions/checkout@v4
with:
ref: ${{ env.targetHash }}
- name: Install dependencies
if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }}
uses: cypress-io/github-action@0da3c06ed8217b912deea9d8ee69630baed1737e # v6.7.6
uses: cypress-io/github-action@v6
with:
# just perform install
runTests: false
@@ -77,6 +72,16 @@ jobs:
mkdir -p cypress/snapshots/stats/base
mv stats cypress/snapshots/stats/base
- name: Cypress run
uses: cypress-io/github-action@v6
id: cypress-snapshot-gen
if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }}
with:
install: false
start: pnpm run dev
wait-on: 'http://localhost:9000'
browser: chrome
e2e:
runs-on: ubuntu-latest
container:
@@ -86,28 +91,28 @@ jobs:
strategy:
fail-fast: false
matrix:
containers: [1, 2, 3, 4, 5]
containers: [1, 2, 3, 4]
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/checkout@v4
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
- uses: pnpm/action-setup@v2
# uses version from "packageManager" field in package.json
- name: Setup Node.js
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
uses: actions/setup-node@v4
with:
node-version-file: '.node-version'
# These cached snapshots are downloaded, providing the reference snapshots.
- name: Cache snapshots
id: cache-snapshot
uses: actions/cache/restore@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
uses: actions/cache/restore@v4
with:
path: ./cypress/snapshots
key: ${{ runner.os }}-snapshots-${{ env.targetHash }}
- name: Install dependencies
uses: cypress-io/github-action@0da3c06ed8217b912deea9d8ee69630baed1737e # v6.7.6
uses: cypress-io/github-action@v6
with:
runTests: false
@@ -123,8 +128,11 @@ jobs:
# Install NPM dependencies, cache them correctly
# and run all Cypress tests
- name: Cypress run
uses: cypress-io/github-action@0da3c06ed8217b912deea9d8ee69630baed1737e # v6.7.6
uses: cypress-io/github-action@v6
id: cypress
# If CYPRESS_RECORD_KEY is set, run in parallel on all containers
# Otherwise (e.g. if running from fork), we run on a single container only
if: ${{ ( env.CYPRESS_RECORD_KEY != '' ) || ( matrix.containers == 1 ) }}
with:
install: false
start: pnpm run dev:coverage
@@ -133,21 +141,14 @@ jobs:
# Disable recording if we don't have an API key
# e.g. if this action was run from a fork
record: ${{ secrets.CYPRESS_RECORD_KEY != '' }}
parallel: ${{ secrets.CYPRESS_RECORD_KEY != '' }}
env:
# Only set Argos environment variables if the visual test comment trigger is present
ARGOS_TOKEN: ${{ env.RUN_VISUAL_TEST == 'true' && secrets.ARGOS_TOKEN || '' }}
ARGOS_PARALLEL: ${{ env.RUN_VISUAL_TEST == 'true' }}
ARGOS_PARALLEL_TOTAL: ${{ env.RUN_VISUAL_TEST == 'true' && strategy.job-total || 1 }}
ARGOS_PARALLEL_INDEX: ${{ env.RUN_VISUAL_TEST == 'true' && matrix.containers || 1 }}
CYPRESS_COMMIT: ${{ github.sha }}
CYPRESS_RECORD_KEY: ${{ env.RUN_VISUAL_TEST == 'true' && secrets.CYPRESS_RECORD_KEY || ''}}
SPLIT: ${{ strategy.job-total }}
SPLIT_INDEX: ${{ strategy.job-index }}
SPLIT_FILE: 'cypress/timings.json'
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
VITEST_COVERAGE: true
CYPRESS_COMMIT: ${{ github.sha }}
- name: Upload Coverage to Codecov
uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0
uses: codecov/codecov-action@v4
# Run step only pushes to develop and pull_requests
if: ${{ steps.cypress.conclusion == 'success' && (github.event_name == 'pull_request' || github.ref == 'refs/heads/develop')}}
with:
@@ -157,3 +158,55 @@ jobs:
fail_ci_if_error: false
verbose: true
token: 6845cc80-77ee-4e17-85a1-026cd95e0766
# We upload the artifacts into numbered archives to prevent overwriting
- name: Upload Artifacts
uses: actions/upload-artifact@v4
if: ${{ always() }}
with:
name: snapshots-${{ matrix.containers }}
retention-days: 1
path: ./cypress/snapshots
combineArtifacts:
needs: e2e
runs-on: ubuntu-latest
if: ${{ always() }}
steps:
# Download all snapshot artifacts and merge them into a single folder
- name: Download All Artifacts
uses: actions/download-artifact@v4
with:
path: snapshots
pattern: snapshots-*
merge-multiple: true
# For successful push events, we save the snapshots cache
- name: Save snapshots cache
id: cache-upload
if: ${{ github.event_name == 'push' && needs.e2e.result != 'failure' }}
uses: actions/cache/save@v4
with:
path: ./snapshots
key: ${{ runner.os }}-snapshots-${{ github.event.after }}
- name: Flatten images to a folder
if: ${{ needs.e2e.result == 'failure' }}
run: |
mkdir errors
cd snapshots
find . -mindepth 2 -type d -name "*__diff_output__*" -exec sh -c 'mv "$0"/*.png ../errors/' {} \;
- name: Upload Error snapshots
if: ${{ needs.e2e.result == 'failure' }}
uses: actions/upload-artifact@v4
id: upload-artifacts
with:
name: error-snapshots
retention-days: 10
path: errors/
- name: Notify Users
if: ${{ needs.e2e.result == 'failure' }}
run: |
echo "::error title=Visual tests failed::You can view images that failed by downloading the error-snapshots artifact: ${{ steps.upload-artifacts.outputs.artifact-url }}"

View File

@@ -4,17 +4,11 @@ on:
issues:
types: [opened]
permissions: # added using https://github.com/step-security/secure-repo
contents: read
jobs:
triage:
permissions:
issues: write # for andymckay/labeler to label issues
pull-requests: write # for andymckay/labeler to label PRs
runs-on: ubuntu-latest
steps:
- uses: andymckay/labeler@e6c4322d0397f3240f0e7e30a33b5c5df2d39e90 # 1.0.4
- uses: andymckay/labeler@1.0.4
with:
repo-token: '${{ secrets.GITHUB_TOKEN }}'
add-labels: 'Status: Triage'

View File

@@ -19,9 +19,6 @@ on:
# * is a special character in YAML so you have to quote this string
- cron: '30 8 * * *'
permissions: # added using https://github.com/step-security/secure-repo
contents: read
jobs:
link-checker:
runs-on: ubuntu-latest
@@ -29,17 +26,17 @@ jobs:
# lychee only uses the GITHUB_TOKEN to avoid rate-limiting
contents: read
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/checkout@v4
- name: Restore lychee cache
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
uses: actions/cache@v4
with:
path: .lycheecache
key: cache-lychee-${{ github.sha }}
restore-keys: cache-lychee-
- name: Link Checker
uses: lycheeverse/lychee-action@c053181aa0c3d17606addfe97a9075a32723548a # v1.9.3
uses: lycheeverse/lychee-action@v1.9.3
with:
args: >-
--config .github/lychee.toml

View File

@@ -4,32 +4,26 @@ on:
push:
merge_group:
pull_request:
types:
- opened
- synchronize
- ready_for_review
workflow_dispatch:
concurrency: ${{ github.workflow }}-${{ github.ref }}
permissions:
contents: write
jobs:
docker-lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: hadolint/hadolint-action@54c9adbab1582c2ef04b2016b760714a4bfde3cf # v3.1.0
with:
verbose: true
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/checkout@v4
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
- uses: pnpm/action-setup@v2
# uses version from "packageManager" field in package.json
- name: Setup Node.js
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
uses: actions/setup-node@v4
with:
cache: pnpm
node-version-file: '.node-version'
@@ -89,9 +83,14 @@ jobs:
continue-on-error: ${{ github.event_name == 'push' }}
run: pnpm run docs:verify
- uses: testomatio/check-tests@0ea638fcec1820cf2e7b9854fdbdd04128a55bd4 # stable
- name: Rebuild Docs
if: ${{ steps.verifyDocs.outcome == 'failure' && github.event_name == 'push' }}
working-directory: ./packages/mermaid
run: pnpm run docs:build
- name: Commit changes
uses: EndBug/add-and-commit@v9
if: ${{ steps.verifyDocs.outcome == 'failure' && github.event_name == 'push' }}
with:
framework: cypress
tests: './cypress/e2e/**/**.spec.js'
token: ${{ secrets.GITHUB_TOKEN }}
has-tests-label: true
message: 'Update docs'
add: 'docs/*'

View File

@@ -22,7 +22,7 @@ jobs:
pull-requests: write # write permission is required to label PRs
steps:
- name: Label PR
uses: release-drafter/release-drafter@3f0f87098bd6b5c5b9a36d49c41d998ea58f9348 # v6.0.0
uses: release-drafter/release-drafter@v6
with:
config-name: pr-labeler.yml
disable-autolabeler: false

View File

@@ -23,12 +23,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
uses: actions/checkout@v4
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
- uses: pnpm/action-setup@v2
- name: Setup Node.js
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
uses: actions/setup-node@v4
with:
cache: pnpm
node-version-file: '.node-version'
@@ -37,13 +37,13 @@ jobs:
run: pnpm install --frozen-lockfile
- name: Setup Pages
uses: actions/configure-pages@1f0c5cde4bc74cd7e1254d0cb4de8d49e9068c7d # v4.0.0
uses: actions/configure-pages@v4
- name: Run Build
run: pnpm --filter mermaid run docs:build:vitepress
- name: Upload artifact
uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3.0.1
uses: actions/upload-pages-artifact@v3
with:
path: packages/mermaid/src/vitepress/.vitepress/dist
@@ -56,4 +56,4 @@ jobs:
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5
uses: actions/deploy-pages@v4

23
.github/workflows/release-draft.yml vendored Normal file
View File

@@ -0,0 +1,23 @@
name: Draft Release
on:
push:
branches:
- master
permissions:
contents: read
jobs:
draft-release:
runs-on: ubuntu-latest
permissions:
contents: write # write permission is required to create a GitHub release
pull-requests: read # required to read PR titles/labels
steps:
- name: Draft Release
uses: release-drafter/release-drafter@v6
with:
disable-autolabeler: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -9,14 +9,14 @@ jobs:
publish-preview:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
- uses: pnpm/action-setup@v2
- name: Setup Node.js
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
uses: actions/setup-node@v4
with:
cache: pnpm
node-version-file: '.node-version'
@@ -28,7 +28,7 @@ jobs:
CYPRESS_CACHE_FOLDER: .cache/Cypress
- name: Install Json
run: npm i json@11.0.0 --global
run: npm i json --global
- name: Publish
working-directory: ./packages/mermaid

View File

@@ -1,43 +0,0 @@
name: Preview release
on:
pull_request:
branches: [develop]
types: [opened, synchronize, labeled, ready_for_review]
concurrency:
group: ${{ github.workflow }}-${{ github.event.number }}
cancel-in-progress: true
permissions:
contents: read
actions: write
jobs:
preview:
if: ${{ github.repository_owner == 'mermaid-js' }}
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
issues: write
pull-requests: write
name: Publish preview release
timeout-minutes: 5
steps:
- name: Checkout Repo
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
- name: Setup Node.js
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
with:
cache: pnpm
node-version-file: '.node-version'
- name: Install Packages
run: pnpm install --frozen-lockfile
- name: Publish packages
run: pnpx pkg-pr-new publish --pnpm './packages/*'

47
.github/workflows/release-publish.yml vendored Normal file
View File

@@ -0,0 +1,47 @@
name: Publish release
on:
release:
types: [published]
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: fregante/setup-git-user@v2
- uses: pnpm/action-setup@v2
# uses version from "packageManager" field in package.json
- name: Setup Node.js
uses: actions/setup-node@v4
with:
cache: pnpm
node-version-file: '.node-version'
- name: Install Packages
run: |
pnpm install --frozen-lockfile
npm i json --global
env:
CYPRESS_CACHE_FOLDER: .cache/Cypress
- name: Prepare release
run: |
VERSION=${GITHUB_REF:10}
echo "Preparing release $VERSION"
git checkout -t origin/release/$VERSION
npm version --no-git-tag-version --allow-same-version $VERSION
git add package.json
git commit -nm "Bump version $VERSION"
git checkout -t origin/master
git merge -m "Release $VERSION" --no-ff release/$VERSION
git push --no-verify
- name: Publish
run: |
npm set //registry.npmjs.org/:_authToken $NPM_TOKEN
npm publish
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

View File

@@ -1,46 +0,0 @@
name: Release
on:
push:
branches:
- master
concurrency: ${{ github.workflow }}-${{ github.ref }}
permissions: # added using https://github.com/step-security/secure-repo
contents: read
jobs:
release:
if: github.repository == 'mermaid-js/mermaid'
permissions:
contents: write # to create release (changesets/action)
id-token: write # OpenID Connect token needed for provenance
pull-requests: write # to create pull request (changesets/action)
name: Release
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
- name: Setup Node.js
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
with:
cache: pnpm
node-version-file: '.node-version'
- name: Install Packages
run: pnpm install --frozen-lockfile
- name: Create Release Pull Request or Publish to npm
id: changesets
uses: changesets/action@3de3850952bec538fde60aac71731376e57b9b57 # v1.4.8
with:
version: pnpm changeset:version
publish: pnpm changeset:publish
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
NPM_CONFIG_PROVENANCE: true

View File

@@ -1,37 +0,0 @@
name: Scorecard supply-chain security
on:
branch_protection_rule:
push:
branches:
- develop
schedule:
- cron: 29 15 * * 0
permissions: read-all
jobs:
analysis:
name: Scorecard analysis
permissions:
id-token: write
security-events: write
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
persist-credentials: false
- name: Run analysis
uses: ossf/scorecard-action@dc50aa9510b46c811795eb24b2f1ba02a914e534 # v2.3.3
with:
results_file: results.sarif
results_format: sarif
publish_results: true
- name: Upload artifact
uses: actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5 # v3.pre.node20
with:
name: SARIF file
path: results.sarif
retention-days: 5
- name: Upload to code-scanning
uses: github/codeql-action/upload-sarif@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12
with:
sarif_file: results.sarif

View File

@@ -9,13 +9,13 @@ jobs:
unit-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/checkout@v4
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
- uses: pnpm/action-setup@v2
# uses version from "packageManager" field in package.json
- name: Setup Node.js
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
uses: actions/setup-node@v4
with:
cache: pnpm
node-version-file: '.node-version'
@@ -38,12 +38,8 @@ jobs:
run: |
pnpm exec vitest run ./packages/mermaid/src/diagrams/gantt/ganttDb.spec.ts --coverage
- name: Verify out-of-tree build with TypeScript
run: |
pnpm test:check:tsc
- name: Upload Coverage to Codecov
uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0
uses: codecov/codecov-action@v4
# Run step only pushes to develop and pull_requests
if: ${{ github.event_name == 'pull_request' || github.ref == 'refs/heads/develop' }}
with:

View File

@@ -8,6 +8,6 @@ jobs:
triage:
runs-on: ubuntu-latest
steps:
- uses: Dunning-Kruger/unlock-issues@b06b7f7e5c3f2eaa1c6d5d89f40930e4d6d9699e # v1
- uses: Dunning-Kruger/unlock-issues@v1
with:
repo-token: '${{ secrets.GITHUB_TOKEN }}'

View File

@@ -8,18 +8,18 @@ jobs:
update-browser-list:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v2
- run: npx update-browserslist-db@latest
- name: Commit changes
uses: EndBug/add-and-commit@a94899bca583c204427a224a7af87c02f9b325d5 # v9.1.4
uses: EndBug/add-and-commit@v9
with:
author_name: ${{ github.actor }}
author_email: ${{ github.actor }}@users.noreply.github.com
message: 'chore: update browsers list'
push: false
- name: Create Pull Request
uses: peter-evans/create-pull-request@c5a7806660adbe173f04e3e038b0ccdcd758773c # v6.1.0
uses: peter-evans/create-pull-request@v6
with:
branch: update-browserslist
title: Update Browserslist

5
.gitignore vendored
View File

@@ -35,7 +35,7 @@ cypress/snapshots/
.tsbuildinfo
tsconfig.tsbuildinfo
#knsv*.html
knsv*.html
local*.html
stats/
@@ -48,7 +48,6 @@ demos/dev/**
!/demos/dev/example.html
!/demos/dev/reload.js
tsx-0/**
vite.config.ts.timestamp-*
# autogenereated by langium-cli
generated/
generated/

View File

@@ -1,2 +0,0 @@
ignored:
- DL3002 # TODO: Last USER should not be root

View File

@@ -1,2 +1,4 @@
#!/usr/bin/env sh
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
NODE_OPTIONS="--max_old_space_size=8192" pnpm run pre-commit

View File

@@ -16,5 +16,3 @@ generated/
# Ignore the files creates in /demos/dev except for example.html
demos/dev/**
!/demos/dev/example.html
# TODO: Lots of errors to fix
cypress/platform/state-refactor.html

View File

@@ -1,5 +1,4 @@
import type { InlineConfig } from 'vite';
import { build, type PluginOption } from 'vite';
import { build, InlineConfig, type PluginOption } from 'vite';
import { resolve } from 'path';
import { fileURLToPath } from 'url';
import jisonPlugin from './jisonPlugin.js';
@@ -47,10 +46,9 @@ interface BuildOptions {
export const getBuildConfig = ({ minify, core, watch, entryName }: BuildOptions): InlineConfig => {
const external: (string | RegExp)[] = ['require', 'fs', 'path'];
// eslint-disable-next-line no-console
console.log(entryName, packageOptions[entryName]);
const { name, file, packageName } = packageOptions[entryName];
const output: OutputOptions = [
let output: OutputOptions = [
{
name,
format: 'esm',
@@ -85,6 +83,7 @@ export const getBuildConfig = ({ minify, core, watch, entryName }: BuildOptions)
plugins: [
jisonPlugin(),
jsonSchemaPlugin(), // handles `.schema.yaml` files
// @ts-expect-error According to the type definitions, rollup plugins are incompatible with vite
typescript({ compilerOptions: { declaration: false } }),
istanbul({
exclude: ['node_modules', 'test/', '__mocks__', 'generated'],
@@ -122,10 +121,10 @@ await generateLangium();
if (watch) {
await build(getBuildConfig({ minify: false, watch, core: false, entryName: 'parser' }));
void build(getBuildConfig({ minify: false, watch, core: false, entryName: 'mermaid' }));
build(getBuildConfig({ minify: false, watch, core: false, entryName: 'mermaid' }));
if (!mermaidOnly) {
void build(getBuildConfig({ minify: false, watch, entryName: 'mermaid-example-diagram' }));
void build(getBuildConfig({ minify: false, watch, entryName: 'mermaid-zenuml' }));
build(getBuildConfig({ minify: false, watch, entryName: 'mermaid-example-diagram' }));
build(getBuildConfig({ minify: false, watch, entryName: 'mermaid-zenuml' }));
}
} else if (visualize) {
await build(getBuildConfig({ minify: false, watch, core: false, entryName: 'parser' }));

View File

@@ -1,4 +1,4 @@
import type { PluginOption } from 'vite';
import { PluginOption } from 'vite';
import { getDefaults, getSchema, loadSchema } from '../.build/jsonSchema.js';
/**

View File

@@ -23,9 +23,8 @@ async function createServer() {
app.use(express.static('cypress/platform'));
app.listen(9000, () => {
// eslint-disable-next-line no-console
console.log(`Listening on http://localhost:9000`);
});
}
void createServer();
createServer();

View File

@@ -1,13 +1,2 @@
FROM node:20.12.2-alpine3.19@sha256:7a91aa397f2e2dfbfcdad2e2d72599f374e0b0172be1d86eeb73f1d33f36a4b2
USER 0:0
RUN corepack enable \
&& corepack enable pnpm
RUN apk add --no-cache git~=2.43.4 \
&& git config --add --system safe.directory /mermaid
ENV NODE_OPTIONS="--max_old_space_size=8192"
EXPOSE 9000 3333
FROM node:20.12.2-alpine3.19 AS base
RUN wget -qO- https://get.pnpm.io/install.sh | ENV="$HOME/.shrc" SHELL="$(which sh)" sh -

View File

@@ -1,7 +0,0 @@
{
"drips": {
"ethereum": {
"ownedBy": "0x0831DDFe60d009d9448CC976157b539089aB821E"
}
}
}

View File

@@ -35,8 +35,6 @@ Try Live Editor previews of future releases: <a href="https://develop.git.mermai
[![NPM Downloads](https://img.shields.io/npm/dm/mermaid)](https://www.npmjs.com/package/mermaid)
[![Join our Discord!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=discord&label=discord)](https://discord.gg/AgrbSrBer3)
[![Twitter Follow](https://img.shields.io/badge/Social-mermaidjs__-blue?style=social&logo=X)](https://twitter.com/mermaidjs_)
[![Covered by Argos Visual Testing](https://argos-ci.com/badge.svg)](https://argos-ci.com?utm_source=mermaid&utm_campaign=oss)
[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/mermaid-js/mermaid/badge)](https://securityscorecards.dev/viewer/?uri=github.com/mermaid-js/mermaid)
<img src="./img/header.png" alt="" />
@@ -83,10 +81,6 @@ You can also use Mermaid within [GitHub](https://github.blog/2022-02-14-include-
For a more detailed introduction to Mermaid and some of its more basic uses, look to the [Beginner's Guide](https://mermaid.js.org/intro/getting-started.html), [Usage](https://mermaid.js.org/config/usage.html) and [Tutorials](https://mermaid.js.org/ecosystem/tutorials.html).
Our PR Visual Regression Testing is powered by [Argos](https://argos-ci.com/?utm_source=mermaid&utm_campaign=oss) with their generous Open Source plan. It makes the process of reviewing PRs with visual changes a breeze.
[![Covered by Argos Visual Testing](https://argos-ci.com/badge-large.svg)](https://argos-ci.com?utm_source=mermaid&utm_campaign=oss)
In our release process we rely heavily on visual regression tests using [applitools](https://applitools.com/). Applitools is a great service which has been easy to use and integrate with our tests.
<a href="https://applitools.com/">
@@ -95,10 +89,6 @@ In our release process we rely heavily on visual regression tests using [applito
<!-- </Main description> -->
## Mermaid AI Bot
[Mermaid](https://codeparrot.ai/oracle?owner=mermaid-js&repo=mermaid) Bot will help you understand this repository better. You can ask for code examples, installation guide, debugging help and much more.
## Examples
**The following are some examples of the diagrams, charts and graphs that can be made using Mermaid. Click here to jump into the [text syntax](https://mermaid.js.org/intro/syntax-reference.html).**

View File

@@ -1,10 +1,7 @@
import eyesPlugin from '@applitools/eyes-cypress';
import { registerArgosTask } from '@argos-ci/cypress/task';
import coverage from '@cypress/code-coverage/task';
import { defineConfig } from 'cypress';
import { addMatchImageSnapshotPlugin } from 'cypress-image-snapshot/plugin';
import cypressSplit from 'cypress-split';
import coverage from '@cypress/code-coverage/task';
import eyesPlugin from '@applitools/eyes-cypress';
export default eyesPlugin(
defineConfig({
projectId: 'n2sma2',
@@ -14,24 +11,16 @@ export default eyesPlugin(
specPattern: 'cypress/integration/**/*.{js,ts}',
setupNodeEvents(on, config) {
coverage(on, config);
cypressSplit(on, config);
on('before:browser:launch', (browser, launchOptions) => {
if (browser.name === 'chrome' && browser.isHeadless) {
launchOptions.args.push('--window-size=1440,1024', '--force-device-scale-factor=1');
}
return launchOptions;
});
addMatchImageSnapshotPlugin(on, config);
// copy any needed variables from process.env to config.env
config.env.useAppli = process.env.USE_APPLI ? true : false;
config.env.useArgos = !!process.env.CI && !!process.env.ARGOS_TOKEN;
if (config.env.useArgos) {
registerArgosTask(on, config, {
token: 'fc3a35cf5200db928d65b2047861582d9444032b',
});
} else {
addMatchImageSnapshotPlugin(on, config);
}
// do not forget to return the changed config object!
return config;
},

View File

@@ -29,14 +29,13 @@ export const mermaidUrl = (
options: CypressMermaidConfig,
api: boolean
): string => {
options.handDrawnSeed = 1;
const codeObject: CodeObject = {
code: graphStr,
mermaid: options,
};
const objStr: string = JSON.stringify(codeObject);
let url = `http://localhost:9000/e2e.html?graph=${utf8ToB64(objStr)}`;
if (api && typeof graphStr === 'string') {
if (api) {
url = `http://localhost:9000/xss.html?graph=${graphStr}`;
}
@@ -55,15 +54,15 @@ export const imgSnapshotTest = (
): void => {
const options: CypressMermaidConfig = {
..._options,
fontFamily: _options.fontFamily ?? 'courier',
// @ts-ignore TODO: Fix type of fontSize
fontSize: _options.fontSize ?? '16px',
fontFamily: _options.fontFamily || 'courier',
fontSize: _options.fontSize || '16px',
sequence: {
...(_options.sequence ?? {}),
...(_options.sequence || {}),
actorFontFamily: 'courier',
noteFontFamily: _options.sequence?.noteFontFamily
? _options.sequence.noteFontFamily
: 'courier',
noteFontFamily:
_options.sequence && _options.sequence.noteFontFamily
? _options.sequence.noteFontFamily
: 'courier',
messageFontFamily: 'courier',
},
};
@@ -74,7 +73,7 @@ export const imgSnapshotTest = (
export const urlSnapshotTest = (
url: string,
options: CypressMermaidConfig = {},
options: CypressMermaidConfig,
_api = false,
validation?: any
): void => {
@@ -95,22 +94,8 @@ export const openURLAndVerifyRendering = (
options: CypressMermaidConfig,
validation?: any
): void => {
const name: string = (options.name ?? cy.state('runnable').fullTitle()).replace(/\s+/g, '-');
cy.visit(url);
cy.window().should('have.property', 'rendered', true);
cy.get('svg').should('be.visible');
if (validation) {
cy.get('svg').should(validation);
}
verifyScreenshot(name);
};
export const verifyScreenshot = (name: string): void => {
const useAppli: boolean = Cypress.env('useAppli');
const useArgos: boolean = Cypress.env('useArgos');
const name: string = (options.name || cy.state('runnable').fullTitle()).replace(/\s+/g, '-');
if (useAppli) {
cy.log(`Opening eyes ${Cypress.spec.name} --- ${name}`);
@@ -120,22 +105,22 @@ export const verifyScreenshot = (name: string): void => {
batchName: Cypress.spec.name,
batchId: batchId + Cypress.spec.name,
});
}
cy.visit(url);
cy.window().should('have.property', 'rendered', true);
cy.get('svg').should('be.visible');
if (validation) {
cy.get('svg').should(validation);
}
if (useAppli) {
cy.log(`Check eyes ${Cypress.spec.name}`);
cy.eyesCheckWindow('Click!');
cy.log(`Closing eyes ${Cypress.spec.name}`);
cy.eyesClose();
} else if (useArgos) {
cy.argosScreenshot(name, {
threshold: 0.01,
});
} else {
cy.matchImageSnapshot(name);
}
};
export const verifyNumber = (value: number, expected: number, deltaPercent = 10): void => {
expect(value).to.be.within(
expected * (1 - deltaPercent / 100),
expected * (1 + deltaPercent / 100)
);
};

View File

@@ -1,4 +1,4 @@
import { renderGraph, verifyScreenshot } from '../../helpers/util.ts';
import { renderGraph } from '../../helpers/util.ts';
describe('Configuration', () => {
describe('arrowMarkerAbsolute', () => {
it('should handle default value false of arrowMarkerAbsolute', () => {
@@ -119,7 +119,8 @@ describe('Configuration', () => {
const url = 'http://localhost:9000/regression/issue-1874.html';
cy.visit(url);
cy.window().should('have.property', 'rendered', true);
verifyScreenshot(
cy.get('svg').should('be.visible');
cy.matchImageSnapshot(
'configuration.spec-should-not-taint-initial-configuration-when-using-multiple-directives'
);
});
@@ -144,7 +145,7 @@ describe('Configuration', () => {
// none of the diagrams should be error diagrams
expect($svg).to.not.contain('Syntax error');
});
verifyScreenshot(
cy.matchImageSnapshot(
'configuration.spec-should-not-render-error-diagram-if-suppressErrorRendering-is-set'
);
});
@@ -161,7 +162,7 @@ describe('Configuration', () => {
// some of the diagrams should be error diagrams
expect($svg).to.contain('Syntax error');
});
verifyScreenshot(
cy.matchImageSnapshot(
'configuration.spec-should-render-error-diagram-if-suppressErrorRendering-is-not-set'
);
});

View File

@@ -0,0 +1,14 @@
import { urlSnapshotTest, openURLAndVerifyRendering } from '../../helpers/util.ts';
describe('Flowchart elk', () => {
it('should use dagre as fallback', () => {
urlSnapshotTest('http://localhost:9000/flow-elk.html', {
name: 'flow-elk fallback to dagre',
});
});
it('should allow overriding with external package', () => {
urlSnapshotTest('http://localhost:9000/flow-elk.html?elk=true', {
name: 'flow-elk overriding dagre with elk',
});
});
});

View File

@@ -10,6 +10,7 @@ describe('XSS', () => {
cy.wait(1000).then(() => {
cy.get('.mermaid').should('exist');
});
cy.get('svg');
});
it('should not allow tags in the css', () => {
@@ -136,9 +137,4 @@ describe('XSS', () => {
cy.wait(1000);
cy.get('#the-malware').should('not.exist');
});
it('should sanitize backticks block diagram labels properly', () => {
cy.visit('http://localhost:9000/xss25.html');
cy.wait(1000);
cy.get('#the-malware').should('not.exist');
});
});

View File

@@ -11,27 +11,6 @@ describe('Git Graph diagram', () => {
{}
);
});
it('Should render subgraphs with title margins and edge labels', () => {
imgSnapshotTest(
`flowchart LR
subgraph TOP
direction TB
subgraph B1
direction RL
i1 --lb1-->f1
end
subgraph B2
direction BT
i2 --lb2-->f2
end
end
A --lb3--> TOP --lb4--> B
B1 --lb5--> B2
`,
{ flowchart: { subGraphTitleMargin: { top: 10, bottom: 5 } } }
);
});
// it(`ultraFastTest`, function () {
// // Navigate to the url we want to test
// // ⭐️ Note to see visual bugs, run the test using the above URL for the 1st run.

View File

@@ -1,233 +0,0 @@
import { imgSnapshotTest, urlSnapshotTest } from '../../helpers/util.ts';
describe.skip('architecture diagram', () => {
it('should render a simple architecture diagram with groups', () => {
imgSnapshotTest(
`architecture-beta
group api(cloud)[API]
service db(database)[Database] in api
service disk1(disk)[Storage] in api
service disk2(disk)[Storage] in api
service server(server)[Server] in api
service gateway(internet)[Gateway]
db L--R server
disk1 T--B server
disk2 T--B db
server T--B gateway
`
);
});
it('should render an architecture diagram with groups within groups', () => {
imgSnapshotTest(
`architecture-beta
group api[API]
group public[Public API] in api
group private[Private API] in api
service serv1(server)[Server] in public
service serv2(server)[Server] in private
service db(database)[Database] in private
service gateway(internet)[Gateway] in api
serv1 B--T serv2
serv2 L--R db
serv1 L--R gateway
`
);
});
it('should render an architecture diagram with the fallback icon', () => {
imgSnapshotTest(
`architecture-beta
service unknown(iconnamedoesntexist)[Unknown Icon]
`
);
});
it('should render an architecture diagram with split directioning', () => {
imgSnapshotTest(
`architecture-beta
service db(database)[Database]
service s3(disk)[Storage]
service serv1(server)[Server 1]
service serv2(server)[Server 2]
service disk(disk)[Disk]
db L--R s3
serv1 L--T s3
serv2 L--B s3
serv1 T--B disk
`
);
});
it('should render an architecture diagram with directional arrows', () => {
imgSnapshotTest(
`architecture-beta
service servC(server)[Server 1]
service servL(server)[Server 2]
service servR(server)[Server 3]
service servT(server)[Server 4]
service servB(server)[Server 5]
servC (L--R) servL
servC (R--L) servR
servC (T--B) servT
servC (B--T) servB
servL (T--L) servT
servL (B--L) servB
servR (T--R) servT
servR (B--R) servB
`
);
});
it('should render an architecture diagram with group edges', () => {
imgSnapshotTest(
`architecture-beta
group left_group(cloud)[Left]
group right_group(cloud)[Right]
group top_group(cloud)[Top]
group bottom_group(cloud)[Bottom]
group center_group(cloud)[Center]
service left_disk(disk)[Disk] in left_group
service right_disk(disk)[Disk] in right_group
service top_disk(disk)[Disk] in top_group
service bottom_disk(disk)[Disk] in bottom_group
service center_disk(disk)[Disk] in center_group
left_disk{group} (R--L) center_disk{group}
right_disk{group} (L--R) center_disk{group}
top_disk{group} (B--T) center_disk{group}
bottom_disk{group} (T--B) center_disk{group}
`
);
});
it('should render an architecture diagram with edge labels', () => {
imgSnapshotTest(
`architecture-beta
service servC(server)[Server 1]
service servL(server)[Server 2]
service servR(server)[Server 3]
service servT(server)[Server 4]
service servB(server)[Server 5]
servC L-[Label]-R servL
servC R-[Label]-L servR
servC T-[Label]-B servT
servC B-[Label]-T servB
servL T-[Label]-L servT
servL B-[Label]-L servB
servR T-[Label]-R servT
servR B-[Label]-R servB
`
);
});
it('should render an architecture diagram with simple junction edges', () => {
imgSnapshotTest(
`architecture-beta
service left_disk(disk)[Disk]
service top_disk(disk)[Disk]
service bottom_disk(disk)[Disk]
service top_gateway(internet)[Gateway]
service bottom_gateway(internet)[Gateway]
junction juncC
junction juncR
left_disk R--L juncC
top_disk B--T juncC
bottom_disk T--B juncC
juncC R--L juncR
top_gateway B--T juncR
bottom_gateway T--B juncR
`
);
});
it('should render an architecture diagram with complex junction edges', () => {
imgSnapshotTest(
`architecture-beta
group left
group right
service left_disk(disk)[Disk] in left
service top_disk(disk)[Disk] in left
service bottom_disk(disk)[Disk] in left
service top_gateway(internet)[Gateway] in right
service bottom_gateway(internet)[Gateway] in right
junction juncC in left
junction juncR in right
left_disk R--L juncC
top_disk B--T juncC
bottom_disk T--B juncC
top_gateway (B--T juncR
bottom_gateway (T--B juncR
juncC{group} R--L) juncR{group}
`
);
});
it('should render an architecture diagram with a resonable height', () => {
imgSnapshotTest(
`architecture-beta
group federated(cloud)[Federated Environment]
service server1(server)[System] in federated
service edge(server)[Edge Device] in federated
server1:R -- L:edge
group on_prem(cloud)[Hub]
service firewall(server)[Firewall Device] in on_prem
service server(server)[Server] in on_prem
firewall:R -- L:server
service db1(database)[db1] in on_prem
service db2(database)[db2] in on_prem
service db3(database)[db3] in on_prem
service db4(database)[db4] in on_prem
service db5(database)[db5] in on_prem
service db6(database)[db6] in on_prem
junction mid in on_prem
server:B -- T:mid
junction 1Leftofmid in on_prem
1Leftofmid:R -- L:mid
1Leftofmid:B -- T:db1
junction 2Leftofmid in on_prem
2Leftofmid:R -- L:1Leftofmid
2Leftofmid:B -- T:db2
junction 3Leftofmid in on_prem
3Leftofmid:R -- L:2Leftofmid
3Leftofmid:B -- T:db3
junction 1RightOfMid in on_prem
mid:R -- L:1RightOfMid
1RightOfMid:B -- T:db4
junction 2RightOfMid in on_prem
1RightOfMid:R -- L:2RightOfMid
2RightOfMid:B -- T:db5
junction 3RightOfMid in on_prem
2RightOfMid:R -- L:3RightOfMid
3RightOfMid:B -- T:db6
edge:R -- L:firewall
`
);
});
});
// Skipped as the layout is not deterministic, and causes issues in E2E tests.
describe.skip('architecture - external', () => {
it('should allow adding external icons', () => {
urlSnapshotTest('http://localhost:9000/architecture-external.html');
});
});

View File

@@ -236,7 +236,7 @@ describe('Block diagram', () => {
);
});
it('BL17: width alignment - blocks shold be equal in width', () => {
it('BL16: width alignment - blocks shold be equal in width', () => {
imgSnapshotTest(
`block-beta
A("This is the text")
@@ -247,7 +247,7 @@ describe('Block diagram', () => {
);
});
it('BL18: block types 1 - square, rounded and circle', () => {
it('BL17: block types 1 - square, rounded and circle', () => {
imgSnapshotTest(
`block-beta
A["square"]
@@ -258,7 +258,7 @@ describe('Block diagram', () => {
);
});
it('BL19: block types 2 - odd, diamond and hexagon', () => {
it('BL18: block types 2 - odd, diamond and hexagon', () => {
imgSnapshotTest(
`block-beta
A>"rect_left_inv_arrow"]
@@ -269,7 +269,7 @@ describe('Block diagram', () => {
);
});
it('BL20: block types 3 - stadium', () => {
it('BL19: block types 3 - stadium', () => {
imgSnapshotTest(
`block-beta
A(["stadium"])
@@ -278,7 +278,7 @@ describe('Block diagram', () => {
);
});
it('BL21: block types 4 - lean right, lean left, trapezoid and inv trapezoid', () => {
it('BL20: block types 4 - lean right, lean left, trapezoid and inv trapezoid', () => {
imgSnapshotTest(
`block-beta
A[/"lean right"/]
@@ -290,7 +290,7 @@ describe('Block diagram', () => {
);
});
it('BL22: block types 1 - square, rounded and circle', () => {
it('BL21: block types 1 - square, rounded and circle', () => {
imgSnapshotTest(
`block-beta
A["square"]
@@ -301,7 +301,7 @@ describe('Block diagram', () => {
);
});
it('BL23: sizing - it should be possible to make a block wider', () => {
it('BL22: sizing - it should be possible to make a block wider', () => {
imgSnapshotTest(
`block-beta
A("rounded"):2
@@ -312,7 +312,7 @@ describe('Block diagram', () => {
);
});
it('BL24: sizing - it should be possible to make a composite block wider', () => {
it('BL23: sizing - it should be possible to make a composite block wider', () => {
imgSnapshotTest(
`block-beta
block:2
@@ -324,7 +324,7 @@ describe('Block diagram', () => {
);
});
it('BL25: block in the middle with space on each side', () => {
it('BL24: block in the middle with space on each side', () => {
imgSnapshotTest(
`block-beta
columns 3
@@ -335,7 +335,7 @@ describe('Block diagram', () => {
{}
);
});
it('BL26: space and an edge', () => {
it('BL25: space and an edge', () => {
imgSnapshotTest(
`block-beta
columns 5
@@ -345,7 +345,7 @@ describe('Block diagram', () => {
{}
);
});
it('BL27: block sizes for regular blocks', () => {
it('BL26: block sizes for regular blocks', () => {
imgSnapshotTest(
`block-beta
columns 3
@@ -354,7 +354,7 @@ describe('Block diagram', () => {
{}
);
});
it('BL28: composite block with a set width - f should use the available space', () => {
it('BL27: composite block with a set width - f should use the available space', () => {
imgSnapshotTest(
`block-beta
columns 3
@@ -363,12 +363,11 @@ describe('Block diagram', () => {
f
end
g
`,
`,
{}
);
});
it('BL29: composite block with a set width - f and g should split the available space', () => {
it('BL23: composite block with a set width - f and g should split the available space', () => {
imgSnapshotTest(
`block-beta
columns 3
@@ -380,7 +379,7 @@ describe('Block diagram', () => {
h
i
j
`,
`,
{}
);
});

View File

@@ -1,7 +1,7 @@
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
describe('C4 diagram', () => {
it('C4.1 should render a simple C4Context diagram', () => {
it('should render a simple C4Context diagram', () => {
imgSnapshotTest(
`
C4Context
@@ -30,8 +30,9 @@ describe('C4 diagram', () => {
`,
{}
);
cy.get('svg');
});
it('C4.2 should render a simple C4Container diagram', () => {
it('should render a simple C4Container diagram', () => {
imgSnapshotTest(
`
C4Container
@@ -49,8 +50,9 @@ describe('C4 diagram', () => {
`,
{}
);
cy.get('svg');
});
it('C4.3 should render a simple C4Component diagram', () => {
it('should render a simple C4Component diagram', () => {
imgSnapshotTest(
`
C4Component
@@ -67,8 +69,9 @@ describe('C4 diagram', () => {
`,
{}
);
cy.get('svg');
});
it('C4.4 should render a simple C4Dynamic diagram', () => {
it('should render a simple C4Dynamic diagram', () => {
imgSnapshotTest(
`
C4Dynamic
@@ -90,8 +93,9 @@ describe('C4 diagram', () => {
`,
{}
);
cy.get('svg');
});
it('C4.5 should render a simple C4Deployment diagram', () => {
it('should render a simple C4Deployment diagram', () => {
imgSnapshotTest(
`
C4Deployment
@@ -113,5 +117,6 @@ describe('C4 diagram', () => {
`,
{}
);
cy.get('svg');
});
});

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -76,7 +76,7 @@ describe('Class diagram V2', () => {
);
});
it('2.1 should render a simple class diagram with different visibilities', () => {
it('should render a simple class diagram with different visibilities', () => {
imgSnapshotTest(
`
classDiagram-v2
@@ -93,7 +93,7 @@ describe('Class diagram V2', () => {
);
});
it('3: should render multiple class diagrams', () => {
it('should render multiple class diagrams', () => {
imgSnapshotTest(
[
`
@@ -581,63 +581,4 @@ class C13["With Città foreign language"]
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
});
it('renders a class diagram with a generic class in a namespace', () => {
const diagramDefinition = `
classDiagram-v2
namespace Company.Project.Module {
class GenericClass~T~ {
+addItem(item: T)
+getItem() T
}
}
`;
imgSnapshotTest(diagramDefinition);
});
it('renders a class diagram with nested namespaces and relationships', () => {
const diagramDefinition = `
classDiagram-v2
namespace Company.Project.Module.SubModule {
class Report {
+generatePDF(data: List)
+generateCSV(data: List)
}
}
namespace Company.Project.Module {
class Admin {
+generateReport()
}
}
Admin --> Report : generates
`;
imgSnapshotTest(diagramDefinition);
});
it('renders a class diagram with multiple classes and relationships in a namespace', () => {
const diagramDefinition = `
classDiagram-v2
namespace Company.Project.Module {
class User {
+login(username: String, password: String)
+logout()
}
class Admin {
+addUser(user: User)
+removeUser(user: User)
+generateReport()
}
class Report {
+generatePDF(reportData: List)
+generateCSV(reportData: List)
}
}
Admin --> User : manages
Admin --> Report : generates
`;
imgSnapshotTest(diagramDefinition);
});
});

File diff suppressed because it is too large Load Diff

View File

@@ -32,6 +32,7 @@ describe('Class diagram', () => {
`,
{ logLevel: 1 }
);
cy.get('svg');
});
it('2: should render a simple class diagrams with cardinality', () => {
@@ -60,6 +61,7 @@ describe('Class diagram', () => {
`,
{}
);
cy.get('svg');
});
it('3: should render a simple class diagram with different visibilities', () => {
@@ -77,6 +79,7 @@ describe('Class diagram', () => {
`,
{}
);
cy.get('svg');
});
it('4: should render a simple class diagram with comments', () => {
@@ -106,6 +109,7 @@ describe('Class diagram', () => {
`,
{}
);
cy.get('svg');
});
it('5: should render a simple class diagram with abstract method', () => {
@@ -117,6 +121,7 @@ describe('Class diagram', () => {
`,
{}
);
cy.get('svg');
});
it('6: should render a simple class diagram with static method', () => {
@@ -128,6 +133,7 @@ describe('Class diagram', () => {
`,
{}
);
cy.get('svg');
});
it('7: should render a simple class diagram with Generic class', () => {
@@ -147,6 +153,7 @@ describe('Class diagram', () => {
`,
{}
);
cy.get('svg');
});
it('8: should render a simple class diagram with Generic class and relations', () => {
@@ -167,6 +174,7 @@ describe('Class diagram', () => {
`,
{}
);
cy.get('svg');
});
it('9: should render a simple class diagram with clickable link', () => {
@@ -188,6 +196,7 @@ describe('Class diagram', () => {
`,
{}
);
cy.get('svg');
});
it('10: should render a simple class diagram with clickable callback', () => {
@@ -209,6 +218,7 @@ describe('Class diagram', () => {
`,
{}
);
cy.get('svg');
});
it('11: should render a simple class diagram with return type on method', () => {
@@ -223,6 +233,7 @@ describe('Class diagram', () => {
`,
{}
);
cy.get('svg');
});
it('12: should render a simple class diagram with generic types', () => {
@@ -238,6 +249,7 @@ describe('Class diagram', () => {
`,
{}
);
cy.get('svg');
});
it('13: should render a simple class diagram with css classes applied', () => {
@@ -255,6 +267,7 @@ describe('Class diagram', () => {
`,
{}
);
cy.get('svg');
});
it('14: should render a simple class diagram with css classes applied directly', () => {
@@ -270,6 +283,7 @@ describe('Class diagram', () => {
`,
{}
);
cy.get('svg');
});
it('15: should render a simple class diagram with css classes applied to multiple classes', () => {
@@ -284,6 +298,7 @@ describe('Class diagram', () => {
`,
{}
);
cy.get('svg');
});
it('16: should render multiple class diagrams', () => {
@@ -336,6 +351,7 @@ describe('Class diagram', () => {
],
{}
);
cy.get('svg');
});
// it('17: should render a class diagram when useMaxWidth is true (default)', () => {
@@ -405,6 +421,7 @@ describe('Class diagram', () => {
`,
{ logLevel: 1 }
);
cy.get('svg');
});
it('should render class diagram with newlines in title', () => {
@@ -422,6 +439,7 @@ describe('Class diagram', () => {
+quack()
}
`);
cy.get('svg');
});
it('should render class diagram with many newlines in title', () => {

View File

@@ -218,6 +218,7 @@ describe('Entity Relationship Diagram', () => {
`,
{ loglevel: 1 }
);
cy.get('svg');
});
it('should render entities with keys', () => {
@@ -321,37 +322,4 @@ ORDER ||--|{ LINE-ITEM : contains
{ logLevel: 1 }
);
});
it('should render relationship labels with line breaks', () => {
imgSnapshotTest(
`
erDiagram
p[Person] {
string firstName
string lastName
}
a["Customer Account"] {
string email
}
b["Customer Account Secondary"] {
string email
}
c["Customer Account Tertiary"] {
string email
}
d["Customer Account Nth"] {
string email
}
p ||--o| a : "has<br />one"
p ||--o| b : "has<br />one<br />two"
p ||--o| c : "has<br />one<br/>two<br />three"
p ||--o| d : "has<br />one<br />two<br/>three<br />...<br/>Nth"
`,
{ logLevel: 1 }
);
});
});

View File

@@ -3,7 +3,7 @@ import { imgSnapshotTest } from '../../helpers/util';
describe('Error Diagrams', () => {
beforeEach(() => {
cy.on('uncaught:exception', (err) => {
expect(err.message).to.include('error');
expect(err.message).to.include('Parse error');
// return false to prevent the error from
// failing this test
return false;

View File

@@ -1,6 +1,6 @@
import { imgSnapshotTest, renderGraph, verifyNumber } from '../../helpers/util.ts';
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
describe('Flowchart ELK', () => {
describe.skip('Flowchart ELK', () => {
it('1-elk: should render a simple flowchart', () => {
imgSnapshotTest(
`flowchart-elk TD
@@ -109,7 +109,7 @@ describe('Flowchart ELK', () => {
const style = svg.attr('style');
expect(style).to.match(/^max-width: [\d.]+px;$/);
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
verifyNumber(maxWidthValue, 380);
expect(maxWidthValue).to.be.within(230 * 0.95, 230 * 1.05);
});
});
it('8-elk: should render a flowchart when useMaxWidth is false', () => {
@@ -128,7 +128,7 @@ describe('Flowchart ELK', () => {
const width = parseFloat(svg.attr('width'));
// use within because the absolute value can be slightly different depending on the environment ±5%
// expect(height).to.be.within(446 * 0.95, 446 * 1.05);
verifyNumber(width, 380);
expect(width).to.be.within(230 * 0.95, 230 * 1.05);
expect(svg).to.not.have.attr('style');
});
});
@@ -692,7 +692,7 @@ A --> B
{}
);
cy.get('svg').should((svg) => {
const edges = svg[0].querySelectorAll('.edges > path');
const edges = svg.querySelectorAll('.edges > path');
edges.forEach((edge) => {
expect(edge).to.have.class('flowchart-link');
});
@@ -739,7 +739,7 @@ NL\`") --"\`1o **bold**\`"--> c
{ flowchart: { titleTopMargin: 0 } }
);
});
it.skip('Wrapping long text with a new line', () => {
it('Wrapping long text with a new line', () => {
imgSnapshotTest(
`%%{init: {"flowchart": {"htmlLabels": true}} }%%
flowchart-elk LR
@@ -837,216 +837,6 @@ subgraph "\`**Two**\`"
in the hat\`") -- "\`1o **ipa**\`" --> d("The dog in the hog")
end
`,
{ flowchart: { titleTopMargin: 0 } }
);
});
it('Sub graphs and markdown strings', () => {
imgSnapshotTest(
`---
config:
layout: elk
---
flowchart LR
subgraph subgraph_ko6czgs5u["Untitled subgraph"]
D["Option 1"]
end
C{"Evaluate"} -- One --> D
C -- Two --> E(("Option 2"))
D --> E
A["A"]
`,
{ flowchart: { titleTopMargin: 0 } }
);
});
it('6080: should handle diamond shape intersections', () => {
imgSnapshotTest(
`---
config:
layout: elk
---
flowchart LR
subgraph s1["Untitled subgraph"]
n1["Evaluate"]
n2["Option 1"]
n3["Option 2"]
n4["fa:fa-car Option 3"]
end
subgraph s2["Untitled subgraph"]
n5["Evaluate"]
n6["Option 1"]
n7["Option 2"]
n8["fa:fa-car Option 3"]
end
A["Start"] -- Some text --> B("Continue")
B --> C{"Evaluate"}
C -- One --> D["Option 1"]
C -- Two --> E["Option 2"]
C -- Three --> F["fa:fa-car Option 3"]
n1 -- One --> n2
n1 -- Two --> n3
n1 -- Three --> n4
n5 -- One --> n6
n5 -- Two --> n7
n5 -- Three --> n8
n1@{ shape: diam}
n2@{ shape: rect}
n3@{ shape: rect}
n4@{ shape: rect}
n5@{ shape: diam}
n6@{ shape: rect}
n7@{ shape: rect}
n8@{ shape: rect}
`,
{ flowchart: { titleTopMargin: 0 } }
);
});
it('6088-1: should handle diamond shape intersections', () => {
imgSnapshotTest(
`---
config:
layout: elk
---
flowchart LR
subgraph S2
subgraph s1["APA"]
D{"Use the editor"}
end
D -- Mermaid js --> I{"fa:fa-code Text"}
D --> I
D --> I
end
`,
{ flowchart: { titleTopMargin: 0 } }
);
});
it('6088-2: should handle diamond shape intersections', () => {
imgSnapshotTest(
`---
config:
layout: elk
---
flowchart LR
a
subgraph s0["APA"]
subgraph s8["APA"]
subgraph s1["APA"]
D{"X"}
E[Q]
end
subgraph s3["BAPA"]
F[Q]
I
end
D --> I
D --> I
D --> I
I{"X"}
end
end
`,
{ flowchart: { titleTopMargin: 0 } }
);
});
it('6088-3: should handle diamond shape intersections', () => {
imgSnapshotTest(
`---
config:
layout: elk
---
flowchart LR
a
D{"Use the editor"}
D -- Mermaid js --> I{"fa:fa-code Text"}
D-->I
D-->I
`,
{ flowchart: { titleTopMargin: 0 } }
);
});
it('6088-4: should handle diamond shape intersections', () => {
imgSnapshotTest(
`---
config:
layout: elk
---
flowchart LR
subgraph s1["Untitled subgraph"]
n1["Evaluate"]
n2["Option 1"]
n3["Option 2"]
n4["fa:fa-car Option 3"]
end
subgraph s2["Untitled subgraph"]
n5["Evaluate"]
n6["Option 1"]
n7["Option 2"]
n8["fa:fa-car Option 3"]
end
A["Start"] -- Some text --> B("Continue")
B --> C{"Evaluate"}
C -- One --> D["Option 1"]
C -- Two --> E["Option 2"]
C -- Three --> F["fa:fa-car Option 3"]
n1 -- One --> n2
n1 -- Two --> n3
n1 -- Three --> n4
n5 -- One --> n6
n5 -- Two --> n7
n5 -- Three --> n8
n1@{ shape: diam}
n2@{ shape: rect}
n3@{ shape: rect}
n4@{ shape: rect}
n5@{ shape: diam}
n6@{ shape: rect}
n7@{ shape: rect}
n8@{ shape: rect}
`,
{ flowchart: { titleTopMargin: 0 } }
);
});
it('6088-5: should handle diamond shape intersections', () => {
imgSnapshotTest(
`---
config:
layout: elk
---
flowchart LR
A{A} --> B & C
`,
{ flowchart: { titleTopMargin: 0 } }
);
});
it('6088-6: should handle diamond shape intersections', () => {
imgSnapshotTest(
`---
config:
layout: elk
---
flowchart LR
A{A} --> B & C
subgraph "subbe"
A
end
`,
{ flowchart: { titleTopMargin: 0 } }
);
@@ -1065,7 +855,7 @@ describe('Title and arrow styling #4813', () => {
flowchart LR
A-->B
A-->C`,
{ layout: 'elk' }
{ flowchart: { defaultRenderer: 'elk' } }
);
cy.get('svg').should((svg) => {
const title = svg[0].querySelector('text');
@@ -1081,14 +871,15 @@ describe('Title and arrow styling #4813', () => {
B-.-oC
C==xD
D ~~~ A`,
{ layout: 'elk' }
{ flowchart: { defaultRenderer: 'elk' } }
);
cy.get('svg').should((svg) => {
const edges = svg[0].querySelectorAll('.edges path');
expect(edges[0].getAttribute('class')).to.contain('edge-pattern-solid');
expect(edges[1].getAttribute('class')).to.contain('edge-pattern-dotted');
expect(edges[2].getAttribute('class')).to.contain('edge-thickness-thick');
expect(edges[3].getAttribute('class')).to.contain('edge-thickness-invisible');
console.log(edges);
expect(edges[0]).to.have.attr('pattern', 'solid');
expect(edges[1]).to.have.attr('pattern', 'dotted');
expect(edges[2]).to.have.css('stroke-width', '3.5px');
expect(edges[3]).to.have.css('stroke-width', '1.5px');
});
});
});

File diff suppressed because it is too large Load Diff

View File

@@ -1,142 +0,0 @@
import { imgSnapshotTest } from '../../helpers/util.ts';
const aliasSet1 = ['process', 'rect', 'proc', 'rectangle'] as const;
const aliasSet2 = ['event', 'rounded'] as const;
const aliasSet3 = ['stadium', 'pill', 'terminal'] as const;
const aliasSet4 = ['fr-rect', 'subproc', 'subprocess', 'framed-rectangle', 'subroutine'] as const;
const aliasSet5 = ['db', 'database', 'cylinder', 'cyl'] as const;
const aliasSet6 = ['diam', 'decision', 'diamond'] as const;
const aliasSet7 = ['hex', 'hexagon', 'prepare'] as const;
const aliasSet8 = ['lean-r', 'lean-right', 'in-out'] as const;
const aliasSet9 = ['lean-l', 'lean-left', 'out-in'] as const;
const aliasSet10 = ['trap-b', 'trapezoid-bottom', 'priority'] as const;
const aliasSet11 = ['trap-t', 'trapezoid-top', 'manual'] as const;
const aliasSet12 = ['dbl-circ', 'double-circle'] as const;
const aliasSet13 = ['notched-rectangle', 'card', 'notch-rect'] as const;
const aliasSet14 = [
'lin-rect',
'lined-rectangle',
'lin-proc',
'lined-process',
'shaded-process',
] as const;
const aliasSet15 = ['sm-circ', 'small-circle', 'start'] as const;
const aliasSet16 = ['fr-circ', 'framed-circle', 'stop'] as const;
const aliasSet17 = ['fork', 'join'] as const;
// brace-r', 'braces'
const aliasSet18 = ['comment', 'brace-l'] as const;
const aliasSet19 = ['bolt', 'com-link', 'lightning-bolt'] as const;
const aliasSet20 = ['doc', 'document'] as const;
const aliasSet21 = ['delay', 'half-rounded-rectangle'] as const;
const aliasSet22 = ['h-cyl', 'das', 'horizontal-cylinder'] as const;
const aliasSet23 = ['lin-cyl', 'disk', 'lined-cylinder'] as const;
const aliasSet24 = ['curv-trap', 'display', 'curved-trapezoid'] as const;
const aliasSet25 = ['div-rect', 'div-proc', 'divided-rectangle', 'divided-process'] as const;
const aliasSet26 = ['extract', 'tri', 'triangle'] as const;
const aliasSet27 = ['win-pane', 'internal-storage', 'window-pane'] as const;
const aliasSet28 = ['f-circ', 'junction', 'filled-circle'] as const;
const aliasSet29 = ['lin-doc', 'lined-document'] as const;
const aliasSet30 = ['notch-pent', 'loop-limit', 'notched-pentagon'] as const;
const aliasSet31 = ['flip-tri', 'manual-file', 'flipped-triangle'] as const;
const aliasSet32 = ['sl-rect', 'manual-input', 'sloped-rectangle'] as const;
const aliasSet33 = ['docs', 'documents', 'st-doc', 'stacked-document'] as const;
const aliasSet34 = ['procs', 'processes', 'st-rect', 'stacked-rectangle'] as const;
const aliasSet35 = ['flag', 'paper-tape'] as const;
const aliasSet36 = ['bow-rect', 'stored-data', 'bow-tie-rectangle'] as const;
const aliasSet37 = ['cross-circ', 'summary', 'crossed-circle'] as const;
const aliasSet38 = ['tag-doc', 'tagged-document'] as const;
const aliasSet39 = ['tag-rect', 'tag-proc', 'tagged-rectangle', 'tagged-process'] as const;
const aliasSet40 = ['collate', 'hourglass'] as const;
// Aggregate all alias sets into a single array
const aliasSets = [
aliasSet1,
aliasSet2,
aliasSet3,
aliasSet4,
aliasSet5,
aliasSet6,
aliasSet7,
aliasSet8,
aliasSet9,
aliasSet10,
aliasSet11,
aliasSet12,
aliasSet13,
aliasSet14,
aliasSet15,
aliasSet16,
aliasSet17,
aliasSet18,
aliasSet19,
aliasSet20,
aliasSet21,
aliasSet22,
aliasSet23,
aliasSet24,
aliasSet25,
aliasSet26,
aliasSet27,
aliasSet28,
aliasSet29,
aliasSet30,
aliasSet31,
aliasSet32,
aliasSet33,
aliasSet34,
aliasSet35,
aliasSet36,
aliasSet37,
aliasSet38,
aliasSet39,
] as const;
aliasSets.forEach((aliasSet) => {
describe(`Test ${aliasSet.join(',')} `, () => {
it(`All ${aliasSet.join(',')} should render same shape`, () => {
let flowchartCode = `flowchart \n`;
aliasSet.forEach((alias, index) => {
flowchartCode += ` n${index}@{ shape: ${alias}, label: "${alias}" }\n`;
});
imgSnapshotTest(flowchartCode);
});
});
});

View File

@@ -99,7 +99,7 @@ describe('Flowchart v2', () => {
const style = svg.attr('style');
expect(style).to.match(/^max-width: [\d.]+px;$/);
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
expect(maxWidthValue).to.be.within(417 * 0.95, 417 * 1.05);
expect(maxWidthValue).to.be.within(290 * 0.95 - 1, 290 * 1.05);
});
});
it('8: should render a flowchart when useMaxWidth is false', () => {
@@ -118,7 +118,7 @@ describe('Flowchart v2', () => {
const width = parseFloat(svg.attr('width'));
// use within because the absolute value can be slightly different depending on the environment ±5%
// expect(height).to.be.within(446 * 0.95, 446 * 1.05);
expect(width).to.be.within(417 * 0.95, 417 * 1.05);
expect(width).to.be.within(290 * 0.95 - 1, 290 * 1.05);
expect(svg).to.not.have.attr('style');
});
});
@@ -786,7 +786,7 @@ A ~~~ B
`---
title: Subgraph nodeSpacing and rankSpacing example
config:
flowchart:
flowchart:
nodeSpacing: 250
rankSpacing: 250
---
@@ -1047,69 +1047,7 @@ end
A --lb3--> TOP --lb4--> B
B1 --lb5--> B2
`,
{
flowchart: { subGraphTitleMargin: { top: 10, bottom: 5 } },
}
);
});
it('Should render self-loops', () => {
imgSnapshotTest(
`flowchart
A --> A
subgraph B
B1 --> B1
end
subgraph C
subgraph C1
C2 --> C2
subgraph D
D1 --> D1
end
D --> D
end
C1 --> C1
end
`,
{
flowchart: { subGraphTitleMargin: { top: 10, bottom: 5 } },
}
);
});
});
describe('New @ sytax for node metadata edge cases', () => {
it('should be possible to use @ syntax to add labels on multi nodes', () => {
imgSnapshotTest(
`flowchart TB
n2["label for n2"] & n4@{ label: "labe for n4"} & n5@{ label: "labe for n5"}
`,
{}
);
});
it('should be possible to use @ syntax to add labels with trail spaces and &', () => {
imgSnapshotTest(
`flowchart TB
n2["label for n2"] & n4@{ label: "labe for n4"} & n5@{ label: "labe for n5"}
`,
{}
);
});
it('should be possible to use @ syntax to add labels with trail spaces', () => {
imgSnapshotTest(
`flowchart TB
n2["label for n2"]
n4@{ label: "labe for n4"}
n5@{ label: "labe for n5"}
`,
{}
);
});
it('should be possible to use @ syntax to add labels with trail spaces and edge/link', () => {
imgSnapshotTest(
`flowchart TD
A["A"] --> B["for B"] & C@{ label: "for c"} & E@{label : "for E"}
D@{label: "for D"}
`,
{}
{ flowchart: { subGraphTitleMargin: { top: 10, bottom: 5 } } }
);
});
});

View File

@@ -7,7 +7,7 @@ describe('Graph', () => {
A[Christmas] -->|Get money| B(Go shopping)
B --> C{Let me think}
C -->|One| D[Laptop]
C -->|Two| E[iPad]
C -->|Two| E[iPhone]
C -->|Three| F[fa:fa-car Car]
`,
{ flowchart: { htmlLabels: false }, fontFamily: 'courier' }
@@ -733,7 +733,7 @@ describe('Graph', () => {
});
it('38: should render a flowchart when useMaxWidth is true (default)', () => {
renderGraph(
`flowchart TD
`graph TD
A[Christmas] -->|Get money| B(Go shopping)
B --> C{Let me think}
C -->|One| D[Laptop]
@@ -751,7 +751,7 @@ describe('Graph', () => {
const style = svg.attr('style');
expect(style).to.match(/^max-width: [\d.]+px;$/);
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
expect(maxWidthValue).to.be.within(446 * 0.9, 446 * 1.1);
expect(maxWidthValue).to.be.within(300 * 0.9, 300 * 1.1);
});
});
it('39: should render a flowchart when useMaxWidth is false', () => {
@@ -770,7 +770,7 @@ describe('Graph', () => {
const width = parseFloat(svg.attr('width'));
// use within because the absolute value can be slightly different depending on the environment ±10%
// expect(height).to.be.within(446 * 0.95, 446 * 1.05);
expect(width).to.be.within(446 * 0.9, 446 * 1.1);
expect(width).to.be.within(300 * 0.9, 300 * 1.1);
expect(svg).to.not.have.attr('style');
});
});
@@ -905,16 +905,13 @@ graph TD
it('67: should be able to style default node independently', () => {
imgSnapshotTest(
`
flowchart TD
flowchart TD
classDef default fill:#a34
hello --> default
style default stroke:#000,stroke-width:4px
`,
{
flowchart: { htmlLabels: true },
securityLevel: 'loose',
}
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
});

View File

@@ -1532,41 +1532,5 @@ gitGraph TB:
{}
);
});
it('75: should render a gitGraph with multiple tags on a merge commit on bottom-to-top orientation', () => {
imgSnapshotTest(
`gitGraph BT:
commit id: "ZERO"
branch develop
commit id:"A"
checkout main
commit id:"ONE"
checkout develop
commit id:"B"
checkout main
merge develop id:"Release 1.0" type:HIGHLIGHT tag: "SAML v2.0" tag: "OpenID v1.1"
commit id:"TWO"
checkout develop
commit id:"C"`,
{}
);
});
});
it('76: should render a gitGraph with multiple tags on a merge commit on left-to-right orientation', () => {
imgSnapshotTest(
`gitGraph
commit id: "ZERO"
branch develop
commit id:"A"
checkout main
commit id:"ONE"
checkout develop
commit id:"B"
checkout main
merge develop id:"Release 1.0" type:HIGHLIGHT tag: "SAML v2.0" tag: "OpenID v1.1"
commit id:"TWO"
checkout develop
commit id:"C"`,
{}
);
});
});

View File

@@ -1,143 +0,0 @@
import { imgSnapshotTest } from '../../helpers/util';
const looks = ['classic', 'handDrawn'] as const;
const directions = [
'TB',
//'BT',
'LR',
// 'RL'
] as const;
const forms = [undefined, 'square', 'circle', 'rounded'] as const;
const labelPos = [undefined, 't', 'b'] as const;
looks.forEach((look) => {
directions.forEach((direction) => {
forms.forEach((form) => {
labelPos.forEach((pos) => {
describe(`Test iconShape in ${form ? `${form} form,` : ''} ${look} look and dir ${direction} with label position ${pos ? pos : 'not defined'}`, () => {
it(`without label`, () => {
let flowchartCode = `flowchart ${direction}\n`;
flowchartCode += ` nA --> nAA@{ icon: 'fa:bell'`;
if (form) {
flowchartCode += `, form: '${form}'`;
}
flowchartCode += ` }\n`;
imgSnapshotTest(flowchartCode, { look });
});
it(`with label`, () => {
let flowchartCode = `flowchart ${direction}\n`;
flowchartCode += ` nA --> nAA@{ icon: 'fa:bell', label: 'This is a label for icon shape'`;
if (form) {
flowchartCode += `, form: '${form}'`;
}
if (pos) {
flowchartCode += `, pos: '${pos}'`;
}
flowchartCode += ` }\n`;
imgSnapshotTest(flowchartCode, { look });
});
it(`with very long label`, () => {
let flowchartCode = `flowchart ${direction}\n`;
flowchartCode += ` nA --> nAA@{ icon: 'fa:bell', label: 'This is a very very very very very long long long label for icon shape'`;
if (form) {
flowchartCode += `, form: '${form}'`;
}
if (pos) {
flowchartCode += `, pos: '${pos}'`;
}
flowchartCode += ` }\n`;
imgSnapshotTest(flowchartCode, { look });
});
it(`with markdown htmlLabels:true`, () => {
let flowchartCode = `flowchart ${direction}\n`;
flowchartCode += ` nA --> nAA@{ icon: 'fa:bell', label: 'This is **bold** </br>and <strong>strong</strong> for icon shape'`;
if (form) {
flowchartCode += `, form: '${form}'`;
}
if (pos) {
flowchartCode += `, pos: '${pos}'`;
}
flowchartCode += ` }\n`;
imgSnapshotTest(flowchartCode, { look });
});
it(`with markdown htmlLabels:false`, () => {
let flowchartCode = `flowchart ${direction}\n`;
flowchartCode += ` nA --> nAA@{ icon: 'fa:bell', label: 'This is **bold** </br>and <strong>strong</strong> for icon shape'`;
if (form) {
flowchartCode += `, form: '${form}'`;
}
if (pos) {
flowchartCode += `, pos: '${pos}'`;
}
flowchartCode += ` }\n`;
imgSnapshotTest(flowchartCode, {
look,
htmlLabels: false,
flowchart: { htmlLabels: false },
});
});
it(`with styles`, () => {
let flowchartCode = `flowchart ${direction}\n`;
flowchartCode += ` nA --> nAA@{ icon: 'fa:bell', label: 'new icon shape'`;
if (form) {
flowchartCode += `, form: '${form}'`;
}
if (pos) {
flowchartCode += `, pos: '${pos}'`;
}
flowchartCode += ` }\n`;
flowchartCode += ` style nAA fill:#f9f,stroke:#333,stroke-width:4px \n`;
imgSnapshotTest(flowchartCode, { look });
});
it(`with classDef`, () => {
let flowchartCode = `flowchart ${direction}\n`;
flowchartCode += ` classDef customClazz fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5\n`;
flowchartCode += ` nA --> nAA@{ icon: 'fa:bell', label: 'new icon shape'`;
if (form) {
flowchartCode += `, form: '${form}'`;
}
if (pos) {
flowchartCode += `, pos: '${pos}'`;
}
flowchartCode += ` }\n`;
flowchartCode += ` nAA:::customClazz\n`;
imgSnapshotTest(flowchartCode, { look });
});
});
});
});
});
});
describe('Test iconShape with different h', () => {
it('with different h', () => {
let flowchartCode = `flowchart TB\n`;
const icon = 'fa:bell';
const iconHeight = 64;
flowchartCode += ` nA --> nAA@{ icon: '${icon}', label: 'icon with different h', h: ${iconHeight} }\n`;
imgSnapshotTest(flowchartCode);
});
});
describe('Test colored iconShape', () => {
it('with no styles', () => {
let flowchartCode = `flowchart TB\n`;
const icon = 'fluent-emoji:tropical-fish';
flowchartCode += ` nA --> nAA@{ icon: '${icon}', form: 'square', label: 'icon with color' }\n`;
imgSnapshotTest(flowchartCode);
});
it('with styles', () => {
let flowchartCode = `flowchart TB\n`;
const icon = 'fluent-emoji:tropical-fish';
flowchartCode += ` nA --> nAA@{ icon: '${icon}', form: 'square', label: 'icon with color' }\n`;
flowchartCode += ` style nAA fill:#f9f,stroke:#333,stroke-width:4px \n`;
imgSnapshotTest(flowchartCode);
});
});

View File

@@ -1,103 +0,0 @@
import { imgSnapshotTest } from '../../helpers/util';
const looks = ['classic', 'handDrawn'] as const;
const directions = [
'TB',
//'BT',
'LR',
// 'RL'
] as const;
const labelPos = [undefined, 't', 'b'] as const;
looks.forEach((look) => {
directions.forEach((direction) => {
labelPos.forEach((pos) => {
describe(`Test imageShape in ${look} look and dir ${direction} with label position ${pos ? pos : 'not defined'}`, () => {
it(`without label`, () => {
let flowchartCode = `flowchart ${direction}\n`;
flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', w: '100', h: '100' }\n`;
imgSnapshotTest(flowchartCode, { look });
});
it(`with label`, () => {
let flowchartCode = `flowchart ${direction}\n`;
flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'This is a label for image shape'`;
flowchartCode += `, w: '100', h: '200'`;
if (pos) {
flowchartCode += `, pos: '${pos}'`;
}
flowchartCode += ` }\n`;
imgSnapshotTest(flowchartCode, { look });
});
it(`with very long label`, () => {
let flowchartCode = `flowchart ${direction}\n`;
flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'This is a very very very very very long long long label for image shape'`;
flowchartCode += `, w: '100', h: '250'`;
if (pos) {
flowchartCode += `, pos: '${pos}'`;
}
flowchartCode += ` }\n`;
imgSnapshotTest(flowchartCode, { look });
});
it(`with markdown htmlLabels:true`, () => {
let flowchartCode = `flowchart ${direction}\n`;
flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'This is **bold** </br>and <strong>strong</strong> for image shape'`;
flowchartCode += `, w: '550', h: '200'`;
if (pos) {
flowchartCode += `, pos: '${pos}'`;
}
flowchartCode += ` }\n`;
imgSnapshotTest(flowchartCode, { look, htmlLabels: true });
});
it(`with markdown htmlLabels:false`, () => {
let flowchartCode = `flowchart ${direction}\n`;
flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'This is **bold** </br>and <strong>strong</strong> for image shape'`;
flowchartCode += `, w: '250', h: '200'`;
if (pos) {
flowchartCode += `, pos: '${pos}'`;
}
flowchartCode += ` }\n`;
imgSnapshotTest(flowchartCode, {
look,
htmlLabels: false,
flowchart: { htmlLabels: false },
});
});
it(`with styles`, () => {
let flowchartCode = `flowchart ${direction}\n`;
flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'new image shape'`;
flowchartCode += `, w: '550', h: '200'`;
if (pos) {
flowchartCode += `, pos: '${pos}'`;
}
flowchartCode += ` }\n`;
flowchartCode += ` style A fill:#f9f,stroke:#333,stroke-width:4px \n`;
imgSnapshotTest(flowchartCode, { look });
});
it(`with classDef`, () => {
let flowchartCode = `flowchart ${direction}\n`;
flowchartCode += ` classDef customClazz fill:#bbf,stroke:#f66,stroke-width:2px,color:#000000,stroke-dasharray: 5 5\n`;
flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'new image shape'`;
flowchartCode += `, w: '500', h: '550'`;
if (pos) {
flowchartCode += `, pos: '${pos}'`;
}
flowchartCode += ` }\n`;
flowchartCode += ` A:::customClazz\n`;
imgSnapshotTest(flowchartCode, { look });
});
});
});
});
});

View File

@@ -1,136 +0,0 @@
import { imgSnapshotTest } from '../../helpers/util.ts';
describe('Kanban diagram', () => {
it('1: should render a kanban with a single section', () => {
imgSnapshotTest(
`kanban
id1[Todo]
docs[Create Documentation]
docs[Create Blog about the new diagram]
`,
{}
);
});
it('2: should render a kanban with multiple sections', () => {
imgSnapshotTest(
`kanban
id1[Todo]
docs[Create Documentation]
id2
docs[Create Blog about the new diagram]
`,
{}
);
});
it('3: should render a kanban with a single wrapping node', () => {
imgSnapshotTest(
`kanban
id1[Todo]
id2[Title of diagram is more than 100 chars when user duplicates diagram with 100 char, wrapping]
`,
{}
);
});
it('4: should handle the height of a section with a wrapping node at the end', () => {
imgSnapshotTest(
`kanban
id1[Todo]
id2[One line]
id3[Title of diagram is more than 100 chars when user duplicates diagram with 100 char, wrapping]
`,
{}
);
});
it('5: should handle the height of a section with a wrapping node at the top', () => {
imgSnapshotTest(
`kanban
id1[Todo]
id2[Title of diagram is more than 100 chars when user duplicates diagram with 100 char, wrapping]
id3[One line]
`,
{}
);
});
it('6: should handle the height of a section with a wrapping node in the middle', () => {
imgSnapshotTest(
`kanban
id1[Todo]
id2[One line]
id3[Title of diagram is more than 100 chars when user duplicates diagram with 100 char, wrapping]
id4[One line]
`,
{}
);
});
it('6: should handle assigments', () => {
imgSnapshotTest(
`kanban
id1[Todo]
docs[Create Documentation]
id2[In progress]
docs[Create Blog about the new diagram]@{ assigned: 'knsv' }
`,
{}
);
});
it('7: should handle prioritization', () => {
imgSnapshotTest(
`kanban
id2[In progress]
vh[Very High]@{ priority: 'Very High' }
h[High]@{ priority: 'High' }
m[Default priority]
l[Low]@{ priority: 'Low' }
vl[Very Low]@{ priority: 'Very Low' }
`,
{}
);
});
it('7: should handle external tickets', () => {
imgSnapshotTest(
`kanban
id1[Todo]
docs[Create Documentation]
id2[In progress]
docs[Create Blog about the new diagram]@{ ticket: MC-2037 }
`,
{}
);
});
it('8: should handle assignments, prioritization and tickets ids in the same item', () => {
imgSnapshotTest(
`kanban
id2[In progress]
docs[Create Blog about the new diagram]@{ priority: 'Very Low', ticket: MC-2037, assigned: 'knsv' }
`,
{}
);
});
it('10: Full example', () => {
imgSnapshotTest(
`---
config:
kanban:
ticketBaseUrl: 'https://abc123.atlassian.net/browse/#TICKET#'
---
kanban
id1[Todo]
docs[Create Documentation]
docs[Create Blog about the new diagram]
id7[In progress]
id6[Create renderer so that it works in all cases. We also add som extra text here for testing purposes. And some more just for the extra flare.]
id8[Design grammar]@{ assigned: 'knsv' }
id9[Ready for deploy]
id10[Ready for test]
id11[Done]
id5[define getData]
id2[Title of diagram is more than 100 chars when user duplicates diagram with 100 char]@{ ticket: MC-2036, priority: 'Very High'}
id3[Update DB function]@{ ticket: MC-2037, assigned: knsv, priority: 'High' }
id4[Create parsing tests]@{ ticket: MC-2038, assigned: 'K.Sveidqvist', priority: 'High' }
id66[last item]@{ priority: 'Very Low', assigned: 'knsv' }
id12[Can't reproduce]
`,
{}
);
});
});

View File

@@ -1,146 +0,0 @@
import { imgSnapshotTest } from '../../helpers/util.ts';
const looks = ['classic', 'handDrawn'] as const;
const directions = [
'TB',
//'BT',
'LR',
//'RL'
] as const;
const newShapesSet1 = [
'triangle',
'sloped-rectangle',
'horizontal-cylinder',
'flipped-triangle',
'hourglass',
] as const;
const newShapesSet2 = [
'tagged-rectangle',
'documents',
'lightning-bolt',
'filled-circle',
'window-pane',
] as const;
const newShapesSet3 = [
'curved-trapezoid',
'bow-rect',
'tagged-document',
'divided-rectangle',
'crossed-circle',
] as const;
const newShapesSet4 = [
'document',
'notched-pentagon',
'lined-cylinder',
'stacked-document',
'half-rounded-rectangle',
] as const;
const newShapesSet5 = [
'lined-document',
'tagged-document',
'brace-l',
'comment',
'braces',
'brace-r',
] as const;
const newShapesSet6 = ['brace-r', 'braces'] as const;
// Aggregate all shape sets into a single array
const newShapesSets = [
newShapesSet1,
newShapesSet2,
newShapesSet3,
newShapesSet4,
newShapesSet5,
newShapesSet6,
];
looks.forEach((look) => {
directions.forEach((direction) => {
newShapesSets.forEach((newShapesSet) => {
describe(`Test ${newShapesSet.join(', ')} in ${look} look and dir ${direction}`, () => {
it(`without label`, () => {
let flowchartCode = `flowchart ${direction}\n`;
newShapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape} }\n`;
});
imgSnapshotTest(flowchartCode, { look });
});
it(`with label`, () => {
let flowchartCode = `flowchart ${direction}\n`;
newShapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'This is a label for ${newShape} shape' }\n`;
});
imgSnapshotTest(flowchartCode, { look });
});
it(`connect all shapes with each other`, () => {
let flowchartCode = `flowchart ${direction}\n`;
newShapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index}${index}@{ shape: ${newShape}, label: 'This is a label for ${newShape} shape' }\n`;
});
for (let i = 0; i < newShapesSet.length; i++) {
for (let j = i + 1; j < newShapesSet.length; j++) {
flowchartCode += ` n${i}${i} --> n${j}${j}\n`;
}
}
if (!(direction === 'TB' && look === 'handDrawn' && newShapesSet === newShapesSet1)) {
//skip this test, works in real. Need to look
imgSnapshotTest(flowchartCode, { look });
}
});
it(`with very long label`, () => {
let flowchartCode = `flowchart ${direction}\n`;
newShapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'This is a very very very very very long long long label for ${newShape} shape' }\n`;
});
imgSnapshotTest(flowchartCode, { look });
});
it(`with markdown htmlLabels:true`, () => {
let flowchartCode = `flowchart ${direction}\n`;
newShapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'This is **bold** </br>and <strong>strong</strong> for ${newShape} shape' }\n`;
});
imgSnapshotTest(flowchartCode, { look });
});
it(`with markdown htmlLabels:false`, () => {
let flowchartCode = `flowchart ${direction}\n`;
newShapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'This is **bold** </br>and <strong>strong</strong> for ${newShape} shape' }\n`;
});
imgSnapshotTest(flowchartCode, {
look,
htmlLabels: false,
flowchart: { htmlLabels: false },
});
});
it(`with styles`, () => {
let flowchartCode = `flowchart ${direction}\n`;
newShapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'new ${newShape} shape' }\n`;
flowchartCode += ` style n${index}${index} fill:#f9f,stroke:#333,stroke-width:4px \n`;
});
imgSnapshotTest(flowchartCode, { look });
});
it(`with classDef`, () => {
let flowchartCode = `flowchart ${direction}\n`;
flowchartCode += ` classDef customClazz fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5\n`;
newShapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'new ${newShape} shape' }\n`;
flowchartCode += ` n${index}${index}:::customClazz\n`;
});
imgSnapshotTest(flowchartCode, { look });
});
});
});
});
});

View File

@@ -1,107 +0,0 @@
import { imgSnapshotTest } from '../../helpers/util';
const looks = ['classic', 'handDrawn'] as const;
const directions = [
'TB',
//'BT',
'LR',
//'RL'
] as const;
const shapesSet1 = ['text', 'card', 'lin-rect', 'diamond', 'hexagon'] as const;
// removing labelRect, need have alias for it
const shapesSet2 = ['rounded', 'rect', 'start', 'stop'] as const;
const shapesSet3 = ['fork', 'choice', 'note', 'stadium', 'odd'] as const;
const shapesSet4 = ['subroutine', 'cylinder', 'circle', 'doublecircle', 'odd'] as const;
const shapesSet5 = ['anchor', 'lean-r', 'lean-l', 'trap-t', 'trap-b'] as const;
// Aggregate all shape sets into a single array
const shapesSets = [shapesSet1, shapesSet2, shapesSet3, shapesSet4, shapesSet5] as const;
looks.forEach((look) => {
directions.forEach((direction) => {
shapesSets.forEach((shapesSet) => {
describe(`Test ${shapesSet.join(', ')} in ${look} look and dir ${direction}`, () => {
it(`without label`, () => {
let flowchartCode = `flowchart ${direction}\n`;
shapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape} }\n`;
});
imgSnapshotTest(flowchartCode, { look });
});
it(`with label`, () => {
let flowchartCode = `flowchart ${direction}\n`;
shapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'This is a label for ${newShape} shape' }\n`;
});
imgSnapshotTest(flowchartCode, { look });
});
it(`connect all shapes with each other`, () => {
let flowchartCode = `flowchart ${direction}\n`;
shapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index}${index}@{ shape: ${newShape}, label: 'This is a label for ${newShape} shape' }\n`;
});
for (let i = 0; i < shapesSet.length; i++) {
for (let j = i + 1; j < shapesSet.length; j++) {
flowchartCode += ` n${i}${i} --> n${j}${j}\n`;
}
}
imgSnapshotTest(flowchartCode, { look });
});
it(`with very long label`, () => {
let flowchartCode = `flowchart ${direction}\n`;
shapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'This is a very very very very very long long long label for ${newShape} shape' }\n`;
});
imgSnapshotTest(flowchartCode, { look });
});
it(`with markdown htmlLabels:true`, () => {
let flowchartCode = `flowchart ${direction}\n`;
shapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'This is **bold** </br>and <strong>strong</strong> for ${newShape} shape' }\n`;
});
imgSnapshotTest(flowchartCode, { look });
});
it(`with markdown htmlLabels:false`, () => {
let flowchartCode = `flowchart ${direction}\n`;
shapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'This is **bold** </br>and <strong>strong</strong> for ${newShape} shape' }\n`;
});
imgSnapshotTest(flowchartCode, {
look,
htmlLabels: false,
flowchart: { htmlLabels: false },
});
});
it(`with styles`, () => {
let flowchartCode = `flowchart ${direction}\n`;
shapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'new ${newShape} shape' }\n`;
flowchartCode += ` style n${index}${index} fill:#f9f,stroke:#333,stroke-width:4px \n`;
});
imgSnapshotTest(flowchartCode, { look });
});
it(`with classDef`, () => {
let flowchartCode = `flowchart ${direction}\n`;
flowchartCode += ` classDef customClazz fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5\n`;
shapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'new ${newShape} shape' }\n`;
flowchartCode += ` n${index}${index}:::customClazz\n`;
});
imgSnapshotTest(flowchartCode, { look });
});
});
});
});
});

View File

@@ -10,15 +10,6 @@ describe('packet structure', () => {
);
});
it('should render a simple packet diagram without ranges', () => {
imgSnapshotTest(
`packet-beta
0: "h"
1: "i"
`
);
});
it('should render a complex packet diagram', () => {
imgSnapshotTest(
`packet-beta

View File

@@ -8,6 +8,7 @@ describe('Quadrant Chart', () => {
`,
{}
);
cy.get('svg');
});
it('should render a complete quadrant chart', () => {
imgSnapshotTest(
@@ -29,6 +30,7 @@ describe('Quadrant Chart', () => {
`,
{}
);
cy.get('svg');
});
it('should render without points', () => {
imgSnapshotTest(
@@ -44,6 +46,7 @@ describe('Quadrant Chart', () => {
`,
{}
);
cy.get('svg');
});
it('should able to render y-axix on right side', () => {
imgSnapshotTest(
@@ -60,6 +63,7 @@ describe('Quadrant Chart', () => {
`,
{}
);
cy.get('svg');
});
it('should able to render x-axix on bottom', () => {
imgSnapshotTest(
@@ -76,6 +80,7 @@ describe('Quadrant Chart', () => {
`,
{}
);
cy.get('svg');
});
it('should able to render x-axix on bottom and y-axis on right', () => {
imgSnapshotTest(
@@ -92,6 +97,7 @@ describe('Quadrant Chart', () => {
`,
{}
);
cy.get('svg');
});
it('should render without title', () => {
imgSnapshotTest(
@@ -106,6 +112,7 @@ describe('Quadrant Chart', () => {
`,
{}
);
cy.get('svg');
});
it('should use all the config', () => {
imgSnapshotTest(
@@ -128,6 +135,7 @@ describe('Quadrant Chart', () => {
`,
{}
);
cy.get('svg');
});
it('should use all the theme variable', () => {
imgSnapshotTest(
@@ -150,6 +158,7 @@ describe('Quadrant Chart', () => {
`,
{}
);
cy.get('svg');
});
it('should render x-axis labels in the center, if x-axis has two labels', () => {
imgSnapshotTest(
@@ -171,6 +180,7 @@ describe('Quadrant Chart', () => {
`,
{}
);
cy.get('svg');
});
it('should render y-axis labels in the center, if y-axis has two labels', () => {
imgSnapshotTest(
@@ -192,6 +202,7 @@ describe('Quadrant Chart', () => {
`,
{}
);
cy.get('svg');
});
it('should render both axes labels on the left and bottom, if both axes have only one label', () => {
imgSnapshotTest(
@@ -213,6 +224,7 @@ describe('Quadrant Chart', () => {
`,
{}
);
cy.get('svg');
});
it('it should render data points with styles', () => {
@@ -237,6 +249,7 @@ describe('Quadrant Chart', () => {
`,
{}
);
cy.get('svg');
});
it('it should render data points with styles + classes', () => {

View File

@@ -44,5 +44,6 @@ describe('Requirement diagram', () => {
`,
{}
);
cy.get('svg');
});
});

View File

@@ -1,6 +1,8 @@
/// <reference types="Cypress" />
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
describe('Sequence diagram', () => {
context('Sequence diagram', () => {
it('should render a sequence diagram with boxes', () => {
renderGraph(
`
@@ -66,19 +68,6 @@ describe('Sequence diagram', () => {
{ sequence: { actorFontFamily: 'courier' } }
);
});
it('should render bidirectional arrows', () => {
imgSnapshotTest(
`
sequenceDiagram
Alice<<->>John: Hello John, how are you?
Alice<<-->>John: Hi Alice, I can hear you!
John<<->>Alice: This also works the other way
John<<-->>Alice: Yes
Alice->John: Test
John->>Alice: Still works
`
);
});
it('should handle different line breaks', () => {
imgSnapshotTest(
`
@@ -242,7 +231,7 @@ describe('Sequence diagram', () => {
`
);
});
describe('font settings', () => {
context('font settings', () => {
it('should render different note fonts when configured', () => {
imgSnapshotTest(
`
@@ -339,7 +328,7 @@ describe('Sequence diagram', () => {
);
});
});
describe('auth width scaling', () => {
context('auth width scaling', () => {
it('should render long actor descriptions', () => {
imgSnapshotTest(
`
@@ -475,18 +464,6 @@ describe('Sequence diagram', () => {
{}
);
});
it('should render notes over actors and participant', () => {
imgSnapshotTest(
`
sequenceDiagram
actor Alice
participant Charlie
note over Alice: some note
note over Charlie: other note
`,
{}
);
});
it('should render long messages from an actor to the left to one to the right', () => {
imgSnapshotTest(
`
@@ -528,7 +505,7 @@ describe('Sequence diagram', () => {
);
});
});
describe('background rects', () => {
context('background rects', () => {
it('should render a single and nested rects', () => {
imgSnapshotTest(
`
@@ -808,7 +785,7 @@ describe('Sequence diagram', () => {
);
});
});
describe('directives', () => {
context('directives', () => {
it('should override config with directive settings', () => {
imgSnapshotTest(
`
@@ -840,7 +817,7 @@ describe('Sequence diagram', () => {
);
});
});
describe('links', () => {
context('links', () => {
it('should support actor links', () => {
renderGraph(
`
@@ -856,7 +833,7 @@ describe('Sequence diagram', () => {
);
cy.get('#actor0_popup').should((popupMenu) => {
const style = popupMenu.attr('style');
// expect(style).to.undefined;
expect(style).to.undefined;
});
cy.get('#root-0').click();
cy.get('#actor0_popup').should((popupMenu) => {
@@ -931,7 +908,7 @@ describe('Sequence diagram', () => {
);
});
});
describe('svg size', () => {
context('svg size', () => {
it('should render a sequence diagram when useMaxWidth is true (default)', () => {
renderGraph(
`
@@ -1010,7 +987,7 @@ describe('Sequence diagram', () => {
});
});
});
describe('render after error', () => {
context('render after error', () => {
it('should render diagram after fixing destroy participant error', () => {
cy.on('uncaught:exception', (err) => {
return false;

View File

@@ -8,6 +8,7 @@ describe('State diagram', () => {
`,
{ logLevel: 1, fontFamily: 'courier' }
);
cy.get('svg');
});
it('v2 should render a simple state diagrams', () => {
imgSnapshotTest(
@@ -19,6 +20,7 @@ describe('State diagram', () => {
`,
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
it('v2 should render a long descriptions instead of id when available', () => {
imgSnapshotTest(
@@ -30,6 +32,7 @@ describe('State diagram', () => {
`,
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
it('v2 should render a long descriptions with additional descriptions', () => {
imgSnapshotTest(
@@ -41,6 +44,7 @@ describe('State diagram', () => {
`,
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
it('v2 should render a single state with short descriptions', () => {
imgSnapshotTest(
@@ -51,6 +55,7 @@ describe('State diagram', () => {
`,
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
it('v2 should render a transition descriptions with new lines', () => {
imgSnapshotTest(
@@ -64,6 +69,7 @@ describe('State diagram', () => {
`,
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
it('v2 should render a state with a note', () => {
imgSnapshotTest(
@@ -77,6 +83,7 @@ describe('State diagram', () => {
`,
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
it('v2 should render a state with on the left side when so specified', () => {
imgSnapshotTest(
@@ -90,6 +97,7 @@ describe('State diagram', () => {
`,
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
it('v2 should render a state with a note together with another state', () => {
imgSnapshotTest(
@@ -105,6 +113,7 @@ describe('State diagram', () => {
`,
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
it('v2 should render a note with multiple lines in it', () => {
imgSnapshotTest(
@@ -147,6 +156,7 @@ describe('State diagram', () => {
`,
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
it('v2 should render a simple state diagrams 2', () => {
imgSnapshotTest(
@@ -159,6 +169,7 @@ describe('State diagram', () => {
`,
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
it('v2 should render a simple state diagrams with labels', () => {
imgSnapshotTest(
@@ -174,6 +185,7 @@ describe('State diagram', () => {
`,
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
it('v2 should render state descriptions', () => {
imgSnapshotTest(
@@ -186,6 +198,7 @@ describe('State diagram', () => {
`,
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
it('v2 should render composite states', () => {
imgSnapshotTest(
@@ -204,6 +217,7 @@ describe('State diagram', () => {
`,
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
it('v2 should render multiple composite states', () => {
imgSnapshotTest(
@@ -273,6 +287,7 @@ describe('State diagram', () => {
`,
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
it('v2 should render concurrency states', () => {
imgSnapshotTest(
@@ -296,6 +311,7 @@ describe('State diagram', () => {
`,
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
it('v2 should render a state with states in it', () => {
imgSnapshotTest(
@@ -542,43 +558,6 @@ stateDiagram-v2
{ logLevel: 0, fontFamily: 'courier' }
);
});
it(' can have styles applied ', () => {
imgSnapshotTest(
`
stateDiagram-v2
AState
style AState fill:#636,border:1px solid red,color:white;
`,
{ logLevel: 0, fontFamily: 'courier' }
);
});
it(' should let styles take preceedence over classes', () => {
imgSnapshotTest(
`
stateDiagram-v2
AState: Should NOT be white
BState
classDef exampleStyleClass fill:#fff,color: blue;
class AState,BState exampleStyleClass
style AState fill:#636,border:1px solid red,color:white;
`,
{ logLevel: 0, fontFamily: 'courier' }
);
});
it(' should allow styles to take effect in stubgraphs', () => {
imgSnapshotTest(
`
stateDiagram
state roundWithTitle {
C: Black with white text
}
D: Black with white text
style C,D stroke:#00f, fill:black, color:white
`,
{ logLevel: 0, fontFamily: 'courier' }
);
});
});
it('1433: should render a simple state diagram with a title', () => {
imgSnapshotTest(
@@ -588,20 +567,6 @@ title: simple state diagram
stateDiagram-v2
[*] --> State1
State1 --> [*]
`,
{}
);
});
it('should align dividers correctly', () => {
imgSnapshotTest(
`stateDiagram-v2
state s2 {
s3
--
s4
--
55
}
`,
{}
);

View File

@@ -10,6 +10,7 @@ describe('State diagram', () => {
`,
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
it('should render a long descriptions instead of id when available', () => {
imgSnapshotTest(
@@ -21,6 +22,7 @@ describe('State diagram', () => {
`,
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
it('should render a long descriptions with additional descriptions', () => {
imgSnapshotTest(
@@ -32,6 +34,7 @@ describe('State diagram', () => {
`,
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
it('should render a single state with short descriptions', () => {
imgSnapshotTest(
@@ -42,6 +45,7 @@ describe('State diagram', () => {
`,
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
it('should render a transition descriptions with new lines', () => {
imgSnapshotTest(
@@ -55,6 +59,7 @@ describe('State diagram', () => {
`,
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
it('should render a state with a note', () => {
imgSnapshotTest(
@@ -68,6 +73,7 @@ describe('State diagram', () => {
`,
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
it('should render a state with on the left side when so specified', () => {
imgSnapshotTest(
@@ -81,6 +87,7 @@ describe('State diagram', () => {
`,
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
it('should render a state with a note together with another state', () => {
imgSnapshotTest(
@@ -96,6 +103,7 @@ describe('State diagram', () => {
`,
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
it('should render a note with multiple lines in it', () => {
imgSnapshotTest(
@@ -138,6 +146,7 @@ describe('State diagram', () => {
`,
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
it('should render a simple state diagrams 2', () => {
imgSnapshotTest(
@@ -150,6 +159,7 @@ describe('State diagram', () => {
`,
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
it('should render a simple state diagrams with labels', () => {
imgSnapshotTest(
@@ -165,6 +175,7 @@ describe('State diagram', () => {
`,
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
it('should render state descriptions', () => {
imgSnapshotTest(
@@ -177,6 +188,7 @@ describe('State diagram', () => {
`,
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
it('should render composite states', () => {
imgSnapshotTest(
@@ -195,6 +207,7 @@ describe('State diagram', () => {
`,
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
it('should render multiple composit states', () => {
imgSnapshotTest(
@@ -264,6 +277,7 @@ describe('State diagram', () => {
`,
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
it('should render concurrency states', () => {
imgSnapshotTest(
@@ -287,6 +301,7 @@ describe('State diagram', () => {
`,
{ logLevel: 0, fontFamily: 'courier' }
);
cy.get('svg');
});
it('should render a state with states in it', () => {
imgSnapshotTest(

View File

@@ -10,6 +10,7 @@ describe('themeCSS balancing, it', () => {
`,
{}
);
cy.get('svg');
});
it('should not allow unbalanced CSS definitions 2', () => {
imgSnapshotTest(
@@ -20,6 +21,7 @@ describe('themeCSS balancing, it', () => {
`,
{}
);
cy.get('svg');
});
});
@@ -43,6 +45,7 @@ describe('Pie Chart', () => {
`,
{ theme }
);
cy.get('svg');
});
it('should render a flowchart diagram', () => {
imgSnapshotTest(
@@ -67,6 +70,7 @@ describe('Pie Chart', () => {
`,
{ theme }
);
cy.get('svg');
});
it('should render a new flowchart diagram', () => {
imgSnapshotTest(
@@ -92,6 +96,7 @@ describe('Pie Chart', () => {
`,
{ theme }
);
cy.get('svg');
});
it('should render a sequence diagram', () => {
imgSnapshotTest(
@@ -120,6 +125,7 @@ describe('Pie Chart', () => {
`,
{ theme }
);
cy.get('svg');
});
it('should render a class diagram', () => {
@@ -169,6 +175,7 @@ describe('Pie Chart', () => {
`,
{ theme }
);
cy.get('svg');
});
it('should render a state diagram', () => {
imgSnapshotTest(
@@ -203,6 +210,7 @@ stateDiagram
`,
{ theme }
);
cy.get('svg');
});
it('should render a state diagram (v2)', () => {
imgSnapshotTest(
@@ -237,6 +245,7 @@ stateDiagram-v2
`,
{ theme }
);
cy.get('svg');
});
it('should render a er diagram', () => {
imgSnapshotTest(
@@ -257,6 +266,7 @@ erDiagram
`,
{ theme }
);
cy.get('svg');
});
it('should render a user journey diagram', () => {
imgSnapshotTest(
@@ -277,6 +287,7 @@ erDiagram
`,
{ theme }
);
cy.get('svg');
});
it('should render a gantt diagram', () => {
cy.clock(new Date('2014-01-06').getTime());
@@ -315,6 +326,7 @@ erDiagram
`,
{ theme }
);
cy.get('svg');
});
});
});

View File

@@ -9,6 +9,7 @@ describe('XY Chart', () => {
`,
{}
);
cy.get('svg');
});
it('Should render a complete chart', () => {
imgSnapshotTest(
@@ -34,6 +35,7 @@ describe('XY Chart', () => {
`,
{}
);
cy.get('svg');
});
it('y-axis title not required', () => {
imgSnapshotTest(
@@ -46,6 +48,7 @@ describe('XY Chart', () => {
`,
{}
);
cy.get('svg');
});
it('Should render a chart without y-axis with different range', () => {
imgSnapshotTest(
@@ -57,6 +60,7 @@ describe('XY Chart', () => {
`,
{}
);
cy.get('svg');
});
it('x axis title not required', () => {
imgSnapshotTest(
@@ -68,6 +72,7 @@ describe('XY Chart', () => {
`,
{}
);
cy.get('svg');
});
it('Multiple plots can be rendered', () => {
imgSnapshotTest(
@@ -82,6 +87,7 @@ describe('XY Chart', () => {
`,
{}
);
cy.get('svg');
});
it('Decimals and negative numbers are supported', () => {
imgSnapshotTest(
@@ -92,6 +98,7 @@ describe('XY Chart', () => {
`,
{}
);
cy.get('svg');
});
it('Render spark line with "plotReservedSpacePercent"', () => {
imgSnapshotTest(
@@ -109,6 +116,7 @@ describe('XY Chart', () => {
`,
{}
);
cy.get('svg');
});
it('Render spark bar without displaying other property', () => {
imgSnapshotTest(
@@ -135,6 +143,7 @@ describe('XY Chart', () => {
`,
{}
);
cy.get('svg');
});
it('Should use all the config from directive', () => {
imgSnapshotTest(
@@ -149,6 +158,7 @@ describe('XY Chart', () => {
`,
{}
);
cy.get('svg');
});
it('Should use all the config from yaml', () => {
imgSnapshotTest(
@@ -189,6 +199,7 @@ describe('XY Chart', () => {
`,
{}
);
cy.get('svg');
});
it('Render with show axis title false', () => {
imgSnapshotTest(
@@ -210,6 +221,7 @@ describe('XY Chart', () => {
`,
{}
);
cy.get('svg');
});
it('Render with show axis label false', () => {
imgSnapshotTest(
@@ -231,6 +243,7 @@ describe('XY Chart', () => {
`,
{}
);
cy.get('svg');
});
it('Render with show axis tick false', () => {
imgSnapshotTest(
@@ -252,6 +265,7 @@ describe('XY Chart', () => {
`,
{}
);
cy.get('svg');
});
it('Render with show axis line false', () => {
imgSnapshotTest(
@@ -273,6 +287,7 @@ describe('XY Chart', () => {
`,
{}
);
cy.get('svg');
});
it('Render all the theme color', () => {
imgSnapshotTest(
@@ -302,17 +317,6 @@ describe('XY Chart', () => {
`,
{}
);
});
it('should use the correct distances between data points', () => {
imgSnapshotTest(
`
xychart-beta
x-axis 0 --> 2
line [0, 1, 0, 1]
bar [1, 0, 1, 0]
`,
{}
);
cy.get('svg');
});
});

Some files were not shown because too many files have changed in this diff Show More