diff --git a/core/.eslintignore b/core/.eslintignore new file mode 100644 index 00000000..3c3629e6 --- /dev/null +++ b/core/.eslintignore @@ -0,0 +1 @@ +node_modules diff --git a/core/.eslintrc.json b/core/.eslintrc.json index 460a1b58..4561ace9 100644 --- a/core/.eslintrc.json +++ b/core/.eslintrc.json @@ -1,12 +1,12 @@ { "root": true, "ignorePatterns": ["**/*"], - "plugins": ["@nrwl/nx"], + "plugins": ["@nx"], "overrides": [ { "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], "rules": { - "@nrwl/nx/enforce-module-boundaries": [ + "@nx/enforce-module-boundaries": [ "off", { "enforceBuildableLibDependency": true, @@ -23,7 +23,7 @@ }, { "files": ["*.ts", "*.tsx"], - "extends": ["plugin:@nrwl/nx/typescript"], + "extends": ["plugin:@nx/typescript"], "rules": { "no-prototype-builtins": "off", "@typescript-eslint/no-explicit-any": "off", @@ -41,7 +41,7 @@ }, { "files": ["*.js", "*.jsx"], - "extends": ["plugin:@nrwl/nx/javascript"], + "extends": ["plugin:@nx/javascript"], "rules": {} } ] diff --git a/core/angular.json b/core/angular.json deleted file mode 100644 index c887c793..00000000 --- a/core/angular.json +++ /dev/null @@ -1,507 +0,0 @@ -{ - "version": 1, - "projects": { - "ame": { - "projectType": "application", - "root": "apps/ame", - "sourceRoot": "apps/ame/src", - "prefix": "ame", - "architect": { - "build": { - "builder": "@angular-devkit/build-angular:browser", - "outputs": ["{options.outputPath}"], - "options": { - "outputPath": "dist/apps/ame", - "index": "apps/ame/src/index.html", - "main": "apps/ame/src/main.ts", - "polyfills": "apps/ame/src/polyfills.ts", - "tsConfig": "apps/ame/tsconfig.app.json", - "inlineStyleLanguage": "scss", - "assets": [ - "apps/ame/src/assets", - { - "glob": "**/*", - "input": "./node_modules/mxgraph/javascript/src", - "output": "apps/ame/src/assets/mxgraph" - } - ], - "styles": ["node_modules/ngx-toastr/toastr.css", "apps/ame/src/styles.scss"], - "scripts": ["node_modules/mxgraph/javascript/mxClient.js", "apps/ame/src/assets/samm-units.js"], - "allowedCommonJsDependencies": ["file-saver", "urn-lib", "mxgraph-factory", "locale-codes", "rdf-parse", "streamify-string"] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "4mb", - "maximumError": "6mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "10kb", - "maximumError": "20kb" - } - ], - "fileReplacements": [ - { - "replace": "environments/environment.ts", - "with": "environments/environment.prod.ts" - } - ], - "outputHashing": "all", - "optimization": { - "scripts": true, - "styles": true, - "fonts": false - } - }, - "development": { - "buildOptimizer": false, - "optimization": false, - "vendorChunk": true, - "extractLicenses": true, - "sourceMap": true, - "namedChunks": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "builder": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "browserTarget": "ame:build:production" - }, - "development": { - "browserTarget": "ame:build:development" - } - }, - "defaultConfiguration": "development" - }, - "serve-coverage": { - "builder": "ngx-build-plus:dev-server", - "configurations": { - "production": { - "browserTarget": "ame:build:production" - }, - "development": { - "browserTarget": "ame:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "builder": "@angular-devkit/build-angular:extract-i18n", - "options": { - "browserTarget": "ame:build" - } - }, - "lint": { - "builder": "@nrwl/linter:eslint", - "options": { - "lintFilePatterns": ["apps/ame/src/**/*.ts", "apps/ame/src/**/*.html"] - } - }, - "test": { - "builder": "@nrwl/jest:jest", - "outputs": ["coverage/apps/ame"], - "options": { - "jestConfig": "apps/ame/jest.config.js", - "passWithNoTests": true - } - } - } - }, - "ame-e2e": { - "root": "apps/ame-e2e", - "sourceRoot": "apps/ame-e2e/src", - "projectType": "application", - "architect": { - "e2e": { - "builder": "@nrwl/cypress:cypress", - "options": { - "cypressConfig": "cypress.config.js", - "devServerTarget": "ame:serve:development", - "tsConfig": "apps/ame-e2e/tsconfig.cypress.json" - }, - "configurations": { - "production": { - "devServerTarget": "ame:serve-coverage:production" - } - } - }, - "lint": { - "builder": "@nrwl/linter:eslint", - "outputs": ["{options.outputFile}"], - "options": { - "lintFilePatterns": ["apps/ame-e2e/**/*.{js,ts}"] - } - } - } - }, - "api": { - "projectType": "library", - "root": "libs/api", - "sourceRoot": "libs/api/src", - "prefix": "ame", - "architect": { - "test": { - "builder": "@nrwl/jest:jest", - "outputs": ["coverage/libs/api"], - "options": { - "jestConfig": "libs/api/jest.config.js", - "passWithNoTests": true - } - }, - "lint": { - "builder": "@nrwl/linter:eslint", - "options": { - "lintFilePatterns": ["libs/api/src/**/*.ts", "libs/api/src/**/*.html"] - } - } - } - }, - "aspect-exporter": { - "projectType": "library", - "root": "libs/aspect-exporter", - "sourceRoot": "libs/aspect-exporter/src", - "prefix": "ame", - "architect": { - "test": { - "builder": "@nrwl/jest:jest", - "outputs": ["coverage/libs/aspect-exporter"], - "options": { - "jestConfig": "libs/aspect-exporter/jest.config.js", - "passWithNoTests": true - } - }, - "lint": { - "builder": "@nrwl/linter:eslint", - "options": { - "lintFilePatterns": ["libs/aspect-exporter/src/**/*.ts", "libs/aspect-exporter/src/**/*.html"] - } - } - } - }, - "cache": { - "projectType": "library", - "root": "libs/cache", - "sourceRoot": "libs/cache/src", - "prefix": "ame", - "architect": { - "test": { - "builder": "@nrwl/jest:jest", - "outputs": ["coverage/libs/cache"], - "options": { - "jestConfig": "libs/cache/jest.config.js", - "passWithNoTests": true - } - }, - "lint": { - "builder": "@nrwl/linter:eslint", - "options": { - "lintFilePatterns": ["libs/cache/src/**/*.ts", "libs/cache/src/**/*.html"] - } - } - } - }, - "connection": { - "projectType": "library", - "root": "libs/connection", - "sourceRoot": "libs/connection/src", - "prefix": "ame", - "architect": { - "test": { - "builder": "@nrwl/jest:jest", - "outputs": ["coverage/libs/connection"], - "options": { - "jestConfig": "libs/connection/jest.config.js", - "passWithNoTests": true - } - }, - "lint": { - "builder": "@nrwl/linter:eslint", - "options": { - "lintFilePatterns": ["libs/connection/src/**/*.ts", "libs/connection/src/**/*.html"] - } - } - } - }, - "editor": { - "projectType": "library", - "root": "libs/editor", - "sourceRoot": "libs/editor/src", - "prefix": "ame", - "architect": { - "test": { - "builder": "@nrwl/jest:jest", - "outputs": ["coverage/libs/editor"], - "options": { - "jestConfig": "libs/editor/jest.config.js", - "passWithNoTests": true - } - }, - "lint": { - "builder": "@nrwl/linter:eslint", - "options": { - "lintFilePatterns": ["libs/editor/src/**/*.ts", "libs/editor/src/**/*.html"] - } - } - } - }, - "instantiator": { - "projectType": "library", - "root": "libs/instantiator", - "sourceRoot": "libs/instantiator/src", - "prefix": "ame", - "architect": { - "test": { - "builder": "@nrwl/jest:jest", - "outputs": ["coverage/libs/instantiator"], - "options": { - "jestConfig": "libs/instantiator/jest.config.js", - "passWithNoTests": true - } - }, - "lint": { - "builder": "@nrwl/linter:eslint", - "options": { - "lintFilePatterns": ["libs/instantiator/src/**/*.ts", "libs/instantiator/src/**/*.html"] - } - } - } - }, - "loader-filters": { - "projectType": "library", - "root": "libs/loader-filters", - "sourceRoot": "libs/loader-filters/src", - "prefix": "ame", - "architect": { - "test": { - "builder": "@nrwl/jest:jest", - "outputs": ["coverage/libs/loader-filters"], - "options": { - "jestConfig": "libs/loader-filters/jest.config.js", - "passWithNoTests": true - } - }, - "lint": { - "builder": "@nrwl/linter:eslint", - "options": { - "lintFilePatterns": ["libs/loader-filters/src/**/*.ts", "libs/loader-filters/src/**/*.html"] - } - } - } - }, - "meta-model": { - "projectType": "library", - "root": "libs/meta-model", - "sourceRoot": "libs/meta-model/src", - "prefix": "ame", - "architect": { - "test": { - "builder": "@nrwl/jest:jest", - "outputs": ["coverage/libs/meta-model"], - "options": { - "jestConfig": "libs/meta-model/jest.config.js", - "passWithNoTests": true - } - }, - "lint": { - "builder": "@nrwl/linter:eslint", - "options": { - "lintFilePatterns": ["libs/meta-model/src/**/*.ts", "libs/meta-model/src/**/*.html"] - } - } - } - }, - "migrator": { - "projectType": "library", - "root": "libs/migrator", - "sourceRoot": "libs/migrator/src", - "prefix": "ame", - "architect": { - "test": { - "builder": "@nrwl/jest:jest", - "outputs": ["coverage/libs/migrator"], - "options": { - "jestConfig": "libs/migrator/jest.config.js", - "passWithNoTests": true - } - }, - "lint": { - "builder": "@nrwl/linter:eslint", - "options": { - "lintFilePatterns": ["libs/migrator/src/**/*.ts", "libs/migrator/src/**/*.html"] - } - } - } - }, - "mx-graph": { - "projectType": "library", - "root": "libs/mx-graph", - "sourceRoot": "libs/mx-graph/src", - "prefix": "ame", - "architect": { - "test": { - "builder": "@nrwl/jest:jest", - "outputs": ["coverage/libs/mx-graph"], - "options": { - "jestConfig": "libs/mx-graph/jest.config.js", - "passWithNoTests": true - } - }, - "lint": { - "builder": "@nrwl/linter:eslint", - "options": { - "lintFilePatterns": ["libs/mx-graph/src/**/*.ts", "libs/mx-graph/src/**/*.html"] - } - } - } - }, - "namespace-manager": { - "projectType": "library", - "root": "libs/namespace-manager", - "sourceRoot": "libs/namespace-manager/src", - "prefix": "ame", - "architect": { - "test": { - "builder": "@nrwl/jest:jest", - "outputs": ["coverage/libs/namespace-manager"], - "options": { - "jestConfig": "libs/namespace-manager/jest.config.js", - "passWithNoTests": true - } - }, - "lint": { - "builder": "@nrwl/linter:eslint", - "options": { - "lintFilePatterns": ["libs/namespace-manager/src/**/*.ts", "libs/namespace-manager/src/**/*.html"] - } - } - } - }, - "rdf": { - "projectType": "library", - "root": "libs/rdf", - "sourceRoot": "libs/rdf/src", - "prefix": "ame", - "architect": { - "test": { - "builder": "@nrwl/jest:jest", - "outputs": ["coverage/libs/rdf"], - "options": { - "jestConfig": "libs/rdf/jest.config.js", - "passWithNoTests": true - } - }, - "lint": { - "builder": "@nrwl/linter:eslint", - "options": { - "lintFilePatterns": ["libs/rdf/src/**/*.ts", "libs/rdf/src/**/*.html"] - } - } - } - }, - "settings-dialog": { - "projectType": "library", - "root": "libs/settings-dialog", - "sourceRoot": "libs/settings-dialog/src", - "prefix": "ame", - "architect": { - "test": { - "builder": "@nrwl/jest:jest", - "outputs": ["coverage/libs/settings-dialog"], - "options": { - "jestConfig": "libs/settings-dialog/jest.config.js", - "passWithNoTests": true - } - }, - "lint": { - "builder": "@nrwl/linter:eslint", - "options": { - "lintFilePatterns": ["libs/settings-dialog/src/**/*.ts", "libs/settings-dialog/src/**/*.html"] - } - } - } - }, - "shared": { - "projectType": "library", - "root": "libs/shared", - "sourceRoot": "libs/shared/src", - "prefix": "ame", - "architect": { - "test": { - "builder": "@nrwl/jest:jest", - "outputs": ["coverage/libs/shared"], - "options": { - "jestConfig": "libs/shared/jest.config.js", - "passWithNoTests": true - } - }, - "lint": { - "builder": "@nrwl/linter:eslint", - "options": { - "lintFilePatterns": ["libs/shared/src/**/*.ts", "libs/shared/src/**/*.html"] - } - } - } - }, - "utils": { - "root": "libs/utils", - "sourceRoot": "libs/utils/src", - "projectType": "library", - "architect": { - "build": { - "builder": "@nrwl/js:tsc", - "outputs": ["{options.outputPath}"], - "options": { - "outputPath": "dist/libs/utils", - "main": "libs/utils/src/index.ts", - "tsConfig": "libs/utils/tsconfig.lib.json", - "assets": ["libs/utils/*.md"] - } - }, - "lint": { - "builder": "@nrwl/linter:eslint", - "outputs": ["{options.outputFile}"], - "options": { - "lintFilePatterns": ["libs/utils/**/*.ts"] - } - }, - "test": { - "builder": "@nrwl/jest:jest", - "outputs": ["coverage/libs/utils"], - "options": { - "jestConfig": "libs/utils/jest.config.ts", - "passWithNoTests": true - } - } - }, - "tags": [] - }, - "vocabulary": { - "projectType": "library", - "root": "libs/vocabulary", - "sourceRoot": "libs/vocabulary/src", - "prefix": "ame", - "architect": { - "test": { - "builder": "@nrwl/jest:jest", - "outputs": ["coverage/libs/vocabulary"], - "options": { - "jestConfig": "libs/vocabulary/jest.config.js", - "passWithNoTests": true - } - }, - "lint": { - "builder": "@nrwl/linter:eslint", - "options": { - "lintFilePatterns": ["libs/vocabulary/src/**/*.ts", "libs/vocabulary/src/**/*.html"] - } - } - } - } - } -} diff --git a/core/apps/ame-e2e/src/fixtures/default-models/aspect-default.txt b/core/apps/ame-e2e/src/fixtures/default-models/aspect-default.txt new file mode 100644 index 00000000..67ba043b --- /dev/null +++ b/core/apps/ame-e2e/src/fixtures/default-models/aspect-default.txt @@ -0,0 +1,30 @@ +# Copyright (c) 2023 Robert Bosch Manufacturing Solutions GmbH +# +# See the AUTHORS file(s) distributed with this work for +# additional information regarding authorship. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at https://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 + +@prefix samm: . +@prefix samm-c: . +@prefix samm-e: . +@prefix unit: . +@prefix rdf: . +@prefix rdfs: . +@prefix xsd: . +@prefix : . + +:AspectDefault a samm:Aspect ; + samm:properties (:property1) ; + samm:operations (); + samm:events () . + +:property1 a samm:Property; + samm:characteristic :Characteristic1 . + +:Characteristic1 a samm:Characteristic ; + samm:dataType xsd:string . diff --git a/core/apps/ame-e2e/src/fixtures/default-models/movement.txt b/core/apps/ame-e2e/src/fixtures/default-models/movement.txt new file mode 100644 index 00000000..7bcb8b8d --- /dev/null +++ b/core/apps/ame-e2e/src/fixtures/default-models/movement.txt @@ -0,0 +1,117 @@ +# Copyright (c) 2023 Robert Bosch Manufacturing Solutions GmbH +# +# See the AUTHORS file(s) distributed with this work for +# additional information regarding authorship. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at https://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 + +@prefix samm: . +@prefix samm-c: . +@prefix samm-e: . +@prefix unit: . +@prefix rdf: . +@prefix rdfs: . +@prefix xsd: . +@prefix : . + +:Movement a samm:Aspect ; + samm:name "Movement" ; + samm:preferredName "movement"@en ; + samm:description "Aspect for movement information"@en ; + samm:properties ( :isMoving :position :speed :speedLimitWarning ) ; + samm:operations ( ) ; + samm:events ( ) . + +:isMoving a samm:Property ; + samm:name "isMoving" ; + samm:preferredName "is moving"@en ; + samm:description "Flag indicating whether the asset is currently moving"@en ; + samm:characteristic samm-c:Boolean . + +:position a samm:Property ; + samm:name "position" ; + samm:preferredName "position"@en ; + samm:description "Indicates a position"@en ; + samm:characteristic :SpatialPositionCharacteristic . + +:speed a samm:Property ; + samm:name "speed" ; + samm:preferredName "speed"@en ; + samm:description "speed of vehicle"@en ; + samm:characteristic :Speed . + +:speedLimitWarning a samm:Property ; + samm:name "speedLimitWarning" ; + samm:preferredName "speed limit warning"@en ; + samm:description "Indicates if the speed limit is adhered to."@en ; + samm:characteristic :TrafficLight . + +:SpatialPositionCharacteristic a samm-c:SingleEntity ; + samm:name "SpatialPositionCharacteristic" ; + samm:preferredName "spatial position characteristic"@en ; + samm:description "Represents a single position in space with optional z coordinate."@en ; + samm:dataType :SpatialPosition . + +:Speed a samm-c:Measurement ; + samm:name "Speed" ; + samm:preferredName "speed"@en ; + samm:description "Scalar representation of speed of an object in kilometers per hour."@en ; + samm:dataType xsd:float ; + samm-c:unit unit:kilometrePerHour . + +:TrafficLight a samm-c:Enumeration ; + samm:name "TrafficLight" ; + samm:preferredName "warning level"@en ; + samm:description "Represents if speed of position change is within specification (green), within tolerance (yellow), or outside specification (red)."@en ; + samm:dataType xsd:string ; + samm-c:values ( "green" "yellow" "red" ) . + +:SpatialPosition a samm:Entity ; + samm:name "SpatialPosition" ; + samm:preferredName "spatial position"@en ; + samm:description "Represents latitude, longitude and altitude information in the WGS84 geodetic reference datum"@en ; + samm:see ; + samm:properties ( :latitude :longitude [ samm:property :altitude; samm:optional true ] ) . + +:latitude a samm:Property ; + samm:name "latitude" ; + samm:preferredName "latitude"@en ; + samm:description "latitude coordinate in space (WGS84)"@en ; + samm:see ; + samm:characteristic :Coordinate ; + samm:exampleValue "9.1781"^^xsd:decimal . + +:longitude a samm:Property ; + samm:name "longitude" ; + samm:preferredName "longitude"@en ; + samm:description "longitude coordinate in space (WGS84)"@en ; + samm:see ; + samm:characteristic :Coordinate ; + samm:exampleValue "48.80835"^^xsd:decimal . + +:altitude a samm:Property ; + samm:name "altitude" ; + samm:preferredName "altitude"@en ; + samm:description "Elevation above sea level zero"@en ; + samm:see ; + samm:characteristic :MetresAboveMeanSeaLevel ; + samm:exampleValue "153"^^xsd:float . + +:Coordinate a samm-c:Measurement ; + samm:name "Coordinate" ; + samm:preferredName "coordinate"@en ; + samm:description "Representing the geographical coordinate"@en ; + samm:dataType xsd:decimal ; + samm-c:unit unit:degreeUnitOfAngle . + +:MetresAboveMeanSeaLevel a samm-c:Measurement ; + samm:name "MetresAboveMeanSeaLevel" ; + samm:preferredName "metres above mean sea level"@en ; + samm:description "Signifies the vertical distance in reference to a historic mean sea level as a vertical datum"@en ; + samm:see ; + samm:dataType xsd:float ; + samm-c:unit unit:metre . diff --git a/core/apps/ame-e2e/src/fixtures/enumeration-instances.txt b/core/apps/ame-e2e/src/fixtures/enumeration-instances.txt new file mode 100644 index 00000000..dbd1a8c9 --- /dev/null +++ b/core/apps/ame-e2e/src/fixtures/enumeration-instances.txt @@ -0,0 +1,34 @@ +# Copyright (c) 2023 Robert Bosch Manufacturing Solutions GmbH +# +# See the AUTHORS file(s) distributed with this work for +# additional information regarding authorship. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at https://mozilla.org/MPL/2.0/. +# +# SPDX-License-Identifier: MPL-2.0 + +@prefix samm: . +@prefix samm-c: . +@prefix samm-e: . +@prefix unit: . +@prefix rdf: . +@prefix rdfs: . +@prefix xsd: . +@prefix : . + +:EnumerationInstances a samm:Aspect; + samm:properties (:enumerationInstancesProperty1); + samm:operations (); + samm:events (). +:enumerationInstancesProperty1 a samm:Property; + samm:characteristic :enumerationInstancesCharacteristic1. +:enumerationInstancesCharacteristic1 a samm-c:Enumeration; + samm:dataType :enumerationInstancesEntity1; + samm-c:values (:enumerationInstancesInstance1 :enumerationInstancesInstance2 :enumerationInstancesInstance3). +:enumerationInstancesEntity1 a samm:Entity; + samm:properties (). +:enumerationInstancesInstance1 a :enumerationInstancesEntity1. +:enumerationInstancesInstance2 a :enumerationInstancesEntity1. +:enumerationInstancesInstance3 a :enumerationInstancesEntity1. diff --git a/core/apps/ame-e2e/src/integration/editor/change-class-behavior.spec.ts b/core/apps/ame-e2e/src/integration/editor/change-class-behavior.spec.ts index b3d65fdc..9429136c 100644 --- a/core/apps/ame-e2e/src/integration/editor/change-class-behavior.spec.ts +++ b/core/apps/ame-e2e/src/integration/editor/change-class-behavior.spec.ts @@ -78,7 +78,6 @@ describe('Constraint', () => { .click({force: true}) .get(`mat-option[cy-value="${classType}"]`) .click({force: true}) - .wait(250) .then(() => cy.get(field.selector).should('have.value', field.value)); }); } diff --git a/core/apps/ame-e2e/src/integration/editor/collapse-expand-model.spec.ts b/core/apps/ame-e2e/src/integration/editor/collapse-expand-model.spec.ts index eab25589..10d2962c 100644 --- a/core/apps/ame-e2e/src/integration/editor/collapse-expand-model.spec.ts +++ b/core/apps/ame-e2e/src/integration/editor/collapse-expand-model.spec.ts @@ -21,6 +21,7 @@ describe('Test collapse/expand model', () => { cy.visitDefault(); cy.startModelling() .then(() => cy.get(SELECTOR_tbCollapseToggle).click({force: true})) + // eslint-disable-next-line cypress/no-unnecessary-waiting .then(() => cy.wait(500)) .then(() => cyHelp.testShapeInCollapsedMode('AspectDefault')) .then(() => cyHelp.testShapeInCollapsedMode('property1')) @@ -54,8 +55,8 @@ describe('Test collapse/expand model', () => { .then(() => { // collapse cy.get(SELECTOR_tbCollapseToggle).click({force: true}); - cy.getHTMLCell('Characteristic1').click({force: true}).wait(1000); // wait for tooltip - cy.get('.mxTooltip') + cy.getHTMLCell('Characteristic1').click({force: true}); // wait for tooltip + cy.get('.mxTooltip', {timeout: 10000}) .should('be.visible') .should('contain', 'Characteristic1') .get('.cell-tooltip table') diff --git a/core/apps/ame-e2e/src/integration/editor/create-recursive-element.spec.ts b/core/apps/ame-e2e/src/integration/editor/create-recursive-element.spec.ts index 672bb822..ac802213 100644 --- a/core/apps/ame-e2e/src/integration/editor/create-recursive-element.spec.ts +++ b/core/apps/ame-e2e/src/integration/editor/create-recursive-element.spec.ts @@ -13,7 +13,7 @@ /// import {cyHelp} from '../../support/helpers'; -import {FIELD_characteristicName, SELECTOR_editorSaveButton, SELECTOR_tbDeleteButton} from '../../support/constants'; +import {FIELD_characteristicName, SELECTOR_tbDeleteButton} from '../../support/constants'; describe('Test create recursive element', () => { function checkIfAspectHasCharacteristic(aspect: any) { @@ -96,7 +96,7 @@ describe('Test create recursive element', () => { cy.shapeExists('NewCharacteristic') .then(() => cy.dbClickShape('NewCharacteristic')) .then(() => cy.get(FIELD_characteristicName).click({force: true}).get('mat-option').contains('Text').click({force: true})) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getUpdatedRDF()) .then(rdf => { expect(rdf).to.contain(':property1 a samm:Property;\n' + ' samm:characteristic samm-c:MultiLanguageText.'); @@ -111,7 +111,7 @@ describe('Test create recursive element', () => { cy.shapeExists('MultiLanguageText') .then(() => cy.dbClickShape('MultiLanguageText')) .then(() => cy.get(FIELD_characteristicName).click({force: true}).get('mat-option').contains('Characteristic').click({force: true})) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.clickConnectShapes('Characteristic1', 'NewEntity')) .then(() => cy.clickConnectShapes('Characteristic1', 'newProperty2')) .then(() => cy.clickConnectShapes('Characteristic1', 'newProperty3')) diff --git a/core/apps/ame-e2e/src/integration/editor/edit-abstract-entity.spec.ts b/core/apps/ame-e2e/src/integration/editor/edit-abstract-entity.spec.ts index fefec817..be2aae25 100644 --- a/core/apps/ame-e2e/src/integration/editor/edit-abstract-entity.spec.ts +++ b/core/apps/ame-e2e/src/integration/editor/edit-abstract-entity.spec.ts @@ -25,7 +25,6 @@ import { SELECTOR_ecAbstractProperty, SELECTOR_ecEntity, SELECTOR_editorCancelButton, - SELECTOR_editorSaveButton, SELECTOR_notificationsButton, SELECTOR_tbDeleteButton, SELECTOR_tbLoadButton, @@ -46,7 +45,7 @@ describe('Create and Edit Abstract Entity', () => { .then(() => cy.get(FIELD_preferredNameen).focus().type('Preferred Name')) .then(() => cy.get(FIELD_descriptionen).focus().type('Description')) .then(() => cy.addSeeElements('http://test.com')) - .then(() => cy.get(SELECTOR_editorSaveButton).click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.clickConnectShapes('AbstractEntity1', 'Entity1')) .then(() => cy.getCellLabel('Entity1', 'preferredName').should('eq', 'Inherited\npreferredName = Preferred Name @en')) .then(() => cy.getCellLabel('Entity1', 'description').should('eq', 'Inherited\ndescription = Description @en')) @@ -56,7 +55,7 @@ describe('Create and Edit Abstract Entity', () => { it('should edit entity1', () => { cy.dbClickShape('Entity1') .then(() => cy.get(FIELD_descriptionen).clear({force: true}).type('Entity Description')) - .then(() => cy.get(SELECTOR_editorSaveButton).click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getCellLabel('Entity1', 'description').should('eq', 'description = Entity Description @en')) .then(() => cy.getCellLabel('Entity1', 'preferredName').should('eq', 'Inherited\npreferredName = Preferred Name @en')) .then(() => cy.getCellLabel('Entity1', 'see').should('eq', 'Inherited\nsee = http://test.com')); @@ -69,7 +68,7 @@ describe('Create and Edit Abstract Entity', () => { .then(() => cy.get('[data-cy="clear-extends-button"]').click({force: true})) .then(() => cy.get(FIELD_extends).focus().type('AbstractEntity2')) .then(() => cy.get('mat-option').contains('AbstractEntity2').first().click({force: true})) - .then(() => cy.get(SELECTOR_editorSaveButton).click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getCellLabel('Entity1', 'extends').should('eq', 'extends = AbstractEntity2')); }); @@ -99,7 +98,7 @@ describe('Create and Edit Abstract Entity', () => { .then(() => cy.get(FIELD_preferredNameen).focus().type('Preferred Name')) .then(() => cy.get(FIELD_descriptionen).focus().type('Description')) .then(() => cy.addSeeElements('http://test.com')) - .then(() => cy.get(SELECTOR_editorSaveButton).click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.dbClickShape('AbstractEntity1')) .then(() => cy.get(FIELD_preferredNameen).should('have.value', 'Preferred Name')) .then(() => cy.get(FIELD_descriptionen).should('have.value', 'Description')) @@ -231,7 +230,7 @@ describe('Create and Edit Abstract Entity', () => { .then(() => cy.get(FIELD_preferredNameen).type('Preferred Name 1', {force: true})) .then(() => cy.get(FIELD_descriptionen).type('Description 1', {force: true})) .then(() => cy.addSeeElements('http://test1.com')) - .then(() => cy.get(SELECTOR_editorSaveButton).click({force: true}).wait(500)); + .then(() => cyHelp.clickSaveButton().wait(500)); cy.getCellLabel('Entity1', 'extends').should('eq', 'extends = AbstractEntity1'); cy.getCellLabel('Entity1', 'preferredName').should('eq', 'Inherited\npreferredName = Preferred Name 1 @en'); diff --git a/core/apps/ame-e2e/src/integration/editor/edit-abstract-property.spec.ts b/core/apps/ame-e2e/src/integration/editor/edit-abstract-property.spec.ts index 258f5d75..4a684d53 100644 --- a/core/apps/ame-e2e/src/integration/editor/edit-abstract-property.spec.ts +++ b/core/apps/ame-e2e/src/integration/editor/edit-abstract-property.spec.ts @@ -20,12 +20,12 @@ import { SELECTOR_dialogInputModel, SELECTOR_dialogStartButton, SELECTOR_ecAbstractProperty, - SELECTOR_editorSaveButton, SELECTOR_tbLoadButton, SELECTOR_ecAbstractEntity, SELECTOR_ecProperty, SELECTOR_ecEntity, } from '../../support/constants'; +import {cyHelp} from '../../support/helpers'; describe('Create and Edit Abstract Property', () => { describe('Property -> Abstract Property', () => { @@ -42,7 +42,7 @@ describe('Create and Edit Abstract Property', () => { .then(() => cy.get(FIELD_preferredNameen).focus().type('Preferred Name')) .then(() => cy.get(FIELD_descriptionen).focus().type('Description')) .then(() => cy.addSeeElements('http://test.com')) - .then(() => cy.get(SELECTOR_editorSaveButton).click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.clickAddShapePlusIcon('Characteristic1')) .then(() => cy.clickAddShapePlusIcon('Entity1')) .then(() => cy.clickConnectShapes('AbstractEntity1', 'abstractProperty1')) @@ -107,13 +107,13 @@ describe('Create and Edit Abstract Property', () => { .then(() => cy.get(FIELD_preferredNameen).type('Preferred Name 1', {force: true})) .then(() => cy.get(FIELD_descriptionen).type('Description 1', {force: true})) .then(() => cy.addSeeElements('http://test1.com')) - .then(() => cy.get(SELECTOR_editorSaveButton).click({force: true}).wait(500)) + .then(() => cyHelp.clickSaveButton().wait(500)) .then(() => cy.dbClickShape('abstractProperty2')) .then(() => cy.get(FIELD_preferredNameen).type('Preferred Name 2', {force: true})) .then(() => cy.get(FIELD_descriptionen).type('Description 2', {force: true})) .then(() => cy.addSeeElements('http://test2.com')) - .then(() => cy.get(SELECTOR_editorSaveButton).click({force: true}).wait(500)); + .then(() => cyHelp.clickSaveButton().wait(500)); cy.getCellLabel('[abstractProperty1]', 'extends').should('eq', 'extends = abstractProperty1'); cy.getCellLabel('[abstractProperty1]', 'preferredName').should('eq', 'Inherited\npreferredName = Preferred Name 1 @en'); diff --git a/core/apps/ame-e2e/src/integration/editor/edit-aspect.spec.ts b/core/apps/ame-e2e/src/integration/editor/edit-aspect.spec.ts index 25dd4f2d..666930ae 100644 --- a/core/apps/ame-e2e/src/integration/editor/edit-aspect.spec.ts +++ b/core/apps/ame-e2e/src/integration/editor/edit-aspect.spec.ts @@ -16,15 +16,28 @@ import { BUTTON_renameModelConfirm, + FIELD_descriptionen, FIELD_name, + FIELD_preferredNameen, + PROP_configuration, FIELD_renameModelInput, - SELECTOR_editorSaveButton, + FIELD_see, SELECTOR_tbDeleteButton, + SELECTOR_configureProp, + FIELD_error, + SELECTOR_resizeWindow, + META_MODEL_preferredName, + META_MODEL_description, + META_MODEL_see, + SELECTOR_saveProperties, + SELECTOR_configuredProperty, + SELECTOR_configuredPropertyCheckBox, + SELECTOR_configuredPropertyPayload, } from '../../support/constants'; import {cyHelp} from '../../support/helpers'; describe('Test editing Aspect', () => { - it('can add new', () => { + it('can add new aspect model', () => { cy.visitDefault(); cy.startModelling(); }); @@ -36,25 +49,160 @@ describe('Test editing Aspect', () => { .then(() => cyHelp.addNewProperty(4)); }); - it('can edit name', () => { + it('can check that all fields are visible and check order', () => { cy.shapeExists('AspectDefault') .then(() => cy.dbClickShape('AspectDefault')) - .then(() => cy.get(FIELD_name).clear({force: true}).type('NewAspect', {force: true})) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cy.get(FIELD_name).clear({force: true}).type('NewAspect')) + .then(() => cy.get(FIELD_preferredNameen).clear().type('New Preffered Name for Aspect')) + .then(() => cy.get(FIELD_descriptionen).clear().type('This is an aspect model')) + .then(() => cy.get(FIELD_see).clear().should('be.visible')) + .then(() => cy.get(PROP_configuration).should('have.text', 'Properties Configuration')) + .then(() => cy.get(SELECTOR_configureProp).should('be.visible').should('have.text', 'Configure')) + .then(() => cy.get(SELECTOR_resizeWindow).should('be.visible')) + .then(() => cyHelp.clickSaveButton()); + }); + + it('can rename aspect name', () => { + cy.shapeExists('NewAspect') + .then(() => cyHelp.renameElement('NewAspect', 'NewAspect1')) + .then(() => cy.getUpdatedRDF()) + .then(rdf => { + expect(rdf).to.contain(':NewAspect1'); + expect(rdf).to.contain(':NewAspect1 a samm:Aspect'); + }) + .then(() => cy.getAspect()) + .then(aspect => expect(aspect.name).to.equal('NewAspect1')); + cy.shapeExists('NewAspect1').then(() => cyHelp.renameElement('NewAspect1', 'NewAspect')); + }); + + it('should validate edit aspect name field', () => { + cy.shapeExists('NewAspect') + .then(() => cy.dbClickShape('NewAspect')) + .then(() => cy.get(FIELD_name).clear().type('newAspect#')) + .then(() => cy.get(FIELD_error).should('be.visible')) + .then(() => cy.get(FIELD_name).clear()) + .then(() => cy.get(FIELD_name).clear().type('NewAspect')); + }); + + it('can edit preferredName', () => { + cy.shapeExists('NewAspect') + .then(() => cy.dbClickShape('NewAspect')) + .then(() => cy.get(FIELD_preferredNameen).clear().type('New Preffered Name for Aspect')) + .then(() => cyHelp.clickSaveButton()) + .then(() => + cy + .getCellLabel('NewAspect', META_MODEL_preferredName) + .should('eq', `${META_MODEL_preferredName} = New Preffered Name for Aspect @en`) + ) + .then(() => cy.getUpdatedRDF()) + .then(rdf => expect(rdf).to.contain('samm:preferredName "New Preffered Name for Aspect"@en')) + .then(() => cy.getAspect()) + .then(aspect => expect(aspect.getPreferredName('en')).to.equal('New Preffered Name for Aspect')); + }); + + it('can edit aspect model description', () => { + cy.shapeExists('NewAspect') + .then(() => cy.dbClickShape('NewAspect')) + .then(() => cy.get(FIELD_descriptionen).clear().type('New description for the aspect model')) + .then(() => cyHelp.clickSaveButton()) + .then(() => + cy + .getCellLabel('NewAspect', META_MODEL_description) + .should('eq', `${META_MODEL_description} = New description for the aspect model @en`) + ) + .then(() => cy.getUpdatedRDF().then(rdf => expect(rdf).to.contain('samm:description "New description for the aspect model"@en'))) + .then(() => cy.getAspect().then(aspect => expect(aspect.getDescription('en')).to.equal('New description for the aspect model'))); + }); + + it('can edit see aspect field', () => { + cy.shapeExists('NewAspect') + .then(() => cy.dbClickShape('NewAspect')) + .then(() => cy.addSeeElements('http://www.seeA.de', 'http://www.seeB.de', 'http://www.seeC.de')) + .then(() => cyHelp.clickSaveButton()) + .then(() => + cy + .getCellLabel('NewAspect', META_MODEL_see) + .should('eq', `${META_MODEL_see} = http://www.seeA.de,http://www.seeB.de,http://www.seeC.de`) + ) .then(() => - cy.getUpdatedRDF().then(rdf => { - expect(rdf).to.contain(':NewAspect'); - expect(rdf).to.contain(':NewAspect a samm:Aspect'); + cy.getUpdatedRDF().then(rdf => expect(rdf).to.contain('samm:see , , ')) + ) + .then(() => + cy.getAspect().then(aspect => { + expect(aspect.getSeeReferences()).to.have.length(3); + expect(aspect.getSeeReferences()[2]).to.equal('http://www.seeC.de'); }) ); + cy.dbClickShape('NewAspect') + .then(() => cy.removeSeeElements('http://www.seeB.de')) + .then(() => cyHelp.clickSaveButton()) + .then(() => cy.getCellLabel('NewAspect', META_MODEL_see).should('eq', `${META_MODEL_see} = http://www.seeA.de,http://www.seeC.de`)) + .then(() => cy.getUpdatedRDF()) + .then(rdf => expect(rdf).to.contain('samm:see , ')) + .then(() => + cy.getAspect().then(aspect => { + expect(aspect.getSeeReferences()).to.have.length(2); + expect(aspect.getSeeReferences()[1]).to.equal('http://www.seeC.de'); + }) + ); + }); + + it('can edit see http attributes to urns', () => { + cy.shapeExists('NewAspect') + .then(() => cy.dbClickShape('NewAspect')) + .then(() => cy.removeSeeElements().addSeeElements('urn:irdi:eclass:0173-1#02-AAO677', 'urn:irdi:iec:0112/2///62683#ACC011#001')) + .then(() => cyHelp.clickSaveButton()) + + .then(() => + cy + .getCellLabel('NewAspect', META_MODEL_see) + .should('eq', `${META_MODEL_see} = urn:irdi:eclass:0173-1#02-AAO677,urn:irdi:iec:0112/2///62683#ACC011#001`) + ) + .then(() => cy.getUpdatedRDF()) + .then(rdf => expect(rdf).to.contain('samm:see , ')) + .then(() => cy.getAspect()) + .then(aspect => { + expect(aspect.getSeeReferences()).to.have.length(2); + expect(aspect.getSeeReferences()[1]).to.equal('urn:irdi:iec:0112/2///62683#ACC011#001'); + }); + + cy.dbClickShape('NewAspect') + .then(() => cy.removeSeeElements().addSeeElements('urn:irdi:eclass:0173-1#02-AAO677')) + .then(() => cyHelp.clickSaveButton()) + + .then(() => cy.getCellLabel('NewAspect', META_MODEL_see).should('eq', `${META_MODEL_see} = urn:irdi:eclass:0173-1#02-AAO677`)) + .then(() => cy.getUpdatedRDF()) + .then(rdf => expect(rdf).to.contain('samm:see ')) + .then(() => cy.getAspect()) + .then(aspect => { + expect(aspect.getSeeReferences()).to.have.length(1); + expect(aspect.getSeeReferences()[0]).to.equal('urn:irdi:eclass:0173-1#02-AAO677'); + }); + }); + + it('can configure properties', () => { + cy.shapeExists('NewAspect') + .then(() => cy.dbClickShape('NewAspect')) + .then(() => cy.get(SELECTOR_configureProp).should('be.visible').should('have.text', 'Configure')) + .then(() => cy.get(SELECTOR_configureProp).focus().click()) + .then(() => cy.get(SELECTOR_configuredProperty).should('be.visible')) + .then(() => cy.get(SELECTOR_configuredPropertyCheckBox).focus().click()) + .then(() => cy.get(SELECTOR_configuredPropertyPayload).type('payload')) + .then(() => cy.get(SELECTOR_saveProperties).focus().click()); + }); + + it('should check outgoing edges', () => { + cy.shapeExists('NewAspect').then(() => cy.dbClickShape('NewAspect')); + cy.contains('Incoming edges').should('not.exist'); + cy.contains('Outgoing edges (4)').should('exist'); }); it('can delete property1 and property3', () => { cy.shapeExists('NewAspect') .then(() => cy.clickShape('property1')) - .then(() => cy.get(SELECTOR_tbDeleteButton).click({force: true})) + .then(() => cy.get(SELECTOR_tbDeleteButton).click()) .then(() => cy.clickShape('property3')) - .then(() => cy.get(SELECTOR_tbDeleteButton).click({force: true})) + .then(() => cy.get(SELECTOR_tbDeleteButton).click()) .then(() => cy.getUpdatedRDF().then(rdf => expect(rdf).to.contain('samm:properties (:property2 :property4)'))); }); diff --git a/core/apps/ame-e2e/src/integration/editor/edit-characteristic.spec.ts b/core/apps/ame-e2e/src/integration/editor/edit-characteristic.spec.ts index 62d268e9..9e6bddeb 100644 --- a/core/apps/ame-e2e/src/integration/editor/edit-characteristic.spec.ts +++ b/core/apps/ame-e2e/src/integration/editor/edit-characteristic.spec.ts @@ -22,8 +22,10 @@ import { FIELD_deconstructionRuleSelect, FIELD_descriptionen, FIELD_elementsModalButton, + FIELD_error, FIELD_name, FIELD_preferredNameen, + FIELD_see, FIELD_unit, FIELD_values, META_MODEL_dataType, @@ -51,13 +53,24 @@ describe('Test editing Characteristic', () => { }); }); + it('should check that all fields are visible and the order is correct', () => { + cy.shapeExists('Characteristic1') + .then(() => cy.dbClickShape('Characteristic1')) + .then(() => cy.get(FIELD_name).should('be.visible')) + .then(() => cy.get(FIELD_preferredNameen).should('be.visible')) + .then(() => cy.get(FIELD_descriptionen).should('be.visible')) + .then(() => cy.get(FIELD_see).should('be.visible')) + .then(() => cy.get(FIELD_dataType).should('be.visible')) + .then(() => cyHelp.clickSaveButton()); + }); + it('can edit description', () => { cy.shapeExists('Characteristic1') .then(() => cy.dbClickShape('Characteristic1')) .then(() => cy.get(FIELD_descriptionen).clear({force: true}).type('New description for the new created characteristic', {force: true}) ) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy .getCellLabel('Characteristic1', META_MODEL_description) @@ -91,7 +104,7 @@ describe('Test editing Characteristic', () => { .contains('integer') .click({force: true}) ) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getCellLabel('Characteristic1', META_MODEL_dataType).should('eq', `${META_MODEL_dataType} = integer`)) .then(() => cy.getUpdatedRDF().then(rdf => expect(rdf).to.contain('samm:dataType xsd:integer'))); }); @@ -100,7 +113,7 @@ describe('Test editing Characteristic', () => { cy.shapeExists('Characteristic1') .then(() => cy.dbClickShape('Characteristic1')) .then(() => cy.addSeeElements('http://www.see1.de', 'http://www.see2.de', 'http://www.see3.de')) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true}).wait(250)) + .then(() => cyHelp.clickSaveButton().wait(250)) .then(() => cy .getCellLabel('Characteristic1', META_MODEL_see) @@ -119,7 +132,7 @@ describe('Test editing Characteristic', () => { cy.dbClickShape('Characteristic1') .then(() => cy.removeSeeElements('http://www.see2.de')) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getCellLabel('Characteristic1', META_MODEL_see).should('eq', `${META_MODEL_see} = http://www.see1.de,http://www.see3.de`) ) @@ -137,7 +150,7 @@ describe('Test editing Characteristic', () => { cy.shapeExists('Characteristic1') .then(() => cy.dbClickShape('Characteristic1')) .then(() => cy.removeSeeElements().addSeeElements('urn:irdi:eclass:0173-1#02-AAO677', 'urn:irdi:iec:0112/2///62683#ACC011#001')) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy @@ -154,7 +167,7 @@ describe('Test editing Characteristic', () => { cy.dbClickShape('Characteristic1') .then(() => cy.removeSeeElements().addSeeElements('urn:irdi:eclass:0173-1#02-AAO677')) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getCellLabel('Characteristic1', META_MODEL_see).should('eq', `${META_MODEL_see} = urn:irdi:eclass:0173-1#02-AAO677`)) .then(() => cy.getUpdatedRDF()) @@ -170,7 +183,7 @@ describe('Test editing Characteristic', () => { cy.shapeExists('Characteristic1') .then(() => cy.dbClickShape('Characteristic1')) .then(() => cy.get(FIELD_preferredNameen).clear({force: true}).type('new-preferredName', {force: true})) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getCellLabel('Characteristic1', META_MODEL_preferredName).should('eq', `${META_MODEL_preferredName} = new-preferredName @en`) @@ -181,6 +194,12 @@ describe('Test editing Characteristic', () => { .then(aspect => expect(aspect.properties[0].property.characteristic.getPreferredName('en')).to.equal('new-preferredName')); }); + it('should check incoming and outgoing edges', () => { + cy.shapeExists('property1').then(() => cy.dbClickShape('property1')); + cy.contains('Incoming edges (1)').should('exist'); + cy.contains('Outgoing edges (1)').should('exist'); + }); + it('can connect', () => { cy.shapeExists('Characteristic1') .then(() => cy.clickShape('property1')) @@ -205,6 +224,17 @@ describe('Test editing Characteristic', () => { .then(aspect => expect(aspect.properties[0].property.characteristic.name).to.equal('NewCharacteristic')); }); + it('should validate name field', () => { + cy.shapeExists('NewCharacteristic') + .then(() => cy.dbClickShape('NewCharacteristic')) + .then(() => { + cy.get(FIELD_name).clear().type('char22#'); + cy.get(FIELD_error).should('contain', 'Please start with an upper case character followed by letters/numerals.'); + }) + .then(() => cy.get(FIELD_name).clear()) + .then(() => cy.get(FIELD_name).clear().type('NewCharacteristic')); + }); + it('can edit unit', () => { cy.shapeExists('NewCharacteristic') .then(() => cy.dbClickShape('NewCharacteristic')) @@ -212,7 +242,7 @@ describe('Test editing Characteristic', () => { .then(() => cy.get(FIELD_unit).clear({force: true}).type('amper', {force: true}).get('mat-option').contains('ampere').click({force: true}) ) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getAspect()) .then(aspect => expect(aspect.properties[0].property.characteristic.unit.name).to.be.equal('ampere')); }); @@ -221,7 +251,7 @@ describe('Test editing Characteristic', () => { cy.shapeExists('NewCharacteristic') .then(() => cy.dbClickShape('NewCharacteristic')) .then(() => cy.get(FIELD_characteristicName).click({force: true}).get('mat-option').contains('Code').click({force: true})) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getUpdatedRDF()) .then(rdf => { @@ -242,7 +272,7 @@ describe('Test editing Characteristic', () => { .then(() => cy.dbClickShape('NewCharacteristic')) .then(() => cy.get(FIELD_characteristicName).click({force: true}).get('mat-option').contains('Enumeration').click({force: true})) .then(() => cy.get(FIELD_values).type('1{enter}2{enter}a{enter}b{enter}3{enter}4{enter}', {force: true})) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getCellLabel('NewCharacteristic', META_MODEL_values).should('eq', `${META_MODEL_values} = 1, 2, a, b, 3, 4`)) .then(() => cy.getUpdatedRDF()) .then(rdf => @@ -263,7 +293,7 @@ describe('Test editing Characteristic', () => { cy.dbClickShape('NewCharacteristic') .then(() => cy.get(FIELD_chipIcon).each(chip => cy.wrap(chip).click({force: true}))) .then(() => cy.get(FIELD_values).type('2{enter}b{enter}3{enter}', {force: true})) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getCellLabel('NewCharacteristic', META_MODEL_values).should('eq', `${META_MODEL_values} = 2, b, 3`)) .then(() => cy.getUpdatedRDF()) .then(rdf => @@ -284,7 +314,7 @@ describe('Test editing Characteristic', () => { .then(() => cy.get(FIELD_characteristicName).click({force: true}).get('mat-option').contains('MultiLanguageText').click({force: true}) ) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cyHelp.getAddShapePlusIcon('MultiLanguageText').then(addShapeIcon => expect(addShapeIcon).to.be.false)); }); @@ -302,7 +332,7 @@ describe('Test editing Characteristic', () => { .then(() => cy.dbClickShape('Characteristic1').wait(200)) .then(() => cy.get(SELECTOR_editorCancelButton).focus()) // reactivate change detection .then(() => cy.get(FIELD_name).clear({force: true}).type('NewCharacteristic', {force: true})) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.clickAddShapePlusIcon('AspectDefault')) .then(() => cy.shapeExists('property2')) .then(() => cy.clickAddShapePlusIcon('property2')) @@ -318,7 +348,7 @@ describe('Test editing Characteristic', () => { cy.shapeExists('AspectDefault') .then(() => cy.dbClickShape('AspectDefault')) .then(() => cy.get(FIELD_name).clear({force: true}).type('NewAspect', {force: true})) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getUpdatedRDF()) .then(rdf => expect(rdf).to.contain( @@ -403,7 +433,8 @@ describe('Structured Value Characteristic', () => { .wait(500) .then(() => cy.get(FIELD_elementsModalButton).click({force: true})) .then(() => shouldHaveValues(['([\\\\w\\\\.-]+)', '([\\\\w\\\\.-]+\\\\.\\\\w{2,4})'], ['username', 'host'])) - .then(() => cy.get(SELECTOR_editorSaveButton).should('be.enabled').click({force: true})) + .then(() => cy.get(SELECTOR_editorSaveButton).should('be.enabled')) + .then(() => cyHelp.clickSaveButton()) .wait(200) .then(() => cy.shapeExists('username')) .then(() => cy.shapeExists('host')) @@ -458,7 +489,7 @@ describe('Structured Value Characteristic', () => { it('should create 3 properties shapes', () => { cy.get(SELECTOR_editorSaveButton) .should('be.enabled') - .click({force: true}) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.shapeExists('group1Property')) .then(() => cy.shapeExists('group2Property')) .then(() => cy.shapeExists('group3Property')); @@ -472,7 +503,8 @@ describe('Structured Value Characteristic', () => { ) .then(() => cy.get(FIELD_elementsModalButton).click({force: true})) .then(() => shouldHaveValues(['(group1)', '(group2)', '(group3)'], ['group1Property', 'group2Property', 'group3Property'])) - .then(() => cy.get(SELECTOR_editorSaveButton).should('be.enabled').click({force: true})); + .then(() => cy.get(SELECTOR_editorSaveButton).should('be.enabled')) + .then(() => cyHelp.clickSaveButton()); }); it('should create characteristics without add shape button', () => { @@ -524,7 +556,8 @@ describe('Structured Value Characteristic', () => { .wait(500) .then(() => cy.get(FIELD_elementsModalButton).click({force: true})) .then(() => shouldHaveValues(['(\\\\d{4})', '(\\\\d{2})', '(\\\\d{2})'], ['year', 'month', 'day'])) - .then(() => cy.get(SELECTOR_editorSaveButton).should('be.enabled').click({force: true})) + .then(() => cy.get(SELECTOR_editorSaveButton).should('be.enabled')) + .then(() => cyHelp.clickSaveButton()) .wait(200) .then(() => cy.shapeExists('year')) .then(() => cy.shapeExists('month')) @@ -568,7 +601,8 @@ describe('Structured Value Characteristic', () => { .wait(500) .then(() => cy.get(FIELD_elementsModalButton).click({force: true})) .then(() => shouldHaveValues(['([0-9A-Fa-f]{2})', '([0-9A-Fa-f]{2})', '([0-9A-Fa-f]{2})'], ['red', 'green', 'blue'])) - .then(() => cy.get(SELECTOR_editorSaveButton).should('be.enabled').click({force: true})) + .then(() => cy.get(SELECTOR_editorSaveButton).should('be.enabled')) + .then(() => cyHelp.clickSaveButton()) .wait(200) .then(() => cy.shapeExists('red')) .then(() => cy.shapeExists('green')) @@ -710,7 +744,6 @@ describe('Structured Value Characteristic', () => { const childrenParams = [{name: 'username'}, {name: 'host'}]; cy.get('#toast-container').contains('Unable to connect elements').click(); - cy.get('#toast-container').should('be.empty'); cy.isConnected(characteristicParams, entityParams).should('be.false'); childrenParams.forEach(childParams => cy.isConnected(characteristicParams, childParams).should('be.true')); }); @@ -723,7 +756,6 @@ describe('Structured Value Characteristic', () => { const childrenParams = [{name: 'username'}, {name: 'host'}]; cy.get('#toast-container').contains('Unable to connect elements').click(); - cy.get('#toast-container').should('be.empty'); cy.isConnected(characteristicParams, parentParams).should('be.false'); cy.isConnected(parentParams, characteristicParams).should('be.true'); childrenParams.forEach(childParams => { @@ -740,7 +772,6 @@ describe('Structured Value Characteristic', () => { const childrenParams = [{name: 'username'}, {name: 'host'}]; cy.get('#toast-container').contains('Unable to connect elements').click(); - cy.get('#toast-container').should('be.empty'); cy.isConnected(characteristicParams, parentParams).should('be.false'); cy.isConnected(parentParams, characteristicParams).should('be.true'); childrenParams.forEach(childParams => { diff --git a/core/apps/ame-e2e/src/integration/editor/edit-collection.spec.ts b/core/apps/ame-e2e/src/integration/editor/edit-collection.spec.ts index c47f754b..c8907112 100644 --- a/core/apps/ame-e2e/src/integration/editor/edit-collection.spec.ts +++ b/core/apps/ame-e2e/src/integration/editor/edit-collection.spec.ts @@ -20,10 +20,10 @@ import { FIELD_name, SELECTOR_ecCharacteristic, SELECTOR_ecEntity, - SELECTOR_editorSaveButton, SELECTOR_tbDeleteButton, SELECTOR_clearElementCharacteristicButton, } from '../../support/constants'; +import {cyHelp} from '../../support/helpers'; describe('Test editing different Collections', () => { context('Type Collection', () => { @@ -202,7 +202,7 @@ describe('Test editing different Collections', () => { .then(() => cy.shapeExists('Characteristic1')) .then(() => cy.dbClickShape('Characteristic1')) .then(() => cy.get(FIELD_characteristicName).click({force: true}).get('mat-option').contains(`${type}`).click({force: true})) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getUpdatedRDF()) .then(rdf => { expect(rdf).to.contain(`samm:characteristic :${characteristic}`); @@ -227,7 +227,7 @@ describe('Test editing different Collections', () => { .contains('Characteristic2') .click({force: true}) ) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getUpdatedRDF()) .then(rdf => expect(rdf).to.contain('samm-c:elementCharacteristic :Characteristic2')) .then(() => cy.getAspect()) @@ -249,7 +249,7 @@ describe('Test editing different Collections', () => { .contains('Entity1') .click({force: true}) ) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getUpdatedRDF()) .then(rdf => expect(rdf).to.contain('samm:dataType :Entity1')); }; @@ -278,7 +278,7 @@ describe('Test editing different Collections', () => { cy.shapeExists('Characteristic2') .then(() => cy.dbClickShape('Characteristic2')) .then(() => cy.get(FIELD_name).clear({force: true}).type('NewCharacteristic', {force: true})) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getUpdatedRDF()) .then(rdf => { expect(rdf).to.contain('samm-c:elementCharacteristic :NewCharacteristic'); @@ -295,9 +295,8 @@ describe('Test editing different Collections', () => { const deleteElementCharacteristicCharacteristic = () => { cy.shapeExists('NewCharacteristic') .then(() => cy.dbClickShape('Characteristic1')) - .then(() => - cy.get(SELECTOR_clearElementCharacteristicButton).click({force: true}).get(SELECTOR_editorSaveButton).click({force: true}) - ) + .then(() => cy.get(SELECTOR_clearElementCharacteristicButton).click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getUpdatedRDF()) .then(rdf => { expect(rdf).not.contain('samm-c:elementCharacteristic :NewCharacteristic'); @@ -315,7 +314,7 @@ describe('Test editing different Collections', () => { cy.shapeExists('Entity1') .then(() => cy.dbClickShape('Entity1')) .then(() => cy.get(FIELD_name).clear({force: true}).type('NewEntity', {force: true})) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getUpdatedRDF()) .then(rdf => { expect(rdf).to.contain('samm:dataType :NewEntity'); diff --git a/core/apps/ame-e2e/src/integration/editor/edit-either.spec.ts b/core/apps/ame-e2e/src/integration/editor/edit-either.spec.ts index ea8368ef..2738f79a 100644 --- a/core/apps/ame-e2e/src/integration/editor/edit-either.spec.ts +++ b/core/apps/ame-e2e/src/integration/editor/edit-either.spec.ts @@ -58,7 +58,7 @@ describe('Test editing Either', () => { .contains('RightCharacteristic') .click({force: true}) ) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cyHelp.hasAddLeftAndRightShapeOverlay('Either1')) .then(hasAddLeftAndRightShapeOverlay => expect(hasAddLeftAndRightShapeOverlay).equal(true)) .then(() => cy.getAspect()) @@ -87,7 +87,7 @@ describe('Test editing Either', () => { cy.get(FIELD_descriptionen).clear({force: true}).type('New description for the new created characteristic', {force: true}); cy.addSeeElements('http://www.see1.de', 'http://www.see2.de', 'http://www.see3.de'); }) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => { cy.getCellLabel('Either1', META_MODEL_preferredName).should('eq', `${META_MODEL_preferredName} = new-preferredName @en`); cy.getCellLabel('Either1', META_MODEL_description).should( @@ -140,7 +140,7 @@ describe('Test editing Either', () => { .contains('RightCharacteristic') .click({force: true}) ) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getAspect()) .then(aspect => { expect(aspect.properties[0].property.characteristic.name).to.equal('Either1'); @@ -215,11 +215,11 @@ describe('Test editing Either', () => { .contains('RightCharacteristic') .click({force: true}) ) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.dbClickShape('Either1')) .then(() => { cy.get(FIELD_characteristicName).click({force: true}).get('mat-option').contains('Characteristic').click({force: true}); - cy.get(SELECTOR_editorSaveButton).focus().click({force: true}); + cyHelp.clickSaveButton(); }) .then(() => cyHelp.hasAddShapeOverlay('AspectDefault')) .then(hasAddOverlay => expect(hasAddOverlay).equal(true)) @@ -262,7 +262,7 @@ describe('Test editing Either', () => { .contains('RightCharacteristic') .click({force: true}) ) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.shapeExists('LeftCharacteristic')) .then(() => cy.clickShape('LeftCharacteristic')) .then(() => cy.get(SELECTOR_tbDeleteButton).click({force: true})) diff --git a/core/apps/ame-e2e/src/integration/editor/edit-entity.spec.ts b/core/apps/ame-e2e/src/integration/editor/edit-entity.spec.ts index 1dca6fb2..35dfcec1 100644 --- a/core/apps/ame-e2e/src/integration/editor/edit-entity.spec.ts +++ b/core/apps/ame-e2e/src/integration/editor/edit-entity.spec.ts @@ -14,11 +14,22 @@ /// -import {SELECTOR_tbDeleteButton} from '../../support/constants'; +import { + FIELD_descriptionen, + FIELD_extends, + FIELD_name, + FIELD_preferredNameen, + FIELD_see, + META_MODEL_description, + META_MODEL_preferredName, + META_MODEL_see, + SELECTOR_configureProp, + SELECTOR_tbDeleteButton, +} from '../../support/constants'; import {cyHelp} from '../../support/helpers'; describe('Test editing Entity', () => { - it('can add new', () => { + it('should add new entity', () => { cy.visitDefault(); cy.startModelling() .then(() => cy.shapeExists('Characteristic1')) @@ -32,7 +43,7 @@ describe('Test editing Entity', () => { }); }); - it('can add properties', () => { + it('should add properties', () => { cy.shapeExists('Entity1') .then(() => cy.clickAddShapePlusIcon('Entity1')) .then(() => cy.shapeExists('property2')) @@ -61,7 +72,7 @@ describe('Test editing Entity', () => { }); }); - it('can connect', () => { + it('should connect', () => { cy.shapeExists('property3') .then(() => cy.clickShape('Characteristic1')) .then(() => cy.get(SELECTOR_tbDeleteButton).click({force: true})) @@ -79,7 +90,7 @@ describe('Test editing Entity', () => { }); }); - it('can connect properties', () => { + it('should connect properties', () => { cy.shapeExists('Entity1') .then(() => cy.clickShape('Entity1')) .then(() => cy.get(SELECTOR_tbDeleteButton).click({force: true})) @@ -100,7 +111,7 @@ describe('Test editing Entity', () => { }); }); - it('can edit entity name', () => { + it('should edit entity name', () => { cy.shapeExists('Entity1') .then(() => cyHelp.renameElement('Entity1', 'NewEntity')) .then(() => { @@ -118,7 +129,73 @@ describe('Test editing Entity', () => { }); }); - it('can edit property name', () => { + it('should validate name', () => { + cy.shapeExists('NewEntity') + .then(() => cy.dbClickShape('NewEntity')) + .then(() => { + cy.get(FIELD_name).clear().type('entity23$%$'); + cy.get(FIELD_preferredNameen).click(); + cy.get(FIELD_name).should('be.visible').click(); + cy.get('ame-name-input-field mat-error').should( + 'contain', + 'Please start with an upper case character followed by letters/numerals.' + ); + }) + .then(() => cy.get(FIELD_name).clear()) + .then(() => cy.get(FIELD_name).clear().type('NewEntity')); + }); + + it('should check that all fields are visible and the order is correct', () => { + cy.shapeExists('NewEntity') + .then(() => cy.dbClickShape('NewEntity')) + .then(() => cy.get(FIELD_name).should('be.visible')) + .then(() => cy.get(FIELD_preferredNameen).clear().type('New Preffered Name for entity')) + .then(() => cy.get(FIELD_descriptionen).clear().type('This is an entity')) + .then(() => cy.get(FIELD_see).should('be.visible')) + .then(() => cy.get(FIELD_extends).should('be.visible')) + .then(() => cy.get(SELECTOR_configureProp).should('be.visible').should('have.text', 'Configure')) + .then(() => cyHelp.clickSaveButton()); + }); + + it('should check incoming and outgoing edges', () => { + cy.shapeExists('NewEntity').then(() => cy.dbClickShape('NewEntity')); + cy.contains('Incoming edges (1)').should('exist'); + cy.contains('Outgoing edges (2)').should('exist'); + }); + + it('should edit preferredName', () => { + cy.shapeExists('NewEntity') + .then(() => cy.dbClickShape('NewEntity')) + .then(() => cy.get(FIELD_preferredNameen).clear().type('New Preffered Name for entity')) + .then(() => cyHelp.clickSaveButton()) + .then(() => + cy + .getCellLabel('NewEntity', META_MODEL_preferredName) + .should('eq', `${META_MODEL_preferredName} = New Preffered Name for entity @en`) + ) + .then(() => cy.getUpdatedRDF()) + .then(rdf => expect(rdf).to.contain('samm:preferredName "New Preffered Name for entity"@en')); + }); + + it('should edit description', () => { + cy.shapeExists('NewEntity') + .then(() => cy.dbClickShape('NewEntity')) + .then(() => cy.get(FIELD_descriptionen).clear({force: true}).type('New description for the entity', {force: true})) + .then(() => cyHelp.clickSaveButton()) + .then(() => + cy.getCellLabel('NewEntity', META_MODEL_description).should('eq', `${META_MODEL_description} = New description for the entity @en`) + ) + .then(() => cy.getUpdatedRDF().then(rdf => expect(rdf).to.contain('samm:description "New description for the entity"@en'))) + .then(() => + cy + .getAspect() + .then(aspect => + expect(aspect.properties[0].property.characteristic.dataType.getDescription('en')).to.equal('New description for the entity') + ) + ); + }); + + it('should edit property name', () => { cy.shapeExists('property2') .then(() => cyHelp.renameElement('property2', 'newProperty2')) .then(() => cy.getUpdatedRDF()) @@ -133,7 +210,7 @@ describe('Test editing Entity', () => { }); }); - it('can edit entity and property name', () => { + it('should edit entity and property name', () => { cy.shapeExists('NewEntity') .then(() => cyHelp.renameElement('NewEntity', 'NewEntity1')) .then(() => cy.wait(1000)) @@ -159,7 +236,7 @@ describe('Test editing Entity', () => { }); }); - it('can delete existing', () => { + it('should delete existing entity', () => { cy.shapeExists('NewEntity1') .then(() => cy.clickShape('NewEntity1')) .then(() => cy.get(SELECTOR_tbDeleteButton)) @@ -174,7 +251,7 @@ describe('Test editing Entity', () => { }); }); - it('add new default entity rename it and add new default entity', () => { + it('should add new default entity, rename it and add new default entity', () => { cy.clickAddShapePlusIcon('Characteristic1') .then(() => cy.shapeExists('Entity1')) .then(() => cy.clickAddShapePlusIcon('Entity1')) @@ -200,7 +277,7 @@ describe('Test editing Entity', () => { }); }); - it('rename aspect and save model', () => { + it('should rename aspect and save model', () => { cy.shapeExists('AspectDefault') .then(() => cyHelp.renameElement('AspectDefault', 'NewAspect')) .then(() => { @@ -233,7 +310,7 @@ describe('Test editing Entity', () => { }); }); - it('can delete existing properties', () => { + it('should delete existing properties', () => { cy.shapeExists('property2') .then(() => cy.clickShape('property2')) .then(() => cy.get(SELECTOR_tbDeleteButton)) diff --git a/core/apps/ame-e2e/src/integration/editor/edit-enumeration-entity-values.spec.ts b/core/apps/ame-e2e/src/integration/editor/edit-enumeration-entity-values.spec.ts index 9ef380ce..d4524194 100644 --- a/core/apps/ame-e2e/src/integration/editor/edit-enumeration-entity-values.spec.ts +++ b/core/apps/ame-e2e/src/integration/editor/edit-enumeration-entity-values.spec.ts @@ -44,7 +44,7 @@ describe('Test enumeration entity value', () => { .then(() => cy.get(FIELD_dataType).clear().type('NewEntity', {force: true}).get('.mat-mdc-option').contains('NewEntity').click({force: true}) ) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.shapeExists('NewEntity')) .then(() => cy.clickAddShapePlusIcon('NewEntity')) .then(() => cy.clickAddShapePlusIcon('NewEntity')) @@ -80,7 +80,7 @@ describe('Test enumeration entity value', () => { ) .then(() => cy.get(SELECTOR_entitySaveButton).click({force: true})) .then(() => cy.wait(200)) - .then(() => cy.get(SELECTOR_editorSaveButton).click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.wait(200)) .then(() => { cy.shapeExists('ev1'); @@ -106,10 +106,10 @@ describe('Test enumeration entity value', () => { }) .then(() => cy.dbClickShape('ev2')) .then(() => cy.get(FIELD_name).should('exist').click({force: true}).clear({force: true}).type('ev2edit', {force: true})) - .then(() => cy.get(SELECTOR_editorSaveButton).click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.dbClickShape('ev3')) .then(() => cy.get(FIELD_name).should('exist').click({force: true}).clear({force: true}).type('ev3edit', {force: true})) - .then(() => cy.get(SELECTOR_editorSaveButton).click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => { cy.shapeExists('ev2edit'); cy.shapeExists('ev3edit'); @@ -118,7 +118,7 @@ describe('Test enumeration entity value', () => { .then(() => { cy.get(FIELD_propertyValueComplex).eq(0).should('have.value', 'ev2edit'); cy.get(FIELD_propertyValueComplex).eq(1).should('have.value', 'ev3edit'); - cy.get(SELECTOR_editorSaveButton).click({force: true}); + cyHelp.clickSaveButton(); }); }); @@ -128,12 +128,12 @@ describe('Test enumeration entity value', () => { .then(() => cy.dbClickShape('ev2edit')) .then(() => { cy.get(FIELD_propertyValueNotComplex).eq(0).should('exist').type('ev2Value', {force: true}); - cy.get(SELECTOR_editorSaveButton).click({force: true}); + cyHelp.clickSaveButton(); }) .then(() => cy.dbClickShape('ev3edit')) .then(() => { cy.get(FIELD_propertyValueNotComplex).eq(0).should('exist').type('ev3Value', {force: true}); - cy.get(SELECTOR_editorSaveButton).click({force: true}); + cyHelp.clickSaveButton(); }) .then(() => cy.getUpdatedRDF().then(rdf => { @@ -183,7 +183,7 @@ describe('Test enumeration entity value', () => { .then(() => checkMatCellValues([4], ['property2'])) .then(() => checkMatCellValues([5], ['TestPropertyValue3'])); }) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.clickShape('Characteristic1')) .then(() => testEntityValuesExists(['EntityValue1', 'EntityValue2', 'EntityValue3'])) .then(() => { @@ -215,7 +215,7 @@ describe('Test enumeration entity value', () => { .then(() => cy.get(SELECTOR_entitySaveButton).click({force: true})) .then(() => cy.wait(200)) .then(() => checkMatPanelTitleValues([0], ['EntityValue'])) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true}).wait(1000)) + .then(() => cyHelp.clickSaveButton().wait(1000)) .then(() => testEntityValuesExists(['EntityValue'])) .then(() => cy.getUpdatedRDF()) .then(rdf => { @@ -242,7 +242,7 @@ describe('Test enumeration entity value', () => { .then(() => cy.get(FIELD_entityValueName).should('exist').type('EntityValue', {force: true})) .then(() => cy.get(SELECTOR_entitySaveButton).click({force: true}).wait(200)) .then(() => checkMatPanelTitleValues([0], ['EntityValue'])) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})); + .then(() => cyHelp.clickSaveButton()); }); it('import new model with entity values', () => { @@ -294,7 +294,7 @@ describe('Test enumeration entity value', () => { .then(() => cy.get('mat-cell').should(cells => expect(cells).to.have.lengthOf(4))) .then(() => checkMatPanelTitleValues([0], ['test2'])) .then(() => checkMatCellValues([0, 1, 2, 3], ['property2', 'test2p2', 'property3', 'test2p3'])) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})); + .then(() => cyHelp.clickSaveButton()); }); it('edit all entity values', () => { @@ -303,21 +303,21 @@ describe('Test enumeration entity value', () => { .then(() => cy.get(FIELD_name).clear({force: true}).type('edit1', {force: true})) .then(() => cy.get(FIELD_propertyValueNotComplex).eq(0).clear({force: true}).type('property2Edit1', {force: true})) .then(() => cy.get(FIELD_propertyValueNotComplex).eq(1).clear({force: true}).type('property3Edit1', {force: true})) - .then(() => cy.get(SELECTOR_editorSaveButton).click({force: true}).wait(200)) + .then(() => cyHelp.clickSaveButton().wait(200)) .shapeExists('test2') .then(() => cy.dbClickShape('test2')) .then(() => cy.get(FIELD_name).clear({force: true}).type('edit2', {force: true})) .then(() => cy.get(FIELD_propertyValueNotComplex).eq(0).clear({force: true}).type('property2Edit2', {force: true})) .then(() => cy.get(FIELD_propertyValueNotComplex).eq(1).clear({force: true}).type('property3Edit2', {force: true})) - .then(() => cy.get(SELECTOR_editorSaveButton).click({force: true}).wait(200)) + .then(() => cyHelp.clickSaveButton().wait(200)) .shapeExists('test3') .then(() => cy.dbClickShape('test3')) .then(() => cy.get(FIELD_name).clear({force: true}).type('edit3', {force: true})) .then(() => cy.get(FIELD_propertyValueNotComplex).eq(0).clear({force: true}).type('property2Edit3', {force: true})) .then(() => cy.get(FIELD_propertyValueNotComplex).eq(1).clear({force: true}).type('property3Edit3', {force: true})) - .then(() => cy.get(SELECTOR_editorSaveButton).click({force: true}).wait(200)) + .then(() => cyHelp.clickSaveButton().wait(200)) .shapeExists('Characteristic1') .then(() => cy.dbClickShape('Characteristic1')) @@ -362,7 +362,7 @@ describe('Test enumeration entity value', () => { .then(() => cy.get(FIELD_propertyValueNotComplex).eq(1).should('exist').clear({force: true}).type('editOnlyOnEntityValueProp3', {force: true}) ) - .then(() => cy.get(SELECTOR_editorSaveButton).click({force: true}).wait(200)) + .then(() => cyHelp.clickSaveButton().wait(200)) .dbClickShape('Characteristic1') .then(() => { @@ -405,7 +405,7 @@ describe('Test enumeration entity value', () => { .get(SELECTOR_editorSaveButton) .should('be.disabled') .then(() => cy.get(FIELD_propertyValueNotComplex).eq(0).should('exist').clear().type('editOnlyOnEntityValueProp2')) - .then(() => cy.get(SELECTOR_editorSaveButton).click({force: true})) + .then(() => cyHelp.clickSaveButton()) ); }); @@ -416,10 +416,11 @@ describe('Test enumeration entity value', () => { .then(() => cy.get('[data-cy="properties-modal-button"]').click({force: true}).wait(200)) .then(() => cy.get(`input[type="checkbox"][name="property2_${FIELD_optional}"]`).click({force: true})) .then(() => cy.get('[data-cy="propertiesSaveButton"]').click({force: true}).wait(200)) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true}).wait(200)) + .then(() => cyHelp.clickSaveButton().wait(200)) .then(() => cy.dbClickShape('edit1').wait(200)) .then(() => cy.get(FIELD_propertyValueNotComplex).eq(0).should('exist').clear({force: true})) - .then(() => cy.get(SELECTOR_editorSaveButton).should('be.enabled').click({force: true})); + .then(() => cy.get(SELECTOR_editorSaveButton).should('be.enabled')) + .then(() => cyHelp.clickSaveButton()); }); it('delete all entity value one by one', () => { @@ -444,7 +445,7 @@ describe('Test enumeration entity value', () => { checkMatPanelTitleValues([1], ['test3']); checkMatCellValues([4, 5, 6, 7], ['property2', 'test3p2', 'property3', 'test3p3']); }) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.clickShape('Characteristic1')) .then(() => { cy.getUpdatedRDF().then(rdf => { @@ -461,7 +462,7 @@ describe('Test enumeration entity value', () => { checkMatPanelTitleValues([0], ['test3']); checkMatCellValues([0, 1, 2, 3], ['property2', 'test3p2', 'property3', 'test3p3']); }) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => { cy.getUpdatedRDF().then(rdf => { expect(rdf).to.contain('samm-c:values (:test3)'); @@ -483,7 +484,7 @@ describe('Test enumeration entity value', () => { .then(() => cy.get(FIELD_entityValueName).should('be.visible').type('FillGapEntityValue')) .then(() => cy.get(SELECTOR_entitySaveButton).click({force: true}).wait(200)) .then(() => checkMatPanelTitleValues([0], ['FillGapEntityValue'])) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.clickAddShapePlusIcon('Characteristic1')) .then(() => cyHelp.hasAddShapeOverlay('Characteristic1')) .then(() => { @@ -562,7 +563,7 @@ describe('Test enumeration entity value', () => { .contains('NewEntity') .click({force: true}) ) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.shapeExists('NewEntity')); }); @@ -586,7 +587,7 @@ describe('Test enumeration entity value', () => { .then(() => cy.get(FIELD_entityValueName).should('exist').type('EntityValue')) .then(() => cy.get(SELECTOR_entitySaveButton).click({force: true}).wait(200)) .then(() => checkMatPanelTitleValues([0], ['EntityValue'])) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.shapeExists('NewEntity')); }); @@ -612,7 +613,7 @@ describe('Test enumeration entity value', () => { .then(() => cy.get(FIELD_entityValueName).eq(0).should('exist').type('ev2')) .then(() => cy.get(FIELD_propertyValueNotComplex).should('exist').type('TestPropertyValue2')) .then(() => cy.get(SELECTOR_entitySaveButton).click({force: true}).wait(200)) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.dbClickShape('Characteristic2')) .then(() => { cy.get(FIELD_characteristicName).click({force: true}); @@ -646,7 +647,7 @@ describe('Test enumeration entity value', () => { .click({force: true}) ) .then(() => cy.get(SELECTOR_entitySaveButton).click({force: true}).wait(200)) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.dbClickShape('Characteristic1')) .then(() => cy.get(FIELD_characteristicName).click({force: true}).get('mat-option').contains('Enumeration').click({force: true})) .then(() => cy.get(SELECTOR_addEntityValue).click({force: true}).wait(200)) @@ -677,7 +678,7 @@ describe('Test enumeration entity value', () => { .click({force: true}) ) .then(() => cy.get(SELECTOR_entitySaveButton).click({force: true}).wait(200)) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => { cy.shapesConnected('Characteristic1', 'ev6'); cy.shapesConnected('Characteristic1', 'ev5'); @@ -706,7 +707,7 @@ describe('Test enumeration entity value', () => { .contains('ev2') .click({force: true}) ) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true}).wait(200)) + .then(() => cyHelp.clickSaveButton().wait(200)) .then(() => { cy.shapesConnected('Characteristic1', 'ev6'); cy.shapesConnected('Characteristic1', 'ev5'); @@ -732,7 +733,7 @@ describe('Test enumeration entity value', () => { .get('.mat-mdc-option') .contains('ev4') ) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true}).wait(200)) + .then(() => cyHelp.clickSaveButton().wait(200)) .then(() => { cy.shapesConnected('Characteristic1', 'ev6'); cy.shapesConnected('Characteristic1', 'ev5'); @@ -748,7 +749,7 @@ describe('Test enumeration entity value', () => { cy.dbClickShape('Characteristic1') .then(() => cy.get('.complex-value-items .bosch-ic-delete').eq(0).click({force: true})) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => { cy.shapesConnected('Characteristic1', 'ev6'); cy.shapesConnected('ev6', 'ev4'); diff --git a/core/apps/ame-e2e/src/integration/editor/edit-events.spec.ts b/core/apps/ame-e2e/src/integration/editor/edit-events.spec.ts index 79278d47..d81dc3e3 100644 --- a/core/apps/ame-e2e/src/integration/editor/edit-events.spec.ts +++ b/core/apps/ame-e2e/src/integration/editor/edit-events.spec.ts @@ -18,10 +18,10 @@ import { SELECTOR_dialogInputModel, SELECTOR_dialogStartButton, SELECTOR_ecEvent, - SELECTOR_editorSaveButton, SELECTOR_tbDeleteButton, SELECTOR_tbLoadButton, } from '../../support/constants'; +import {cyHelp} from '../../support/helpers'; describe('Test edit Events', () => { it('can load events', () => { @@ -90,7 +90,7 @@ describe('Test edit Events', () => { cy.shapeExists('event1') .then(() => cy.dbClickShape('event1')) .then(() => cy.get(FIELD_name).clear({force: true}).type('newEvent', {force: true})) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getAspect().then(aspect => { expect(aspect.name).to.equal('AspectDefault'); diff --git a/core/apps/ame-e2e/src/integration/editor/edit-operation.spec.ts b/core/apps/ame-e2e/src/integration/editor/edit-operation.spec.ts index 00d9d1d9..fa0db6ba 100644 --- a/core/apps/ame-e2e/src/integration/editor/edit-operation.spec.ts +++ b/core/apps/ame-e2e/src/integration/editor/edit-operation.spec.ts @@ -13,14 +13,7 @@ /// -import { - FIELD_inputValues, - FIELD_name, - FIELD_output, - SELECTOR_ecOperation, - SELECTOR_editorSaveButton, - SELECTOR_tbDeleteButton, -} from '../../support/constants'; +import {FIELD_inputValues, FIELD_name, FIELD_output, SELECTOR_ecOperation, SELECTOR_tbDeleteButton} from '../../support/constants'; import {cyHelp} from '../../support/helpers'; describe('Test edit operation', () => { @@ -65,7 +58,7 @@ describe('Test edit operation', () => { cy.shapeExists('operation1') .then(() => cy.dbClickShape('operation1')) .then(() => cy.get(FIELD_name).clear({force: true}).type('newOperation', {force: true})) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getAspect().then(aspect => { expect(aspect.name).to.equal('AspectDefault'); @@ -178,7 +171,7 @@ describe('Test edit operation', () => { .contains('addOutputProperty1') .click({force: true}) ) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getAspect().then(aspect => { expect(aspect.name).to.equal('AspectDefault'); @@ -210,7 +203,7 @@ describe('Test edit operation', () => { .then(() => cy.dbClickShape('newOperation')) .then(() => cy.get('[data-cy="input"]').eq(0).click({force: true})) .then(() => cy.get('[data-cy="input"]').eq(1).click({force: true})) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getAspect().then(aspect => { expect(aspect.name).to.equal('AspectDefault'); @@ -248,7 +241,7 @@ describe('Test edit operation', () => { .contains('addNewOutputProperty1') .click({force: true}) ) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getAspect().then(aspect => { expect(aspect.name).to.equal('AspectDefault'); @@ -296,7 +289,7 @@ describe('Test edit operation', () => { .contains('addNewOutputProperty2') .click({force: true}) ) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getAspect().then(aspect => { expect(aspect.name).to.equal('AspectDefault'); @@ -334,7 +327,7 @@ describe('Test edit operation', () => { .contains('addNewOutputProperty1') .click({force: true}) ) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getAspect().then(aspect => { expect(aspect.name).to.equal('AspectDefault'); @@ -373,7 +366,7 @@ describe('Test edit operation', () => { .contains('addNewOutputProperty1') .click({force: true}) ) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getAspect().then(aspect => { expect(aspect.name).to.equal('AspectDefault'); @@ -409,7 +402,7 @@ describe('Test edit operation', () => { .contains('addNewOutputProperty2') .click({force: true}) ) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getAspect().then(aspect => { expect(aspect.name).to.equal('AspectDefault'); @@ -441,7 +434,7 @@ describe('Test edit operation', () => { .then(() => cy.dbClickShape('newOperation')) .then(() => cy.get('[data-cy="input"]').eq(0).click({force: true})) .then(() => cy.get('[data-cy="input"]').eq(0).click({force: true})) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getAspect().then(aspect => { expect(aspect.name).to.equal('AspectDefault'); diff --git a/core/apps/ame-e2e/src/integration/editor/edit-property.spec.ts b/core/apps/ame-e2e/src/integration/editor/edit-property.spec.ts index 42768697..05e5e0c1 100644 --- a/core/apps/ame-e2e/src/integration/editor/edit-property.spec.ts +++ b/core/apps/ame-e2e/src/integration/editor/edit-property.spec.ts @@ -14,31 +14,42 @@ /// +import {ExampleValueInputFieldComponent} from '@ame/editor'; import { FIELD_characteristicName, + FIELD_descriptionen, FIELD_entityValueName, + FIELD_error, FIELD_name, FIELD_notInPayload, FIELD_optional, FIELD_payloadName, + FIELD_preferredNameen, + FIELD_see, + META_MODEL_description, + META_MODEL_exampleValue, + META_MODEL_preferredName, + META_MODEL_see, SELECTOR_addEntityValue, SELECTOR_ecProperty, SELECTOR_editorSaveButton, SELECTOR_entitySaveButton, + SELECTOR_exampleProperty, SELECTOR_searchEntityValueInputField, SELECTOR_tbDeleteButton, } from '../../support/constants'; +import {cyHelp} from '../../support/helpers'; // These tests are for the special case that the name of the shape is changed and the turtle file is generated correctly. describe('Test edit property', () => { - it('rename first property and new property', () => { + it('should rename first property and new property', () => { cy.visitDefault(); cy.startModelling() .then(() => cy.shapeExists('property1')) .then(() => cy.dbClickShape('property1')) .then(() => { cy.get(FIELD_name).clear({force: true}).type('test', {force: true}); - return cy.get(SELECTOR_editorSaveButton).focus().click({force: true}); + return cyHelp.clickSaveButton(); }) .then(() => cy.clickAddShapePlusIcon('AspectDefault')) .then(() => cy.getUpdatedRDF()) @@ -56,7 +67,7 @@ describe('Test edit property', () => { .then(() => cy.dbClickShape('property1')) .then(() => { cy.get(FIELD_name).clear({force: true}).type('test', {force: true}); - return cy.get(SELECTOR_editorSaveButton).focus().click({force: true}); + cyHelp.forceChangeDetection().then(() => cyHelp.clickSaveButton()); }); }); @@ -90,21 +101,142 @@ describe('Test edit property', () => { }); }); - it('rename first property and rename new added property', () => { + it('should check that all fields are visible and the order is correct', () => { + cy.shapeExists('property1') + .then(() => cy.dbClickShape('property1')) + .then(() => cy.get(FIELD_name).clear().should('be.visible').type('property1')) + .then(() => cy.get(FIELD_preferredNameen).clear().type('New Preffered Name for Property')) + .then(() => cy.get(FIELD_descriptionen).clear().type('This is a property')) + .then(() => cy.get(FIELD_see).should('be.visible')) + .then(() => cy.get(SELECTOR_exampleProperty).should('be.visible').clear().type('example')) + .then(() => cyHelp.clickSaveButton()); + }); + + it('should check incoming and outgoing edges', () => { + cy.shapeExists('property1').then(() => cy.dbClickShape('property1')); + cy.contains('Incoming edges (1)').should('exist'); + cy.contains('Outgoing edges (1)').should('exist'); + }); + + it('should validate edit property name field', () => { + cy.shapeExists('property1') + .then(() => cy.dbClickShape('property1')) + .then(() => { + cy.get(FIELD_name).clear().type('Property2#'); + cy.get(FIELD_error).should('contain', 'Please start with a lower case character followed by letters/numerals.'); + }) + .then(() => cy.get(FIELD_name).clear()) + .then(() => cy.get(FIELD_name).clear().type('property1')); + }); + + it('should edit preferredName', () => { + cy.shapeExists('property1') + .then(() => cy.dbClickShape('property1')) + .then(() => cy.get(FIELD_preferredNameen).clear().type('New Preffered Name for property')) + .then(() => cyHelp.clickSaveButton()) + .then(() => + cy + .getCellLabel('property1', META_MODEL_preferredName) + .should('eq', `${META_MODEL_preferredName} = New Preffered Name for property @en`) + ) + .then(() => cy.getUpdatedRDF()) + .then(rdf => expect(rdf).to.contain('samm:preferredName "New Preffered Name for property"@en')); + }); + + it('should edit property description field', () => { + cy.shapeExists('property1') + .then(() => cy.dbClickShape('property1')) + .then(() => cy.get(FIELD_descriptionen).clear().type('New description for the property')) + .then(() => cyHelp.clickSaveButton()) + .then(() => + cy + .getCellLabel('property1', META_MODEL_description) + .should('eq', `${META_MODEL_description} = New description for the property @en`) + ) + .then(() => cy.getUpdatedRDF().then(rdf => expect(rdf).to.contain('samm:description "New description for the property"@en'))); + }); + + it('should edit see property field', () => { + cy.shapeExists('property1') + .then(() => cy.dbClickShape('property1')) + .then(() => cy.addSeeElements('http://www.seeA.de', 'http://www.seeB.de', 'http://www.seeC.de')) + .then(() => cyHelp.clickSaveButton()) + .then(() => + cy + .getCellLabel('property1', META_MODEL_see) + .should('eq', `${META_MODEL_see} = http://www.seeA.de,http://www.seeB.de,http://www.seeC.de`) + ) + .then(() => + cy.getUpdatedRDF().then(rdf => expect(rdf).to.contain('samm:see , , ')) + ) + .then(() => + cy.getAspect().then(aspect => { + expect(aspect.properties[0].property.getSeeReferences()).to.have.length(3); + expect(aspect.properties[0].property.getSeeReferences()[2]).to.equal('http://www.seeC.de'); + }) + ); + cy.dbClickShape('property1') + .then(() => cy.removeSeeElements('http://www.seeB.de')) + .then(() => cyHelp.clickSaveButton()) + .then(() => cy.getCellLabel('property1', META_MODEL_see).should('eq', `${META_MODEL_see} = http://www.seeA.de,http://www.seeC.de`)) + .then(() => cy.getUpdatedRDF()) + .then(rdf => expect(rdf).to.contain('samm:see , ')) + .then(() => + cy.getAspect().then(aspect => { + expect(aspect.properties[0].property.getSeeReferences()).to.have.length(2); + expect(aspect.properties[0].property.getSeeReferences()[1]).to.equal('http://www.seeC.de'); + }) + ); + }); + + it('should edit see http attributes to urns', () => { + cy.shapeExists('property1') + .then(() => cy.dbClickShape('property1')) + .then(() => cy.removeSeeElements().addSeeElements('urn:irdi:eclass:0173-1#02-AAO677', 'urn:irdi:iec:0112/2///62683#ACC011#001')) + .then(() => cyHelp.clickSaveButton()) + + .then(() => + cy + .getCellLabel('property1', META_MODEL_see) + .should('eq', `${META_MODEL_see} = urn:irdi:eclass:0173-1#02-AAO677,urn:irdi:iec:0112/2///62683#ACC011#001`) + ) + .then(() => cy.getUpdatedRDF()) + .then(rdf => expect(rdf).to.contain('samm:see , ')) + .then(() => cy.getAspect()) + .then(aspect => { + expect(aspect.properties[0].property.getSeeReferences()).to.have.length(2); + expect(aspect.properties[0].property.getSeeReferences()[1]).to.equal('urn:irdi:iec:0112/2///62683#ACC011#001'); + }); + + cy.dbClickShape('property1') + .then(() => cy.removeSeeElements().addSeeElements('urn:irdi:eclass:0173-1#02-AAO677')) + .then(() => cyHelp.clickSaveButton()) + + .then(() => cy.getCellLabel('property1', META_MODEL_see).should('eq', `${META_MODEL_see} = urn:irdi:eclass:0173-1#02-AAO677`)) + .then(() => cy.getUpdatedRDF()) + .then(rdf => expect(rdf).to.contain('samm:see ')) + .then(() => cy.getAspect()) + .then(aspect => { + expect(aspect.properties[0].property.getSeeReferences()).to.have.length(1); + expect(aspect.properties[0].property.getSeeReferences()[0]).to.equal('urn:irdi:eclass:0173-1#02-AAO677'); + }); + }); + + it('should rename first property and rename new added property', () => { cy.visitDefault(); cy.startModelling() .then(() => cy.shapeExists('property1')) .then(() => cy.dbClickShape('property1')) .then(() => { cy.get(FIELD_name).clear({force: true}).type('test1', {force: true}); - return cy.get(SELECTOR_editorSaveButton).focus().click({force: true}); + return cyHelp.clickSaveButton(); }) .then(() => cy.clickAddShapePlusIcon('AspectDefault')) // Shape is not yet synced, so you cannot search for the name .then(() => cy.dbClickShape('property1')) .then(() => { cy.get(FIELD_name).clear({force: true}).type('test2', {force: true}); - return cy.get(SELECTOR_editorSaveButton).focus().click({force: true}); + return cyHelp.clickSaveButton(); }) .then(() => cy.getUpdatedRDF()) .then(rdf => { @@ -114,21 +246,21 @@ describe('Test edit property', () => { }); }); - it('rename first property and rename second added second property and add new default property', () => { + it('should rename first property and rename second added second property and add new default property', () => { cy.visitDefault(); cy.startModelling() .then(() => cy.shapeExists('property1')) .then(() => cy.dbClickShape('property1')) .then(() => { cy.get(FIELD_name).clear({force: true}).type('test1', {force: true}); - return cy.get(SELECTOR_editorSaveButton).focus().click({force: true}); + return cyHelp.clickSaveButton(); }) .then(() => cy.clickAddShapePlusIcon('AspectDefault')) // Shape is not yet synced, so you cannot search for the name .then(() => cy.dbClickShape('property1')) .then(() => { cy.get(FIELD_name).clear({force: true}).type('test2', {force: true}); - return cy.get(SELECTOR_editorSaveButton).focus().click({force: true}); + return cyHelp.clickSaveButton(); }) .then(() => cy.clickAddShapePlusIcon('AspectDefault')) .then(() => cy.getUpdatedRDF()) @@ -140,26 +272,26 @@ describe('Test edit property', () => { }); }); - it('rename property and rename second added property and rename third added default property', () => { + it('should rename property and rename second added property and rename third added default property', () => { cy.visitDefault(); cy.startModelling() .then(() => cy.shapeExists('property1')) .then(() => cy.dbClickShape('property1')) .then(() => { cy.get(FIELD_name).clear({force: true}).type('test1', {force: true}); - return cy.get(SELECTOR_editorSaveButton).focus().click({force: true}); + return cyHelp.clickSaveButton(); }) .then(() => cy.clickAddShapePlusIcon('AspectDefault')) .then(() => cy.dbClickShape('property1')) .then(() => { cy.get(FIELD_name).clear({force: true}).type('test2', {force: true}); - return cy.get(SELECTOR_editorSaveButton).focus().click({force: true}); + return cyHelp.clickSaveButton(); }) .then(() => cy.clickAddShapePlusIcon('AspectDefault')) .then(() => cy.dbClickShape('property1')) .then(() => { cy.get(FIELD_name).clear({force: true}).type('test3', {force: true}); - return cy.get(SELECTOR_editorSaveButton).focus().click({force: true}); + return cyHelp.clickSaveButton(); }) .then(() => cy.getUpdatedRDF()) .then(rdf => { @@ -180,32 +312,32 @@ describe('Test edit property', () => { .then(() => cy.dbClickShape('property1')) .then(() => { cy.get(FIELD_name).clear({force: true}).type('a', {force: true}); - return cy.get(SELECTOR_editorSaveButton).focus().click({force: true}); + return cyHelp.clickSaveButton(); }) // create b .then(() => cy.clickAddShapePlusIcon('AspectDefault')) .then(() => cy.dbClickShape('property1')) .then(() => { cy.get(FIELD_name).clear({force: true}).type('b', {force: true}); - return cy.get(SELECTOR_editorSaveButton).focus().click({force: true}); + return cyHelp.clickSaveButton(); }) // rename a to z .then(() => cy.dbClickShape('a')) .then(() => { cy.get(FIELD_name).clear({force: true}).type('z', {force: true}); - return cy.get(SELECTOR_editorSaveButton).focus().click({force: true}); + return cyHelp.clickSaveButton(); }) // rename b to a .then(() => cy.dbClickShape('b')) .then(() => { cy.get(FIELD_name).clear({force: true}).type('a', {force: true}); - return cy.get(SELECTOR_editorSaveButton).focus().click({force: true}); + return cyHelp.clickSaveButton(); }) // rename z to b .then(() => cy.dbClickShape('z')) .then(() => { cy.get(FIELD_name).clear({force: true}).type('b', {force: true}); - return cy.get(SELECTOR_editorSaveButton).focus().click({force: true}); + return cyHelp.clickSaveButton(); }) // rename b to a .then(() => cy.dbClickShape('b')) @@ -221,20 +353,20 @@ describe('Test edit property', () => { }); }); - it('rename aspect after rename property and create new default property', () => { + it('should rename aspect after rename property and create new default property', () => { cy.visitDefault(); cy.startModelling() .then(() => cy.shapeExists('property1')) .then(() => cy.dbClickShape('property1')) .then(() => { cy.get(FIELD_name).clear({force: true}).type('newProperty', {force: true}); - return cy.get(SELECTOR_editorSaveButton).focus().click({force: true}); + return cyHelp.clickSaveButton(); }) .then(() => cy.clickAddShapePlusIcon('AspectDefault')) .then(() => cy.shapeExists('AspectDefault')) .then(() => cy.dbClickShape('AspectDefault')) .then(() => cy.get(FIELD_name).clear({force: true}).type('NewAspect', {force: true})) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getUpdatedRDF()) .then(rdf => { expect(rdf).to.contain(':property1 a samm:Property.'); @@ -249,7 +381,7 @@ describe('Test edit property', () => { }); }); - it('create entity rename new created property and create new default entity property', () => { + it('should create entity rename new created property and create new default entity property', () => { cy.visitDefault(); cy.startModelling() .then(() => cy.clickAddShapePlusIcon('Characteristic1')) @@ -259,7 +391,7 @@ describe('Test edit property', () => { .then(() => cy.dbClickShape('property2')) .then(() => { cy.get(FIELD_name).clear({force: true}).type('newProperty', {force: true}); - return cy.get(SELECTOR_editorSaveButton).focus().click({force: true}); + return cyHelp.clickSaveButton(); }) .then(() => cy.clickAddShapePlusIcon('Entity1')) .then(() => cy.shapeExists('property2')) @@ -276,7 +408,7 @@ describe('Test edit property', () => { }); }); - it('rename entity after rename new created property and create new default entity property', () => { + it('should rename entity after rename new created property and create new default entity property', () => { cy.visitDefault(); cy.startModelling() .then(() => cy.clickAddShapePlusIcon('Characteristic1')) @@ -286,14 +418,14 @@ describe('Test edit property', () => { .then(() => cy.dbClickShape('property2')) .then(() => { cy.get(FIELD_name).clear({force: true}).type('newProperty', {force: true}); - return cy.get(SELECTOR_editorSaveButton).focus().click({force: true}); + return cyHelp.clickSaveButton(); }) .then(() => cy.clickAddShapePlusIcon('Entity1')) .then(() => cy.shapeExists('property2')) .then(() => cy.dbClickShape('Entity1')) .then(() => { cy.get(FIELD_name).clear({force: true}).type('NewEntity', {force: true}); - return cy.get(SELECTOR_editorSaveButton).focus().click({force: true}); + return cyHelp.clickSaveButton(); }) .then(() => cy.shapeExists('NewEntity')) .then(() => cy.getUpdatedRDF()) @@ -309,7 +441,7 @@ describe('Test edit property', () => { }); }); - it('rename entity property and create new default property and then create aspect property and rename the aspect', () => { + it('should rename entity property and create new default property and then create aspect property and rename the aspect', () => { cy.visitDefault(); cy.startModelling() .then(() => cy.clickAddShapePlusIcon('Characteristic1')) @@ -319,21 +451,21 @@ describe('Test edit property', () => { .then(() => cy.dbClickShape('property2')) .then(() => { cy.get(FIELD_name).clear({force: true}).type('newProperty', {force: true}); - return cy.get(SELECTOR_editorSaveButton).focus().click({force: true}); + return cyHelp.clickSaveButton(); }) .then(() => cy.clickAddShapePlusIcon('Entity1')) .then(() => cy.shapeExists('property2')) .then(() => cy.dbClickShape('Entity1')) .then(() => { cy.get(FIELD_name).clear({force: true}).type('NewEntity', {force: true}); - return cy.get(SELECTOR_editorSaveButton).focus().click({force: true}); + return cyHelp.clickSaveButton(); }) .then(() => cy.clickAddShapePlusIcon('AspectDefault')) .then(() => cy.shapeExists('property3')) .then(() => cy.dbClickShape('AspectDefault')) .then(() => { cy.get(FIELD_name).clear({force: true}).type('NewAspect', {force: true}); - return cy.get(SELECTOR_editorSaveButton).focus().click({force: true}); + return cyHelp.clickSaveButton(); }) .then(() => cy.shapeExists('NewAspect')) .then(() => cy.getUpdatedRDF()) @@ -366,7 +498,7 @@ describe('Test edit property', () => { }) .then(() => cy.get('[data-cy="propertiesSaveButton"]').click({force: true})) .then(() => cy.wait(500)) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getUpdatedRDF()) .then(rdf => { expect(rdf).to.contain(':property1 a samm:Property;\n' + ' samm:characteristic :Characteristic1.'); @@ -393,7 +525,7 @@ describe('Test edit property', () => { .then(() => cy.get(SELECTOR_addEntityValue).click({force: true}).wait(200)) .then(() => cy.get(FIELD_entityValueName).should('exist').type('EntityValue', {force: true})) .then(() => cy.get(SELECTOR_entitySaveButton).click({force: true}).wait(200)) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.clickAddShapePlusIcon('Entity1')) .then(() => cy.dbClickShape('Entity1')) .then(() => cy.get('[data-cy="properties-modal-button"]').click({force: true})) @@ -403,7 +535,7 @@ describe('Test edit property', () => { }) .then(() => cy.get('[data-cy="propertiesSaveButton"]').click({force: true}).should('not.exist')) .then(() => cy.wait(500)) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getUpdatedRDF()) .then(rdf => { expect(rdf).to.contain( @@ -425,7 +557,7 @@ describe('Test edit property', () => { .then(() => cy.wait(500)) .then(() => cy.get('[data-cy="propertiesSaveButton"]').click({force: true})) .then(() => cy.wait(500)) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getUpdatedRDF()) .then(rdf => { expect(rdf).to.contain(':property1 a samm:Property;\n' + ' samm:characteristic :Characteristic1.'); diff --git a/core/apps/ame-e2e/src/integration/editor/edit-time-series-entity.spec.ts b/core/apps/ame-e2e/src/integration/editor/edit-time-series-entity.spec.ts index 5d2e1011..f42da452 100644 --- a/core/apps/ame-e2e/src/integration/editor/edit-time-series-entity.spec.ts +++ b/core/apps/ame-e2e/src/integration/editor/edit-time-series-entity.spec.ts @@ -17,10 +17,10 @@ import { FIELD_extends, SELECTOR_dialogInputModel, SELECTOR_dialogStartButton, - SELECTOR_editorSaveButton, SELECTOR_tbDeleteButton, SELECTOR_tbLoadButton, } from '../../support/constants'; +import {cyHelp} from '../../support/helpers'; describe('Time Series Entity', () => { function createTimeSeriesEntity() { @@ -28,7 +28,7 @@ describe('Time Series Entity', () => { .then(() => cy.dbClickShape('Entity1')) .then(() => cy.get(FIELD_extends).type('TimeSeriesEntity', {force: true})) .then(() => cy.get('[data-cy="TimeSeriesEntity"]').click({force: true})) - .then(() => cy.get(SELECTOR_editorSaveButton).click({force: true})); + .then(() => cyHelp.clickSaveButton()); } it('should create TimeSeriesEntity with its properties', () => { diff --git a/core/apps/ame-e2e/src/integration/editor/edit-trait.spec.ts b/core/apps/ame-e2e/src/integration/editor/edit-trait.spec.ts index b73a184f..d3f541f1 100644 --- a/core/apps/ame-e2e/src/integration/editor/edit-trait.spec.ts +++ b/core/apps/ame-e2e/src/integration/editor/edit-trait.spec.ts @@ -13,7 +13,8 @@ /// -import {FIELD_descriptionen, FIELD_preferredNameen, SELECTOR_editorSaveButton} from '../../support/constants'; +import {FIELD_descriptionen, FIELD_preferredNameen} from '../../support/constants'; +import {cyHelp} from '../../support/helpers'; describe('Test editing Trait', () => { it('can add new and rename', () => { @@ -34,20 +35,17 @@ describe('Test editing Trait', () => { cy.shapeExists('Property1Trait').then(() => { cy.dbClickShape('Property1Trait').then(() => { cy.get(FIELD_descriptionen).clear({force: true}).type('New description for the new created trait', {force: true}); - cy.get(SELECTOR_editorSaveButton) - .focus() - .click({force: true}) - .then(() => { - cy.getUpdatedRDF().then(() => { - // TODO: resolve after validator fix - // expect(rdf).to.contain('samm:description "New description for the new created trait"@en'); - cy.getAspect().then(aspect => { - expect(aspect.properties[0].property.characteristic.getDescription('en')).to.equal( - 'New description for the new created trait' - ); - }); + cyHelp.clickSaveButton().then(() => { + cy.getUpdatedRDF().then(() => { + // TODO: resolve after validator fix + // expect(rdf).to.contain('samm:description "New description for the new created trait"@en'); + cy.getAspect().then(aspect => { + expect(aspect.properties[0].property.characteristic.getDescription('en')).to.equal( + 'New description for the new created trait' + ); }); }); + }); }); }); }); @@ -56,14 +54,11 @@ describe('Test editing Trait', () => { cy.shapeExists('Property1Trait').then(() => { cy.dbClickShape('Property1Trait').then(() => { cy.get(FIELD_preferredNameen).clear({force: true}).type('new-preferredName'); - cy.get(SELECTOR_editorSaveButton) - .focus() - .click({force: true}) - .then(() => { - cy.getUpdatedRDF().then(rdf => { - expect(rdf).to.contain('samm:preferredName "new-preferredName"@en'); - }); + cyHelp.clickSaveButton().then(() => { + cy.getUpdatedRDF().then(rdf => { + expect(rdf).to.contain('samm:preferredName "new-preferredName"@en'); }); + }); }); }); }); diff --git a/core/apps/ame-e2e/src/integration/editor/edit-unit.spec.ts b/core/apps/ame-e2e/src/integration/editor/edit-unit.spec.ts index 5e6d1987..13f77ffe 100644 --- a/core/apps/ame-e2e/src/integration/editor/edit-unit.spec.ts +++ b/core/apps/ame-e2e/src/integration/editor/edit-unit.spec.ts @@ -13,13 +13,7 @@ /// -import { - FIELD_characteristicName, - FIELD_name, - FIELD_unit, - SELECTOR_editorSaveButton, - SELECTOR_tbDeleteButton, -} from '../../support/constants'; +import {FIELD_characteristicName, FIELD_name, FIELD_unit, SELECTOR_tbDeleteButton} from '../../support/constants'; import {cyHelp} from '../../support/helpers'; describe('Test editing Unit', () => { @@ -38,7 +32,7 @@ describe('Test editing Unit', () => { .contains('CustomUnit1') .click({force: true}) ) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cyHelp.hasAddShapeOverlay('Quantifiable1')) .then(hasAddOverlay => expect(hasAddOverlay).equal(true)) .then(() => { @@ -69,7 +63,7 @@ describe('Test editing Unit', () => { .contains('CustomUnit2') .click({force: true}) ) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => { cy.getAspect().then(aspect => { expect(aspect.properties[0].property.characteristic.name).to.equal('Quantifiable1'); @@ -92,7 +86,7 @@ describe('Test editing Unit', () => { it('can remove unit connection in edit view', () => { cy.dbClickShape('Quantifiable1') .then(() => cy.get('[data-cy=clear-unit-button]').click({force: true})) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => { cy.getAspect().then(aspect => { expect(aspect.properties[0].property.characteristic.name).to.equal('Quantifiable1'); @@ -123,7 +117,7 @@ describe('Test editing Unit', () => { .contains('CustomUnit2') .click({force: true}) ) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.clickShape('CustomUnit2')) .then(() => cy.get(SELECTOR_tbDeleteButton).click({force: true})) .then(() => @@ -156,11 +150,11 @@ describe('Test editing Unit', () => { .contains('CustomUnit1') .click({force: true}) ) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.dbClickShape('Quantifiable1')) .then(() => cy.get(FIELD_characteristicName).click({force: true}).get('mat-option').contains('Measurement').click({force: true})) .then(() => cy.get(FIELD_name).clear({force: true}).type('Measurement1', {force: true})) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cyHelp.hasAddShapeOverlay('Measurement1')) .then(hasAddOverlay => expect(hasAddOverlay).equal(true)) .then(() => { @@ -188,7 +182,7 @@ describe('Test editing Unit', () => { .contains('CustomUnit1') .click({force: true}) ) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cyHelp.hasAddShapeOverlay('Duration1')) .then(hasAddOverlay => expect(hasAddOverlay).equal(true)) .then(() => { @@ -206,7 +200,7 @@ describe('Test editing Unit', () => { .then(() => cy.dbClickShape('Duration1')) .then(() => cy.get('[data-cy=clear-unit-button]').click({force: true})) .then(() => cy.get(FIELD_unit).clear({force: true}).type('day').get('mat-option').eq(1).contains('day').click({force: true})) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cyHelp.hasAddShapeOverlay('Duration1')) .then(hasAddOverlay => expect(hasAddOverlay).equal(true)) .then(() => { diff --git a/core/apps/ame-e2e/src/integration/editor/elements-count.spec.ts b/core/apps/ame-e2e/src/integration/editor/elements-count.spec.ts new file mode 100644 index 00000000..ebbb94ec --- /dev/null +++ b/core/apps/ame-e2e/src/integration/editor/elements-count.spec.ts @@ -0,0 +1,260 @@ +/* eslint-disable cypress/no-unnecessary-waiting */ +/* + * Copyright (c) 2023 Robert Bosch Manufacturing Solutions GmbH + * + * See the AUTHORS file(s) distributed with this work for + * additional information regarding authorship. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + */ + +/// + +import {cyHelp} from '../../support/helpers'; +import {SELECTOR_dialogStartButton, SELECTOR_openNamespacesButton} from '../../support/constants'; +import {setUpDynamicModellingInterceptors, setUpStaticModellingInterceptors} from '../../support/api-mocks'; +import {awaitValidateModelRequest} from '../../support/api-mock-helpers'; + +describe('Elements count', () => { + describe('Movement model', () => { + it('should display elements count for incoming & outgoing edges', () => { + cy.intercept('POST', 'http://localhost:9091/ame/api/models/validate', {fixture: 'model-validation-response.json'}); + cy.visitDefault(); + cy.fixture('/default-models/movement.txt') + .then(rdfString => cyHelp.loadCustomModel(rdfString)) + .then(() => { + cy.get(SELECTOR_dialogStartButton).click(); + + cy.dbClickShape('Movement'); + cy.contains('Incoming edges').should('not.exist'); + cy.contains('Outgoing edges (4)').should('exist'); + + cy.dbClickShape('isMoving'); + cy.contains('Incoming edges (1)').should('exist'); + cy.contains('Outgoing edges (1)').should('exist'); + + cy.dbClickShape('position'); + cy.contains('Incoming edges (1)').should('exist'); + cy.contains('Outgoing edges (1)').should('exist'); + + cy.dbClickShape('speed'); + cy.contains('Incoming edges (1)').should('exist'); + cy.contains('Outgoing edges (1)').should('exist'); + + cy.dbClickShape('speedLimitWarning'); + cy.contains('Incoming edges (1)').should('exist'); + cy.contains('Outgoing edges (1)').should('exist'); + + cy.dbClickShape('Boolean'); + cy.contains('Incoming edges (1)').should('exist'); + cy.contains('Outgoing edges').should('not.exist'); + + cy.dbClickShape('SpatialPositionCharacteristic'); + cy.contains('Incoming edges (1)').should('exist'); + cy.contains('Outgoing edges (1)').should('exist'); + + cy.dbClickShape('Speed'); + cy.contains('Incoming edges (1)').should('exist'); + cy.contains('Outgoing edges (1)').should('exist'); + + cy.dbClickShape('TrafficLight'); + cy.contains('Incoming edges (1)').should('exist'); + cy.contains('Outgoing edges').should('not.exist'); + + cy.dbClickShape('SpatialPosition'); + cy.contains('Incoming edges (1)').should('exist'); + cy.contains('Outgoing edges (3)').should('exist'); + + cy.dbClickShape('kilometrePerHour'); + cy.contains('Incoming edges (1)').should('exist'); + cy.contains('Outgoing edges').should('not.exist'); + + cy.dbClickShape('latitude'); + cy.contains('Incoming edges (1)').should('exist'); + cy.contains('Outgoing edges (1)').should('exist'); + + cy.dbClickShape('longitude'); + cy.contains('Incoming edges (1)').should('exist'); + cy.contains('Outgoing edges (1)').should('exist'); + + cy.dbClickShape('altitude'); + cy.contains('Incoming edges (1)').should('exist'); + cy.contains('Outgoing edges (1)').should('exist'); + + cy.dbClickShape('Coordinate'); + cy.contains('Incoming edges (2)').should('exist'); + cy.contains('Outgoing edges (1)').should('exist'); + + cy.dbClickShape('MetresAboveMeanSeaLevel'); + cy.contains('Incoming edges (1)').should('exist'); + cy.contains('Outgoing edges (1)').should('exist'); + + cy.dbClickShape('degreeUnitOfAngle'); + cy.contains('Incoming edges (1)').should('exist'); + cy.contains('Outgoing edges').should('not.exist'); + + cy.dbClickShape('metre'); + cy.contains('Incoming edges (1)').should('exist'); + cy.contains('Outgoing edges').should('not.exist'); + }); + }); + + it('should display elements count in sidebar', () => { + cy.intercept('POST', 'http://localhost:9091/ame/api/models/validate', {fixture: 'model-validation-response.json'}); + const namespacesConfig = { + aspectDefault: { + name: 'org.eclipse.digitaltwin:1.0.0', + files: [ + { + name: 'AspectDefault.ttl', + response: {fixture: '/default-models/aspect-default.txt'}, + }, + ], + }, + movement: { + name: 'org.eclipse.examples.movement:1.0.0', + files: [ + { + name: 'Movement.ttl', + response: {fixture: '/default-models/movement.txt'}, + }, + ], + }, + }; + + setUpStaticModellingInterceptors(); + setUpDynamicModellingInterceptors(namespacesConfig); + + cy.visitDefault(); + cy.fixture(namespacesConfig.aspectDefault.files[0].response.fixture) + .then(rdfString => cyHelp.loadCustomModel(rdfString)) + .then(() => { + cy.get(SELECTOR_dialogStartButton).click(); + return awaitValidateModelRequest(`:AspectDefault`); + }) + .then(({body}) => { + namespacesConfig.aspectDefault.files[0].response = body; + setUpDynamicModellingInterceptors(namespacesConfig); + }) + .then(() => cy.fixture(namespacesConfig.movement.files[0].response.fixture)) + .then(rdfString => cyHelp.loadCustomModel(rdfString)) + .then(() => { + cy.get(SELECTOR_dialogStartButton).click(); + return awaitValidateModelRequest(`:Movement`); + }) + .then(({body}) => { + namespacesConfig.movement.files[0].response = body; + setUpDynamicModellingInterceptors(namespacesConfig); + }) + .then(() => cy.startModelling()) + .then(() => { + cy.get(SELECTOR_openNamespacesButton).click({force: true}); + cy.contains('Movement.ttl').click(); + cy.contains('Properties (7)').should('exist'); + cy.contains('Characteristics (5)').should('exist'); + cy.contains('Entities (1)').should('exist'); + }); + }); + }); + + describe('Enumeration instances model', () => { + it('should display elements count for incoming & outgoing edges', () => { + cy.intercept('POST', 'http://localhost:9091/ame/api/models/validate', {fixture: 'model-validation-response.json'}); + cy.visitDefault(); + cy.fixture('/enumeration-instances.txt') + .then(rdfString => cyHelp.loadCustomModel(rdfString)) + .then(() => { + cy.get(SELECTOR_dialogStartButton).click(); + + cy.dbClickShape('EnumerationInstances'); + cy.contains('Incoming edges').should('not.exist'); + cy.contains('Outgoing edges (1)').should('exist'); + + cy.dbClickShape('enumerationInstancesProperty1'); + cy.contains('Incoming edges (1)').should('exist'); + cy.contains('Outgoing edges (1)').should('exist'); + + cy.dbClickShape('enumerationInstancesCharacteristic1'); + cy.contains('Incoming edges (1)').should('exist'); + cy.contains('Outgoing edges (4)').should('exist'); + + cy.dbClickShape('enumerationInstancesEntity1'); + cy.contains('Incoming edges (4)').should('exist'); + cy.contains('Outgoing edges').should('not.exist'); + + cy.dbClickShape('enumerationInstancesInstance1'); + cy.contains('Incoming edges (1)').should('exist'); + cy.contains('Outgoing edges (1)').should('exist'); + + cy.dbClickShape('enumerationInstancesInstance2'); + cy.contains('Incoming edges (1)').should('exist'); + cy.contains('Outgoing edges (1)').should('exist'); + + cy.dbClickShape('enumerationInstancesInstance3'); + cy.contains('Incoming edges (1)').should('exist'); + cy.contains('Outgoing edges (1)').should('exist'); + }); + }); + + it('should display elements count in sidebar', () => { + cy.intercept('POST', 'http://localhost:9091/ame/api/models/validate', {fixture: 'model-validation-response.json'}); + const namespacesConfig = { + aspectDefault: { + name: 'org.eclipse.digitaltwin:1.0.0', + files: [ + { + name: 'AspectDefault.ttl', + response: {fixture: '/default-models/aspect-default.txt'}, + }, + ], + }, + enumerationInstances: { + name: 'org.eclipse.digitaltwin:1.0.0', + files: [ + { + name: 'EnumerationInstances.ttl', + response: {fixture: '/enumeration-instances.txt'}, + }, + ], + }, + }; + + setUpStaticModellingInterceptors(); + setUpDynamicModellingInterceptors(namespacesConfig); + + cy.visitDefault(); + cy.fixture(namespacesConfig.aspectDefault.files[0].response.fixture) + .then(rdfString => cyHelp.loadCustomModel(rdfString)) + .then(() => { + cy.get(SELECTOR_dialogStartButton).click(); + return awaitValidateModelRequest(`:AspectDefault`); + }) + .then(({body}) => { + namespacesConfig.aspectDefault.files[0].response = body; + setUpDynamicModellingInterceptors(namespacesConfig); + }) + .then(() => cy.fixture(namespacesConfig.enumerationInstances.files[0].response.fixture)) + .then(rdfString => cyHelp.loadCustomModel(rdfString)) + .then(() => { + cy.get(SELECTOR_dialogStartButton).click(); + return awaitValidateModelRequest(`:EnumerationInstances`); + }) + .then(({body}) => { + namespacesConfig.enumerationInstances.files[0].response = body; + setUpDynamicModellingInterceptors(namespacesConfig); + }) + .then(() => cy.startModelling()) + .then(() => { + cy.get(SELECTOR_openNamespacesButton).click({force: true}); + cy.contains('EnumerationInstances.ttl').click(); + cy.contains('Properties (1)').should('exist'); + cy.contains('Characteristics (1)').should('exist'); + cy.contains('Entities (1)').should('exist'); + }); + }); + }); +}); diff --git a/core/apps/ame-e2e/src/integration/editor/file-resource-entity.spec.ts b/core/apps/ame-e2e/src/integration/editor/file-resource-entity.spec.ts index 972cabcb..60a980f0 100644 --- a/core/apps/ame-e2e/src/integration/editor/file-resource-entity.spec.ts +++ b/core/apps/ame-e2e/src/integration/editor/file-resource-entity.spec.ts @@ -13,7 +13,8 @@ /// -import {FIELD_extends, SELECTOR_editorSaveButton, SELECTOR_tbDeleteButton} from '../../support/constants'; +import {FIELD_extends, SELECTOR_tbDeleteButton} from '../../support/constants'; +import {cyHelp} from '../../support/helpers'; describe('Time Series Entity', () => { function createFileResourceEntity() { @@ -21,7 +22,7 @@ describe('Time Series Entity', () => { .then(() => cy.dbClickShape('Entity1')) .then(() => cy.get(FIELD_extends).type('FileResource', {force: true})) .then(() => cy.get('[data-cy="FileResource"]').click({force: true})) - .then(() => cy.get(SELECTOR_editorSaveButton).click({force: true})); + .then(() => cyHelp.clickSaveButton()); } it('should create FileResource with its properties', () => { diff --git a/core/apps/ame-e2e/src/integration/editor/load-model.spec.ts b/core/apps/ame-e2e/src/integration/editor/load-model.spec.ts index 0a3e6425..aac2c7a8 100644 --- a/core/apps/ame-e2e/src/integration/editor/load-model.spec.ts +++ b/core/apps/ame-e2e/src/integration/editor/load-model.spec.ts @@ -93,7 +93,7 @@ describe('Test load different characteristics', () => { cy.get('[data-cy="minValue"]').type('1', {force: true}).click({force: true}); cy.get('[data-cy="maxValue"]').type('10', {force: true}).click({force: true}); }) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getUpdatedRDF()) .then(rdf => { expect(rdf).to.contain('samm-c:constraint :Constraint1'); @@ -117,7 +117,7 @@ describe('Test load different characteristics', () => { .contains('amperePerMetre') .click({force: true}); }) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getUpdatedRDF().then(rdf => expect(rdf).to.contain('samm-c:unit unit:amperePerMetre'))); }); @@ -127,7 +127,7 @@ describe('Test load different characteristics', () => { .then(() => cy.get(FIELD_dataType).clear({force: true}).type('double', {force: true}).get(FIELD_dataTypeOption).eq(0).click({force: true}) ) - .then(() => cy.get(SELECTOR_editorSaveButton).click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getUpdatedRDF().then(rdf => expect(rdf).to.contain('samm:dataType xsd:double'))); }); @@ -135,12 +135,17 @@ describe('Test load different characteristics', () => { cy.clickAddTraitPlusIcon('TestMeasurement') .then(() => cy.dbClickShape('Constraint2')) .then(() => { - cy.get(FIELD_constraintName).click({force: true}).get('mat-option').contains('FixedPointConstraint').click({force: true}); + cy.get(FIELD_constraintName) + .click({force: true}) + .then(() => cyHelp.forceChangeDetection()) + .get('mat-option') + .contains('FixedPointConstraint') + .click({force: true}); cy.get(SELECTOR_editorSaveButton).should('be.disabled'); cy.get('[data-cy="scale"]').type('1', {force: true}).click({force: true}); cy.get('[data-cy="integer"]').type('1', {force: true}).click({force: true}); }) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getUpdatedRDF()) .then(rdf => { expect(rdf).to.contain('samm-c:constraint :Constraint2'); @@ -154,6 +159,7 @@ describe('Test load different characteristics', () => { cy.dbClickShape('Constraint2') .then(() => cy.get('[data-cy="scale"]').clear({force: true}).type('-1', {force: true})) .then(() => cy.get('[data-cy="integer"]').click({force: true})) + .then(() => cyHelp.forceChangeDetection()) .then(() => { cy.get('mat-error').should('have.text', 'Please provide a positive number'); cy.get(SELECTOR_editorSaveButton).should('be.disabled'); @@ -165,6 +171,7 @@ describe('Test load different characteristics', () => { cy.dbClickShape('Constraint2') .then(() => cy.get('[data-cy="integer"]').clear({force: true}).type('-1', {force: true})) .then(() => cy.get('[data-cy="scale"]').click({force: true})) + .then(() => cyHelp.forceChangeDetection()) .then(() => { cy.get('mat-error').should('have.text', 'Please provide a positive integer'); cy.get(SELECTOR_editorSaveButton).should('be.disabled'); @@ -175,7 +182,7 @@ describe('Test load different characteristics', () => { it('can modify scale', () => { cy.dbClickShape('Constraint2') .then(() => cy.get('[data-cy="scale"]').clear({force: true}).type('10', {force: true}).click({force: true})) - .then(() => cy.get(SELECTOR_editorSaveButton).click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getUpdatedRDF()) .then(rdf => { expect(rdf).to.contain('samm-c:scale "10"^^xsd:positiveInteger'); @@ -194,7 +201,7 @@ describe('Test load different characteristics', () => { .then(() => cy.get(SELECTOR_editorCancelButton).focus().click({force: true})) .then(() => cy.dbClickShape('Constraint3')) .then(() => cy.get('mat-option').contains('EncodingConstraint').click({force: true})) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getUpdatedRDF()) .then(rdf => { expect(rdf).to.contain('samm-c:constraint :Constraint3'); @@ -217,7 +224,7 @@ describe('Test load different characteristics', () => { cy.get('mat-option').contains('RegularExpressionConstraint').click({force: true}); }) .then(() => cy.get('[data-cy="value"]').type('*', {force: true})) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getUpdatedRDF()) .then(rdf => { expect(rdf).to.contain('samm-c:constraint :Constraint4'); @@ -241,7 +248,7 @@ describe('Test load different characteristics', () => { cy.get('[data-cy="maxValue"]').type('100', {force: true}); cy.get('[data-cy="minValue"]').type('1', {force: true}); }) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getUpdatedRDF()) .then(rdf => { expect(rdf).to.contain('samm-c:constraint :Constraint5'); @@ -272,7 +279,7 @@ describe('Test load different characteristics', () => { .contains('de-DE') .click({force: true}); }) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getUpdatedRDF()) .then(rdf => { expect(rdf).to.contain('samm-c:constraint :Constraint6'); @@ -300,7 +307,7 @@ describe('Test load different characteristics', () => { .contains('en') .click({force: true}); }) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getUpdatedRDF()) .then(rdf => { expect(rdf).to.contain('samm-c:constraint :Constraint7'); diff --git a/core/apps/ame-e2e/src/integration/editor/migrate-common-attributes.spec.ts b/core/apps/ame-e2e/src/integration/editor/migrate-common-attributes.spec.ts index f6b887f7..513b454e 100644 --- a/core/apps/ame-e2e/src/integration/editor/migrate-common-attributes.spec.ts +++ b/core/apps/ame-e2e/src/integration/editor/migrate-common-attributes.spec.ts @@ -25,8 +25,8 @@ import { FIELD_unit, FIELD_values, SELECTOR_ecCharacteristic, - SELECTOR_editorSaveButton, } from '../../support/constants'; +import {cyHelp} from '../../support/helpers'; describe('Test migration of common attributes on Constraint/Characteristic type change', () => { it('can add new', () => { @@ -44,7 +44,7 @@ describe('Test migration of common attributes on Constraint/Characteristic type .then(() => cy.get(FIELD_dataType).clear({force: true}).type('string', {force: true}).get(FIELD_dataTypeOption).eq(1).click({force: true}) ) - .then(() => cy.get(SELECTOR_editorSaveButton).click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getUpdatedRDF()) .then(rdf => expect(rdf).to.contain( @@ -61,7 +61,7 @@ describe('Test migration of common attributes on Constraint/Characteristic type cy.shapeExists('Characteristic1') .then(() => cy.dbClickShape('Characteristic1')) .then(() => cy.get(FIELD_characteristicName).click({force: true}).get('mat-option').contains('Code').click({force: true})) - .then(() => cy.get(SELECTOR_editorSaveButton).click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getUpdatedRDF()) .then(rdf => expect(rdf).to.contain( @@ -88,7 +88,7 @@ describe('Test migration of common attributes on Constraint/Characteristic type .contains('Characteristic2') .click({force: true}) ) - .then(() => cy.get(SELECTOR_editorSaveButton).click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getUpdatedRDF()) .then(rdf => { expect(rdf).to.contain( @@ -106,7 +106,7 @@ describe('Test migration of common attributes on Constraint/Characteristic type cy.shapeExists('Characteristic1') .then(() => cy.dbClickShape('Characteristic1')) .then(() => cy.get(FIELD_characteristicName).click({force: true}).get('mat-option').contains('List').click({force: true})) - .then(() => cy.get(SELECTOR_editorSaveButton).click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getUpdatedRDF()) .then(rdf => expect(rdf).to.contain( @@ -124,7 +124,7 @@ describe('Test migration of common attributes on Constraint/Characteristic type cy.shapeExists('Characteristic1') .then(() => cy.dbClickShape('Characteristic1')) .then(() => cy.get(FIELD_characteristicName).click({force: true}).get('mat-option').contains('Set').click({force: true})) - .then(() => cy.get(SELECTOR_editorSaveButton).click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getUpdatedRDF()) .then(rdf => expect(rdf).to.contain( @@ -142,7 +142,7 @@ describe('Test migration of common attributes on Constraint/Characteristic type cy.shapeExists('Characteristic1') .then(() => cy.dbClickShape('Characteristic1')) .then(() => cy.get(FIELD_characteristicName).click({force: true}).get('mat-option').contains('SortedSet').click({force: true})) - .then(() => cy.get(SELECTOR_editorSaveButton).click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getUpdatedRDF()) .then(rdf => expect(rdf).to.contain( @@ -160,7 +160,7 @@ describe('Test migration of common attributes on Constraint/Characteristic type cy.shapeExists('Characteristic1') .then(() => cy.dbClickShape('Characteristic1')) .then(() => cy.get(FIELD_characteristicName).click({force: true}).get('mat-option').contains('TimeSeries').click({force: true})) - .then(() => cy.get(SELECTOR_editorSaveButton).click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getUpdatedRDF()) .then(rdf => expect(rdf).to.contain( @@ -179,7 +179,7 @@ describe('Test migration of common attributes on Constraint/Characteristic type .then(() => cy.dbClickShape('Characteristic1')) .then(() => cy.get(FIELD_characteristicName).click({force: true}).get('mat-option').contains('Enumeration').click({force: true})) .then(() => cy.get(FIELD_values).type('1{enter}2{enter}a{enter}b{enter}3{enter}4{enter}', {force: true})) - .then(() => cy.get(SELECTOR_editorSaveButton).click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getUpdatedRDF()) .then(rdf => { expect(rdf).to.contain( @@ -198,7 +198,7 @@ describe('Test migration of common attributes on Constraint/Characteristic type .then(() => cy.dbClickShape('Characteristic1')) .then(() => cy.get(FIELD_characteristicName).click({force: true}).get('mat-option').contains('State').click({force: true})) .then(() => cy.get(FIELD_defaultValue).type('testState', {force: true})) - .then(() => cy.get(SELECTOR_editorSaveButton).click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getUpdatedRDF()) .then(rdf => { expect(rdf).contain(':Characteristic1 a samm-c:State'); @@ -215,7 +215,7 @@ describe('Test migration of common attributes on Constraint/Characteristic type .then(() => cy.dbClickShape('Characteristic1')) .then(() => cy.get(FIELD_characteristicName).click({force: true}).get('mat-option').contains('Duration').click({force: true})) .then(() => cy.get(FIELD_unit).clear({force: true}).type('commonYe').get('mat-option').contains('commonYear').click({force: true})) - .then(() => cy.get(SELECTOR_editorSaveButton).click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getUpdatedRDF()) .then(rdf => expect(rdf).to.contain( @@ -236,7 +236,7 @@ describe('Test migration of common attributes on Constraint/Characteristic type .then(() => cy.get(FIELD_unit).should('have.value', 'commonYear')) .then(() => cy.get('[data-cy=clear-unit-button]').click({force: true})) .then(() => cy.get(FIELD_unit).clear({force: true}).type('ampe').get('mat-option').contains('ampere').click({force: true})) - .then(() => cy.get(SELECTOR_editorSaveButton).click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getUpdatedRDF()) .then(rdf => expect(rdf).to.contain( @@ -254,7 +254,7 @@ describe('Test migration of common attributes on Constraint/Characteristic type cy.shapeExists('Characteristic1') .then(() => cy.dbClickShape('Characteristic1')) .then(() => cy.get(FIELD_characteristicName).click({force: true}).get('mat-option').contains('SingleEntity').click({force: true})) - .then(() => cy.get(SELECTOR_editorSaveButton).click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getUpdatedRDF()) .then(rdf => expect(rdf).to.contain( @@ -273,7 +273,7 @@ describe('Test migration of common attributes on Constraint/Characteristic type .then(() => cy.get(FIELD_characteristicName).click({force: true}).get('mat-option').contains('Characteristic').click({force: true})) .then(() => cy.get(FIELD_characteristicName).click({force: true}).get('mat-option').contains('SingleEntity').click({force: true})) .then(() => cy.get(FIELD_name).should('have.value', 'Characteristic1')) - .then(() => cy.get(SELECTOR_editorSaveButton).click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getUpdatedRDF()) .then(rdf => expect(rdf).to.contain( @@ -292,7 +292,7 @@ describe('Test migration of common attributes on Constraint/Characteristic type .then(() => cy.get(FIELD_characteristicName).click({force: true}).get('mat-option').contains('Measurement').click({force: true})) .then(() => cy.get(FIELD_unit).should('have.value', '')) .then(() => cy.get(FIELD_unit).clear({force: true}).type('acr').get('mat-option').contains('acre').click({force: true})) - .then(() => cy.get(SELECTOR_editorSaveButton).click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.clickAddShapePlusIcon('Characteristic1')) .then(() => cy.shapeExists('Entity1')) .then(() => cy.getUpdatedRDF()) @@ -313,7 +313,7 @@ describe('Test migration of common attributes on Constraint/Characteristic type .then(() => cy.get(FIELD_unit).clear({force: true}).type('day').get('mat-option[data-unit-cy="day"]').contains('day').click({force: true}) ) - .then(() => cy.get(SELECTOR_editorSaveButton).click({force: true})) + .then(() => cyHelp.clickSaveButton()) .then(() => cy.getUpdatedRDF()) .then(rdf => expect(rdf).to.contain( diff --git a/core/apps/ame-e2e/src/integration/editor/point3d-entity.spec.ts b/core/apps/ame-e2e/src/integration/editor/point3d-entity.spec.ts index 2f59f210..f72fe714 100644 --- a/core/apps/ame-e2e/src/integration/editor/point3d-entity.spec.ts +++ b/core/apps/ame-e2e/src/integration/editor/point3d-entity.spec.ts @@ -13,7 +13,8 @@ /// -import {FIELD_extends, SELECTOR_editorSaveButton, SELECTOR_tbDeleteButton} from '../../support/constants'; +import {FIELD_extends, SELECTOR_tbDeleteButton} from '../../support/constants'; +import {cyHelp} from '../../support/helpers'; describe('Time Series Entity', () => { function createPoint3dEntity() { @@ -21,7 +22,7 @@ describe('Time Series Entity', () => { .then(() => cy.dbClickShape('Entity1')) .then(() => cy.get(FIELD_extends).type('Point3d', {force: true})) .then(() => cy.get('[data-cy="Point3d"]').click({force: true})) - .then(() => cy.get(SELECTOR_editorSaveButton).click({force: true})); + .then(() => cyHelp.clickSaveButton()); } it('should create Point3d with its properties', () => { diff --git a/core/apps/ame-e2e/src/integration/export/export-namespace.spec.ts b/core/apps/ame-e2e/src/integration/export/export-namespace.spec.ts new file mode 100644 index 00000000..238f38f1 --- /dev/null +++ b/core/apps/ame-e2e/src/integration/export/export-namespace.spec.ts @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2023 Robert Bosch Manufacturing Solutions GmbH + * + * See the AUTHORS file(s) distributed with this work for + * additional information regarding authorship. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + */ + +/// + +import { + SELECTOR_dialogStartButton, + SELECTOR_enNamespaceList, + SELECTOR_tbSaveButton, + SELECTOR_tbSaveMenuExportNamespaceButton, +} from '../../support/constants'; +import {cyHelp} from '../../support/helpers'; +import {setUpDynamicModellingInterceptors, setUpStaticModellingInterceptors} from '../../support/api-mocks'; +import {awaitValidateModelRequest} from '../../support/api-mock-helpers'; + +describe('Export namespace', () => { + it('should have all namespaces ready for export from the very start', () => { + const namespacesConfig = { + aspectDefault: { + name: 'org.eclipse.digitaltwin:1.0.0', + files: [ + { + name: 'AspectDefault.ttl', + response: {fixture: '/default-models/aspect-default.txt'}, + }, + ], + }, + movement: { + name: 'org.eclipse.examples.movement:1.0.0', + files: [ + { + name: 'Movement.ttl', + response: {fixture: '/default-models/movement.txt'}, + }, + ], + }, + }; + + setUpStaticModellingInterceptors(); + setUpDynamicModellingInterceptors(namespacesConfig); + + cy.visitDefault(); + cy.startModelling().then(() => { + cy.get(SELECTOR_tbSaveButton).click(); + cy.get(SELECTOR_tbSaveMenuExportNamespaceButton).click(); + cy.get(SELECTOR_enNamespaceList).should('have.length', 2); + cy.get(SELECTOR_enNamespaceList).contains(namespacesConfig.aspectDefault.name); + cy.get(SELECTOR_enNamespaceList).contains(namespacesConfig.movement.name); + }); + }); + + it('should have all namespaces ready for export after switching between models', () => { + const namespacesConfig = { + aspectDefault: { + name: 'org.eclipse.digitaltwin:1.0.0', + files: [ + { + name: 'AspectDefault.ttl', + response: {fixture: '/default-models/aspect-default.txt'}, + }, + ], + }, + movement: { + name: 'org.eclipse.examples.movement:1.0.0', + files: [ + { + name: 'Movement.ttl', + response: {fixture: '/default-models/movement.txt'}, + }, + ], + }, + }; + + setUpStaticModellingInterceptors(); + setUpDynamicModellingInterceptors(namespacesConfig); + + cy.visitDefault(); + cy.fixture(namespacesConfig.aspectDefault.files[0].response.fixture) + .then(rdfString => cyHelp.loadCustomModel(rdfString)) + .then(() => { + cy.get(SELECTOR_dialogStartButton).click(); + return awaitValidateModelRequest(`:AspectDefault`); + }) + .then(({body}) => { + namespacesConfig.aspectDefault.files[0].response = body; + setUpDynamicModellingInterceptors(namespacesConfig); + }) + .then(() => cy.fixture(namespacesConfig.movement.files[0].response.fixture)) + .then(rdfString => cyHelp.loadCustomModel(rdfString)) + .then(() => { + cy.get(SELECTOR_dialogStartButton).click(); + return awaitValidateModelRequest(`:Movement`); + }) + .then(({body}) => { + namespacesConfig.movement.files[0].response = body; + setUpDynamicModellingInterceptors(namespacesConfig); + }) + .then(() => cy.startModelling()) + .then(() => { + cy.get(SELECTOR_tbSaveButton).click(); + cy.get(SELECTOR_tbSaveMenuExportNamespaceButton).click(); + cy.get(SELECTOR_enNamespaceList).should('have.length', 2); + cy.get(SELECTOR_enNamespaceList).contains(namespacesConfig.aspectDefault.name); + cy.get(SELECTOR_enNamespaceList).contains(namespacesConfig.movement.name); + }); + }); +}); diff --git a/core/apps/ame-e2e/src/integration/settings/auto-save.spec.ts b/core/apps/ame-e2e/src/integration/settings/auto-save.spec.ts index 15aa9134..e4cd2ace 100644 --- a/core/apps/ame-e2e/src/integration/settings/auto-save.spec.ts +++ b/core/apps/ame-e2e/src/integration/settings/auto-save.spec.ts @@ -35,6 +35,6 @@ describe('Auto Save', () => { it('should stop timer for saving', () => { cy.get(SettingsDialogSelectors.autoSaveInput).clear({force: true}).type('2'); cy.get(SettingsDialogSelectors.autoSaveToggle).click({force: true}); - cy.wait(2000).then(() => cy.get(SNACK_BAR).should('not.exist')); + cy.get(SNACK_BAR, {timeout: 7000}).should('not.exist'); }); }); diff --git a/core/apps/ame-e2e/src/integration/settings/change-referenced-model-namespace.spec.ts b/core/apps/ame-e2e/src/integration/settings/change-referenced-model-namespace.spec.ts index 1290b385..692cc7f0 100644 --- a/core/apps/ame-e2e/src/integration/settings/change-referenced-model-namespace.spec.ts +++ b/core/apps/ame-e2e/src/integration/settings/change-referenced-model-namespace.spec.ts @@ -21,7 +21,8 @@ import { SELECTOR_tbDeleteButton, } from '../../support/constants'; import {cyHelp} from '../../support/helpers'; -import Chainable = Cypress.Chainable; +import {setUpDynamicModellingInterceptors, setUpStaticModellingInterceptors} from '../../support/api-mocks'; +import {awaitFormatModelRequest} from '../../support/api-mock-helpers'; /** * Take into consideration that these tests do not use real backend and verify @@ -60,8 +61,8 @@ describe.skip('Test modifying referenced model', () => { }, }; - setUpStaticInterceptors(); - setUpDynamicInterceptors(namespacesConfig); + setUpStaticModellingInterceptors(); + setUpDynamicModellingInterceptors(namespacesConfig); cy.visitDefault(); cy.fixture(namespacesConfig.shared.files[0].response.fixture) @@ -77,14 +78,14 @@ describe.skip('Test modifying referenced model', () => { .then(({body}) => { // Update interceptors to return the most recent value namespacesConfig.dependent.files[0].response = body; - setUpDynamicInterceptors(namespacesConfig); + setUpDynamicModellingInterceptors(namespacesConfig); }) .then(() => awaitFormatModelRequest(`@prefix : <${newUrn}#>`)) .then(({body}) => { // Update interceptors to return the most recent value namespacesConfig.shared.files[0].response = body; namespacesConfig.shared.name = newNamespace; - setUpDynamicInterceptors(namespacesConfig); + setUpDynamicModellingInterceptors(namespacesConfig); }) .then(() => { // Trigger namespaces update in order to get the latest stubbed values from interceptors @@ -132,8 +133,8 @@ describe.skip('Test modifying referenced model', () => { }, }; - setUpStaticInterceptors(); - setUpDynamicInterceptors(namespacesConfig); + setUpStaticModellingInterceptors(); + setUpDynamicModellingInterceptors(namespacesConfig); cy.visitDefault(); cy.fixture(namespacesConfig.same.files[0].response.fixture) @@ -149,7 +150,7 @@ describe.skip('Test modifying referenced model', () => { .then(({body}) => { // Update interceptors to return the most recent value namespacesConfig.same.files[1].response = body; - setUpDynamicInterceptors(namespacesConfig); + setUpDynamicModellingInterceptors(namespacesConfig); }) .then(() => awaitFormatModelRequest(`@prefix : <${newUrn}#>`)) .then(({body}) => { @@ -164,7 +165,7 @@ describe.skip('Test modifying referenced model', () => { ], }; namespacesConfig.same.files = [namespacesConfig.same.files[1]]; - setUpDynamicInterceptors(namespacesConfig); + setUpDynamicModellingInterceptors(namespacesConfig); }) .then(() => { // Trigger namespaces update in order to get the latest stubbed values from interceptors @@ -202,15 +203,15 @@ describe.skip('Test modifying referenced model', () => { }, }; - setUpStaticInterceptors(); - setUpDynamicInterceptors(namespacesConfig); + setUpStaticModellingInterceptors(); + setUpDynamicModellingInterceptors(namespacesConfig); cy.visitDefault(); cy.startModelling() .then(() => cy.getAspect()) .then(({body}) => { namespacesConfig.main.files[0].response = body; - setUpDynamicInterceptors(namespacesConfig); + setUpDynamicModellingInterceptors(namespacesConfig); }) .then(() => { cyHelp.saveCurrentModelToWorkspace(); @@ -220,7 +221,7 @@ describe.skip('Test modifying referenced model', () => { .then(({body}) => { // Update interceptors to return the most recent value namespacesConfig.main.files[0].response = body; - setUpDynamicInterceptors(namespacesConfig); + setUpDynamicModellingInterceptors(namespacesConfig); }) .then(() => cy.dbClickShape('AspectDefault')) .then(() => cy.get(SELECTOR_tbDeleteButton).click()) @@ -232,7 +233,7 @@ describe.skip('Test modifying referenced model', () => { // Update interceptors to return the most recent value namespacesConfig.main.files[0].name = sharedModelFileName; namespacesConfig.main.files[0].response = body; - setUpDynamicInterceptors(namespacesConfig); + setUpDynamicModellingInterceptors(namespacesConfig); }) .then(() => { // Trigger namespaces update in order to get the latest stubbed values from interceptors @@ -245,48 +246,3 @@ describe.skip('Test modifying referenced model', () => { }); }); }); - -function setUpStaticInterceptors(): void { - cy.intercept('POST', 'http://localhost:9091/ame/api/models/validate', {fixture: 'model-validation-response.json'}); - cy.intercept('POST', 'http://localhost:9091/ame/api/models/format', {}).as('formatModel'); - cy.intercept('POST', 'http://localhost:9091/ame/api/models', {}); - cy.intercept('DELETE', 'http://localhost:9091/ame/api/models', {}); -} - -function setUpDynamicInterceptors(namespacesConfig: any): void { - const values: any[] = Object.values(namespacesConfig); - - // Set up namespaces structure to return - cy.intercept( - 'GET', - 'http://localhost:9091/ame/api/models/namespaces?shouldRefresh=true', - values.reduce( - (acc, value) => ({ - ...acc, - [value.name]: value.files.map(f => f.name), - }), - {} - ) - ); - - // Set up files content to return - values.forEach(value => { - value.files.forEach(file => { - cy.intercept( - { - method: 'GET', - url: 'http://localhost:9091/ame/api/models', - headers: {namespace: value.name, 'file-name': file.name}, - }, - file.response - ); - }); - }); -} - -function awaitFormatModelRequest(toInclude: string): Chainable { - return cy.wait('@formatModel').then(({request}) => { - cy.wrap(request.body).should('include', toInclude); - return cy.wrap(request); - }); -} diff --git a/core/apps/ame-e2e/src/support/api-mock-helpers.ts b/core/apps/ame-e2e/src/support/api-mock-helpers.ts new file mode 100644 index 00000000..db3e634e --- /dev/null +++ b/core/apps/ame-e2e/src/support/api-mock-helpers.ts @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2023 Robert Bosch Manufacturing Solutions GmbH + * + * See the AUTHORS file(s) distributed with this work for + * additional information regarding authorship. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + */ + +import Chainable = Cypress.Chainable; + +export function awaitValidateModelRequest(toInclude: string): Chainable { + return cy.wait('@validateModel', {timeout: 10000}).then(({request}) => { + cy.wrap(request.body).should('include', toInclude); + return cy.wrap(request); + }); +} + +export function awaitFormatModelRequest(toInclude: string): Chainable { + return cy.wait('@formatModel').then(({request}) => { + cy.wrap(request.body).should('include', toInclude); + return cy.wrap(request); + }); +} diff --git a/core/apps/ame-e2e/src/support/api-mocks.ts b/core/apps/ame-e2e/src/support/api-mocks.ts new file mode 100644 index 00000000..d2880832 --- /dev/null +++ b/core/apps/ame-e2e/src/support/api-mocks.ts @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2023 Robert Bosch Manufacturing Solutions GmbH + * + * See the AUTHORS file(s) distributed with this work for + * additional information regarding authorship. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + */ + +export interface InterceptorConfigNamespaces { + [key: string]: InterceptorConfigNamespace; +} + +interface InterceptorConfigNamespace { + name: string; + files: InterceptorConfigNamespaceFile[]; +} + +interface InterceptorConfigNamespaceFile { + name: string; + response: { + fixture?: string; + }; +} + +export function setUpStaticModellingInterceptors(): void { + cy.intercept('POST', 'http://localhost:9091/ame/api/models/validate', {fixture: 'model-validation-response.json'}).as('validateModel'); + cy.intercept('POST', 'http://localhost:9091/ame/api/models/format', {}).as('formatModel'); + cy.intercept('POST', 'http://localhost:9091/ame/api/models', {}); + cy.intercept('DELETE', 'http://localhost:9091/ame/api/models', {}); +} + +export function setUpDynamicModellingInterceptors(namespacesConfig: InterceptorConfigNamespaces): void { + const values: any[] = Object.values(namespacesConfig); + + // Set up namespaces structure to return + cy.intercept( + 'GET', + 'http://localhost:9091/ame/api/models/namespaces?shouldRefresh=true', + values.reduce( + (acc, value) => ({ + ...acc, + [value.name]: value.files.map(f => f.name), + }), + {} + ) + ); + + // Set up files content to return + values.forEach(value => { + value.files.forEach(file => { + console.warn('file', file); + cy.intercept( + { + method: 'GET', + url: 'http://localhost:9091/ame/api/models', + headers: {namespace: value.name, 'file-name': file.name}, + }, + file.response + ); + }); + }); +} diff --git a/core/apps/ame-e2e/src/support/constants.ts b/core/apps/ame-e2e/src/support/constants.ts index 460e94f1..0be555dd 100644 --- a/core/apps/ame-e2e/src/support/constants.ts +++ b/core/apps/ame-e2e/src/support/constants.ts @@ -62,6 +62,9 @@ export const SELECTOR_settingsButton = '[data-cy="settings-button"]'; export const SELECTOR_notificationsButton = '[data-cy="notifications-button"]'; export const SELECTOR_helpButton = '[data-cy="help-button"]'; +// Export namespace +export const SELECTOR_enNamespaceList = '[data-cy="enNamespaceList"]'; + // Notifications export const SELECTOR_notificationsDialogCloseButton = '[data-cy="close-notifications"]'; export const SELECTOR_notificationsClearButton = '[data-cy="clear-notifications"]'; @@ -116,6 +119,18 @@ export const FIELD_deconstructionRuleInput = '[data-cy="deconstruction-rule-inpu export const FIELD_deconstructionRuleSelect = '[data-cy="deconstruction-rule-select"]'; export const FIELD_elementsModalButton = '[data-cy="elements-modal-button"]'; export const SELECTOR_removeEntityValue = '[data-cy="remove-entity-value"]'; +export const PROP_configuration = '.properties-button > p > span'; +export const SELECTOR_configureProp = '[data-cy="properties-modal-button"]'; +export const SELECTOR_outgoingEdges = '.mat-expansion-panel-header-title > h3'; +export const FIELD_error = '.mat-mdc-form-field-error-wrapper'; +export const SELECTOR_resizeWindow = '.as-split-gutter-icon'; +export const SELECTOR_saveProperties = '[data-cy="propertiesSaveButton"]'; +export const SELECTOR_locateElement = '[data-cy="locateElement"]'; +export const SELECTOR_configuredProperty = ':nth-child(2) > .cdk-column-name > span'; +export const SELECTOR_configuredPropertyCheckBox = '#mat-mdc-checkbox-1-input'; +export const SELECTOR_configuredPropertyPayload = '#mat-input-42'; +export const SELECTOR_exampleProperty = + 'ame-example-value-input-field > .mat-mdc-form-field > .mat-mdc-text-field-wrapper > .mat-mdc-form-field-flex > .mat-mdc-form-field-infix'; // Search model export const SELECTOR_searchInputField = '[data-cy="searchInputField"]'; @@ -146,6 +161,7 @@ export const META_MODEL_minValue = 'minValue'; export const META_MODEL_maxValue = 'maxValue'; export const META_MODEL_localeCode = 'localeCode'; export const META_MODEL_languageCode = 'languageCode'; +export const META_MODEL_exampleValue = 'exampleValue'; // Settings Dialog export enum SettingsDialogSelectors { diff --git a/core/apps/ame-e2e/src/support/helpers.ts b/core/apps/ame-e2e/src/support/helpers.ts index 322cabec..87f4faf0 100644 --- a/core/apps/ame-e2e/src/support/helpers.ts +++ b/core/apps/ame-e2e/src/support/helpers.ts @@ -51,6 +51,23 @@ export class cyHelp { }); } + public static forceChangeDetection() { + let angular; + let $document; + return cy + .window() + .then(win => (angular = win['ng'])) + .then(() => cy.document().then(d => ($document = d))) + .then(() => { + const app = angular.getComponent($document.querySelector('ame-root')); + angular.applyChanges(app); + }); + } + + public static clickSaveButton() { + return this.forceChangeDetection().then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})); + } + // TODO: after we replace the add buttons with those from label, change this public static findShapeByName(name: string, win: Window): mxgraph.mxCell { const mxGraphAttributeService: MxGraphAttributeService = win['angular.mxGraphAttributeService']; @@ -228,7 +245,7 @@ export class cyHelp { .then(() => cy.dbClickShape(oldName)) .then(() => cy.get('#graph').click()) .then(() => cy.get(FIELD_name).clear({force: true}).type(newName, {force: true})) - .then(() => cy.get(SELECTOR_editorSaveButton).focus().click({force: true})); + .then(() => this.clickSaveButton()); } static assertNullMultiLanguageValues(modelElement: BaseMetaModelElement, langTag: string) { diff --git a/core/apps/ame-e2e/src/support/index.ts b/core/apps/ame-e2e/src/support/index.ts index 883e746c..61613986 100644 --- a/core/apps/ame-e2e/src/support/index.ts +++ b/core/apps/ame-e2e/src/support/index.ts @@ -31,8 +31,9 @@ import './constants'; // When a command from ./commands is ready to use, import with `import * as commands from './commands'` syntax // import * as commands from './commands'; import './commands'; - import './helpers'; +import './api-mocks'; +import './api-mock-helpers'; before(function before() { // Do not truncate assertion outputs of arrays and objects diff --git a/core/apps/ame/src/app/components/editor-canvas/editor-canvas-menu.component.ts b/core/apps/ame/src/app/components/editor-canvas/editor-canvas-menu.component.ts index 177dcc23..2aa8ed81 100644 --- a/core/apps/ame/src/app/components/editor-canvas/editor-canvas-menu.component.ts +++ b/core/apps/ame/src/app/components/editor-canvas/editor-canvas-menu.component.ts @@ -14,6 +14,7 @@ import {Component} from '@angular/core'; import {EditorService} from '@ame/editor'; import {ConfigurationService, Settings} from '@ame/settings-dialog'; +import {LoadingScreenService} from '@ame/shared'; @Component({ selector: 'ame-editor-canvas-menu', @@ -23,23 +24,63 @@ import {ConfigurationService, Settings} from '@ame/settings-dialog'; export class EditorCanvasMenuComponent { settings: Settings; - constructor(private editorService: EditorService, public configurationService: ConfigurationService) { + constructor( + private editorService: EditorService, + public configurationService: ConfigurationService, + private loadingScreenService: LoadingScreenService + ) { this.settings = configurationService.getSettings(); } zoomIn() { - this.editorService.zoomIn(); + this.loadingScreenService + .open({ + title: 'Zooming in...', + content: 'Please wait until zoom finishes', + }) + .afterOpened() + .subscribe(() => { + this.editorService.zoomIn(); + this.loadingScreenService.close(); + }); } zoomOut() { - this.editorService.zoomOut(); + this.loadingScreenService + .open({ + title: 'Zooming out...', + content: 'Please wait until zoom finishes', + }) + .afterOpened() + .subscribe(() => { + this.editorService.zoomOut(); + this.loadingScreenService.close(); + }); } fit() { - this.editorService.fit(); + this.loadingScreenService + .open({ + title: 'Fitting...', + content: 'Please wait until fitting finishes', + }) + .afterOpened() + .subscribe(() => { + this.editorService.fit(); + this.loadingScreenService.close(); + }); } actualSize() { - this.editorService.actualSize(); + this.loadingScreenService + .open({ + title: 'Fit to view...', + content: 'Please wait until fitting finishes', + }) + .afterOpened() + .subscribe(() => { + this.editorService.actualSize(); + this.loadingScreenService.close(); + }); } } diff --git a/core/apps/ame/src/app/components/editor-canvas/editor-canvas.component.ts b/core/apps/ame/src/app/components/editor-canvas/editor-canvas.component.ts index 9d313d63..8aa6c50b 100644 --- a/core/apps/ame/src/app/components/editor-canvas/editor-canvas.component.ts +++ b/core/apps/ame/src/app/components/editor-canvas/editor-canvas.component.ts @@ -19,7 +19,7 @@ import {mxgraph} from 'mxgraph-factory'; import {BaseMetaModelElement, ElementModelService} from '@ame/meta-model'; import {MxGraphService} from '@ame/mx-graph'; import {LogService} from '@ame/shared'; -import {ShapeSettingsService} from '@ame/editor'; +import {ShapeSettingsService, ShapeSettingsStateService} from '@ame/editor'; import {ModelService} from '@ame/rdf/services'; import {FormGroup} from '@angular/forms'; @@ -32,11 +32,11 @@ export class EditorCanvasComponent implements AfterViewInit, OnInit, OnDestroy { private unsubscribe: Subject = new Subject(); private get selectedShapeForUpdate(): mxgraph.mxCell | null { - return this.shapeSettingsService.selectedShapeForUpdate; + return this.shapeSettingsStateService.selectedShapeForUpdate; } public get isShapeSettingOpened() { - return this.shapeSettingsService.isShapeSettingOpened; + return this.shapeSettingsStateService.isShapeSettingOpened; } public get modelElement(): BaseMetaModelElement { @@ -45,6 +45,7 @@ export class EditorCanvasComponent implements AfterViewInit, OnInit, OnDestroy { constructor( private shapeSettingsService: ShapeSettingsService, + private shapeSettingsStateService: ShapeSettingsStateService, private mxGraphService: MxGraphService, private router: Router, private activatedRoute: ActivatedRoute, @@ -53,7 +54,7 @@ export class EditorCanvasComponent implements AfterViewInit, OnInit, OnDestroy { private elementModelService: ElementModelService, private changeDetector: ChangeDetectorRef ) { - this.shapeSettingsService.onSettingsOpened$.subscribe(() => + this.shapeSettingsStateService.onSettingsOpened$.subscribe(() => requestAnimationFrame(() => { this.changeDetector.detectChanges(); }) @@ -88,7 +89,7 @@ export class EditorCanvasComponent implements AfterViewInit, OnInit, OnDestroy { closeShapeSettings() { if (this.modelService.getLoadedAspectModel().rdfModel) { - this.shapeSettingsService.closeShapeSettings(); + this.shapeSettingsStateService.closeShapeSettings(); this.changeDetector.detectChanges(); } } @@ -104,7 +105,7 @@ export class EditorCanvasComponent implements AfterViewInit, OnInit, OnDestroy { } resetSelectedShapeForUpdate() { - this.shapeSettingsService.closeShapeSettings(); + this.shapeSettingsStateService.closeShapeSettings(); this.shapeSettingsService.unselectShapeForUpdate(); } diff --git a/core/apps/ame/src/app/components/editor-canvas/editor-canvas.module.ts b/core/apps/ame/src/app/components/editor-canvas/editor-canvas.module.ts index 9674bf98..5012d992 100644 --- a/core/apps/ame/src/app/components/editor-canvas/editor-canvas.module.ts +++ b/core/apps/ame/src/app/components/editor-canvas/editor-canvas.module.ts @@ -36,6 +36,7 @@ import {MatDialogModule} from '@angular/material/dialog'; import {MatProgressSpinnerModule} from '@angular/material/progress-spinner'; import {MxEditorComponent} from './mx-editor/mx-editor.component'; import {SidebarElementFilter} from './sidebar/sidebar-new-element/elements-filter.pipe'; +import {CounterPipe} from '@ame/shared'; @NgModule({ imports: [ @@ -53,6 +54,7 @@ import {SidebarElementFilter} from './sidebar/sidebar-new-element/elements-filte FormsModule, MatDialogModule, MatProgressSpinnerModule, + CounterPipe, ], declarations: [ EditorCanvasComponent, diff --git a/core/apps/ame/src/app/components/editor-canvas/sidebar/sidebar-namespace-elements/namespace-element-list/namespace-element-list.component.html b/core/apps/ame/src/app/components/editor-canvas/sidebar/sidebar-namespace-elements/namespace-element-list/namespace-element-list.component.html index e5df476d..736a3f51 100644 --- a/core/apps/ame/src/app/components/editor-canvas/sidebar/sidebar-namespace-elements/namespace-element-list/namespace-element-list.component.html +++ b/core/apps/ame/src/app/components/editor-canvas/sidebar/sidebar-namespace-elements/namespace-element-list/namespace-element-list.component.html @@ -12,7 +12,7 @@ --> -
{{ title }}
+
{{ title | counter: elements.length }}
See all elements
diff --git a/core/apps/ame/src/app/components/editor-canvas/sidebar/sidebar.component.ts b/core/apps/ame/src/app/components/editor-canvas/sidebar/sidebar.component.ts index 879500ea..c3e342e3 100644 --- a/core/apps/ame/src/app/components/editor-canvas/sidebar/sidebar.component.ts +++ b/core/apps/ame/src/app/components/editor-canvas/sidebar/sidebar.component.ts @@ -14,7 +14,7 @@ import {AfterViewInit, Component, ElementRef, EventEmitter, OnDestroy, OnInit, Output, ViewChild} from '@angular/core'; import {ModelApiService} from '@ame/api'; import {NamespacesCacheService} from '@ame/cache'; -import {ConfirmDialogService, EditorService} from '@ame/editor'; +import {ConfirmDialogService, EditorService, ShapeSettingsStateService} from '@ame/editor'; import { BaseMetaModelElement, DefaultAbstractEntity, @@ -63,6 +63,7 @@ export class EditorCanvasSidebarComponent implements AfterViewInit, OnInit, OnDe private notificationsService: NotificationsService, private elementRef: ElementRef, private rdfService: RdfService, + private shapeSettingsStateService: ShapeSettingsStateService, public sidebarService: SidebarService ) {} @@ -191,7 +192,12 @@ export class EditorCanvasSidebarComponent implements AfterViewInit, OnInit, OnDe }); return throwError(() => error); }), - finalize(() => this.loadingScreenService.close()) + finalize(() => { + this.loadingScreenService.close(); + if (this.shapeSettingsStateService.isShapeSettingOpened) { + this.shapeSettingsStateService.closeShapeSettings(); + } + }) ) ) ) diff --git a/core/libs/api/src/lib/model-api.service.ts b/core/libs/api/src/lib/model-api.service.ts index 4299bbf8..11e43cb4 100644 --- a/core/libs/api/src/lib/model-api.service.ts +++ b/core/libs/api/src/lib/model-api.service.ts @@ -17,7 +17,6 @@ import {catchError, map, mergeMap, tap, timeout} from 'rxjs/operators'; import {forkJoin, Observable, of, throwError} from 'rxjs'; import {APP_CONFIG, AppConfig, BrowserService, FileContentModel, HttpHeaderBuilder, LogService} from '@ame/shared'; import {ModelValidatorService} from './model-validator.service'; -import {RdfModel} from '@ame/rdf/utils'; import {OpenApi, ViolationError} from '@ame/editor'; @Injectable({ @@ -142,12 +141,12 @@ export class ModelApiService { ); } - getAllNamespacesFilesContent(rdfModel?: RdfModel): Observable { + getAllNamespacesFilesContent(exceptionFileName?: string | undefined): Observable { return this.getNamespacesAppendWithFiles().pipe( map(aspectModelFileNames => aspectModelFileNames.reduce( (files, absoluteFileName) => - absoluteFileName !== rdfModel?.absoluteAspectModelFileName + absoluteFileName !== exceptionFileName ? [ ...files, this.getAspectMetaModel(absoluteFileName).pipe( diff --git a/core/libs/editor/src/lib/editor-dialog/components/abstract-entities/abstract-entity.component.html b/core/libs/editor/src/lib/editor-dialog/components/abstract-entities/abstract-entity.component.html index 425516f0..c69c120e 100644 --- a/core/libs/editor/src/lib/editor-dialog/components/abstract-entities/abstract-entity.component.html +++ b/core/libs/editor/src/lib/editor-dialog/components/abstract-entities/abstract-entity.component.html @@ -13,5 +13,5 @@ - - + + diff --git a/core/libs/editor/src/lib/editor-dialog/components/abstract-property/abstract-property.component.html b/core/libs/editor/src/lib/editor-dialog/components/abstract-property/abstract-property.component.html index 58d260e2..8490f140 100644 --- a/core/libs/editor/src/lib/editor-dialog/components/abstract-property/abstract-property.component.html +++ b/core/libs/editor/src/lib/editor-dialog/components/abstract-property/abstract-property.component.html @@ -12,5 +12,5 @@ --> - - + + diff --git a/core/libs/editor/src/lib/editor-dialog/components/aspect/aspect.component.html b/core/libs/editor/src/lib/editor-dialog/components/aspect/aspect.component.html index bcb142a3..ef92402a 100644 --- a/core/libs/editor/src/lib/editor-dialog/components/aspect/aspect.component.html +++ b/core/libs/editor/src/lib/editor-dialog/components/aspect/aspect.component.html @@ -12,4 +12,4 @@ --> - + diff --git a/core/libs/editor/src/lib/editor-dialog/components/characteristics/characteristic.component.html b/core/libs/editor/src/lib/editor-dialog/components/characteristics/characteristic.component.html index 372b5499..44ba3c20 100644 --- a/core/libs/editor/src/lib/editor-dialog/components/characteristics/characteristic.component.html +++ b/core/libs/editor/src/lib/editor-dialog/components/characteristics/characteristic.component.html @@ -53,6 +53,6 @@ - - + + diff --git a/core/libs/editor/src/lib/editor-dialog/components/characteristics/trait-characteristic/trait-characteristic.component.html b/core/libs/editor/src/lib/editor-dialog/components/characteristics/trait-characteristic/trait-characteristic.component.html index 58d260e2..8490f140 100644 --- a/core/libs/editor/src/lib/editor-dialog/components/characteristics/trait-characteristic/trait-characteristic.component.html +++ b/core/libs/editor/src/lib/editor-dialog/components/characteristics/trait-characteristic/trait-characteristic.component.html @@ -12,5 +12,5 @@ --> - - + + diff --git a/core/libs/editor/src/lib/editor-dialog/components/constraints/constraint.component.html b/core/libs/editor/src/lib/editor-dialog/components/constraints/constraint.component.html index 291a1573..e132661f 100644 --- a/core/libs/editor/src/lib/editor-dialog/components/constraints/constraint.component.html +++ b/core/libs/editor/src/lib/editor-dialog/components/constraints/constraint.component.html @@ -57,5 +57,5 @@ > - - + + diff --git a/core/libs/editor/src/lib/editor-dialog/components/element-list/element-list.component.html b/core/libs/editor/src/lib/editor-dialog/components/element-list/element-list.component.html index 54d22911..92c5645f 100644 --- a/core/libs/editor/src/lib/editor-dialog/components/element-list/element-list.component.html +++ b/core/libs/editor/src/lib/editor-dialog/components/element-list/element-list.component.html @@ -15,7 +15,7 @@ account_tree -

{{ label }}

+

{{ label | counter: elements.length }}

diff --git a/core/libs/editor/src/lib/editor-dialog/components/element-list/element-list.component.ts b/core/libs/editor/src/lib/editor-dialog/components/element-list/element-list.component.ts index f50da0b7..3693de40 100644 --- a/core/libs/editor/src/lib/editor-dialog/components/element-list/element-list.component.ts +++ b/core/libs/editor/src/lib/editor-dialog/components/element-list/element-list.component.ts @@ -13,7 +13,7 @@ import {Component, Input} from '@angular/core'; import {BaseMetaModelElement} from '@ame/meta-model'; import {MxGraphService} from '@ame/mx-graph'; -import {ShapeSettingsService} from '../../services'; +import {ShapeSettingsService, ShapeSettingsStateService} from '../../services'; @Component({ selector: 'ame-element-list', @@ -25,14 +25,18 @@ export class ElementListComponent { @Input() public iconRotation: 'rotate0' | 'rotate90' | 'rotate270' = 'rotate90'; @Input() public elements: BaseMetaModelElement[] = []; - constructor(private mxGraphService: MxGraphService, private shapeSettingsService: ShapeSettingsService) {} + constructor( + private mxGraphService: MxGraphService, + private shapeSettingsService: ShapeSettingsService, + private shapeSettingsStateService: ShapeSettingsStateService + ) {} editElementModel(elementModel: BaseMetaModelElement) { const cell = this.mxGraphService.resolveCellByModelElement(elementModel); this.shapeSettingsService.editModel(elementModel); if (cell) { this.mxGraphService.navigateToCell(cell, true); - this.shapeSettingsService.selectedShapeForUpdate = cell; + this.shapeSettingsStateService.selectedShapeForUpdate = cell; } } diff --git a/core/libs/editor/src/lib/editor-dialog/components/entities/entity.component.html b/core/libs/editor/src/lib/editor-dialog/components/entities/entity.component.html index 425516f0..c69c120e 100644 --- a/core/libs/editor/src/lib/editor-dialog/components/entities/entity.component.html +++ b/core/libs/editor/src/lib/editor-dialog/components/entities/entity.component.html @@ -13,5 +13,5 @@ - - + + diff --git a/core/libs/editor/src/lib/editor-dialog/components/entity-value/entity-value.component.html b/core/libs/editor/src/lib/editor-dialog/components/entity-value/entity-value.component.html index 469e71a2..14979a92 100644 --- a/core/libs/editor/src/lib/editor-dialog/components/entity-value/entity-value.component.html +++ b/core/libs/editor/src/lib/editor-dialog/components/entity-value/entity-value.component.html @@ -13,5 +13,5 @@ - - + + diff --git a/core/libs/editor/src/lib/editor-dialog/components/events/event.component.html b/core/libs/editor/src/lib/editor-dialog/components/events/event.component.html index 0322fb3a..0e6d0a0d 100644 --- a/core/libs/editor/src/lib/editor-dialog/components/events/event.component.html +++ b/core/libs/editor/src/lib/editor-dialog/components/events/event.component.html @@ -11,5 +11,5 @@ ~ SPDX-License-Identifier: MPL-2.0 --> - - + + diff --git a/core/libs/editor/src/lib/editor-dialog/components/fields/base/name-input-field/name-input-field.component.ts b/core/libs/editor/src/lib/editor-dialog/components/fields/base/name-input-field/name-input-field.component.ts index 5b259e5d..2f92887a 100644 --- a/core/libs/editor/src/lib/editor-dialog/components/fields/base/name-input-field/name-input-field.component.ts +++ b/core/libs/editor/src/lib/editor-dialog/components/fields/base/name-input-field/name-input-field.component.ts @@ -11,7 +11,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -import {Component, OnInit, inject} from '@angular/core'; +import {Component, OnDestroy, OnInit, inject} from '@angular/core'; import {FormControl, Validators} from '@angular/forms'; import { BaseMetaModelElement, @@ -27,25 +27,32 @@ import { import {EditorDialogValidators} from '../../../../validators'; import {InputFieldComponent} from '../../input-field.component'; import {RdfService} from '@ame/rdf/services'; +import {Subscription} from 'rxjs'; @Component({ selector: 'ame-name-input-field', templateUrl: './name-input-field.component.html', }) -export class NameInputFieldComponent extends InputFieldComponent implements OnInit { +export class NameInputFieldComponent extends InputFieldComponent implements OnInit, OnDestroy { public fieldName = 'name'; private rdfService = inject(RdfService); + private nameSubscription = new Subscription(); ngOnInit(): void { this.subscription = this.getMetaModelData().subscribe(() => this.setNameControl()); } + ngOnDestroy() { + super.ngOnDestroy(); + this.nameSubscription.unsubscribe(); + } + private isDisabled() { return this.metaModelElement instanceof DefaultProperty && !!this.metaModelElement?.extendedElement; } private setNameControl() { - const nameControl = this.parentForm.get('name'); + let nameControl = this.parentForm.get('name'); if (nameControl?.value) { nameControl.updateValueAndValidity(); } @@ -62,7 +69,24 @@ export class NameInputFieldComponent extends InputFieldComponent { + const validation = EditorDialogValidators.duplicateName( + this.namespacesCacheService, + this.metaModelElement, + this.rdfService + )(nameControl); + if (validation) { + nameControl.setErrors({ + ...(nameControl.errors || {}), + ...(validation || {}), + }); + } + }) + ); + nameControl.markAsTouched(); } private getNameValidators(): any[] { @@ -70,10 +94,7 @@ export class NameInputFieldComponent extends InputFieldComponent(); constructor( - public metaModelDialogService: EditorModelService, + public editorModelService: EditorModelService, public modelService: ModelService, public languageSettings: LanguageSettingsService, private namespacesCacheService: NamespacesCacheService, private modelElementNamingService: ModelElementNamingService ) { - super(metaModelDialogService, modelService, languageSettings); + super(editorModelService, modelService, languageSettings); } ngOnInit(): void { @@ -99,6 +99,10 @@ export class CharacteristicNameDropdownFieldComponent extends DropdownFieldCompo this.metaModelElement.name = this.selectedMetaModelElement.name; } else if (oldCharacteristic.isPredefined() && selectedCharacteristic.isPredefined()) { this.metaModelElement = this.modelElementNamingService.resolveElementNaming(newCharacteristicType) as DefaultCharacteristic; + if (this.originalCharacteristic && !this.originalCharacteristic.isPredefined()) { + this.metaModelElement.name = this.originalCharacteristic.name; + this.metaModelElement.aspectModelUrn = this.originalCharacteristic.aspectModelUrn; + } } else { this.metaModelElement.name = oldMetaModelElement.name; this.migrateCommonAttributes(oldMetaModelElement); diff --git a/core/libs/editor/src/lib/editor-dialog/components/fields/characteristic/data-type-input-field/data-type-input-field.component.scss b/core/libs/editor/src/lib/editor-dialog/components/fields/characteristic/data-type-input-field/data-type-input-field.component.scss index 2aaed3ed..21f17751 100644 --- a/core/libs/editor/src/lib/editor-dialog/components/fields/characteristic/data-type-input-field/data-type-input-field.component.scss +++ b/core/libs/editor/src/lib/editor-dialog/components/fields/characteristic/data-type-input-field/data-type-input-field.component.scss @@ -29,3 +29,7 @@ } } } + +mat-option span:nth-child(2) { + padding-left: 5px; +} diff --git a/core/libs/editor/src/lib/editor-dialog/components/fields/characteristic/data-type-input-field/data-type-input-field.component.ts b/core/libs/editor/src/lib/editor-dialog/components/fields/characteristic/data-type-input-field/data-type-input-field.component.ts index b35baab2..ff457b3b 100644 --- a/core/libs/editor/src/lib/editor-dialog/components/fields/characteristic/data-type-input-field/data-type-input-field.component.ts +++ b/core/libs/editor/src/lib/editor-dialog/components/fields/characteristic/data-type-input-field/data-type-input-field.component.ts @@ -56,12 +56,12 @@ export class DataTypeInputFieldComponent extends InputFieldComponent(); constructor( - public metaModelDialogService: EditorModelService, + public editorModelService: EditorModelService, public modelService: ModelService, public namespacesCacheService: NamespacesCacheService, public languageSettings: LanguageSettingsService ) { - super(metaModelDialogService, modelService, languageSettings); + super(editorModelService, modelService, languageSettings); } ngOnInit(): void { diff --git a/core/libs/editor/src/lib/editor-dialog/components/fields/dropdown-field.component.ts b/core/libs/editor/src/lib/editor-dialog/components/fields/dropdown-field.component.ts index a1919a52..3eafe858 100644 --- a/core/libs/editor/src/lib/editor-dialog/components/fields/dropdown-field.component.ts +++ b/core/libs/editor/src/lib/editor-dialog/components/fields/dropdown-field.component.ts @@ -16,7 +16,7 @@ import {FormControl, FormGroup} from '@angular/forms'; import {EditorModelService} from '../../editor-model.service'; import {tap} from 'rxjs/operators'; import {Subscription} from 'rxjs'; -import {DefaultCharacteristic, DefaultConstraint} from '@ame/meta-model'; +import {BaseMetaModelElement, DefaultCharacteristic, DefaultConstraint} from '@ame/meta-model'; import {LanguageSettingsService} from '@ame/settings-dialog'; import {RdfModelUtil} from '@ame/rdf/utils'; import {ModelService} from '@ame/rdf/services'; @@ -31,13 +31,16 @@ export abstract class DropdownFieldComponent(); protected constructor( - public metaModelDialogService: EditorModelService, + public editorModelService: EditorModelService, public modelService: ModelService, public languageSettings: LanguageSettingsService ) {} @@ -72,7 +75,7 @@ export abstract class DropdownFieldComponent { this.metaModelElement = metaModelElement; }) @@ -105,7 +108,7 @@ export abstract class DropdownFieldComponent - - - + Create new Abstract Entity: {{ extends.value }} - - Abstract Entity should be upper case - - - - + Create new Entity: {{ extends.value }} - - Entity should be upper case - - - - - + Create new Entity: {{ extends.value }} - - Entity should be upper case - + + + + + Create new Abstract Entity: {{ extends.value }} + + + Abstract Entity should be upper case + + + + + + Create new Entity: {{ extends.value }} + + + Entity should be upper case + + + - - + + diff --git a/core/libs/editor/src/lib/editor-dialog/components/properties/property.component.html b/core/libs/editor/src/lib/editor-dialog/components/properties/property.component.html index 52052297..3cb9a6df 100644 --- a/core/libs/editor/src/lib/editor-dialog/components/properties/property.component.html +++ b/core/libs/editor/src/lib/editor-dialog/components/properties/property.component.html @@ -13,5 +13,5 @@ - - + + diff --git a/core/libs/editor/src/lib/editor-dialog/components/units/unit.component.html b/core/libs/editor/src/lib/editor-dialog/components/units/unit.component.html index a95d13f0..81d7c27d 100644 --- a/core/libs/editor/src/lib/editor-dialog/components/units/unit.component.html +++ b/core/libs/editor/src/lib/editor-dialog/components/units/unit.component.html @@ -18,5 +18,5 @@ - - + + diff --git a/core/libs/editor/src/lib/editor-dialog/editor-dialog.module.ts b/core/libs/editor/src/lib/editor-dialog/editor-dialog.module.ts index ec921bcb..bfcfbae5 100644 --- a/core/libs/editor/src/lib/editor-dialog/editor-dialog.module.ts +++ b/core/libs/editor/src/lib/editor-dialog/editor-dialog.module.ts @@ -97,6 +97,7 @@ import {MatAutocompleteModule} from '@angular/material/autocomplete'; import {CommonModule} from '@angular/common'; import {MatButtonModule} from '@angular/material/button'; import {MatDialogModule} from '@angular/material/dialog'; +import {CounterPipe} from '../../../../shared/src/lib/pipes/counter.pipe'; @NgModule({ providers: [EditorModelService], @@ -117,6 +118,7 @@ import {MatDialogModule} from '@angular/material/dialog'; MatExpansionModule, MatButtonModule, MatDialogModule, + CounterPipe, ], declarations: [ AspectComponent, diff --git a/core/libs/editor/src/lib/editor-dialog/editor-model.service.ts b/core/libs/editor/src/lib/editor-dialog/editor-model.service.ts index 4eeaf020..b31c0dc6 100644 --- a/core/libs/editor/src/lib/editor-dialog/editor-model.service.ts +++ b/core/libs/editor/src/lib/editor-dialog/editor-model.service.ts @@ -26,9 +26,17 @@ export class EditorModelService { private readOnly = false; private saveButtonEnabled = true; private characteristicInstantiator: CharacteristicInstantiator; + public originalMetaModel: BaseMetaModelElement; constructor(private modelService: ModelService) { this.metaModelElementSubject.asObservable().subscribe(newMetaModelElement => { + if (this.originalMetaModel && !newMetaModelElement) { + this.originalMetaModel = null; + } + + if (!this.originalMetaModel && newMetaModelElement) { + this.originalMetaModel = newMetaModelElement; + } this.metaModelElement = newMetaModelElement; }); } @@ -54,6 +62,11 @@ export class EditorModelService { } _updateMetaModelElement(metaModelElement: BaseMetaModelElement): void { + if (metaModelElement === null) { + this.metaModelElementSubject.next(metaModelElement); + return; + } + if (!this.characteristicInstantiator) { this.characteristicInstantiator = new CharacteristicInstantiator( new MetaModelElementInstantiator(this.modelService.getLoadedAspectModel().rdfModel, null) diff --git a/core/libs/editor/src/lib/editor-dialog/services/index.ts b/core/libs/editor/src/lib/editor-dialog/services/index.ts index 1df4a777..16fb5165 100644 --- a/core/libs/editor/src/lib/editor-dialog/services/index.ts +++ b/core/libs/editor/src/lib/editor-dialog/services/index.ts @@ -11,3 +11,4 @@ * SPDX-License-Identifier: MPL-2.0 */ export * from './shape-settings.service'; +export * from './shape-settings-state.service'; diff --git a/core/libs/editor/src/lib/editor-dialog/services/shape-settings-state.service.ts b/core/libs/editor/src/lib/editor-dialog/services/shape-settings-state.service.ts new file mode 100644 index 00000000..ccbb24fb --- /dev/null +++ b/core/libs/editor/src/lib/editor-dialog/services/shape-settings-state.service.ts @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2023 Robert Bosch Manufacturing Solutions GmbH + * + * See the AUTHORS file(s) distributed with this work for + * additional information regarding authorship. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + */ + +import {Injectable} from '@angular/core'; +import {mxgraph} from 'mxgraph-factory'; +import {BehaviorSubject} from 'rxjs'; +import {EditorModelService} from '../editor-model.service'; + +@Injectable({providedIn: 'root'}) +export class ShapeSettingsStateService { + public selectedShapeForUpdate: mxgraph.mxCell | null; + public isShapeSettingOpened = false; + + onSettingsOpened$ = new BehaviorSubject(this.isShapeSettingOpened); + + constructor(private editorModelService: EditorModelService) {} + + openShapeSettings() { + this.isShapeSettingOpened = true; + this.onSettingsOpened$.next(this.isShapeSettingOpened); + } + + closeShapeSettings() { + this.isShapeSettingOpened = false; + this.onSettingsOpened$.next(this.isShapeSettingOpened); + this.editorModelService._updateMetaModelElement(null); + } +} diff --git a/core/libs/editor/src/lib/editor-dialog/services/shape-settings.service.ts b/core/libs/editor/src/lib/editor-dialog/services/shape-settings.service.ts index 05fcb799..6bea3f37 100644 --- a/core/libs/editor/src/lib/editor-dialog/services/shape-settings.service.ts +++ b/core/libs/editor/src/lib/editor-dialog/services/shape-settings.service.ts @@ -17,26 +17,23 @@ import {MxGraphAttributeService, MxGraphHelper, MxGraphService, MxGraphShapeSele import {BindingsService} from '@ame/shared'; import {mxgraph} from 'mxgraph-factory'; import {EditorService} from '../../editor.service'; -import {BehaviorSubject} from 'rxjs'; +import {ShapeSettingsStateService} from './shape-settings-state.service'; const PURPLE_BLUE = '#448ee4'; const BLACK = 'black'; @Injectable({providedIn: 'root'}) export class ShapeSettingsService { - public selectedShapeForUpdate: mxgraph.mxCell; - public isShapeSettingOpened = false; public modelElement: BaseMetaModelElement = null; private shapesToHighlight: Array | null; - onSettingsOpened$ = new BehaviorSubject(this.isShapeSettingOpened); - constructor( private mxGraphAttributeService: MxGraphAttributeService, private mxGraphService: MxGraphService, private mxGraphShapeSelectorService: MxGraphShapeSelectorService, private bindingsService: BindingsService, - private editorService: EditorService + private editorService: EditorService, + private shapeSettingsStateService: ShapeSettingsStateService ) {} setGraphListeners() { @@ -86,34 +83,25 @@ export class ShapeSettingsService { this.mxGraphAttributeService.graph.addListener(mxEvent.DOUBLE_CLICK, () => this.editSelectedCell()); } - openShapeSettings() { - this.isShapeSettingOpened = true; - this.onSettingsOpened$.next(this.isShapeSettingOpened); - } - - closeShapeSettings() { - this.isShapeSettingOpened = false; - this.onSettingsOpened$.next(this.isShapeSettingOpened); - } - unselectShapeForUpdate() { - this.selectedShapeForUpdate = null; + this.shapeSettingsStateService.selectedShapeForUpdate = null; } editSelectedCell() { - this.selectedShapeForUpdate = this.mxGraphShapeSelectorService.getSelectedShape(); + this.shapeSettingsStateService.selectedShapeForUpdate = this.mxGraphShapeSelectorService.getSelectedShape(); - if (!this.selectedShapeForUpdate || this.selectedShapeForUpdate?.isEdge()) { - this.selectedShapeForUpdate = null; + if (!this.shapeSettingsStateService.selectedShapeForUpdate || this.shapeSettingsStateService.selectedShapeForUpdate?.isEdge()) { + this.shapeSettingsStateService.selectedShapeForUpdate = null; return; } - this.openShapeSettings(); - this.modelElement = MxGraphHelper.getModelElement(this.selectedShapeForUpdate); + this.shapeSettingsStateService.openShapeSettings(); + this.modelElement = MxGraphHelper.getModelElement(this.shapeSettingsStateService.selectedShapeForUpdate); } editModel(elementModel: BaseMetaModelElement) { - this.openShapeSettings(); + console.log('in editModel'); + this.shapeSettingsStateService.openShapeSettings(); this.modelElement = elementModel; } diff --git a/core/libs/editor/src/lib/editor-toolbar/editor-toolbar.component.ts b/core/libs/editor/src/lib/editor-toolbar/editor-toolbar.component.ts index 92250108..625bad15 100644 --- a/core/libs/editor/src/lib/editor-toolbar/editor-toolbar.component.ts +++ b/core/libs/editor/src/lib/editor-toolbar/editor-toolbar.component.ts @@ -22,7 +22,7 @@ import { MxGraphShapeSelectorService, } from '@ame/mx-graph'; import {ConfigurationService, Settings} from '@ame/settings-dialog'; -import {BindingsService, LoadingScreenOptions, NotificationsService, cellRelations} from '@ame/shared'; +import {BindingsService, LoadingScreenOptions, LoadingScreenService, NotificationsService, cellRelations} from '@ame/shared'; import {EditorService} from '../editor.service'; import {ShapeConnectorService, ShapeConnectorUtil} from '@ame/connection'; import {FileHandlingService, GenerateHandlingService, InformationHandlingService} from './services'; @@ -77,7 +77,8 @@ export class EditorToolbarComponent implements AfterViewInit, OnInit, OnDestroy private mxGraphShapeSelectorService: MxGraphShapeSelectorService, private matDialog: MatDialog, private namespaceManagerService: NamespacesManagerService, - private shapeSettingsService: ShapeSettingsService + private shapeSettingsService: ShapeSettingsService, + private loadingScreenService: LoadingScreenService ) {} ngOnInit(): void { @@ -251,13 +252,18 @@ export class EditorToolbarComponent implements AfterViewInit, OnInit, OnDestroy } onToggleExpand() { - if (this.isAllShapesExpanded) { - this.mxGraphService.foldCells(); - } else { - this.mxGraphService.expandCells(); - } - this.isAllShapesExpanded = !this.isAllShapesExpanded; - this.mxGraphService.formatShapes(true); + this.loadingScreenService + .open({ + title: this.isAllShapesExpanded ? 'Folding...' : 'Expanding...', + content: 'Please wait until the action is finished!', + }) + .afterOpened() + .pipe(switchMap(() => (this.isAllShapesExpanded ? this.mxGraphService.foldCells() : this.mxGraphService.expandCells()))) + .subscribe(() => { + this.isAllShapesExpanded = !this.isAllShapesExpanded; + this.mxGraphService.formatShapes(true); + this.loadingScreenService.close(); + }); } openConnectWithDialog() { @@ -281,7 +287,16 @@ export class EditorToolbarComponent implements AfterViewInit, OnInit, OnDestroy } onFormat() { - this.editorService.formatAspect(); + this.loadingScreenService + .open({ + title: 'Formatting...', + content: 'Please wait until formatting finishes', + }) + .afterOpened() + .subscribe(() => { + this.editorService.formatAspect(); + this.loadingScreenService.close(); + }); } onConnect() { diff --git a/core/libs/editor/src/lib/editor-toolbar/interfaces/violation-error.ts b/core/libs/editor/src/lib/editor-toolbar/interfaces/violation-error.ts index cbe9d3a2..94a5675b 100644 --- a/core/libs/editor/src/lib/editor-toolbar/interfaces/violation-error.ts +++ b/core/libs/editor/src/lib/editor-toolbar/interfaces/violation-error.ts @@ -15,4 +15,5 @@ export interface ViolationError { message: string; focusNode: string; fix: string[]; + errorCode?: string; } diff --git a/core/libs/editor/src/lib/editor-toolbar/services/file-handling.service.ts b/core/libs/editor/src/lib/editor-toolbar/services/file-handling.service.ts index 94c40efa..496172a0 100644 --- a/core/libs/editor/src/lib/editor-toolbar/services/file-handling.service.ts +++ b/core/libs/editor/src/lib/editor-toolbar/services/file-handling.service.ts @@ -80,18 +80,26 @@ export class FileHandlingService { this.loadingScreenService.open(loadingScreenOptions); const migratedModel = this.migratorService.bammToSamm(rdfAspectModel); - return this.editorService.loadNewAspectModel(migratedModel, '').pipe( - first(), - catchError(error => { - this.notificationsService.error({ - title: 'Error when loading Aspect Model. Reverting to previous Aspect Model', - message: `${error}`, - timeout: 5000, - }); - return of(null); - }), - finalize(() => this.loadingScreenService.close()) - ); + return this.modelApiService + .validate(migratedModel) + .pipe( + switchMap(validations => { + const found = validations.find(({errorCode}) => errorCode === 'ERR_PROCESSING'); + return found ? throwError(() => found.message) : this.editorService.loadNewAspectModel(migratedModel, ''); + }) + ) + .pipe( + first(), + catchError(error => { + this.notificationsService.error({ + title: 'Error when loading Aspect Model. Reverting to previous Aspect Model', + message: `${error}`, + timeout: 5000, + }); + return of(null); + }), + finalize(() => this.loadingScreenService.close()) + ); }) ); } @@ -257,13 +265,19 @@ export class FileHandlingService { let newModelAbsoluteFileName: string; return this.modelApiService.formatModel(migratedFile).pipe( - tap(formattedModel => (newModelContent = formattedModel)), - switchMap(() => - this.rdfService.loadExternalReferenceModelIntoStore({ - fileName, - aspectMetaModel: newModelContent, - }) - ), + switchMap(formattedModel => { + newModelContent = formattedModel; + return this.modelApiService.validate(migratedFile); + }), + switchMap(validations => { + const found = validations.find(({errorCode}) => errorCode === 'ERR_PROCESSING'); + return found + ? throwError(() => found.message) + : this.rdfService.loadExternalReferenceModelIntoStore({ + fileName, + aspectMetaModel: newModelContent, + }); + }), tap(({absoluteAspectModelFileName}) => (newModelAbsoluteFileName = absoluteAspectModelFileName)), switchMap(() => this.modelApiService.saveModel(newModelContent, newModelAbsoluteFileName)), tap(() => { diff --git a/core/libs/editor/src/lib/editor.service.ts b/core/libs/editor/src/lib/editor.service.ts index 02065076..89dae794 100644 --- a/core/libs/editor/src/lib/editor.service.ts +++ b/core/libs/editor/src/lib/editor.service.ts @@ -64,7 +64,6 @@ import { DefaultCharacteristic, DefaultConstraint, DefaultEntity, - DefaultEntityValue, DefaultEvent, DefaultOperation, DefaultProperty, @@ -83,26 +82,24 @@ import {RdfModel} from '@ame/rdf/utils'; import {Title} from '@angular/platform-browser'; import {OpenApi, ViolationError} from './editor-toolbar'; import {FiltersService, FILTER_ATTRIBUTES, FilterAttributesService} from '@ame/loader-filters'; +import {ShapeSettingsStateService} from './editor-dialog'; @Injectable({ providedIn: 'root', }) export class EditorService { - private filtersService = inject(FiltersService); - private filterAttributes: FilterAttributesService = inject(FILTER_ATTRIBUTES); - private configurationService = inject(ConfigurationService); + loadModel$ = new BehaviorSubject(null); + delayedBindings: Array = []; - private get settings() { - return this.configurationService.getSettings(); - } + private filtersService: FiltersService = inject(FiltersService); + private filterAttributes: FilterAttributesService = inject(FILTER_ATTRIBUTES); + private configurationService: ConfigurationService = inject(ConfigurationService); - private validateModel$ = new BehaviorSubject(this.settings.autoValidationEnabled); + private validateModel$ = new BehaviorSubject(this.settings.autoValidationEnabled); private validateModelSubscription$: Subscription; - private saveModel$ = new BehaviorSubject(this.settings.autoSaveEnabled); + private saveModel$ = new BehaviorSubject(this.settings.autoSaveEnabled); private saveLatestModelSubscription$: Subscription; private lastSavedRDF$ = new BehaviorSubject>({}); - public loadModel$ = new BehaviorSubject(null); - public delayedBindings: Array = []; public get savedRdf$() { return this.lastSavedRDF$.asObservable(); @@ -112,6 +109,10 @@ export class EditorService { return this.namespaceCacheService.currentCachedFile; } + private get settings() { + return this.configurationService.getSettings(); + } + constructor( private mxGraphService: MxGraphService, private mxGraphSetupService: MxGraphSetupService, @@ -131,7 +132,8 @@ export class EditorService { private confirmDialogService: ConfirmDialogService, private elementModelService: ElementModelService, private titleService: Title, - private sidebarService: SidebarService + private sidebarService: SidebarService, + private shapeSettingsStateService: ShapeSettingsStateService ) { if (!environment.production) { window['angular.editorService'] = this; @@ -223,14 +225,6 @@ export class EditorService { this.mxGraphAttributeService.editor.addAction(actionName, callback); } - removeEntityValueToEntityValueEdge(parentEntityValue: DefaultEntityValue, childEntityValue: DefaultEntityValue): void { - const parentEntityValueCell = this.mxGraphService.resolveCellByModelElement(parentEntityValue); - const childEntityValueCell = this.mxGraphService.resolveCellByModelElement(childEntityValue); - const edgeToRemove = parentEntityValueCell.edges.find(edge => edge.target === childEntityValueCell); - - this.mxGraphService.removeCells([edgeToRemove]); - } - handleFileVersionConflicts(fileName: string, fileContent: string): Observable { const currentModel = this.rdfService.currentRdfModel; @@ -287,44 +281,47 @@ export class EditorService { return this.instantiatorService.instantiateFile(extRdfModel, findCacheFile, fileName); } - public loadExternalModels(loadedRdfModel?: RdfModel) { + loadExternalModels(loadedRdfModel?: RdfModel): Observable { this.rdfService.externalRdfModels = []; - return this.modelApiService.getAllNamespacesFilesContent(loadedRdfModel).pipe( - mergeMap((fileContentModels: Array) => { - if (fileContentModels.length) { - return forkJoin(fileContentModels.map(fileContent => this.rdfService.loadExternalReferenceModelIntoStore(fileContent))); - } - return of([]); - }) - ); + return this.modelApiService + .getAllNamespacesFilesContent(loadedRdfModel?.absoluteAspectModelFileName) + .pipe( + mergeMap((fileContentModels: Array) => + fileContentModels.length + ? forkJoin(fileContentModels.map(fileContent => this.rdfService.loadExternalReferenceModelIntoStore(fileContent))) + : of([]) + ) + ); } - public addAspectModelFileIntoStore(aspectModelFileName: string): Observable { + loadModels(): Observable { return this.modelApiService - .getAspectMetaModel(aspectModelFileName) + .getAllNamespacesFilesContent() .pipe( - tap(aspectModel => this.rdfService.loadExternalReferenceModelIntoStore(new FileContentModel(aspectModelFileName, aspectModel))) + mergeMap((fileContentModels: FileContentModel[]) => + fileContentModels.length ? this.rdfService.parseModels(fileContentModels) : of([]) + ) ); } - public removeAspectModelFileFromStore(aspectModelFileName: string) { + removeAspectModelFileFromStore(aspectModelFileName: string) { const index = this.rdfService.externalRdfModels.findIndex( extRdfModel => extRdfModel.absoluteAspectModelFileName === aspectModelFileName ); this.rdfService.externalRdfModels.splice(index, 1); } - public generateJsonSample(rdfModel: RdfModel) { + generateJsonSample(rdfModel: RdfModel): Observable { const serializedModel = this.rdfService.serializeModel(rdfModel); return this.modelApiService.generateJsonSample(serializedModel); } - public generateJsonSchema(rdfModel: RdfModel, language: string) { + generateJsonSchema(rdfModel: RdfModel, language: string): Observable { const serializedModel = this.rdfService.serializeModel(rdfModel); return this.modelApiService.generateJsonSchema(serializedModel, language); } - public generateOpenApiSpec(rdfModel: RdfModel, openApi: OpenApi) { + generateOpenApiSpec(rdfModel: RdfModel, openApi: OpenApi): Observable { const serializedModel = this.rdfService.serializeModel(rdfModel); return this.modelApiService.generateOpenApiSpec(serializedModel, openApi); } @@ -365,21 +362,21 @@ export class EditorService { this.mxGraphService .updateGraph(() => { this.mxGraphService.firstTimeFold = true; + MxGraphHelper.filterMode = this.filtersService.currentFilter.filterType; const rootElements = this.namespaceCacheService.currentCachedFile.getAllElements().filter(e => !e.parents.length); const filtered = this.filtersService.filter(rootElements); for (const elementTree of filtered) { mxGraphRenderer.render(elementTree, null); } + + this.mxGraphAttributeService.inCollapsedMode && this.mxGraphService.foldCells(); }) - .pipe( - tap(() => { - this.mxGraphService.formatShapes(true); - this.mxGraphSetupService.centerGraph(); - }), - switchMap(() => this.validate()) - ) - .subscribe(() => localStorage.removeItem(ValidateStatus.validating)); + .subscribe(() => { + this.mxGraphService.formatShapes(true); + this.mxGraphSetupService.centerGraph(); + localStorage.removeItem(ValidateStatus.validating); + }); } catch (error) { console.groupCollapsed('editor.service', error); console.groupEnd(); @@ -553,6 +550,10 @@ export class EditorService { } private deleteElements(cells: mxgraph.mxCell[]): void { + if (this.shapeSettingsStateService.isShapeSettingOpened && cells.includes(this.shapeSettingsStateService.selectedShapeForUpdate)) { + this.shapeSettingsStateService.closeShapeSettings(); + } + cells.forEach((cell: mxgraph.mxCell) => { this.mxGraphAttributeService.graph.setCellStyles( mxConstants.STYLE_STROKECOLOR, @@ -610,7 +611,7 @@ export class EditorService { } } - validateModel() { + validateModel(): Observable { return this.validateModel$.asObservable().pipe( delayWhen(() => timer(this.settings.validationTimerSeconds * 1000)), switchMap(() => this.validate().pipe(first())), @@ -734,7 +735,7 @@ export class EditorService { ); } - getSerializedModel() { + getSerializedModel(): string { return this.rdfService.serializeModel(this.modelService.getLoadedAspectModel().rdfModel); } diff --git a/core/libs/loader-filters/src/lib/filters.service.ts b/core/libs/loader-filters/src/lib/filters.service.ts index 095eddaa..4fa1e5de 100644 --- a/core/libs/loader-filters/src/lib/filters.service.ts +++ b/core/libs/loader-filters/src/lib/filters.service.ts @@ -16,12 +16,14 @@ import {DefaultFilter} from './filters/default-filter'; import {PropertiesFilterLoader} from './filters/properties-filter'; import {FilterLoader, ModelFilter, ModelTree, ModelTreeOptions} from './models'; import {BaseMetaModelElement} from '@ame/meta-model'; -import {MxGraphHelper, MxGraphRenderer, MxGraphService, MxGraphShapeOverlayService} from '@ame/mx-graph'; +import {MxGraphAttributeService, MxGraphHelper, MxGraphRenderer, MxGraphService, MxGraphShapeOverlayService} from '@ame/mx-graph'; import {NamespacesCacheService} from '@ame/cache'; import {ModelService} from '@ame/rdf/services'; import {LanguageSettingsService} from '@ame/settings-dialog'; import {LoadingScreenService} from '@ame/shared'; import {FILTER_ATTRIBUTES, FilterAttributesService} from './active-filter.session'; +import {switchMap} from 'rxjs'; +import {EditorService} from '@ame/editor'; export type Filters = { default: FilterLoader; @@ -58,7 +60,7 @@ export class FiltersService { } selectPropertiesFilter() { - this.currentFilter = new PropertiesFilterLoader(); + this.currentFilter = new PropertiesFilterLoader(this.injector); this.filterAttributesService.activeFilter = ModelFilter.PROPERTIES; } @@ -86,42 +88,52 @@ export class FiltersService { renderByFilter(filter: ModelFilter) { const mxGraphService = this.injector.get(MxGraphService); + const editorService = this.injector.get(EditorService); let selectedCell = mxGraphService.graph.selectionModel.cells?.[0]; const selectedModelElement = selectedCell && MxGraphHelper.getModelElement(selectedCell); this.loadingScreen .open({title: 'Changing filter...', content: 'Please wait until the filtering is done'}) .afterOpened() - .subscribe(() => { - this.filterAttributesService.isFiltering = true; - this.filtersMethods[filter]?.(); - const namespaceCacheService = this.injector.get(NamespacesCacheService); - const mxGraphSetupVisitor = new MxGraphRenderer( - mxGraphService, - this.injector.get(MxGraphShapeOverlayService), - namespaceCacheService, - this.injector.get(LanguageSettingsService), - this.injector.get(ModelService).getLoadedAspectModel().rdfModel - ); - - const currentFile = namespaceCacheService.currentCachedFile; - const rootElements = currentFile.getAllElements().filter(e => e.parents.length <= 0); - const filteredElements = this.filter(rootElements); - - mxGraphService.deleteAllShapes(); - mxGraphService - .updateGraph(() => { + .pipe( + switchMap(() => { + MxGraphHelper.filterMode = filter; + this.filterAttributesService.isFiltering = true; + this.filtersMethods[filter]?.(); + const namespaceCacheService = this.injector.get(NamespacesCacheService); + const mxGraphSetupVisitor = new MxGraphRenderer( + mxGraphService, + this.injector.get(MxGraphShapeOverlayService), + namespaceCacheService, + this.injector.get(LanguageSettingsService), + this.injector.get(ModelService).getLoadedAspectModel().rdfModel + ); + + const currentFile = namespaceCacheService.currentCachedFile; + const rootElements = currentFile.getAllElements().filter(e => e.parents.length <= 0); + const filteredElements = this.filter(rootElements); + + mxGraphService.deleteAllShapes(); + + return mxGraphService.updateGraph(() => { for (const elementTree of filteredElements) { mxGraphSetupVisitor.render(elementTree, null); } - }) - .subscribe(() => { - mxGraphService.formatShapes(true); - this.filterAttributesService.isFiltering = false; - selectedCell = selectedModelElement && mxGraphService.resolveCellByModelElement(selectedModelElement); - if (selectedCell) mxGraphService.navigateToCellByUrn(selectedModelElement.aspectModelUrn); - this.loadingScreen.close(); + this.injector.get(MxGraphAttributeService).inCollapsedMode && mxGraphService.foldCells(); }); + }), + switchMap(() => { + mxGraphService.formatShapes(true); + this.filterAttributesService.isFiltering = false; + selectedCell = selectedModelElement && mxGraphService.resolveCellByModelElement(selectedModelElement); + if (selectedCell) mxGraphService.navigateToCellByUrn(selectedModelElement.aspectModelUrn); + + return editorService.validate(); + }) + ) + .subscribe(() => { + localStorage.removeItem('validating'); + this.loadingScreen.close(); }); } } diff --git a/core/libs/loader-filters/src/lib/filters/properties-filter.ts b/core/libs/loader-filters/src/lib/filters/properties-filter.ts index 38439bd9..9ab406f1 100644 --- a/core/libs/loader-filters/src/lib/filters/properties-filter.ts +++ b/core/libs/loader-filters/src/lib/filters/properties-filter.ts @@ -24,6 +24,8 @@ import { import {ArrowStyle, ChildrenArray, FilterLoader, ModelFilter, ModelTree, ModelTreeOptions} from '../models'; import {ShapeGeometry, basicShapeGeometry, circleShapeGeometry} from '@ame/shared'; import {MxGraphHelper} from '@ame/mx-graph'; +import {Injector} from '@angular/core'; +import {ShapeSettingsStateService} from '@ame/editor'; const allowedElements = [DefaultAspect, DefaultProperty, DefaultEntity, DefaultEither]; @@ -32,7 +34,14 @@ export class PropertiesFilterLoader implements FilterLoader { filterType: ModelFilter = ModelFilter.PROPERTIES; visibleElements = [DefaultAspect, DefaultProperty]; + constructor(private injector: Injector) {} + filter(rootElements: BaseMetaModelElement[]): ModelTree[] { + const shapeSettingsStateService = this.injector.get(ShapeSettingsStateService); + if (shapeSettingsStateService.isShapeSettingOpened) { + shapeSettingsStateService.closeShapeSettings(); + } + return rootElements .map(element => { this.cache = {}; diff --git a/core/libs/loader-filters/src/lib/models/filter-loader.interface.ts b/core/libs/loader-filters/src/lib/models/filter-loader.interface.ts index 6f8d967a..8c34b8cd 100644 --- a/core/libs/loader-filters/src/lib/models/filter-loader.interface.ts +++ b/core/libs/loader-filters/src/lib/models/filter-loader.interface.ts @@ -17,7 +17,7 @@ import {ShapeGeometry} from '@ame/shared'; /** * Generates class type which implements an interface */ -export type ClassImplementing = new (...args: Args) => BaseMetaModelElement; +export type ClassReference = new (...args: Args) => T; export type ArrowStyle = 'entityValueEntityEdge' | 'optionalPropertyEdge' | 'abstractPropertyEdge' | 'abstractElementEdge' | 'defaultEdge'; @@ -74,7 +74,7 @@ export type ModelTreeOptions = Partial<{ /** * Any class in this list will not be considered for the next filter loop */ - notAllowed: ClassImplementing[]; + notAllowed: ClassReference[]; }>; export enum ModelFilter { @@ -85,7 +85,7 @@ export enum ModelFilter { export interface FilterLoader { cache: {[key: string]: boolean}; filterType: ModelFilter; - visibleElements: ClassImplementing[]; + visibleElements: ClassReference[]; filter(rootElements: T[]): ModelTree[]; generateTree(element: T, options?: ModelTreeOptions): ModelTree; getArrowStyle(element: T, parent: T): ArrowStyle; diff --git a/core/libs/loader-filters/src/lib/models/filter-relations.ts b/core/libs/loader-filters/src/lib/models/filter-relations.ts new file mode 100644 index 00000000..3fce3b45 --- /dev/null +++ b/core/libs/loader-filters/src/lib/models/filter-relations.ts @@ -0,0 +1,63 @@ +import { + BaseMetaModelElement, + DefaultAspect, + DefaultProperty, + DefaultOperation, + DefaultEvent, + DefaultCharacteristic, + DefaultTrait, + DefaultAbstractProperty, + DefaultConstraint, + DefaultCollection, + DefaultStructuredValue, + DefaultEither, + DefaultEntity, + DefaultEntityValue, + DefaultUnit, + DefaultAbstractEntity, +} from '@ame/meta-model'; +import {ClassReference, ModelFilter} from './filter-loader.interface'; + +export class FilterRelation { + constructor( + public from: ClassReference, + public to: ClassReference[], + public exceptInFilter: { + [ModelFilter.DEFAULT]?: ClassReference[]; + [ModelFilter.PROPERTIES]?: ClassReference[]; + } = {} + ) { + if (!this.exceptInFilter[ModelFilter.DEFAULT]) { + this.exceptInFilter[ModelFilter.DEFAULT] = []; + } + + if (!this.exceptInFilter[ModelFilter.PROPERTIES]) { + this.exceptInFilter[ModelFilter.PROPERTIES] = []; + } + } + + isExceptions(element: BaseMetaModelElement, filterMode: ModelFilter) { + return this.exceptInFilter[filterMode].some(c => element instanceof c); + } +} + +export const filterRelations = [ + new FilterRelation(DefaultAspect, [DefaultProperty, DefaultOperation, DefaultEvent]), + new FilterRelation(DefaultProperty, [DefaultCharacteristic, DefaultTrait, DefaultAbstractProperty, DefaultProperty], { + [ModelFilter.PROPERTIES]: [DefaultProperty], + }), + new FilterRelation(DefaultAbstractProperty, [DefaultAbstractProperty]), + new FilterRelation(DefaultTrait, [DefaultConstraint, DefaultCharacteristic], { + [ModelFilter.PROPERTIES]: [DefaultProperty], + }), + new FilterRelation(DefaultCollection, [DefaultCharacteristic]), + new FilterRelation(DefaultStructuredValue, [DefaultProperty]), + new FilterRelation(DefaultEither, [DefaultCharacteristic]), + new FilterRelation(DefaultCharacteristic, [DefaultEntity, DefaultEntityValue, DefaultUnit]), + new FilterRelation(DefaultEntity, [DefaultProperty, DefaultEntity, DefaultAbstractEntity]), + new FilterRelation(DefaultEntityValue, [DefaultEntityValue, DefaultEntity]), + new FilterRelation(DefaultEvent, [DefaultProperty]), + new FilterRelation(DefaultOperation, [DefaultProperty]), + new FilterRelation(DefaultUnit, [DefaultUnit]), + new FilterRelation(DefaultAbstractEntity, [DefaultAbstractEntity, DefaultProperty, DefaultAbstractProperty]), +]; diff --git a/core/libs/loader-filters/src/lib/models/index.ts b/core/libs/loader-filters/src/lib/models/index.ts index cf0142ed..bfc24cca 100644 --- a/core/libs/loader-filters/src/lib/models/index.ts +++ b/core/libs/loader-filters/src/lib/models/index.ts @@ -12,3 +12,4 @@ */ export * from './filter-loader.interface'; +export * from './filter-relations'; diff --git a/core/libs/meta-model/src/lib/element-service/base-entity-model.service.ts b/core/libs/meta-model/src/lib/element-service/base-entity-model.service.ts index e1c0f950..327a781a 100644 --- a/core/libs/meta-model/src/lib/element-service/base-entity-model.service.ts +++ b/core/libs/meta-model/src/lib/element-service/base-entity-model.service.ts @@ -13,6 +13,7 @@ import {MxGraphHelper, MxGraphService} from '@ame/mx-graph'; import {NotificationsService} from '@ame/shared'; +import {ShapeConnectorService} from '@ame/connection'; import {Injectable} from '@angular/core'; import {CanExtend, DefaultAbstractEntity, DefaultEntity} from '../aspect-meta-model'; @@ -20,7 +21,11 @@ import {CanExtend, DefaultAbstractEntity, DefaultEntity} from '../aspect-meta-mo providedIn: 'root', }) export class BaseEntityModelService { - constructor(private mxGraphService: MxGraphService, private notificationService: NotificationsService) {} + constructor( + private mxGraphService: MxGraphService, + private notificationService: NotificationsService, + private shapeConnectorService: ShapeConnectorService + ) {} checkExtendedElement(metaModelElement: CanExtend, extendedElement: CanExtend) { if (extendedElement && ![DefaultEntity, DefaultAbstractEntity].some(c => extendedElement instanceof c)) { @@ -38,6 +43,15 @@ export class BaseEntityModelService { return; } + if (extendedElement && extendedElement instanceof DefaultAbstractEntity && !extendedElement.predefined) { + this.shapeConnectorService.connectShapes( + metaModelElement, + extendedElement, + this.mxGraphService.resolveCellByModelElement(metaModelElement), + resolvedCell + ); + } + metaModelElement.extendedElement = extendedElement; } } diff --git a/core/libs/meta-model/src/lib/element-service/element-model.service.ts b/core/libs/meta-model/src/lib/element-service/element-model.service.ts index b5079ea0..32c5ac7d 100644 --- a/core/libs/meta-model/src/lib/element-service/element-model.service.ts +++ b/core/libs/meta-model/src/lib/element-service/element-model.service.ts @@ -58,6 +58,7 @@ export class ElementModelService { } const characteristicModelService = this.injector.get(CharacteristicModelService); const modelElement = MxGraphHelper.getModelElement(cell); + const modelService = modelElement instanceof DefaultEnumeration ? characteristicModelService : this.modelRootService.getElementModelService(modelElement); modelService.update(cell, form); diff --git a/core/libs/mx-graph/src/lib/helpers/mx-graph-helper.ts b/core/libs/mx-graph/src/lib/helpers/mx-graph-helper.ts index 29f804ea..0f0a7ae9 100644 --- a/core/libs/mx-graph/src/lib/helpers/mx-graph-helper.ts +++ b/core/libs/mx-graph/src/lib/helpers/mx-graph-helper.ts @@ -27,14 +27,16 @@ import { } from '@ame/meta-model'; import {RdfModelUtil} from '@ame/rdf/utils'; import {LanguageSettingsService} from '@ame/settings-dialog'; -import {basicShapeGeometry, ModelCompactTreeLayout, ModelHierarchicalLayout, modelRelations} from '@ame/shared'; +import {basicShapeGeometry, ModelCompactTreeLayout, ModelHierarchicalLayout} from '@ame/shared'; import {mxgraph} from 'mxgraph-factory'; import {ModelBaseProperties} from '../models'; import {mxCompactTreeLayout, mxConstants, mxHierarchicalLayout} from '../providers'; import {MxGraphVisitorHelper, ShapeAttribute} from './mx-graph-visitor-helper'; -import {ModelTree} from '@ame/loader-filters'; +import {ModelFilter, ModelTree, filterRelations} from '@ame/loader-filters'; export class MxGraphHelper { + static filterMode: ModelFilter = ModelFilter.DEFAULT; + /** * Gets the node element for a cell * @@ -154,7 +156,7 @@ export class MxGraphHelper { * @param child child for parent */ static establishRelation(parent: BaseMetaModelElement, child: BaseMetaModelElement) { - const hasRelation = modelRelations.some(relation => { + const hasRelation = filterRelations.some(relation => { if (!(parent instanceof relation.from)) { return false; } @@ -163,7 +165,7 @@ export class MxGraphHelper { return false; } - return true; + return !relation.isExceptions(child, this.filterMode); }); if (hasRelation) { @@ -288,6 +290,7 @@ export class MxGraphHelper { } return p; } + if (targetModelElement instanceof DefaultProperty && sourceModelElement instanceof DefaultEntity) { const entityIncomingEdges = graph.getIncomingEdges(cell.source); let hasEnumeration = false; diff --git a/core/libs/mx-graph/src/lib/services/mx-graph-setup.service.ts b/core/libs/mx-graph/src/lib/services/mx-graph-setup.service.ts index 0eea6778..8e80ac8d 100644 --- a/core/libs/mx-graph/src/lib/services/mx-graph-setup.service.ts +++ b/core/libs/mx-graph/src/lib/services/mx-graph-setup.service.ts @@ -16,7 +16,7 @@ * https://github.com/jgraph/mxgraph/blob/master/javascript/examples/extendcanvas.html */ -import {Inject, Injectable} from '@angular/core'; +import {Inject, Injectable, NgZone} from '@angular/core'; import {mxgraph} from 'mxgraph-factory'; import {MxGraphShapeSelectorService} from './mx-graph-shape-selector.service'; import {MxGraphAttributeService} from './mx-graph-attribute.service'; @@ -44,52 +44,56 @@ export class MxGraphSetupService { private bindingsService: BindingsService, private browserService: BrowserService, private mxGraphShapeSelectorService: MxGraphShapeSelectorService, - private mxGraphAttributeService: MxGraphAttributeService + private mxGraphAttributeService: MxGraphAttributeService, + private ngZone: NgZone ) {} setUp() { - const editor = (this.mxGraphAttributeService.editor = new mxEditor( - mxUtils.load(this.appConfig.editorConfiguration).getDocumentElement() - )); - this.graph = this.mxGraphAttributeService.graph = (editor as any).graph; - - this.scrollTileSize = new mxRectangle(0, 0, this.graph.container.clientWidth, this.graph.container.clientHeight); - this.graphSizeDidChange = this.graph.sizeDidChange; - this.graphCellRedraw = this.graph.cellRenderer.redraw; - - this.graph.setPanning(true); - this.graph.setCellsEditable(false); - this.graph.setCellsResizable(false); - this.graph.graphHandler.setRemoveCellsFromParent(false); - this.graph.setAllowDanglingEdges(false); - this.graph.setCellsDisconnectable(false); - - this.graph.popupMenuHandler.factoryMethod = (menu: mxgraph.mxPopupMenu, cell: mxgraph.mxCell) => this.getPopupFactoryMethod(menu, cell); - this.graph.view.getBackgroundPageBounds = () => this.getBackgroundPageBounds(); - this.graph.getPreferredPageSize = () => this.getPreferredPageSize(); - this.graph.sizeDidChange = () => this.sizeDidChange(); - this.graph.convertValueToString = (cell: mxgraph.mxCell) => this.convertValueToString(cell); - this.graph.cellRenderer.redraw = (state, force, rendering) => this.redraw(state, force, rendering); - this.graph.getTooltipForCell = (cell: mxgraph.mxCell) => this.getTooltipForCell(cell); - this.graph.isCellVisible = (cell: mxgraph.mxCell) => this.isCellVisible(cell); - this.graph.setHtmlLabels(true); - - this.initializeGraphConstants(); - this.initLayout(); - - this.graph.getLabel = (cell): any => { - if (!cell.value && this.configurationService.getSettings().showConnectionLabels) { - // label for edges - return MxGraphHelper.createEdgeLabel(cell, this.graph); - } + this.ngZone.runOutsideAngular(() => { + const editor = (this.mxGraphAttributeService.editor = new mxEditor( + mxUtils.load(this.appConfig.editorConfiguration).getDocumentElement() + )); + this.graph = this.mxGraphAttributeService.graph = (editor as any).graph; + + this.scrollTileSize = new mxRectangle(0, 0, this.graph.container.clientWidth, this.graph.container.clientHeight); + this.graphSizeDidChange = this.graph.sizeDidChange; + this.graphCellRedraw = this.graph.cellRenderer.redraw; + + this.graph.setPanning(true); + this.graph.setCellsEditable(false); + this.graph.setCellsResizable(false); + this.graph.graphHandler.setRemoveCellsFromParent(false); + this.graph.setAllowDanglingEdges(false); + this.graph.setCellsDisconnectable(false); + + this.graph.popupMenuHandler.factoryMethod = (menu: mxgraph.mxPopupMenu, cell: mxgraph.mxCell) => + this.getPopupFactoryMethod(menu, cell); + this.graph.view.getBackgroundPageBounds = () => this.getBackgroundPageBounds(); + this.graph.getPreferredPageSize = () => this.getPreferredPageSize(); + this.graph.sizeDidChange = () => this.sizeDidChange(); + this.graph.convertValueToString = (cell: mxgraph.mxCell) => this.convertValueToString(cell); + this.graph.cellRenderer.redraw = (state, force, rendering) => this.redraw(state, force, rendering); + this.graph.getTooltipForCell = (cell: mxgraph.mxCell) => this.getTooltipForCell(cell); + this.graph.isCellVisible = (cell: mxgraph.mxCell) => this.isCellVisible(cell); + this.graph.setHtmlLabels(true); + + this.initializeGraphConstants(); + this.initLayout(); + + this.graph.getLabel = (cell): any => { + if (!cell.value && this.configurationService.getSettings().showConnectionLabels) { + // label for edges + return MxGraphHelper.createEdgeLabel(cell, this.graph); + } - if (!cell.connectable) { - // label for sub cells - return; - } + if (!cell.connectable) { + // label for sub cells + return; + } - return MxGraphHelper.createPropertiesLabel(cell); - }; + return MxGraphHelper.createPropertiesLabel(cell); + }; + }); } // construct the path for the asset diff --git a/core/libs/mx-graph/src/lib/services/mx-graph.service.ts b/core/libs/mx-graph/src/lib/services/mx-graph.service.ts index 871daf9e..5b4e1d98 100644 --- a/core/libs/mx-graph/src/lib/services/mx-graph.service.ts +++ b/core/libs/mx-graph/src/lib/services/mx-graph.service.ts @@ -133,7 +133,6 @@ export class MxGraphService { * @throws {Error} - If there are issues in shape creation or overlay operations. */ renderModelElement(node: ModelTree, configuration?: ShapeConfiguration): mxgraph.mxCell { - let modelShape: mxgraph.mxCell; const geometry = this.mxGraphGeometryProviderService.createGeometry( node, (configuration && configuration.geometry.x) || this.nextCellCoordinates?.x || 0, @@ -141,29 +140,25 @@ export class MxGraphService { ); this.nextCellCoordinates = null; + let cellStyle = node.shape.mxGraphStyle || ''; - try { - modelShape = this.mxGraphShapeOverlayService.createShape(node, geometry, configuration?.shapeAttributes || []); - MxGraphHelper.setElementNode(modelShape, node); + cellStyle = this.themeService.generateThemeStyle(cellStyle); + if (node.element.isExternalReference()) { + cellStyle = mxUtils.setStyle(cellStyle, mxConstants.STYLE_FILL_OPACITY, 80); + } - this.themeService.applyShapeStyle(modelShape); + node.shape.mxGraphStyle = cellStyle; + const modelShape = this.mxGraphShapeOverlayService.createShape(node, geometry, configuration?.shapeAttributes || []); + MxGraphHelper.setElementNode(modelShape, node); - if (node.element.isExternalReference()) { - const style = this.graph.getModel().getStyle(modelShape); - const newStyle = mxUtils.setStyle(style, mxConstants.STYLE_FILL_OPACITY, 80); - this.graph.setCellStyle(newStyle, [modelShape]); - } + this.mxGraphShapeOverlayService.checkComplexEnumerationOverlays(node.element, modelShape); - this.mxGraphShapeOverlayService.checkComplexEnumerationOverlays(node.element, modelShape); - - if (!node.element.isExternalReference()) { - this.mxGraphShapeOverlayService.addBottomShapeOverlay(modelShape); - this.mxGraphShapeOverlayService.addTopShapeOverlay(modelShape); - } - } finally { - this.mxGraphAttributeService.inCollapsedMode ? this.foldCell(modelShape) : this.expandCell(modelShape); - this.graph.resizeCell(modelShape, geometry); + if (!node.element.isExternalReference()) { + this.mxGraphShapeOverlayService.addBottomShapeOverlay(modelShape); + this.mxGraphShapeOverlayService.addTopShapeOverlay(modelShape); } + this.graph.labelChanged(modelShape, MxGraphHelper.createPropertiesLabel(modelShape)); + this.mxGraphAttributeService.inCollapsedMode && this.foldCell(modelShape); return modelShape; } @@ -252,12 +247,12 @@ export class MxGraphService { /** Expand all cells*/ expandCells() { - this.updateGraph(() => { - const cells = this.graph.getChildCells(this.graph.getDefaultParent(), true, false); - this.graph.foldCells(false, true, cells); - this.mxGraphAttributeService.inCollapsedMode = false; + const cells = this.graph.getChildCells(this.graph.getDefaultParent(), true, false); + this.graph.foldCells(false, true, cells); + this.mxGraphAttributeService.inCollapsedMode = false; - cells.forEach(cell => { + return this.updateGraph(() => { + for (const cell of cells) { this.graph.resizeCell( cell, this.mxGraphGeometryProviderService.createGeometry(MxGraphHelper.getElementNode(cell), cell?.geometry?.x, cell?.geometry?.y) @@ -272,13 +267,13 @@ export class MxGraphService { MxGraphHelper.setConstrainOverlayOffset(overlay, cell); }); - }); - this.formatShapes(true); - }).subscribe(() => { + } + const selectedCell = this.mxGraphShapeSelectorService.getSelectedShape(); if (selectedCell) { this.navigateToCell(selectedCell, true); } + if (this.firstTimeFold) { this.firstTimeFold = false; this.formatShapes(true); @@ -289,11 +284,12 @@ export class MxGraphService { /** Collapse all cells */ foldCells() { - this.updateGraph(() => { - const cells = this.graph.getChildCells(this.graph.getDefaultParent(), true, false); - this.graph.foldCells(true, true, cells); + const cells = this.graph.getChildCells(this.graph.getDefaultParent(), true, false); + this.graph.foldCells(true, true, cells); + this.mxGraphAttributeService.inCollapsedMode = true; - cells.forEach(cell => { + return this.updateGraph(() => { + for (const cell of cells) { const modelElement = MxGraphHelper.getModelElement(cell); if (MxGraphHelper.isComplexEnumeration(modelElement)) { this.mxGraphShapeOverlayService.removeOverlay(cell, MxGraphHelper.getRightOverlayButton(cell)); @@ -309,11 +305,8 @@ export class MxGraphService { const isVertex = this.graph.model.isVertex(cell); this.mxGraphGeometryProviderService.upgradeTraitGeometry(cell, geometry, isVertex); this.mxGraphGeometryProviderService.upgradeEntityValueGeometry(cell, geometry, isVertex); - }); + } - this.mxGraphAttributeService.inCollapsedMode = true; - this.formatShapes(true); - }).subscribe(() => { const selectedCell = this.mxGraphShapeSelectorService.getSelectedShape(); if (selectedCell) { this.navigateToCell(selectedCell, true); @@ -333,6 +326,12 @@ export class MxGraphService { */ expandCell(cell: mxgraph.mxCell): void { this.graph.foldCells(false, false, [cell]); + cell.overlays?.forEach(overlay => { + overlay.image.width = overlayGeometry.expandedWith; + overlay.image.height = overlayGeometry.expandedHeight; + + MxGraphHelper.setConstrainOverlayOffset(overlay, cell); + }); } /** @@ -342,6 +341,13 @@ export class MxGraphService { */ foldCell(cell: mxgraph.mxCell): void { this.graph.foldCells(true, false, [cell]); + cell.overlays?.forEach(overlay => { + overlay.image.width = overlayGeometry.collapsedWidth; + overlay.image.height = overlayGeometry.collapsedHeight; + + MxGraphHelper.setConstrainOverlayOffset(overlay, cell); + }); + this.graph.refresh(); } /** Re-formats entire schematic. */ diff --git a/core/libs/mx-graph/src/lib/themes/theme.service.ts b/core/libs/mx-graph/src/lib/themes/theme.service.ts index dada9a2d..a6da1840 100644 --- a/core/libs/mx-graph/src/lib/themes/theme.service.ts +++ b/core/libs/mx-graph/src/lib/themes/theme.service.ts @@ -58,21 +58,23 @@ export class ThemeService { applyTheme(theme: string) { this.setCssVars(theme); this.graph.getChildVertices(this.graph.getDefaultParent()).forEach((shape: mxgraph.mxCell) => { - this.applyShapeStyle(shape); + this.graph.setCellStyle(this.generateThemeStyle(shape.style), [shape]); }); } - applyShapeStyle(shape: mxgraph.mxCell) { - const shapeStyle = this.graph.getModel().getStyle(shape)?.split(';')[0]; + generateThemeStyle(cellStyle: string) { + const shapeStyle = cellStyle?.split(';')[0]; if (!shapeStyle) { - return; + return ''; } - const style = [...Object.entries(this.theme[shapeStyle]), ...Object.entries(this.getDefaultShapesColors)].reduce( - (acc, [key, value]) => `${acc};${key}=${value}`, - '' + return ( + shapeStyle + + [...Object.entries(this.theme[shapeStyle]), ...Object.entries(this.getDefaultShapesColors)].reduce( + (acc, [key, value]) => `${acc};${key}=${value}`, + '' + ) ); - this.graph.setCellStyle(`${shapeStyle}${style}`, [shape]); } setCssVars(theme: string) { diff --git a/core/libs/namespace-manager/src/lib/namespace-exporter/components/select-namespaces/select-namespaces.component.html b/core/libs/namespace-manager/src/lib/namespace-exporter/components/select-namespaces/select-namespaces.component.html index 7a072eef..b7ca2986 100644 --- a/core/libs/namespace-manager/src/lib/namespace-exporter/components/select-namespaces/select-namespaces.component.html +++ b/core/libs/namespace-manager/src/lib/namespace-exporter/components/select-namespaces/select-namespaces.component.html @@ -25,6 +25,7 @@

Namespaces

[disabled]="item.value.disabled" (change)="toggleNamespace($event, item.key)" class="namespace" + data-cy="enNamespaceList" >
{{ item.key }} diff --git a/core/libs/namespace-manager/src/lib/namespace-exporter/components/select-namespaces/select-namespaces.component.ts b/core/libs/namespace-manager/src/lib/namespace-exporter/components/select-namespaces/select-namespaces.component.ts index b04ebe8d..4dabd03a 100644 --- a/core/libs/namespace-manager/src/lib/namespace-exporter/components/select-namespaces/select-namespaces.component.ts +++ b/core/libs/namespace-manager/src/lib/namespace-exporter/components/select-namespaces/select-namespaces.component.ts @@ -15,9 +15,12 @@ import {Component, OnInit} from '@angular/core'; import {MatCheckboxChange} from '@angular/material/checkbox'; import {Router} from '@angular/router'; import {NamespacesManagerService} from '../../../shared'; -import {FlatNode} from '../../../shared/models'; import {RdfService} from '@ame/rdf/services'; import {Prefixes} from 'n3'; +import {RdfModel, RdfModelUtil} from '@ame/rdf/utils'; +import {EditorService} from '@ame/editor'; +import {tap} from 'rxjs/operators'; +import {first} from 'rxjs'; const nonDependentNamespaces = [ 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', @@ -29,23 +32,58 @@ const nonDependentNamespaces = [ 'http://www.w3.org/2001/XMLSchema#', ]; +interface NamespacesDependencies { + [namespace: string]: { + disabled: boolean; + dependencies: string[]; + files: string[]; + checked: boolean; + }; +} + @Component({ templateUrl: './select-namespaces.component.html', styleUrls: ['select-namespaces.component.scss'], }) export class SelectNamespacesComponent implements OnInit { - public selectedNamespaces: string[] = []; - public namespacesDependencies: {[namespace: string]: {disabled: boolean; dependencies: string[]; files: string[]; checked: boolean}} = {}; + selectedNamespaces: string[] = []; + namespacesDependencies: NamespacesDependencies = {}; - private readonly namespaceSplitter = ':'; - private visitedNamespaces = []; + private visitedNamespaces: string[] = []; - constructor(private namespacesManager: NamespacesManagerService, private rdfService: RdfService, private router: Router) {} + constructor( + private namespacesManager: NamespacesManagerService, + private rdfService: RdfService, + private editorService: EditorService, + private router: Router + ) {} ngOnInit(): void { - this.namespacesDependencies = this.rdfService.externalRdfModels.reduce((acc, rdfModel) => { - const [namespace, version, file] = rdfModel.absoluteAspectModelFileName.split(this.namespaceSplitter); - const versionedNamespace = `${namespace}:${version}`; + this.editorService + .loadModels() + .pipe( + first(), + tap(models => (this.namespacesDependencies = this.getNamespacesDependencies(models))) + ) + .subscribe(); + } + + toggleNamespace(event: MatCheckboxChange, namespace: string): void { + this.selectDependencies(namespace, event.checked); + this.visitedNamespaces = []; + } + + validate(): void { + const namespaces = Array.from(new Set(this.selectedNamespaces)); + const validatePayload = namespaces.map(namespace => ({namespace, files: this.namespacesDependencies[namespace].files})); + this.namespacesManager.validateExport(validatePayload).subscribe(); + this.router.navigate([{outlets: {'export-namespaces': 'validate'}}]); + } + + private getNamespacesDependencies(models: RdfModel[]): NamespacesDependencies { + return models.reduce((acc, rdfModel) => { + const versionedNamespace = RdfModelUtil.getNamespaceFromRdf(rdfModel.absoluteAspectModelFileName); + const fileName = RdfModelUtil.getFileNameFromRdf(rdfModel.absoluteAspectModelFileName); let nDependency = acc[versionedNamespace]; if (!nDependency) { @@ -61,26 +99,12 @@ export class SelectNamespacesComponent implements OnInit { nDependency.dependencies = Array.from( new Set([...nDependency.dependencies, ...this.getDependentNamespaces(rdfModel.getNamespaces())]) ); - nDependency.files = Array.from(new Set([...nDependency.files, file])); + nDependency.files = Array.from(new Set([...nDependency.files, fileName])); return acc; }, {}); } - toggleNamespace(event: MatCheckboxChange, namespace: string) { - this.selectDependencies(namespace, event.checked); - this.visitedNamespaces = []; - } - - validate() { - const namespaces = Array.from(new Set(this.selectedNamespaces)); - const validatePayload = namespaces.map(namespace => ({namespace, files: this.namespacesDependencies[namespace].files})); - this.namespacesManager.validateExport(validatePayload).subscribe(); - this.router.navigate([{outlets: {'export-namespaces': 'validate'}}]); - } - - hasChild = (_: number, node: FlatNode) => node.expandable; - - private getDependentNamespaces(prefixes: Prefixes) { + private getDependentNamespaces(prefixes: Prefixes): string[] { return Object.entries(prefixes).reduce((acc, [key, value]) => { if (!nonDependentNamespaces.includes(value) && key !== '') { acc.push(value.replace('urn:samm:', '').replace('#', '')); @@ -90,7 +114,7 @@ export class SelectNamespacesComponent implements OnInit { }, []); } - private selectDependencies(namespace: string, checked: boolean, level = 0) { + private selectDependencies(namespace: string, checked: boolean, level = 0): void { const nDependency = this.namespacesDependencies[namespace]; nDependency.checked = checked; nDependency.disabled = level > 0 && checked; diff --git a/core/libs/rdf/src/lib/services/rdf.service.ts b/core/libs/rdf/src/lib/services/rdf.service.ts index 3254733e..8f77e500 100644 --- a/core/libs/rdf/src/lib/services/rdf.service.ts +++ b/core/libs/rdf/src/lib/services/rdf.service.ts @@ -11,7 +11,7 @@ * SPDX-License-Identifier: MPL-2.0 */ import {DataFactory, Parser, Quad, Store, Util, Writer} from 'n3'; -import {map, Observable, of, Subject, switchMap, throwError} from 'rxjs'; +import {forkJoin, map, Observable, of, Subject, switchMap, throwError} from 'rxjs'; import {Inject, Injectable} from '@angular/core'; import {environment} from 'environments/environment'; import {ModelApiService} from '@ame/api'; @@ -153,10 +153,6 @@ export class RdfService { ); } - loadModelLatest(): Observable { - return this.modelApiService.loadLatest().pipe(switchMap(rdf => this.loadModel(rdf))); - } - loadModel(rdf: string, namespaceFileName?: string): Observable { const subject = new Subject(); const store: Store = new Store(); @@ -232,6 +228,40 @@ export class RdfService { return subject; } + parseModels(fileContentModels: FileContentModel[]): Observable { + return forkJoin(fileContentModels.map(fileContent => this.parseModel(fileContent))); + } + + parseModel(fileContent: FileContentModel): Observable { + const subject = new Subject(); + const store: Store = new Store(); + const parser = new Parser(); + + parser.parse(fileContent.aspectMetaModel, (error, quad, prefixes) => { + let rdfModel: RdfModel; + + if (quad) { + store.addQuad(quad); + } else if (prefixes) { + rdfModel = new RdfModel(store, this.dataTypeService, prefixes); + } + + if (error) { + rdfModel = new RdfModel(store, this.dataTypeService, {}); + rdfModel.hasErrors = true; + this.logService.logInfo(`Error when parsing RDF ${error}`); + } + + if (prefixes || error) { + rdfModel.aspectModelFileName = fileContent.fileName; + subject.next(rdfModel); + subject.complete(); + } + }); + + return subject.asObservable(); + } + isSameModelContent(absoluteFileName: string, fileContent: string, modelToCompare: RdfModel): Observable { if (modelToCompare.absoluteAspectModelFileName !== absoluteFileName) return of(false); diff --git a/core/libs/shared/src/index.ts b/core/libs/shared/src/index.ts index 64376305..5154b336 100644 --- a/core/libs/shared/src/index.ts +++ b/core/libs/shared/src/index.ts @@ -30,3 +30,4 @@ export * from './lib/alert.service'; export * from './lib/config'; export * from './lib/electron-tunnel.service'; export * from './lib/sidebar.service'; +export * from './lib/pipes'; diff --git a/core/libs/shared/src/lib/components/loading-screen/loading-screen.component.html b/core/libs/shared/src/lib/components/loading-screen/loading-screen.component.html index 92fc6569..df0e050d 100644 --- a/core/libs/shared/src/lib/components/loading-screen/loading-screen.component.html +++ b/core/libs/shared/src/lib/components/loading-screen/loading-screen.component.html @@ -18,6 +18,6 @@

{{ data.title }}

{{ data.content || 'Please wait...' }}

- - + + diff --git a/core/libs/shared/src/lib/constants/elements-relations.ts b/core/libs/shared/src/lib/constants/elements-relations.ts index e03b5f28..b164e6ae 100644 --- a/core/libs/shared/src/lib/constants/elements-relations.ts +++ b/core/libs/shared/src/lib/constants/elements-relations.ts @@ -11,24 +11,6 @@ * SPDX-License-Identifier: MPL-2.0 */ -import { - DefaultAbstractEntity, - DefaultAbstractProperty, - DefaultAspect, - DefaultCharacteristic, - DefaultCollection, - DefaultConstraint, - DefaultEither, - DefaultEntity, - DefaultEntityValue, - DefaultEvent, - DefaultOperation, - DefaultProperty, - DefaultStructuredValue, - DefaultTrait, - DefaultUnit, -} from '@ame/meta-model'; - export enum Elements { aspect = 'aspect', property = 'property', @@ -62,62 +44,3 @@ export const cellRelations = { [Elements.filteredProperties_entity]: [Elements.property], [Elements.filteredProperties_either]: [Elements.property], }; - -export const modelRelations = [ - { - from: DefaultAspect, - to: [DefaultProperty, DefaultOperation, DefaultEvent], - }, - { - from: DefaultProperty, - to: [DefaultCharacteristic, DefaultTrait, DefaultAbstractProperty, DefaultProperty], - }, - { - from: DefaultAbstractProperty, - to: [DefaultAbstractProperty], - }, - { - from: DefaultTrait, - to: [DefaultConstraint, DefaultCharacteristic], - }, - { - from: DefaultCollection, - to: [DefaultCharacteristic], - }, - { - from: DefaultStructuredValue, - to: [DefaultProperty], - }, - { - from: DefaultEither, - to: [DefaultCharacteristic], - }, - { - from: DefaultCharacteristic, - to: [DefaultEntity, DefaultEntityValue, DefaultUnit], - }, - { - from: DefaultEntity, - to: [DefaultProperty, DefaultEntity, DefaultAbstractEntity], - }, - { - from: DefaultEntityValue, - to: [DefaultEntityValue, DefaultEntity], - }, - { - from: DefaultEvent, - to: [DefaultProperty], - }, - { - from: DefaultOperation, - to: [DefaultProperty], - }, - { - from: DefaultUnit, - to: [DefaultUnit], - }, - { - from: DefaultAbstractEntity, - to: [DefaultAbstractEntity, DefaultProperty, DefaultAbstractProperty], - }, -]; diff --git a/core/libs/shared/src/lib/pipes/counter.pipe.spec.ts b/core/libs/shared/src/lib/pipes/counter.pipe.spec.ts new file mode 100644 index 00000000..4ae00de6 --- /dev/null +++ b/core/libs/shared/src/lib/pipes/counter.pipe.spec.ts @@ -0,0 +1,42 @@ +import {CounterPipe} from './counter.pipe'; + +const falsyValues = [null, '', undefined, 0, NaN]; + +describe('CounterPipe', () => { + let pipe: CounterPipe; + + beforeEach(() => (pipe = new CounterPipe())); + + it('should create an instance', () => { + expect(pipe).toBeTruthy(); + }); + + it('should attach a counter to the value', () => { + const value = 'VALUE'; + const counter = 1; + const expectation = 'VALUE (1)'; + + const result = pipe.transform(value, counter); + + expect(result).toEqual(expectation); + }); + + it('should attach "0" for falsy counter values', () => { + const value = 'VALUE'; + const expectation = 'VALUE (0)'; + + falsyValues.forEach(falsyValue => { + const result = pipe.transform(value, falsyValue); + expect(result).toEqual(expectation); + }); + }); + + it('should return falsy values "as is", without a counter', () => { + const counter = 1; + + falsyValues.forEach(falsyValue => { + const result = pipe.transform(falsyValue as any, counter); + expect(result).toEqual(falsyValue); + }); + }); +}); diff --git a/core/libs/shared/src/lib/pipes/counter.pipe.ts b/core/libs/shared/src/lib/pipes/counter.pipe.ts new file mode 100644 index 00000000..ac3b515d --- /dev/null +++ b/core/libs/shared/src/lib/pipes/counter.pipe.ts @@ -0,0 +1,14 @@ +import {Pipe, PipeTransform} from '@angular/core'; + +/** + * The pipe is intended for displaying an element's counter next to its original value + */ +@Pipe({ + name: 'counter', + standalone: true, +}) +export class CounterPipe implements PipeTransform { + transform(value: string, counter: number | string): string { + return !value ? value : `${value} (${counter || 0})`; + } +} diff --git a/core/libs/shared/src/lib/pipes/index.ts b/core/libs/shared/src/lib/pipes/index.ts new file mode 100644 index 00000000..59cf1c4e --- /dev/null +++ b/core/libs/shared/src/lib/pipes/index.ts @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2023 Robert Bosch Manufacturing Solutions GmbH + * + * See the AUTHORS file(s) distributed with this work for + * additional information regarding authorship. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * SPDX-License-Identifier: MPL-2.0 + */ + +export * from './counter.pipe'; diff --git a/core/package-lock.json b/core/package-lock.json index 944caf52..1facaf36 100644 --- a/core/package-lock.json +++ b/core/package-lock.json @@ -122,9 +122,9 @@ } }, "node_modules/@adobe/css-tools": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.1.tgz", - "integrity": "sha512-/62yikz7NLScCGAAST5SHdnjaDJQBDq0M2muyRTpf2VQhw6StBg2ALiu73zSJQ4fMVLA+0uBhBHAle7Wg+2kSg==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.0.tgz", + "integrity": "sha512-+RNNcQvw2V1bmnBTPAtOLfW/9mhH2vC67+rUSi5T8EtEWt6lEnGNY2GuhZ1/YwbgikT1TkhvidCDmN5Q5YCo/w==", "dev": true }, "node_modules/@aduh95/viz.js": { @@ -170,12 +170,12 @@ } }, "node_modules/@angular-devkit/architect": { - "version": "0.1602.0", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1602.0.tgz", - "integrity": "sha512-ZRmUTBeD+uGr605eOHnsovEn6f1mOBI+kxP64DRvagNweX5TN04s3iyQ8jmLSAHQD9ush31LFxv3dVNxv3ceXQ==", + "version": "0.1601.8", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1601.8.tgz", + "integrity": "sha512-kOXVGwsQnZvtz2UZNefcEy64Jiwq0eSoQUeozvDXOaYRJABLjPKI2YaarvKC9/Z1SGLuje0o/eRJO4T8aRk9rQ==", "dev": true, "dependencies": { - "@angular-devkit/core": "16.2.0", + "@angular-devkit/core": "16.1.8", "rxjs": "7.8.1" }, "engines": { @@ -707,9 +707,9 @@ } }, "node_modules/@angular-devkit/core": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.2.0.tgz", - "integrity": "sha512-l1k6Rqm3YM16BEn3CWyQKrk9xfu+2ux7Bw3oS+h1TO4/RoxO2PgHj8LLRh/WNrYVarhaqO7QZ5ePBkXNMkzJ1g==", + "version": "16.1.8", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.1.8.tgz", + "integrity": "sha512-dSRD/+bGanArIXkj+kaU1kDFleZeQMzmBiOXX+pK0Ah9/0Yn1VmY3RZh1zcX9vgIQXV+t7UPrTpOjaERMUtVGw==", "dev": true, "dependencies": { "ajv": "8.12.0", @@ -750,32 +750,6 @@ "yarn": ">= 1.13.0" } }, - "node_modules/@angular-devkit/schematics/node_modules/@angular-devkit/core": { - "version": "16.1.8", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.1.8.tgz", - "integrity": "sha512-dSRD/+bGanArIXkj+kaU1kDFleZeQMzmBiOXX+pK0Ah9/0Yn1VmY3RZh1zcX9vgIQXV+t7UPrTpOjaERMUtVGw==", - "dev": true, - "dependencies": { - "ajv": "8.12.0", - "ajv-formats": "2.1.1", - "jsonc-parser": "3.2.0", - "rxjs": "7.8.1", - "source-map": "0.7.4" - }, - "engines": { - "node": "^16.14.0 || >=18.10.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - }, - "peerDependencies": { - "chokidar": "^3.5.2" - }, - "peerDependenciesMeta": { - "chokidar": { - "optional": true - } - } - }, "node_modules/@angular-eslint/builder": { "version": "16.1.0", "resolved": "https://registry.npmjs.org/@angular-eslint/builder/-/builder-16.1.0.tgz", @@ -1148,47 +1122,6 @@ "yarn": ">= 1.13.0" } }, - "node_modules/@angular/cli/node_modules/@angular-devkit/architect": { - "version": "0.1601.8", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1601.8.tgz", - "integrity": "sha512-kOXVGwsQnZvtz2UZNefcEy64Jiwq0eSoQUeozvDXOaYRJABLjPKI2YaarvKC9/Z1SGLuje0o/eRJO4T8aRk9rQ==", - "dev": true, - "dependencies": { - "@angular-devkit/core": "16.1.8", - "rxjs": "7.8.1" - }, - "engines": { - "node": "^16.14.0 || >=18.10.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - } - }, - "node_modules/@angular/cli/node_modules/@angular-devkit/core": { - "version": "16.1.8", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.1.8.tgz", - "integrity": "sha512-dSRD/+bGanArIXkj+kaU1kDFleZeQMzmBiOXX+pK0Ah9/0Yn1VmY3RZh1zcX9vgIQXV+t7UPrTpOjaERMUtVGw==", - "dev": true, - "dependencies": { - "ajv": "8.12.0", - "ajv-formats": "2.1.1", - "jsonc-parser": "3.2.0", - "rxjs": "7.8.1", - "source-map": "0.7.4" - }, - "engines": { - "node": "^16.14.0 || >=18.10.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - }, - "peerDependencies": { - "chokidar": "^3.5.2" - }, - "peerDependenciesMeta": { - "chokidar": { - "optional": true - } - } - }, "node_modules/@angular/common": { "version": "16.1.4", "resolved": "https://registry.npmjs.org/@angular/common/-/common-16.1.4.tgz", @@ -4549,9 +4482,9 @@ "dev": true }, "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.21.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", - "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -8171,9 +8104,9 @@ } }, "node_modules/@rollup/plugin-node-resolve": { - "version": "15.2.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.2.0.tgz", - "integrity": "sha512-mKur03xNGT8O9ODO6FtT43ITGqHWZbKPdVJHZb+iV9QYcdlhUUB0wgknvA4KCUmC5oHJF6O2W1EgmyOQyVUI4Q==", + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.1.0.tgz", + "integrity": "sha512-xeZHCgsiZ9pzYVgAo9580eCGqwh/XCEUM9q6iQfGNocjgkufHAqC3exA+45URvhiYV8sBF9RlBai650eNs7AsA==", "dev": true, "dependencies": { "@rollup/pluginutils": "^5.0.1", @@ -8196,9 +8129,9 @@ } }, "node_modules/@rollup/pluginutils": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.3.tgz", - "integrity": "sha512-hfllNN4a80rwNQ9QCxhxuHCGHMAvabXqxNdaChUSSadMre7t4iEUI6fFAhBOn/eIYTgYVhBv7vCLsAJ4u3lf3g==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.2.tgz", + "integrity": "sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==", "dev": true, "dependencies": { "@types/estree": "^1.0.0", @@ -8233,36 +8166,10 @@ "yarn": ">= 1.13.0" } }, - "node_modules/@schematics/angular/node_modules/@angular-devkit/core": { - "version": "16.1.8", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.1.8.tgz", - "integrity": "sha512-dSRD/+bGanArIXkj+kaU1kDFleZeQMzmBiOXX+pK0Ah9/0Yn1VmY3RZh1zcX9vgIQXV+t7UPrTpOjaERMUtVGw==", - "dev": true, - "dependencies": { - "ajv": "8.12.0", - "ajv-formats": "2.1.1", - "jsonc-parser": "3.2.0", - "rxjs": "7.8.1", - "source-map": "0.7.4" - }, - "engines": { - "node": "^16.14.0 || >=18.10.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - }, - "peerDependencies": { - "chokidar": "^3.5.2" - }, - "peerDependenciesMeta": { - "chokidar": { - "optional": true - } - } - }, "node_modules/@sigstore/bundle": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-1.1.0.tgz", - "integrity": "sha512-PFutXEy0SmQxYI4texPw3dd2KewuNqv7OuK1ZFtY2fM754yhvG2KdgwIhRnoEE2uHdtdGNQ8s0lb94dW9sELog==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-1.0.0.tgz", + "integrity": "sha512-yLvrWDOh6uMOUlFCTJIZEnwOT9Xte7NPXUqVexEKGSF5XtBAuSg5du0kn3dRR0p47a4ah10Y0mNt8+uyeQXrBQ==", "dev": true, "dependencies": { "@sigstore/protobuf-specs": "^0.2.0" @@ -8272,24 +8179,10 @@ } }, "node_modules/@sigstore/protobuf-specs": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.2.1.tgz", - "integrity": "sha512-XTWVxnWJu+c1oCshMLwnKvz8ZQJJDVOlciMfgpJBQbThVjKTCG8dwyhgLngBD2KN0ap9F/gOV8rFDEx8uh7R2A==", - "dev": true, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/@sigstore/sign": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-1.0.0.tgz", - "integrity": "sha512-INxFVNQteLtcfGmcoldzV6Je0sbbfh9I16DM4yJPw3j5+TFP8X6uIiA18mvpEa9yyeycAKgPmOA3X9hVdVTPUA==", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.2.0.tgz", + "integrity": "sha512-8ZhZKAVfXjIspDWwm3D3Kvj0ddbJ0HqDZ/pOs5cx88HpT8mVsotFrg7H1UMnXOuDHz6Zykwxn4mxG3QLuN+RUg==", "dev": true, - "dependencies": { - "@sigstore/bundle": "^1.1.0", - "@sigstore/protobuf-specs": "^0.2.0", - "make-fetch-happen": "^11.0.1" - }, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } @@ -8809,9 +8702,9 @@ } }, "node_modules/@types/node": { - "version": "16.18.41", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.41.tgz", - "integrity": "sha512-YZJjn+Aaw0xihnpdImxI22jqGbp0DCgTFKRycygjGx/Y27NnWFJa5FJ7P+MRT3u07dogEeMVh70pWpbIQollTA==" + "version": "16.18.40", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.40.tgz", + "integrity": "sha512-+yno3ItTEwGxXiS/75Q/aHaa5srkpnJaH+kdkTVJ3DtJEwv92itpKbxU+FjPoh2m/5G9zmUQfrL4A4C13c+iGA==" }, "node_modules/@types/normalize-package-data": { "version": "2.4.1", @@ -12170,9 +12063,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001521", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001521.tgz", - "integrity": "sha512-fnx1grfpEOvDGH+V17eccmNjucGUnCbP6KL+l5KqBIerp26WK/+RQ7CIDE37KGJjaPyqWXXlFUyKiWmvdNNKmQ==", + "version": "1.0.30001519", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001519.tgz", + "integrity": "sha512-0QHgqR+Jv4bxHMp8kZ1Kn8CH55OikjKJ6JmKkZYP1F3D7w+lnFXF70nG5eNfsZS89jadi5Ywy5UCSKLAglIRkg==", "dev": true, "funding": [ { @@ -13157,7 +13050,6 @@ "version": "0.0.19", "resolved": "https://registry.npmjs.org/critters/-/critters-0.0.19.tgz", "integrity": "sha512-Fm4ZAXsG0VzWy1U30rP4qxbaWGSsqXDgSupJW1OUJGDAs0KWC+j37v7p5a2kZ9BPJvhRzWm3be+Hc9WvQOBUOw==", - "deprecated": "Please upgrade to the latest version. There is a potential XSS vulnerability in this version", "dev": true, "dependencies": { "chalk": "^4.1.0", @@ -13610,13 +13502,13 @@ "dev": true }, "node_modules/cypress": { - "version": "12.17.4", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-12.17.4.tgz", - "integrity": "sha512-gAN8Pmns9MA5eCDFSDJXWKUpaL3IDd89N9TtIupjYnzLSmlpVr+ZR+vb4U/qaMp+lB6tBvAmt7504c3Z4RU5KQ==", + "version": "12.17.3", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-12.17.3.tgz", + "integrity": "sha512-/R4+xdIDjUSLYkiQfwJd630S81KIgicmQOLXotFxVXkl+eTeVO+3bHXxdi5KBh/OgC33HWN33kHX+0tQR/ZWpg==", "dev": true, "hasInstallScript": true, "dependencies": { - "@cypress/request": "2.88.12", + "@cypress/request": "^2.88.11", "@cypress/xvfb": "^1.2.4", "@types/node": "^16.18.39", "@types/sinonjs__fake-timers": "8.1.1", @@ -13651,7 +13543,6 @@ "minimist": "^1.2.8", "ospath": "^1.2.2", "pretty-bytes": "^5.6.0", - "process": "^0.11.10", "proxy-from-env": "1.0.0", "request-progress": "^3.0.0", "semver": "^7.5.3", @@ -14935,9 +14826,9 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/electron-to-chromium": { - "version": "1.4.495", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.495.tgz", - "integrity": "sha512-mwknuemBZnoOCths4GtpU/SDuVMp3uQHKa2UNJT9/aVD6WVRjGpXOxRGX7lm6ILIenTdGXPSTCTDaWos5tEU8Q==", + "version": "1.4.488", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.488.tgz", + "integrity": "sha512-Dv4sTjiW7t/UWGL+H8ZkgIjtUAVZDgb/PwGWvMsCT7jipzUV/u5skbLXPFKb6iV0tiddVi/bcS2/kUrczeWgIQ==", "dev": true }, "node_modules/emittery": { @@ -15836,9 +15727,9 @@ } }, "node_modules/eslint-plugin-cypress/node_modules/globals": { - "version": "13.21.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", - "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -16068,9 +15959,9 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.2.tgz", + "integrity": "sha512-8drBzUEyZ2llkpCA67iYrgEssKDUu68V8ChqqOfFupIaG/LCVPUT+CoGJpT77zJprs4T/W7p07LP7zAIMuweVw==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -16191,9 +16082,9 @@ } }, "node_modules/eslint/node_modules/globals": { - "version": "13.21.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", - "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -17507,26 +17398,17 @@ } }, "node_modules/fs-minipass": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", - "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.2.tgz", + "integrity": "sha512-2GAfyfoaCDRrM6jaOS3UsBts8yJ55VioXdWcOL7dK9zdAuKT71+WBA4ifnNYqVjYv+4SsPxjK0JT4yIIn4cA/g==", "dev": true, "dependencies": { - "minipass": "^7.0.3" + "minipass": "^5.0.0" }, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/fs-minipass/node_modules/minipass": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.3.tgz", - "integrity": "sha512-LhbbwCfz3vsb12j/WkWQPZfKTsgqIe1Nf/ti1pKjYESGLHIVjWU96G9/ljLH4F9mWNVhlQOm0VySdAWzf05dpg==", - "dev": true, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, "node_modules/fs-monkey": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.4.tgz", @@ -19869,9 +19751,9 @@ } }, "node_modules/jackspeak": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.0.tgz", - "integrity": "sha512-uKmsITSsF4rUWQHzqaRUuyAir3fZfW3f202Ee34lz/gZCi970CPZwyQXLGNgWJvvZbvFyzeyGq0+4fcG/mBKZg==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.2.2.tgz", + "integrity": "sha512-mgNtVv4vUuaKA97yxUHoA3+FkuhtxkjdXEWOyB/N76fjy0FjezEt34oy3epBtvCvS+7DyKwqCFWx/oJLV5+kCg==", "dev": true, "dependencies": { "@isaacs/cliui": "^8.0.2" @@ -21771,9 +21653,9 @@ } }, "node_modules/jiti": { - "version": "1.19.3", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.19.3.tgz", - "integrity": "sha512-5eEbBDQT/jF1xg6l36P+mWGGoH9Spuy0PCdSr2dtWRDGC6ph/w9ZCL4lmESW8f8F7MwT3XKescfP0wnZWAKL9w==", + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.19.1.tgz", + "integrity": "sha512-oVhqoRDaBXf7sjkll95LHVS6Myyyb1zaunVwk4Z0+WPSW4gjS0pl01zYKHScTuyEhQsFxV5L4DR5r+YqSyqyyg==", "dev": true, "bin": { "jiti": "bin/jiti.js" @@ -23324,12 +23206,12 @@ "dev": true }, "node_modules/minipass-fetch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", - "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.3.tgz", + "integrity": "sha512-n5ITsTkDqYkYJZjcRWzZt9qnZKCT7nKCosJhHoj7S7zD+BP4jVbWs+odsniw5TA3E0sLomhTKOKjF86wf11PuQ==", "dev": true, "dependencies": { - "minipass": "^7.0.3", + "minipass": "^5.0.0", "minipass-sized": "^1.0.3", "minizlib": "^2.1.2" }, @@ -23340,15 +23222,6 @@ "encoding": "^0.1.13" } }, - "node_modules/minipass-fetch/node_modules/minipass": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.3.tgz", - "integrity": "sha512-LhbbwCfz3vsb12j/WkWQPZfKTsgqIe1Nf/ti1pKjYESGLHIVjWU96G9/ljLH4F9mWNVhlQOm0VySdAWzf05dpg==", - "dev": true, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, "node_modules/minipass-flush": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", @@ -27465,9 +27338,9 @@ } }, "node_modules/npm-install-checks": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-6.2.0.tgz", - "integrity": "sha512-744wat5wAAHsxa4590mWO0tJ8PKxR8ORZsH9wGpQc3nWTzozMAgBN/XyqYw7mg3yqLM8dLwEnwSfKMmXAjF69g==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-6.1.1.tgz", + "integrity": "sha512-dH3GmQL4vsPtld59cOn8uY0iOqRmqKvV+DLGwNXV/Q7MDgD2QfOADWd/mFXcIE5LVhYYGjA3baz6W9JneqnuCw==", "dev": true, "dependencies": { "semver": "^7.1.1" @@ -28976,9 +28849,9 @@ } }, "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.1.tgz", - "integrity": "sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.0.tgz", + "integrity": "sha512-svTf/fzsKHffP42sujkO/Rjs37BCIsQVRCeNYIm9WN8rgT7ffoUnRtZCqU+6BqcSBdv8gwJeTz8knJpgACeQMw==", "dev": true, "engines": { "node": "14 || >=16.14" @@ -30332,15 +30205,6 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", - "dev": true, - "engines": { - "node": ">= 0.6.0" - } - }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -32195,14 +32059,13 @@ "dev": true }, "node_modules/sigstore": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-1.9.0.tgz", - "integrity": "sha512-0Zjz0oe37d08VeOtBIuB6cRriqXse2e8w+7yIy2XSXjshRKxbc2KkhXjL229jXSxEm7UbcjS76wcJDGQddVI9A==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-1.8.0.tgz", + "integrity": "sha512-ogU8qtQ3VFBawRJ8wjsBEX/vIFeHuGs1fm4jZtjWQwjo8pfAt7T/rh+udlAN4+QUe0IzA8qRSc/YZ7dHP6kh+w==", "dev": true, "dependencies": { - "@sigstore/bundle": "^1.1.0", + "@sigstore/bundle": "^1.0.0", "@sigstore/protobuf-specs": "^0.2.0", - "@sigstore/sign": "^1.0.0", "@sigstore/tuf": "^1.0.3", "make-fetch-happen": "^11.0.1" }, @@ -32802,26 +32665,17 @@ } }, "node_modules/ssri": { - "version": "10.0.5", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.5.tgz", - "integrity": "sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==", + "version": "10.0.4", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.4.tgz", + "integrity": "sha512-12+IR2CB2C28MMAw0Ncqwj5QbTcs0nGIhgJzYWzDkb21vWmfNI83KS4f3Ci6GI98WreIfG7o9UXp3C0qbpA8nQ==", "dev": true, "dependencies": { - "minipass": "^7.0.3" + "minipass": "^5.0.0" }, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/ssri/node_modules/minipass": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.3.tgz", - "integrity": "sha512-LhbbwCfz3vsb12j/WkWQPZfKTsgqIe1Nf/ti1pKjYESGLHIVjWU96G9/ljLH4F9mWNVhlQOm0VySdAWzf05dpg==", - "dev": true, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, "node_modules/stack-utils": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz",