Merge branch 'develop'

This commit is contained in:
Paulo Gustavo Veiga 2023-02-15 22:50:04 -08:00
commit ecaf509cdc
687 changed files with 40120 additions and 32675 deletions

42
.gitignore vendored
View File

@ -7,51 +7,27 @@
node_modules/ node_modules/
dist/ dist/
# Compiled Java class files
*.class
# Compiled Python bytecode
*.py[cod]
# Log files # Log files
*.log *.log
# Package files
*.jar
# Maven
target/
dist/
# JetBrains IDE
.idea/
# Unit test reports
TEST*.xml
# Generated by MacOS # Generated by MacOS
.DS_Store .DS_Store
# Generated by Windows # Generated by Windows
Thumbs.db Thumbs.db
# Applications
*.app
*.exe
*.war
# Large media files
*.mp4
*.tiff
*.avi
*.flv
*.mov
*.wmv
**/build/**/* **/build/**/*
.vscode .vscode
*/test/playground/dist
# visual code local workspaces # visual code local workspaces
wisemapping-frontend.code-workspace wisemapping-frontend.code-workspace
.yarn/*
./yarn/cache
!.yarn/releases
!.yarn/plugins
.pnp.*
packages/**/.yalc/
packages/**/yalc.lock

4
.husky/pre-commit Executable file
View File

@ -0,0 +1,4 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
yarn lint-staged

4
.husky/pre-push Executable file
View File

@ -0,0 +1,4 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
yarn lint && yarn test

823
.yarn/releases/yarn-3.3.1.cjs vendored Executable file

File diff suppressed because one or more lines are too long

3
.yarnrc.yml Normal file
View File

@ -0,0 +1,3 @@
nodeLinker: node-modules
yarnPath: .yarn/releases/yarn-3.3.1.cjs

View File

@ -18,7 +18,6 @@ pipelines:
script: script:
- export CYPRESS_imageSnaphots="true" - export CYPRESS_imageSnaphots="true"
- yarn install - yarn install
- yarn bootstrap
- yarn build - yarn build
- yarn lint - yarn lint
- yarn test:unit - yarn test:unit

View File

@ -0,0 +1 @@
../packages/webapp/dist/editor_dist_editor_bundle_js.bundle.js

View File

@ -0,0 +1 @@
../packages/webapp/dist/editor_dist_editor_bundle_js.bundle.js.map

View File

@ -1 +0,0 @@
../packages/webapp/dist/src_components_maps-page_account-menu_index_tsx-src_components_maps-page_action-dispatcher_in-ba81d4.bundle.js

View File

@ -1 +0,0 @@
../packages/webapp/dist/src_components_maps-page_account-menu_index_tsx-src_components_maps-page_action-dispatcher_in-ba81d4.bundle.js.map

View File

@ -0,0 +1 @@
../packages/webapp/dist/src_components_maps-page_account-menu_index_tsx.bundle.js

View File

@ -0,0 +1 @@
../packages/webapp/dist/src_components_maps-page_account-menu_index_tsx.bundle.js.map

View File

@ -0,0 +1 @@
../packages/webapp/dist/src_components_maps-page_action-dispatcher_index_tsx.bundle.js

View File

@ -0,0 +1 @@
../packages/webapp/dist/src_components_maps-page_action-dispatcher_index_tsx.bundle.js.map

View File

@ -1,9 +1,9 @@
version: '3' version: '3'
services: services:
e2e: e2e:
image: cypress/included:10.11.0 image: cypress/included:12.2.0
container_name: wisemapping-integration-tests container_name: wisemapping-integration-tests
entrypoint: '/bin/sh -c "yarn install && yarn bootstrap && yarn build && yarn test:integration"' entrypoint: '/bin/sh -c "yarn install && yarn build && yarn test:integration"'
working_dir: /e2e working_dir: /e2e
environment: environment:
- CYPRESS_imageSnaphots=true - CYPRESS_imageSnaphots=true

View File

@ -1,9 +1,9 @@
version: '3' version: '3'
services: services:
e2e: e2e:
image: cypress/included:10.11.0 image: cypress/included:12.3.0
container_name: wisemapping-integration-tests container_name: wisemapping-integration-tests
entrypoint: '/bin/sh -c "yarn bootstrap && yarn build && yarn test:integration"' entrypoint: '/bin/sh -c "yarn build && yarn test:integration"'
working_dir: /e2e working_dir: /e2e
environment: environment:
- CYPRESS_imageSnaphots=true - CYPRESS_imageSnaphots=true

View File

