diff --git a/.github/workflows/build_test.yml b/.github/workflows/build_test.yml index 123b994c..7f1ddc6d 100644 --- a/.github/workflows/build_test.yml +++ b/.github/workflows/build_test.yml @@ -89,3 +89,4 @@ jobs: uses: zowe-actions/zlux-builds/zen/publish@v2.x/main with: os: macos + diff --git a/package-lock.json b/package-lock.json index eafb3d46..7a84d3e2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,12 +25,14 @@ "electron-squirrel-startup": "^1.0.0", "electron-store": "^8.1.0", "flat": "^5.0.2", + "jimp": "^0.22.10", + "js-yaml": "^4.1.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-redux": "^8.0.5", "react-router-dom": "^6.8.1", "yaml": "^2.2.1", - "zos-node-accessor": "^1.0.14" + "zos-node-accessor": "^1.0.16" }, "devDependencies": { "@electron-forge/cli": "^6.0.5", @@ -40,6 +42,7 @@ "@electron-forge/maker-squirrel": "^6.0.5", "@electron-forge/maker-zip": "^6.0.5", "@electron-forge/plugin-webpack": "^6.0.5", + "@playwright/test": "^1.38.0", "@types/flat": "^5.0.2", "@types/js-yaml": "^4.0.5", "@types/react": "^18.0.28", @@ -50,6 +53,7 @@ "@vercel/webpack-asset-relocator-loader": "^1.7.3", "css-loader": "^6.7.3", "electron": "22.0.0", + "electron-playwright-helpers": "^1.6.0", "eslint": "^8.34.0", "eslint-plugin-header": "^3.1.1", "eslint-plugin-import": "^2.27.5", @@ -58,6 +62,7 @@ "monaco-editor": "^0.41.0", "monaco-editor-webpack-plugin": "^7.1.0", "node-loader": "^2.0.0", + "playwright": "^1.38.0", "style-loader": "^3.3.1", "ts-loader": "^9.4.2", "ts-node": "^10.9.1", @@ -672,9 +677,9 @@ } }, "node_modules/@electron/asar": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/@electron/asar/-/asar-3.2.3.tgz", - "integrity": "sha512-wmOfE6szYyqZhRIiLH+eyZEp+bGcJI0OD/SCvSUrfBE0jvauyGYO2ZhpWxmNCcDojKu5DYrsVqT5BOCZZ01XIg==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@electron/asar/-/asar-3.2.4.tgz", + "integrity": "sha512-lykfY3TJRRWFeTxccEKdf1I6BLl2Plw81H0bbp4Fc5iEc67foDCa5pjJQULVgo0wF+Dli75f3xVcdb/67FFZ/g==", "dev": true, "dependencies": { "chromium-pickle-js": "^0.2.0", @@ -687,9 +692,6 @@ }, "engines": { "node": ">=10.12.0" - }, - "optionalDependencies": { - "@types/glob": "^7.1.1" } }, "node_modules/@electron/get": { @@ -1157,6 +1159,394 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, + "node_modules/@jimp/bmp": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/bmp/-/bmp-0.22.10.tgz", + "integrity": "sha512-1UXRl1Nw1KptZ1r0ANqtXOst9vGH51dq7keVKQzyyTO2lz4dOaezS9StuSTNh+RmiHg/SVPaFRpPfB0S/ln4Kg==", + "dependencies": { + "@jimp/utils": "^0.22.10", + "bmp-js": "^0.1.0" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/core": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/core/-/core-0.22.10.tgz", + "integrity": "sha512-ZKyrehVy6wu1PnBXIUpn/fXmyMRQiVSbvHDubgXz4bfTOao3GiOurKHjByutQIgozuAN6ZHWiSge1dKA+dex3w==", + "dependencies": { + "@jimp/utils": "^0.22.10", + "any-base": "^1.1.0", + "buffer": "^5.2.0", + "exif-parser": "^0.1.12", + "file-type": "^16.5.4", + "isomorphic-fetch": "^3.0.0", + "pixelmatch": "^4.0.2", + "tinycolor2": "^1.6.0" + } + }, + "node_modules/@jimp/custom": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/custom/-/custom-0.22.10.tgz", + "integrity": "sha512-sPZkUYe1hu0iIgNisjizxPJqq2vaaKvkCkPoXq2U6UV3ZA1si/WVdrg25da3IcGIEV+83AoHgM8TvqlLgrCJsg==", + "dependencies": { + "@jimp/core": "^0.22.10" + } + }, + "node_modules/@jimp/gif": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/gif/-/gif-0.22.10.tgz", + "integrity": "sha512-yEX2dSpamvkSx1PPDWGnKeWDrBz0vrCKjVG/cn4Zr68MRRT75tbZIeOrBa+RiUpY3ho5ix7d36LkYvt3qfUIhQ==", + "dependencies": { + "@jimp/utils": "^0.22.10", + "gifwrap": "^0.10.1", + "omggif": "^1.0.9" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/jpeg": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/jpeg/-/jpeg-0.22.10.tgz", + "integrity": "sha512-6bu98pAcVN4DY2oiDLC4TOgieX/lZrLd1tombWZOFCN5PBmqaHQxm7IUmT+Wj4faEvh8QSHgVLSA+2JQQRJWVA==", + "dependencies": { + "@jimp/utils": "^0.22.10", + "jpeg-js": "^0.4.4" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-blit": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-blit/-/plugin-blit-0.22.10.tgz", + "integrity": "sha512-6EI8Sl+mxYHEIy6Yteh6eknD+EZguKpNdr3sCKxNezmLR0+vK99vHcllo6uGSjXXiwtwS67Xqxn8SsoatL+UJQ==", + "dependencies": { + "@jimp/utils": "^0.22.10" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-blur": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-blur/-/plugin-blur-0.22.10.tgz", + "integrity": "sha512-4XRTWuPVdMXJeclJMisXPGizeHtTryVaVV5HnuQXpKqIZtzXReCCpNGH8q/i0kBQOQMXhGWS3mpqOEwtpPePKw==", + "dependencies": { + "@jimp/utils": "^0.22.10" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-circle": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-circle/-/plugin-circle-0.22.10.tgz", + "integrity": "sha512-mhcwTO1ywRxiCgtLGge6tDDIDPlX6qkI3CY+BjgGG/XhVHccCddXgOGLdlf+5OuKIEF2Nqs0V01LQEQIJFTmEw==", + "dependencies": { + "@jimp/utils": "^0.22.10" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-color": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-color/-/plugin-color-0.22.10.tgz", + "integrity": "sha512-e4t3L7Kedd96E0x1XjsTM6NcgulKUU66HdFTao7Tc9FYJRFSlttARZ/C6LEryGDm/i69R6bJEpo7BkNz0YL55Q==", + "dependencies": { + "@jimp/utils": "^0.22.10", + "tinycolor2": "^1.6.0" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-contain": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-contain/-/plugin-contain-0.22.10.tgz", + "integrity": "sha512-eP8KrzctuEoqibQAxi9WhbnoRosydhiwg+IYya3dKuKDBTrD9UHt+ERlPQ/lTNWHzV/l4S1ntV3r9s9saJgsXA==", + "dependencies": { + "@jimp/utils": "^0.22.10" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5", + "@jimp/plugin-blit": ">=0.3.5", + "@jimp/plugin-resize": ">=0.3.5", + "@jimp/plugin-scale": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-cover": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-cover/-/plugin-cover-0.22.10.tgz", + "integrity": "sha512-kJCwL5T1igfa0InCfkE7bBeqg26m46aoRt10ug+rvm11P6RrvRMGrgINFyIKB+mnB7CiyBN/MOula1CvLhSInQ==", + "dependencies": { + "@jimp/utils": "^0.22.10" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5", + "@jimp/plugin-crop": ">=0.3.5", + "@jimp/plugin-resize": ">=0.3.5", + "@jimp/plugin-scale": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-crop": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-crop/-/plugin-crop-0.22.10.tgz", + "integrity": "sha512-BOZ+YGaZlhU7c5ye65RxikicXH0Ki0It6/XHISvipR5WZrfjLjL2Ke20G+AGnwBQc76gKenVcMXVUCnEjtZV+Q==", + "dependencies": { + "@jimp/utils": "^0.22.10" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-displace": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-displace/-/plugin-displace-0.22.10.tgz", + "integrity": "sha512-llNiWWMTKISDXt5+cXI0GaFmZWAjlT+4fFLYf4eXquuL/9wZoQsEBhv2GdGd48mkiS8jZq1Nnb2Q4ehEPTvrzw==", + "dependencies": { + "@jimp/utils": "^0.22.10" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-dither": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-dither/-/plugin-dither-0.22.10.tgz", + "integrity": "sha512-05WLmeV5M+P/0FS+bWf13hMew2X0oa8w9AtmevL2UyA/5GqiyvP2Xm5WfGQ8oFiiMvpnL6RFomJQOZtWca0C2w==", + "dependencies": { + "@jimp/utils": "^0.22.10" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-fisheye": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-fisheye/-/plugin-fisheye-0.22.10.tgz", + "integrity": "sha512-InjiXvc7Gkzrx8VWtU97kDqV7ENnhHGPULymJWeZaF2aicud9Fpk4iCtd/DcZIrk7Cbe60A8RwNXN00HXIbSCg==", + "dependencies": { + "@jimp/utils": "^0.22.10" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-flip": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-flip/-/plugin-flip-0.22.10.tgz", + "integrity": "sha512-42GkGtTHWnhnwTMPVK/kXObZbkYIpQWfuIfy5EMEMk6zRj05zpv4vsjkKWfuemweZINwfvD7wDJF7FVFNNcZZg==", + "dependencies": { + "@jimp/utils": "^0.22.10" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5", + "@jimp/plugin-rotate": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-gaussian": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-gaussian/-/plugin-gaussian-0.22.10.tgz", + "integrity": "sha512-ykrG/6lTp9Q5YA8jS5XzwMHtRxb9HOFMgtmnrUZ8kU+BK8REecfy9Ic5BUEOjCYvS1a/xLsnrZQU07iiYxBxFg==", + "dependencies": { + "@jimp/utils": "^0.22.10" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-invert": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-invert/-/plugin-invert-0.22.10.tgz", + "integrity": "sha512-d8j9BlUJYs/c994t4azUWSWmQq4LLPG4ecm8m6SSNqap+S/HlVQGqjYhJEBbY9EXkOTYB9vBL9bqwSM1Rr6paA==", + "dependencies": { + "@jimp/utils": "^0.22.10" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-mask": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-mask/-/plugin-mask-0.22.10.tgz", + "integrity": "sha512-yRBs1230XZkz24uFTdTcSlZ0HXZpIWzM3iFQN56MzZ7USgdVZjPPDCQ8I9RpqfZ36nDflQkUO0wV7ucsi4ogow==", + "dependencies": { + "@jimp/utils": "^0.22.10" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-normalize": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-normalize/-/plugin-normalize-0.22.10.tgz", + "integrity": "sha512-Wk9GX6eJMchX/ZAazVa70Fagu+OXMvHiPY+HrcEwcclL+p1wo8xAHEsf9iKno7Ja4EU9lLhbBRY5hYJyiKMEkg==", + "dependencies": { + "@jimp/utils": "^0.22.10" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-print": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-print/-/plugin-print-0.22.10.tgz", + "integrity": "sha512-1U3VloIR+beE1kWPdGEJMiE2h1Do29iv3w8sBbvPyRP4qXxRFcDpmCGtctsrKmb1krlBFlj8ubyAY90xL+5n9w==", + "dependencies": { + "@jimp/utils": "^0.22.10", + "load-bmfont": "^1.4.1" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5", + "@jimp/plugin-blit": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-resize": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-resize/-/plugin-resize-0.22.10.tgz", + "integrity": "sha512-ixomxVcnAONXDgaq0opvAx4UAOiEhOA/tipuhFFOvPKFd4yf1BAnEviB5maB0SBHHkJXPUSzDp/73xVTMGSe7g==", + "dependencies": { + "@jimp/utils": "^0.22.10" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-rotate": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-rotate/-/plugin-rotate-0.22.10.tgz", + "integrity": "sha512-eeFX8dnRyf3LAdsdXWKWuN18hLRg8zy1cP0cP9rHzQVWRK7ck/QsLxK1vHq7MADGwQalNaNTJ9SQxH6c8mz6jw==", + "dependencies": { + "@jimp/utils": "^0.22.10" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5", + "@jimp/plugin-blit": ">=0.3.5", + "@jimp/plugin-crop": ">=0.3.5", + "@jimp/plugin-resize": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-scale": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-scale/-/plugin-scale-0.22.10.tgz", + "integrity": "sha512-TG/H0oUN69C9ArBCZg4PmuoixFVKIiru8282KzSB/Tp1I0xwX0XLTv3dJ5pobPlIgPcB+TmD4xAIdkCT4rtWxg==", + "dependencies": { + "@jimp/utils": "^0.22.10" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5", + "@jimp/plugin-resize": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-shadow": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-shadow/-/plugin-shadow-0.22.10.tgz", + "integrity": "sha512-TN9xm6fI7XfxbMUQqFPZjv59Xdpf0tSiAQdINB4g6pJMWiVANR/74OtDONoy3KKpenu5Y38s+FkrtID/KcQAhw==", + "dependencies": { + "@jimp/utils": "^0.22.10" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5", + "@jimp/plugin-blur": ">=0.3.5", + "@jimp/plugin-resize": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-threshold": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-threshold/-/plugin-threshold-0.22.10.tgz", + "integrity": "sha512-DA2lSnU0TgIRbAgmXaxroYw3Ad6J2DOFEoJp0NleSm2h3GWbZEE5yW9U2B6hD3iqn4AenG4E2b2WzHXZyzSutw==", + "dependencies": { + "@jimp/utils": "^0.22.10" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5", + "@jimp/plugin-color": ">=0.8.0", + "@jimp/plugin-resize": ">=0.8.0" + } + }, + "node_modules/@jimp/plugins": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugins/-/plugins-0.22.10.tgz", + "integrity": "sha512-KDMZyM6pmvS8freB+UBLko1TO/k4D7URS/nphCozuH+P7i3UMe7NdckXKJ8u+WD6sqN0YFYvBehpkpnUiw/91w==", + "dependencies": { + "@jimp/plugin-blit": "^0.22.10", + "@jimp/plugin-blur": "^0.22.10", + "@jimp/plugin-circle": "^0.22.10", + "@jimp/plugin-color": "^0.22.10", + "@jimp/plugin-contain": "^0.22.10", + "@jimp/plugin-cover": "^0.22.10", + "@jimp/plugin-crop": "^0.22.10", + "@jimp/plugin-displace": "^0.22.10", + "@jimp/plugin-dither": "^0.22.10", + "@jimp/plugin-fisheye": "^0.22.10", + "@jimp/plugin-flip": "^0.22.10", + "@jimp/plugin-gaussian": "^0.22.10", + "@jimp/plugin-invert": "^0.22.10", + "@jimp/plugin-mask": "^0.22.10", + "@jimp/plugin-normalize": "^0.22.10", + "@jimp/plugin-print": "^0.22.10", + "@jimp/plugin-resize": "^0.22.10", + "@jimp/plugin-rotate": "^0.22.10", + "@jimp/plugin-scale": "^0.22.10", + "@jimp/plugin-shadow": "^0.22.10", + "@jimp/plugin-threshold": "^0.22.10", + "timm": "^1.6.1" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/png": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/png/-/png-0.22.10.tgz", + "integrity": "sha512-RYinU7tZToeeR2g2qAMn42AU+8OUHjXPKZZ9RkmoL4bguA1xyZWaSdr22/FBkmnHhOERRlr02KPDN1OTOYHLDQ==", + "dependencies": { + "@jimp/utils": "^0.22.10", + "pngjs": "^6.0.0" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/tiff": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/tiff/-/tiff-0.22.10.tgz", + "integrity": "sha512-OaivlSYzpNTHyH/h7pEtl3A7F7TbsgytZs52GLX/xITW92ffgDgT6PkldIrMrET6ERh/hdijNQiew7IoEEr2og==", + "dependencies": { + "utif2": "^4.0.1" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/types": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/types/-/types-0.22.10.tgz", + "integrity": "sha512-u/r+XYzbCx4zZukDmxx8S0er3Yq3iDPI6+31WKX0N18i2qPPJYcn8qwIFurfupRumGvJ8SlGLCgt/T+Y8zzUIw==", + "dependencies": { + "@jimp/bmp": "^0.22.10", + "@jimp/gif": "^0.22.10", + "@jimp/jpeg": "^0.22.10", + "@jimp/png": "^0.22.10", + "@jimp/tiff": "^0.22.10", + "timm": "^1.6.1" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/utils": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.22.10.tgz", + "integrity": "sha512-ztlOK9Mm2iLG2AMoabzM4i3WZ/FtshcgsJCbZCRUs/DKoeS2tySRJTnQZ1b7Roq0M4Ce+FUAxnCAcBV0q7PH9w==", + "dependencies": { + "regenerator-runtime": "^0.13.3" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", @@ -1674,6 +2064,21 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, + "node_modules/@playwright/test": { + "version": "1.38.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.38.0.tgz", + "integrity": "sha512-xis/RXXsLxwThKnlIXouxmIvvT3zvQj1JE39GsNieMUrMpb3/GySHDh2j8itCG22qKVD4MYLBp7xB73cUW/UUw==", + "dev": true, + "dependencies": { + "playwright": "1.38.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/@popperjs/core": { "version": "2.11.6", "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz", @@ -1738,6 +2143,11 @@ "node": ">=10" } }, + "node_modules/@tokenizer/token": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", + "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==" + }, "node_modules/@tootallnate/once": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", @@ -2689,6 +3099,11 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/any-base": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/any-base/-/any-base-1.1.0.tgz", + "integrity": "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==" + }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", @@ -2887,8 +3302,7 @@ "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/array-flatten": { "version": "1.1.1", @@ -3071,7 +3485,6 @@ "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, "funding": [ { "type": "github", @@ -3128,6 +3541,11 @@ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", "dev": true }, + "node_modules/bmp-js": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/bmp-js/-/bmp-js-0.1.0.tgz", + "integrity": "sha512-vHdS19CnY3hwiNdkaqk93DvjVLfbEcI8mys4UjuWrlX1haDmroo8o4xCzh4wD6DGV6HxRCyauwhHRqMTfERtjw==" + }, "node_modules/body-parser": { "version": "1.20.1", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", @@ -3262,7 +3680,6 @@ "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, "funding": [ { "type": "github", @@ -4340,6 +4757,11 @@ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, + "node_modules/dom-walk": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", + "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==" + }, "node_modules/domelementtype": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", @@ -4876,6 +5298,15 @@ "node": ">=14.14" } }, + "node_modules/electron-playwright-helpers": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/electron-playwright-helpers/-/electron-playwright-helpers-1.6.0.tgz", + "integrity": "sha512-0csyp77xRAi8m5g1ApcYdTMJ8n0+Geyb4huyMAsIYTInk4wsuUTHmIy2gMfgF3I130ogfpX6ZfEGeffS93FaUA==", + "dev": true, + "dependencies": { + "@electron/asar": "^3.2.4" + } + }, "node_modules/electron-squirrel-startup": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/electron-squirrel-startup/-/electron-squirrel-startup-1.0.0.tgz", @@ -5020,7 +5451,6 @@ "version": "0.1.13", "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "dev": true, "optional": true, "dependencies": { "iconv-lite": "^0.6.2" @@ -5030,7 +5460,6 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, "optional": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" @@ -5617,6 +6046,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/exif-parser": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz", + "integrity": "sha512-c2bQfLNbMzLPmzQuOr8fy0csy84WmwnER81W88DzTp9CYNPJ6yzOj2EZAh9pywYpqHnshVLHQJ8WzldAyfY+Iw==" + }, "node_modules/expand-tilde": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", @@ -5828,6 +6262,22 @@ "webpack": "^4.0.0 || ^5.0.0" } }, + "node_modules/file-type": { + "version": "16.5.4", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-16.5.4.tgz", + "integrity": "sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw==", + "dependencies": { + "readable-web-to-node-stream": "^3.0.0", + "strtok3": "^6.2.4", + "token-types": "^4.1.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/file-type?sponsor=1" + } + }, "node_modules/filename-reserved-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", @@ -6359,6 +6809,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/gifwrap": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/gifwrap/-/gifwrap-0.10.1.tgz", + "integrity": "sha512-2760b1vpJHNmLzZ/ubTtNnEx5WApN/PYWJvXvgS+tL1egTTthayFYIQQNi136FLEDcN/IyEY2EcGpIITD6eYUw==", + "dependencies": { + "image-q": "^4.0.0", + "omggif": "^1.0.10" + } + }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -6397,6 +6856,15 @@ "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", "dev": true }, + "node_modules/global": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz", + "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==", + "dependencies": { + "min-document": "^2.19.0", + "process": "^0.11.10" + } + }, "node_modules/global-agent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", @@ -6966,7 +7434,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, "funding": [ { "type": "github", @@ -6991,6 +7458,19 @@ "node": ">= 4" } }, + "node_modules/image-q": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/image-q/-/image-q-4.0.0.tgz", + "integrity": "sha512-PfJGVgIfKQJuq3s0tTDOKtztksibuUEbJQIYT3by6wctQo+Rdlh7ef4evJ5NCdxY4CfMbvFkocEwbl4BF8RlJw==", + "dependencies": { + "@types/node": "16.9.1" + } + }, + "node_modules/image-q/node_modules/@types/node": { + "version": "16.9.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.9.1.tgz", + "integrity": "sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==" + }, "node_modules/image-size": { "version": "0.7.5", "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.7.5.tgz", @@ -7251,6 +7731,11 @@ "node": ">=8" } }, + "node_modules/is-function": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz", + "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==" + }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -7550,6 +8035,15 @@ "node": ">=0.10.0" } }, + "node_modules/isomorphic-fetch": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz", + "integrity": "sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==", + "dependencies": { + "node-fetch": "^2.6.1", + "whatwg-fetch": "^3.4.1" + } + }, "node_modules/jest-worker": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", @@ -7579,6 +8073,22 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/jimp": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/jimp/-/jimp-0.22.10.tgz", + "integrity": "sha512-lCaHIJAgTOsplyJzC1w/laxSxrbSsEBw4byKwXgUdMmh+ayPsnidTblenQm+IvhIs44Gcuvlb6pd2LQ0wcKaKg==", + "dependencies": { + "@jimp/custom": "^0.22.10", + "@jimp/plugins": "^0.22.10", + "@jimp/types": "^0.22.10", + "regenerator-runtime": "^0.13.3" + } + }, + "node_modules/jpeg-js": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz", + "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==" + }, "node_modules/js-sdsl": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", @@ -7598,7 +8108,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, "dependencies": { "argparse": "^2.0.1" }, @@ -7746,6 +8255,29 @@ } } }, + "node_modules/load-bmfont": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/load-bmfont/-/load-bmfont-1.4.1.tgz", + "integrity": "sha512-8UyQoYmdRDy81Brz6aLAUhfZLwr5zV0L3taTQ4hju7m6biuwiWiJXjPhBJxbUQJA8PrkvJ/7Enqmwk2sM14soA==", + "dependencies": { + "buffer-equal": "0.0.1", + "mime": "^1.3.4", + "parse-bmfont-ascii": "^1.0.3", + "parse-bmfont-binary": "^1.0.5", + "parse-bmfont-xml": "^1.1.4", + "phin": "^2.9.1", + "xhr": "^2.0.1", + "xtend": "^4.0.0" + } + }, + "node_modules/load-bmfont/node_modules/buffer-equal": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz", + "integrity": "sha512-RgSV6InVQ9ODPdLWJ5UAqBqJBOg370Nz6ZQtRzpt6nUjc8v0St97uJ4PYC6NztqIScrAXafKM3mZPMygSe1ggA==", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/load-json-file": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", @@ -8131,7 +8663,6 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, "bin": { "mime": "cli.js" }, @@ -8177,6 +8708,14 @@ "node": ">=4" } }, + "node_modules/min-document": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", + "integrity": "sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ==", + "dependencies": { + "dom-walk": "^0.1.0" + } + }, "node_modules/minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", @@ -8455,7 +8994,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz", "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==", - "dev": true, "dependencies": { "whatwg-url": "^5.0.0" }, @@ -8703,6 +9241,11 @@ "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", "dev": true }, + "node_modules/omggif": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/omggif/-/omggif-1.0.10.tgz", + "integrity": "sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==" + }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -8915,6 +9458,11 @@ "node": ">=6" } }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" + }, "node_modules/param-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", @@ -8948,6 +9496,25 @@ "node": ">=0.10.0" } }, + "node_modules/parse-bmfont-ascii": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/parse-bmfont-ascii/-/parse-bmfont-ascii-1.0.6.tgz", + "integrity": "sha512-U4RrVsUFCleIOBsIGYOMKjn9PavsGOXxbvYGtMOEfnId0SVNsgehXh1DxUdVPLoxd5mvcEtvmKs2Mmf0Mpa1ZA==" + }, + "node_modules/parse-bmfont-binary": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/parse-bmfont-binary/-/parse-bmfont-binary-1.0.6.tgz", + "integrity": "sha512-GxmsRea0wdGdYthjuUeWTMWPqm2+FAd4GI8vCvhgJsFnoGhTrLhXDDupwTo7rXVAgaLIGoVHDZS9p/5XbSqeWA==" + }, + "node_modules/parse-bmfont-xml": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/parse-bmfont-xml/-/parse-bmfont-xml-1.1.4.tgz", + "integrity": "sha512-bjnliEOmGv3y1aMEfREMBJ9tfL3WR0i0CKPj61DnSLaoxWR3nLrsQrEbCId/8rF4NyRF0cCqisSVXyQYWM+mCQ==", + "dependencies": { + "xml-parse-from-string": "^1.0.0", + "xml2js": "^0.4.5" + } + }, "node_modules/parse-color": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/parse-color/-/parse-color-1.0.0.tgz", @@ -8965,6 +9532,11 @@ "dev": true, "optional": true }, + "node_modules/parse-headers": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.5.tgz", + "integrity": "sha512-ft3iAoLOB/MlwbNXgzy43SWGP6sQki2jQvAyBg/zDFAgr9bfNWZIUj42Kw2eJIl8kEi4PbgE6U1Zau/HwI75HA==" + }, "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", @@ -9056,12 +9628,29 @@ "node": ">=8" } }, + "node_modules/peek-readable": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-4.1.0.tgz", + "integrity": "sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg==", + "engines": { + "node": ">=8" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", "dev": true }, + "node_modules/phin": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/phin/-/phin-2.9.3.tgz", + "integrity": "sha512-CzFr90qM24ju5f88quFC/6qohjC144rehe5n6DH900lgXmUe86+xCKc10ev56gRKC4/BkHUoG4uSiQgBiIXwDA==" + }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", @@ -9089,6 +9678,25 @@ "node": ">=0.10.0" } }, + "node_modules/pixelmatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/pixelmatch/-/pixelmatch-4.0.2.tgz", + "integrity": "sha512-J8B6xqiO37sU/gkcMglv6h5Jbd9xNER7aHzpfRdNmV4IbQBzBpe4l9XmbG+xPF/znacgu2jfEw+wHffaq/YkXA==", + "dependencies": { + "pngjs": "^3.0.0" + }, + "bin": { + "pixelmatch": "bin/pixelmatch" + } + }, + "node_modules/pixelmatch/node_modules/pngjs": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", + "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==", + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", @@ -9220,6 +9828,36 @@ "node": ">=4" } }, + "node_modules/playwright": { + "version": "1.38.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.38.0.tgz", + "integrity": "sha512-fJGw+HO0YY+fU/F1N57DMO+TmXHTrmr905J05zwAQE9xkuwP/QLDk63rVhmyxh03dYnEhnRbsdbH9B0UVVRB3A==", + "dev": true, + "dependencies": { + "playwright-core": "1.38.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=16" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.38.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.38.0.tgz", + "integrity": "sha512-f8z1y8J9zvmHoEhKgspmCvOExF2XdcxMW8jNRuX4vkQFrzV4MlZ55iwb5QeyiFQgOFCUolXiRHgpjSEnqvO48g==", + "dev": true, + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/plist": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/plist/-/plist-3.0.6.tgz", @@ -9233,6 +9871,14 @@ "node": ">=6" } }, + "node_modules/pngjs": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-6.0.0.tgz", + "integrity": "sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg==", + "engines": { + "node": ">=12.13.0" + } + }, "node_modules/postcss": { "version": "8.4.21", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", @@ -9354,6 +10000,14 @@ "renderkid": "^3.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==", + "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", @@ -9767,7 +10421,6 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -9777,6 +10430,21 @@ "node": ">= 6" } }, + "node_modules/readable-web-to-node-stream": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz", + "integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==", + "dependencies": { + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -10102,7 +10770,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, "funding": [ { "type": "github", @@ -10136,7 +10803,12 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true + "devOptional": true + }, + "node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" }, "node_modules/scheduler": { "version": "0.23.0", @@ -10690,7 +11362,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, "dependencies": { "safe-buffer": "~5.2.0" } @@ -10809,6 +11480,22 @@ "node": ">=0.8.0" } }, + "node_modules/strtok3": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.3.0.tgz", + "integrity": "sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw==", + "dependencies": { + "@tokenizer/token": "^0.3.0", + "peek-readable": "^4.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, "node_modules/style-loader": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.1.tgz", @@ -11022,6 +11709,11 @@ "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", "dev": true }, + "node_modules/timm": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/timm/-/timm-1.7.1.tgz", + "integrity": "sha512-IjZc9KIotudix8bMaBW6QvMuq64BrJWFs1+4V0lXwWGQZwH+LnX87doAYhem4caOEusRP9/g6jVDQmZ8XOk1nw==" + }, "node_modules/tiny-each-async": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/tiny-each-async/-/tiny-each-async-2.0.3.tgz", @@ -11029,6 +11721,11 @@ "dev": true, "optional": true }, + "node_modules/tinycolor2": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz", + "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==" + }, "node_modules/tmp": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", @@ -11101,11 +11798,26 @@ "node": ">=0.6" } }, + "node_modules/token-types": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/token-types/-/token-types-4.2.1.tgz", + "integrity": "sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ==", + "dependencies": { + "@tokenizer/token": "^0.3.0", + "ieee754": "^1.2.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, "node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, "node_modules/trim-repeated": { "version": "1.0.0", @@ -11545,11 +12257,18 @@ "which": "bin/which" } }, + "node_modules/utif2": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/utif2/-/utif2-4.1.0.tgz", + "integrity": "sha512-+oknB9FHrJ7oW7A2WZYajOcv4FcDR4CfoGB0dPNfxbi4GO05RRnFmt5oa23+9w32EanrYcSJWspUiJkLMs+37w==", + "dependencies": { + "pako": "^1.0.11" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "node_modules/utila": { "version": "0.4.0", @@ -11634,8 +12353,7 @@ "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "dev": true + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, "node_modules/webpack": { "version": "5.76.2", @@ -11899,11 +12617,15 @@ "node": ">=0.8.0" } }, + "node_modules/whatwg-fetch": { + "version": "3.6.19", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.19.tgz", + "integrity": "sha512-d67JP4dHSbm2TrpFj8AbO8DnL1JXL5J9u0Kq2xW6d0TFDbCA3Muhdt8orXC22utleTVj7Prqt82baN6RBvnEgw==" + }, "node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dev": true, "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" @@ -12035,6 +12757,42 @@ } } }, + "node_modules/xhr": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.6.0.tgz", + "integrity": "sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA==", + "dependencies": { + "global": "~4.4.0", + "is-function": "^1.0.1", + "parse-headers": "^2.0.0", + "xtend": "^4.0.0" + } + }, + "node_modules/xml-parse-from-string": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz", + "integrity": "sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g==" + }, + "node_modules/xml2js": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xml2js/node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "engines": { + "node": ">=4.0" + } + }, "node_modules/xmlbuilder": { "version": "15.1.1", "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", @@ -12056,8 +12814,6 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "optional": true, "engines": { "node": ">=0.4" } @@ -12251,9 +13007,9 @@ } }, "node_modules/zos-node-accessor": { - "version": "1.0.14", - "resolved": "https://registry.npmjs.org/zos-node-accessor/-/zos-node-accessor-1.0.14.tgz", - "integrity": "sha512-+DXcOSBcixulEGPXVEn8ktXZqIP/eSzrQLO8daIELcak1zP89z7rdFRhMcKmEXk11PLq2wcoDzzIq3KPSHBLiA==", + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/zos-node-accessor/-/zos-node-accessor-1.0.16.tgz", + "integrity": "sha512-7IsneaFw7sryn2ovopz4lr3W57LRXZ3p4tEdnRLSJav3xYY7qkbnfV5nni5kdWusd2rLaArf4omZY1O/LD4lhA==", "dependencies": { "debug": "3.1.0", "ftp4": "~0.3.13", diff --git a/package.json b/package.json index 0c684543..abe2b24a 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,9 @@ "package": "electron-forge package", "make": "electron-forge make", "publish": "electron-forge publish", - "lint": "eslint --ext .ts,.tsx ." + "lint": "eslint --ext .ts,.tsx .", + "preplaytest": "npm run package", + "playtest": "playwright test" }, "keywords": [], "license": "EPL 2.0", @@ -22,6 +24,7 @@ "@electron-forge/maker-squirrel": "^6.0.5", "@electron-forge/maker-zip": "^6.0.5", "@electron-forge/plugin-webpack": "^6.0.5", + "@playwright/test": "^1.38.0", "@types/flat": "^5.0.2", "@types/js-yaml": "^4.0.5", "@types/react": "^18.0.28", @@ -32,6 +35,7 @@ "@vercel/webpack-asset-relocator-loader": "^1.7.3", "css-loader": "^6.7.3", "electron": "22.0.0", + "electron-playwright-helpers": "^1.6.0", "eslint": "^8.34.0", "eslint-plugin-header": "^3.1.1", "eslint-plugin-import": "^2.27.5", @@ -40,6 +44,7 @@ "monaco-editor": "^0.41.0", "monaco-editor-webpack-plugin": "^7.1.0", "node-loader": "^2.0.0", + "playwright": "^1.38.0", "style-loader": "^3.3.1", "ts-loader": "^9.4.2", "ts-node": "^10.9.1", @@ -62,11 +67,13 @@ "electron-squirrel-startup": "^1.0.0", "electron-store": "^8.1.0", "flat": "^5.0.2", + "jimp": "^0.22.10", + "js-yaml": "^4.1.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-redux": "^8.0.5", "react-router-dom": "^6.8.1", "yaml": "^2.2.1", - "zos-node-accessor": "^1.0.14" + "zos-node-accessor": "^1.0.16" } } diff --git a/playwright_test/Pages/connection.page.ts b/playwright_test/Pages/connection.page.ts new file mode 100644 index 00000000..f71b55c6 --- /dev/null +++ b/playwright_test/Pages/connection.page.ts @@ -0,0 +1,35 @@ +import { Page,ElectronApplication, Locator,_electron as electron } from '@playwright/test'; +let electronApp: ElectronApplication + +class ConnectionPage{ + page: Page; + host: Locator; + port: Locator; + userName: Locator; + password: Locator; + validateCredential: Locator; + + + constructor(page: Page) { + this.page = page; + this.host = page.locator('label:has-text("Host") + div input#standard-required') + this.port = page.locator('#standard-number') + this.userName = page.locator('label:has-text("User Name") + div input#standard-required') + this.password = page.locator('#standard-password-input') + this.validateCredential = page.locator("//button[contains(text(), 'Validate credentials')]") + + } + async fillConnectionDetails(host: string, port: string, username: string, password: string){ + await this.host.fill(host) + await this.port.fill(port) + await this.userName.fill(username) + await this.password.fill(password) + } + async SubmitValidateCredential(){ + await this.validateCredential.click() + + } + +} + + export default ConnectionPage; \ No newline at end of file diff --git a/playwright_test/Pages/title.page.ts b/playwright_test/Pages/title.page.ts new file mode 100644 index 00000000..5ef726af --- /dev/null +++ b/playwright_test/Pages/title.page.ts @@ -0,0 +1,19 @@ +import { Page,ElectronApplication, Locator,_electron as electron } from '@playwright/test'; +let electronApp: ElectronApplication + +class TitlePage { + page: Page; + zoweInstallButton: Locator; + zoweDryrunButton: Locator; + + constructor(page: Page) { + this.page = page; + this.zoweInstallButton = page.locator('#card-install') + this.zoweDryrunButton = page.locator('#card-configure') + + } + async navigateToConnectionTab(){ + await this.zoweInstallButton.click({timeout: 9000}) + } } + + export default TitlePage; \ No newline at end of file diff --git a/playwright_test/README.MD b/playwright_test/README.MD new file mode 100644 index 00000000..4813f61f --- /dev/null +++ b/playwright_test/README.MD @@ -0,0 +1,37 @@ +### Prerequisite For Test + +Make sure command zen is installed by running `npm install` + +### Start Test + +Example command: + +``` + ZOWE_EXTENSION_DIR=\\path\\to\\zowe\\extension \ + ZOWE_LOG_DIR=\\path\\to\\zowe\\logs \ + ZOWE_ROOT_DIR=\\path\\to\\zowe \ + ZOWE_WORKSPACE_DIR=\\path\\to\\zowe\\workspaceDir \ + SSH_HOST=test-server \ + SSH_PORT=12022 \ + SSH_USER=********* \ + SSH_PASSWD=********* \ + ZOSMF_PORT=10443 \ + JOB_NAME= \ + JOB_PREFIX=ZWE \ + JAVA_HOME=\\path\\to\\java \ + NODE_HOME=\\path\\to\\node \ + SECURITY_ADMIN=ZWEADMIN \ + SECURITY_SYSPROG=ZWEADMIN \ + SECURITY_STC=ZWEADMIN \ + SECURITY_AUX=ZWESASTC \ + SECURITY_USER_ZIS=ZWESIUSR \ + SECURITY_USER_ZOWE=ZWESVUSR \ + SECURITY_STC_ZIS=ZWESISTC \ + SECURITY_STC_ZOWE=ZWESLSTC \ + ZOSMF_APP_ID=IZUDFLT \ + npm run playtest +``` + +To run individial test, specify the name of the test file ex: + +``` npm run playtest testConnectionTab.spec.ts ``` diff --git a/playwright_test/Tests/Connection.spec.ts b/playwright_test/Tests/Connection.spec.ts new file mode 100644 index 00000000..5582747b --- /dev/null +++ b/playwright_test/Tests/Connection.spec.ts @@ -0,0 +1,27 @@ +import { test, ElectronApplication, expect, _electron as electron } from '@playwright/test'; +import ConnectionPage from '../Pages/connection.page'; +import TitlePage from '../Pages/title.page'; + +let electronApp: ElectronApplication + +test.describe('ConnectionTab', () => { + let connectionPage: ConnectionPage; + let titlePage : TitlePage; + + test.beforeEach(async ({ page }) => { + electronApp = await electron.launch({ args: ['.webpack/main/index.js'] }) + page= await electronApp.firstWindow() + connectionPage = new ConnectionPage(page); + titlePage = new TitlePage(page); + + }) + + test('Verify connection details', async ({ page }) => { + // verify title + titlePage.navigateToConnectionTab() + connectionPage.fillConnectionDetails('rs22','21','csmvdqe','9jipigi') + connectionPage.SubmitValidateCredential() + await page.waitForTimeout(2000); + }) + +}) \ No newline at end of file diff --git a/playwright_test/Tests/titleTab.spec.ts b/playwright_test/Tests/titleTab.spec.ts new file mode 100644 index 00000000..1a4ef432 --- /dev/null +++ b/playwright_test/Tests/titleTab.spec.ts @@ -0,0 +1,28 @@ +import { test, ElectronApplication, expect, _electron as electron } from '@playwright/test'; +import TitlePage from '../Pages/title.page'; + +let electronApp: ElectronApplication + +test.describe('Home', () => { + let titlePage: TitlePage; + + test.beforeEach(async ({ page }) => { + electronApp = await electron.launch({ args: ['.webpack/main/index.js'] }) + page= await electronApp.firstWindow() + titlePage = new TitlePage(page); + + }) + + test('Open HomePage and verify title', async ({ page }) => { + // verify title + // page = await electronApp.firstWindow() + await expect(page).toHaveTitle('Zowe Enterprise Necessity'); + }) + + test('Verify install buttons', async ({ page }) => { + // verify title + //page = await electronApp.firstWindow() + await expect(titlePage.zoweInstallButton).toBeVisible() + await expect(titlePage.zoweDryrunButton).toBeVisible() + }) +}) \ No newline at end of file diff --git a/playwright_test/exampe.spec.ts b/playwright_test/exampe.spec.ts new file mode 100644 index 00000000..b70f5345 --- /dev/null +++ b/playwright_test/exampe.spec.ts @@ -0,0 +1,85 @@ +const { test, expect } = require('@playwright/test') +import { ElectronApplication, Page, _electron as electron } from 'playwright' +import { spawn } from 'child_process'; +import path from 'path'; + +let electronApp: ElectronApplication +let page: Page + + +test.beforeAll(async () => { + const createDirsScriptPath = path.resolve(__dirname, './prepare.js'); + console.log('Creating child process with command:', 'node', [createDirsScriptPath]); + const child = spawn('node', [createDirsScriptPath]); + if (!child) { + console.error('Failed to spawn child process'); + return; + } + console.log('Child process created successfully'); + child.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + child.stderr.on('data', (data) => { + console.error(`stderr: ${data}`); + }); + child.on('error', (error) => { + console.error('Child process encountered an error:', error); + }); + await new Promise(resolve => setTimeout(resolve, 3000)); + electronApp = await electron.launch({ args: ['.webpack/main/index.js'] }) + electronApp.on('window', async (page) => { + const filename = page.url()?.split('/').pop() + console.log(`Window opened: ${filename}`) + page.on('pageerror', (error) => { + console.error(error) + }) + page.on('console', (msg) => { + console.log(msg.text()) + }) + }) +}); + + + +test.afterAll(async () => { + await electronApp.close() +}) + +test('Test Title', async () => { + page = await electronApp.firstWindow() + await page.waitForTimeout(2000); + const title = await page.title(); + expect(title).toBe("Zowe Enterprise Necessity"); +}) + + +test('Test Zowe Installation Button Exist', async () => { + const window = await electronApp.firstWindow() + await window.waitForTimeout(2000); + const button = await window.$('#card-install'); + expect(button).toBeTruthy(); +}) + +test('Test Dry Run Button Exist', async () => { + const window = await electronApp.firstWindow() + await window.waitForTimeout(2000); + const button = await window.$('#card-configure'); + expect(button).toBeTruthy(); +}) + + +test('Test Click Zowe Installation', async () => { + page = await electronApp.firstWindow() + page.click('#card-install') + const newPage = await electronApp.waitForEvent('window') + expect(newPage).toBeTruthy() + page = newPage +}) + + +test(`example test`, async ({ page }) => { + page = await electronApp.firstWindow() + page.click('#card-install') + await page.getByLabel('User Name').fill(process.env.SSH_USER); + await page.getByLabel('Password').fill(process.env.SSH_PASSWD); +}); \ No newline at end of file diff --git a/playwright_test/prepare.js b/playwright_test/prepare.js new file mode 100644 index 00000000..2498253e --- /dev/null +++ b/playwright_test/prepare.js @@ -0,0 +1,25 @@ +const Script = require('./setup.js'); + +const SSH_HOST = process.env.SSH_HOST; +const SSH_PORT = process.env.SSH_PORT; +const SSH_USER = process.env.SSH_USER; +const SSH_PASSWD = process.env.SSH_PASSWD; +const ZOWE_ROOT_DIR = process.env.ZOWE_ROOT_DIR; + +async function prepare() { + const scriptRunner = new Script({ + host: SSH_HOST, + port: SSH_PORT, + user: SSH_USER, + password: SSH_PASSWD, + }); + + await scriptRunner.install(ZOWE_ROOT_DIR); +} + +prepare().then(() => { + console.log('Preparation complete.'); +}).catch((error) => { + console.error('Error during preparation:', error); + process.exit(1); +}); diff --git a/playwright_test/setup.js b/playwright_test/setup.js new file mode 100644 index 00000000..d0305ecb --- /dev/null +++ b/playwright_test/setup.js @@ -0,0 +1,103 @@ +const zos = require('zos-node-accessor'); +const https = require('https'); + +class Script { + constructor(config) { + this.config = config; + } + + async mkdir(installDir) { + const script = `mkdir ${installDir}`; + return this.run(script); + } + + static getZoweVersion() { + return new Promise((resolve, reject) => { + https.get('https://raw.githubusercontent.com/zowe/zowe-install-packaging/v2.x/master/manifest.json.template', (res) => { + let data = ''; + + res.on('data', (chunk) => { + data += chunk; + }); + + res.on('end', () => { + try { + const parsedData = JSON.parse(data); + resolve({ status: true, details: parsedData.version }); + } catch (error) { + reject({ status: false, details: { error } }); + } + }); + + }).on('error', (error) => { + reject({ status: false, details: { error } }); + }); + }); + } + + async download(installDir) { + try { + const { status, details: version } = await Script.getZoweVersion(); + if (!status) { + throw new Error('Failed to retrieve Zowe version.'); + } + const script = `URL="https://zowe.jfrog.io/zowe/list/libs-release-local/org/zowe"; +curl $URL/${version}/zowe-${version}.pax +-k +-o ${installDir}/zowe.pax` + return this.run(script); + } catch (error) { + console.error('Error:', error); + return null; + } + } + + async unpax(installDir) { + const script = `cd ${installDir};\npax -ppx -rf zowe.pax;\nrm zowe.pax`; + return this.run(script); + } + + async install(installDir) { + try { + await this.mkdir(installDir); + await this.download(installDir); + await this.unpax(installDir); + console.log('Installation completed successfully.'); + } catch (error) { + console.error('Installation failed:', error); + } + } + + async run(script) { + const jcl = `//ZWEJOB01 JOB IZUACCT,'SYSPROG',CLASS=A, +// MSGLEVEL=(1,1),MSGCLASS=A +//RUNSCRP EXEC PGM=BPXBATCH,REGION=0M +//STDOUT DD SYSOUT=* +//STDERR DD SYSOUT=* +//STDPARM DD * +sh set -x; +${script}; +echo "Script finished." +/* `; + + try { + console.log('Connecting to FTP server...'); + const client = new zos(); + await client.connect(this.config); + + if (!client.connected) { + throw new Error('Failed to connect to ' + this.config.host); + } + const result = await client.submitJCL(jcl, ["STDOUT", "STDERR"]); + console.log('JCL submitted successfully.'); + console.log('Result:', result); + return result; + } catch (error) { + console.error('Error:', error); + return null; + } + } +} + +module.exports = Script; + diff --git a/playwright_test/testApfauthTab.spec.ts b/playwright_test/testApfauthTab.spec.ts new file mode 100644 index 00000000..3492c170 --- /dev/null +++ b/playwright_test/testApfauthTab.spec.ts @@ -0,0 +1,248 @@ +import { test, expect } from '@playwright/test'; +import { setup } from './setup'; +import { ElectronApplication, Page } from 'playwright'; +let electronApp: ElectronApplication; +let page: Page; + +//selectors +const continueButtonSelector = '.MuiButton-containedPrimary.MuiButton-sizeMedium' +const userNameInputSelector = 'label:has-text("User Name") + div input#standard-required' +const writeConfig_greenCheckXpath = '#card-download-progress-card svg.MuiSvgIcon-colorSuccess' +const uploadYaml_greenCheckXpath = '#card-download-progress-card svg.MuiSvgIcon-colorSuccess' +const init_apfauth_greenCheckXpath = '#card-upload-progress-card svg.MuiSvgIcon-colorSuccess' +const previous_step_button = '//button[contains(text(),"Previous step")]' +const skip_installation_button = '//button[contains(text(),"Skip")]' +const skip_apf_auth_button = '//button[contains(text(),"Skip")]' +const continue_apfauth_setup = '//button[contains(text(),"Continue to APF Auth Setup")]' +const continue_security_setup = '//button[contains(text(),"Continue to Security Setup")]' +const editor_title_element = '//h2[text()="Editor"]' +const INSTALLATION_TITLE = 'Installation' +const APFAUTH_TITLE = 'APF Authorize Load Libraries' +const SECURITY_TITLE = 'Security' +const DATASET_PREFIX = 'IBMUSER.ZWEV2' +const AUTH_LOAD_LIB = 'IBMUSER.ZWEV2.ZWEAUTH' +const AUTH_PLUGIN_LIB = 'IBMUSER.ZWEV2.CUST.ZWESAPL' + +async function setupPage(page: Page) { + electronApp = await setup(); + page = await electronApp.firstWindow(); + await page.waitForTimeout(1000); + await page.locator("//button[contains(text(), 'License Agreement')]").click(); + await page.locator("//html/body/div[2]/div[3]/div/div[2]/button[1]").click(); + await page.locator("//button[contains(text(), 'Continue to Components Installation')]").click(); +} + +test.beforeEach(async () => { + test.setTimeout(90000); + await setupPage(page); +}); + +test.afterEach(async () => { + await electronApp.close() +}) + + +test('Test Titles', async () => { + page = await electronApp.firstWindow(); + const installation_title = await page.locator('//div[text()="Installation"]').textContent(); + expect (installation_title).toBe(INSTALLATION_TITLE) + await page.locator(skip_installation_button).click(); + const apfauth_title = await page.locator('//div[text()="APF Authorize Load Libraries"]').textContent(); + expect (apfauth_title).toBe(APFAUTH_TITLE) + +}); + +test('Test all required fields on Installation Tab', async () => { + page = await electronApp.firstWindow(); + const prefix = await page.waitForSelector('#/properties/prefix2-input'); + const auth_load_lib = await page.waitForSelector('#/properties/authLoadlib3-input'); + const auth_plugin_lib = await page.waitForSelector('#/properties/authPluginLib3-input'); + const install_mvs_datasets = await page.locator('//button[contains(text(),"Install MVS datasets")]'); + const skip_installation = await page.locator(skip_installation_button); + await page.waitForTimeout(1000); + expect(prefix).toBeTruthy(); + expect(auth_load_lib).toBeTruthy(); + expect(auth_plugin_lib).toBeTruthy(); + expect(install_mvs_datasets).toBeTruthy(); + expect(skip_installation).toBeTruthy(); + expect(continue_apfauth_setup).toBeTruthy(); + const isButtonDisabled = await page.isDisabled(continue_apfauth_setup); + expect(isButtonDisabled).toBe(true); +}); + +test('Test all required fields on Apf Auth Tab', async () => { + page = await electronApp.firstWindow(); + const dataset_prefix = await page.getByLabel('Dataset Prefix'); + const auth_load_lib = await page.getByLabel('APF Authorized Load Library'); + const auth_plugin_lib = await page.getByLabel('Zowe ZIS Plugins Load Library'); + const run_zwe_init_apfauth = await page.locator('//button[contains(text(),"zwe init apfauth")]'); + const view_yaml = await page.locator('//button[contains(text(),"View Yaml")]'); + const view_submit_job = await page.locator('//button[contains(text(),"View/Submit Job")]'); + const view_job_output = await page.locator('//button[contains(text(),"View Job Output")]'); + const save_and_close = await page.locator('//button[contains(text(),"Save & close")]'); + const previous_step = await page.locator(previous_step_button); + const skip_apf_auth = await page.locator(skip_apf_auth_button); + await page.waitForTimeout(1000); + expect(dataset_prefix).toBeTruthy(); + expect(auth_load_lib).toBeTruthy(); + expect(auth_plugin_lib).toBeTruthy(); + expect(run_zwe_init_apfauth).toBeTruthy(); + expect(view_yaml).toBeTruthy(); + expect(view_submit_job).toBeTruthy(); + expect(view_job_output).toBeTruthy(); + expect(save_and_close).toBeTruthy(); + expect(previous_step).toBeTruthy(); + expect(skip_apf_auth).toBeTruthy(); + expect(continue_security_setup).toBeTruthy(); + const isButtonDisabled = await page.isDisabled(continue_security_setup); + expect(isButtonDisabled).toBe(true); +}); + +test('Test Required fields after Run Zwe Init ApfAuth', async () => { + page = await electronApp.firstWindow(); + await page.locator('//button[contains(text(),"zwe init apfauth")]').click(); + const write_config = await page.locator('//p[contains(text(),"Write configuration file locally to temp directory")]'); + const upload_config = await page.locator('//p[contains(text(),"Upload configuration file to")]'); + const zwe_init_apfauth = await page.locator('//p[contains(text(),"Run zwe init apfauth command")]'); + await page.waitForTimeout(1000); + expect(write_config).toBeTruthy(); + expect(upload_config).toBeTruthy(); + expect(zwe_init_apfauth).toBeTruthy(); +}); + +test('Test Run APF Auth with valid data', async () => { + page = await electronApp.firstWindow(); + await page.locator('input[id="#/properties/prefix2-input"]').fill(DATASET_PREFIX); + await page.locator('input[id="#/properties/authLoadlib3-input"]').fill(AUTH_LOAD_LIB); + await page.locator('input[id="#/properties/authPluginLib3-input"]').fill(AUTH_PLUGIN_LIB); + await page.locator(skip_installation_button).click(); + const dataset_prefix_value = await page.getByLabel('Dataset Prefix').textContent(); + const auth_load_lib_value = await page.getByLabel('APF Authorized Load Library').textContent(); + const auth_plugin_lib_value = await page.getByLabel('Zowe ZIS Plugins Load Library').textContent(); + expect(dataset_prefix_value).toBe(DATASET_PREFIX) + expect(auth_load_lib_value).toBe(AUTH_LOAD_LIB) + expect(auth_plugin_lib_value).toBe(AUTH_PLUGIN_LIB) + await page.locator('//button[contains(text(),"zwe init apfauth")]').click(); + await page.waitForSelector(writeConfig_greenCheckXpath, { timeout: 50000 }); + const isIconVisible1 = await page.isVisible(writeConfig_greenCheckXpath); + expect(isIconVisible1).toBe(true); + + await page.waitForSelector(uploadYaml_greenCheckXpath, { timeout: 50000 }); + const isIconVisible2 = await page.isVisible(uploadYaml_greenCheckXpath); + expect(isIconVisible2).toBe(true); + + await page.waitForSelector(init_apfauth_greenCheckXpath, { timeout: 50000 }); + const isIconVisible3 = await page.isVisible(init_apfauth_greenCheckXpath); + expect(isIconVisible3).toBe(true); + + const isButtonEnabled = await page.isEnabled(continue_security_setup); + expect(isButtonEnabled).toBe(true); +}); + +test('Test Run APF Auth with Empty data', async () => { + page = await electronApp.firstWindow(); + await page.locator('input[id="#/properties/prefix2-input"]').fill(''); + await page.locator('input[id="#/properties/authLoadlib3-input"]').fill(''); + await page.locator('input[id="#/properties/authPluginLib3-input"]').fill(''); + await page.locator(skip_installation_button).click(); + const dataset_prefix_value = await page.getByLabel('Dataset Prefix').textContent(); + const auth_load_lib_value = await page.getByLabel('APF Authorized Load Library').textContent(); + const auth_plugin_lib_value = await page.getByLabel('Zowe ZIS Plugins Load Library').textContent(); + expect(dataset_prefix_value).toBe('') + expect(auth_load_lib_value).toBe('') + expect(auth_plugin_lib_value).toBe('') + await page.locator('//button[contains(text(),"zwe init apfauth")]').click(); + await page.waitForSelector(writeConfig_greenCheckXpath, { timeout: 50000 }); + const isIconVisible1 = await page.isVisible(writeConfig_greenCheckXpath); + expect(isIconVisible1).toBe(false); + + await page.waitForSelector(uploadYaml_greenCheckXpath, { timeout: 50000 }); + const isIconVisible2 = await page.isVisible(uploadYaml_greenCheckXpath); + expect(isIconVisible2).toBe(false); + + await page.waitForSelector(init_apfauth_greenCheckXpath, { timeout: 50000 }); + const isIconVisible3 = await page.isVisible(init_apfauth_greenCheckXpath); + expect(isIconVisible3).toBe(false); + + const isButtonEnabled = await page.isEnabled(continue_security_setup); + expect(isButtonEnabled).toBe(false); +}); + +test('Test Skip APF Auth', async () => { + page = await electronApp.firstWindow(); + const is_skipInstallation_ButtonEnabled = await page.isEnabled(skip_installation_button); + expect(is_skipInstallation_ButtonEnabled).toBe(true); + await page.locator(skip_installation_button).click(); + const is_skipApfauth_ButtonEnabled = await page.isEnabled(skip_apf_auth_button); + expect(is_skipApfauth_ButtonEnabled).toBe(true); + await page.locator(skip_apf_auth_button).click(); + const security_title = await page.locator('//div[text()="Security"]').textContent(); + expect (security_title).toBe(SECURITY_TITLE) +}); + +test('Test Previous Step', async () => { + page = await electronApp.firstWindow(); + await page.locator(skip_installation_button).click(); + const apfauth_title = await page.locator('//div[text()="APF Authorize Load Libraries"]').textContent(); + expect (apfauth_title).toBe(APFAUTH_TITLE) + const isButtonEnabled = await page.isEnabled(previous_step_button); + expect(isButtonEnabled).toBe(true); + await page.locator(previous_step_button).click(); + const installation_title = await page.locator('//div[text()="Installation"]').textContent(); + expect (installation_title).toBe(INSTALLATION_TITLE) +}); + +test('Test View Yaml', async () => { + page = await electronApp.firstWindow(); + await page.waitForTimeout(2000); + await page.click('//button[contains(text(), "View Yaml")]'); + const editor_dialog = await page.waitForSelector(editor_title_element, { timeout: 5000 }); + expect(editor_dialog).toBeTruthy(); + await page.click('//button[contains(text(), "Close")]'); +}) + +test('Test View/Submit Job', async () => { + page = await electronApp.firstWindow(); + await page.waitForTimeout(2000); + await page.click('//button[contains(text(), "Preview Job")]'); + const editor_dialog = await page.waitForSelector(editor_title_element, { timeout: 5000 }); + expect(editor_dialog).toBeTruthy(); + await page.click('//button[contains(text(), "Close")]'); +}) + +test('Test View Job', async () => { + page = await electronApp.firstWindow(); + await page.waitForTimeout(2000); + await page.click('//button[contains(text(), "Submit Job")]'); + const editor_dialog = await page.waitForSelector(editor_title_element, { timeout: 5000 }); + expect(editor_dialog).toBeTruthy(); + await page.click('//button[contains(text(), "Close")]'); +}) + +test('Test Save & Close', async () => { + page = await electronApp.firstWindow(); + await page.locator('input[id="#/properties/prefix2-input"]').fill(DATASET_PREFIX); + await page.locator('input[id="#/properties/authLoadlib3-input"]').fill(AUTH_LOAD_LIB); + await page.locator('input[id="#/properties/authPluginLib3-input"]').fill(AUTH_PLUGIN_LIB); + await page.locator('//button[contains(text(),"Save & close")]').click(); + page.click('#card-install') + await page.locator(userNameInputSelector).fill(process.env.SSH_USER); + await page.getByLabel('Password').fill(process.env.SSH_PASSWD); + await page.getByLabel('Host').fill(process.env.SSH_HOST); + await page.getByLabel('FTP Port').fill(process.env.SSH_PORT); + await page.click('button.MuiButton-root') + await page.click(continueButtonSelector) + await page.locator("//button[contains(text(), 'Continue to Installation Options')]").click(); + await page.waitForTimeout(1000); + await page.locator("//button[contains(text(), 'License Agreement')]").click(); + await page.locator("//html/body/div[2]/div[3]/div/div[2]/button[1]").click(); + await page.locator("//button[contains(text(), 'Continue to Components Installation')]").click(); + await page.locator(skip_installation_button).click(); + + const dataset_prefix_value = await page.getByLabel('Dataset Prefix').textContent(); + const auth_load_lib_value = await page.getByLabel('APF Authorized Load Library').textContent(); + const auth_plugin_lib_value = await page.getByLabel('Zowe ZIS Plugins Load Library').textContent(); + expect(dataset_prefix_value).toBe(DATASET_PREFIX) + expect(auth_load_lib_value).toBe(AUTH_LOAD_LIB) + expect(auth_plugin_lib_value).toBe(AUTH_PLUGIN_LIB) +}); diff --git a/playwright_test/testConnectionTab.spec.ts b/playwright_test/testConnectionTab.spec.ts new file mode 100644 index 00000000..279919a5 --- /dev/null +++ b/playwright_test/testConnectionTab.spec.ts @@ -0,0 +1,100 @@ +const { test, expect } = require('@playwright/test') +import { ElectronApplication, Page, _electron as electron } from 'playwright' + + +let electronApp: ElectronApplication +let page: Page + +//selectors +const continueButtonSelector = '.MuiButton-containedPrimary.MuiButton-sizeMedium'; +const userNameInputSelector = 'label:has-text("User Name") + div input#standard-required'; +const greenCheckIconSelector = 'div svg.MuiSvgIcon-colorSuccess'; + +test.beforeAll(async () => { + electronApp = await electron.launch({ args: ['.webpack/main/index.js'] }) + electronApp.on('window', async (page) => { + const filename = page.url()?.split('/').pop() + console.log(`Window opened: ${filename}`) + page.on('pageerror', (error) => { + console.error(error) + }) + page.on('console', (msg) => { + console.log(msg.text()) + }) + page.click('#card-install') + }) + +}) + +test.afterAll(async () => { + await electronApp.close() +}) + + +test('Test Title', async () => { + page = await electronApp.firstWindow() + await page.waitForTimeout(2000); + const title = await page.title(); + expect(title).toBe("Zowe Enterprise Necessity"); +}) + + +test('Test Required Elements', async () => { + page = await electronApp.firstWindow() + await page.waitForTimeout(2000); + page = await electronApp.firstWindow() + const usernameInput = await page.waitForSelector(userNameInputSelector); + const passwordInput = await page.waitForSelector('#standard-password-input'); + const portInput = await page.waitForSelector('#standard-number'); + const hostInput = await page.waitForSelector('label:has-text("Host") + div input#standard-required'); + expect(usernameInput).toBeTruthy(); + expect(passwordInput).toBeTruthy(); + expect(portInput).toBeTruthy(); + expect(hostInput).toBeTruthy(); +}) + + +test('Test Continue Disable', async () => { + page = await electronApp.firstWindow() + await page.waitForTimeout(2000); + page = await electronApp.firstWindow() + const isButtonDisabled = await page.isDisabled(continueButtonSelector); + expect(isButtonDisabled).toBe(true); +}) + + +test('Test Invalid Credentials', async () => { + page = await electronApp.firstWindow() + await page.waitForTimeout(2000); + page = await electronApp.firstWindow() + await page.locator(userNameInputSelector).fill(process.env.SSH_USER); + await page.getByLabel('Password').fill('random'); + await page.getByLabel('Host').fill(process.env.SSH_HOST); + await page.getByLabel('FTP Port').fill(process.env.SSH_PORT); + await page.waitForTimeout(2000); + await page.click('button.MuiButton-root') + await page.waitForTimeout(1000); + const isGreenCheckIconVisible = await page.isHidden(greenCheckIconSelector); + expect(isGreenCheckIconVisible).toBe(true); + const isButtonDisabled = await page.isDisabled(continueButtonSelector); + expect(isButtonDisabled).toBe(true); +}) + + +test('Test Valid Credentials', async () => { + page = await electronApp.firstWindow() + await page.waitForTimeout(2000); + page = await electronApp.firstWindow() + await page.locator(userNameInputSelector).fill(process.env.SSH_USER); + await page.getByLabel('Password').fill(process.env.SSH_PASSWD); + await page.getByLabel('Host').fill(process.env.SSH_HOST); + await page.getByLabel('FTP Port').fill(process.env.SSH_PORT); + await page.waitForTimeout(2000); + await page.click('button.MuiButton-root') + await page.waitForTimeout(1000); + await page.waitForSelector(greenCheckIconSelector); + const isGreenCheckIconVisible = await page.isVisible(greenCheckIconSelector); + expect(isGreenCheckIconVisible).toBe(true); + const isButtonDisabled = await page.isDisabled(continueButtonSelector); + expect(isButtonDisabled).toBe(false); +}) diff --git a/playwright_test/testSecurityTab.spec.ts b/playwright_test/testSecurityTab.spec.ts new file mode 100644 index 00000000..5adda93e --- /dev/null +++ b/playwright_test/testSecurityTab.spec.ts @@ -0,0 +1,279 @@ +import { test, expect } from '@playwright/test'; +import { ElectronApplication, _electron as electron, Page } from 'playwright'; +let electronApp: ElectronApplication; +let page: Page; + +//selectors +const continueButtonSelector = '.MuiButton-containedPrimary.MuiButton-sizeMedium'; +const userNameInputSelector = 'label:has-text("User Name") + div input#standard-required'; +const greenCheckIconSelector = 'svg[data-testid="CheckCircleOutlineIcon"]'; +const mainXpath = '//html/body/div/div[2]/div/div[4]/div/form/div/div[3]/div[1]/div[3]/div/div[2]/div/div/div' +const writeConfig_greenCheckXpath = '#card-init-security-progress-card svg.MuiSvgIcon-colorSuccess' +const uploadYaml_greenCheckXpath = '#card-download-progress-card svg.MuiSvgIcon-colorSuccess' +const init_security_greenCheckXpath = '#card-success-progress-card svg.MuiSvgIcon-colorSuccess' +const Skip_SecuritySelector = '//button[contains(text(), "Skip")]' +const Continue_CertificateSelector = '//button[contains(text(), "Continue to Certificates Setup")]' +const Save_CloseSelector='//button[contains(text(), "Save & close")]' +const monacoEditor_Selector = '//*[@id="monaco-editor-container"]' +const Previous_buttonSelector='//button[contains(text(), "Previous step")]' + + +async function setupPlanning(page: Page) { + electronApp = await electron.launch({ args: ['.webpack/main/index.js'] }); + + electronApp.on('window', async (window) => { + const filename = window.url()?.split('/').pop(); + console.log(`Window opened: ${filename}`); + window.on('pageerror', (error) => { + console.error(error); + }); + window.on('console', (msg) => { + console.log(msg.text()); + }); + + await window.waitForSelector('#card-install'); + await window.click('#card-install').catch((error) => { + console.error("Error clicking '#card-install':", error); + }); + }); + page = await electronApp.firstWindow(); + await page.waitForTimeout(1000); + await page.locator(userNameInputSelector).fill(process.env.SSH_USER); + await page.getByLabel('Password').fill(process.env.SSH_PASSWD); + await page.getByLabel('Host').fill(process.env.SSH_HOST); + await page.getByLabel('FTP Port').fill(process.env.SSH_PORT); + await page.click('button.MuiButton-root') + await page.waitForTimeout(1000); + await page.waitForSelector(greenCheckIconSelector); + const isGreenCheckIconVisible = await page.isVisible(greenCheckIconSelector); + await page.click(continueButtonSelector) + await page.locator("//button[contains(text(), 'Save and validate')]").click(); + await page.waitForTimeout(5000); + await page.getByLabel('Run-time Directory (or installation location)').fill('/u/ts5223'); + await page.getByLabel('Workspace Directory').fill('/u/ts5223/workspace'); + await page.getByLabel('Extensions Directory').fill('/u/ts5223/extension'); + await page.getByLabel('Log Directory').fill('/u/ts5223/logs'); + await page.getByLabel('Rbac Profile Identifier').fill('1'); + await page.getByLabel('Job Name').fill('ZWEMVDHP'); + await page.getByLabel('Job Prefix').fill('ZWE'); + await page.getByLabel('Java location').fill('/rsusr/java/IBM/J8.0_64.sr7fp11'); + await page.getByLabel('Node.js location').fill('/proj/mvd/node/installs/node-v18.18.2-os390-s390x-202310180251'); + await page.getByLabel('z/OSMF Application Id').fill('IZUDFLT'); + await page.locator("//button[contains(text(), 'Validate locations')]").click(); + await page.waitForTimeout(2000); + await page.locator("//button[contains(text(), 'Continue to Installation Options')]").click(); +} + + +async function setupPage(page: Page) { + await setupPlanning(); + page = await electronApp.firstWindow(); + await page.waitForTimeout(1000); + await page.locator("//button[contains(text(), 'License Agreement')]").click(); + await page.locator("//html/body/div[2]/div[3]/div/div[2]/button[1]").click(); + await page.locator("//button[contains(text(), 'Continue to Components Installation')]").click(); + await page.locator("//button[contains(text(), 'Skip ')]").click(); + await page.locator("//button[contains(text(), 'Skip ')]").click(); +} + +test.beforeEach(async () => { + test.setTimeout(100000); + await setupPage(); +}); + +test.afterEach(async () => { + await electronApp.close() +}) + +test('Test Skip Security is enable', async () => { + page = await electronApp.firstWindow(); + const isButtonEnabled = await page.isEnabled(Skip_SecuritySelector); + expect(isButtonEnabled).toBe(true); +}) + +test('Test Previous button is enable', async () => { + page = await electronApp.firstWindow(); + const Prev_ButtonEnabled = await page.isEnabled(Previous_buttonSelector); + expect(Prev_ButtonEnabled).toBe(true); +}) + +test('Test click Previous button', async () => { + page = await electronApp.firstWindow(); + await page.locator(Previous_buttonSelector).click(); + await page.locator('span.MuiStepLabel-label:has-text("APF Authorize Load Libraries")'); + await page.waitForSelector(':has-text("APF Authorize Load Libraries")'); + const isApfTextVisible = await page.isVisible(':has-text("Certificates")'); + expect(isApfTextVisible).toBe(true); +}) + +test('Test click Skip Security', async () => { + page = await electronApp.firstWindow(); + await page.locator(Skip_SecuritySelector).click(); + await page.locator('span.MuiStepLabel-label:has-text("Certificates")'); + await page.waitForSelector(':has-text("Certificates")'); + const isCertificatesTextVisible = await page.isVisible(':has-text("Certificates")'); + expect(isCertificatesTextVisible).toBe(true); +}) + +test('Test Continue to certificate setup disable', async () => { + page = await electronApp.firstWindow() + await page.waitForTimeout(2000); + page = await electronApp.firstWindow() + const isButtonDisabled = await page.isDisabled(Continue_CertificateSelector); + expect(isButtonDisabled).toBe(true); +}) + +test('Test View Yaml should open Editor', async () => { + page = await electronApp.firstWindow(); + await page.waitForTimeout(2000); + await page.click('//button[contains(text(), "View Yaml")]'); + const editorContainer = await page.waitForSelector(monacoEditor_Selector, { timeout: 5000 }); + expect(editorContainer).toBeTruthy(); + await page.click('//button[contains(text(), "Close")]'); +}) + +test('Test View/Submit Job job should open Editor', async () => { + page = await electronApp.firstWindow(); + await page.waitForTimeout(2000); + await page.click('//button[contains(text(), "Preview Job")]'); + const editorContainer = await page.waitForSelector(monacoEditor_Selector, { timeout: 5000 }); + expect(editorContainer).toBeTruthy(); + await page.click('//button[contains(text(), "Close")]'); +}) + +test('Test View Job should open Editor', async () => { + page = await electronApp.firstWindow(); + await page.waitForTimeout(2000); + await page.click('//button[contains(text(), "Submit Job")]'); + const editorContainer = await page.waitForSelector(monacoEditor_Selector, { timeout: 5000 }); + expect(editorContainer).toBeTruthy(); + await page.click('//button[contains(text(), "Close")]'); +}) + +test('Test all required fields', async () => { + page = await electronApp.firstWindow(); + const Security_Product = await page.locator('input[role="combobox"]') + const admin = await page.getByLabel('Admin'); + const stc = await page.getByLabel('Stc'); + const sys_prog = await page.getByLabel('Sys Prog'); + const user_zis = await page.locator(mainXpath +'/div/div/div[2]/div/div/input'); + const user_zowe = await page.locator(mainXpath +'/div/div/div[1]/div/div/input'); + const aux = await page.getByLabel('Aux'); + const stc_zowe = await page.locator(mainXpath + '/div[1]/div/div[1]/div/div/input'); + const stc_zis = await page.locator(mainXpath + '/div[1]/div/div[2]/div/div/input'); + await page.waitForTimeout(1000); + expect(Security_Product).toBeTruthy(); + expect(admin).toBeTruthy(); + expect(stc).toBeTruthy(); + expect(sys_prog).toBeTruthy(); + expect(user_zis).toBeTruthy(); + expect(user_zowe).toBeTruthy(); + expect(aux).toBeTruthy(); + expect(stc_zowe).toBeTruthy(); + expect(stc_zis).toBeTruthy(); +}) + +test('Test Save and close button', async () => { + page = await electronApp.firstWindow(); + await page.locator('input[role="combobox"]').fill('RACF'); + await page.getByLabel('Admin').fill(process.env.SECURITY_ADMIN); + await page.getByLabel('Stc').fill(process.env.SECURITY_STC); + await page.locator(Save_CloseSelector).click(); + page.click('#card-install') + await page.locator(userNameInputSelector).fill(process.env.SSH_USER); + await page.getByLabel('Password').fill(process.env.SSH_PASSWD); + await page.getByLabel('Host').fill(process.env.SSH_HOST); + await page.getByLabel('FTP Port').fill(process.env.SSH_PORT); + await page.click('button.MuiButton-root') + await page.click(continueButtonSelector) + await page.locator("//button[contains(text(), 'Continue to Installation Options')]").click(); + await page.waitForTimeout(1000); + await page.locator("//button[contains(text(), 'License Agreement')]").click(); + await page.locator("//html/body/div[2]/div[3]/div/div[2]/button[1]").click(); + await page.locator("//button[contains(text(), 'Continue to Components Installation')]").click(); + await page.locator("//button[contains(text(), 'Skip ')]").click(); + await page.locator("//button[contains(text(), 'Skip ')]").click(); + const AdminText = await page.getByLabel('Admin').inputValue(); + const StcText = await page.getByLabel('Stc').inputValue(); + expect(AdminText).toBe(process.env.SECURITY_ADMIN); + expect(StcText).toBe(process.env.SECURITY_STC); +}); + +test('Test Continue Certificate setup enable after intialization', async () => { + page = await electronApp.firstWindow(); + await page.locator('input[role="combobox"]').fill('RACF'); + await page.getByLabel('Admin').fill(process.env.SECURITY_ADMIN); + await page.getByLabel('Stc').fill(process.env.SECURITY_STC); + await page.getByLabel('Sys Prog').fill(process.env.SECURITY_SYSPROG); + await page.locator(mainXpath +'/div/div/div[2]/div/div/input').fill(process.env.SECURITY_USER_ZIS); + await page.locator(mainXpath +'/div/div/div[1]/div/div/input').fill(process.env.SECURITY_USER_ZOWE); + await page.getByLabel('Aux').fill(process.env.SECURITY_AUX); + await page.locator(mainXpath + '/div[1]/div/div[1]/div/div/input').fill(process.env.SECURITY_STC_ZOWE); + await page.locator(mainXpath + '/div[1]/div/div[2]/div/div/input').fill(process.env.SECURITY_STC_ZIS); + await page.locator("//button[contains(text(), 'Initialize Security Config')]").click(); + await page.waitForSelector(writeConfig_greenCheckXpath, { timeout: 50000 }); + const isIconVisible1 = await page.isVisible(writeConfig_greenCheckXpath); + expect(isIconVisible1).toBe(true); + + await page.waitForSelector(uploadYaml_greenCheckXpath, { timeout: 50000 }); + const isIconVisible2 = await page.isVisible(uploadYaml_greenCheckXpath); + expect(isIconVisible2).toBe(true); + + await page.waitForSelector(init_security_greenCheckXpath, { timeout: 50000 }); + const isIconVisible3 = await page.isVisible(init_security_greenCheckXpath); + expect(isIconVisible3).toBe(true); + const ButtonDisabled = await page.isEnabled(Continue_CertificateSelector); + expect(ButtonDisabled).toBe(true); +}); + + +test('Test Security RACF Product', async () => { + page = await electronApp.firstWindow(); + await page.locator('input[role="combobox"]').fill('RACF'); + await page.getByLabel('Admin').fill(process.env.SECURITY_ADMIN); + await page.getByLabel('Stc').fill(process.env.SECURITY_STC); + await page.getByLabel('Sys Prog').fill(process.env.SECURITY_SYSPROG); + await page.locator(mainXpath +'/div/div/div[2]/div/div/input').fill(process.env.SECURITY_USER_ZIS); + await page.locator(mainXpath +'/div/div/div[1]/div/div/input').fill(process.env.SECURITY_USER_ZOWE); + await page.getByLabel('Aux').fill(process.env.SECURITY_AUX); + await page.locator(mainXpath + '/div[1]/div/div[1]/div/div/input').fill(process.env.SECURITY_STC_ZOWE); + await page.locator(mainXpath + '/div[1]/div/div[2]/div/div/input').fill(process.env.SECURITY_STC_ZIS); + await page.locator("//button[contains(text(), 'Initialize Security Config')]").click(); + await page.waitForSelector(writeConfig_greenCheckXpath, { timeout: 50000 }); + const isIconVisible1 = await page.isVisible(writeConfig_greenCheckXpath); + expect(isIconVisible1).toBe(true); + + await page.waitForSelector(uploadYaml_greenCheckXpath, { timeout: 50000 }); + const isIconVisible2 = await page.isVisible(uploadYaml_greenCheckXpath); + expect(isIconVisible2).toBe(true); + + await page.waitForSelector(init_security_greenCheckXpath, { timeout: 50000 }); + const isIconVisible3 = await page.isVisible(init_security_greenCheckXpath); + expect(isIconVisible3).toBe(true); +}); + + +test('Test with all fields empty', async () => { + page = await electronApp.firstWindow(); + await page.locator('input[role="combobox"]').fill(''); + await page.getByLabel('Admin').fill(''); + await page.getByLabel('Stc').fill(''); + await page.getByLabel('Sys Prog').fill(''); + await page.locator(mainXpath +'/div/div/div[2]/div/div/input').fill(''); + await page.locator(mainXpath +'/div/div/div[1]/div/div/input').fill(''); + await page.getByLabel('Aux').fill(''); + await page.locator(mainXpath + '/div[1]/div/div[1]/div/div/input').fill(''); + await page.locator(mainXpath + '/div[1]/div/div[2]/div/div/input').fill(''); + await page.locator("//button[contains(text(), 'Initialize Security Config')]").click(); + await page.waitForSelector(writeConfig_greenCheckXpath, { timeout: 50000 }); + const isIconVisible1 = await page.isVisible(writeConfig_greenCheckXpath); + expect(isIconVisible1).toBe(false); + + await page.waitForSelector(uploadYaml_greenCheckXpath, { timeout: 50000 }); + const isIconVisible2 = await page.isVisible(uploadYaml_greenCheckXpath); + expect(isIconVisible2).toBe(false); + + await page.waitForSelector(init_security_greenCheckXpath, { timeout: 50000 }); + const isIconVisible3 = await page.isVisible(init_security_greenCheckXpath); + expect(isIconVisible3).toBe(false); +}); \ No newline at end of file