diff --git a/.eslintrc.json b/.eslintrc.json index 0da42ae61..02753280c 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -63,6 +63,13 @@ "rules": { "no-console": "off" } + }, + { + "files": ["./**/*.spec.{ts,js}", "./cypress/**", "./demos/**", "./**/docs/**"], + "rules": { + "jsdoc/require-jsdoc": "off", + "@typescript-eslint/no-unused-vars": "off" + } } ] } diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index c7015dbe7..396ff4e6e 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -14,7 +14,7 @@ jobs: name: check tests if: github.repository_owner == 'mermaid-js' steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: fetch-depth: 0 - uses: testomatio/check-tests@stable diff --git a/.github/workflows/e2e b/.github/workflows/e2e deleted file mode 100644 index 5b716e429..000000000 --- a/.github/workflows/e2e +++ /dev/null @@ -1,38 +0,0 @@ -name: E2E - -on: [push, pull_request] - -permissions: - contents: read - -jobs: - build: - runs-on: ubuntu-latest - strategy: - matrix: - node-version: [16.x] - steps: - - uses: actions/checkout@v3 - - - name: Setup Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 - with: - cache: yarn - node-version: ${{ matrix.node-version }} - - - name: Install Yarn - run: npm i yarn --global - - - name: Install Packages - run: | - yarn install --frozen-lockfile - env: - CYPRESS_CACHE_FOLDER: .cache/Cypress - - - name: Run Build - run: yarn build - - - name: Run E2E Tests - run: yarn e2e - env: - CYPRESS_CACHE_FOLDER: .cache/Cypress diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml new file mode 100644 index 000000000..06a346aeb --- /dev/null +++ b/.github/workflows/e2e.yml @@ -0,0 +1,38 @@ +name: E2E + +on: [push, pull_request] + +permissions: + contents: read + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + node-version: [16.x] + steps: + - uses: actions/checkout@v3 + + - name: Setup Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v3 + with: + cache: yarn + node-version: ${{ matrix.node-version }} + + - name: Install Yarn + run: npm i yarn --global + + - name: Install Packages + run: | + yarn install --frozen-lockfile + env: + CYPRESS_CACHE_FOLDER: .cache/Cypress + + - name: Run Build + run: yarn build + + - name: Run E2E Tests + run: yarn e2e + env: + CYPRESS_CACHE_FOLDER: .cache/Cypress diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 97aa0a377..08c35befa 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -32,3 +32,12 @@ jobs: - name: Run Unit Tests run: | yarn ci --coverage + + - name: Upload Coverage to Coveralls + # it feels a bit weird to use @master, but that's what the docs use + # (coveralls also doesn't publish a @v1 we can use) + # https://github.com/marketplace/actions/coveralls-github-action + uses: coverallsapp/github-action@master + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + flag-name: unit diff --git a/.lintstagedrc.json b/.lintstagedrc.json index c53b7f626..1e7c61dd8 100644 --- a/.lintstagedrc.json +++ b/.lintstagedrc.json @@ -1,5 +1,6 @@ { "src/docs/**": ["yarn docs:build --git"], - "*.{ts,js,json,html,md}": ["eslint --fix", "prettier --write"], + "src/docs.mts": ["yarn docs:build --git"], + "*.{ts,js,json,html,md,mts}": ["eslint --fix", "prettier --write"], "*.jison": ["yarn lint:jison"] } diff --git a/applitools.cnfig.js b/applitools.cnfig.js deleted file mode 100644 index 900aabf2e..000000000 --- a/applitools.cnfig.js +++ /dev/null @@ -1,16 +0,0 @@ -module.exports = { - testConcurrency: 1, - // browser: [ - // // Add browsers with different viewports - // { width: 800, height: 600, name: 'chrome' }, - // { width: 700, height: 500, name: 'firefox' }, - // { width: 1600, height: 1200, name: 'ie11' }, - // { width: 1024, height: 768, name: 'edgechromium' }, - // { width: 800, height: 600, name: 'safari' }, - // // Add mobile emulation devices in Portrait mode - // { deviceName: 'iPhone X', screenOrientation: 'portrait' }, - // { deviceName: 'Pixel 2', screenOrientation: 'portrait' }, - // ], - // // set batch name to the configuration - // batchName: 'Ultrafast Batch', -}; diff --git a/applitools.config.js b/applitools.config.js new file mode 100644 index 000000000..1c0607868 --- /dev/null +++ b/applitools.config.js @@ -0,0 +1,19 @@ +// eslint-disable-next-line @typescript-eslint/no-var-requires +const { defineConfig } = require('cypress'); + +module.exports = defineConfig({ + testConcurrency: 1, + browser: [ + // Add browsers with different viewports + // { width: 800, height: 600, name: 'chrome' }, + // { width: 700, height: 500, name: 'firefox' }, + // { width: 1600, height: 1200, name: 'ie11' }, + // { width: 1024, height: 768, name: 'edgechromium' }, + // { width: 800, height: 600, name: 'safari' }, + // // Add mobile emulation devices in Portrait mode + // { deviceName: 'iPhone X', screenOrientation: 'portrait' }, + // { deviceName: 'Pixel 2', screenOrientation: 'portrait' }, + ], + // set batch name to the configuration + batchName: `Mermaid ${process.env.APPLI_BRANCH ?? "'no APPLI_BRANCH set'"}`, +}); diff --git a/cypress.config.js b/cypress.config.js index d7c9831d4..b434cec47 100644 --- a/cypress.config.js +++ b/cypress.config.js @@ -2,21 +2,20 @@ const { defineConfig } = require('cypress'); const { addMatchImageSnapshotPlugin } = require('cypress-image-snapshot/plugin'); -require('@applitools/eyes-cypress')(module); module.exports = defineConfig({ e2e: { - specPattern: 'cypress/e2e/**/*.{js,jsx,ts,tsx}', + specPattern: 'cypress/integration/**/*.{js,jsx,ts,tsx}', setupNodeEvents(on, config) { addMatchImageSnapshotPlugin(on, config); // copy any needed variables from process.env to config.env config.env.useAppli = process.env.USE_APPLI ? true : false; - config.env.codeBranch = process.env.APPLI_BRANCH; // do not forget to return the changed config object! return config; }, - supportFile: 'cypress/support/index.js', }, video: false, }); + +require('@applitools/eyes-cypress')(module); diff --git a/cypress/downloads/downloads.html b/cypress/downloads/downloads.html deleted file mode 100644 index b42fc821e..000000000 --- a/cypress/downloads/downloads.html +++ /dev/null @@ -1 +0,0 @@ -Cr24 \ No newline at end of file diff --git a/cypress/helpers/util.js b/cypress/helpers/util.js index b5e64a1e8..d138dfcfe 100644 --- a/cypress/helpers/util.js +++ b/cypress/helpers/util.js @@ -44,15 +44,13 @@ export const imgSnapshotTest = (graphStr, _options, api = false, validation) => } const useAppli = Cypress.env('useAppli'); //const useAppli = false; - const branch = Cypress.env('codeBranch'); cy.log('Hello ' + useAppli ? 'Appli' : 'image-snapshot'); const name = (options.name || cy.state('runnable').fullTitle()).replace(/\s+/g, '-'); if (useAppli) { cy.eyesOpen({ - appName: 'Mermaid-' + branch, + appName: 'Mermaid', testName: name, - batchName: branch, }); } @@ -96,15 +94,13 @@ export const urlSnapshotTest = (url, _options, api = false, validation) => { options.fontSize = '16px'; } const useAppli = Cypress.env('useAppli'); - const branch = Cypress.env('codeBranch'); cy.log('Hello ' + useAppli ? 'Appli' : 'image-snapshot'); const name = (options.name || cy.state('runnable').fullTitle()).replace(/\s+/g, '-'); if (useAppli) { cy.eyesOpen({ - appName: 'Mermaid-' + branch, + appName: 'Mermaid', testName: name, - batchName: branch, }); } diff --git a/cypress/integration/other/configuration.spec.js b/cypress/integration/other/configuration.spec.js index a67758d9c..513cf0714 100644 --- a/cypress/integration/other/configuration.spec.js +++ b/cypress/integration/other/configuration.spec.js @@ -15,11 +15,13 @@ describe('Configuration', () => { // Check the marker-end property to make sure it is properly set to // start with # - cy.get('.edgePath path') - .first() - .should('have.attr', 'marker-end') - .should('exist') - .and('include', 'url(#'); + cy.get('.edgePaths').within(() => { + cy.get('path') + .first() + .should('have.attr', 'marker-end') + .should('exist') + .and('include', 'url(#'); + }); }); it('should handle default value false of arrowMarkerAbsolute', () => { renderGraph( @@ -35,11 +37,13 @@ describe('Configuration', () => { // Check the marker-end property to make sure it is properly set to // start with # - cy.get('.edgePath path') - .first() - .should('have.attr', 'marker-end') - .should('exist') - .and('include', 'url(#'); + cy.get('.edgePaths').within(() => { + cy.get('path') + .first() + .should('have.attr', 'marker-end') + .should('exist') + .and('include', 'url(#'); + }); }); it('should handle arrowMarkerAbsolute explicitly set to false', () => { renderGraph( @@ -57,11 +61,13 @@ describe('Configuration', () => { // Check the marker-end property to make sure it is properly set to // start with # - cy.get('.edgePath path') - .first() - .should('have.attr', 'marker-end') - .should('exist') - .and('include', 'url(#'); + cy.get('.edgePaths').within(() => { + cy.get('path') + .first() + .should('have.attr', 'marker-end') + .should('exist') + .and('include', 'url(#'); + }); }); it('should handle arrowMarkerAbsolute explicitly set to "false" as false', () => { renderGraph( @@ -79,15 +85,17 @@ describe('Configuration', () => { // Check the marker-end property to make sure it is properly set to // start with # - cy.get('.edgePath path') - .first() - .should('have.attr', 'marker-end') - .should('exist') - .and('include', 'url(#'); + cy.get('.edgePaths').within(() => { + cy.get('path') + .first() + .should('have.attr', 'marker-end') + .should('exist') + .and('include', 'url(#'); + }); }); it('should handle arrowMarkerAbsolute set to true', () => { renderGraph( - `graph TD + `flowchart TD A[Christmas] -->|Get money| B(Go shopping) B --> C{Let me think} C -->|One| D[Laptop] @@ -99,11 +107,13 @@ describe('Configuration', () => { } ); - cy.get('.edgePath path') - .first() - .should('have.attr', 'marker-end') - .should('exist') - .and('include', 'url(http://localhost'); + cy.get('.edgePaths').within(() => { + cy.get('path') + .first() + .should('have.attr', 'marker-end') + .should('exist') + .and('include', 'url(http://localhost'); + }); }); it('should not taint the initial configuration when using multiple directives', () => { const url = 'http://localhost:9000/regression/issue-1874.html'; diff --git a/cypress/integration/other/xss.spec.js b/cypress/integration/other/xss.spec.js index 912354f7d..4911dd8df 100644 --- a/cypress/integration/other/xss.spec.js +++ b/cypress/integration/other/xss.spec.js @@ -81,6 +81,9 @@ describe('XSS', () => { cy.get('#the-malware').should('not.exist'); }); it('should not allow manipulating antiscript to run javascript using onerror in state diagrams with dagre d3', () => { + cy.on('uncaught:exception', (_err, _runnable) => { + return false; // continue rendering even if there if mermaid throws an error + }); cy.visit('http://localhost:9000/xss9.html'); cy.wait(1000); cy.get('#the-malware').should('not.exist'); diff --git a/cypress/integration/rendering/flowchart.spec.js b/cypress/integration/rendering/flowchart.spec.js index b4e94d1ab..c4ef54fcf 100644 --- a/cypress/integration/rendering/flowchart.spec.js +++ b/cypress/integration/rendering/flowchart.spec.js @@ -745,13 +745,13 @@ describe('Graph', () => { cy.get('svg').should((svg) => { expect(svg).to.have.attr('width', '100%'); // expect(svg).to.have.attr('height'); - // use within because the absolute value can be slightly different depending on the environment ±5% + // use within because the absolute value can be slightly different depending on the environment ±10% // const height = parseFloat(svg.attr('height')); // expect(height).to.be.within(446 * 0.95, 446 * 1.05); 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(300 * 0.95, 300 * 1.05); + expect(maxWidthValue).to.be.within(300 * 0.9, 300 * 1.1); }); }); it('39: should render a flowchart when useMaxWidth is false', () => { @@ -768,9 +768,9 @@ describe('Graph', () => { cy.get('svg').should((svg) => { // const height = parseFloat(svg.attr('height')); const width = parseFloat(svg.attr('width')); - // use within because the absolute value can be slightly different depending on the environment ±5% + // 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(300 * 0.95, 300 * 1.05); + expect(width).to.be.within(300 * 0.9, 300 * 1.1); expect(svg).to.not.have.attr('style'); }); }); diff --git a/cypress/integration/rendering/gitGraph.spec.js b/cypress/integration/rendering/gitGraph.spec.js index 80981c31c..b0d65d0cc 100644 --- a/cypress/integration/rendering/gitGraph.spec.js +++ b/cypress/integration/rendering/gitGraph.spec.js @@ -213,42 +213,43 @@ describe('Git Graph diagram', () => { ` gitGraph checkout main - commit + %% Make sure to manually set the ID of all commits, for consistent visual tests + commit id: "1-abcdefg" checkout main branch branch1 - commit + commit id: "2-abcdefg" checkout main merge branch1 branch branch2 - commit + commit id: "3-abcdefg" checkout main merge branch2 branch branch3 - commit + commit id: "4-abcdefg" checkout main merge branch3 branch branch4 - commit + commit id: "5-abcdefg" checkout main merge branch4 branch branch5 - commit + commit id: "6-abcdefg" checkout main merge branch5 branch branch6 - commit + commit id: "7-abcdefg" checkout main merge branch6 branch branch7 - commit + commit id: "8-abcdefg" checkout main merge branch7 branch branch8 - commit + commit id: "9-abcdefg" checkout main merge branch8 branch branch9 - commit + commit id: "10-abcdefg" `, {} ); diff --git a/cypress/platform/bundle-test.js b/cypress/platform/bundle-test.js index b4ce798b2..373f8741a 100644 --- a/cypress/platform/bundle-test.js +++ b/cypress/platform/bundle-test.js @@ -1,4 +1,4 @@ -import mermaid from '../../dist/mermaid.core.mjs'; +import mermaid from '../../dist/mermaid.core'; let code = `flowchart LR Power_Supply --> Transmitter_A diff --git a/cypress/platform/knsv.html b/cypress/platform/knsv.html index c98ce70c8..a06667c1f 100644 --- a/cypress/platform/knsv.html +++ b/cypress/platform/knsv.html @@ -39,6 +39,14 @@
+flowchart LR + a --- ++
+flowchart LR + a2 --- ++
flowchart LR classDef aPID stroke:#4e4403,fill:#fdde29,color:#4e4403,rx:5px,ry:5px; classDef crm stroke:#333333,fill:#DCDCDC,color:#333333,rx:5px,ry:5px; @@ -73,7 +81,31 @@ flowchart TD
flowchart TD -id + + release-branch[Create Release Branch]:::relClass + develop-branch[Update Develop Branch]:::relClass + github-release-draft[GitHub Release Draft]:::relClass + trigger-pipeline[Trigger Jenkins pipeline]:::fixClass + github-release[GitHub Release]:::postClass + + build-ready --> release-branch + build-ready --> develop-branch + release-branch --> jenkins-release-build + jenkins-release-build --> github-release-draft + jenkins-release-build --> install-release + install-release --> verify-release + jenkins-release-build --> announce + github-release-draft --> github-release + verify-release --> verify-check + verify-check -- Yes --> github-release + verify-check -- No --> release-fix + release-fix --> release-branch-pr + verify-check -- No --> delete-artifacts + release-branch-pr --> trigger-pipeline + delete-artifacts --> trigger-pipeline + trigger-pipeline --> jenkins-release-build + +
flowchart LR @@ -99,7 +131,7 @@ flowchart TD class A someclass; class C someclass;-
+sequenceDiagram title: My Sequence Diagram Title accTitle: My Acc Sequence Diagram @@ -109,14 +141,14 @@ flowchart TD John-->>Alice: Great! Alice-)John: See you later!-+graph TD A -->|000| B B -->|111| C linkStyle 1 stroke:#ff3,stroke-width:4px,color:red;-+journey accTitle: My User Journey Diagram accDescr: My User Journey Diagram Description @@ -130,10 +162,10 @@ graph TD Go downstairs: 5: Me Sit down: 5: Me-+info-+requirementDiagram accTitle: My req Diagram accDescr: My req Diagram Description @@ -174,7 +206,7 @@ requirementDiagram test_req - contains -> test_req3 test_req <- copies - test_entity2-+gantt dateFormat YYYY-MM-DD title Adding GANTT diagram functionality to mermaid @@ -206,7 +238,7 @@ gantt Add gantt diagram to demo page :20h Add another diagram to demo page :48h-+stateDiagram state Active { Idle @@ -234,7 +266,7 @@ stateDiagram end B ->> A: Return-+classDiagram accTitle: My class diagram accDescr: My class diagram Description @@ -259,7 +291,7 @@ class Class10 { A->>Bob: Hola Bob-->A: Pasten !-+gitGraph commit id: "ZERO" branch develop @@ -288,7 +320,7 @@ flowchart TD C -->|Two| E[iPhone] C -->|Three| F[fa:fa-car Car]-+classDiagram Animal "1" <|-- Duck Animal <|-- Fish @@ -311,7 +343,7 @@ flowchart TD +run() }-+erDiagram CAR ||--o{ NAMED-DRIVER : allows CAR { @@ -357,6 +389,11 @@ flowchart TD document.getElementsByTagName('body')[0].appendChild(div); } + + mermaid.parseError = function (err, hash) { + console.error('In parse error:'); + console.error(err); + };