@ -1,21 +1,57 @@
{ {
"name": "wisemapping-front-end", "name": "wisemapping-front-end",
"scripts": { "scripts": {
"bootstrap": "lerna bootstrap", "bootstrap": "lerna run bootstrap",
"build": "lerna run build", "build": "lerna run build",
"clean": "lerna clean && rm -rf node_modules", "clean": "lerna clean && rm -rf node_modules",
"lint": "lerna run lint --stream", "lint": "lerna run lint --stream",
"playground": "lerna run playground --stream", "playground": "lerna run playground --stream",
"test": "lerna run test --stream", "test": "lerna run test --stream",
"test:unit": "lerna run test:unit --stream", "test:unit": "lerna run test:unit --stream",
"test:integration": "lerna run test:integration --stream" "test:integration": "lerna run test:integration --stream",
"prepare": "husky install"
}, },
"private": true, "private": true,
"devDependencies": { "devDependencies": {
"cypress": "^8.4.1", "@babel/core": "^7.20.12",
"husky": "4", "@babel/preset-env": "^7.14.7",
"@babel/preset-typescript": "^7.16.5",
"@babel/register": "^7.16.0",
"@formatjs/cli": "^5.1.3",
"@types/jest": "^29.0.5",
"@typescript-eslint/eslint-plugin": "^5.48.0 ",
"@typescript-eslint/parser": "^5.48.0",
"babel-loader": "^9.1.2",
"copy-webpack-plugin": "^10.2.4",
"css-loader": "^6.7.3",
"eslint": "^8.4.1",
"eslint-config-airbnb-base": "^14.2.1",
"eslint-config-prettier": "^8.5.0",
"eslint-config-standard": "^17.0.0",
"eslint-nibble": "^8.0.0",
"eslint-plugin-cypress": "^2.12.1",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-react": "^7.31.10",
"eslint-plugin-react-hooks": "^4.6.0",
"html-webpack-plugin": "^5.3.2",
"husky": "^8.0.0",
"jest": "^29.3.1",
"jest-diff": "^29.3.1",
"jest-environment-jsdom": "^29.3.1",
"jest-webpack": "^0.5.1",
"lerna": "^3.16.4", "lerna": "^3.16.4",
"lint-staged": "^10.5.4" "lint-staged": "^10.5.4",
"prettier": "^2.7.1",
"start-server-and-test": "^1.14.0",
"style-loader": "^3.3.1",
"ts-jest": "^29.0.5",
"ts-loader": "^9.4.2",
"ts-node": "^10.9.1",
"typescript": "^4.8.4",
"webpack": "^5.75.0",
"webpack-bundle-analyzer": "^4.5.0",
"webpack-cli": "^5.0.1",
"webpack-dev-server": "^4.11.1"
}, },
"workspaces": [ "workspaces": [
"packages/*" "packages/*"
@ -57,8 +93,8 @@
] ]
}, },
"eslintConfig": { "eslintConfig": {
"rules": { "rules": {
"implicit-arrow-linebreak": "off" "implicit-arrow-linebreak": "off"
} }
} }
} }

View File

@ -1,14 +0,0 @@
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": false,
"targets": {
"esmodules": true
}
}
]
],
"sourceType": "module"
}

View File

@ -4,7 +4,7 @@
"description": "WiseMapping - Core Common Libraries", "description": "WiseMapping - Core Common Libraries",
"homepage": "http://www.wisemapping.org/", "homepage": "http://www.wisemapping.org/",
"license": "MIT", "license": "MIT",
"main": "dist/core.js", "main": "src/index.ts",
"files": [ "files": [
"src" "src"
], ],
@ -17,18 +17,7 @@
}, },
"scripts": { "scripts": {
"build": "webpack --config webpack.prod.js", "build": "webpack --config webpack.prod.js",
"dev": "webpack --mode development --config webpack.dev.js" "dev": "webpack --mode development --config webpack.dev.js",
}, "bootstrap": "yalc publish"
"private": false, }
"devDependencies": {
"@babel/core": "^7.18.13",
"@babel/preset-env": "^7.14.7",
"babel-loader": "^8.2.2",
"clean-webpack-plugin": "^4.0.0-alpha.0",
"core-js": "^3.15.2",
"webpack": "^5.74.0",
"webpack-cli": "^4.7.2",
"webpack-merge": "^5.8.0"
},
"dependencies": {}
} }

View File

@ -1,93 +0,0 @@
/*
* Copyright [2015] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Cross-browser implementation of creating an XML document object.
*/
export const createDocument = function () {
var doc = null;
if ($defined(window.ActiveXObject)) {
//http://blogs.msdn.com/b/xmlteam/archive/2006/10/23/using-the-right-version-of-msxml-in-internet-explorer.aspx
var progIDs = ['Msxml2.DOMDocument.6.0', 'Msxml2.DOMDocument.3.0'];
for (var i = 0; i < progIDs.length; i++) {
try {
doc = new ActiveXObject(progIDs[i]);
break;
} catch (ex) {}
}
} else if (window.document.implementation && window.document.implementation.createDocument) {
doc = window.document.implementation.createDocument('', '', null);
}
$assert(doc, 'Parser could not be instantiated');
return doc;
};
/*
Function: $defined
Returns true if the passed in value/object is defined, that means is not null or undefined.
Arguments:
obj - object to inspect
*/
export const $defined = function (obj) {
return obj != undefined;
};
export const $assert = function (assert, message) {
if (!$defined(assert) || !assert) {
logStackTrace();
console.log(message);
throw new Error(message);
}
};
export const sign = function (value) {
return value >= 0 ? 1 : -1;
};
export function logStackTrace(exception) {
if (!$defined(exception)) {
try {
throw Error('Unexpected Exception');
} catch (e) {
exception = e;
}
}
var result = '';
if (exception.stack) {
//Firefox and Chrome...
result = exception.stack;
} else if (window.opera && exception.message) {
//Opera
result = exception.message;
} else {
//IE and Safari
result = exception.sourceURL + ': ' + exception.line + '\n\n';
var currentFunction = arguments.callee.caller;
while (currentFunction) {
var fn = currentFunction.toString();
result = result + '\n' + fn;
currentFunction = currentFunction.caller;
}
}
window.errorStack = result;
return result;
}

View File

@ -0,0 +1,45 @@
/*
* Copyright [2015] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export const createDocument = (): Document => {
var doc: Document | null = null;
if (window.document.implementation?.createDocument) {
doc = window.document.implementation.createDocument('', '', null);
}
if (!doc) {
throw new Error('Document could not be initialized');
}
return doc;
};
export const $defined = (obj: any) => {
return obj != undefined && obj != null;
};
export const $assert = (assert, message: string): void => {
if (!$defined(assert) || !assert) {
console.error(message);
throw new Error(message);
}
};
export const sign = (value: number): 1 | -1 => {
return value >= 0 ? 1 : -1;
};

View File

@ -0,0 +1,31 @@
{
"compilerOptions": {
"outDir": "./dist/",
"sourceMap": true,
"module": "amd",
"moduleResolution": "node",
"target": "es6",
"allowJs": true,
"strict": true,
"esModuleInterop": true,
"resolveJsonModule": true,
"declaration": true,
"strictNullChecks": true,
"noImplicitAny": false,
"noImplicitReturns": true,
"noImplicitThis": true,
"noUnusedLocals": true,
"strictFunctionTypes": true,
"rootDirs": [
"src",
]
},
"include": [
"src/**/*", "storybook/src/stories",
],
"exclude": [
"node_modules"
]
}

View File

@ -1,35 +1,15 @@
const path = require('path'); const path = require('path');
const { CleanWebpackPlugin } = require('clean-webpack-plugin'); const { merge } = require('webpack-merge');
const common = require('../../webpack.common');
module.exports = { const prodConfig = {
output: { output: {
path: path.resolve(__dirname, 'dist'), path: path.resolve(__dirname, 'dist'),
filename: 'core.js', filename: 'index.ts',
publicPath: '',
library: { library: {
type: 'umd', type: 'umd',
}, },
}, }
target: 'web',
optimization: {
usedExports: true,
},
module: {
rules: [
{
use: 'babel-loader',
test: /.js$/,
exclude: [/node_modules/],
},
],
},
resolve: {
extensions: ['.js'],
},
plugins: [
new CleanWebpackPlugin({
dangerouslyAllowCleanPatternsOutsideProject: true,
dry: false,
}),
],
}; };
module.exports = merge(common, prodConfig);

View File

@ -4,9 +4,15 @@ const common = require('./webpack.common');
const prodConfig = { const prodConfig = {
mode: 'production', mode: 'production',
devtool: 'source-map', devtool: 'source-map',
output: {
library: {
type: 'umd',
},
},
optimization: { optimization: {
splitChunks: { splitChunks: {
chunks: 'all', chunks: 'all',
usedExports: true,
}, },
}, },
}; };

View File

