diff --git a/.idea/runConfigurations/_template__of_mocha_javascript_test_runner.xml b/.idea/runConfigurations/_template__of_mocha_javascript_test_runner.xml index 56e8ffd..2295145 100644 --- a/.idea/runConfigurations/_template__of_mocha_javascript_test_runner.xml +++ b/.idea/runConfigurations/_template__of_mocha_javascript_test_runner.xml @@ -2,6 +2,7 @@ project + $PROJECT_DIR$/node_modules/electron-mocha true bdd diff --git a/package-lock.json b/package-lock.json index aaf4f7b..dbfb087 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,6 +31,7 @@ "css-loader": "^6.7.3", "electron": "^24.1.2", "electron-builder": "^24.2.1", + "electron-mocha": "^12.0.0", "eslint": "^8.39.0", "eslint-plugin-tsdoc": "^0.2.17", "execa": "^7.1.1", @@ -55,6 +56,7 @@ "webpack": "^5.80.0", "webpack-cli": "^5.0.1", "webpack-dev-server": "^4.13.3", + "xvfb-maybe": "^0.2.1", "yauzl": "^2.10.0", "zx": "^7.2.1" } @@ -133,12 +135,12 @@ } }, "node_modules/@babel/generator": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.4.tgz", - "integrity": "sha512-NieM3pVIYW2SwGzKoqfPrQsf4xGs9M9AIG3ThppsSRmO+m7eQhmI6amajKMUeIO37wFfsvnvcxQFx6x6iqxDnA==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.5.tgz", + "integrity": "sha512-SrKK/sRv8GesIW1bDagf9cCG38IOMYZusoe1dfg0D8aiUe3Amvoj1QtjTPAWcfrZFvIwlleLb0gxzQidL9w14w==", "dev": true, "dependencies": { - "@babel/types": "^7.21.4", + "@babel/types": "^7.21.5", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -191,9 +193,9 @@ "dev": true }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.21.5.tgz", + "integrity": "sha512-IYl4gZ3ETsWocUWgsFZLM5i1BYx9SoemminVEXadgLBa9TdeorzgLKm8wWLA6J1N/kT3Kch8XIk1laNzYoHKvQ==", "dev": true, "engines": { "node": ">=6.9.0" @@ -280,9 +282,9 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", - "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.21.5.tgz", + "integrity": "sha512-5pTUx3hAJaZIdW99sJ6ZUUgWq/Y+Hja7TowEnLNMm1VivRgZQL3vpBY3qUACVsvw+yQU6+YgfBVmcbLaZtrA1w==", "dev": true, "engines": { "node": ">=6.9.0" @@ -358,9 +360,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.4.tgz", - "integrity": "sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw==", + "version": "7.21.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.8.tgz", + "integrity": "sha512-6zavDGdzG3gUqAdWvlLFfk+36RilI+Pwyuuh7HItyeScCWP3k6i8vKclAQ0bM/0y/Kz/xiwvxhMv9MgTJP5gmA==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -384,19 +386,19 @@ } }, "node_modules/@babel/traverse": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.4.tgz", - "integrity": "sha512-eyKrRHKdyZxqDm+fV1iqL9UAHMoIg0nDaGqfIOd8rKH17m5snv7Gn4qgjBoFfLz9APvjFU/ICT00NVCv1Epp8Q==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.5.tgz", + "integrity": "sha512-AhQoI3YjWi6u/y/ntv7k48mcrCXmus0t79J9qPNlk/lAsFlCiJ047RmbfMOawySTHtywXhbXgpx/8nXMYd+oFw==", "dev": true, "dependencies": { "@babel/code-frame": "^7.21.4", - "@babel/generator": "^7.21.4", - "@babel/helper-environment-visitor": "^7.18.9", + "@babel/generator": "^7.21.5", + "@babel/helper-environment-visitor": "^7.21.5", "@babel/helper-function-name": "^7.21.0", "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.21.4", - "@babel/types": "^7.21.4", + "@babel/parser": "^7.21.5", + "@babel/types": "^7.21.5", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -405,12 +407,12 @@ } }, "node_modules/@babel/types": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.4.tgz", - "integrity": "sha512-rU2oY501qDxE8Pyo7i/Orqma4ziCOrby0/9mvbDUGEfvZjb279Nk9k19e2fiCxHbRRpY2ZyrgW1eq22mvmOIzA==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.5.tgz", + "integrity": "sha512-m4AfNvVF2mVC/F7fDEdH2El3HzUg9It/XsCxZiOTTA3m3qYfcSVSbTfM6Q9xG+hYDniZssYhlXKKUMD5m8tF4Q==", "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.19.4", + "@babel/helper-string-parser": "^7.21.5", "@babel/helper-validator-identifier": "^7.19.1", "to-fast-properties": "^2.0.0" }, @@ -1509,6 +1511,212 @@ "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==", "dev": true }, + "node_modules/@swc/core": { + "version": "1.3.56", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.3.56.tgz", + "integrity": "sha512-yz/EeXT+PMZucUNrYceRUaTfuNS4IIu5EDZSOlvCEvm4jAmZi7CYH1B/kvzEzoAOzr7zkQiDPNJftcQXLkjbjA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/swc" + }, + "optionalDependencies": { + "@swc/core-darwin-arm64": "1.3.56", + "@swc/core-darwin-x64": "1.3.56", + "@swc/core-linux-arm-gnueabihf": "1.3.56", + "@swc/core-linux-arm64-gnu": "1.3.56", + "@swc/core-linux-arm64-musl": "1.3.56", + "@swc/core-linux-x64-gnu": "1.3.56", + "@swc/core-linux-x64-musl": "1.3.56", + "@swc/core-win32-arm64-msvc": "1.3.56", + "@swc/core-win32-ia32-msvc": "1.3.56", + "@swc/core-win32-x64-msvc": "1.3.56" + }, + "peerDependencies": { + "@swc/helpers": "^0.5.0" + }, + "peerDependenciesMeta": { + "@swc/helpers": { + "optional": true + } + } + }, + "node_modules/@swc/core-darwin-arm64": { + "version": "1.3.56", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.56.tgz", + "integrity": "sha512-DZcu7BzDaLEdWHabz9DRTP0yEBLqkrWmskFcD5BX0lGAvoIvE4duMnAqi5F2B3X7630QioHRCYFoRw2WkeE3Cw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-darwin-x64": { + "version": "1.3.56", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.3.56.tgz", + "integrity": "sha512-VH5saqYFasdRXJy6RAT+MXm0+IjkMZvOkohJwUei+oA65cKJofQwrJ1jZro8yOJFYvUSI3jgNRGsdBkmo/4hMw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm-gnueabihf": { + "version": "1.3.56", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.56.tgz", + "integrity": "sha512-LWwPo6NnJkH01+ukqvkoNIOpMdw+Zundm4vBeicwyVrkP+mC3kwVfi03TUFpQUz3kRKdw/QEnxGTj+MouCPbtw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-gnu": { + "version": "1.3.56", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.56.tgz", + "integrity": "sha512-GzsUy/4egJ4cMlxbM+Ub7AMi5CKAc+pxBxrh8MUPQbyStW8jGgnQsJouTnGy0LHawtdEnsCOl6PcO6OgvktXuQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-musl": { + "version": "1.3.56", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.56.tgz", + "integrity": "sha512-9gxL09BIiAv8zY0DjfnFf19bo8+P4T9tdhzPwcm+1yPJcY5yr1+YFWLNFzz01agtOj6VlZ2/wUJTaOfdjjtc+A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-gnu": { + "version": "1.3.56", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.56.tgz", + "integrity": "sha512-n0ORNknl50vMRkll3BDO1E4WOqY6iISlPV1ZQCRLWQ6YQ2q8/WAryBxc2OAybcGHBUFkxyACpJukeU1QZ/9tNw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-musl": { + "version": "1.3.56", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.56.tgz", + "integrity": "sha512-r+D34WLAOAlJtfw1gaVWpHRwCncU9nzW9i7w9kSw4HpWYnHJOz54jLGSEmNsrhdTCz1VK2ar+V2ktFUsrlGlDA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-arm64-msvc": { + "version": "1.3.56", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.56.tgz", + "integrity": "sha512-29Yt75Is6X24z3x8h/xZC1HnDPkPpyLH9mDQiM6Cuc0I9mVr1XSriPEUB2N/awf5IE4SA8c+3IVq1DtKWbkJIw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-ia32-msvc": { + "version": "1.3.56", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.56.tgz", + "integrity": "sha512-mplp0zbYDrcHtfvkniXlXdB04e2qIjz2Gq/XHKr4Rnc6xVORJjjXF91IemXKpavx2oZYJws+LNJL7UFQ8jyCdQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-x64-msvc": { + "version": "1.3.56", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.56.tgz", + "integrity": "sha512-zp8MBnrw/bjdLenO/ifYzHrImSjKunqL0C2IF4LXYNRfcbYFh2NwobsVQMZ20IT0474lKRdlP8Oxdt+bHuXrzA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">=10" + } + }, "node_modules/@szmarczak/http-timer": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", @@ -4770,6 +4978,40 @@ "node": ">= 10.0.0" } }, + "node_modules/electron-mocha": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/electron-mocha/-/electron-mocha-12.0.0.tgz", + "integrity": "sha512-zJU0kWJnov0GMeTfh5KymBBBqCH4OxasIzWi1+oZ+vWFtIgmO5KIO1o9k2B05mJgxSQLP/Vr818yZGec8770Vw==", + "dev": true, + "dependencies": { + "ansi-colors": "^4.1.1", + "electron-window": "^0.8.0", + "mocha": "^10.2.0", + "which": "^3.0.0", + "yargs": "^17.7.1" + }, + "bin": { + "electron-mocha": "bin/electron-mocha" + }, + "engines": { + "node": ">= 16.0.0" + } + }, + "node_modules/electron-mocha/node_modules/which": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz", + "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/electron-publish": { "version": "24.1.2", "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-24.1.2.tgz", @@ -4907,6 +5149,15 @@ "integrity": "sha512-e2aeCAixCj9M7nJxdB/wDjO6mbYX+lJJxSJCXDzlr5YPGYVofuJwGN9nKg2o6wWInjX6XmxRinn3AeJMK81ltw==", "dev": true }, + "node_modules/electron-window": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/electron-window/-/electron-window-0.8.1.tgz", + "integrity": "sha512-W1i9LfnZJozk3MXE8VgsL2E5wOUHSgyCvcg1H2vQQjj+gqhO9lVudgY3z3SF7LJAmi+0vy3CJkbMqsynWB49EA==", + "dev": true, + "dependencies": { + "is-electron-renderer": "^2.0.0" + } + }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -7374,6 +7625,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-electron-renderer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-electron-renderer/-/is-electron-renderer-2.0.1.tgz", + "integrity": "sha512-pRlQnpaCFhDVPtkXkP+g9Ybv/CjbiQDjnKFQTEjpBfDKeV6dRDBczuFRDpM6DVfk2EjpMS8t5kwE5jPnqYl3zA==", + "dev": true + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -13377,6 +13634,46 @@ "node": ">=8.0" } }, + "node_modules/xvfb-maybe": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/xvfb-maybe/-/xvfb-maybe-0.2.1.tgz", + "integrity": "sha512-9IyRz3l6Qyhl6LvnGRF5jMPB4oBEepQnuzvVAFTynP6ACLLSevqigICJ9d/+ofl29m2daeaVBChnPYUnaeJ7yA==", + "dev": true, + "dependencies": { + "debug": "^2.2.0", + "which": "^1.2.4" + }, + "bin": { + "xvfb-maybe": "src/xvfb-maybe.js" + } + }, + "node_modules/xvfb-maybe/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/xvfb-maybe/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/xvfb-maybe/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -13646,12 +13943,12 @@ } }, "@babel/generator": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.4.tgz", - "integrity": "sha512-NieM3pVIYW2SwGzKoqfPrQsf4xGs9M9AIG3ThppsSRmO+m7eQhmI6amajKMUeIO37wFfsvnvcxQFx6x6iqxDnA==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.5.tgz", + "integrity": "sha512-SrKK/sRv8GesIW1bDagf9cCG38IOMYZusoe1dfg0D8aiUe3Amvoj1QtjTPAWcfrZFvIwlleLb0gxzQidL9w14w==", "dev": true, "requires": { - "@babel/types": "^7.21.4", + "@babel/types": "^7.21.5", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -13694,9 +13991,9 @@ } }, "@babel/helper-environment-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.21.5.tgz", + "integrity": "sha512-IYl4gZ3ETsWocUWgsFZLM5i1BYx9SoemminVEXadgLBa9TdeorzgLKm8wWLA6J1N/kT3Kch8XIk1laNzYoHKvQ==", "dev": true }, "@babel/helper-function-name": { @@ -13762,9 +14059,9 @@ } }, "@babel/helper-string-parser": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", - "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.21.5.tgz", + "integrity": "sha512-5pTUx3hAJaZIdW99sJ6ZUUgWq/Y+Hja7TowEnLNMm1VivRgZQL3vpBY3qUACVsvw+yQU6+YgfBVmcbLaZtrA1w==", "dev": true }, "@babel/helper-validator-identifier": { @@ -13821,9 +14118,9 @@ } }, "@babel/parser": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.4.tgz", - "integrity": "sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw==", + "version": "7.21.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.8.tgz", + "integrity": "sha512-6zavDGdzG3gUqAdWvlLFfk+36RilI+Pwyuuh7HItyeScCWP3k6i8vKclAQ0bM/0y/Kz/xiwvxhMv9MgTJP5gmA==", "dev": true }, "@babel/template": { @@ -13838,30 +14135,30 @@ } }, "@babel/traverse": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.4.tgz", - "integrity": "sha512-eyKrRHKdyZxqDm+fV1iqL9UAHMoIg0nDaGqfIOd8rKH17m5snv7Gn4qgjBoFfLz9APvjFU/ICT00NVCv1Epp8Q==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.5.tgz", + "integrity": "sha512-AhQoI3YjWi6u/y/ntv7k48mcrCXmus0t79J9qPNlk/lAsFlCiJ047RmbfMOawySTHtywXhbXgpx/8nXMYd+oFw==", "dev": true, "requires": { "@babel/code-frame": "^7.21.4", - "@babel/generator": "^7.21.4", - "@babel/helper-environment-visitor": "^7.18.9", + "@babel/generator": "^7.21.5", + "@babel/helper-environment-visitor": "^7.21.5", "@babel/helper-function-name": "^7.21.0", "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.21.4", - "@babel/types": "^7.21.4", + "@babel/parser": "^7.21.5", + "@babel/types": "^7.21.5", "debug": "^4.1.0", "globals": "^11.1.0" } }, "@babel/types": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.4.tgz", - "integrity": "sha512-rU2oY501qDxE8Pyo7i/Orqma4ziCOrby0/9mvbDUGEfvZjb279Nk9k19e2fiCxHbRRpY2ZyrgW1eq22mvmOIzA==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.5.tgz", + "integrity": "sha512-m4AfNvVF2mVC/F7fDEdH2El3HzUg9It/XsCxZiOTTA3m3qYfcSVSbTfM6Q9xG+hYDniZssYhlXKKUMD5m8tF4Q==", "dev": true, "requires": { - "@babel/helper-string-parser": "^7.19.4", + "@babel/helper-string-parser": "^7.21.5", "@babel/helper-validator-identifier": "^7.19.1", "to-fast-properties": "^2.0.0" } @@ -14719,6 +15016,106 @@ "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==", "dev": true }, + "@swc/core": { + "version": "1.3.56", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.3.56.tgz", + "integrity": "sha512-yz/EeXT+PMZucUNrYceRUaTfuNS4IIu5EDZSOlvCEvm4jAmZi7CYH1B/kvzEzoAOzr7zkQiDPNJftcQXLkjbjA==", + "dev": true, + "optional": true, + "peer": true, + "requires": { + "@swc/core-darwin-arm64": "1.3.56", + "@swc/core-darwin-x64": "1.3.56", + "@swc/core-linux-arm-gnueabihf": "1.3.56", + "@swc/core-linux-arm64-gnu": "1.3.56", + "@swc/core-linux-arm64-musl": "1.3.56", + "@swc/core-linux-x64-gnu": "1.3.56", + "@swc/core-linux-x64-musl": "1.3.56", + "@swc/core-win32-arm64-msvc": "1.3.56", + "@swc/core-win32-ia32-msvc": "1.3.56", + "@swc/core-win32-x64-msvc": "1.3.56" + } + }, + "@swc/core-darwin-arm64": { + "version": "1.3.56", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.56.tgz", + "integrity": "sha512-DZcu7BzDaLEdWHabz9DRTP0yEBLqkrWmskFcD5BX0lGAvoIvE4duMnAqi5F2B3X7630QioHRCYFoRw2WkeE3Cw==", + "dev": true, + "optional": true, + "peer": true + }, + "@swc/core-darwin-x64": { + "version": "1.3.56", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.3.56.tgz", + "integrity": "sha512-VH5saqYFasdRXJy6RAT+MXm0+IjkMZvOkohJwUei+oA65cKJofQwrJ1jZro8yOJFYvUSI3jgNRGsdBkmo/4hMw==", + "dev": true, + "optional": true, + "peer": true + }, + "@swc/core-linux-arm-gnueabihf": { + "version": "1.3.56", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.56.tgz", + "integrity": "sha512-LWwPo6NnJkH01+ukqvkoNIOpMdw+Zundm4vBeicwyVrkP+mC3kwVfi03TUFpQUz3kRKdw/QEnxGTj+MouCPbtw==", + "dev": true, + "optional": true, + "peer": true + }, + "@swc/core-linux-arm64-gnu": { + "version": "1.3.56", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.56.tgz", + "integrity": "sha512-GzsUy/4egJ4cMlxbM+Ub7AMi5CKAc+pxBxrh8MUPQbyStW8jGgnQsJouTnGy0LHawtdEnsCOl6PcO6OgvktXuQ==", + "dev": true, + "optional": true, + "peer": true + }, + "@swc/core-linux-arm64-musl": { + "version": "1.3.56", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.56.tgz", + "integrity": "sha512-9gxL09BIiAv8zY0DjfnFf19bo8+P4T9tdhzPwcm+1yPJcY5yr1+YFWLNFzz01agtOj6VlZ2/wUJTaOfdjjtc+A==", + "dev": true, + "optional": true, + "peer": true + }, + "@swc/core-linux-x64-gnu": { + "version": "1.3.56", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.56.tgz", + "integrity": "sha512-n0ORNknl50vMRkll3BDO1E4WOqY6iISlPV1ZQCRLWQ6YQ2q8/WAryBxc2OAybcGHBUFkxyACpJukeU1QZ/9tNw==", + "dev": true, + "optional": true, + "peer": true + }, + "@swc/core-linux-x64-musl": { + "version": "1.3.56", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.56.tgz", + "integrity": "sha512-r+D34WLAOAlJtfw1gaVWpHRwCncU9nzW9i7w9kSw4HpWYnHJOz54jLGSEmNsrhdTCz1VK2ar+V2ktFUsrlGlDA==", + "dev": true, + "optional": true, + "peer": true + }, + "@swc/core-win32-arm64-msvc": { + "version": "1.3.56", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.56.tgz", + "integrity": "sha512-29Yt75Is6X24z3x8h/xZC1HnDPkPpyLH9mDQiM6Cuc0I9mVr1XSriPEUB2N/awf5IE4SA8c+3IVq1DtKWbkJIw==", + "dev": true, + "optional": true, + "peer": true + }, + "@swc/core-win32-ia32-msvc": { + "version": "1.3.56", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.56.tgz", + "integrity": "sha512-mplp0zbYDrcHtfvkniXlXdB04e2qIjz2Gq/XHKr4Rnc6xVORJjjXF91IemXKpavx2oZYJws+LNJL7UFQ8jyCdQ==", + "dev": true, + "optional": true, + "peer": true + }, + "@swc/core-win32-x64-msvc": { + "version": "1.3.56", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.56.tgz", + "integrity": "sha512-zp8MBnrw/bjdLenO/ifYzHrImSjKunqL0C2IF4LXYNRfcbYFh2NwobsVQMZ20IT0474lKRdlP8Oxdt+bHuXrzA==", + "dev": true, + "optional": true, + "peer": true + }, "@szmarczak/http-timer": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", @@ -17218,6 +17615,30 @@ } } }, + "electron-mocha": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/electron-mocha/-/electron-mocha-12.0.0.tgz", + "integrity": "sha512-zJU0kWJnov0GMeTfh5KymBBBqCH4OxasIzWi1+oZ+vWFtIgmO5KIO1o9k2B05mJgxSQLP/Vr818yZGec8770Vw==", + "dev": true, + "requires": { + "ansi-colors": "^4.1.1", + "electron-window": "^0.8.0", + "mocha": "^10.2.0", + "which": "^3.0.0", + "yargs": "^17.7.1" + }, + "dependencies": { + "which": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz", + "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, "electron-publish": { "version": "24.1.2", "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-24.1.2.tgz", @@ -17325,6 +17746,15 @@ "integrity": "sha512-e2aeCAixCj9M7nJxdB/wDjO6mbYX+lJJxSJCXDzlr5YPGYVofuJwGN9nKg2o6wWInjX6XmxRinn3AeJMK81ltw==", "dev": true }, + "electron-window": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/electron-window/-/electron-window-0.8.1.tgz", + "integrity": "sha512-W1i9LfnZJozk3MXE8VgsL2E5wOUHSgyCvcg1H2vQQjj+gqhO9lVudgY3z3SF7LJAmi+0vy3CJkbMqsynWB49EA==", + "dev": true, + "requires": { + "is-electron-renderer": "^2.0.0" + } + }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -19149,6 +19579,12 @@ "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", "dev": true }, + "is-electron-renderer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-electron-renderer/-/is-electron-renderer-2.0.1.tgz", + "integrity": "sha512-pRlQnpaCFhDVPtkXkP+g9Ybv/CjbiQDjnKFQTEjpBfDKeV6dRDBczuFRDpM6DVfk2EjpMS8t5kwE5jPnqYl3zA==", + "dev": true + }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -23619,6 +24055,42 @@ "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", "dev": true }, + "xvfb-maybe": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/xvfb-maybe/-/xvfb-maybe-0.2.1.tgz", + "integrity": "sha512-9IyRz3l6Qyhl6LvnGRF5jMPB4oBEepQnuzvVAFTynP6ACLLSevqigICJ9d/+ofl29m2daeaVBChnPYUnaeJ7yA==", + "dev": true, + "requires": { + "debug": "^2.2.0", + "which": "^1.2.4" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, "y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", diff --git a/package.json b/package.json index f2d62d8..f9f777e 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "ci:dist": "electron-builder", "release": "electron-builder", "test:winery-launcher": "mvn -pl winery-launcher test", - "test:electron": "mocha -r ts-node/register test/**/*.unit.test.ts test/**/*.integration.test.ts", + "test:electron": "xvfb-maybe electron-mocha -r ts-node/register test/**/*.unit.test.ts test/**/*.integration.test.ts", "test:electron:coverage": "nyc npm run test:electron", "test": "npm-run-all test:winery-launcher test:electron" }, @@ -115,6 +115,7 @@ "css-loader": "^6.7.3", "electron": "^24.1.2", "electron-builder": "^24.2.1", + "electron-mocha": "^12.0.0", "eslint": "^8.39.0", "eslint-plugin-tsdoc": "^0.2.17", "execa": "^7.1.1", @@ -139,6 +140,7 @@ "webpack": "^5.80.0", "webpack-cli": "^5.0.1", "webpack-dev-server": "^4.13.3", + "xvfb-maybe": "^0.2.1", "yauzl": "^2.10.0", "zx": "^7.2.1" }, diff --git a/src/main/index.ts b/src/main/index.ts index fc0c353..3d4c7df 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -78,9 +78,6 @@ function isValidRepository(repositoryPath: string) { function checkUrlType(url: URL): NavigationUrlType { const parsedMainWindowUrl = new URL(mainWindowUrl) - console.log(url.pathname) - console.log(wineryProcess.toscaManagerUrl.pathname) - if (url.href.startsWith(parsedMainWindowUrl.href)) { return "mainWindow" } else if ( diff --git a/src/main/windowManager.ts b/src/main/windowManager.ts index fbae899..b648c01 100644 --- a/src/main/windowManager.ts +++ b/src/main/windowManager.ts @@ -19,19 +19,13 @@ export class WindowManager extends EventEmitter { private topologyModelerWindowSet = new Set() constructor(private urlTypeChecker: (url: URL) => NavigationUrlType) { - if (!urlTypeChecker) { - throw new Error("Could not initialize Window Manager: Need to pass in an URL type checker!") - } super() - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - app['bw'] = BrowserWindow } get mainWindow() { return this._mainWindow } - get toscaManagerWindows() { return Array.from(this.toscaManagerWindowSet) } - get topologyModelerWindows() { return Array.from(this.topologyModelerWindowSet) } - get wineryWindows() { return [...this.toscaManagerWindows, ...this.topologyModelerWindows] } + get toscaManagerWindows() { return Object.freeze(Array.from(this.toscaManagerWindowSet)) } + get topologyModelerWindows() { return Object.freeze(Array.from(this.topologyModelerWindowSet)) } + get wineryWindows() { return Object.freeze([...this.toscaManagerWindows, ...this.topologyModelerWindows]) } /** * Opens the main "workspace selection" window. Makes sure it is created as needed and that there is only one main @@ -178,8 +172,6 @@ export class WindowManager extends EventEmitter { private wineryWindowOpenHandler(details: HandlerDetails): ReturnType { const parsedUrl = new URL(details.url) const urlType = this.urlTypeChecker(parsedUrl) - console.log(urlType) - console.log(details.url) this.openWindowFor(parsedUrl).catch() diff --git a/test/main/utils.ts b/test/main/utils.ts new file mode 100644 index 0000000..33db622 --- /dev/null +++ b/test/main/utils.ts @@ -0,0 +1,18 @@ +import {mainWindowUrl, wineryApiPath} from "../../src/main/resources"; +import {createLogger, transports} from "winston"; +import {PassThrough} from "stream"; +import {match} from "sinon"; + +export const PORT = 8000 +const wineryApiUrl = new URL(wineryApiPath, `http://localhost:${PORT}`).toString() +export const wineryApiUrlMatcher = match((url: URL) => url.toString() === wineryApiUrl) +export const mainWindowUrlMatcher = match((url: URL) => url.toString() === mainWindowUrl) + +// Helper function: create da test dummy logger to listen for "logged" events +export const createTestLogger = () => { + const testTransport = new transports.Stream({stream: new PassThrough()}) + const testLogger = createLogger({ + transports: [testTransport] + }) + return {testTransport, testLogger}; +}; \ No newline at end of file diff --git a/test/main/window-manager.unit.test.ts b/test/main/window-manager.unit.test.ts new file mode 100644 index 0000000..e5617b9 --- /dev/null +++ b/test/main/window-manager.unit.test.ts @@ -0,0 +1,105 @@ +import {expect} from 'chai'; +import {BrowserWindow, shell} from 'electron'; +import sinon, {SinonStub} from 'sinon'; +import {NavigationUrlType, WindowManager} from "../../src/main/windowManager"; +import {mainWindowUrlMatcher} from "./utils"; +import {mainWindowUrl} from "../../src/main/resources"; + +type LoadURLStub = SinonStub<[string, Electron.LoadURLOptions?], Promise> + +describe('WindowManager', () => { + let windowManager: WindowManager; + let urlTypeCheckerStub: SinonStub<[URL], NavigationUrlType>; + + beforeEach(() => { + urlTypeCheckerStub = sinon.stub<[URL]>() + windowManager = new WindowManager(urlTypeCheckerStub) + + // make sure electron does not try to load any urls during tests (which would open an error dialog) + sinon + .stub(BrowserWindow.prototype, 'loadURL') + .withArgs(mainWindowUrlMatcher) + .resolves() + }); + + afterEach(() => { + sinon.restore(); + }); + + describe('openMainWindow', () => { + it('should create a new main window when called for the first time', () => { + expect(windowManager.mainWindow).to.be.null; + windowManager.openMainWindow(); + expect(windowManager.mainWindow).to.be.instanceOf(BrowserWindow); + }); + + it('should not create a new main window when called multiple times', () => { + windowManager.openMainWindow(); + const firstWindow = windowManager.mainWindow; + windowManager.openMainWindow(); + const secondWindow = windowManager.mainWindow; + expect(firstWindow).to.equal(secondWindow); + }); + }); + + describe('openWindowFor', () => { + it('should create and load a TOSCA Manager window when called with a TOSCA Manager URL', async () => { + const url = "about:blank" + urlTypeCheckerStub.returns("toscaManager"); + + const window = await windowManager.openWindowFor(new URL(url)) + + expect((window.loadURL as LoadURLStub).calledOnceWith(url.toString())).to.be.true; + expect(windowManager.toscaManagerWindows.length).to.equal(1) + expect(windowManager.toscaManagerWindows).to.contain(window) + }); + + it('should create and load a new Topology Modeler window with the specified URL', async () => { + const url = "about:blank" + urlTypeCheckerStub.returns("topologyModeler"); + const window = await windowManager.openWindowFor(new URL(url)) + + expect((window.loadURL as LoadURLStub).calledOnceWith(url.toString())).to.be.true; + expect(windowManager.topologyModelerWindows.length).to.equal(1) + expect(windowManager.topologyModelerWindows).to.contain(window) + }); + + it('should open external links in the user\'s web browser', async () => { + const externalUrl = new URL('http://example.com'); + urlTypeCheckerStub.returns("external"); + const shellOpenExternalStub = sinon.stub(shell, 'openExternal') + .withArgs(externalUrl.toString()) + .resolves() + + await windowManager.openWindowFor(externalUrl); + expect(shellOpenExternalStub.calledOnceWith(externalUrl.toString())).to.be.true; + }); + + it('should throw an error if the specified URL is the main window URL', async () => { + urlTypeCheckerStub.returns("mainWindow"); + try { + await windowManager.openWindowFor(new URL(mainWindowUrl)) + expect.fail("openWindowFor should fail when trying to open the mainWindowUrl") + } catch (e) { /* empty */ } + }); + }); + + describe('closeAllWineryWindows', () => { + it('should close all winery windows', () => { + const destroySpy = sinon.spy(BrowserWindow.prototype, 'destroy'); + + // Open two Tosca Manager windows and one Topology Modeler window + urlTypeCheckerStub.returns("toscaManager"); + windowManager.openWindowFor(new URL('about:blank')); + windowManager.openWindowFor(new URL('about:blank')); + + urlTypeCheckerStub.returns("topologyModeler"); + windowManager.openWindowFor(new URL('about:blank')); + + expect(windowManager.wineryWindows.length).to.equal(3) + + windowManager.closeAllWineryWindows(); + expect(windowManager.wineryWindows).to.be.empty + }); + }); +}); \ No newline at end of file diff --git a/test/main/winery-manager.unit.test.ts b/test/main/winery-manager.unit.test.ts index 3524486..8ba9628 100644 --- a/test/main/winery-manager.unit.test.ts +++ b/test/main/winery-manager.unit.test.ts @@ -7,13 +7,9 @@ import child_process, {ChildProcess} from "child_process"; import {Duplex, PassThrough, Writable} from "stream"; import {expect} from "chai"; import {WineryManager} from "../../src/main/wineryManager"; -import {createLogger, LogEntry, transports} from "winston"; +import {LogEntry} from "winston"; import * as fse from "fs-extra"; -import {wineryApiPath} from "../../src/main/resources"; - -const PORT = 8000 -const wineryApiUrl = new URL(wineryApiPath, `http://localhost:${PORT}`).toString() -const wineryApiUrlMatcher = match((url: URL) => url.toString() === wineryApiUrl) +import {createTestLogger, PORT, wineryApiUrlMatcher} from "./utils"; class MockChildProcess extends ChildProcess { constructor( @@ -27,15 +23,6 @@ class MockChildProcess extends ChildProcess { } -// Helper function: create da test dummy logger to listen for "logged" events -const createTestLogger = () => { - const testTransport = new transports.Stream({stream: new PassThrough()}) - const testLogger = createLogger({ - transports: [testTransport] - }) - return {testTransport, testLogger}; -}; - describe('Winery Manager Unit Tests', () => { let fetchStub: SinonStub; let writeFileStub: SinonStub; diff --git a/test/tsconfig.json b/test/tsconfig.json index 648f077..c7613ca 100644 --- a/test/tsconfig.json +++ b/test/tsconfig.json @@ -7,7 +7,7 @@ "esModuleInterop": true }, "include": [ - "./**/*.test.ts" + "./**/*.ts" ], "exclude": [ "../node_modules"