@ -7,8 +7,25 @@
"eslint:recommended", "eslint:recommended",
"prettier", "prettier",
"plugin:react/recommended", "plugin:react/recommended",
"plugin:@typescript-eslint/recommended" "plugin:@typescript-eslint/recommended",
"plugin:cypress/recommended"
], ],
"settings": {
"react": {
"version": "detect"
},
"import/resolver": {
"node": {
"extensions": [
".js",
".ts"
]
},
"webpack": {
"config": "./webpack.common.js"
}
}
},
"parser": "@typescript-eslint/parser", "parser": "@typescript-eslint/parser",
"parserOptions": { "parserOptions": {
"ecmaFeatures": { "ecmaFeatures": {
@ -29,7 +46,16 @@
"@typescript-eslint/no-explicit-any": "error", "@typescript-eslint/no-explicit-any": "error",
"@typescript-eslint/explicit-module-boundary-types": "error", "@typescript-eslint/explicit-module-boundary-types": "error",
"@typescript-eslint/no-unused-vars": "error", "@typescript-eslint/no-unused-vars": "error",
"react-hooks/rules-of-hooks": "error", // Checks rules of Hooks "react-hooks/rules-of-hooks": "off", // Checks rules of Hooks
"react-hooks/exhaustive-deps": "warn" // Checks effect dependencies "react-hooks/exhaustive-deps": "off", // Checks effect dependencies
"no-restricted-imports": [
"error",
{
"patterns": [
"@mui/*/*/*",
"!@mui/material/test-utils/*"
]
}
]
} }
} }

View File

@ -0,0 +1,6 @@
node_modules
public
dist
lang
coverage
*.json

View File

@ -0,0 +1,7 @@
{
"trailingComma": "all",
"tabWidth": 2,
"semi": true,
"singleQuote": true,
"printWidth": 100
}

View File

@ -1,25 +0,0 @@
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": false,
"targets": {
"esmodules": true
}
},
"@babel/preset-typescript",
]
],
"env": {
"test": {
"plugins": [
"transform-require-context"
],
},
},
"plugins": [
"@babel/plugin-proposal-class-properties"
],
"sourceType": "module"
}

View File

@ -2,14 +2,16 @@ import { defineConfig } from 'cypress';
export default defineConfig({ export default defineConfig({
projectId: 'it9g7s', projectId: 'it9g7s',
video: false, video: true,
videoUploadOnPasses: false, videoUploadOnPasses: false,
includeShadowDom: true, includeShadowDom: true,
viewportWidth: 1000,
viewportHeight: 660,
e2e: { e2e: {
// We've imported your old cypress plugins here. // We've imported your old cypress plugins here.
// You may want to clean this up later by importing these. // You may want to clean this up later by importing these.
setupNodeEvents(on, config) { setupNodeEvents(on, config) {
return require('./cypress/plugins/index.js')(on, config); return require('./cypress/plugins/index.ts')(on, config);
}, },
baseUrl: 'http://localhost:8081', baseUrl: 'http://localhost:8081',
}, },

View File

@ -1,24 +0,0 @@
context('Relationship Topics', () => {
beforeEach(() => {
cy.visit('/editor.html');
cy.reload();
cy.get('[test-id="30-11-relationship"]').first().click({ force: true });
});
it('Add Relationship', () => {
cy.contains('Features').first().click();
cy.get(`[aria-label="Add Relationship"]`).first().click();
cy.contains('Try it Now!').first().click();
cy.get('[test-id="11-15-relationship"]').first().click({ force: true });
cy.matchImageSnapshot('addRelationship');
});
it('Delete Relationship', () => {
cy.get('[test-id="11-15-relationship"]').click({ force: true });
cy.get('body').type('{backspace}');
cy.get('[test-id="11-15-relationship"]').should('not.exist');
cy.matchImageSnapshot('delete relationship');
});
});

View File

@ -0,0 +1,78 @@
/// <reference types="cypress" />
describe('Relationship Topics', () => {
beforeEach(() => {
// Remove storage for autosave ...
cy.visit('/editor.html');
cy.waitEditorLoaded();
});
it.skip('Add Relationship', () => {
// Create new relationship ...
cy.focusTopicByText('Features');
cy.onClickToolbarButton('Add Relationship');
cy.focusTopicByText('Try it Now!');
cy.get('[test-id="11-15-relationship"]').as('rel');
cy.get('@rel').click({ force: true });
cy.get('@rel').should('exist');
cy.matchImageSnapshot('addRelationship');
// Undo relationship ...
cy.get('[aria-label^="Undo ').eq(1).click();
cy.get('@rel').should('not.exist');
});
it('Delete Relationship', () => {
// Add new relationship ...
cy.focusTopicByText('Features');
cy.onClickToolbarButton('Add Relationship');
cy.focusTopicByText('Try it Now!');
// Delete it ...
cy.get('[test-id="11-15-relationship"]').as('rel');
cy.get('@rel').should('exist');
cy.get('@rel').click({ force: true });
cy.get('body').type('{backspace}');
cy.get('@rel').should('not.exist');
cy.matchImageSnapshot('delete relationship');
// Undo relationship ...
cy.triggerUndo();
cy.get('@rel').should('exist');
});
it('Change Control Point', () => {
// Create new relationship ...
cy.focusTopicByText('Features');
cy.onClickToolbarButton('Add Relationship');
cy.focusTopicByText('Try it Now!');
// Select relationship ...
cy.get('[test-id="11-15-relationship"]').as('rel');
cy.get('@rel').should('exist');
cy.get('@rel').click({ force: true });
// Move control point start ...
cy.get('[test-id="relctl:0:11-15"]').first().trigger('mousedown');
cy.get('body').trigger('mousemove', { clientX: 350, clientY: 380 });
cy.get('body').trigger('mouseup');
cy.matchImageSnapshot('move ctl pont 0');
// Move control point end ...
cy.get('[test-id="relctl:1:11-15"]').first().trigger('mousedown');
cy.get('body').trigger('mousemove', { clientX: 350, clientY: 100 });
cy.get('body').trigger('mouseup');
cy.matchImageSnapshot('move ctl pont 1');
// Test undo and redo ...
cy.triggerUndo();
cy.triggerUndo();
cy.get('@rel').should('exist');
cy.matchImageSnapshot('rel ctl undo');
});
});

View File

@ -0,0 +1,34 @@
/// <reference types="cypress" />
describe('Render all sample maps', () => {
[
'complex',
'emoji',
'emptyNodes',
'error-on-load',
'huge',
'huge2',
'icon-sample',
'img-support',
'order',
//'rel-error',
'sample1',
'sample2',
'sample3',
'welcome-prism',
'sample4',
'sample5',
'sample6',
'connection-style',
'sample8',
'welcome',
].forEach((mapId) => {
it(`Render map => ${mapId}`, () => {
cy.visit(`/viewmode.html?id=${mapId}`);
cy.waitEditorLoaded();
cy.get('svg > path').should('be.visible');
cy.get('[aria-label="vortex-loading"]', { timeout: 120000 }).should('not.exist');
cy.matchImageSnapshot(`map-${mapId}`);
});
});
});

View File

@ -0,0 +1,19 @@
/// <reference types="cypress" />
describe('Topic Copy and Paste Suite', () => {
beforeEach(() => {
// Remove storage for autosave ...
cy.visit('/editor.html');
cy.waitEditorLoaded();
cy.focusTopicById(2);
});
it('Copy and Paste', () => {
cy.get(`[aria-label="Topic Style"]`).first().trigger('mouseover');
cy.get('body').type('{meta}c');
// Copy & Paste require permissions. More reseach needed.
// cy.get('body').type('{meta}v');
// cy.get('[test-id=50]').click();
// cy.matchImageSnapshot('copyandpaste');
});
});

View File

@ -1,7 +1,9 @@
context('Change topic position', () => { /// <reference types="cypress" />
describe('Topic Drag and Drop', () => {
beforeEach(() => { beforeEach(() => {
// Remove storage for autosave ...
cy.visit('/editor.html'); cy.visit('/editor.html');
cy.reload(); cy.waitEditorLoaded();
}); });
it('Move up node "Mind Mapping"', () => { it('Move up node "Mind Mapping"', () => {

View File

@ -1,75 +0,0 @@
context('Edit Topic', () => {
// TODO: review why click({force: true}) is needed in these tests
// also, why is the element outside the viewport in screenshots?
beforeEach(() => {
cy.visit('/editor.html');
cy.reload();
cy.get('[test-id=1]').click();
});
it('Change Main Topic Text', () => {
cy.get('body').type('New Title Main Topic{enter}');
cy.get('[test-id=1] > text > tspan').should('have.text', 'New Title Main Topic');
cy.matchImageSnapshot('changeMainTopicText');
});
it('Change Font Size', () => {
// Go to the minimal size.
cy.get(`[aria-label="Font Style"]`).first().trigger('mouseover');
cy.get(`[aria-label="Smaller"]`).first().click();
cy.get(`[aria-label="Smaller"]`).first().click();
// cy.get('[test-id=1] > text').invoke('attr', 'font-size').should('eq', '8.1');
cy.matchImageSnapshot('changeFontSizeSmall');
cy.get(`[aria-label="Font Style"]`).first().trigger('mouseover');
cy.get(`[aria-label="Bigger"]`).first().click();
// cy.get('[test-id=1] > text').invoke('attr', 'font-size').should('eq', '10.8');
cy.matchImageSnapshot('changeFontSizeNormal');
cy.get(`[aria-label="Font Style"]`).first().trigger('mouseover');
cy.get(`[aria-label="Bigger"]`).first().click();
// cy.get('[test-id=1] > text').invoke('attr', 'font-size').should('eq', '13.4');
cy.matchImageSnapshot('changeFontSizeLarge');
cy.get(`[aria-label="Font Style"]`).first().trigger('mouseover');
cy.get(`[aria-label="Bigger"]`).first().click();
// cy.get('[test-id=1] > text').invoke('attr', 'font-size').should('eq', '20.2');
cy.matchImageSnapshot('changeFontSizeHuge');
// Can not scale it more.
cy.get(`[aria-label="Bigger"]`).first().click();
// cy.get('[test-id=1] > text').invoke('attr', 'font-size').should('eq', '20.2');
cy.matchImageSnapshot('changeFontSizeHuge');
});
// it('Change Font To Italic', () => {
// cy.get(`[aria-label="Font Style"]`).trigger('mouseover');
// cy.contains(`[data-test-id="FormactItalicIcon"]`).click();
// cy.get('[test-id=1] > text').invoke('attr', 'font-family').should('eq', 'Times');
// cy.matchImageSnapshot('changeFontType');
// });
// it('Change Font Italic', () => {
// cy.get(`[aria-label="Font Style"]`).trigger('mouseover');
// cy.contains('[data-testid="FormatItalicIcon"]').click();
// cy.get('[test-id=1] > text').invoke('attr', 'font-style').should('eq', 'italic');
// cy.matchImageSnapshot('changeFontItalic');
// });
// it('Change Font color', () => {
// cy.get('#fontColorTip').click();
// cy.get('[title="RGB (153, 0, 255)"]').click({ force: true });
// cy.get('[test-id=1] > text').invoke('attr', 'fill').should('eq', 'rgb(153, 0, 255)');
// cy.matchImageSnapshot('changeFontColor');
// });
});

View File

@ -0,0 +1,82 @@
/// <reference types="cypress" />
describe('Topic Font Suite', () => {
beforeEach(() => {
// Remove storage for autosave ...
cy.visit('/editor.html');
cy.waitEditorLoaded();
cy.focusTopicById(1);
});
it('Open Font Shape Panel', () => {
cy.onMouseOverToolbarButton('Font Style');
cy.matchImageSnapshot('fontShapePanel');
});
it('Change Main Topic Text', () => {
cy.get('body').type('New Title Main Topic{enter}');
cy.get('[test-id=1] > text > tspan').should('have.text', 'New Title Main Topic');
cy.focusTopicByText('Mind Mapping');
cy.matchImageSnapshot('changeMainTopicText');
});
it('Change Font Size', () => {
// Go to the minimal size.
cy.onMouseOverToolbarButton('Font Style');
cy.get('[aria-label="Smaller"]').as('smaller');
cy.get('@smaller').eq(1).click();
cy.get('@smaller').eq(1).click();
cy.get('[test-id=1] > text').invoke('attr', 'font-size').should('eq', '8.1');
cy.matchImageSnapshot('changeFontSizeSmall');
cy.get('[aria-label="Bigger"]').as('bigger');
cy.get('@bigger').eq(1).click();
cy.matchImageSnapshot('changeFontSizeNormal');
cy.get('@bigger').eq(1).click();
cy.get('[test-id=1] > text').invoke('attr', 'font-size').should('eq', '13.4');
cy.matchImageSnapshot('changeFontSizeLarge');
cy.get('@bigger').eq(1).click();
cy.get('[test-id=1] > text').invoke('attr', 'font-size').should('eq', '20.2');
cy.matchImageSnapshot('changeFontSizeHuge');
cy.get('@bigger').eq(1).click();
cy.get('[test-id=1] > text').invoke('attr', 'font-size').should('eq', '20.2');
cy.matchImageSnapshot('changeFontSizeHuge');
});
it('Change Font To Italic', () => {
cy.onMouseOverToolbarButton('Font Style');
cy.get('[aria-label^="Italic ').first().click();
cy.get('[test-id=1] > text').invoke('attr', 'font-style').should('eq', 'italic');
cy.contains('Mind Mapping').click({ force: true });
cy.matchImageSnapshot('changeFontItalic');
});
it('Change Font to Bold', () => {
cy.onMouseOverToolbarButton('Font Style');
cy.get('[aria-label^="Bold ').first().click();
cy.get('[test-id=1] > text').invoke('attr', 'font-weight').should('eq', 'normal');
cy.contains('Mind Mapping').click({ force: true });
cy.matchImageSnapshot('changeFontBold');
});
it('Change Font Color', () => {
cy.onMouseOverToolbarButton('Font Style');
cy.get('[aria-label="Color"]').eq(1).click();
cy.get('[title="#cc0000"]').click({ force: true });
cy.get('[test-id=1] > text').invoke('attr', 'fill').should('eq', '#cc0000');
cy.focusTopicByText('Mind Mapping');
cy.matchImageSnapshot('changeFontColor');
});
});

View File

@ -0,0 +1,23 @@
/// <reference types="cypress" />
describe('Topic Icon Suite', () => {
beforeEach(() => {
cy.visit('/editor.html');
cy.waitEditorLoaded();
});
it('Open panel', () => {
cy.onClickToolbarButton('Add Icon');
// Icon images must be loaded. No better solution than wait.
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(5000);
cy.matchImageSnapshot('icons-pannel');
});
it('Add new icon', () => {
cy.focusTopicById(3);
cy.onClickToolbarButton('Add Icon');
cy.get('[aria-label="grinning"]').click();
cy.matchImageSnapshot('add-new-icon');
});
});

View File

@ -1,30 +1,32 @@
context('Node manager', () => { /// <reference types="cypress" />
before(() => { describe('Node manager', () => {
beforeEach(() => {
cy.visit('/editor.html'); cy.visit('/editor.html');
cy.waitEditorLoaded();
// Select root node ...
cy.focusTopicByText('Mind Mapping');
}); });
it('shortcut add sibling node', () => { it('shortcut add sibling node', () => {
cy.contains('Mind Mapping').click();
cy.get('body').type('{enter}').type('Mind Mapping rocks!!').type('{enter}'); cy.get('body').type('{enter}').type('Mind Mapping rocks!!').type('{enter}');
cy.get('[test-id=36] > text > tspan').should('exist'); cy.get('[test-id=36] > text > tspan').should('exist');
cy.matchImageSnapshot('editor-shortcut-edit'); cy.matchImageSnapshot('editor-shortcut-edit');
}); });
it('shortcut add child node', () => { it('shortcut add child node', () => {
cy.contains('Mind Mapping rocks!!').click();
cy.get('body').type('{insert}').type('Child 1 mind Mapping rocks!!').type('{enter}'); cy.get('body').type('{insert}').type('Child 1 mind Mapping rocks!!').type('{enter}');
cy.get('body').type('{enter}').type('Child 2 mind Mapping rocks!!').type('{enter}'); cy.get('body').type('{enter}').type('Child 2 mind Mapping rocks!!').type('{enter}');
cy.get('[test-id=36] > text > tspan').should('exist'); cy.focusTopicById(36);
cy.get('[test-id=37] > text > tspan').should('exist'); cy.focusTopicById(37);
cy.matchImageSnapshot('addChildNodeSortcut'); cy.matchImageSnapshot('addChildNodeSortcut');
}); });
it('Delete topic', () => { it('Delete topic', () => {
cy.get('[test-id=37]').click(); cy.get('body').type('{enter}').type('Mind Mapping rocks!!').type('{enter}');
cy.focusTopicById(36);
cy.get('body').type('{del}'); cy.get('body').type('{del}');
cy.get('[test-id=37]').should('not.exist'); cy.get('[test-id=37]').should('not.exist');
@ -33,23 +35,26 @@ context('Node manager', () => {
}); });
it('undo changes', () => { it('undo changes', () => {
cy.get('[data-testid="UndoOutlinedIcon"]').click(); cy.get('body').type('{enter}').type('Mind Mapping rocks!!').type('{enter}');
cy.focusTopicByText('Mind Mapping rocks!!');
cy.get('[test-id=36] > text > tspan').should('exist'); cy.triggerUndo();
cy.matchImageSnapshot('undoChange'); cy.matchImageSnapshot('undoChange');
}); });
it('redo changes', () => { it('redo changes', () => {
cy.get('[data-testid="RedoOutlinedIcon"]').click(); cy.get('body').type('{enter}').type('Mind Mapping rocks!!').type('{enter}');
cy.get('[test-id=36] > text > tspan').should('exist'); cy.focusTopicByText('Mind Mapping rocks!!');
cy.triggerUndo();
cy.triggerRedo();
cy.focusTopicByText('Mind Mapping rocks!!');
cy.matchImageSnapshot('redoChange'); cy.matchImageSnapshot('redoChange');
}); });
it('Save changes', () => { it('save changes', () => {
cy.contains('Mind Mapping rocks!!').click();
cy.get('body').type('{ctrl}s'); cy.get('body').type('{ctrl}s');
cy.matchImageSnapshot('saveChagesShortcut'); cy.matchImageSnapshot('saveChagesShortcut');
}); });
}); });

View File

@ -1,51 +0,0 @@
context('Change Topic shape', () => {
beforeEach(() => {
cy.visit('/editor.html');
cy.reload();
cy.contains('Try it Now!').click();
});
it('change to square shape', () => {
cy.get(`[aria-label="Topic Style"]`).first().trigger('mouseover');
cy.get(`[aria-label="Rectangle shape"]`).first().click();
cy.get('[test-id=11] > rect').eq(1).invoke('attr', 'rx').then(parseInt).should('be.a', 'number').should('eq', 0);
cy.matchImageSnapshot('changeToSquareShape');
});
it('change to rounded rectangle', () => {
cy.contains('Mind Mapping').click();
cy.get(`[aria-label="Topic Style"]`).first().trigger('mouseover');
cy.get(`[aria-label="Rounded shape"]`).first().click();
// Todo: Check how to validate this. Difference when it run in docker vs test:integration
cy.get('[test-id=6] > rect').eq(1).invoke('attr', 'rx').then(parseInt).should('be.a', 'number').should('be.gte', 4);
cy.get('[test-id=6] > rect').eq(1).invoke('attr', 'rx').then(parseInt).should('be.a', 'number').should('be.lt', 5);
cy.matchImageSnapshot('changeToRoundedRectangle');
});
it('change to line', () => {
cy.contains('Try it Now!').click();
cy.get(`[aria-label="Topic Style"]`).first().trigger('mouseover');
cy.get(`[aria-label="Line shape"]`).first().click();
cy.matchImageSnapshot('changeToLine');
});
it('change to ellipse shape', () => {
cy.contains('Productivity').click();
cy.get(`[aria-label="Topic Style"]`).first().trigger('mouseover');
cy.get(`[aria-label="Ellipse shape"]`).first().click();
// Todo: Check how to validate this. Difference when it run in docker vs test:integration
cy.get('[test-id=2] > rect').eq(1).invoke('attr', 'rx').then(parseInt).should('be.a', 'number').should('be.gte', 12);
cy.get('[test-id=2] > rect').eq(1).invoke('attr', 'rx').then(parseInt).should('be.a', 'number').should('be.lt', 15);
cy.matchImageSnapshot('changeToEllipseShape');
});
});

View File

@ -0,0 +1,88 @@
/// <reference types="cypress" />
describe('Topic Shape Suite', () => {
beforeEach(() => {
cy.visit('/editor.html');
// Wait all has been loaded ...
cy.waitEditorLoaded();
// Select one node ...
cy.focusTopicByText('Try it Now!');
});
it('open shape', () => {
cy.onMouseOverToolbarButton('Topic Style');
cy.matchImageSnapshot('topicShapePanel');
});
it('change to square shape', () => {
cy.onMouseOverToolbarButton('Topic Style');
cy.get(`[aria-label="Rectangle shape"]`).first().click();
cy.get('[test-id=11] > rect')
.eq(1)
.invoke('attr', 'rx')
.then(parseInt)
.should('be.a', 'number')
.should('eq', 0);
cy.focusTopicByText('Mind Mapping');
cy.matchImageSnapshot('changeToSquareShape');
});
it('change to rounded rectangle', () => {
cy.focusTopicByText('Mind Mapping');
cy.onMouseOverToolbarButton('Topic Style');
cy.get(`[aria-label="Rounded shape"]`).first().click();
// Todo: Check how to validate this. Difference when it run in docker vs test:integration
cy.get('[test-id=6] > rect')
.eq(1)
.invoke('attr', 'rx')
.then(parseInt)
.should('be.a', 'number')
.should('be.gte', 4);
cy.get('[test-id=6] > rect')
.eq(1)
.invoke('attr', 'rx')
.then(parseInt)
.should('be.a', 'number')
.should('be.gte', 8);
cy.focusTopicByText('Mind Mapping');
cy.matchImageSnapshot('changeToRoundedRectangle');
});
it('change to line', () => {
cy.onMouseOverToolbarButton('Topic Style');
cy.get(`[aria-label="Line shape"]`).first().click();
cy.focusTopicByText('Mind Mapping');
cy.matchImageSnapshot('changeToLine');
});
it('change to ellipse shape', () => {
cy.focusTopicByText('Productivity');
cy.onMouseOverToolbarButton('Topic Style');
cy.get(`[aria-label="Ellipse shape"]`).first().click();
// Todo: Check how to validate this. Difference when it run in docker vs test:integration
cy.get('[test-id=2] > rect')
.eq(1)
.invoke('attr', 'rx')
.then(parseInt)
.should('be.a', 'number')
.should('be.gte', 11);
cy.get('[test-id=2] > rect')
.eq(1)
.invoke('attr', 'rx')
.then(parseInt)
.should('be.a', 'number')
.should('be.lt', 15);
cy.focusTopicByText('Mind Mapping');
cy.matchImageSnapshot('changeToEllipseShape');
});
});

View File

@ -1,5 +0,0 @@
{
"name": "Using fixtures to represent data",
"email": "hello@cypress.io",
"body": "Fixtures are a great way to mock data for responses to routes"
}

View File

@ -12,7 +12,7 @@
// This function is called when a project is opened or re-opened (e.g. due to // This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing) // the project's config changing)
const { addMatchImageSnapshotPlugin } = require('cypress-image-snapshot/plugin'); import { addMatchImageSnapshotPlugin } from 'cypress-image-snapshot/plugin';
/** /**
* @type {Cypress.PluginConfig} * @type {Cypress.PluginConfig}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

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