From d34f1e81b49bd557c400616348569374bcd6b340 Mon Sep 17 00:00:00 2001 From: gee05053 Date: Tue, 28 Nov 2023 15:47:13 +0900 Subject: [PATCH 01/48] install cypress and make signin test --- cypress.config.ts | 16 +++++++++++ cypress/e2e/SiginInTest.cy.ts | 43 ++++++++++++++++++++++++++++ cypress/fixtures/example.json | 5 ++++ cypress/support/commands.ts | 37 ++++++++++++++++++++++++ cypress/support/component-index.html | 12 ++++++++ cypress/support/component.ts | 39 +++++++++++++++++++++++++ cypress/support/e2e.ts | 20 +++++++++++++ package.json | 4 ++- 8 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 cypress.config.ts create mode 100644 cypress/e2e/SiginInTest.cy.ts create mode 100644 cypress/fixtures/example.json create mode 100644 cypress/support/commands.ts create mode 100644 cypress/support/component-index.html create mode 100644 cypress/support/component.ts create mode 100644 cypress/support/e2e.ts diff --git a/cypress.config.ts b/cypress.config.ts new file mode 100644 index 0000000000..1471a7b825 --- /dev/null +++ b/cypress.config.ts @@ -0,0 +1,16 @@ +import { defineConfig } from "cypress"; + +export default defineConfig({ + e2e: { + setupNodeEvents(on, config) { + // implement node event listeners here + }, + }, + + component: { + devServer: { + framework: "react", + bundler: "webpack", + }, + }, +}); diff --git a/cypress/e2e/SiginInTest.cy.ts b/cypress/e2e/SiginInTest.cy.ts new file mode 100644 index 0000000000..fcd2b14232 --- /dev/null +++ b/cypress/e2e/SiginInTest.cy.ts @@ -0,0 +1,43 @@ +describe('Initial cypress E2E test', () => { + beforeEach(() => {// 테스트 실행하기 전 실행할 문구 + cy.visit('http://localhost:9081'); //방문할 페이지 + }); + + it('logininPage Component test', () => { + cy.get("backend-ai-webui[id='webui-shell']").shadow().within(() => { + cy.get("backend-ai-login[id='login-panel']").shadow().within(() => { + cy.get("backend-ai-dialog[id='login-panel']").should("exist").then((loginDialog) => { //loginDialog + cy.get(loginDialog).find("div[slot='title']").should("exist").then((title) => { //title + cy.get(title).find("div[class='horizontal center layout']").find("img[class='title-img']").should("exist"); //로고 image + }); + cy.get(loginDialog).find("div[slot='content']").should("exist").then((content) => { //content + cy.get(content).find("h3[class='horizontal center layout']").should("exist"); //E-mail로그인 + cy.get(content).find("div[class='horizontal flex layout login-input-without-trailing-icon']").should("exist"); //e-mail input + cy.get(content).find("div[class='horizontal flex layout']").should("exist"); //password input + cy.get(content).find("div[id='id_api_endpoint_container']").should("exist"); //endpoint + cy.get(content).find("mwc-button[id='login-button']").should("exist"); //siginIn buttton + }); + }); + }); + }); + }); + + it('login test', () => { + cy.get("backend-ai-webui[id='webui-shell']").shadow().within(() => { + cy.get("backend-ai-login[id='login-panel']").shadow().within(() => { + cy.get("backend-ai-dialog[id='login-panel']").should("exist").then((loginDialog) => { //loginDialog + cy.get(loginDialog).find("mwc-textfield[id='id_user_id']").shadow().within(()=>{ + cy.get("input[type='email']").should("exist").type("admin@lablup.com"); + }); + cy.get(loginDialog).find("mwc-textfield[id='id_password']").shadow().within(()=>{ + cy.get("input[type='password']").should("exist").type("wJalrXUt"); + }); + cy.get(loginDialog).find("mwc-textfield[id='id_api_endpoint']").shadow().within(()=>{ + cy.get("input[type='text']").should("exist").type("http://10.100.64.15:8090"); + }); + cy.get(loginDialog).find("mwc-button[id='login-button']").should("exist").click(); //siginIn buttton + }); + }); + }); + }); +}); \ No newline at end of file diff --git a/cypress/fixtures/example.json b/cypress/fixtures/example.json new file mode 100644 index 0000000000..02e4254378 --- /dev/null +++ b/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts new file mode 100644 index 0000000000..698b01a42c --- /dev/null +++ b/cypress/support/commands.ts @@ -0,0 +1,37 @@ +/// +// *********************************************** +// This example commands.ts shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) +// +// declare global { +// namespace Cypress { +// interface Chainable { +// login(email: string, password: string): Chainable +// drag(subject: string, options?: Partial): Chainable +// dismiss(subject: string, options?: Partial): Chainable +// visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable +// } +// } +// } \ No newline at end of file diff --git a/cypress/support/component-index.html b/cypress/support/component-index.html new file mode 100644 index 0000000000..ac6e79fd83 --- /dev/null +++ b/cypress/support/component-index.html @@ -0,0 +1,12 @@ + + + + + + + Components App + + +
+ + \ No newline at end of file diff --git a/cypress/support/component.ts b/cypress/support/component.ts new file mode 100644 index 0000000000..bd8ff0182d --- /dev/null +++ b/cypress/support/component.ts @@ -0,0 +1,39 @@ +// *********************************************************** +// This example support/component.ts is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') + +import { mount } from 'cypress/react' + +// Augment the Cypress namespace to include type definitions for +// your custom command. +// Alternatively, can be defined in cypress/support/component.d.ts +// with a at the top of your spec. +declare global { + namespace Cypress { + interface Chainable { + mount: typeof mount + } + } +} + +Cypress.Commands.add('mount', mount) + +// Example use: +// cy.mount() \ No newline at end of file diff --git a/cypress/support/e2e.ts b/cypress/support/e2e.ts new file mode 100644 index 0000000000..f80f74f8e1 --- /dev/null +++ b/cypress/support/e2e.ts @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/e2e.ts is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') \ No newline at end of file diff --git a/package.json b/package.json index d822565eba..7989bea224 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,8 @@ "update": "npx tsc", "postinstall": "npx concurrently -c \"auto\" --names \"react-dependencies\" \"cd react && npm install\"", "patch:lit-translate": "unzip -o ./scripts/lit-translate.zip -d ./node_modules/lit-translate && cp -f ./scripts/lit-translate-index.js ./node_modules/lit-translate/index.js", - "prepare": "husky install" + "prepare": "husky install", + "test:cypress": "cypress open" }, "dependencies": { "@material/mwc-button": "^0.27.0", @@ -69,6 +70,7 @@ "chart.js": "~4.4.0", "chartjs-adapter-date-fns": "^3.0.0", "commander": "^11.0.0", + "cypress": "^13.6.0", "date-fns": "^2.30.0", "dotenv": "^16.3.1", "drawflow": "^0.0.59", From 91234cf7a42b0f9074fd76131c47b5ffc80f7a9b Mon Sep 17 00:00:00 2001 From: gee05053 Date: Tue, 28 Nov 2023 16:44:52 +0900 Subject: [PATCH 02/48] change package-lock.json --- package-lock.json | 1343 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 1199 insertions(+), 144 deletions(-) diff --git a/package-lock.json b/package-lock.json index 856c64f158..cfc5351ad8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -47,6 +47,7 @@ "chart.js": "~4.4.0", "chartjs-adapter-date-fns": "^3.0.0", "commander": "^11.0.0", + "cypress": "^13.6.0", "date-fns": "^2.30.0", "dotenv": "^16.3.1", "drawflow": "^0.0.59", @@ -2139,6 +2140,65 @@ "node": ">=0.1.90" } }, + "node_modules/@cypress/request": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.1.tgz", + "integrity": "sha512-TWivJlJi8ZDx2wGOw1dbLuHJKUYX7bWySw377nlnGOW3hP9/MUKIsEdXT/YngWxVdgNCHRBmFlBipE+5/2ZZlQ==", + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "http-signature": "~1.3.6", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "performance-now": "^2.1.0", + "qs": "6.10.4", + "safe-buffer": "^5.1.2", + "tough-cookie": "^4.1.3", + "tunnel-agent": "^0.6.0", + "uuid": "^8.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@cypress/request/node_modules/qs": { + "version": "6.10.4", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.4.tgz", + "integrity": "sha512-OQiU+C+Ds5qiH91qh/mg0w+8nwQuLjM4F4M/PbmhDOoYehPh+Fb0bDjtR1sOvy7YKxvj28Y/M0PhP5uVX0kB+g==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/@cypress/xvfb": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@cypress/xvfb/-/xvfb-1.2.4.tgz", + "integrity": "sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==", + "dependencies": { + "debug": "^3.1.0", + "lodash.once": "^4.1.1" + } + }, + "node_modules/@cypress/xvfb/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, "node_modules/@dabh/diagnostics": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", @@ -4987,9 +5047,12 @@ "dev": true }, "node_modules/@types/node": { - "version": "18.15.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.3.tgz", - "integrity": "sha512-p6ua9zBxz5otCmbpb5D3U4B5Nanw6Pk3PPyX05xnxbB/fRv71N7CPmORg7uAD5P70T0xmx1pzAx/FUfa5X+3cw==" + "version": "18.18.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.13.tgz", + "integrity": "sha512-vXYZGRrSCreZmq1rEjMRLXJhiy8MrIeVasx+PCVlP414N7CJLHnMf+juVvjdprHyH+XRy3zKZLHeNueOpJCn0g==", + "dependencies": { + "undici-types": "~5.26.4" + } }, "node_modules/@types/parse5": { "version": "6.0.3", @@ -5046,6 +5109,16 @@ "@types/node": "*" } }, + "node_modules/@types/sinonjs__fake-timers": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz", + "integrity": "sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g==" + }, + "node_modules/@types/sizzle": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.8.tgz", + "integrity": "sha512-0vWLNK2D5MT9dg0iOo8GlKguPAU02QjmZitPEsXRuJXU/OGIOt9vT9Fc26wtYuavLxtO45v9PGleoL9Z0k1LHg==" + }, "node_modules/@types/triple-beam": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.2.tgz", @@ -5068,7 +5141,6 @@ "version": "2.10.0", "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz", "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==", - "dev": true, "optional": true, "dependencies": { "@types/node": "*" @@ -6433,11 +6505,18 @@ "node": ">=8" } }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "engines": { + "node": ">=6" + } + }, "node_modules/ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, "dependencies": { "type-fest": "^0.21.3" }, @@ -6452,7 +6531,6 @@ "version": "0.21.3", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, "engines": { "node": ">=10" }, @@ -6464,7 +6542,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "engines": { "node": ">=8" } @@ -6525,7 +6602,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", - "dev": true, "funding": [ { "type": "github", @@ -6676,6 +6752,14 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, "node_modules/asn1.js": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", @@ -6704,6 +6788,14 @@ "util": "0.10.3" } }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "engines": { + "node": ">=0.8" + } + }, "node_modules/assert/node_modules/inherits": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", @@ -6740,6 +6832,14 @@ "node": ">=4" } }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "engines": { + "node": ">=8" + } + }, "node_modules/async": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", @@ -6756,11 +6856,15 @@ "node": ">=0.12.0" } }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, "node_modules/at-least-node": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "dev": true, "engines": { "node": ">= 4.0.0" } @@ -6786,6 +6890,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", + "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==" + }, "node_modules/axe-core": { "version": "4.6.3", "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.6.3.tgz", @@ -6941,8 +7058,7 @@ "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "node_modules/base32-encode": { "version": "1.2.0", @@ -6958,7 +7074,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", @@ -6974,6 +7089,14 @@ } ] }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, "node_modules/before-after-hook": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", @@ -7048,6 +7171,11 @@ "node": ">= 6" } }, + "node_modules/blob-util": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz", + "integrity": "sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==" + }, "node_modules/blocking-elements": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/blocking-elements/-/blocking-elements-0.1.1.tgz", @@ -7056,8 +7184,7 @@ "node_modules/bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" }, "node_modules/bn.js": { "version": "5.2.1", @@ -7200,7 +7327,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -7554,7 +7680,6 @@ "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "dev": true, "engines": { "node": "*" } @@ -7738,11 +7863,18 @@ "integrity": "sha512-WF0LihfemtesFcJgO7xfOoOcnWzY/QHR4qeDqV44jPU3HTI54+LnfXK3SA27AVVGCdZFgjjFFaqUA9Jx7dMJZA==", "dev": true }, + "node_modules/cachedir": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.4.0.tgz", + "integrity": "sha512-9EtFOZR8g22CL7BWjJ9BUx1+A/djkofnyW3aOXZORNW2kxoUpx2h+uN2cOqwPmFhnpVmxg+KW2OjOSgChTEvsQ==", + "engines": { + "node": ">=6" + } + }, "node_modules/call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, "dependencies": { "function-bind": "^1.1.1", "get-intrinsic": "^1.0.2" @@ -7800,6 +7932,11 @@ } ] }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" + }, "node_modules/catharsis": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", @@ -7978,6 +8115,14 @@ "node": "*" } }, + "node_modules/check-more-types": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", + "integrity": "sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==", + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", @@ -8168,6 +8313,38 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/cli-table3": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz", + "integrity": "sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==", + "dependencies": { + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "@colors/colors": "1.5.0" + } + }, + "node_modules/cli-table3/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/cli-table3/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/cli-truncate": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz", @@ -8443,8 +8620,7 @@ "node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" }, "node_modules/colorspace": { "version": "1.1.4", @@ -8482,6 +8658,17 @@ "integrity": "sha512-Y8L5rp6jo+g9VEPgvqNfEopjTR4OTYct8lXlS8iVQdmnjDvbdbzYe9rjtFCB9egC86JoNCU61WRY+ScjkZpnIg==", "dev": true }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/command-line-args": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz", @@ -8555,7 +8742,6 @@ "version": "1.8.2", "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", - "dev": true, "engines": { "node": ">=4.0.0" } @@ -8644,8 +8830,7 @@ "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, "node_modules/concat-stream": { "version": "1.6.2", @@ -9015,7 +9200,6 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -9101,95 +9285,629 @@ "resolved": "https://registry.npmjs.org/custom-error-instance/-/custom-error-instance-2.1.1.tgz", "integrity": "sha512-p6JFxJc3M4OTD2li2qaHkDCw9SfMw82Ldr6OC9Je1aXiGfhx2W8p3GaoeaGrPJTUN9NirTM/KTxHWMUdR1rsUg==" }, - "node_modules/d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "node_modules/cypress": { + "version": "13.6.0", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.6.0.tgz", + "integrity": "sha512-quIsnFmtj4dBUEJYU4OH0H12bABJpSujvWexC24Ju1gTlKMJbeT6tTO0vh7WNfiBPPjoIXLN+OUqVtiKFs6SGw==", + "hasInstallScript": true, "dependencies": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, - "node_modules/dash-ast": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/dash-ast/-/dash-ast-2.0.1.tgz", - "integrity": "sha512-5TXltWJGc+RdnabUGzhRae1TRq6m4gr+3K2wQX0is5/F2yS6MJXJvLyI3ErAnsAXuJoGqvfVD5icRgim07DrxQ==", - "dev": true - }, - "node_modules/data-uri-to-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", - "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", - "dev": true, + "@cypress/request": "^3.0.0", + "@cypress/xvfb": "^1.2.4", + "@types/node": "^18.17.5", + "@types/sinonjs__fake-timers": "8.1.1", + "@types/sizzle": "^2.3.2", + "arch": "^2.2.0", + "blob-util": "^2.0.2", + "bluebird": "^3.7.2", + "buffer": "^5.6.0", + "cachedir": "^2.3.0", + "chalk": "^4.1.0", + "check-more-types": "^2.24.0", + "cli-cursor": "^3.1.0", + "cli-table3": "~0.6.1", + "commander": "^6.2.1", + "common-tags": "^1.8.0", + "dayjs": "^1.10.4", + "debug": "^4.3.4", + "enquirer": "^2.3.6", + "eventemitter2": "6.4.7", + "execa": "4.1.0", + "executable": "^4.1.1", + "extract-zip": "2.0.1", + "figures": "^3.2.0", + "fs-extra": "^9.1.0", + "getos": "^3.2.1", + "is-ci": "^3.0.0", + "is-installed-globally": "~0.4.0", + "lazy-ass": "^1.6.0", + "listr2": "^3.8.3", + "lodash": "^4.17.21", + "log-symbols": "^4.0.0", + "minimist": "^1.2.8", + "ospath": "^1.2.2", + "pretty-bytes": "^5.6.0", + "process": "^0.11.10", + "proxy-from-env": "1.0.0", + "request-progress": "^3.0.0", + "semver": "^7.5.3", + "supports-color": "^8.1.1", + "tmp": "~0.2.1", + "untildify": "^4.0.0", + "yauzl": "^2.10.0" + }, + "bin": { + "cypress": "bin/cypress" + }, "engines": { - "node": ">= 12" + "node": "^16.0.0 || ^18.0.0 || >=20.0.0" } }, - "node_modules/date-fns": { - "version": "2.30.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", - "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "node_modules/cypress/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dependencies": { - "@babel/runtime": "^7.21.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=0.11" + "node": ">=8" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/date-fns" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/de-indent": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", - "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==", - "dev": true - }, - "node_modules/debounce": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", - "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==", - "dev": true + "node_modules/cypress/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "node_modules/cypress/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dependencies": { - "ms": "2.1.2" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=6.0" + "node": ">=10" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "dev": true, + "node_modules/cypress/node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "dev": true, + "node_modules/cypress/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/cypress/node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", "dependencies": { - "mimic-response": "^3.1.0" + "restore-cursor": "^3.1.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" + } + }, + "node_modules/cypress/node_modules/cli-truncate": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "dependencies": { + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cypress/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/cypress/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/cypress/node_modules/commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/cypress/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/cypress/node_modules/execa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", + "dependencies": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/cypress/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cypress/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cypress/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/cypress/node_modules/human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", + "engines": { + "node": ">=8.12.0" + } + }, + "node_modules/cypress/node_modules/is-ci": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", + "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", + "dependencies": { + "ci-info": "^3.2.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/cypress/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/cypress/node_modules/listr2": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.14.0.tgz", + "integrity": "sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g==", + "dependencies": { + "cli-truncate": "^2.1.0", + "colorette": "^2.0.16", + "log-update": "^4.0.0", + "p-map": "^4.0.0", + "rfdc": "^1.3.0", + "rxjs": "^7.5.1", + "through": "^2.3.8", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "enquirer": ">= 2.3.0 < 3" + }, + "peerDependenciesMeta": { + "enquirer": { + "optional": true + } + } + }, + "node_modules/cypress/node_modules/log-update": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", + "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", + "dependencies": { + "ansi-escapes": "^4.3.0", + "cli-cursor": "^3.1.0", + "slice-ansi": "^4.0.0", + "wrap-ansi": "^6.2.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cypress/node_modules/log-update/node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/cypress/node_modules/log-update/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cypress/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cypress/node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "node_modules/cypress/node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/cypress/node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cypress/node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cypress/node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cypress/node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cypress/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cypress/node_modules/slice-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cypress/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cypress/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/cypress/node_modules/tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dependencies": { + "rimraf": "^3.0.0" + }, + "engines": { + "node": ">=8.17.0" + } + }, + "node_modules/cypress/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/cypress/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/cypress/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dependencies": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "node_modules/dash-ast": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/dash-ast/-/dash-ast-2.0.1.tgz", + "integrity": "sha512-5TXltWJGc+RdnabUGzhRae1TRq6m4gr+3K2wQX0is5/F2yS6MJXJvLyI3ErAnsAXuJoGqvfVD5icRgim07DrxQ==", + "dev": true + }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/date-fns": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "dependencies": { + "@babel/runtime": "^7.21.0" + }, + "engines": { + "node": ">=0.11" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/date-fns" + } + }, + "node_modules/dayjs": { + "version": "1.11.10", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", + "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==" + }, + "node_modules/de-indent": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", + "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==", + "dev": true + }, + "node_modules/debounce": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", + "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==", + "dev": true + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/decompress-response/node_modules/mimic-response": { @@ -9403,6 +10121,14 @@ "rimraf": "bin.js" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", @@ -9692,6 +10418,15 @@ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, "node_modules/ecdsa-sig-formatter": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", @@ -10121,7 +10856,6 @@ "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, "dependencies": { "once": "^1.4.0" } @@ -10170,6 +10904,18 @@ "node": ">=10.13.0" } }, + "node_modules/enquirer": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", + "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", + "dependencies": { + "ansi-colors": "^4.1.1", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8.6" + } + }, "node_modules/ensure-type": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/ensure-type/-/ensure-type-1.5.1.tgz", @@ -11108,6 +11854,11 @@ "es5-ext": "~0.10.14" } }, + "node_modules/eventemitter2": { + "version": "6.4.7", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.7.tgz", + "integrity": "sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg==" + }, "node_modules/eventemitter3": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", @@ -11248,6 +11999,25 @@ "which": "bin/which" } }, + "node_modules/executable": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz", + "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==", + "dependencies": { + "pify": "^2.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/executable/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/expand-template": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", @@ -11327,11 +12097,15 @@ "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==" }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, "node_modules/extract-zip": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "dev": true, "dependencies": { "debug": "^4.1.1", "get-stream": "^5.1.0", @@ -11351,7 +12125,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, "dependencies": { "pump": "^3.0.0" }, @@ -11362,6 +12135,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "engines": [ + "node >=0.6.0" + ] + }, "node_modules/falafel": { "version": "2.2.5", "resolved": "https://registry.npmjs.org/falafel/-/falafel-2.2.5.tgz", @@ -11464,7 +12245,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", - "dev": true, "dependencies": { "pend": "~1.2.0" } @@ -11497,6 +12277,20 @@ "node": "^12.20 || >= 14.13" } }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -11760,6 +12554,27 @@ "node": ">=8.0.0" } }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "engines": { + "node": "*" + } + }, + "node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, "node_modules/formdata-polyfill": { "version": "4.0.10", "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", @@ -11868,8 +12683,7 @@ "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, "node_modules/fsevents": { "version": "2.3.2", @@ -11887,8 +12701,7 @@ "node_modules/function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "node_modules/function.prototype.name": { "version": "1.1.5", @@ -12041,7 +12854,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", - "dev": true, "dependencies": { "function-bind": "^1.1.1", "has": "^1.0.3", @@ -12139,7 +12951,6 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/getos/-/getos-3.2.1.tgz", "integrity": "sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==", - "dev": true, "dependencies": { "async": "^3.2.0" } @@ -12147,8 +12958,15 @@ "node_modules/getos/node_modules/async": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", - "dev": true + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" + }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "dependencies": { + "assert-plus": "^1.0.0" + } }, "node_modules/github-from-package": { "version": "0.0.0", @@ -12298,6 +13116,28 @@ "dev": true, "optional": true }, + "node_modules/global-dirs": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", + "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", + "dependencies": { + "ini": "2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/global-dirs/node_modules/ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "engines": { + "node": ">=10" + } + }, "node_modules/globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -12411,7 +13251,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, "dependencies": { "function-bind": "^1.1.1" }, @@ -12678,6 +13517,19 @@ "node": ">= 0.8" } }, + "node_modules/http-signature": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.6.tgz", + "integrity": "sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==", + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^2.0.2", + "sshpk": "^1.14.1" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/http-status-codes": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/http-status-codes/-/http-status-codes-2.2.0.tgz", @@ -12994,7 +13846,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", @@ -13128,7 +13979,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -13443,7 +14293,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } @@ -13473,6 +14322,21 @@ "node": ">=0.10.0" } }, + "node_modules/is-installed-globally": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", + "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", + "dependencies": { + "global-dirs": "^3.0.0", + "is-path-inside": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-jquery-obj": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-jquery-obj/-/is-jquery-obj-0.1.1.tgz", @@ -13605,7 +14469,6 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, "engines": { "node": ">=8" } @@ -13780,6 +14643,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-utf8": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", @@ -13870,8 +14749,7 @@ "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, "node_modules/isobject": { "version": "3.0.1", @@ -13882,6 +14760,11 @@ "node": ">=0.10.0" } }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" + }, "node_modules/istanbul-lib-coverage": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", @@ -14131,6 +15014,11 @@ "xmlcreate": "^2.0.4" } }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" + }, "node_modules/jsdoc": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.2.tgz", @@ -14219,8 +15107,7 @@ "node_modules/json-schema": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", - "dev": true + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" }, "node_modules/json-schema-traverse": { "version": "0.4.1", @@ -14237,9 +15124,7 @@ "node_modules/json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "dev": true, - "optional": true + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" }, "node_modules/json5": { "version": "2.2.3", @@ -14340,6 +15225,20 @@ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, + "node_modules/jsprim": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", + "integrity": "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==", + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + } + }, "node_modules/jstransformer": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz", @@ -14614,6 +15513,14 @@ "language-subtag-registry": "^0.3.20" } }, + "node_modules/lazy-ass": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz", + "integrity": "sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==", + "engines": { + "node": "> 0.8" + } + }, "node_modules/lazy-cache": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", @@ -15032,6 +15939,11 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, "node_modules/lodash.sortby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", @@ -15066,6 +15978,85 @@ "uni-global": "^1.0.0" } }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-symbols/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/log-symbols/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/log-symbols/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/log-symbols/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/log-update": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/log-update/-/log-update-5.0.1.tgz", @@ -15700,7 +16691,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -15712,7 +16702,6 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -16214,7 +17203,6 @@ "version": "1.12.3", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -16417,6 +17405,11 @@ "node": ">=0.10.0" } }, + "node_modules/ospath": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz", + "integrity": "sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA==" + }, "node_modules/p-cancelable": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", @@ -16629,7 +17622,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "engines": { "node": ">=8" } @@ -16692,8 +17684,12 @@ "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 + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==" + }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" }, "node_modules/picocolors": { "version": "1.0.0", @@ -17428,7 +18424,6 @@ "version": "5.6.0", "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", - "dev": true, "engines": { "node": ">=6" }, @@ -17458,7 +18453,6 @@ "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", - "dev": true, "engines": { "node": ">= 0.6.0" } @@ -17543,6 +18537,11 @@ "node": ">= 0.10" } }, + "node_modules/proxy-from-env": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", + "integrity": "sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A==" + }, "node_modules/pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", @@ -17552,8 +18551,7 @@ "node_modules/psl": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", - "dev": true + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" }, "node_modules/public-encrypt": { "version": "4.0.3", @@ -17705,7 +18703,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -18389,6 +19386,14 @@ "integrity": "sha512-saxS4y7NFkLMa92BR4bPHR41GD+f/qoDAwD2xZmN+MpDXgibkxwLO2qk7dCHYtskSkd/bWS8Jy6kC5MZUkg1tw==", "dev": true }, + "node_modules/request-progress": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz", + "integrity": "sha512-MnWzEHHaxHO2iWiQuHrUPBi/1WeBf5PkxQqNyNvLl9VAYSdXkP8tQ3pBSeCPD+yw0v0Aq1zosWLz0BdeXpWwZg==", + "dependencies": { + "throttleit": "^1.0.0" + } + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -18626,8 +19631,7 @@ "node_modules/rfdc": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", - "dev": true + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" }, "node_modules/right-align": { "version": "0.1.3", @@ -18645,7 +19649,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, "dependencies": { "glob": "^7.1.3" }, @@ -18660,7 +19663,6 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -18758,7 +19760,6 @@ "version": "7.8.1", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "dev": true, "dependencies": { "tslib": "^2.1.0" } @@ -18807,8 +19808,7 @@ "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/sanitize-filename": { "version": "1.6.3", @@ -19141,7 +20141,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -19153,7 +20152,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "engines": { "node": ">=8" } @@ -19171,7 +20169,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, "dependencies": { "call-bind": "^1.0.0", "get-intrinsic": "^1.0.2", @@ -19405,6 +20402,30 @@ "es5-ext": "^0.10.53" } }, + "node_modules/sshpk": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", + "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/stack-trace": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", @@ -19722,7 +20743,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -19762,7 +20782,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, "engines": { "node": ">=6" } @@ -21007,11 +22026,18 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, + "node_modules/throttleit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.1.tgz", + "integrity": "sha512-vDZpf9Chs9mAdfY046mcPt8fg5QSZr37hEH4TXYBnDF+izxgrbRGUAAaBvIk/fJm9aOFCGFd1EsNg5AZCbnQCQ==", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" }, "node_modules/through2": { "version": "2.0.5", @@ -21241,7 +22267,6 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", - "dev": true, "dependencies": { "psl": "^1.1.33", "punycode": "^2.1.1", @@ -21256,7 +22281,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", - "dev": true, "engines": { "node": ">=6" } @@ -21265,7 +22289,6 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", - "dev": true, "engines": { "node": ">= 4.0.0" } @@ -21420,7 +22443,6 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", - "dev": true, "dependencies": { "safe-buffer": "^5.0.1" }, @@ -21442,6 +22464,11 @@ "url-parse": "^1.5.7" } }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" + }, "node_modules/type": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", @@ -21714,6 +22741,11 @@ "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==", "dev": true }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, "node_modules/uni-global": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/uni-global/-/uni-global-1.0.0.tgz", @@ -21827,6 +22859,14 @@ "integrity": "sha512-vRCqFv6UhXpWxZPyGDh/F3ZpNv8/qo7w6iufLpQg9aKnQ71qM4B5KiI7Mia9COcjEhrO9LueHpMYjYzsWH3OIg==", "dev": true }, + "node_modules/untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "engines": { + "node": ">=8" + } + }, "node_modules/upath": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", @@ -21977,7 +23017,6 @@ "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "peer": true, "bin": { "uuid": "dist/bin/uuid" } @@ -22023,6 +23062,24 @@ "node": ">= 0.8" } }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/verror/node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" + }, "node_modules/vinyl": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-3.0.0.tgz", @@ -22448,7 +23505,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -23508,7 +24564,6 @@ "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", - "dev": true, "dependencies": { "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" From a968fa8ace631de824bc39eccb7050ecbe154519 Mon Sep 17 00:00:00 2001 From: gee05053 Date: Wed, 29 Nov 2023 12:36:02 +0900 Subject: [PATCH 03/48] add changeProfile test --- cypress/e2e/ChangeProfileTest.cy.ts | 60 +++++++++++++++++++++++++++++ cypress/e2e/SiginInTest.cy.ts | 43 --------------------- 2 files changed, 60 insertions(+), 43 deletions(-) create mode 100644 cypress/e2e/ChangeProfileTest.cy.ts delete mode 100644 cypress/e2e/SiginInTest.cy.ts diff --git a/cypress/e2e/ChangeProfileTest.cy.ts b/cypress/e2e/ChangeProfileTest.cy.ts new file mode 100644 index 0000000000..809a96dc68 --- /dev/null +++ b/cypress/e2e/ChangeProfileTest.cy.ts @@ -0,0 +1,60 @@ +describe('Initial cypress E2E test', () => { + beforeEach(() => { + cy.viewport(1280,800) + cy.visit('http://localhost:9081'); //방문할 페이지 + }) + + it('Admin-user-profile change', () => { + cy.get("backend-ai-webui[id='webui-shell']").shadow().within(() => { + cy.get("backend-ai-login[id='login-panel']").shadow().within(() => { //로그인 + cy.get("mwc-textfield[id='id_user_id']").shadow().within(() => { //email input + cy.get("input[type='email']").type("admin@lablup.com"); + }); + cy.get("mwc-textfield[id='id_password']").shadow().within(() => { //password input + cy.get("input[type='password']").type("wJalrXUt"); + }); + cy.get("mwc-textfield[id='id_api_endpoint']").shadow().within(() => { //endpoint input + cy.get("input[type='text']").type("http://127.0.0.1:8090"); + }); + cy.get("mwc-button[id='login-button']").click(); //siginIn buttton + }); + cy.get("mwc-list-item:contains('사용자')").click() + cy.get("backend-ai-credential-view").shadow().within(() => { + cy.get("backend-ai-user-list[id='active-user-list']").shadow().within(() => { + cy.get("vaadin-grid-cell-content[slot='vaadin-grid-cell-content-15']").within(() => { + cy.get("mwc-icon-button[icon='settings']").click(); + }); + cy.get("backend-ai-react-user-setting-dialog").shadow().within(() => { + cy.get("input[id='password']").focus().type("test123@"); + cy.wait(500); + cy.get("input[id='password_confirm']").focus().type("test123@"); + cy.get("button:contains('확인')").click(); + }); + }); + }); + cy.get("backend-ai-react-user-dropdown-menu").trigger("click").then((dropdownMenu) => { + cy.get(dropdownMenu).shadow().within(() => { + cy.get("li:contains('로그아웃')").click(); + }); + }); + }); + }); + + it('test user login test', () => { + cy.get("backend-ai-webui[id='webui-shell']").shadow().within(() => { //로그인 + cy.get("backend-ai-login[id='login-panel']").shadow().within(() => { + cy.get("mwc-textfield[id='id_user_id']").shadow().within(() => { + cy.get("input[type='email']").type("test@lablup.com"); + }); + cy.get("mwc-textfield[id='id_password']").shadow().within(() => { + cy.get("input[type='password']").type("test123@"); + }); + cy.get("mwc-textfield[id='id_api_endpoint']").shadow().within(() => { //endpoint input + cy.get("input[type='text']").type("http://127.0.0.1:8090"); + }); + cy.get("mwc-button[id='login-button']").click(); + }); + cy.get("mwc-drawer[style='visibility: visible; --mdc-drawer-width: 250px;']").should("exist"); + }); + }); +}); \ No newline at end of file diff --git a/cypress/e2e/SiginInTest.cy.ts b/cypress/e2e/SiginInTest.cy.ts deleted file mode 100644 index fcd2b14232..0000000000 --- a/cypress/e2e/SiginInTest.cy.ts +++ /dev/null @@ -1,43 +0,0 @@ -describe('Initial cypress E2E test', () => { - beforeEach(() => {// 테스트 실행하기 전 실행할 문구 - cy.visit('http://localhost:9081'); //방문할 페이지 - }); - - it('logininPage Component test', () => { - cy.get("backend-ai-webui[id='webui-shell']").shadow().within(() => { - cy.get("backend-ai-login[id='login-panel']").shadow().within(() => { - cy.get("backend-ai-dialog[id='login-panel']").should("exist").then((loginDialog) => { //loginDialog - cy.get(loginDialog).find("div[slot='title']").should("exist").then((title) => { //title - cy.get(title).find("div[class='horizontal center layout']").find("img[class='title-img']").should("exist"); //로고 image - }); - cy.get(loginDialog).find("div[slot='content']").should("exist").then((content) => { //content - cy.get(content).find("h3[class='horizontal center layout']").should("exist"); //E-mail로그인 - cy.get(content).find("div[class='horizontal flex layout login-input-without-trailing-icon']").should("exist"); //e-mail input - cy.get(content).find("div[class='horizontal flex layout']").should("exist"); //password input - cy.get(content).find("div[id='id_api_endpoint_container']").should("exist"); //endpoint - cy.get(content).find("mwc-button[id='login-button']").should("exist"); //siginIn buttton - }); - }); - }); - }); - }); - - it('login test', () => { - cy.get("backend-ai-webui[id='webui-shell']").shadow().within(() => { - cy.get("backend-ai-login[id='login-panel']").shadow().within(() => { - cy.get("backend-ai-dialog[id='login-panel']").should("exist").then((loginDialog) => { //loginDialog - cy.get(loginDialog).find("mwc-textfield[id='id_user_id']").shadow().within(()=>{ - cy.get("input[type='email']").should("exist").type("admin@lablup.com"); - }); - cy.get(loginDialog).find("mwc-textfield[id='id_password']").shadow().within(()=>{ - cy.get("input[type='password']").should("exist").type("wJalrXUt"); - }); - cy.get(loginDialog).find("mwc-textfield[id='id_api_endpoint']").shadow().within(()=>{ - cy.get("input[type='text']").should("exist").type("http://10.100.64.15:8090"); - }); - cy.get(loginDialog).find("mwc-button[id='login-button']").should("exist").click(); //siginIn buttton - }); - }); - }); - }); -}); \ No newline at end of file From af235bd2238f80f81e3a09072193b5b6e3e775d6 Mon Sep 17 00:00:00 2001 From: gee05053 Date: Thu, 30 Nov 2023 23:24:34 +0900 Subject: [PATCH 04/48] modify code more simply --- cypress/commands/LoginPage.cy.ts | 10 +++++ cypress/commands/UserDropdown.cy.ts | 24 ++++++++++++ cypress/e2e/ChangeProfileTest.cy.ts | 60 ----------------------------- cypress/e2e/e2eTest.cy.ts | 20 ++++++++++ cypress/helper/FindShadowRoot.cy.ts | 12 ++++++ 5 files changed, 66 insertions(+), 60 deletions(-) create mode 100644 cypress/commands/LoginPage.cy.ts create mode 100644 cypress/commands/UserDropdown.cy.ts delete mode 100644 cypress/e2e/ChangeProfileTest.cy.ts create mode 100644 cypress/e2e/e2eTest.cy.ts create mode 100644 cypress/helper/FindShadowRoot.cy.ts diff --git a/cypress/commands/LoginPage.cy.ts b/cypress/commands/LoginPage.cy.ts new file mode 100644 index 0000000000..e9cd1de847 --- /dev/null +++ b/cypress/commands/LoginPage.cy.ts @@ -0,0 +1,10 @@ +import {findShadowRoot} from '../helper/FindShadowRoot.cy'; + +Cypress.Commands.add('login', (email, password) => { + const emailInput = findShadowRoot("backend-ai-webui > backend-ai-login > #id_user_id").find("input"); + const passwordInput = findShadowRoot("backend-ai-webui > backend-ai-login > #id_password").find("input"); + const loginButton = findShadowRoot("backend-ai-webui > backend-ai-login > #login-button").find("button"); + emailInput.type(email); + passwordInput.type(password); + loginButton.click(); +}); \ No newline at end of file diff --git a/cypress/commands/UserDropdown.cy.ts b/cypress/commands/UserDropdown.cy.ts new file mode 100644 index 0000000000..a41e60d826 --- /dev/null +++ b/cypress/commands/UserDropdown.cy.ts @@ -0,0 +1,24 @@ +import { cy } from 'date-fns/locale'; +import {findShadowRoot} from '../helper/FindShadowRoot.cy'; + +Cypress.Commands.add('userProfileChange', (userName, originalPassword, newPassword) => { + findShadowRoot("backend-ai-webui").find("backend-ai-react-user-dropdown-menu").trigger("click").then(() =>{ + findShadowRoot("backend-ai-webui > backend-ai-react-user-dropdown-menu").find("li:contains(사용자 정보 변경)").click(); + }); + findShadowRoot("backend-ai-webui > backend-ai-react-user-profile-setting-dialog") + .find("#full_name").clear().focus().type(userName); + findShadowRoot("backend-ai-webui > backend-ai-react-user-profile-setting-dialog") + .find("#originalPassword").focus().type(originalPassword); + findShadowRoot("backend-ai-webui > backend-ai-react-user-profile-setting-dialog") + .find("#newPassword").focus().type(newPassword); + findShadowRoot("backend-ai-webui > backend-ai-react-user-profile-setting-dialog") + .find("#newPasswordConfirm").focus().type(newPassword); + findShadowRoot("backend-ai-webui > backend-ai-react-user-profile-setting-dialog") + .find("button:contains(변경)").click(); +}); + +Cypress.Commands.add('logout', () => { + findShadowRoot("backend-ai-webui").find("backend-ai-react-user-dropdown-menu").trigger("click").then(() =>{ + findShadowRoot("backend-ai-webui > backend-ai-react-user-dropdown-menu").find("li:contains(로그아웃)").click(); + }); +}) \ No newline at end of file diff --git a/cypress/e2e/ChangeProfileTest.cy.ts b/cypress/e2e/ChangeProfileTest.cy.ts deleted file mode 100644 index 809a96dc68..0000000000 --- a/cypress/e2e/ChangeProfileTest.cy.ts +++ /dev/null @@ -1,60 +0,0 @@ -describe('Initial cypress E2E test', () => { - beforeEach(() => { - cy.viewport(1280,800) - cy.visit('http://localhost:9081'); //방문할 페이지 - }) - - it('Admin-user-profile change', () => { - cy.get("backend-ai-webui[id='webui-shell']").shadow().within(() => { - cy.get("backend-ai-login[id='login-panel']").shadow().within(() => { //로그인 - cy.get("mwc-textfield[id='id_user_id']").shadow().within(() => { //email input - cy.get("input[type='email']").type("admin@lablup.com"); - }); - cy.get("mwc-textfield[id='id_password']").shadow().within(() => { //password input - cy.get("input[type='password']").type("wJalrXUt"); - }); - cy.get("mwc-textfield[id='id_api_endpoint']").shadow().within(() => { //endpoint input - cy.get("input[type='text']").type("http://127.0.0.1:8090"); - }); - cy.get("mwc-button[id='login-button']").click(); //siginIn buttton - }); - cy.get("mwc-list-item:contains('사용자')").click() - cy.get("backend-ai-credential-view").shadow().within(() => { - cy.get("backend-ai-user-list[id='active-user-list']").shadow().within(() => { - cy.get("vaadin-grid-cell-content[slot='vaadin-grid-cell-content-15']").within(() => { - cy.get("mwc-icon-button[icon='settings']").click(); - }); - cy.get("backend-ai-react-user-setting-dialog").shadow().within(() => { - cy.get("input[id='password']").focus().type("test123@"); - cy.wait(500); - cy.get("input[id='password_confirm']").focus().type("test123@"); - cy.get("button:contains('확인')").click(); - }); - }); - }); - cy.get("backend-ai-react-user-dropdown-menu").trigger("click").then((dropdownMenu) => { - cy.get(dropdownMenu).shadow().within(() => { - cy.get("li:contains('로그아웃')").click(); - }); - }); - }); - }); - - it('test user login test', () => { - cy.get("backend-ai-webui[id='webui-shell']").shadow().within(() => { //로그인 - cy.get("backend-ai-login[id='login-panel']").shadow().within(() => { - cy.get("mwc-textfield[id='id_user_id']").shadow().within(() => { - cy.get("input[type='email']").type("test@lablup.com"); - }); - cy.get("mwc-textfield[id='id_password']").shadow().within(() => { - cy.get("input[type='password']").type("test123@"); - }); - cy.get("mwc-textfield[id='id_api_endpoint']").shadow().within(() => { //endpoint input - cy.get("input[type='text']").type("http://127.0.0.1:8090"); - }); - cy.get("mwc-button[id='login-button']").click(); - }); - cy.get("mwc-drawer[style='visibility: visible; --mdc-drawer-width: 250px;']").should("exist"); - }); - }); -}); \ No newline at end of file diff --git a/cypress/e2e/e2eTest.cy.ts b/cypress/e2e/e2eTest.cy.ts new file mode 100644 index 0000000000..07723a3fa9 --- /dev/null +++ b/cypress/e2e/e2eTest.cy.ts @@ -0,0 +1,20 @@ +import '../commands/LoginPage.cy'; +import '../commands/UserDropdown.cy'; + +describe('Initial cypress E2E test', () => { + beforeEach(() => { + cy.viewport(1280,800); + cy.visit('http://localhost:9081'); //방문할 페이지 + }); + + it('user profile change test', () => { + cy.login("test@lablup.com", "test123!").then(() => { + cy.wait(4000); + cy.userProfileChange("test", "test123!", "test123@").then(() =>{ + cy.logout().then(() => { + cy.login("test@lablup.com", "test123@"); + }); + }) + }); + }); +}); \ No newline at end of file diff --git a/cypress/helper/FindShadowRoot.cy.ts b/cypress/helper/FindShadowRoot.cy.ts new file mode 100644 index 0000000000..046ce4f146 --- /dev/null +++ b/cypress/helper/FindShadowRoot.cy.ts @@ -0,0 +1,12 @@ +export const findShadowRoot = (routes) => { + const segments = routes.split(">").map((route) => route.trim()); + let element = cy.get(segments[0]).shadow(); + for (const [idx,segment] of segments.entries()) { + if (idx === 0) { + continue + } else { + element = element.find(segment).shadow(); + } + } + return element; +}; \ No newline at end of file From 19fdf8f82746fae6d7b5eee901ad4a9d7a5abd86 Mon Sep 17 00:00:00 2001 From: gee05053 Date: Thu, 30 Nov 2023 23:25:33 +0900 Subject: [PATCH 05/48] delete unused import --- cypress/commands/UserDropdown.cy.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/cypress/commands/UserDropdown.cy.ts b/cypress/commands/UserDropdown.cy.ts index a41e60d826..9d5e790047 100644 --- a/cypress/commands/UserDropdown.cy.ts +++ b/cypress/commands/UserDropdown.cy.ts @@ -1,4 +1,3 @@ -import { cy } from 'date-fns/locale'; import {findShadowRoot} from '../helper/FindShadowRoot.cy'; Cypress.Commands.add('userProfileChange', (userName, originalPassword, newPassword) => { From 883e761898318383116ff381820480a711f3d2df Mon Sep 17 00:00:00 2001 From: gee05053 Date: Mon, 4 Dec 2023 09:49:21 +0900 Subject: [PATCH 06/48] change test account --- cypress/e2e/e2eTest.cy.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cypress/e2e/e2eTest.cy.ts b/cypress/e2e/e2eTest.cy.ts index 07723a3fa9..857ebe3d44 100644 --- a/cypress/e2e/e2eTest.cy.ts +++ b/cypress/e2e/e2eTest.cy.ts @@ -8,11 +8,11 @@ describe('Initial cypress E2E test', () => { }); it('user profile change test', () => { - cy.login("test@lablup.com", "test123!").then(() => { + cy.login("test2@lablup.com", "test123!").then(() => { cy.wait(4000); - cy.userProfileChange("test", "test123!", "test123@").then(() =>{ + cy.userProfileChange("test2222", "test123!", "test123@").then(() =>{ cy.logout().then(() => { - cy.login("test@lablup.com", "test123@"); + cy.login("test2@lablup.com", "test123@"); }); }) }); From a88a633d1f4222a00ad781073515dff1d7771664 Mon Sep 17 00:00:00 2001 From: gee05053 Date: Wed, 6 Dec 2023 16:22:32 +0900 Subject: [PATCH 07/48] implemnet createVfolder test --- cypress/commands/DataPage.cy.ts | 16 ++++++++++++++++ cypress/commands/LoginPage.cy.ts | 10 ++++++---- cypress/e2e/e2eTest.cy.ts | 14 +++++--------- src/components/backend-ai-webui.ts | 2 +- 4 files changed, 28 insertions(+), 14 deletions(-) create mode 100644 cypress/commands/DataPage.cy.ts diff --git a/cypress/commands/DataPage.cy.ts b/cypress/commands/DataPage.cy.ts new file mode 100644 index 0000000000..ae9bec19ad --- /dev/null +++ b/cypress/commands/DataPage.cy.ts @@ -0,0 +1,16 @@ +import {findShadowRoot} from '../helper/FindShadowRoot.cy'; + +Cypress.Commands.add('createVfolder', (vfolderName: string) => { + findShadowRoot('backend-ai-webui').find('#data').click(); + cy.wait(400); + const createVfolderDialog = findShadowRoot('backend-ai-webui > backend-ai-data-view').find('#add-folder'); + const vfolderNameInput = findShadowRoot('backend-ai-webui > backend-ai-data-view > #add-folder-name').find('input'); + const createButton = findShadowRoot('backend-ai-webui > backend-ai-data-view').find('#add-button'); + createVfolderDialog.click(); + vfolderNameInput.type(vfolderName); + createButton.click(); + cy.wait(5000); + findShadowRoot('backend-ai-webui > backend-ai-data-view > backend-ai-storage-list') + .find(`#controls[folder-name=${vfolderName}]`) + .should('exist'); +}); \ No newline at end of file diff --git a/cypress/commands/LoginPage.cy.ts b/cypress/commands/LoginPage.cy.ts index e9cd1de847..d95148ceff 100644 --- a/cypress/commands/LoginPage.cy.ts +++ b/cypress/commands/LoginPage.cy.ts @@ -1,10 +1,12 @@ import {findShadowRoot} from '../helper/FindShadowRoot.cy'; -Cypress.Commands.add('login', (email, password) => { - const emailInput = findShadowRoot("backend-ai-webui > backend-ai-login > #id_user_id").find("input"); - const passwordInput = findShadowRoot("backend-ai-webui > backend-ai-login > #id_password").find("input"); - const loginButton = findShadowRoot("backend-ai-webui > backend-ai-login > #login-button").find("button"); +Cypress.Commands.add('login', (email: string, password: string, endpoint: string) => { + const emailInput = findShadowRoot('backend-ai-webui > backend-ai-login > #id_user_id').find('input'); + const passwordInput = findShadowRoot('backend-ai-webui > backend-ai-login > #id_password').find('input'); + const endpointInput = findShadowRoot('backend-ai-webui > backend-ai-login > #id_api_endpoint').find('input'); + const loginButton = findShadowRoot('backend-ai-webui > backend-ai-login > #login-button').find('button'); emailInput.type(email); passwordInput.type(password); + endpointInput.clear().type(endpoint); loginButton.click(); }); \ No newline at end of file diff --git a/cypress/e2e/e2eTest.cy.ts b/cypress/e2e/e2eTest.cy.ts index 857ebe3d44..a526a79513 100644 --- a/cypress/e2e/e2eTest.cy.ts +++ b/cypress/e2e/e2eTest.cy.ts @@ -1,5 +1,6 @@ import '../commands/LoginPage.cy'; import '../commands/UserDropdown.cy'; +import '../commands/DataPage.cy'; describe('Initial cypress E2E test', () => { beforeEach(() => { @@ -7,14 +8,9 @@ describe('Initial cypress E2E test', () => { cy.visit('http://localhost:9081'); //방문할 페이지 }); - it('user profile change test', () => { - cy.login("test2@lablup.com", "test123!").then(() => { - cy.wait(4000); - cy.userProfileChange("test2222", "test123!", "test123@").then(() =>{ - cy.logout().then(() => { - cy.login("test2@lablup.com", "test123@"); - }); - }) - }); + it('localhost E2E test', () => { + cy.login('test2@lablup.com', 'test123!', 'http://127.0.0.1:8090'); + cy.wait(400); + cy.createVfolder('test-e2eTest'); }); }); \ No newline at end of file diff --git a/src/components/backend-ai-webui.ts b/src/components/backend-ai-webui.ts index 4153fb17c4..5b5eb81053 100644 --- a/src/components/backend-ai-webui.ts +++ b/src/components/backend-ai-webui.ts @@ -1476,7 +1476,7 @@ export default class BackendAIWebUI extends connect(store)(LitElement) { ${_t('webui.menu.Import&Run')} - backend-ai-data-view > backend-ai-storage-list > #delete-folder-name' + ).find('input'); + const deleteButton = + findShadowRoot('backend-ai-webui > backend-ai-data-view > backend-ai-storage-list') + .find('#delete-button'); + deleteDialogOpenButton.click(); + deleteVfolderNameInput.type(vfolderName); + deleteButton.click(); + findShadowRoot('backend-ai-webui > backend-ai-data-view > backend-ai-storage-list') + .find(`lablup-shields[folder-name=${vfolderName}][description="deleted-complete"]`) + .should('exist'); }); \ No newline at end of file diff --git a/cypress/e2e/e2eTest.cy.ts b/cypress/e2e/e2eTest.cy.ts index a526a79513..cd98077521 100644 --- a/cypress/e2e/e2eTest.cy.ts +++ b/cypress/e2e/e2eTest.cy.ts @@ -12,5 +12,6 @@ describe('Initial cypress E2E test', () => { cy.login('test2@lablup.com', 'test123!', 'http://127.0.0.1:8090'); cy.wait(400); cy.createVfolder('test-e2eTest'); + cy.deleteVfolder('test-e2eTest'); }); }); \ No newline at end of file diff --git a/src/components/backend-ai-storage-list.ts b/src/components/backend-ai-storage-list.ts index ad00034f92..9fb42ddd51 100644 --- a/src/components/backend-ai-storage-list.ts +++ b/src/components/backend-ai-storage-list.ts @@ -1792,6 +1792,7 @@ export default class BackendAiStorageList extends BackendAIPage { From 4e5aa4a555679ebd91fcc27dd35078c1754828aa Mon Sep 17 00:00:00 2001 From: gee05053 Date: Thu, 7 Dec 2023 11:27:18 +0900 Subject: [PATCH 09/48] apply prettier and change DataPage to DataStoragePage --- .prettierignore | 1 + cypress/.prettierrc.json | 10 ++++ cypress/commands/DataPage.cy.ts | 38 ------------- cypress/commands/DataStoragePage.cy.ts | 50 +++++++++++++++++ cypress/commands/LoginPage.cy.ts | 33 +++++++---- cypress/commands/UserDropdown.cy.ts | 78 +++++++++++++++++++------- cypress/e2e/e2eTest.cy.ts | 4 +- 7 files changed, 143 insertions(+), 71 deletions(-) create mode 100644 cypress/.prettierrc.json delete mode 100644 cypress/commands/DataPage.cy.ts create mode 100644 cypress/commands/DataStoragePage.cy.ts diff --git a/.prettierignore b/.prettierignore index 97a9e2c1e4..7f25b5077b 100644 --- a/.prettierignore +++ b/.prettierignore @@ -2,5 +2,6 @@ src/lib/ !/src !/react +!/cypress **/__generated__/*.graphql.ts *.graphql \ No newline at end of file diff --git a/cypress/.prettierrc.json b/cypress/.prettierrc.json new file mode 100644 index 0000000000..a632bb880d --- /dev/null +++ b/cypress/.prettierrc.json @@ -0,0 +1,10 @@ +{ + "tabWidth": 2, + "semi": true, + "singleQuote": true, + "importOrderSeparation": true, + "printWidth": 80, + "bracketSpacing": true, + "trailingComma": "all", + "singleAttributePerLine": false +} diff --git a/cypress/commands/DataPage.cy.ts b/cypress/commands/DataPage.cy.ts deleted file mode 100644 index 8ab4eabc18..0000000000 --- a/cypress/commands/DataPage.cy.ts +++ /dev/null @@ -1,38 +0,0 @@ -import {findShadowRoot} from '../helper/FindShadowRoot.cy'; - -Cypress.Commands.add('createVfolder', (vfolderName: string) => { - findShadowRoot('backend-ai-webui').find('#data').click(); - cy.wait(400); - const createDialogOpenButton = findShadowRoot('backend-ai-webui > backend-ai-data-view').find('#add-folder'); - const vfolderNameInput = findShadowRoot('backend-ai-webui > backend-ai-data-view > #add-folder-name').find('input'); - const createButton = findShadowRoot('backend-ai-webui > backend-ai-data-view').find('#add-button'); - createDialogOpenButton.click(); - vfolderNameInput.type(vfolderName); - createButton.click(); - cy.wait(5000); - findShadowRoot('backend-ai-webui > backend-ai-data-view > backend-ai-storage-list') - .find(`#controls[folder-name=${vfolderName}]`) - .should('exist'); -}); - -Cypress.Commands.add('deleteVfolder', (vfolderName: string) => { - findShadowRoot('backend-ai-webui').find('#data').click(); - cy.wait(400); - const deleteDialogOpenButton = - findShadowRoot('backend-ai-webui > backend-ai-data-view > backend-ai-storage-list') - .find(`#controls[folder-name=${vfolderName}]`) - .find('mwc-icon-button[icon="delete"]'); - const deleteVfolderNameInput = - findShadowRoot( - 'backend-ai-webui > backend-ai-data-view > backend-ai-storage-list > #delete-folder-name' - ).find('input'); - const deleteButton = - findShadowRoot('backend-ai-webui > backend-ai-data-view > backend-ai-storage-list') - .find('#delete-button'); - deleteDialogOpenButton.click(); - deleteVfolderNameInput.type(vfolderName); - deleteButton.click(); - findShadowRoot('backend-ai-webui > backend-ai-data-view > backend-ai-storage-list') - .find(`lablup-shields[folder-name=${vfolderName}][description="deleted-complete"]`) - .should('exist'); -}); \ No newline at end of file diff --git a/cypress/commands/DataStoragePage.cy.ts b/cypress/commands/DataStoragePage.cy.ts new file mode 100644 index 0000000000..dbe4f2c3ec --- /dev/null +++ b/cypress/commands/DataStoragePage.cy.ts @@ -0,0 +1,50 @@ +import { findShadowRoot } from '../helper/FindShadowRoot.cy'; + +Cypress.Commands.add('createVfolder', (vfolderName: string) => { + findShadowRoot('backend-ai-webui').find('#data').click(); + cy.wait(400); + const createDialogOpenButton = findShadowRoot( + 'backend-ai-webui > backend-ai-data-view', + ).find('#add-folder'); + const vfolderNameInput = findShadowRoot( + 'backend-ai-webui > backend-ai-data-view > #add-folder-name', + ).find('input'); + const createButton = findShadowRoot( + 'backend-ai-webui > backend-ai-data-view', + ).find('#add-button'); + createDialogOpenButton.click(); + vfolderNameInput.type(vfolderName); + createButton.click(); + cy.wait(5000); + findShadowRoot( + 'backend-ai-webui > backend-ai-data-view > backend-ai-storage-list', + ) + .find(`#controls[folder-name=${vfolderName}]`) + .should('exist'); +}); + +Cypress.Commands.add('deleteVfolder', (vfolderName: string) => { + findShadowRoot('backend-ai-webui').find('#data').click(); + cy.wait(400); + const deleteDialogOpenButton = findShadowRoot( + 'backend-ai-webui > backend-ai-data-view > backend-ai-storage-list', + ) + .find(`#controls[folder-name=${vfolderName}]`) + .find('mwc-icon-button[icon="delete"]'); + const deleteVfolderNameInput = findShadowRoot( + 'backend-ai-webui > backend-ai-data-view > backend-ai-storage-list > #delete-folder-name', + ).find('input'); + const deleteButton = findShadowRoot( + 'backend-ai-webui > backend-ai-data-view > backend-ai-storage-list', + ).find('#delete-button'); + deleteDialogOpenButton.click(); + deleteVfolderNameInput.type(vfolderName); + deleteButton.click(); + findShadowRoot( + 'backend-ai-webui > backend-ai-data-view > backend-ai-storage-list', + ) + .find( + `lablup-shields[folder-name=${vfolderName}][description="deleted-complete"]`, + ) + .should('exist'); +}); diff --git a/cypress/commands/LoginPage.cy.ts b/cypress/commands/LoginPage.cy.ts index d95148ceff..ed92e0bc1f 100644 --- a/cypress/commands/LoginPage.cy.ts +++ b/cypress/commands/LoginPage.cy.ts @@ -1,12 +1,23 @@ -import {findShadowRoot} from '../helper/FindShadowRoot.cy'; +import { findShadowRoot } from '../helper/FindShadowRoot.cy'; -Cypress.Commands.add('login', (email: string, password: string, endpoint: string) => { - const emailInput = findShadowRoot('backend-ai-webui > backend-ai-login > #id_user_id').find('input'); - const passwordInput = findShadowRoot('backend-ai-webui > backend-ai-login > #id_password').find('input'); - const endpointInput = findShadowRoot('backend-ai-webui > backend-ai-login > #id_api_endpoint').find('input'); - const loginButton = findShadowRoot('backend-ai-webui > backend-ai-login > #login-button').find('button'); - emailInput.type(email); - passwordInput.type(password); - endpointInput.clear().type(endpoint); - loginButton.click(); -}); \ No newline at end of file +Cypress.Commands.add( + 'login', + (email: string, password: string, endpoint: string) => { + const emailInput = findShadowRoot( + 'backend-ai-webui > backend-ai-login > #id_user_id', + ).find('input'); + const passwordInput = findShadowRoot( + 'backend-ai-webui > backend-ai-login > #id_password', + ).find('input'); + const endpointInput = findShadowRoot( + 'backend-ai-webui > backend-ai-login > #id_api_endpoint', + ).find('input'); + const loginButton = findShadowRoot( + 'backend-ai-webui > backend-ai-login > #login-button', + ).find('button'); + emailInput.type(email); + passwordInput.type(password); + endpointInput.clear().type(endpoint); + loginButton.click(); + }, +); diff --git a/cypress/commands/UserDropdown.cy.ts b/cypress/commands/UserDropdown.cy.ts index 9d5e790047..1d9b2488b8 100644 --- a/cypress/commands/UserDropdown.cy.ts +++ b/cypress/commands/UserDropdown.cy.ts @@ -1,23 +1,61 @@ -import {findShadowRoot} from '../helper/FindShadowRoot.cy'; +import { findShadowRoot } from '../helper/FindShadowRoot.cy'; -Cypress.Commands.add('userProfileChange', (userName, originalPassword, newPassword) => { - findShadowRoot("backend-ai-webui").find("backend-ai-react-user-dropdown-menu").trigger("click").then(() =>{ - findShadowRoot("backend-ai-webui > backend-ai-react-user-dropdown-menu").find("li:contains(사용자 정보 변경)").click(); - }); - findShadowRoot("backend-ai-webui > backend-ai-react-user-profile-setting-dialog") - .find("#full_name").clear().focus().type(userName); - findShadowRoot("backend-ai-webui > backend-ai-react-user-profile-setting-dialog") - .find("#originalPassword").focus().type(originalPassword); - findShadowRoot("backend-ai-webui > backend-ai-react-user-profile-setting-dialog") - .find("#newPassword").focus().type(newPassword); - findShadowRoot("backend-ai-webui > backend-ai-react-user-profile-setting-dialog") - .find("#newPasswordConfirm").focus().type(newPassword); - findShadowRoot("backend-ai-webui > backend-ai-react-user-profile-setting-dialog") - .find("button:contains(변경)").click(); -}); +Cypress.Commands.add( + 'userProfileChange', + (userName, originalPassword, newPassword) => { + findShadowRoot('backend-ai-webui') + .find('backend-ai-react-user-dropdown-menu') + .trigger('click') + .then(() => { + findShadowRoot('backend-ai-webui > backend-ai-react-user-dropdown-menu') + .find('li:contains(사용자 정보 변경)') + .click(); + }); + findShadowRoot( + 'backend-ai-webui > backend-ai-react-user-profile-setting-dialog', + ) + .find('#full_name') + .clear() + .focus() + .type(userName); + findShadowRoot( + 'backend-ai-webui > backend-ai-react-user-profile-setting-dialog', + ) + .find('#originalPassword') + .focus() + .type(originalPassword); + findShadowRoot( + 'backend-ai-webui > backend-ai-react-user-profile-setting-dialog', + ) + .find('#newPassword') + .focus() + .type(newPassword); + findShadowRoot( + 'backend-ai-webui > backend-ai-react-user-profile-setting-dialog', + ) + .find('#newPasswordConfirm') + .focus() + .type(newPassword); + findShadowRoot( + 'backend-ai-webui > backend-ai-react-user-profile-setting-dialog', + ) + .find('button:contains(변경)') + .click(); + }, +); Cypress.Commands.add('logout', () => { - findShadowRoot("backend-ai-webui").find("backend-ai-react-user-dropdown-menu").trigger("click").then(() =>{ - findShadowRoot("backend-ai-webui > backend-ai-react-user-dropdown-menu").find("li:contains(로그아웃)").click(); - }); -}) \ No newline at end of file + findShadowRoot('backend-ai-webui') + .find('backend-ai-react-user-dropdown-menu') + .trigger('click') + .then(() => { + findShadowRoot('backend-ai-webui > backend-ai-react-user-dropdown-menu') + .find('li:contains(로그아웃)') + .click(); + }); +}); + +const a = { + adajndakdnsxanalcnajkcnjkacasaajda: 100, + asdasnbdaskdnajdjkad: 213313, +}; diff --git a/cypress/e2e/e2eTest.cy.ts b/cypress/e2e/e2eTest.cy.ts index cd98077521..96ae1e989c 100644 --- a/cypress/e2e/e2eTest.cy.ts +++ b/cypress/e2e/e2eTest.cy.ts @@ -4,7 +4,7 @@ import '../commands/DataPage.cy'; describe('Initial cypress E2E test', () => { beforeEach(() => { - cy.viewport(1280,800); + cy.viewport(1280, 800); cy.visit('http://localhost:9081'); //방문할 페이지 }); @@ -14,4 +14,4 @@ describe('Initial cypress E2E test', () => { cy.createVfolder('test-e2eTest'); cy.deleteVfolder('test-e2eTest'); }); -}); \ No newline at end of file +}); From 9244b1fe9e6d9362511fafa097ec69a7039f3d18 Mon Sep 17 00:00:00 2001 From: gee05053 Date: Thu, 7 Dec 2023 11:30:48 +0900 Subject: [PATCH 10/48] fix: apply prettier --- cypress/helper/FindShadowRoot.cy.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cypress/helper/FindShadowRoot.cy.ts b/cypress/helper/FindShadowRoot.cy.ts index 046ce4f146..836c66a1b7 100644 --- a/cypress/helper/FindShadowRoot.cy.ts +++ b/cypress/helper/FindShadowRoot.cy.ts @@ -1,12 +1,12 @@ export const findShadowRoot = (routes) => { - const segments = routes.split(">").map((route) => route.trim()); + const segments = routes.split('>').map((route) => route.trim()); let element = cy.get(segments[0]).shadow(); - for (const [idx,segment] of segments.entries()) { + for (const [idx, segment] of segments.entries()) { if (idx === 0) { - continue + continue; } else { element = element.find(segment).shadow(); } } return element; -}; \ No newline at end of file +}; From 8417746cd55d448851ab72a481d4e166baf64a92 Mon Sep 17 00:00:00 2001 From: gee05053 Date: Thu, 7 Dec 2023 16:23:39 +0900 Subject: [PATCH 11/48] implement launch session e2e test --- .eslintignore | 1 + cypress/commands/SessionPage.cy.ts | 70 +++++++++++++++++++++++ cypress/e2e/e2eTest.cy.ts | 8 ++- src/components/backend-ai-session-list.ts | 4 +- src/components/backend-ai-webui.ts | 2 +- 5 files changed, 80 insertions(+), 5 deletions(-) create mode 100644 cypress/commands/SessionPage.cy.ts diff --git a/.eslintignore b/.eslintignore index c73a83a449..119a34143e 100644 --- a/.eslintignore +++ b/.eslintignore @@ -16,3 +16,4 @@ src/lib/backend.ai-client-node-to-es6.js src/lib/backend.ai-client-node-test-native-es6.js src/lib/Chart.min.js src/lib/json_to_csv.js +cypress/* \ No newline at end of file diff --git a/cypress/commands/SessionPage.cy.ts b/cypress/commands/SessionPage.cy.ts new file mode 100644 index 0000000000..a33778578b --- /dev/null +++ b/cypress/commands/SessionPage.cy.ts @@ -0,0 +1,70 @@ +import { findShadowRoot } from '../helper/FindShadowRoot.cy'; + +Cypress.Commands.add( + 'launchSession', + ( + environmnet: string, + architecture: string, + sessionName: string, + vfolderName: string, + ) => { + findShadowRoot('backend-ai-webui').find('#session').click(); + cy.wait(400); + const launchDialogOpenButton = findShadowRoot( + 'backend-ai-webui > backend-ai-session-view > backend-ai-session-launcher', + ).find('#launch-session'); + launchDialogOpenButton.click(); + + const versionSelect = findShadowRoot( + 'backend-ai-webui > backend-ai-session-view > backend-ai-session-launcher', + ).find('#version'); + const selectedVersion = findShadowRoot( + 'backend-ai-webui > backend-ai-session-view > backend-ai-session-launcher', + ).find(`mwc-list-item[id=${environmnet}][architecture=${architecture}]`); + const sessionNameInput = findShadowRoot( + 'backend-ai-webui > backend-ai-session-view > backend-ai-session-launcher > #session-name', + ).find('input'); + const nextButton = findShadowRoot( + 'backend-ai-webui > backend-ai-session-view > backend-ai-session-launcher', + ).find('#next-button'); + const launchButton = findShadowRoot( + 'backend-ai-webui > backend-ai-session-view > backend-ai-session-launcher', + ).find('#launch-button'); + versionSelect.click(); + cy.wait(500); + selectedVersion.click(); + sessionNameInput.clear().type(sessionName); + nextButton.click(); + const mountVfolder = findShadowRoot( + 'backend-ai-webui > backend-ai-session-view > backend-ai-session-launcher', + ) + .find('#non-auto-mounted-folder-grid') + .find(`div:contains(${vfolderName})`); + mountVfolder.click(); + nextButton.click(); + const resourceGroupExtension = findShadowRoot( + 'backend-ai-webui > backend-ai-session-view > backend-ai-session-launcher', + ).find('lablup-expansion[name="resource-group"]'); + const ramResourceInput = findShadowRoot( + 'backend-ai-webui > backend-ai-session-view > backend-ai-session-launcher > #mem-resource > #textfield', + ).find('input'); + resourceGroupExtension.click(); + ramResourceInput.clear().type(2); + nextButton.click(); + launchButton.click(); + cy.wait(10000); + const appDialog = findShadowRoot( + 'backend-ai-webui > backend-ai-app-launcher > #app-dialog', + ).find('mwc-icon-button[icon="close"]'); + appDialog.click(); + const sessionStatus = findShadowRoot( + 'backend-ai-webui > backend-ai-session-view > backend-ai-session-list', + ).find(`#${sessionName}-status`); + sessionStatus.should('exist'); + }, +); + +Cypress.Commands.add('deleteSession', (sessionName: string) => { + findShadowRoot('backend-ai-webui').find('#session').click(); + cy.wait(400); +}); diff --git a/cypress/e2e/e2eTest.cy.ts b/cypress/e2e/e2eTest.cy.ts index 96ae1e989c..1b1b1bcd62 100644 --- a/cypress/e2e/e2eTest.cy.ts +++ b/cypress/e2e/e2eTest.cy.ts @@ -1,6 +1,7 @@ import '../commands/LoginPage.cy'; import '../commands/UserDropdown.cy'; -import '../commands/DataPage.cy'; +import '../commands/DataStoragePage.cy'; +import '../commands/SessionPage.cy'; describe('Initial cypress E2E test', () => { beforeEach(() => { @@ -11,7 +12,8 @@ describe('Initial cypress E2E test', () => { it('localhost E2E test', () => { cy.login('test2@lablup.com', 'test123!', 'http://127.0.0.1:8090'); cy.wait(400); - cy.createVfolder('test-e2eTest'); - cy.deleteVfolder('test-e2eTest'); + //cy.createVfolder('test-e2eTest'); + //cy.deleteVfolder('test-e2eTest'); + cy.launchSession('3\\.9-ubuntu20\\.04', 'aarch64', 'test', 'tttt'); }); }); diff --git a/src/components/backend-ai-session-list.ts b/src/components/backend-ai-session-list.ts index 133f54a1a6..9282a95850 100644 --- a/src/components/backend-ai-session-list.ts +++ b/src/components/backend-ai-session-list.ts @@ -3635,7 +3635,9 @@ ${rowData.item[this.sessionNameField]} - ${rowData.item.status} + + ${rowData.item.status} + ${!rowData.item.status_data || rowData.item.status_data === '{}' ? html`` : html` diff --git a/src/components/backend-ai-webui.ts b/src/components/backend-ai-webui.ts index 5b5eb81053..5b8717efe4 100644 --- a/src/components/backend-ai-webui.ts +++ b/src/components/backend-ai-webui.ts @@ -1393,7 +1393,7 @@ export default class BackendAIWebUI extends connect(store)(LitElement) { ${_t('webui.menu.Summary')} - backend-ai-session-view', + ).find('mwc-tab[title="finished"]'); + terminateDialogOpenButton.click(); + deleteButton.click(); + cy.wait(5000); + finishedTab.click(); + cy.wait(5000); + findShadowRoot( + 'backend-ai-webui > backend-ai-session-view > backend-ai-session-list', + ) + .find(`#${sessionName}-status`) + .contains('TERMINATED'); }); diff --git a/cypress/e2e/e2eTest.cy.ts b/cypress/e2e/e2eTest.cy.ts index 1b1b1bcd62..15a609aa06 100644 --- a/cypress/e2e/e2eTest.cy.ts +++ b/cypress/e2e/e2eTest.cy.ts @@ -3,6 +3,16 @@ import '../commands/UserDropdown.cy'; import '../commands/DataStoragePage.cy'; import '../commands/SessionPage.cy'; +const generateRandomString = ( + length = 6, + chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', +) => { + let result = ''; + for (let i = length; i > 0; --i) + result += chars[Math.floor(Math.random() * chars.length)]; + return result; +}; + describe('Initial cypress E2E test', () => { beforeEach(() => { cy.viewport(1280, 800); @@ -10,10 +20,18 @@ describe('Initial cypress E2E test', () => { }); it('localhost E2E test', () => { - cy.login('test2@lablup.com', 'test123!', 'http://127.0.0.1:8090'); + cy.login('test@lablup.com', 'test123!', 'http://127.0.0.1:8090'); cy.wait(400); - //cy.createVfolder('test-e2eTest'); - //cy.deleteVfolder('test-e2eTest'); - cy.launchSession('3\\.9-ubuntu20\\.04', 'aarch64', 'test', 'tttt'); + const vfolderName = generateRandomString(); + const sessionName = generateRandomString(); + cy.createVfolder(vfolderName); + cy.launchSession( + '3\\.9-ubuntu20\\.04', + 'aarch64', + vfolderName, + sessionName, + ); + cy.deleteSession(sessionName); + cy.deleteVfolder(vfolderName); }); }); diff --git a/src/components/backend-ai-session-list.ts b/src/components/backend-ai-session-list.ts index 9282a95850..8945123f5f 100644 --- a/src/components/backend-ai-session-list.ts +++ b/src/components/backend-ai-session-list.ts @@ -2906,7 +2906,7 @@ ${rowData.item[this.sessionNameField]} Date: Thu, 7 Dec 2023 18:15:14 +0900 Subject: [PATCH 14/48] fix:add cy.wait() to see test process --- cypress/commands/LoginPage.cy.ts | 4 +- cypress/commands/SessionPage.cy.ts | 6 +++ cypress/commands/UserDropdown.cy.ts | 61 ----------------------------- cypress/e2e/e2eTest.cy.ts | 1 - 4 files changed, 8 insertions(+), 64 deletions(-) delete mode 100644 cypress/commands/UserDropdown.cy.ts diff --git a/cypress/commands/LoginPage.cy.ts b/cypress/commands/LoginPage.cy.ts index ed92e0bc1f..209da4e268 100644 --- a/cypress/commands/LoginPage.cy.ts +++ b/cypress/commands/LoginPage.cy.ts @@ -13,8 +13,8 @@ Cypress.Commands.add( 'backend-ai-webui > backend-ai-login > #id_api_endpoint', ).find('input'); const loginButton = findShadowRoot( - 'backend-ai-webui > backend-ai-login > #login-button', - ).find('button'); + 'backend-ai-webui > backend-ai-login', + ).find('#login-button'); emailInput.type(email); passwordInput.type(password); endpointInput.clear().type(endpoint); diff --git a/cypress/commands/SessionPage.cy.ts b/cypress/commands/SessionPage.cy.ts index 523da17042..39bd266346 100644 --- a/cypress/commands/SessionPage.cy.ts +++ b/cypress/commands/SessionPage.cy.ts @@ -33,15 +33,20 @@ Cypress.Commands.add( versionSelect.click(); cy.wait(500); selectedVersion.click(); + cy.wait(500); sessionNameInput.clear().type(sessionName); + cy.wait(500); nextButton.click(); + cy.wait(500); const mountVfolder = findShadowRoot( 'backend-ai-webui > backend-ai-session-view > backend-ai-session-launcher', ) .find('#non-auto-mounted-folder-grid') .find(`div:contains(${mountVfolderName})`); mountVfolder.click(); + cy.wait(500); nextButton.click(); + cy.wait(500); const resourceGroupExtension = findShadowRoot( 'backend-ai-webui > backend-ai-session-view > backend-ai-session-launcher', ).find('lablup-expansion[name="resource-group"]'); @@ -51,6 +56,7 @@ Cypress.Commands.add( resourceGroupExtension.click(); ramResourceInput.clear().type(2); nextButton.click(); + cy.wait(500); launchButton.click(); cy.wait(10000); const appDialog = findShadowRoot( diff --git a/cypress/commands/UserDropdown.cy.ts b/cypress/commands/UserDropdown.cy.ts deleted file mode 100644 index 1d9b2488b8..0000000000 --- a/cypress/commands/UserDropdown.cy.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { findShadowRoot } from '../helper/FindShadowRoot.cy'; - -Cypress.Commands.add( - 'userProfileChange', - (userName, originalPassword, newPassword) => { - findShadowRoot('backend-ai-webui') - .find('backend-ai-react-user-dropdown-menu') - .trigger('click') - .then(() => { - findShadowRoot('backend-ai-webui > backend-ai-react-user-dropdown-menu') - .find('li:contains(사용자 정보 변경)') - .click(); - }); - findShadowRoot( - 'backend-ai-webui > backend-ai-react-user-profile-setting-dialog', - ) - .find('#full_name') - .clear() - .focus() - .type(userName); - findShadowRoot( - 'backend-ai-webui > backend-ai-react-user-profile-setting-dialog', - ) - .find('#originalPassword') - .focus() - .type(originalPassword); - findShadowRoot( - 'backend-ai-webui > backend-ai-react-user-profile-setting-dialog', - ) - .find('#newPassword') - .focus() - .type(newPassword); - findShadowRoot( - 'backend-ai-webui > backend-ai-react-user-profile-setting-dialog', - ) - .find('#newPasswordConfirm') - .focus() - .type(newPassword); - findShadowRoot( - 'backend-ai-webui > backend-ai-react-user-profile-setting-dialog', - ) - .find('button:contains(변경)') - .click(); - }, -); - -Cypress.Commands.add('logout', () => { - findShadowRoot('backend-ai-webui') - .find('backend-ai-react-user-dropdown-menu') - .trigger('click') - .then(() => { - findShadowRoot('backend-ai-webui > backend-ai-react-user-dropdown-menu') - .find('li:contains(로그아웃)') - .click(); - }); -}); - -const a = { - adajndakdnsxanalcnajkcnjkacasaajda: 100, - asdasnbdaskdnajdjkad: 213313, -}; diff --git a/cypress/e2e/e2eTest.cy.ts b/cypress/e2e/e2eTest.cy.ts index 15a609aa06..c50912d17d 100644 --- a/cypress/e2e/e2eTest.cy.ts +++ b/cypress/e2e/e2eTest.cy.ts @@ -1,5 +1,4 @@ import '../commands/LoginPage.cy'; -import '../commands/UserDropdown.cy'; import '../commands/DataStoragePage.cy'; import '../commands/SessionPage.cy'; From 0c61074ac493e75b69b5d55022c8da44f3213457 Mon Sep 17 00:00:00 2001 From: gee05053 Date: Thu, 14 Dec 2023 14:35:06 +0900 Subject: [PATCH 15/48] feat:implement add user and delete user --- cypress/commands/CredentialPage.cy.ts | 156 +++++++++++++++++++++++++ cypress/e2e/e2eTest.cy.ts | 5 +- src/components/backend-ai-user-list.ts | 30 +++-- src/components/backend-ai-webui.ts | 1 + 4 files changed, 174 insertions(+), 18 deletions(-) create mode 100644 cypress/commands/CredentialPage.cy.ts diff --git a/cypress/commands/CredentialPage.cy.ts b/cypress/commands/CredentialPage.cy.ts new file mode 100644 index 0000000000..095c548362 --- /dev/null +++ b/cypress/commands/CredentialPage.cy.ts @@ -0,0 +1,156 @@ +import { findShadowRoot } from '../helper/FindShadowRoot.cy'; + +Cypress.Commands.add( + 'addUser', + (email: string, userName: string, password: string) => { + findShadowRoot('backend-ai-webui').find('#credential').click(); + cy.wait(1000); + const addUserButton = findShadowRoot( + 'backend-ai-webui > backend-ai-credential-view', + ).find('#add-user'); + const userEmailInput = findShadowRoot( + 'backend-ai-webui > backend-ai-credential-view > #id_user_email', + ).find('input'); + const userNameInput = findShadowRoot( + 'backend-ai-webui > backend-ai-credential-view > #id_user_name', + ).find('input'); + const passwordInput = findShadowRoot( + 'backend-ai-webui > backend-ai-credential-view > #id_user_password', + ).find('input'); + const confirmPasswordInput = findShadowRoot( + 'backend-ai-webui > backend-ai-credential-view > #id_user_confirm', + ).find('input'); + const createUserButton = findShadowRoot( + 'backend-ai-webui > backend-ai-credential-view', + ).find('#create-user-button'); + const credentialsTab = findShadowRoot( + 'backend-ai-webui > backend-ai-credential-view', + ).find('#mdc-tab-2'); + addUserButton.click(); + cy.wait(500); + userEmailInput.type(email); + cy.wait(500); + userNameInput.type(userName); + cy.wait(500); + passwordInput.type(password); + cy.wait(500); + confirmPasswordInput.type(password); + cy.wait(500); + createUserButton.click(); + cy.wait(2000); + findShadowRoot( + 'backend-ai-webui > backend-ai-credential-view > #active-user-list', + ) + .find('vaadin-grid-cell-content') + .filter(`:contains(${email})`) + .should('exist'); + credentialsTab.click(); + cy.wait(500); + findShadowRoot( + 'backend-ai-webui > backend-ai-credential-view > #active-credential-list', + ) + .find('vaadin-grid-cell-content') + .filter(`:contains(${email})`) + .should('exist'); + }, +); + +Cypress.Commands.add('deleteUser', (email: string) => { + findShadowRoot('backend-ai-webui').find('#credential').click(); + cy.wait(1000); + const userTab = findShadowRoot( + 'backend-ai-webui > backend-ai-credential-view', + ).find('#mdc-tab-1'); + const deleteUserButton = findShadowRoot( + 'backend-ai-webui > backend-ai-credential-view > #active-user-list', + ) + .find(`div[user-id="${email}"]`) + .find('mwc-icon-button[icon="delete_forever"]'); + const agreeButton = findShadowRoot( + 'backend-ai-webui > backend-ai-credential-view > #active-user-list', + ).find('#deleteOk'); + const userInactiveSubTab = findShadowRoot( + 'backend-ai-webui > backend-ai-credential-view', + ).find('#mdc-tab-5'); + const credentialsTab = findShadowRoot( + 'backend-ai-webui > backend-ai-credential-view', + ).find('#mdc-tab-2'); + const credentialInactiveSubTab = findShadowRoot( + 'backend-ai-webui > backend-ai-credential-view', + ).find('#mdc-tab-7'); + userTab.click(); + cy.wait(500); + deleteUserButton.click(); + cy.wait(500); + agreeButton.click(); + cy.wait(2000); + findShadowRoot( + 'backend-ai-webui > backend-ai-credential-view > #active-user-list', + ) + .find('vaadin-grid-cell-content') + .filter(`:contains(${email})`) + .should('not.exist'); + userInactiveSubTab.click(); + cy.wait(500); + findShadowRoot( + 'backend-ai-webui > backend-ai-credential-view > #inactive-user-list', + ) + .find('vaadin-grid-cell-content') + .filter(`:contains(${email})`) + .should('exist'); + credentialsTab.click(); + cy.wait(500); + credentialInactiveSubTab.click(); + cy.wait(500); + findShadowRoot( + 'backend-ai-webui > backend-ai-credential-view > #inactive-credential-list', + ) + .find('vaadin-grid-cell-content') + .filter(`:contains(${email})`) + .should('exist'); + /* + const userEmailInput = findShadowRoot( + 'backend-ai-webui > backend-ai-credential-view > #id_user_email', + ).find('input'); + const userNameInput = findShadowRoot( + 'backend-ai-webui > backend-ai-credential-view > #id_user_name', + ).find('input'); + const passwordInput = findShadowRoot( + 'backend-ai-webui > backend-ai-credential-view > #id_user_password', + ).find('input'); + const confirmPasswordInput = findShadowRoot( + 'backend-ai-webui > backend-ai-credential-view > #id_user_confirm', + ).find('input'); + const createUserButton = findShadowRoot( + 'backend-ai-webui > backend-ai-credential-view', + ).find('#create-user-button'); + addUserButton.click(); + cy.wait(500); + userEmailInput.type(email); + cy.wait(500); + userNameInput.type(userName); + cy.wait(500); + passwordInput.type(password); + cy.wait(500); + confirmPasswordInput.type(password); + cy.wait(500); + createUserButton.click(); + cy.wait(2000); + findShadowRoot( + 'backend-ai-webui > backend-ai-credential-view > #active-user-list', + ) + .find('vaadin-grid-cell-content') + .filter(`:contains(${email})`) + .should('exist'); + findShadowRoot('backend-ai-webui > backend-ai-credential-view') + .find('#mdc-tab-2') + .click(); + cy.wait(500); + findShadowRoot( + 'backend-ai-webui > backend-ai-credential-view > backend-ai-credential-list', + ) + .find('vaadin-grid-cell-content') + .filter(`:contains(${email})`) + .should('exist'); + */ +}); diff --git a/cypress/e2e/e2eTest.cy.ts b/cypress/e2e/e2eTest.cy.ts index c50912d17d..5ab9f62eee 100644 --- a/cypress/e2e/e2eTest.cy.ts +++ b/cypress/e2e/e2eTest.cy.ts @@ -1,6 +1,7 @@ import '../commands/LoginPage.cy'; import '../commands/DataStoragePage.cy'; import '../commands/SessionPage.cy'; +import '../commands/CredentialPage.cy'; const generateRandomString = ( length = 6, @@ -19,7 +20,7 @@ describe('Initial cypress E2E test', () => { }); it('localhost E2E test', () => { - cy.login('test@lablup.com', 'test123!', 'http://127.0.0.1:8090'); + cy.login('admin@lablup.com', 'wJalrXUt', 'http://127.0.0.1:8090'); cy.wait(400); const vfolderName = generateRandomString(); const sessionName = generateRandomString(); @@ -32,5 +33,7 @@ describe('Initial cypress E2E test', () => { ); cy.deleteSession(sessionName); cy.deleteVfolder(vfolderName); + cy.addUser('test6@lablup.com', 'test6', 'test123!', 'test123!'); + cy.deleteUser('test6\\@lablup\\.com'); }); }); diff --git a/src/components/backend-ai-user-list.ts b/src/components/backend-ai-user-list.ts index fe6e8df876..20f00ee2b7 100644 --- a/src/components/backend-ai-user-list.ts +++ b/src/components/backend-ai-user-list.ts @@ -77,7 +77,6 @@ export default class BackendAIUserList extends BackendAIPage { @property({ type: Object }) _totpActivatedRenderer = this.totpActivatedRenderer.bind(this); @property({ type: Object }) keypairs; - @property({ type: String }) signoutUserName = ''; @property({ type: Object }) notification = Object(); @property({ type: String }) listCondition: StatusCondition = 'loading'; @property({ type: Number }) _totalUserCount = 0; @@ -305,28 +304,24 @@ export default class BackendAIUserList extends BackendAIPage { }); } - async _openUserSettingModal(e) { - const controls = e.target.closest('#controls'); - this.userEmail = controls['user-id']; + async _openUserSettingModal(userEmail) { + this.userEmail = userEmail; this.openUserSettingModal = true; } - async _openUserInfoModal(e) { - const controls = e.target.closest('#controls'); - this.userEmail = controls['user-id']; + async _openUserInfoModal(userEmail) { + this.userEmail = userEmail; this.openUserInfoModal = true; } - _signoutUserDialog(e) { - const controls = e.target.closest('#controls'); - const user_id = controls['user-id']; - this.signoutUserName = user_id; + _signoutUserDialog(userEmail) { + this.userEmail = userEmail; this.signoutUserDialog.show(); } _signoutUser() { globalThis.backendaiclient.user - .delete(this.signoutUserName) + .delete(this.userEmail) .then((response) => { this.notification.text = _text( 'credential.SignoutSeccessfullyFinished', @@ -499,24 +494,24 @@ export default class BackendAIUserList extends BackendAIPage {
${globalThis.backendaiclient.is_superadmin && this._isActive() ? html` ` : html``} @@ -697,7 +692,7 @@ export default class BackendAIUserList extends BackendAIPage {

You are inactivating the user - ${this.signoutUserName} + ${this.userEmail} .

${_t('dialog.ask.DoYouWantToProceed')}

@@ -708,6 +703,7 @@ export default class BackendAIUserList extends BackendAIPage { @click="${(e) => this._hideDialog(e)}" > Date: Thu, 14 Dec 2023 14:38:46 +0900 Subject: [PATCH 16/48] fix:remove unused params --- cypress/e2e/e2eTest.cy.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cypress/e2e/e2eTest.cy.ts b/cypress/e2e/e2eTest.cy.ts index 5ab9f62eee..d81f6ac135 100644 --- a/cypress/e2e/e2eTest.cy.ts +++ b/cypress/e2e/e2eTest.cy.ts @@ -33,7 +33,7 @@ describe('Initial cypress E2E test', () => { ); cy.deleteSession(sessionName); cy.deleteVfolder(vfolderName); - cy.addUser('test6@lablup.com', 'test6', 'test123!', 'test123!'); + cy.addUser('test6@lablup.com', 'test6', 'test123!'); cy.deleteUser('test6\\@lablup\\.com'); }); }); From 778747990234108330633a1fcab469df95092f79 Mon Sep 17 00:00:00 2001 From: gee05053 Date: Mon, 18 Dec 2023 13:58:30 +0900 Subject: [PATCH 17/48] feat:add playwright and implement test --- .github/workflows/playwright.yml | 27 ++++++++ .gitignore | 4 ++ e2e/e2eTest.spec.ts | 11 ++++ package-lock.json | 70 ++++++++++++++++++++- package.json | 2 + playwright.config.ts | 77 +++++++++++++++++++++++ tests-examples/DataStoragePage.spec.ts | 10 +++ tests-examples/SessionStoragePage.spec.ts | 24 +++++++ tests-examples/login.spec.ts | 7 +++ 9 files changed, 229 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/playwright.yml create mode 100644 e2e/e2eTest.spec.ts create mode 100644 playwright.config.ts create mode 100644 tests-examples/DataStoragePage.spec.ts create mode 100644 tests-examples/SessionStoragePage.spec.ts create mode 100644 tests-examples/login.spec.ts diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml new file mode 100644 index 0000000000..90b6b700d4 --- /dev/null +++ b/.github/workflows/playwright.yml @@ -0,0 +1,27 @@ +name: Playwright Tests +on: + push: + branches: [ main, master ] + pull_request: + branches: [ main, master ] +jobs: + test: + timeout-minutes: 60 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: 18 + - name: Install dependencies + run: npm ci + - name: Install Playwright Browsers + run: npx playwright install --with-deps + - name: Run Playwright tests + run: npx playwright test + - uses: actions/upload-artifact@v3 + if: always() + with: + name: playwright-report + path: playwright-report/ + retention-days: 30 diff --git a/.gitignore b/.gitignore index 4515240ce4..8dd2e83d09 100644 --- a/.gitignore +++ b/.gitignore @@ -128,3 +128,7 @@ src/plugins/* # !.vscode/i18n-ally-* +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ diff --git a/e2e/e2eTest.spec.ts b/e2e/e2eTest.spec.ts new file mode 100644 index 0000000000..c06f3bdba2 --- /dev/null +++ b/e2e/e2eTest.spec.ts @@ -0,0 +1,11 @@ +import { test, expect } from '@playwright/test'; +import { login } from '../tests-examples/login.spec' +import { createVfolder } from '../tests-examples/DataStoragePage.spec'; +import { createSession, deleteSession } from '../tests-examples/SessionStoragePage.spec'; + +test('E2E test', async ({ page }) => { + await page.goto('http://localhost:9081/'); + await login(page, 'test@lablup.com', 'test123!'); + await createVfolder(page, 'testvfolder') + await createSession(page, 'Ubuntu 20.04 aarch64', 'testvfolder', 'testSession'); +}); diff --git a/package-lock.json b/package-lock.json index fb3eb6ddc4..7beba206d0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -76,6 +76,7 @@ "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/preset-typescript": "^7.23.2", "@babel/types": "^7.23.2", + "@playwright/test": "^1.40.1", "@rollup/plugin-commonjs": "^25.0.4", "@rollup/plugin-node-resolve": "^15.2.1", "@rollup/plugin-replace": "^5.0.2", @@ -85,6 +86,7 @@ "@types/drawflow": "^0.0.6", "@types/estree": "1.0.2", "@types/hammerjs": "^2.0.42", + "@types/node": "^20.10.4", "@typescript-eslint/eslint-plugin": "^6.7.3", "@typescript-eslint/parser": "^6.7.3", "@web/dev-server": "^0.3.1", @@ -4507,6 +4509,21 @@ "picomatch": "^2.2.2" } }, + "node_modules/@playwright/test": { + "version": "1.40.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.40.1.tgz", + "integrity": "sha512-EaaawMTOeEItCRvfmkI9v6rBkF1svM8wjl/YPRrg2N2Wmp+4qJYkWtJsbew1szfKKDm6fPLy4YAanBhIlf9dWw==", + "dev": true, + "dependencies": { + "playwright": "1.40.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/@polymer/polymer": { "version": "3.5.1", "resolved": "https://registry.npmjs.org/@polymer/polymer/-/polymer-3.5.1.tgz", @@ -5048,9 +5065,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "18.18.13", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.13.tgz", - "integrity": "sha512-vXYZGRrSCreZmq1rEjMRLXJhiy8MrIeVasx+PCVlP414N7CJLHnMf+juVvjdprHyH+XRy3zKZLHeNueOpJCn0g==", + "version": "20.10.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.4.tgz", + "integrity": "sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==", "dependencies": { "undici-types": "~5.26.4" } @@ -9346,6 +9363,14 @@ "node": "^16.0.0 || ^18.0.0 || >=20.0.0" } }, + "node_modules/cypress/node_modules/@types/node": { + "version": "18.19.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.3.tgz", + "integrity": "sha512-k5fggr14DwAytoA/t8rPrIz++lXK7/DqckthCmoZOKNsEbJkId4Z//BqgApXBUGrGddrigYa1oqheo/7YmW4rg==", + "dependencies": { + "undici-types": "~5.26.4" + } + }, "node_modules/cypress/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -10782,6 +10807,15 @@ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.450.tgz", "integrity": "sha512-BLG5HxSELlrMx7dJ2s+8SFlsCtJp37Zpk2VAxyC6CZtbc+9AJeZHfYHbrlSgdXp6saQ8StMqOTEDaBKgA7u1sw==" }, + "node_modules/electron/node_modules/@types/node": { + "version": "18.19.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.3.tgz", + "integrity": "sha512-k5fggr14DwAytoA/t8rPrIz++lXK7/DqckthCmoZOKNsEbJkId4Z//BqgApXBUGrGddrigYa1oqheo/7YmW4rg==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, "node_modules/elegant-spinner": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", @@ -18320,6 +18354,36 @@ "node": ">= 10.0.0" } }, + "node_modules/playwright": { + "version": "1.40.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.40.1.tgz", + "integrity": "sha512-2eHI7IioIpQ0bS1Ovg/HszsN/XKNwEG1kbzSDDmADpclKc7CyqkHw7Mg2JCz/bbCxg25QUPcjksoMW7JcIFQmw==", + "dev": true, + "dependencies": { + "playwright-core": "1.40.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=16" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.40.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.40.1.tgz", + "integrity": "sha512-+hkOycxPiV534c4HhpfX6yrlawqVUzITRKwHAmYfmsVreltEl6fAZJ3DPfLMOODw0H3s1Itd6MDCWmP1fl/QvQ==", + "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", diff --git a/package.json b/package.json index 3b35123cde..887e3879cb 100644 --- a/package.json +++ b/package.json @@ -99,6 +99,7 @@ "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/preset-typescript": "^7.23.2", "@babel/types": "^7.23.2", + "@playwright/test": "^1.40.1", "@rollup/plugin-commonjs": "^25.0.4", "@rollup/plugin-node-resolve": "^15.2.1", "@rollup/plugin-replace": "^5.0.2", @@ -108,6 +109,7 @@ "@types/drawflow": "^0.0.6", "@types/estree": "1.0.2", "@types/hammerjs": "^2.0.42", + "@types/node": "^20.10.4", "@typescript-eslint/eslint-plugin": "^6.7.3", "@typescript-eslint/parser": "^6.7.3", "@web/dev-server": "^0.3.1", diff --git a/playwright.config.ts b/playwright.config.ts new file mode 100644 index 0000000000..bfe3e83033 --- /dev/null +++ b/playwright.config.ts @@ -0,0 +1,77 @@ +import { defineConfig, devices } from '@playwright/test'; + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './e2e', + /* Run tests in files in parallel */ + fullyParallel: true, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'html', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Base URL to use in actions like `await page.goto('/')`. */ + // baseURL: 'http://127.0.0.1:3000', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + }, + + { + name: 'firefox', + use: { ...devices['Desktop Firefox'] }, + }, + + { + name: 'webkit', + use: { ...devices['Desktop Safari'] }, + }, + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { ...devices['Pixel 5'] }, + // }, + // { + // name: 'Mobile Safari', + // use: { ...devices['iPhone 12'] }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { ...devices['Desktop Edge'], channel: 'msedge' }, + // }, + // { + // name: 'Google Chrome', + // use: { ...devices['Desktop Chrome'], channel: 'chrome' }, + // }, + ], + + /* Run your local dev server before starting the tests */ + // webServer: { + // command: 'npm run start', + // url: 'http://127.0.0.1:3000', + // reuseExistingServer: !process.env.CI, + // }, +}); diff --git a/tests-examples/DataStoragePage.spec.ts b/tests-examples/DataStoragePage.spec.ts new file mode 100644 index 0000000000..f2031fe7dd --- /dev/null +++ b/tests-examples/DataStoragePage.spec.ts @@ -0,0 +1,10 @@ +import { expect } from '@playwright/test'; + +export async function createVfolder(page: Page, vfolderName: string) { + await page.locator('#data').click(); + await page.getByRole('button', { name: 'add' }).click(); + await page.locator('#add-folder-name label').click(); + await page.getByRole('textbox', { name: 'Folder name*' }).fill('testvfolder'); + await page.getByRole('button', { name: 'Create', exact: true }).click(); + await expect(page.getByText('testvfolder')).toBeVisible(); +} \ No newline at end of file diff --git a/tests-examples/SessionStoragePage.spec.ts b/tests-examples/SessionStoragePage.spec.ts new file mode 100644 index 0000000000..8be1fabb86 --- /dev/null +++ b/tests-examples/SessionStoragePage.spec.ts @@ -0,0 +1,24 @@ +import { expect } from '@playwright/test'; + +export async function createSession( + page: Page, + environmnet: string, + mountVfolderName: string, + sessionName: string,) { + await page.locator('#session').click(); + await page.getByRole('heading', { name: 'more_horiz power_settings_new' }).getByLabel('power_settings_new').click(); + await page.getByRole('combobox', { name: 'Version*' }).click(); + await page.getByRole('option', { name: environmnet }).click(); + await page.getByRole('textbox', { name: 'label' }).click(); + await page.locator('backend-ai-session-view label').filter({ hasText: 'label' }).click(); + await page.getByRole('textbox', { name: 'label' }).fill(sessionName); + await page.getByRole('button', { name: 'arrow_forward' }).click(); + await page.locator('backend-ai-session-view').getByText(mountVfolderName).click(); + await page.getByRole('button', { name: 'arrow_forward' }).click(); + await page.getByRole('button', { name: 'arrow_forward' }).click(); + await page.getByRole('button', { name: 'rowing' }).click(); + await page.waitForTimeout(5000); + await page.getByRole('button', { name: 'close' }).click(); + await page.waitForTimeout(2000); + await expect(page.getByText(sessionName)).toBeVisible(); +} \ No newline at end of file diff --git a/tests-examples/login.spec.ts b/tests-examples/login.spec.ts new file mode 100644 index 0000000000..fe9415c288 --- /dev/null +++ b/tests-examples/login.spec.ts @@ -0,0 +1,7 @@ +export async function login(page: Page, email: string, password: string) { + await page.locator('#id_user_id label').click(); + await page.locator('#id_user_id label').fill(email); + await page.locator('#id_password label').click(); + await page.locator('#id_password label').fill(password); + await page.locator('#login-button').click(); +} \ No newline at end of file From cb750c745b880c1a91e8186f547523e1e093be44 Mon Sep 17 00:00:00 2001 From: gee05053 Date: Mon, 18 Dec 2023 15:16:47 +0900 Subject: [PATCH 18/48] feat:implment delete session test --- e2e/e2eTest.spec.ts | 1 + tests-examples/SessionStoragePage.spec.ts | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/e2e/e2eTest.spec.ts b/e2e/e2eTest.spec.ts index c06f3bdba2..58e2ca98af 100644 --- a/e2e/e2eTest.spec.ts +++ b/e2e/e2eTest.spec.ts @@ -8,4 +8,5 @@ test('E2E test', async ({ page }) => { await login(page, 'test@lablup.com', 'test123!'); await createVfolder(page, 'testvfolder') await createSession(page, 'Ubuntu 20.04 aarch64', 'testvfolder', 'testSession'); + await deleteSession(page, 'test@lablup.com', 'testSession') }); diff --git a/tests-examples/SessionStoragePage.spec.ts b/tests-examples/SessionStoragePage.spec.ts index 8be1fabb86..ac251287cc 100644 --- a/tests-examples/SessionStoragePage.spec.ts +++ b/tests-examples/SessionStoragePage.spec.ts @@ -21,4 +21,14 @@ export async function createSession( await page.getByRole('button', { name: 'close' }).click(); await page.waitForTimeout(2000); await expect(page.getByText(sessionName)).toBeVisible(); +} + +export async function deleteSession(page: Page, email: string, sessionName: string,) { + await page.locator('#session').click(); + await page.locator('#testSession-power').getByLabel('power_settings_new').click(); + await page.getByRole('button', { name: 'Okay' }).click(); + await page.waitForTimeout(5000); + await expect(page.getByText(sessionName)).toBeHidden(); + await page.getByRole('tab', { name: 'Finished' }).click(); + await expect(page.getByRole('row', { name: `1 ${email} ${sessionName}` }).locator('#vaadin-grid-cell-36')).toBeVisible(); } \ No newline at end of file From e063020a929d9eaba42994e6f724df64bc824eee Mon Sep 17 00:00:00 2001 From: gee05053 Date: Mon, 18 Dec 2023 15:17:29 +0900 Subject: [PATCH 19/48] fix:modify vfolder name to use params --- tests-examples/DataStoragePage.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests-examples/DataStoragePage.spec.ts b/tests-examples/DataStoragePage.spec.ts index f2031fe7dd..dcd51efe35 100644 --- a/tests-examples/DataStoragePage.spec.ts +++ b/tests-examples/DataStoragePage.spec.ts @@ -4,7 +4,7 @@ export async function createVfolder(page: Page, vfolderName: string) { await page.locator('#data').click(); await page.getByRole('button', { name: 'add' }).click(); await page.locator('#add-folder-name label').click(); - await page.getByRole('textbox', { name: 'Folder name*' }).fill('testvfolder'); + await page.getByRole('textbox', { name: 'Folder name*' }).fill(vfolderName); await page.getByRole('button', { name: 'Create', exact: true }).click(); - await expect(page.getByText('testvfolder')).toBeVisible(); + await expect(page.getByText(vfolderName)).toBeVisible(); } \ No newline at end of file From cd906f34dccbd603ca6a29e8b18aea0cb83af5bb Mon Sep 17 00:00:00 2001 From: gee05053 Date: Mon, 18 Dec 2023 15:29:50 +0900 Subject: [PATCH 20/48] fix:add login with endpoint --- e2e/e2eTest.spec.ts | 2 +- tests-examples/login.spec.ts | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/e2e/e2eTest.spec.ts b/e2e/e2eTest.spec.ts index 58e2ca98af..0e7a43336e 100644 --- a/e2e/e2eTest.spec.ts +++ b/e2e/e2eTest.spec.ts @@ -5,7 +5,7 @@ import { createSession, deleteSession } from '../tests-examples/SessionStoragePa test('E2E test', async ({ page }) => { await page.goto('http://localhost:9081/'); - await login(page, 'test@lablup.com', 'test123!'); + await login(page, 'test@lablup.com', 'test123!', 'http://127.0.0.1:8090'); await createVfolder(page, 'testvfolder') await createSession(page, 'Ubuntu 20.04 aarch64', 'testvfolder', 'testSession'); await deleteSession(page, 'test@lablup.com', 'testSession') diff --git a/tests-examples/login.spec.ts b/tests-examples/login.spec.ts index fe9415c288..7d31a38eaf 100644 --- a/tests-examples/login.spec.ts +++ b/tests-examples/login.spec.ts @@ -1,7 +1,9 @@ -export async function login(page: Page, email: string, password: string) { +export async function login(page: Page, email: string, password: string, endpoint: string) { await page.locator('#id_user_id label').click(); await page.locator('#id_user_id label').fill(email); await page.locator('#id_password label').click(); await page.locator('#id_password label').fill(password); + await page.locator('#id_api_endpoint label').click(); + await page.locator('#id_api_endpoint label').fill(endpoint); await page.locator('#login-button').click(); } \ No newline at end of file From d50da4cc46907c60b81deee064f403c5b85f3791 Mon Sep 17 00:00:00 2001 From: gee05053 Date: Mon, 18 Dec 2023 16:12:44 +0900 Subject: [PATCH 21/48] feat:implement delete vfolder test --- e2e/e2eTest.spec.ts | 3 ++- tests-examples/DataStoragePage.spec.ts | 9 +++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/e2e/e2eTest.spec.ts b/e2e/e2eTest.spec.ts index 0e7a43336e..3e9a4ef0be 100644 --- a/e2e/e2eTest.spec.ts +++ b/e2e/e2eTest.spec.ts @@ -1,6 +1,6 @@ import { test, expect } from '@playwright/test'; import { login } from '../tests-examples/login.spec' -import { createVfolder } from '../tests-examples/DataStoragePage.spec'; +import { createVfolder, deleteVfolder } from '../tests-examples/DataStoragePage.spec'; import { createSession, deleteSession } from '../tests-examples/SessionStoragePage.spec'; test('E2E test', async ({ page }) => { @@ -9,4 +9,5 @@ test('E2E test', async ({ page }) => { await createVfolder(page, 'testvfolder') await createSession(page, 'Ubuntu 20.04 aarch64', 'testvfolder', 'testSession'); await deleteSession(page, 'test@lablup.com', 'testSession') + await deleteVfolder(page, 'testvfolder') }); diff --git a/tests-examples/DataStoragePage.spec.ts b/tests-examples/DataStoragePage.spec.ts index dcd51efe35..e56709552a 100644 --- a/tests-examples/DataStoragePage.spec.ts +++ b/tests-examples/DataStoragePage.spec.ts @@ -7,4 +7,13 @@ export async function createVfolder(page: Page, vfolderName: string) { await page.getByRole('textbox', { name: 'Folder name*' }).fill(vfolderName); await page.getByRole('button', { name: 'Create', exact: true }).click(); await expect(page.getByText(vfolderName)).toBeVisible(); +} + +export async function deleteVfolder(page: Page, vfolderName: string) { + await page.locator('#data').click(); + await page.locator(`#controls[folder-name=${vfolderName}]`).locator('mwc-icon-button[icon="delete"]').click(); + await page.locator('#delete-folder-name').click(); + await page.locator('#delete-folder-name label').fill(vfolderName); + await page.locator('#delete-button').click(); + await expect(page.locator(`lablup-shields[folder-name=${vfolderName}][description="deleted-complete"]`)).toBeVisible(); } \ No newline at end of file From 761ad326265c33cf522330d1dcd979b7a7a493a6 Mon Sep 17 00:00:00 2001 From: gee05053 Date: Tue, 19 Dec 2023 13:04:00 +0900 Subject: [PATCH 22/48] feat:implement create and delete user --- e2e/e2eTest.spec.ts | 9 ++++-- tests-examples/CredentialPage.spec.ts | 40 +++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 3 deletions(-) create mode 100644 tests-examples/CredentialPage.spec.ts diff --git a/e2e/e2eTest.spec.ts b/e2e/e2eTest.spec.ts index 3e9a4ef0be..03ae73b179 100644 --- a/e2e/e2eTest.spec.ts +++ b/e2e/e2eTest.spec.ts @@ -2,12 +2,15 @@ import { test, expect } from '@playwright/test'; import { login } from '../tests-examples/login.spec' import { createVfolder, deleteVfolder } from '../tests-examples/DataStoragePage.spec'; import { createSession, deleteSession } from '../tests-examples/SessionStoragePage.spec'; +import { createUser, deleteUser } from '../tests-examples/CredentialPage.spec' test('E2E test', async ({ page }) => { await page.goto('http://localhost:9081/'); await login(page, 'test@lablup.com', 'test123!', 'http://127.0.0.1:8090'); - await createVfolder(page, 'testvfolder') + await createVfolder(page, 'testvfolder'); await createSession(page, 'Ubuntu 20.04 aarch64', 'testvfolder', 'testSession'); - await deleteSession(page, 'test@lablup.com', 'testSession') - await deleteVfolder(page, 'testvfolder') + await deleteSession(page, 'test@lablup.com', 'testSession'); + await deleteVfolder(page, 'testvfolder'); + await createUser(page, 'test8@lablup.com', 'test8', 'test123!'); + await deleteUser(page, 'test8\\@lablup\\.com'); }); diff --git a/tests-examples/CredentialPage.spec.ts b/tests-examples/CredentialPage.spec.ts new file mode 100644 index 0000000000..c5be0ff207 --- /dev/null +++ b/tests-examples/CredentialPage.spec.ts @@ -0,0 +1,40 @@ +import { expect } from '@playwright/test'; + +export async function createUser(page: Page, email:string, userName: string, password: string) { + + await page.locator('#credential').click(); + await page.waitForURL('**/credential'); + await page.locator('#mdc-tab-1').click(); + await page.locator('#mdc-tab-4').click(); + await page.locator('#add-user').click(); + await page.locator('#new-user-dialog #id_user_email').click(); + await page.locator('#new-user-dialog #id_user_email label').fill(email); + await page.locator('#new-user-dialog #id_user_name').click(); + await page.locator('#new-user-dialog #id_user_name label').fill(userName); + await page.locator('#new-user-dialog #id_user_password').click(); + await page.locator('#new-user-dialog #id_user_password label').fill(password); + await page.locator('#new-user-dialog #id_user_confirm').click(); + await page.locator('#new-user-dialog #id_user_confirm label').fill(password); + await page.locator('#new-user-dialog #create-user-button').click(); + await expect(page.locator('#active-user-list vaadin-grid-cell-content').filter({ hasText: email })).toBeVisible(); + await page.locator('#mdc-tab-2').click(); + await page.locator('#mdc-tab-6').click(); + await expect(page.locator('#active-credential-list vaadin-grid-cell-content').filter({ hasText: email })).toBeVisible(); +} + +export async function deleteUser(page: Page, email: string) { + const emailText = email.replace(/\\/g, ''); + await page.locator('#credential').click(); + await page.waitForURL('**/credential'); + await page.locator('#mdc-tab-1').click(); + await page.locator('#mdc-tab-4').click(); + await page.locator(`#controls[user-id=${email}]`).locator('mwc-icon-button[icon="delete_forever"]').click(); + await page.locator('#active-user-list #deleteOk').click(); + await expect(page.locator('#active-user-list vaadin-grid-cell-content').filter({ hasText: emailText })).toBeHidden(); + await page.locator('#mdc-tab-5').click(); + await expect(page.locator('#inactive-user-list vaadin-grid-cell-content').filter({ hasText: emailText })).toBeVisible(); + await page.locator('#mdc-tab-2').click(); + await expect(page.locator('#active-credential-list vaadin-grid-cell-content').filter({ hasText: emailText })).toBeHidden(); + await page.locator('#mdc-tab-7').click(); + await expect(page.locator('#inactive-credential-list vaadin-grid-cell-content').filter({ hasText: emailText })).toBeVisible(); +} \ No newline at end of file From bf52ed7e7248d14740dfb06287b8f359fc5759ae Mon Sep 17 00:00:00 2001 From: gee05053 Date: Tue, 19 Dec 2023 18:47:23 +0900 Subject: [PATCH 23/48] fix:modify code to use id --- cypress/commands/CredentialPage.cy.ts | 45 ----------------------- e2e/e2eTest.spec.ts | 8 ++-- tests-examples/CredentialPage.spec.ts | 18 ++++----- tests-examples/DataStoragePage.spec.ts | 10 +++-- tests-examples/SessionStoragePage.spec.ts | 29 ++++++++------- 5 files changed, 35 insertions(+), 75 deletions(-) diff --git a/cypress/commands/CredentialPage.cy.ts b/cypress/commands/CredentialPage.cy.ts index 095c548362..53303b5e04 100644 --- a/cypress/commands/CredentialPage.cy.ts +++ b/cypress/commands/CredentialPage.cy.ts @@ -108,49 +108,4 @@ Cypress.Commands.add('deleteUser', (email: string) => { .find('vaadin-grid-cell-content') .filter(`:contains(${email})`) .should('exist'); - /* - const userEmailInput = findShadowRoot( - 'backend-ai-webui > backend-ai-credential-view > #id_user_email', - ).find('input'); - const userNameInput = findShadowRoot( - 'backend-ai-webui > backend-ai-credential-view > #id_user_name', - ).find('input'); - const passwordInput = findShadowRoot( - 'backend-ai-webui > backend-ai-credential-view > #id_user_password', - ).find('input'); - const confirmPasswordInput = findShadowRoot( - 'backend-ai-webui > backend-ai-credential-view > #id_user_confirm', - ).find('input'); - const createUserButton = findShadowRoot( - 'backend-ai-webui > backend-ai-credential-view', - ).find('#create-user-button'); - addUserButton.click(); - cy.wait(500); - userEmailInput.type(email); - cy.wait(500); - userNameInput.type(userName); - cy.wait(500); - passwordInput.type(password); - cy.wait(500); - confirmPasswordInput.type(password); - cy.wait(500); - createUserButton.click(); - cy.wait(2000); - findShadowRoot( - 'backend-ai-webui > backend-ai-credential-view > #active-user-list', - ) - .find('vaadin-grid-cell-content') - .filter(`:contains(${email})`) - .should('exist'); - findShadowRoot('backend-ai-webui > backend-ai-credential-view') - .find('#mdc-tab-2') - .click(); - cy.wait(500); - findShadowRoot( - 'backend-ai-webui > backend-ai-credential-view > backend-ai-credential-list', - ) - .find('vaadin-grid-cell-content') - .filter(`:contains(${email})`) - .should('exist'); - */ }); diff --git a/e2e/e2eTest.spec.ts b/e2e/e2eTest.spec.ts index 03ae73b179..151fad5150 100644 --- a/e2e/e2eTest.spec.ts +++ b/e2e/e2eTest.spec.ts @@ -7,10 +7,10 @@ import { createUser, deleteUser } from '../tests-examples/CredentialPage.spec' test('E2E test', async ({ page }) => { await page.goto('http://localhost:9081/'); await login(page, 'test@lablup.com', 'test123!', 'http://127.0.0.1:8090'); - await createVfolder(page, 'testvfolder'); + await createVfolder(page, 'test2'); await createSession(page, 'Ubuntu 20.04 aarch64', 'testvfolder', 'testSession'); await deleteSession(page, 'test@lablup.com', 'testSession'); - await deleteVfolder(page, 'testvfolder'); - await createUser(page, 'test8@lablup.com', 'test8', 'test123!'); - await deleteUser(page, 'test8\\@lablup\\.com'); + await deleteVfolder(page, 'test2'); + await createUser(page, 'test9@lablup.com', 'test9', 'test123!'); + await deleteUser(page, 'test9\\@lablup\\.com'); }); diff --git a/tests-examples/CredentialPage.spec.ts b/tests-examples/CredentialPage.spec.ts index c5be0ff207..e95c102d94 100644 --- a/tests-examples/CredentialPage.spec.ts +++ b/tests-examples/CredentialPage.spec.ts @@ -4,8 +4,8 @@ export async function createUser(page: Page, email:string, userName: string, pas await page.locator('#credential').click(); await page.waitForURL('**/credential'); - await page.locator('#mdc-tab-1').click(); - await page.locator('#mdc-tab-4').click(); + await page.getByRole('tab', { name: 'Users' }).click(); + await page.getByRole('tab', { name: 'Active', exact: true }).click(); await page.locator('#add-user').click(); await page.locator('#new-user-dialog #id_user_email').click(); await page.locator('#new-user-dialog #id_user_email label').fill(email); @@ -17,8 +17,8 @@ export async function createUser(page: Page, email:string, userName: string, pas await page.locator('#new-user-dialog #id_user_confirm label').fill(password); await page.locator('#new-user-dialog #create-user-button').click(); await expect(page.locator('#active-user-list vaadin-grid-cell-content').filter({ hasText: email })).toBeVisible(); - await page.locator('#mdc-tab-2').click(); - await page.locator('#mdc-tab-6').click(); + await page.getByRole('tab', { name: 'Credentials' }).click(); + await page.getByRole('tab', { name: 'Active', exact: true }).click(); await expect(page.locator('#active-credential-list vaadin-grid-cell-content').filter({ hasText: email })).toBeVisible(); } @@ -26,15 +26,15 @@ export async function deleteUser(page: Page, email: string) { const emailText = email.replace(/\\/g, ''); await page.locator('#credential').click(); await page.waitForURL('**/credential'); - await page.locator('#mdc-tab-1').click(); - await page.locator('#mdc-tab-4').click(); + await page.getByRole('tab', { name: 'Users' }).click(); + await page.getByRole('tab', { name: 'Active', exact: true }).click(); await page.locator(`#controls[user-id=${email}]`).locator('mwc-icon-button[icon="delete_forever"]').click(); await page.locator('#active-user-list #deleteOk').click(); await expect(page.locator('#active-user-list vaadin-grid-cell-content').filter({ hasText: emailText })).toBeHidden(); - await page.locator('#mdc-tab-5').click(); + await page.getByRole('tab', { name: 'Inactive' }).click(); await expect(page.locator('#inactive-user-list vaadin-grid-cell-content').filter({ hasText: emailText })).toBeVisible(); - await page.locator('#mdc-tab-2').click(); + await page.getByRole('tab', { name: 'Credentials' }).click(); await expect(page.locator('#active-credential-list vaadin-grid-cell-content').filter({ hasText: emailText })).toBeHidden(); - await page.locator('#mdc-tab-7').click(); + await page.getByRole('tab', { name: 'Inactive' }).click(); await expect(page.locator('#inactive-credential-list vaadin-grid-cell-content').filter({ hasText: emailText })).toBeVisible(); } \ No newline at end of file diff --git a/tests-examples/DataStoragePage.spec.ts b/tests-examples/DataStoragePage.spec.ts index e56709552a..a4cb030a9a 100644 --- a/tests-examples/DataStoragePage.spec.ts +++ b/tests-examples/DataStoragePage.spec.ts @@ -2,15 +2,17 @@ import { expect } from '@playwright/test'; export async function createVfolder(page: Page, vfolderName: string) { await page.locator('#data').click(); - await page.getByRole('button', { name: 'add' }).click(); - await page.locator('#add-folder-name label').click(); - await page.getByRole('textbox', { name: 'Folder name*' }).fill(vfolderName); - await page.getByRole('button', { name: 'Create', exact: true }).click(); + await page.waitForURL('**/data'); + await page.locator('#add-folder').click(); + await page.locator('#add-folder-name').click(); + await page.locator('#add-folder-name label').fill(vfolderName); + await page.locator('#add-button').click(); await expect(page.getByText(vfolderName)).toBeVisible(); } export async function deleteVfolder(page: Page, vfolderName: string) { await page.locator('#data').click(); + await page.waitForURL('**/data'); await page.locator(`#controls[folder-name=${vfolderName}]`).locator('mwc-icon-button[icon="delete"]').click(); await page.locator('#delete-folder-name').click(); await page.locator('#delete-folder-name label').fill(vfolderName); diff --git a/tests-examples/SessionStoragePage.spec.ts b/tests-examples/SessionStoragePage.spec.ts index ac251287cc..6f975346f2 100644 --- a/tests-examples/SessionStoragePage.spec.ts +++ b/tests-examples/SessionStoragePage.spec.ts @@ -6,17 +6,18 @@ export async function createSession( mountVfolderName: string, sessionName: string,) { await page.locator('#session').click(); - await page.getByRole('heading', { name: 'more_horiz power_settings_new' }).getByLabel('power_settings_new').click(); - await page.getByRole('combobox', { name: 'Version*' }).click(); - await page.getByRole('option', { name: environmnet }).click(); - await page.getByRole('textbox', { name: 'label' }).click(); - await page.locator('backend-ai-session-view label').filter({ hasText: 'label' }).click(); - await page.getByRole('textbox', { name: 'label' }).fill(sessionName); - await page.getByRole('button', { name: 'arrow_forward' }).click(); - await page.locator('backend-ai-session-view').getByText(mountVfolderName).click(); - await page.getByRole('button', { name: 'arrow_forward' }).click(); - await page.getByRole('button', { name: 'arrow_forward' }).click(); - await page.getByRole('button', { name: 'rowing' }).click(); + await page.waitForURL('**/job'); + await page.getByRole('tab', { name: 'Running' }).click(); + await page.locator('backend-ai-session-view').locator('#launch-session').click(); + await page.locator('backend-ai-session-view').locator('#version').click(); + await page.locator('backend-ai-session-view').getByRole('option', { name: environmnet }).click(); + await page.locator('backend-ai-session-view').locator('#session-name').click(); + await page.locator('backend-ai-session-view').locator('#session-name label').fill(sessionName); + await page.locator('backend-ai-session-view').locator('#next-button').click(); + await page.getByText(`${mountVfolderName} local:volume1`).click(); + await page.locator('backend-ai-session-view').locator('#next-button').click(); + await page.locator('backend-ai-session-view').locator('#next-button').click(); + await page.locator('backend-ai-session-view').locator('#launch-button').click(); await page.waitForTimeout(5000); await page.getByRole('button', { name: 'close' }).click(); await page.waitForTimeout(2000); @@ -25,8 +26,10 @@ export async function createSession( export async function deleteSession(page: Page, email: string, sessionName: string,) { await page.locator('#session').click(); - await page.locator('#testSession-power').getByLabel('power_settings_new').click(); - await page.getByRole('button', { name: 'Okay' }).click(); + await page.waitForURL('**/job'); + await page.getByRole('tab', { name: 'Running' }).click(); + await page.locator(`#${sessionName}-power`).getByLabel('power_settings_new').click(); + await page.locator(`#terminate-session-dialog`).locator('mwc-button[class="ok"]').click(); await page.waitForTimeout(5000); await expect(page.getByText(sessionName)).toBeHidden(); await page.getByRole('tab', { name: 'Finished' }).click(); From 6a600457b2d94013d0c267ab9cc47fcf9f2fb446 Mon Sep 17 00:00:00 2001 From: gee05053 Date: Tue, 19 Dec 2023 18:48:54 +0900 Subject: [PATCH 24/48] fix:add ; --- e2e/e2eTest.spec.ts | 4 ++-- tests-examples/CredentialPage.spec.ts | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/e2e/e2eTest.spec.ts b/e2e/e2eTest.spec.ts index 151fad5150..1c7893a451 100644 --- a/e2e/e2eTest.spec.ts +++ b/e2e/e2eTest.spec.ts @@ -1,8 +1,8 @@ import { test, expect } from '@playwright/test'; -import { login } from '../tests-examples/login.spec' +import { login } from '../tests-examples/login.spec'; import { createVfolder, deleteVfolder } from '../tests-examples/DataStoragePage.spec'; import { createSession, deleteSession } from '../tests-examples/SessionStoragePage.spec'; -import { createUser, deleteUser } from '../tests-examples/CredentialPage.spec' +import { createUser, deleteUser } from '../tests-examples/CredentialPage.spec'; test('E2E test', async ({ page }) => { await page.goto('http://localhost:9081/'); diff --git a/tests-examples/CredentialPage.spec.ts b/tests-examples/CredentialPage.spec.ts index e95c102d94..c4c374552d 100644 --- a/tests-examples/CredentialPage.spec.ts +++ b/tests-examples/CredentialPage.spec.ts @@ -1,7 +1,6 @@ import { expect } from '@playwright/test'; export async function createUser(page: Page, email:string, userName: string, password: string) { - await page.locator('#credential').click(); await page.waitForURL('**/credential'); await page.getByRole('tab', { name: 'Users' }).click(); From f44554c7e432b90483bf41092e66621baf5e6b38 Mon Sep 17 00:00:00 2001 From: gee05053 Date: Tue, 19 Dec 2023 19:05:40 +0900 Subject: [PATCH 25/48] fix:apply prettier --- .prettierignore | 1 + e2e/e2eTest.spec.ts | 16 ----- playwright.config.ts | 2 +- playwright/.prettierrc.json | 10 +++ playwright/e2eTest.spec.ts | 21 ++++++ .../pages}/CredentialPage.spec.ts | 50 +++++++++++--- .../pages}/DataStoragePage.spec.ts | 13 +++- .../pages/LoginPage.spec.ts | 9 ++- playwright/pages/SessionStoragePage.spec.ts | 67 +++++++++++++++++++ tests-examples/SessionStoragePage.spec.ts | 37 ---------- 10 files changed, 158 insertions(+), 68 deletions(-) delete mode 100644 e2e/e2eTest.spec.ts create mode 100644 playwright/.prettierrc.json create mode 100644 playwright/e2eTest.spec.ts rename {tests-examples => playwright/pages}/CredentialPage.spec.ts (59%) rename {tests-examples => playwright/pages}/DataStoragePage.spec.ts (73%) rename tests-examples/login.spec.ts => playwright/pages/LoginPage.spec.ts (78%) create mode 100644 playwright/pages/SessionStoragePage.spec.ts delete mode 100644 tests-examples/SessionStoragePage.spec.ts diff --git a/.prettierignore b/.prettierignore index 7f25b5077b..0351dcecca 100644 --- a/.prettierignore +++ b/.prettierignore @@ -3,5 +3,6 @@ src/lib/ !/src !/react !/cypress +!/playwright **/__generated__/*.graphql.ts *.graphql \ No newline at end of file diff --git a/e2e/e2eTest.spec.ts b/e2e/e2eTest.spec.ts deleted file mode 100644 index 1c7893a451..0000000000 --- a/e2e/e2eTest.spec.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { test, expect } from '@playwright/test'; -import { login } from '../tests-examples/login.spec'; -import { createVfolder, deleteVfolder } from '../tests-examples/DataStoragePage.spec'; -import { createSession, deleteSession } from '../tests-examples/SessionStoragePage.spec'; -import { createUser, deleteUser } from '../tests-examples/CredentialPage.spec'; - -test('E2E test', async ({ page }) => { - await page.goto('http://localhost:9081/'); - await login(page, 'test@lablup.com', 'test123!', 'http://127.0.0.1:8090'); - await createVfolder(page, 'test2'); - await createSession(page, 'Ubuntu 20.04 aarch64', 'testvfolder', 'testSession'); - await deleteSession(page, 'test@lablup.com', 'testSession'); - await deleteVfolder(page, 'test2'); - await createUser(page, 'test9@lablup.com', 'test9', 'test123!'); - await deleteUser(page, 'test9\\@lablup\\.com'); -}); diff --git a/playwright.config.ts b/playwright.config.ts index bfe3e83033..b1172151bf 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -10,7 +10,7 @@ import { defineConfig, devices } from '@playwright/test'; * See https://playwright.dev/docs/test-configuration. */ export default defineConfig({ - testDir: './e2e', + testDir: './playwright/', /* Run tests in files in parallel */ fullyParallel: true, /* Fail the build on CI if you accidentally left test.only in the source code. */ diff --git a/playwright/.prettierrc.json b/playwright/.prettierrc.json new file mode 100644 index 0000000000..a632bb880d --- /dev/null +++ b/playwright/.prettierrc.json @@ -0,0 +1,10 @@ +{ + "tabWidth": 2, + "semi": true, + "singleQuote": true, + "importOrderSeparation": true, + "printWidth": 80, + "bracketSpacing": true, + "trailingComma": "all", + "singleAttributePerLine": false +} diff --git a/playwright/e2eTest.spec.ts b/playwright/e2eTest.spec.ts new file mode 100644 index 0000000000..5fa7132f51 --- /dev/null +++ b/playwright/e2eTest.spec.ts @@ -0,0 +1,21 @@ +import { test } from '@playwright/test'; +import { login } from './pages/LoginPage.spec'; +import { createVfolder, deleteVfolder } from './pages/DataStoragePage.spec'; +import { createSession, deleteSession } from './pages/SessionStoragePage.spec'; +import { createUser, deleteUser } from './pages/CredentialPage.spec'; + +test('E2E test', async ({ page }) => { + await page.goto('http://localhost:9081/'); + await login(page, 'test@lablup.com', 'test123!', 'http://127.0.0.1:8090'); + await createVfolder(page, 'test2'); + await createSession( + page, + 'Ubuntu 20.04 aarch64', + 'testvfolder', + 'testSession', + ); + await deleteSession(page, 'test@lablup.com', 'testSession'); + await deleteVfolder(page, 'test2'); + await createUser(page, 'test9@lablup.com', 'test9', 'test123!'); + await deleteUser(page, 'test9\\@lablup\\.com'); +}); diff --git a/tests-examples/CredentialPage.spec.ts b/playwright/pages/CredentialPage.spec.ts similarity index 59% rename from tests-examples/CredentialPage.spec.ts rename to playwright/pages/CredentialPage.spec.ts index c4c374552d..76b5bb5328 100644 --- a/tests-examples/CredentialPage.spec.ts +++ b/playwright/pages/CredentialPage.spec.ts @@ -1,6 +1,11 @@ import { expect } from '@playwright/test'; -export async function createUser(page: Page, email:string, userName: string, password: string) { +export async function createUser( + page: Page, + email: string, + userName: string, + password: string, +) { await page.locator('#credential').click(); await page.waitForURL('**/credential'); await page.getByRole('tab', { name: 'Users' }).click(); @@ -15,10 +20,18 @@ export async function createUser(page: Page, email:string, userName: string, pas await page.locator('#new-user-dialog #id_user_confirm').click(); await page.locator('#new-user-dialog #id_user_confirm label').fill(password); await page.locator('#new-user-dialog #create-user-button').click(); - await expect(page.locator('#active-user-list vaadin-grid-cell-content').filter({ hasText: email })).toBeVisible(); + await expect( + page + .locator('#active-user-list vaadin-grid-cell-content') + .filter({ hasText: email }), + ).toBeVisible(); await page.getByRole('tab', { name: 'Credentials' }).click(); await page.getByRole('tab', { name: 'Active', exact: true }).click(); - await expect(page.locator('#active-credential-list vaadin-grid-cell-content').filter({ hasText: email })).toBeVisible(); + await expect( + page + .locator('#active-credential-list vaadin-grid-cell-content') + .filter({ hasText: email }), + ).toBeVisible(); } export async function deleteUser(page: Page, email: string) { @@ -27,13 +40,32 @@ export async function deleteUser(page: Page, email: string) { await page.waitForURL('**/credential'); await page.getByRole('tab', { name: 'Users' }).click(); await page.getByRole('tab', { name: 'Active', exact: true }).click(); - await page.locator(`#controls[user-id=${email}]`).locator('mwc-icon-button[icon="delete_forever"]').click(); + await page + .locator(`#controls[user-id=${email}]`) + .locator('mwc-icon-button[icon="delete_forever"]') + .click(); await page.locator('#active-user-list #deleteOk').click(); - await expect(page.locator('#active-user-list vaadin-grid-cell-content').filter({ hasText: emailText })).toBeHidden(); + await expect( + page + .locator('#active-user-list vaadin-grid-cell-content') + .filter({ hasText: emailText }), + ).toBeHidden(); await page.getByRole('tab', { name: 'Inactive' }).click(); - await expect(page.locator('#inactive-user-list vaadin-grid-cell-content').filter({ hasText: emailText })).toBeVisible(); + await expect( + page + .locator('#inactive-user-list vaadin-grid-cell-content') + .filter({ hasText: emailText }), + ).toBeVisible(); await page.getByRole('tab', { name: 'Credentials' }).click(); - await expect(page.locator('#active-credential-list vaadin-grid-cell-content').filter({ hasText: emailText })).toBeHidden(); + await expect( + page + .locator('#active-credential-list vaadin-grid-cell-content') + .filter({ hasText: emailText }), + ).toBeHidden(); await page.getByRole('tab', { name: 'Inactive' }).click(); - await expect(page.locator('#inactive-credential-list vaadin-grid-cell-content').filter({ hasText: emailText })).toBeVisible(); -} \ No newline at end of file + await expect( + page + .locator('#inactive-credential-list vaadin-grid-cell-content') + .filter({ hasText: emailText }), + ).toBeVisible(); +} diff --git a/tests-examples/DataStoragePage.spec.ts b/playwright/pages/DataStoragePage.spec.ts similarity index 73% rename from tests-examples/DataStoragePage.spec.ts rename to playwright/pages/DataStoragePage.spec.ts index a4cb030a9a..0460def3c3 100644 --- a/tests-examples/DataStoragePage.spec.ts +++ b/playwright/pages/DataStoragePage.spec.ts @@ -13,9 +13,16 @@ export async function createVfolder(page: Page, vfolderName: string) { export async function deleteVfolder(page: Page, vfolderName: string) { await page.locator('#data').click(); await page.waitForURL('**/data'); - await page.locator(`#controls[folder-name=${vfolderName}]`).locator('mwc-icon-button[icon="delete"]').click(); + await page + .locator(`#controls[folder-name=${vfolderName}]`) + .locator('mwc-icon-button[icon="delete"]') + .click(); await page.locator('#delete-folder-name').click(); await page.locator('#delete-folder-name label').fill(vfolderName); await page.locator('#delete-button').click(); - await expect(page.locator(`lablup-shields[folder-name=${vfolderName}][description="deleted-complete"]`)).toBeVisible(); -} \ No newline at end of file + await expect( + page.locator( + `lablup-shields[folder-name=${vfolderName}][description="deleted-complete"]`, + ), + ).toBeVisible(); +} diff --git a/tests-examples/login.spec.ts b/playwright/pages/LoginPage.spec.ts similarity index 78% rename from tests-examples/login.spec.ts rename to playwright/pages/LoginPage.spec.ts index 7d31a38eaf..d74ef67ceb 100644 --- a/tests-examples/login.spec.ts +++ b/playwright/pages/LoginPage.spec.ts @@ -1,4 +1,9 @@ -export async function login(page: Page, email: string, password: string, endpoint: string) { +export async function login( + page: Page, + email: string, + password: string, + endpoint: string, +) { await page.locator('#id_user_id label').click(); await page.locator('#id_user_id label').fill(email); await page.locator('#id_password label').click(); @@ -6,4 +11,4 @@ export async function login(page: Page, email: string, password: string, endpoin await page.locator('#id_api_endpoint label').click(); await page.locator('#id_api_endpoint label').fill(endpoint); await page.locator('#login-button').click(); -} \ No newline at end of file +} diff --git a/playwright/pages/SessionStoragePage.spec.ts b/playwright/pages/SessionStoragePage.spec.ts new file mode 100644 index 0000000000..4ed5f066d4 --- /dev/null +++ b/playwright/pages/SessionStoragePage.spec.ts @@ -0,0 +1,67 @@ +import { expect } from '@playwright/test'; + +export async function createSession( + page: Page, + environmnet: string, + mountVfolderName: string, + sessionName: string, +) { + await page.locator('#session').click(); + await page.waitForURL('**/job'); + await page.getByRole('tab', { name: 'Running' }).click(); + await page + .locator('backend-ai-session-view') + .locator('#launch-session') + .click(); + await page.locator('backend-ai-session-view').locator('#version').click(); + await page + .locator('backend-ai-session-view') + .getByRole('option', { name: environmnet }) + .click(); + await page + .locator('backend-ai-session-view') + .locator('#session-name') + .click(); + await page + .locator('backend-ai-session-view') + .locator('#session-name label') + .fill(sessionName); + await page.locator('backend-ai-session-view').locator('#next-button').click(); + await page.getByText(`${mountVfolderName} local:volume1`).click(); + await page.locator('backend-ai-session-view').locator('#next-button').click(); + await page.locator('backend-ai-session-view').locator('#next-button').click(); + await page + .locator('backend-ai-session-view') + .locator('#launch-button') + .click(); + await page.waitForTimeout(5000); + await page.getByRole('button', { name: 'close' }).click(); + await page.waitForTimeout(2000); + await expect(page.getByText(sessionName)).toBeVisible(); +} + +export async function deleteSession( + page: Page, + email: string, + sessionName: string, +) { + await page.locator('#session').click(); + await page.waitForURL('**/job'); + await page.getByRole('tab', { name: 'Running' }).click(); + await page + .locator(`#${sessionName}-power`) + .getByLabel('power_settings_new') + .click(); + await page + .locator(`#terminate-session-dialog`) + .locator('mwc-button[class="ok"]') + .click(); + await page.waitForTimeout(5000); + await expect(page.getByText(sessionName)).toBeHidden(); + await page.getByRole('tab', { name: 'Finished' }).click(); + await expect( + page + .getByRole('row', { name: `1 ${email} ${sessionName}` }) + .locator('#vaadin-grid-cell-36'), + ).toBeVisible(); +} diff --git a/tests-examples/SessionStoragePage.spec.ts b/tests-examples/SessionStoragePage.spec.ts deleted file mode 100644 index 6f975346f2..0000000000 --- a/tests-examples/SessionStoragePage.spec.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { expect } from '@playwright/test'; - -export async function createSession( - page: Page, - environmnet: string, - mountVfolderName: string, - sessionName: string,) { - await page.locator('#session').click(); - await page.waitForURL('**/job'); - await page.getByRole('tab', { name: 'Running' }).click(); - await page.locator('backend-ai-session-view').locator('#launch-session').click(); - await page.locator('backend-ai-session-view').locator('#version').click(); - await page.locator('backend-ai-session-view').getByRole('option', { name: environmnet }).click(); - await page.locator('backend-ai-session-view').locator('#session-name').click(); - await page.locator('backend-ai-session-view').locator('#session-name label').fill(sessionName); - await page.locator('backend-ai-session-view').locator('#next-button').click(); - await page.getByText(`${mountVfolderName} local:volume1`).click(); - await page.locator('backend-ai-session-view').locator('#next-button').click(); - await page.locator('backend-ai-session-view').locator('#next-button').click(); - await page.locator('backend-ai-session-view').locator('#launch-button').click(); - await page.waitForTimeout(5000); - await page.getByRole('button', { name: 'close' }).click(); - await page.waitForTimeout(2000); - await expect(page.getByText(sessionName)).toBeVisible(); -} - -export async function deleteSession(page: Page, email: string, sessionName: string,) { - await page.locator('#session').click(); - await page.waitForURL('**/job'); - await page.getByRole('tab', { name: 'Running' }).click(); - await page.locator(`#${sessionName}-power`).getByLabel('power_settings_new').click(); - await page.locator(`#terminate-session-dialog`).locator('mwc-button[class="ok"]').click(); - await page.waitForTimeout(5000); - await expect(page.getByText(sessionName)).toBeHidden(); - await page.getByRole('tab', { name: 'Finished' }).click(); - await expect(page.getByRole('row', { name: `1 ${email} ${sessionName}` }).locator('#vaadin-grid-cell-36')).toBeVisible(); -} \ No newline at end of file From 79af35467052e77414e039373d531a4318d70a3b Mon Sep 17 00:00:00 2001 From: gee05053 Date: Wed, 20 Dec 2023 09:54:36 +0900 Subject: [PATCH 26/48] fix:change sessionStoragePage to sessionPage --- .../pages/{SessionStoragePage.spec.ts => SessionPage.spec.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename playwright/pages/{SessionStoragePage.spec.ts => SessionPage.spec.ts} (100%) diff --git a/playwright/pages/SessionStoragePage.spec.ts b/playwright/pages/SessionPage.spec.ts similarity index 100% rename from playwright/pages/SessionStoragePage.spec.ts rename to playwright/pages/SessionPage.spec.ts From 6d7e7c8152aed0dc2645466fc0a3b92c4d209885 Mon Sep 17 00:00:00 2001 From: gee05053 Date: Wed, 20 Dec 2023 10:47:40 +0900 Subject: [PATCH 27/48] fix:wrong import --- playwright/e2eTest.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playwright/e2eTest.spec.ts b/playwright/e2eTest.spec.ts index 5fa7132f51..d8fdca8d98 100644 --- a/playwright/e2eTest.spec.ts +++ b/playwright/e2eTest.spec.ts @@ -1,7 +1,7 @@ import { test } from '@playwright/test'; import { login } from './pages/LoginPage.spec'; import { createVfolder, deleteVfolder } from './pages/DataStoragePage.spec'; -import { createSession, deleteSession } from './pages/SessionStoragePage.spec'; +import { createSession, deleteSession } from './pages/SessionPage.spec'; import { createUser, deleteUser } from './pages/CredentialPage.spec'; test('E2E test', async ({ page }) => { From ed49d55ec43b6701e644e1248e6da8e70779bfd4 Mon Sep 17 00:00:00 2001 From: gee05053 Date: Thu, 21 Dec 2023 17:15:46 +0900 Subject: [PATCH 28/48] fix:remove cypress --- .eslintignore | 3 +- .github/workflows/playwright.yml | 27 - .prettierignore | 1 - cypress.config.ts | 16 - cypress/.prettierrc.json | 10 - cypress/commands/CredentialPage.cy.ts | 111 -- cypress/commands/DataStoragePage.cy.ts | 52 - cypress/commands/LoginPage.cy.ts | 23 - cypress/commands/SessionPage.cy.ts | 97 -- cypress/e2e/e2eTest.cy.ts | 39 - cypress/fixtures/example.json | 5 - cypress/helper/FindShadowRoot.cy.ts | 12 - cypress/support/commands.ts | 37 - cypress/support/component-index.html | 12 - cypress/support/component.ts | 39 - cypress/support/e2e.ts | 20 - package-lock.json | 1327 +++--------------------- package.json | 5 +- 18 files changed, 151 insertions(+), 1685 deletions(-) delete mode 100644 .github/workflows/playwright.yml delete mode 100644 cypress.config.ts delete mode 100644 cypress/.prettierrc.json delete mode 100644 cypress/commands/CredentialPage.cy.ts delete mode 100644 cypress/commands/DataStoragePage.cy.ts delete mode 100644 cypress/commands/LoginPage.cy.ts delete mode 100644 cypress/commands/SessionPage.cy.ts delete mode 100644 cypress/e2e/e2eTest.cy.ts delete mode 100644 cypress/fixtures/example.json delete mode 100644 cypress/helper/FindShadowRoot.cy.ts delete mode 100644 cypress/support/commands.ts delete mode 100644 cypress/support/component-index.html delete mode 100644 cypress/support/component.ts delete mode 100644 cypress/support/e2e.ts diff --git a/.eslintignore b/.eslintignore index 119a34143e..9d9e4add2c 100644 --- a/.eslintignore +++ b/.eslintignore @@ -15,5 +15,4 @@ src/lib/backend.ai-client-node.ts src/lib/backend.ai-client-node-to-es6.js src/lib/backend.ai-client-node-test-native-es6.js src/lib/Chart.min.js -src/lib/json_to_csv.js -cypress/* \ No newline at end of file +src/lib/json_to_csv.js \ No newline at end of file diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml deleted file mode 100644 index 90b6b700d4..0000000000 --- a/.github/workflows/playwright.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: Playwright Tests -on: - push: - branches: [ main, master ] - pull_request: - branches: [ main, master ] -jobs: - test: - timeout-minutes: 60 - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 - with: - node-version: 18 - - name: Install dependencies - run: npm ci - - name: Install Playwright Browsers - run: npx playwright install --with-deps - - name: Run Playwright tests - run: npx playwright test - - uses: actions/upload-artifact@v3 - if: always() - with: - name: playwright-report - path: playwright-report/ - retention-days: 30 diff --git a/.prettierignore b/.prettierignore index 0351dcecca..0dca7eedf0 100644 --- a/.prettierignore +++ b/.prettierignore @@ -2,7 +2,6 @@ src/lib/ !/src !/react -!/cypress !/playwright **/__generated__/*.graphql.ts *.graphql \ No newline at end of file diff --git a/cypress.config.ts b/cypress.config.ts deleted file mode 100644 index 1471a7b825..0000000000 --- a/cypress.config.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { defineConfig } from "cypress"; - -export default defineConfig({ - e2e: { - setupNodeEvents(on, config) { - // implement node event listeners here - }, - }, - - component: { - devServer: { - framework: "react", - bundler: "webpack", - }, - }, -}); diff --git a/cypress/.prettierrc.json b/cypress/.prettierrc.json deleted file mode 100644 index a632bb880d..0000000000 --- a/cypress/.prettierrc.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "tabWidth": 2, - "semi": true, - "singleQuote": true, - "importOrderSeparation": true, - "printWidth": 80, - "bracketSpacing": true, - "trailingComma": "all", - "singleAttributePerLine": false -} diff --git a/cypress/commands/CredentialPage.cy.ts b/cypress/commands/CredentialPage.cy.ts deleted file mode 100644 index 53303b5e04..0000000000 --- a/cypress/commands/CredentialPage.cy.ts +++ /dev/null @@ -1,111 +0,0 @@ -import { findShadowRoot } from '../helper/FindShadowRoot.cy'; - -Cypress.Commands.add( - 'addUser', - (email: string, userName: string, password: string) => { - findShadowRoot('backend-ai-webui').find('#credential').click(); - cy.wait(1000); - const addUserButton = findShadowRoot( - 'backend-ai-webui > backend-ai-credential-view', - ).find('#add-user'); - const userEmailInput = findShadowRoot( - 'backend-ai-webui > backend-ai-credential-view > #id_user_email', - ).find('input'); - const userNameInput = findShadowRoot( - 'backend-ai-webui > backend-ai-credential-view > #id_user_name', - ).find('input'); - const passwordInput = findShadowRoot( - 'backend-ai-webui > backend-ai-credential-view > #id_user_password', - ).find('input'); - const confirmPasswordInput = findShadowRoot( - 'backend-ai-webui > backend-ai-credential-view > #id_user_confirm', - ).find('input'); - const createUserButton = findShadowRoot( - 'backend-ai-webui > backend-ai-credential-view', - ).find('#create-user-button'); - const credentialsTab = findShadowRoot( - 'backend-ai-webui > backend-ai-credential-view', - ).find('#mdc-tab-2'); - addUserButton.click(); - cy.wait(500); - userEmailInput.type(email); - cy.wait(500); - userNameInput.type(userName); - cy.wait(500); - passwordInput.type(password); - cy.wait(500); - confirmPasswordInput.type(password); - cy.wait(500); - createUserButton.click(); - cy.wait(2000); - findShadowRoot( - 'backend-ai-webui > backend-ai-credential-view > #active-user-list', - ) - .find('vaadin-grid-cell-content') - .filter(`:contains(${email})`) - .should('exist'); - credentialsTab.click(); - cy.wait(500); - findShadowRoot( - 'backend-ai-webui > backend-ai-credential-view > #active-credential-list', - ) - .find('vaadin-grid-cell-content') - .filter(`:contains(${email})`) - .should('exist'); - }, -); - -Cypress.Commands.add('deleteUser', (email: string) => { - findShadowRoot('backend-ai-webui').find('#credential').click(); - cy.wait(1000); - const userTab = findShadowRoot( - 'backend-ai-webui > backend-ai-credential-view', - ).find('#mdc-tab-1'); - const deleteUserButton = findShadowRoot( - 'backend-ai-webui > backend-ai-credential-view > #active-user-list', - ) - .find(`div[user-id="${email}"]`) - .find('mwc-icon-button[icon="delete_forever"]'); - const agreeButton = findShadowRoot( - 'backend-ai-webui > backend-ai-credential-view > #active-user-list', - ).find('#deleteOk'); - const userInactiveSubTab = findShadowRoot( - 'backend-ai-webui > backend-ai-credential-view', - ).find('#mdc-tab-5'); - const credentialsTab = findShadowRoot( - 'backend-ai-webui > backend-ai-credential-view', - ).find('#mdc-tab-2'); - const credentialInactiveSubTab = findShadowRoot( - 'backend-ai-webui > backend-ai-credential-view', - ).find('#mdc-tab-7'); - userTab.click(); - cy.wait(500); - deleteUserButton.click(); - cy.wait(500); - agreeButton.click(); - cy.wait(2000); - findShadowRoot( - 'backend-ai-webui > backend-ai-credential-view > #active-user-list', - ) - .find('vaadin-grid-cell-content') - .filter(`:contains(${email})`) - .should('not.exist'); - userInactiveSubTab.click(); - cy.wait(500); - findShadowRoot( - 'backend-ai-webui > backend-ai-credential-view > #inactive-user-list', - ) - .find('vaadin-grid-cell-content') - .filter(`:contains(${email})`) - .should('exist'); - credentialsTab.click(); - cy.wait(500); - credentialInactiveSubTab.click(); - cy.wait(500); - findShadowRoot( - 'backend-ai-webui > backend-ai-credential-view > #inactive-credential-list', - ) - .find('vaadin-grid-cell-content') - .filter(`:contains(${email})`) - .should('exist'); -}); diff --git a/cypress/commands/DataStoragePage.cy.ts b/cypress/commands/DataStoragePage.cy.ts deleted file mode 100644 index 74a22b2eae..0000000000 --- a/cypress/commands/DataStoragePage.cy.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { findShadowRoot } from '../helper/FindShadowRoot.cy'; - -Cypress.Commands.add('createVfolder', (vfolderName: string) => { - findShadowRoot('backend-ai-webui').find('#data').click(); - cy.wait(1000); - const createDialogOpenButton = findShadowRoot( - 'backend-ai-webui > backend-ai-data-view', - ).find('#add-folder'); - const vfolderNameInput = findShadowRoot( - 'backend-ai-webui > backend-ai-data-view > #add-folder-name', - ).find('input'); - const createButton = findShadowRoot( - 'backend-ai-webui > backend-ai-data-view', - ).find('#add-button'); - createDialogOpenButton.click(); - cy.wait(500); - vfolderNameInput.type(vfolderName); - cy.wait(500); - createButton.click(); - cy.wait(5000); - findShadowRoot( - 'backend-ai-webui > backend-ai-data-view > backend-ai-storage-list', - ) - .find(`#controls[folder-name=${vfolderName}]`) - .should('exist'); -}); - -Cypress.Commands.add('deleteVfolder', (vfolderName: string) => { - findShadowRoot('backend-ai-webui').find('#data').click(); - cy.wait(400); - const deleteDialogOpenButton = findShadowRoot( - 'backend-ai-webui > backend-ai-data-view > backend-ai-storage-list', - ) - .find(`#controls[folder-name=${vfolderName}]`) - .find('mwc-icon-button[icon="delete"]'); - const deleteVfolderNameInput = findShadowRoot( - 'backend-ai-webui > backend-ai-data-view > backend-ai-storage-list > #delete-folder-name', - ).find('input'); - const deleteButton = findShadowRoot( - 'backend-ai-webui > backend-ai-data-view > backend-ai-storage-list', - ).find('#delete-button'); - deleteDialogOpenButton.click(); - deleteVfolderNameInput.type(vfolderName); - deleteButton.click(); - findShadowRoot( - 'backend-ai-webui > backend-ai-data-view > backend-ai-storage-list', - ) - .find( - `lablup-shields[folder-name=${vfolderName}][description="deleted-complete"]`, - ) - .should('exist'); -}); diff --git a/cypress/commands/LoginPage.cy.ts b/cypress/commands/LoginPage.cy.ts deleted file mode 100644 index 209da4e268..0000000000 --- a/cypress/commands/LoginPage.cy.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { findShadowRoot } from '../helper/FindShadowRoot.cy'; - -Cypress.Commands.add( - 'login', - (email: string, password: string, endpoint: string) => { - const emailInput = findShadowRoot( - 'backend-ai-webui > backend-ai-login > #id_user_id', - ).find('input'); - const passwordInput = findShadowRoot( - 'backend-ai-webui > backend-ai-login > #id_password', - ).find('input'); - const endpointInput = findShadowRoot( - 'backend-ai-webui > backend-ai-login > #id_api_endpoint', - ).find('input'); - const loginButton = findShadowRoot( - 'backend-ai-webui > backend-ai-login', - ).find('#login-button'); - emailInput.type(email); - passwordInput.type(password); - endpointInput.clear().type(endpoint); - loginButton.click(); - }, -); diff --git a/cypress/commands/SessionPage.cy.ts b/cypress/commands/SessionPage.cy.ts deleted file mode 100644 index 39bd266346..0000000000 --- a/cypress/commands/SessionPage.cy.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { findShadowRoot } from '../helper/FindShadowRoot.cy'; - -Cypress.Commands.add( - 'launchSession', - ( - environmnet: string, - architecture: string, - mountVfolderName: string, - sessionName: string, - ) => { - findShadowRoot('backend-ai-webui').find('#session').click(); - cy.wait(400); - const launchDialogOpenButton = findShadowRoot( - 'backend-ai-webui > backend-ai-session-view > backend-ai-session-launcher', - ).find('#launch-session'); - launchDialogOpenButton.click(); - - const versionSelect = findShadowRoot( - 'backend-ai-webui > backend-ai-session-view > backend-ai-session-launcher', - ).find('#version'); - const selectedVersion = findShadowRoot( - 'backend-ai-webui > backend-ai-session-view > backend-ai-session-launcher', - ).find(`mwc-list-item[id=${environmnet}][architecture=${architecture}]`); - const sessionNameInput = findShadowRoot( - 'backend-ai-webui > backend-ai-session-view > backend-ai-session-launcher > #session-name', - ).find('input'); - const nextButton = findShadowRoot( - 'backend-ai-webui > backend-ai-session-view > backend-ai-session-launcher', - ).find('#next-button'); - const launchButton = findShadowRoot( - 'backend-ai-webui > backend-ai-session-view > backend-ai-session-launcher', - ).find('#launch-button'); - versionSelect.click(); - cy.wait(500); - selectedVersion.click(); - cy.wait(500); - sessionNameInput.clear().type(sessionName); - cy.wait(500); - nextButton.click(); - cy.wait(500); - const mountVfolder = findShadowRoot( - 'backend-ai-webui > backend-ai-session-view > backend-ai-session-launcher', - ) - .find('#non-auto-mounted-folder-grid') - .find(`div:contains(${mountVfolderName})`); - mountVfolder.click(); - cy.wait(500); - nextButton.click(); - cy.wait(500); - const resourceGroupExtension = findShadowRoot( - 'backend-ai-webui > backend-ai-session-view > backend-ai-session-launcher', - ).find('lablup-expansion[name="resource-group"]'); - const ramResourceInput = findShadowRoot( - 'backend-ai-webui > backend-ai-session-view > backend-ai-session-launcher > #mem-resource > #textfield', - ).find('input'); - resourceGroupExtension.click(); - ramResourceInput.clear().type(2); - nextButton.click(); - cy.wait(500); - launchButton.click(); - cy.wait(10000); - const appDialog = findShadowRoot( - 'backend-ai-webui > backend-ai-app-launcher > #app-dialog', - ).find('mwc-icon-button[icon="close"]'); - appDialog.click(); - const sessionStatus = findShadowRoot( - 'backend-ai-webui > backend-ai-session-view > backend-ai-session-list', - ).find(`#${sessionName}-status`); - sessionStatus.should('exist'); - }, -); - -Cypress.Commands.add('deleteSession', (sessionName: string) => { - findShadowRoot('backend-ai-webui').find('#session').click(); - cy.wait(400); - const terminateDialogOpenButton = findShadowRoot( - 'backend-ai-webui > backend-ai-session-view > backend-ai-session-list', - ).find(`#${sessionName}-power`); - const deleteButton = findShadowRoot( - 'backend-ai-webui > backend-ai-session-view > backend-ai-session-list', - ) - .find('#terminate-session-dialog') - .find('mwc-button[class="ok"]'); - const finishedTab = findShadowRoot( - 'backend-ai-webui > backend-ai-session-view', - ).find('mwc-tab[title="finished"]'); - terminateDialogOpenButton.click(); - deleteButton.click(); - cy.wait(5000); - finishedTab.click(); - cy.wait(5000); - findShadowRoot( - 'backend-ai-webui > backend-ai-session-view > backend-ai-session-list', - ) - .find(`#${sessionName}-status`) - .contains('TERMINATED'); -}); diff --git a/cypress/e2e/e2eTest.cy.ts b/cypress/e2e/e2eTest.cy.ts deleted file mode 100644 index d81f6ac135..0000000000 --- a/cypress/e2e/e2eTest.cy.ts +++ /dev/null @@ -1,39 +0,0 @@ -import '../commands/LoginPage.cy'; -import '../commands/DataStoragePage.cy'; -import '../commands/SessionPage.cy'; -import '../commands/CredentialPage.cy'; - -const generateRandomString = ( - length = 6, - chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', -) => { - let result = ''; - for (let i = length; i > 0; --i) - result += chars[Math.floor(Math.random() * chars.length)]; - return result; -}; - -describe('Initial cypress E2E test', () => { - beforeEach(() => { - cy.viewport(1280, 800); - cy.visit('http://localhost:9081'); //방문할 페이지 - }); - - it('localhost E2E test', () => { - cy.login('admin@lablup.com', 'wJalrXUt', 'http://127.0.0.1:8090'); - cy.wait(400); - const vfolderName = generateRandomString(); - const sessionName = generateRandomString(); - cy.createVfolder(vfolderName); - cy.launchSession( - '3\\.9-ubuntu20\\.04', - 'aarch64', - vfolderName, - sessionName, - ); - cy.deleteSession(sessionName); - cy.deleteVfolder(vfolderName); - cy.addUser('test6@lablup.com', 'test6', 'test123!'); - cy.deleteUser('test6\\@lablup\\.com'); - }); -}); diff --git a/cypress/fixtures/example.json b/cypress/fixtures/example.json deleted file mode 100644 index 02e4254378..0000000000 --- a/cypress/fixtures/example.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "Using fixtures to represent data", - "email": "hello@cypress.io", - "body": "Fixtures are a great way to mock data for responses to routes" -} diff --git a/cypress/helper/FindShadowRoot.cy.ts b/cypress/helper/FindShadowRoot.cy.ts deleted file mode 100644 index 836c66a1b7..0000000000 --- a/cypress/helper/FindShadowRoot.cy.ts +++ /dev/null @@ -1,12 +0,0 @@ -export const findShadowRoot = (routes) => { - const segments = routes.split('>').map((route) => route.trim()); - let element = cy.get(segments[0]).shadow(); - for (const [idx, segment] of segments.entries()) { - if (idx === 0) { - continue; - } else { - element = element.find(segment).shadow(); - } - } - return element; -}; diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts deleted file mode 100644 index 698b01a42c..0000000000 --- a/cypress/support/commands.ts +++ /dev/null @@ -1,37 +0,0 @@ -/// -// *********************************************** -// This example commands.ts shows you how to -// create various custom commands and overwrite -// existing commands. -// -// For more comprehensive examples of custom -// commands please read more here: -// https://on.cypress.io/custom-commands -// *********************************************** -// -// -// -- This is a parent command -- -// Cypress.Commands.add('login', (email, password) => { ... }) -// -// -// -- This is a child command -- -// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) -// -// -// -- This is a dual command -- -// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) -// -// -// -- This will overwrite an existing command -- -// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) -// -// declare global { -// namespace Cypress { -// interface Chainable { -// login(email: string, password: string): Chainable -// drag(subject: string, options?: Partial): Chainable -// dismiss(subject: string, options?: Partial): Chainable -// visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable -// } -// } -// } \ No newline at end of file diff --git a/cypress/support/component-index.html b/cypress/support/component-index.html deleted file mode 100644 index ac6e79fd83..0000000000 --- a/cypress/support/component-index.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - Components App - - -
- - \ No newline at end of file diff --git a/cypress/support/component.ts b/cypress/support/component.ts deleted file mode 100644 index bd8ff0182d..0000000000 --- a/cypress/support/component.ts +++ /dev/null @@ -1,39 +0,0 @@ -// *********************************************************** -// This example support/component.ts is processed and -// loaded automatically before your test files. -// -// This is a great place to put global configuration and -// behavior that modifies Cypress. -// -// You can change the location of this file or turn off -// automatically serving support files with the -// 'supportFile' configuration option. -// -// You can read more here: -// https://on.cypress.io/configuration -// *********************************************************** - -// Import commands.js using ES2015 syntax: -import './commands' - -// Alternatively you can use CommonJS syntax: -// require('./commands') - -import { mount } from 'cypress/react' - -// Augment the Cypress namespace to include type definitions for -// your custom command. -// Alternatively, can be defined in cypress/support/component.d.ts -// with a at the top of your spec. -declare global { - namespace Cypress { - interface Chainable { - mount: typeof mount - } - } -} - -Cypress.Commands.add('mount', mount) - -// Example use: -// cy.mount() \ No newline at end of file diff --git a/cypress/support/e2e.ts b/cypress/support/e2e.ts deleted file mode 100644 index f80f74f8e1..0000000000 --- a/cypress/support/e2e.ts +++ /dev/null @@ -1,20 +0,0 @@ -// *********************************************************** -// This example support/e2e.ts is processed and -// loaded automatically before your test files. -// -// This is a great place to put global configuration and -// behavior that modifies Cypress. -// -// You can change the location of this file or turn off -// automatically serving support files with the -// 'supportFile' configuration option. -// -// You can read more here: -// https://on.cypress.io/configuration -// *********************************************************** - -// Import commands.js using ES2015 syntax: -import './commands' - -// Alternatively you can use CommonJS syntax: -// require('./commands') \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 7beba206d0..87f326ce3a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -47,7 +47,6 @@ "chart.js": "~4.4.0", "chartjs-adapter-date-fns": "^3.0.0", "commander": "^11.0.0", - "cypress": "^13.6.0", "date-fns": "^2.30.0", "dotenv": "^16.3.1", "drawflow": "^0.0.59", @@ -2143,65 +2142,6 @@ "node": ">=0.1.90" } }, - "node_modules/@cypress/request": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.1.tgz", - "integrity": "sha512-TWivJlJi8ZDx2wGOw1dbLuHJKUYX7bWySw377nlnGOW3hP9/MUKIsEdXT/YngWxVdgNCHRBmFlBipE+5/2ZZlQ==", - "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "http-signature": "~1.3.6", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "performance-now": "^2.1.0", - "qs": "6.10.4", - "safe-buffer": "^5.1.2", - "tough-cookie": "^4.1.3", - "tunnel-agent": "^0.6.0", - "uuid": "^8.3.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@cypress/request/node_modules/qs": { - "version": "6.10.4", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.4.tgz", - "integrity": "sha512-OQiU+C+Ds5qiH91qh/mg0w+8nwQuLjM4F4M/PbmhDOoYehPh+Fb0bDjtR1sOvy7YKxvj28Y/M0PhP5uVX0kB+g==", - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/@cypress/xvfb": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@cypress/xvfb/-/xvfb-1.2.4.tgz", - "integrity": "sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==", - "dependencies": { - "debug": "^3.1.0", - "lodash.once": "^4.1.1" - } - }, - "node_modules/@cypress/xvfb/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dependencies": { - "ms": "^2.1.1" - } - }, "node_modules/@dabh/diagnostics": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", @@ -5127,16 +5067,6 @@ "@types/node": "*" } }, - "node_modules/@types/sinonjs__fake-timers": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz", - "integrity": "sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g==" - }, - "node_modules/@types/sizzle": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.8.tgz", - "integrity": "sha512-0vWLNK2D5MT9dg0iOo8GlKguPAU02QjmZitPEsXRuJXU/OGIOt9vT9Fc26wtYuavLxtO45v9PGleoL9Z0k1LHg==" - }, "node_modules/@types/triple-beam": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.2.tgz", @@ -5159,6 +5089,7 @@ "version": "2.10.0", "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz", "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==", + "dev": true, "optional": true, "dependencies": { "@types/node": "*" @@ -6527,6 +6458,9 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "optional": true, + "peer": true, "engines": { "node": ">=6" } @@ -6535,6 +6469,7 @@ "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, "dependencies": { "type-fest": "^0.21.3" }, @@ -6549,6 +6484,7 @@ "version": "0.21.3", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, "engines": { "node": ">=10" }, @@ -6560,6 +6496,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, "engines": { "node": ">=8" } @@ -6620,6 +6557,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", + "dev": true, "funding": [ { "type": "github", @@ -6770,14 +6708,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", - "dependencies": { - "safer-buffer": "~2.1.0" - } - }, "node_modules/asn1.js": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", @@ -6806,14 +6736,6 @@ "util": "0.10.3" } }, - "node_modules/assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", - "engines": { - "node": ">=0.8" - } - }, "node_modules/assert/node_modules/inherits": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", @@ -6850,14 +6772,6 @@ "node": ">=4" } }, - "node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "engines": { - "node": ">=8" - } - }, "node_modules/async": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", @@ -6874,15 +6788,11 @@ "node": ">=0.12.0" } }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, "node_modules/at-least-node": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true, "engines": { "node": ">= 4.0.0" } @@ -6908,19 +6818,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", - "engines": { - "node": "*" - } - }, - "node_modules/aws4": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", - "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==" - }, "node_modules/axe-core": { "version": "4.6.3", "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.6.3.tgz", @@ -7076,7 +6973,8 @@ "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true }, "node_modules/base32-encode": { "version": "1.2.0", @@ -7092,6 +6990,7 @@ "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", @@ -7107,14 +7006,6 @@ } ] }, - "node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", - "dependencies": { - "tweetnacl": "^0.14.3" - } - }, "node_modules/before-after-hook": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", @@ -7189,11 +7080,6 @@ "node": ">= 6" } }, - "node_modules/blob-util": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz", - "integrity": "sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==" - }, "node_modules/blocking-elements": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/blocking-elements/-/blocking-elements-0.1.1.tgz", @@ -7202,7 +7088,8 @@ "node_modules/bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true }, "node_modules/bn.js": { "version": "5.2.1", @@ -7345,6 +7232,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -7701,6 +7589,7 @@ "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true, "engines": { "node": "*" } @@ -7884,18 +7773,11 @@ "integrity": "sha512-WF0LihfemtesFcJgO7xfOoOcnWzY/QHR4qeDqV44jPU3HTI54+LnfXK3SA27AVVGCdZFgjjFFaqUA9Jx7dMJZA==", "dev": true }, - "node_modules/cachedir": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.4.0.tgz", - "integrity": "sha512-9EtFOZR8g22CL7BWjJ9BUx1+A/djkofnyW3aOXZORNW2kxoUpx2h+uN2cOqwPmFhnpVmxg+KW2OjOSgChTEvsQ==", - "engines": { - "node": ">=6" - } - }, "node_modules/call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, "dependencies": { "function-bind": "^1.1.1", "get-intrinsic": "^1.0.2" @@ -7953,11 +7835,6 @@ } ] }, - "node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" - }, "node_modules/catharsis": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", @@ -8136,14 +8013,6 @@ "node": "*" } }, - "node_modules/check-more-types": { - "version": "2.24.0", - "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", - "integrity": "sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==", - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", @@ -8334,38 +8203,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cli-table3": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz", - "integrity": "sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==", - "dependencies": { - "string-width": "^4.2.0" - }, - "engines": { - "node": "10.* || >= 12.*" - }, - "optionalDependencies": { - "@colors/colors": "1.5.0" - } - }, - "node_modules/cli-table3/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/cli-table3/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/cli-truncate": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz", @@ -8641,7 +8478,8 @@ "node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true }, "node_modules/colorspace": { "version": "1.1.4", @@ -8679,17 +8517,6 @@ "integrity": "sha512-Y8L5rp6jo+g9VEPgvqNfEopjTR4OTYct8lXlS8iVQdmnjDvbdbzYe9rjtFCB9egC86JoNCU61WRY+ScjkZpnIg==", "dev": true }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/command-line-args": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz", @@ -8763,6 +8590,7 @@ "version": "1.8.2", "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", + "dev": true, "engines": { "node": ">=4.0.0" } @@ -8851,7 +8679,8 @@ "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true }, "node_modules/concat-stream": { "version": "1.6.2", @@ -9221,6 +9050,7 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -9306,640 +9136,98 @@ "resolved": "https://registry.npmjs.org/custom-error-instance/-/custom-error-instance-2.1.1.tgz", "integrity": "sha512-p6JFxJc3M4OTD2li2qaHkDCw9SfMw82Ldr6OC9Je1aXiGfhx2W8p3GaoeaGrPJTUN9NirTM/KTxHWMUdR1rsUg==" }, - "node_modules/cypress": { - "version": "13.6.0", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.6.0.tgz", - "integrity": "sha512-quIsnFmtj4dBUEJYU4OH0H12bABJpSujvWexC24Ju1gTlKMJbeT6tTO0vh7WNfiBPPjoIXLN+OUqVtiKFs6SGw==", - "hasInstallScript": true, + "node_modules/d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", "dependencies": { - "@cypress/request": "^3.0.0", - "@cypress/xvfb": "^1.2.4", - "@types/node": "^18.17.5", - "@types/sinonjs__fake-timers": "8.1.1", - "@types/sizzle": "^2.3.2", - "arch": "^2.2.0", - "blob-util": "^2.0.2", - "bluebird": "^3.7.2", - "buffer": "^5.6.0", - "cachedir": "^2.3.0", - "chalk": "^4.1.0", - "check-more-types": "^2.24.0", - "cli-cursor": "^3.1.0", - "cli-table3": "~0.6.1", - "commander": "^6.2.1", - "common-tags": "^1.8.0", - "dayjs": "^1.10.4", - "debug": "^4.3.4", - "enquirer": "^2.3.6", - "eventemitter2": "6.4.7", - "execa": "4.1.0", - "executable": "^4.1.1", - "extract-zip": "2.0.1", - "figures": "^3.2.0", - "fs-extra": "^9.1.0", - "getos": "^3.2.1", - "is-ci": "^3.0.0", - "is-installed-globally": "~0.4.0", - "lazy-ass": "^1.6.0", - "listr2": "^3.8.3", - "lodash": "^4.17.21", - "log-symbols": "^4.0.0", - "minimist": "^1.2.8", - "ospath": "^1.2.2", - "pretty-bytes": "^5.6.0", - "process": "^0.11.10", - "proxy-from-env": "1.0.0", - "request-progress": "^3.0.0", - "semver": "^7.5.3", - "supports-color": "^8.1.1", - "tmp": "~0.2.1", - "untildify": "^4.0.0", - "yauzl": "^2.10.0" - }, - "bin": { - "cypress": "bin/cypress" - }, - "engines": { - "node": "^16.0.0 || ^18.0.0 || >=20.0.0" + "es5-ext": "^0.10.50", + "type": "^1.0.1" } }, - "node_modules/cypress/node_modules/@types/node": { - "version": "18.19.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.3.tgz", - "integrity": "sha512-k5fggr14DwAytoA/t8rPrIz++lXK7/DqckthCmoZOKNsEbJkId4Z//BqgApXBUGrGddrigYa1oqheo/7YmW4rg==", - "dependencies": { - "undici-types": "~5.26.4" + "node_modules/dash-ast": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/dash-ast/-/dash-ast-2.0.1.tgz", + "integrity": "sha512-5TXltWJGc+RdnabUGzhRae1TRq6m4gr+3K2wQX0is5/F2yS6MJXJvLyI3ErAnsAXuJoGqvfVD5icRgim07DrxQ==", + "dev": true + }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "dev": true, + "engines": { + "node": ">= 12" } }, - "node_modules/cypress/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/date-fns": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", "dependencies": { - "color-convert": "^2.0.1" + "@babel/runtime": "^7.21.0" }, "engines": { - "node": ">=8" + "node": ">=0.11" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/date-fns" } }, - "node_modules/cypress/node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } + "node_modules/de-indent": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", + "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==", + "dev": true }, - "node_modules/cypress/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/debounce": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", + "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==", + "dev": true + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "ms": "2.1.2" }, "engines": { - "node": ">=10" + "node": ">=6.0" }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/cypress/node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dependencies": { - "has-flag": "^4.0.0" - }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/cypress/node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "dependencies": { + "mimic-response": "^3.1.0" + }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cypress/node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dependencies": { - "restore-cursor": "^3.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cypress/node_modules/cli-truncate": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", - "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", - "dependencies": { - "slice-ansi": "^3.0.0", - "string-width": "^4.2.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cypress/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/cypress/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/cypress/node_modules/commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", - "engines": { - "node": ">= 6" - } - }, - "node_modules/cypress/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/cypress/node_modules/execa": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", - "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", - "dependencies": { - "cross-spawn": "^7.0.0", - "get-stream": "^5.0.0", - "human-signals": "^1.1.1", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.0", - "onetime": "^5.1.0", - "signal-exit": "^3.0.2", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/cypress/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cypress/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cypress/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/cypress/node_modules/human-signals": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", - "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", - "engines": { - "node": ">=8.12.0" - } - }, - "node_modules/cypress/node_modules/is-ci": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", - "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", - "dependencies": { - "ci-info": "^3.2.0" - }, - "bin": { - "is-ci": "bin.js" - } - }, - "node_modules/cypress/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/cypress/node_modules/listr2": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.14.0.tgz", - "integrity": "sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g==", - "dependencies": { - "cli-truncate": "^2.1.0", - "colorette": "^2.0.16", - "log-update": "^4.0.0", - "p-map": "^4.0.0", - "rfdc": "^1.3.0", - "rxjs": "^7.5.1", - "through": "^2.3.8", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "enquirer": ">= 2.3.0 < 3" - }, - "peerDependenciesMeta": { - "enquirer": { - "optional": true - } - } - }, - "node_modules/cypress/node_modules/log-update": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", - "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", - "dependencies": { - "ansi-escapes": "^4.3.0", - "cli-cursor": "^3.1.0", - "slice-ansi": "^4.0.0", - "wrap-ansi": "^6.2.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cypress/node_modules/log-update/node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/cypress/node_modules/log-update/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cypress/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cypress/node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" - }, - "node_modules/cypress/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/cypress/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cypress/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cypress/node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cypress/node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cypress/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cypress/node_modules/slice-ansi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", - "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cypress/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cypress/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/cypress/node_modules/tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", - "dependencies": { - "rimraf": "^3.0.0" - }, - "engines": { - "node": ">=8.17.0" - } - }, - "node_modules/cypress/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/cypress/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/cypress/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "dependencies": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, - "node_modules/dash-ast": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/dash-ast/-/dash-ast-2.0.1.tgz", - "integrity": "sha512-5TXltWJGc+RdnabUGzhRae1TRq6m4gr+3K2wQX0is5/F2yS6MJXJvLyI3ErAnsAXuJoGqvfVD5icRgim07DrxQ==", - "dev": true - }, - "node_modules/dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", - "dependencies": { - "assert-plus": "^1.0.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/data-uri-to-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", - "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", - "dev": true, - "engines": { - "node": ">= 12" - } - }, - "node_modules/date-fns": { - "version": "2.30.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", - "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", - "dependencies": { - "@babel/runtime": "^7.21.0" - }, - "engines": { - "node": ">=0.11" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/date-fns" - } - }, - "node_modules/dayjs": { - "version": "1.11.10", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", - "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==" - }, - "node_modules/de-indent": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", - "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==", - "dev": true - }, - "node_modules/debounce": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", - "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==", - "dev": true - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "dev": true, - "dependencies": { - "mimic-response": "^3.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decompress-response/node_modules/mimic-response": { + "node_modules/decompress-response/node_modules/mimic-response": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", @@ -10150,14 +9438,6 @@ "rimraf": "bin.js" } }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", @@ -10447,15 +9727,6 @@ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true }, - "node_modules/ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", - "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, "node_modules/ecdsa-sig-formatter": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", @@ -10894,6 +10165,7 @@ "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, "dependencies": { "once": "^1.4.0" } @@ -10946,6 +10218,9 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", + "dev": true, + "optional": true, + "peer": true, "dependencies": { "ansi-colors": "^4.1.1", "strip-ansi": "^6.0.1" @@ -11892,11 +11167,6 @@ "es5-ext": "~0.10.14" } }, - "node_modules/eventemitter2": { - "version": "6.4.7", - "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.7.tgz", - "integrity": "sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg==" - }, "node_modules/eventemitter3": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", @@ -12037,25 +11307,6 @@ "which": "bin/which" } }, - "node_modules/executable": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz", - "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==", - "dependencies": { - "pify": "^2.2.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/executable/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/expand-template": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", @@ -12135,15 +11386,11 @@ "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==" }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, "node_modules/extract-zip": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "dev": true, "dependencies": { "debug": "^4.1.1", "get-stream": "^5.1.0", @@ -12163,6 +11410,7 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, "dependencies": { "pump": "^3.0.0" }, @@ -12173,14 +11421,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", - "engines": [ - "node >=0.6.0" - ] - }, "node_modules/falafel": { "version": "2.2.5", "resolved": "https://registry.npmjs.org/falafel/-/falafel-2.2.5.tgz", @@ -12283,6 +11523,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "dev": true, "dependencies": { "pend": "~1.2.0" } @@ -12315,20 +11556,6 @@ "node": "^12.20 || >= 14.13" } }, - "node_modules/figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dependencies": { - "escape-string-regexp": "^1.0.5" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -12592,27 +11819,6 @@ "node": ">=8.0.0" } }, - "node_modules/forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", - "engines": { - "node": "*" - } - }, - "node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, "node_modules/formdata-polyfill": { "version": "4.0.10", "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", @@ -12721,7 +11927,8 @@ "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true }, "node_modules/fsevents": { "version": "2.3.2", @@ -12739,7 +11946,8 @@ "node_modules/function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true }, "node_modules/function.prototype.name": { "version": "1.1.5", @@ -12892,6 +12100,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "dev": true, "dependencies": { "function-bind": "^1.1.1", "has": "^1.0.3", @@ -12989,6 +12198,7 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/getos/-/getos-3.2.1.tgz", "integrity": "sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==", + "dev": true, "dependencies": { "async": "^3.2.0" } @@ -12996,15 +12206,8 @@ "node_modules/getos/node_modules/async": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" - }, - "node_modules/getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", - "dependencies": { - "assert-plus": "^1.0.0" - } + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", + "dev": true }, "node_modules/github-from-package": { "version": "0.0.0", @@ -13154,28 +12357,6 @@ "dev": true, "optional": true }, - "node_modules/global-dirs": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", - "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", - "dependencies": { - "ini": "2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/global-dirs/node_modules/ini": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", - "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", - "engines": { - "node": ">=10" - } - }, "node_modules/globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -13289,6 +12470,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, "dependencies": { "function-bind": "^1.1.1" }, @@ -13555,19 +12737,6 @@ "node": ">= 0.8" } }, - "node_modules/http-signature": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.6.tgz", - "integrity": "sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==", - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^2.0.2", - "sshpk": "^1.14.1" - }, - "engines": { - "node": ">=0.10" - } - }, "node_modules/http-status-codes": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/http-status-codes/-/http-status-codes-2.2.0.tgz", @@ -13884,6 +13053,7 @@ "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", @@ -14017,6 +13187,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -14331,6 +13502,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, "engines": { "node": ">=8" } @@ -14360,21 +13532,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-installed-globally": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", - "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", - "dependencies": { - "global-dirs": "^3.0.0", - "is-path-inside": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-jquery-obj": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-jquery-obj/-/is-jquery-obj-0.1.1.tgz", @@ -14507,6 +13664,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, "engines": { "node": ">=8" } @@ -14681,22 +13839,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-utf8": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", @@ -14787,7 +13929,8 @@ "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true }, "node_modules/isobject": { "version": "3.0.1", @@ -14798,11 +13941,6 @@ "node": ">=0.10.0" } }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" - }, "node_modules/istanbul-lib-coverage": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", @@ -15052,11 +14190,6 @@ "xmlcreate": "^2.0.4" } }, - "node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" - }, "node_modules/jsdoc": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.2.tgz", @@ -15145,7 +14278,8 @@ "node_modules/json-schema": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "dev": true }, "node_modules/json-schema-traverse": { "version": "0.4.1", @@ -15162,7 +14296,9 @@ "node_modules/json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true, + "optional": true }, "node_modules/json5": { "version": "2.2.3", @@ -15263,20 +14399,6 @@ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, - "node_modules/jsprim": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", - "integrity": "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==", - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - } - }, "node_modules/jstransformer": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz", @@ -15551,14 +14673,6 @@ "language-subtag-registry": "^0.3.20" } }, - "node_modules/lazy-ass": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz", - "integrity": "sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==", - "engines": { - "node": "> 0.8" - } - }, "node_modules/lazy-cache": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", @@ -15977,11 +15091,6 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, - "node_modules/lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" - }, "node_modules/lodash.sortby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", @@ -16016,85 +15125,6 @@ "uni-global": "^1.0.0" } }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-symbols/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/log-symbols/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/log-symbols/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/log-symbols/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/log-update": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/log-update/-/log-update-5.0.1.tgz", @@ -16729,6 +15759,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -16740,6 +15771,7 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -17241,6 +16273,7 @@ "version": "1.12.3", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -17443,11 +16476,6 @@ "node": ">=0.10.0" } }, - "node_modules/ospath": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz", - "integrity": "sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA==" - }, "node_modules/p-cancelable": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", @@ -17660,6 +16688,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, "engines": { "node": ">=8" } @@ -17722,12 +16751,8 @@ "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==" - }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "dev": true }, "node_modules/picocolors": { "version": "1.0.0", @@ -18492,6 +17517,7 @@ "version": "5.6.0", "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", + "dev": true, "engines": { "node": ">=6" }, @@ -18521,6 +17547,7 @@ "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true, "engines": { "node": ">= 0.6.0" } @@ -18605,11 +17632,6 @@ "node": ">= 0.10" } }, - "node_modules/proxy-from-env": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", - "integrity": "sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A==" - }, "node_modules/pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", @@ -18619,7 +17641,8 @@ "node_modules/psl": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", + "dev": true }, "node_modules/public-encrypt": { "version": "4.0.3", @@ -18771,6 +17794,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -19454,14 +18478,6 @@ "integrity": "sha512-saxS4y7NFkLMa92BR4bPHR41GD+f/qoDAwD2xZmN+MpDXgibkxwLO2qk7dCHYtskSkd/bWS8Jy6kC5MZUkg1tw==", "dev": true }, - "node_modules/request-progress": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz", - "integrity": "sha512-MnWzEHHaxHO2iWiQuHrUPBi/1WeBf5PkxQqNyNvLl9VAYSdXkP8tQ3pBSeCPD+yw0v0Aq1zosWLz0BdeXpWwZg==", - "dependencies": { - "throttleit": "^1.0.0" - } - }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -19699,7 +18715,8 @@ "node_modules/rfdc": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", + "dev": true }, "node_modules/right-align": { "version": "0.1.3", @@ -19717,6 +18734,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, "dependencies": { "glob": "^7.1.3" }, @@ -19731,6 +18749,7 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -19828,6 +18847,7 @@ "version": "7.8.1", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dev": true, "dependencies": { "tslib": "^2.1.0" } @@ -19876,7 +18896,8 @@ "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true }, "node_modules/sanitize-filename": { "version": "1.6.3", @@ -20209,6 +19230,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -20220,6 +19242,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, "engines": { "node": ">=8" } @@ -20237,6 +19260,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, "dependencies": { "call-bind": "^1.0.0", "get-intrinsic": "^1.0.2", @@ -20470,30 +19494,6 @@ "es5-ext": "^0.10.53" } }, - "node_modules/sshpk": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", - "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", - "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/stack-trace": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", @@ -20811,6 +19811,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -20850,6 +19851,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, "engines": { "node": ">=6" } @@ -22094,18 +21096,11 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, - "node_modules/throttleit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.1.tgz", - "integrity": "sha512-vDZpf9Chs9mAdfY046mcPt8fg5QSZr37hEH4TXYBnDF+izxgrbRGUAAaBvIk/fJm9aOFCGFd1EsNg5AZCbnQCQ==", - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true }, "node_modules/through2": { "version": "2.0.5", @@ -22335,6 +21330,7 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", + "dev": true, "dependencies": { "psl": "^1.1.33", "punycode": "^2.1.1", @@ -22349,6 +21345,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "dev": true, "engines": { "node": ">=6" } @@ -22357,6 +21354,7 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "dev": true, "engines": { "node": ">= 4.0.0" } @@ -22511,6 +21509,7 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dev": true, "dependencies": { "safe-buffer": "^5.0.1" }, @@ -22532,11 +21531,6 @@ "url-parse": "^1.5.7" } }, - "node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" - }, "node_modules/type": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", @@ -22927,14 +21921,6 @@ "integrity": "sha512-vRCqFv6UhXpWxZPyGDh/F3ZpNv8/qo7w6iufLpQg9aKnQ71qM4B5KiI7Mia9COcjEhrO9LueHpMYjYzsWH3OIg==", "dev": true }, - "node_modules/untildify": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", - "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", - "engines": { - "node": ">=8" - } - }, "node_modules/upath": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", @@ -23085,6 +22071,7 @@ "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "peer": true, "bin": { "uuid": "dist/bin/uuid" } @@ -23130,24 +22117,6 @@ "node": ">= 0.8" } }, - "node_modules/verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "node_modules/verror/node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" - }, "node_modules/vinyl": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-3.0.0.tgz", @@ -23573,6 +22542,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -24632,6 +23602,7 @@ "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "dev": true, "dependencies": { "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" diff --git a/package.json b/package.json index 887e3879cb..4f549eaed1 100644 --- a/package.json +++ b/package.json @@ -28,9 +28,7 @@ "docs": "npx jsdoc -c ./jsdoc.json", "update": "npx tsc", "postinstall": "npx concurrently -c \"auto\" --names \"react-dependencies\" \"cd react && npm install\"", - "patch:lit-translate": "unzip -o ./scripts/lit-translate.zip -d ./node_modules/lit-translate && cp -f ./scripts/lit-translate-index.js ./node_modules/lit-translate/index.js", - "prepare": "husky install", - "test:cypress": "cypress open" + "patch:lit-translate": "unzip -o ./scripts/lit-translate.zip -d ./node_modules/lit-translate && cp -f ./scripts/lit-translate-index.js ./node_modules/lit-translate/index.js" }, "dependencies": { "@material/mwc-button": "^0.27.0", @@ -70,7 +68,6 @@ "chart.js": "~4.4.0", "chartjs-adapter-date-fns": "^3.0.0", "commander": "^11.0.0", - "cypress": "^13.6.0", "date-fns": "^2.30.0", "dotenv": "^16.3.1", "drawflow": "^0.0.59", From 697c52383537ff79916c661ecc70be78d7b4a8ef Mon Sep 17 00:00:00 2001 From: gee05053 Date: Tue, 26 Dec 2023 11:14:07 +0900 Subject: [PATCH 29/48] fix:rewrite prepare that was deleted by mistake --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 4f549eaed1..58c132b41f 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,8 @@ "docs": "npx jsdoc -c ./jsdoc.json", "update": "npx tsc", "postinstall": "npx concurrently -c \"auto\" --names \"react-dependencies\" \"cd react && npm install\"", - "patch:lit-translate": "unzip -o ./scripts/lit-translate.zip -d ./node_modules/lit-translate && cp -f ./scripts/lit-translate-index.js ./node_modules/lit-translate/index.js" + "patch:lit-translate": "unzip -o ./scripts/lit-translate.zip -d ./node_modules/lit-translate && cp -f ./scripts/lit-translate-index.js ./node_modules/lit-translate/index.js", + "prepare": "husky install" }, "dependencies": { "@material/mwc-button": "^0.27.0", From f5ce4dd964fe46b4fe60442b3b6906055da4c197 Mon Sep 17 00:00:00 2001 From: gee05053 Date: Wed, 27 Dec 2023 15:16:01 +0900 Subject: [PATCH 30/48] fix:prettierrc.json --- playwright/.prettierrc.json | 3 +++ playwright/e2eTest.spec.ts | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/playwright/.prettierrc.json b/playwright/.prettierrc.json index a632bb880d..0fd43b9b42 100644 --- a/playwright/.prettierrc.json +++ b/playwright/.prettierrc.json @@ -3,8 +3,11 @@ "semi": true, "singleQuote": true, "importOrderSeparation": true, + "importOrderParserPlugins": ["typescript", "decorators"], "printWidth": 80, "bracketSpacing": true, "trailingComma": "all", + "plugins": ["@trivago/prettier-plugin-sort-imports"], + "htmlWhitespaceSensitivity": "ignore", "singleAttributePerLine": false } diff --git a/playwright/e2eTest.spec.ts b/playwright/e2eTest.spec.ts index d8fdca8d98..bbff4393ec 100644 --- a/playwright/e2eTest.spec.ts +++ b/playwright/e2eTest.spec.ts @@ -1,8 +1,8 @@ -import { test } from '@playwright/test'; -import { login } from './pages/LoginPage.spec'; +import { createUser, deleteUser } from './pages/CredentialPage.spec'; import { createVfolder, deleteVfolder } from './pages/DataStoragePage.spec'; +import { login } from './pages/LoginPage.spec'; import { createSession, deleteSession } from './pages/SessionPage.spec'; -import { createUser, deleteUser } from './pages/CredentialPage.spec'; +import { test } from '@playwright/test'; test('E2E test', async ({ page }) => { await page.goto('http://localhost:9081/'); From aa146db881d375a371d3061ca0701d2816e72530 Mon Sep 17 00:00:00 2001 From: gee05053 Date: Mon, 15 Jan 2024 11:50:27 +0900 Subject: [PATCH 31/48] fix:modify test structure --- playwright/e2eTest.spec.ts | 21 --------------- playwright/pages/LoginPage.spec.ts | 41 ++++++++++++++++++++---------- 2 files changed, 27 insertions(+), 35 deletions(-) delete mode 100644 playwright/e2eTest.spec.ts diff --git a/playwright/e2eTest.spec.ts b/playwright/e2eTest.spec.ts deleted file mode 100644 index bbff4393ec..0000000000 --- a/playwright/e2eTest.spec.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { createUser, deleteUser } from './pages/CredentialPage.spec'; -import { createVfolder, deleteVfolder } from './pages/DataStoragePage.spec'; -import { login } from './pages/LoginPage.spec'; -import { createSession, deleteSession } from './pages/SessionPage.spec'; -import { test } from '@playwright/test'; - -test('E2E test', async ({ page }) => { - await page.goto('http://localhost:9081/'); - await login(page, 'test@lablup.com', 'test123!', 'http://127.0.0.1:8090'); - await createVfolder(page, 'test2'); - await createSession( - page, - 'Ubuntu 20.04 aarch64', - 'testvfolder', - 'testSession', - ); - await deleteSession(page, 'test@lablup.com', 'testSession'); - await deleteVfolder(page, 'test2'); - await createUser(page, 'test9@lablup.com', 'test9', 'test123!'); - await deleteUser(page, 'test9\\@lablup\\.com'); -}); diff --git a/playwright/pages/LoginPage.spec.ts b/playwright/pages/LoginPage.spec.ts index d74ef67ceb..6c583576d1 100644 --- a/playwright/pages/LoginPage.spec.ts +++ b/playwright/pages/LoginPage.spec.ts @@ -1,14 +1,27 @@ -export async function login( - page: Page, - email: string, - password: string, - endpoint: string, -) { - await page.locator('#id_user_id label').click(); - await page.locator('#id_user_id label').fill(email); - await page.locator('#id_password label').click(); - await page.locator('#id_password label').fill(password); - await page.locator('#id_api_endpoint label').click(); - await page.locator('#id_api_endpoint label').fill(endpoint); - await page.locator('#login-button').click(); -} +import { test, expect } from '@playwright/test'; + +test.describe('LoginPage: User login', () => { + test.beforeEach(async ({ page }) => { + await page.goto('http://localhost:9081'); + }); + test('User login success', async ({ page }) => { + await page.locator('#id_user_id label').click(); + await page.locator('#id_user_id label').fill('test@lablup.com'); + await page.locator('#id_password label').click(); + await page.locator('#id_password label').fill('test123!'); + await page.locator('#id_api_endpoint label').click(); + await page.locator('#id_api_endpoint label').fill('http://localhost:8090'); + await page.locator('#login-button').click(); + await expect(page.locator('#app-body')).toBeVisible(); + }); + test('User login fail', async ({ page }) => { + await page.locator('#id_user_id label').click(); + await page.locator('#id_user_id label').fill('test10@lablup.com'); + await page.locator('#id_password label').click(); + await page.locator('#id_password label').fill('test123!'); + await page.locator('#id_api_endpoint label').click(); + await page.locator('#id_api_endpoint label').fill('http://localhost:8090'); + await page.locator('#login-button').click(); + await expect(page.locator('#app-body')).toBeHidden(); + }); +}); From c2aeffd85bfca55cdfc35e2b1aee1c8dfb0d2619 Mon Sep 17 00:00:00 2001 From: gee05053 Date: Tue, 16 Jan 2024 17:25:00 +0900 Subject: [PATCH 32/48] fix:modify code structure and add helper --- playwright/helper/helper.ts | 9 ++ playwright/pages/DataStoragePage.spec.ts | 103 +++++++++++++++++------ 2 files changed, 86 insertions(+), 26 deletions(-) create mode 100644 playwright/helper/helper.ts diff --git a/playwright/helper/helper.ts b/playwright/helper/helper.ts new file mode 100644 index 0000000000..b2c3d9a78a --- /dev/null +++ b/playwright/helper/helper.ts @@ -0,0 +1,9 @@ +export const generateRandomString = ( + length = 64, + chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-_', +) => { + let result = ''; + for (let i = length; i > 0; --i) + result += chars[Math.floor(Math.random() * chars.length)]; + return result; +}; diff --git a/playwright/pages/DataStoragePage.spec.ts b/playwright/pages/DataStoragePage.spec.ts index 0460def3c3..4cfedb8cc8 100644 --- a/playwright/pages/DataStoragePage.spec.ts +++ b/playwright/pages/DataStoragePage.spec.ts @@ -1,28 +1,79 @@ -import { expect } from '@playwright/test'; +import { generateRandomString } from '../helper/helper'; +import { test, expect } from '@playwright/test'; -export async function createVfolder(page: Page, vfolderName: string) { - await page.locator('#data').click(); - await page.waitForURL('**/data'); - await page.locator('#add-folder').click(); - await page.locator('#add-folder-name').click(); - await page.locator('#add-folder-name label').fill(vfolderName); - await page.locator('#add-button').click(); - await expect(page.getByText(vfolderName)).toBeVisible(); -} +test.describe('Vfolder creation', () => { + const randomVfolderName = generateRandomString(); + test.beforeEach(async ({ page }) => { + await page.goto('http://localhost:9081'); + await page.locator('#id_user_id label').click(); + await page.locator('#id_user_id label').fill('test@lablup.com'); + await page.locator('#id_password label').click(); + await page.locator('#id_password label').fill('test123!'); + await page.locator('#id_api_endpoint label').click(); + await page.locator('#id_api_endpoint label').fill('http://localhost:8090'); + await page.locator('#login-button').click(); + await page.locator('#data').click(); + await page.waitForURL('**/data'); + }); + test('User can create vfolder', async ({ page }) => { + await page.locator('#add-folder').click(); + await page.locator('#add-folder-name').click(); + await page.locator('#add-folder-name label').fill(randomVfolderName); + await page.locator('#add-button').click(); + await page.waitForTimeout(5000); + await page + .getByRole('treegrid') + .evaluate(async (e) => (e.scrollTop = e.scrollHeight)); + await page.waitForTimeout(1000); + expect( + await page + .getByText(`folder_open ${randomVfolderName}`, { exact: true }) + .isVisible(), + ).toBe(true); + expect( + await page + .locator( + `lablup-shields[folder-name=${randomVfolderName}][description="ready"]`, + ) + .isVisible(), + ).toBe(true); + }); +}); -export async function deleteVfolder(page: Page, vfolderName: string) { - await page.locator('#data').click(); - await page.waitForURL('**/data'); - await page - .locator(`#controls[folder-name=${vfolderName}]`) - .locator('mwc-icon-button[icon="delete"]') - .click(); - await page.locator('#delete-folder-name').click(); - await page.locator('#delete-folder-name label').fill(vfolderName); - await page.locator('#delete-button').click(); - await expect( - page.locator( - `lablup-shields[folder-name=${vfolderName}][description="deleted-complete"]`, - ), - ).toBeVisible(); -} +test.describe('Vfolder deletion', () => { + const deleteVfolderName = + 'dBvGpQPVo4V6ArAM3qtwnERwV5W5iL3WKZOJKA3rXX0rm0RgC10r1bA14AQoWC9F'; + test.beforeEach(async ({ page }) => { + await page.goto('http://localhost:9081'); + await page.locator('#id_user_id label').click(); + await page.locator('#id_user_id label').fill('test@lablup.com'); + await page.locator('#id_password label').click(); + await page.locator('#id_password label').fill('test123!'); + await page.locator('#id_api_endpoint label').click(); + await page.locator('#id_api_endpoint label').fill('http://localhost:8090'); + await page.locator('#login-button').click(); + await page.locator('#data').click(); + await page.waitForURL('**/data'); + }); + test('User can delete vfolder', async ({ page }) => { + await page + .getByRole('treegrid') + .evaluate(async (e) => (e.scrollTop = e.scrollHeight)); + await page.waitForTimeout(1000); + await page + .locator(`#controls[folder-name=${deleteVfolderName}]`) + .locator('mwc-icon-button[icon="delete"]') + .click(); + await page.locator('#delete-folder-name').click(); + await page.locator('#delete-folder-name label').fill(deleteVfolderName); + await page.locator('#delete-button').click(); + await page.waitForTimeout(5000); + expect( + await page + .locator( + `lablup-shields[folder-name=${deleteVfolderName}][description="deleted-complete"]`, + ) + .isVisible(), + ).toBe(true); + }); +}); From 48fac6722d9f4924dc0dc0d570ef290abd66c268 Mon Sep 17 00:00:00 2001 From: gee05053 Date: Tue, 16 Jan 2024 18:12:29 +0900 Subject: [PATCH 33/48] fix:modify CredentialPage code structure --- playwright/pages/CredentialPage.spec.ts | 174 ++++++++++++++---------- 1 file changed, 105 insertions(+), 69 deletions(-) diff --git a/playwright/pages/CredentialPage.spec.ts b/playwright/pages/CredentialPage.spec.ts index 76b5bb5328..cf11e203d3 100644 --- a/playwright/pages/CredentialPage.spec.ts +++ b/playwright/pages/CredentialPage.spec.ts @@ -1,71 +1,107 @@ -import { expect } from '@playwright/test'; +import { test, expect } from '@playwright/test'; -export async function createUser( - page: Page, - email: string, - userName: string, - password: string, -) { - await page.locator('#credential').click(); - await page.waitForURL('**/credential'); - await page.getByRole('tab', { name: 'Users' }).click(); - await page.getByRole('tab', { name: 'Active', exact: true }).click(); - await page.locator('#add-user').click(); - await page.locator('#new-user-dialog #id_user_email').click(); - await page.locator('#new-user-dialog #id_user_email label').fill(email); - await page.locator('#new-user-dialog #id_user_name').click(); - await page.locator('#new-user-dialog #id_user_name label').fill(userName); - await page.locator('#new-user-dialog #id_user_password').click(); - await page.locator('#new-user-dialog #id_user_password label').fill(password); - await page.locator('#new-user-dialog #id_user_confirm').click(); - await page.locator('#new-user-dialog #id_user_confirm label').fill(password); - await page.locator('#new-user-dialog #create-user-button').click(); - await expect( - page - .locator('#active-user-list vaadin-grid-cell-content') - .filter({ hasText: email }), - ).toBeVisible(); - await page.getByRole('tab', { name: 'Credentials' }).click(); - await page.getByRole('tab', { name: 'Active', exact: true }).click(); - await expect( - page - .locator('#active-credential-list vaadin-grid-cell-content') - .filter({ hasText: email }), - ).toBeVisible(); -} +test.describe('Create account', () => { + test.beforeEach(async ({ page }) => { + await page.goto('http://localhost:9081'); + await page.locator('#id_user_id label').click(); + await page.locator('#id_user_id label').fill('test@lablup.com'); + await page.locator('#id_password label').click(); + await page.locator('#id_password label').fill('test123!'); + await page.locator('#id_api_endpoint label').click(); + await page.locator('#id_api_endpoint label').fill('http://localhost:8090'); + await page.locator('#login-button').click(); + await page.locator('#credential').click(); + await page.waitForURL('**/credential'); + await page.getByRole('tab', { name: 'Users' }).click(); + await page.getByRole('tab', { name: 'Active', exact: true }).click(); + await page.waitForTimeout(1000); + }); + test('Admin can create account', async ({ page }) => { + const email = 'test4@lablup.com'; + const userName = 'test4'; + const password = 'test123!'; + await page.locator('#add-user').click(); + await page.locator('#new-user-dialog #id_user_email').click(); + await page.locator('#new-user-dialog #id_user_email label').fill(email); + await page.locator('#new-user-dialog #id_user_name').click(); + await page.locator('#new-user-dialog #id_user_name label').fill(userName); + await page.locator('#new-user-dialog #id_user_password').click(); + await page + .locator('#new-user-dialog #id_user_password label') + .fill(password); + await page.locator('#new-user-dialog #id_user_confirm').click(); + await page + .locator('#new-user-dialog #id_user_confirm label') + .fill(password); + await page.locator('#new-user-dialog #create-user-button').click(); + await page.waitForTimeout(5000); + expect( + await page + .locator('#active-user-list vaadin-grid-cell-content') + .filter({ hasText: email }) + .isVisible(), + ).toBe(true); + await page.getByRole('tab', { name: 'Credentials' }).click(); + await page.getByRole('tab', { name: 'Active', exact: true }).click(); + await page.waitForTimeout(1000); + expect( + await page + .locator('#active-credential-list vaadin-grid-cell-content') + .filter({ hasText: email }) + .isVisible(), + ).toBe(true); + }); +}); -export async function deleteUser(page: Page, email: string) { - const emailText = email.replace(/\\/g, ''); - await page.locator('#credential').click(); - await page.waitForURL('**/credential'); - await page.getByRole('tab', { name: 'Users' }).click(); - await page.getByRole('tab', { name: 'Active', exact: true }).click(); - await page - .locator(`#controls[user-id=${email}]`) - .locator('mwc-icon-button[icon="delete_forever"]') - .click(); - await page.locator('#active-user-list #deleteOk').click(); - await expect( - page - .locator('#active-user-list vaadin-grid-cell-content') - .filter({ hasText: emailText }), - ).toBeHidden(); - await page.getByRole('tab', { name: 'Inactive' }).click(); - await expect( - page - .locator('#inactive-user-list vaadin-grid-cell-content') - .filter({ hasText: emailText }), - ).toBeVisible(); - await page.getByRole('tab', { name: 'Credentials' }).click(); - await expect( - page - .locator('#active-credential-list vaadin-grid-cell-content') - .filter({ hasText: emailText }), - ).toBeHidden(); - await page.getByRole('tab', { name: 'Inactive' }).click(); - await expect( - page - .locator('#inactive-credential-list vaadin-grid-cell-content') - .filter({ hasText: emailText }), - ).toBeVisible(); -} +test.describe('Delete account', () => { + test.beforeEach(async ({ page }) => { + await page.goto('http://localhost:9081'); + await page.locator('#id_user_id label').click(); + await page.locator('#id_user_id label').fill('test@lablup.com'); + await page.locator('#id_password label').click(); + await page.locator('#id_password label').fill('test123!'); + await page.locator('#id_api_endpoint label').click(); + await page.locator('#id_api_endpoint label').fill('http://localhost:8090'); + await page.locator('#login-button').click(); + await page.locator('#credential').click(); + await page.waitForURL('**/credential'); + await page.getByRole('tab', { name: 'Users' }).click(); + await page.getByRole('tab', { name: 'Active', exact: true }).click(); + await page.waitForTimeout(1000); + }); + test('Admin can delete account', async ({ page }) => { + const email = 'test4@lablup.com'; + await page + .locator(`#controls[user-id="${email}"]`) + .locator('mwc-icon-button[icon="delete_forever"]') + .click(); + await page.locator('#active-user-list #deleteOk').click(); + await page.waitForTimeout(5000); + expect( + await page.getByRole('gridcell', { name: email, exact: true }).isHidden(), + ).toBe(true); + await page.getByRole('tab', { name: 'Inactive' }).click(); + await page.waitForTimeout(1000); + expect( + await page + .getByRole('gridcell', { name: email, exact: true }) + .isVisible(), + ).toBe(true); + await page.getByRole('tab', { name: 'Credentials' }).click(); + await page.waitForTimeout(1000); + expect( + await page + .locator('#active-credential-list vaadin-grid-cell-content') + .filter({ hasText: email }) + .isHidden(), + ).toBe(true); + await page.getByRole('tab', { name: 'Inactive' }).click(); + await page.waitForTimeout(1000); + expect( + await page + .locator('#inactive-credential-list vaadin-grid-cell-content') + .filter({ hasText: email }) + .isVisible(), + ).toBe(true); + }); +}); From 2319d1d4d1615c11eff64bd2a84fef6be448bb9d Mon Sep 17 00:00:00 2001 From: gee05053 Date: Tue, 16 Jan 2024 19:47:36 +0900 Subject: [PATCH 34/48] fix:modify SessionPage code structure --- playwright/pages/SessionPage.spec.ts | 164 ++++++++++++++++----------- 1 file changed, 99 insertions(+), 65 deletions(-) diff --git a/playwright/pages/SessionPage.spec.ts b/playwright/pages/SessionPage.spec.ts index 4ed5f066d4..83677de686 100644 --- a/playwright/pages/SessionPage.spec.ts +++ b/playwright/pages/SessionPage.spec.ts @@ -1,67 +1,101 @@ -import { expect } from '@playwright/test'; +import { generateRandomString } from '../helper/helper'; +import { test, expect } from '@playwright/test'; -export async function createSession( - page: Page, - environmnet: string, - mountVfolderName: string, - sessionName: string, -) { - await page.locator('#session').click(); - await page.waitForURL('**/job'); - await page.getByRole('tab', { name: 'Running' }).click(); - await page - .locator('backend-ai-session-view') - .locator('#launch-session') - .click(); - await page.locator('backend-ai-session-view').locator('#version').click(); - await page - .locator('backend-ai-session-view') - .getByRole('option', { name: environmnet }) - .click(); - await page - .locator('backend-ai-session-view') - .locator('#session-name') - .click(); - await page - .locator('backend-ai-session-view') - .locator('#session-name label') - .fill(sessionName); - await page.locator('backend-ai-session-view').locator('#next-button').click(); - await page.getByText(`${mountVfolderName} local:volume1`).click(); - await page.locator('backend-ai-session-view').locator('#next-button').click(); - await page.locator('backend-ai-session-view').locator('#next-button').click(); - await page - .locator('backend-ai-session-view') - .locator('#launch-button') - .click(); - await page.waitForTimeout(5000); - await page.getByRole('button', { name: 'close' }).click(); - await page.waitForTimeout(2000); - await expect(page.getByText(sessionName)).toBeVisible(); -} +test.describe('Create Session', () => { + test.beforeEach(async ({ page }) => { + await page.goto('http://localhost:9081'); + await page.locator('#id_user_id label').click(); + await page.locator('#id_user_id label').fill('test@lablup.com'); + await page.locator('#id_password label').click(); + await page.locator('#id_password label').fill('test123!'); + await page.locator('#id_api_endpoint label').click(); + await page.locator('#id_api_endpoint label').fill('http://localhost:8090'); + await page.locator('#login-button').click(); + await page.locator('#session').click(); + await page.waitForURL('**/job'); + await page.waitForTimeout(1000); + }); + test('User can create session', async ({ page }) => { + const version = 'Ubuntu 20.04 aarch64'; + const randomSessionName = generateRandomString( + 4, + '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', + ); + const mountVfolderName = 'test'; + await page + .locator('backend-ai-session-view') + .locator('#launch-session') + .click(); + await page.locator('backend-ai-session-view').locator('#version').click(); + await page + .locator('backend-ai-session-view') + .getByRole('option', { name: version }) + .click(); + await page + .locator('backend-ai-session-view') + .locator('#session-name') + .click(); + await page + .locator('backend-ai-session-view') + .locator('#session-name label') + .fill(randomSessionName); + await page + .locator('backend-ai-session-view') + .locator('#next-button') + .click(); + await page.getByText(`${mountVfolderName} local:volume1`).click(); + await page + .locator('backend-ai-session-view') + .locator('#next-button') + .click(); + await page + .locator('backend-ai-session-view') + .locator('#next-button') + .click(); + await page + .locator('backend-ai-session-view') + .locator('#launch-button') + .click(); + await page.waitForTimeout(5000); + await page.getByRole('button', { name: 'close' }).click(); + await page.waitForTimeout(2000); + expect(await page.getByText(randomSessionName).isVisible()).toBe(true); + }); +}); -export async function deleteSession( - page: Page, - email: string, - sessionName: string, -) { - await page.locator('#session').click(); - await page.waitForURL('**/job'); - await page.getByRole('tab', { name: 'Running' }).click(); - await page - .locator(`#${sessionName}-power`) - .getByLabel('power_settings_new') - .click(); - await page - .locator(`#terminate-session-dialog`) - .locator('mwc-button[class="ok"]') - .click(); - await page.waitForTimeout(5000); - await expect(page.getByText(sessionName)).toBeHidden(); - await page.getByRole('tab', { name: 'Finished' }).click(); - await expect( - page - .getByRole('row', { name: `1 ${email} ${sessionName}` }) - .locator('#vaadin-grid-cell-36'), - ).toBeVisible(); -} +test.describe('Delete Session', () => { + test.beforeEach(async ({ page }) => { + await page.goto('http://localhost:9081'); + await page.locator('#id_user_id label').click(); + await page.locator('#id_user_id label').fill('test@lablup.com'); + await page.locator('#id_password label').click(); + await page.locator('#id_password label').fill('test123!'); + await page.locator('#id_api_endpoint label').click(); + await page.locator('#id_api_endpoint label').fill('http://localhost:8090'); + await page.locator('#login-button').click(); + await page.locator('#session').click(); + await page.waitForURL('**/job'); + await page.waitForTimeout(1000); + }); + test('User can delete session', async ({ page }) => { + const sessionName = 'ssss'; + const sessionOwner = 'test@lablup.com'; + await page + .locator(`[id="${sessionName}-power"]`) + .getByLabel('power_settings_new') + .click(); + await page + .locator(`#terminate-session-dialog`) + .locator('mwc-button[class="ok"]') + .click(); + await page.waitForTimeout(5000); + expect(await page.getByText(sessionName).isHidden()).toBe(true); + await page.getByRole('tab', { name: 'Finished' }).click(); + await page.waitForTimeout(1000); + expect( + await page + .getByRole('row', { name: `1 ${sessionOwner} ${sessionName}` }) + .isVisible(), + ).toBe(true); + }); +}); From c6f4386241d8d2d9e3fa86efed7b1d23ec96ef92 Mon Sep 17 00:00:00 2001 From: gee05053 Date: Thu, 18 Jan 2024 09:54:52 +0900 Subject: [PATCH 35/48] fix:add comment and modify expect --- playwright/helper/helper.ts | 2 +- playwright/pages/CredentialPage.spec.ts | 58 +++++++++++------------- playwright/pages/DataStoragePage.spec.ts | 54 ++++++++++------------ playwright/pages/LoginPage.spec.ts | 5 +- playwright/pages/SessionPage.spec.ts | 11 ++--- 5 files changed, 60 insertions(+), 70 deletions(-) diff --git a/playwright/helper/helper.ts b/playwright/helper/helper.ts index b2c3d9a78a..aa28a5837f 100644 --- a/playwright/helper/helper.ts +++ b/playwright/helper/helper.ts @@ -1,6 +1,6 @@ export const generateRandomString = ( length = 64, - chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-_', + chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', ) => { let result = ''; for (let i = length; i > 0; --i) diff --git a/playwright/pages/CredentialPage.spec.ts b/playwright/pages/CredentialPage.spec.ts index cf11e203d3..5b6eff4a6b 100644 --- a/playwright/pages/CredentialPage.spec.ts +++ b/playwright/pages/CredentialPage.spec.ts @@ -17,9 +17,9 @@ test.describe('Create account', () => { await page.waitForTimeout(1000); }); test('Admin can create account', async ({ page }) => { - const email = 'test4@lablup.com'; - const userName = 'test4'; - const password = 'test123!'; + const email = 'test4@lablup.com'; //Write new account'email + const userName = 'test4'; //Write new account'userName + const password = 'test123!'; //Write new account'password await page.locator('#add-user').click(); await page.locator('#new-user-dialog #id_user_email').click(); await page.locator('#new-user-dialog #id_user_email label').fill(email); @@ -35,21 +35,19 @@ test.describe('Create account', () => { .fill(password); await page.locator('#new-user-dialog #create-user-button').click(); await page.waitForTimeout(5000); - expect( - await page + await expect( + page .locator('#active-user-list vaadin-grid-cell-content') - .filter({ hasText: email }) - .isVisible(), - ).toBe(true); + .filter({ hasText: email }), + ).toBeVisible(); await page.getByRole('tab', { name: 'Credentials' }).click(); await page.getByRole('tab', { name: 'Active', exact: true }).click(); await page.waitForTimeout(1000); - expect( - await page + await expect( + page .locator('#active-credential-list vaadin-grid-cell-content') - .filter({ hasText: email }) - .isVisible(), - ).toBe(true); + .filter({ hasText: email }), + ).toBeVisible(); }); }); @@ -70,38 +68,34 @@ test.describe('Delete account', () => { await page.waitForTimeout(1000); }); test('Admin can delete account', async ({ page }) => { - const email = 'test4@lablup.com'; + const email = 'test4@lablup.com'; //Write account's email you want to delete await page .locator(`#controls[user-id="${email}"]`) .locator('mwc-icon-button[icon="delete_forever"]') .click(); await page.locator('#active-user-list #deleteOk').click(); await page.waitForTimeout(5000); - expect( - await page.getByRole('gridcell', { name: email, exact: true }).isHidden(), - ).toBe(true); + await expect( + page.getByRole('gridcell', { name: email, exact: true }), + ).toBeHidden(); await page.getByRole('tab', { name: 'Inactive' }).click(); await page.waitForTimeout(1000); - expect( - await page - .getByRole('gridcell', { name: email, exact: true }) - .isVisible(), - ).toBe(true); + await expect( + page.getByRole('gridcell', { name: email, exact: true }), + ).toBeVisible(); await page.getByRole('tab', { name: 'Credentials' }).click(); await page.waitForTimeout(1000); - expect( - await page + await expect( + page .locator('#active-credential-list vaadin-grid-cell-content') - .filter({ hasText: email }) - .isHidden(), - ).toBe(true); + .filter({ hasText: email }), + ).toBeHidden(); await page.getByRole('tab', { name: 'Inactive' }).click(); await page.waitForTimeout(1000); - expect( - await page + await expect( + page .locator('#inactive-credential-list vaadin-grid-cell-content') - .filter({ hasText: email }) - .isVisible(), - ).toBe(true); + .filter({ hasText: email }), + ).toBeVisible(); }); }); diff --git a/playwright/pages/DataStoragePage.spec.ts b/playwright/pages/DataStoragePage.spec.ts index 4cfedb8cc8..e51c95ac87 100644 --- a/playwright/pages/DataStoragePage.spec.ts +++ b/playwright/pages/DataStoragePage.spec.ts @@ -1,8 +1,7 @@ import { generateRandomString } from '../helper/helper'; import { test, expect } from '@playwright/test'; -test.describe('Vfolder creation', () => { - const randomVfolderName = generateRandomString(); +test.describe('Create vfolder', () => { test.beforeEach(async ({ page }) => { await page.goto('http://localhost:9081'); await page.locator('#id_user_id label').click(); @@ -16,33 +15,27 @@ test.describe('Vfolder creation', () => { await page.waitForURL('**/data'); }); test('User can create vfolder', async ({ page }) => { + const randomVfolderName = generateRandomString(); //Make random vfolder name await page.locator('#add-folder').click(); await page.locator('#add-folder-name').click(); await page.locator('#add-folder-name label').fill(randomVfolderName); await page.locator('#add-button').click(); - await page.waitForTimeout(5000); await page .getByRole('treegrid') .evaluate(async (e) => (e.scrollTop = e.scrollHeight)); - await page.waitForTimeout(1000); - expect( - await page - .getByText(`folder_open ${randomVfolderName}`, { exact: true }) - .isVisible(), - ).toBe(true); - expect( - await page - .locator( - `lablup-shields[folder-name=${randomVfolderName}][description="ready"]`, - ) - .isVisible(), - ).toBe(true); + await page.waitForSelector(`div[folder-name="${randomVfolderName}"]`); + await expect( + page.getByText(`folder_open ${randomVfolderName}`, { exact: true }), + ).toBeVisible(); + await expect( + page.locator( + `lablup-shields[folder-name="${randomVfolderName}"][description="ready"]`, + ), + ).toBeVisible(); }); }); -test.describe('Vfolder deletion', () => { - const deleteVfolderName = - 'dBvGpQPVo4V6ArAM3qtwnERwV5W5iL3WKZOJKA3rXX0rm0RgC10r1bA14AQoWC9F'; +test.describe('Delete Vfolder', () => { test.beforeEach(async ({ page }) => { await page.goto('http://localhost:9081'); await page.locator('#id_user_id label').click(); @@ -56,24 +49,27 @@ test.describe('Vfolder deletion', () => { await page.waitForURL('**/data'); }); test('User can delete vfolder', async ({ page }) => { + const deleteVfolderName = + 'PzHsLEJkWPXPdMirzYpR7Dpr530VbEuxX7bAJKSEuN60hSJzv6Q6m5wUh9h0PIKg'; //Write vfolder name you want to delete await page .getByRole('treegrid') .evaluate(async (e) => (e.scrollTop = e.scrollHeight)); - await page.waitForTimeout(1000); + await page.waitForSelector(`div[folder-name="${deleteVfolderName}"]`); await page - .locator(`#controls[folder-name=${deleteVfolderName}]`) + .locator(`#controls[folder-name="${deleteVfolderName}"]`) .locator('mwc-icon-button[icon="delete"]') .click(); await page.locator('#delete-folder-name').click(); await page.locator('#delete-folder-name label').fill(deleteVfolderName); await page.locator('#delete-button').click(); - await page.waitForTimeout(5000); - expect( - await page - .locator( - `lablup-shields[folder-name=${deleteVfolderName}][description="deleted-complete"]`, - ) - .isVisible(), - ).toBe(true); + await page + .getByRole('treegrid') + .evaluate(async (e) => (e.scrollTop = e.scrollHeight)); + await page.waitForSelector(`div[folder-name="${deleteVfolderName}"]`); + await expect( + page.locator( + `lablup-shields[folder-name="${deleteVfolderName}"][description="deleted-complete"]`, + ), + ).toBeVisible(); }); }); diff --git a/playwright/pages/LoginPage.spec.ts b/playwright/pages/LoginPage.spec.ts index 6c583576d1..f2820c6e5b 100644 --- a/playwright/pages/LoginPage.spec.ts +++ b/playwright/pages/LoginPage.spec.ts @@ -1,6 +1,6 @@ import { test, expect } from '@playwright/test'; -test.describe('LoginPage: User login', () => { +test.describe('Login user', () => { test.beforeEach(async ({ page }) => { await page.goto('http://localhost:9081'); }); @@ -16,12 +16,13 @@ test.describe('LoginPage: User login', () => { }); test('User login fail', async ({ page }) => { await page.locator('#id_user_id label').click(); - await page.locator('#id_user_id label').fill('test10@lablup.com'); + await page.locator('#id_user_id label').fill('test11@lablup.com'); await page.locator('#id_password label').click(); await page.locator('#id_password label').fill('test123!'); await page.locator('#id_api_endpoint label').click(); await page.locator('#id_api_endpoint label').fill('http://localhost:8090'); await page.locator('#login-button').click(); + await page.waitForTimeout(1000); await expect(page.locator('#app-body')).toBeHidden(); }); }); diff --git a/playwright/pages/SessionPage.spec.ts b/playwright/pages/SessionPage.spec.ts index 83677de686..a1f853db2b 100644 --- a/playwright/pages/SessionPage.spec.ts +++ b/playwright/pages/SessionPage.spec.ts @@ -13,15 +13,14 @@ test.describe('Create Session', () => { await page.locator('#login-button').click(); await page.locator('#session').click(); await page.waitForURL('**/job'); - await page.waitForTimeout(1000); }); test('User can create session', async ({ page }) => { - const version = 'Ubuntu 20.04 aarch64'; const randomSessionName = generateRandomString( 4, '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', - ); - const mountVfolderName = 'test'; + ); //Make random vfolder name + const version = 'Ubuntu 20.04 aarch64'; //Write version + const mountVfolderName = 'test'; //Write mount vfolder await page .locator('backend-ai-session-view') .locator('#launch-session') @@ -78,8 +77,8 @@ test.describe('Delete Session', () => { await page.waitForTimeout(1000); }); test('User can delete session', async ({ page }) => { - const sessionName = 'ssss'; - const sessionOwner = 'test@lablup.com'; + const sessionName = 'ssss'; //Write session name you want to delete + const sessionOwner = 'test@lablup.com'; //Write session owner await page .locator(`[id="${sessionName}-power"]`) .getByLabel('power_settings_new') From 4132b4cfb83f57c420663e00e5a45e4da80d3eae Mon Sep 17 00:00:00 2001 From: gee05053 Date: Thu, 18 Jan 2024 13:33:07 +0900 Subject: [PATCH 36/48] fix:modify result is shown as list --- playwright.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playwright.config.ts b/playwright.config.ts index b1172151bf..358d573d30 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -20,7 +20,7 @@ export default defineConfig({ /* Opt out of parallel tests on CI. */ workers: process.env.CI ? 1 : undefined, /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'html', + reporter: [['list', { printSteps: true }]], /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ use: { /* Base URL to use in actions like `await page.goto('/')`. */ From d1c2f1ff32248452a1506b4c4c144fe8a988f9e1 Mon Sep 17 00:00:00 2001 From: gee05053 Date: Sun, 21 Jan 2024 15:58:35 +0900 Subject: [PATCH 37/48] fix:add data-testid --- src/components/backend-ai-session-list.ts | 7 +++---- src/components/backend-ai-storage-list.ts | 5 +++-- src/components/backend-ai-webui.ts | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/components/backend-ai-session-list.ts b/src/components/backend-ai-session-list.ts index 0412921d98..3db817a1b0 100644 --- a/src/components/backend-ai-session-list.ts +++ b/src/components/backend-ai-session-list.ts @@ -3019,7 +3019,8 @@ ${rowData.item[this.sessionNameField]} - - ${rowData.item.status} - + ${rowData.item.status} ${!rowData.item.status_data || rowData.item.status_data === '{}' ? html`` : html` diff --git a/src/components/backend-ai-storage-list.ts b/src/components/backend-ai-storage-list.ts index b7a57aabd6..2a3065c868 100644 --- a/src/components/backend-ai-storage-list.ts +++ b/src/components/backend-ai-storage-list.ts @@ -1654,7 +1654,8 @@ export default class BackendAiStorageList extends BackendAIPage { // language=HTML html`
diff --git a/src/components/backend-ai-webui.ts b/src/components/backend-ai-webui.ts index 9cc053c910..8d4eddbafa 100644 --- a/src/components/backend-ai-webui.ts +++ b/src/components/backend-ai-webui.ts @@ -1394,7 +1394,7 @@ export default class BackendAIWebUI extends connect(store)(LitElement) { ${_t('webui.menu.Summary')} - ${_t('webui.menu.Import&Run')} - Date: Sun, 21 Jan 2024 16:01:22 +0900 Subject: [PATCH 38/48] fix:rollback user-list component --- src/components/backend-ai-user-list.ts | 50 ++++++++++++++------------ 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/src/components/backend-ai-user-list.ts b/src/components/backend-ai-user-list.ts index a6cb6f4573..291d94c06e 100644 --- a/src/components/backend-ai-user-list.ts +++ b/src/components/backend-ai-user-list.ts @@ -41,20 +41,20 @@ type LablupLoadingSpinner = HTMLElementTagNameMap['lablup-loading-spinner']; type BackendAIDialog = HTMLElementTagNameMap['backend-ai-dialog']; /** - Backend AI User List + Backend AI User List - `backend-ai-user-list` is list of user details. - Through this, user information can be read or modified, and the user can be logged out. + `backend-ai-user-list` is list of user details. + Through this, user information can be read or modified, and the user can be logged out. - Example: + Example: - - ... - + + ... + -@group Backend.AI Web UI - @element backend-ai-user-list - */ + @group Backend.AI Web UI + @element backend-ai-user-list + */ @customElement('backend-ai-user-list') export default class BackendAIUserList extends BackendAIPage { @@ -77,6 +77,7 @@ export default class BackendAIUserList extends BackendAIPage { @property({ type: Object }) _totpActivatedRenderer = this.totpActivatedRenderer.bind(this); @property({ type: Object }) keypairs; + @property({ type: String }) signoutUserName = ''; @property({ type: Object }) notification = Object(); @property({ type: String }) listCondition: StatusCondition = 'loading'; @property({ type: Number }) _totalUserCount = 0; @@ -304,24 +305,28 @@ export default class BackendAIUserList extends BackendAIPage { }); } - async _openUserSettingModal(userEmail) { - this.userEmail = userEmail; + async _openUserSettingModal(e) { + const controls = e.target.closest('#controls'); + this.userEmail = controls['user-id']; this.openUserSettingModal = true; } - async _openUserInfoModal(userEmail) { - this.userEmail = userEmail; + async _openUserInfoModal(e) { + const controls = e.target.closest('#controls'); + this.userEmail = controls['user-id']; this.openUserInfoModal = true; } - _signoutUserDialog(userEmail) { - this.userEmail = userEmail; + _signoutUserDialog(e) { + const controls = e.target.closest('#controls'); + const user_id = controls['user-id']; + this.signoutUserName = user_id; this.signoutUserDialog.show(); } _signoutUser() { globalThis.backendaiclient.user - .delete(this.userEmail) + .delete(this.signoutUserName) .then((response) => { this.notification.text = _text( 'credential.SignoutSeccessfullyFinished', @@ -494,24 +499,24 @@ export default class BackendAIUserList extends BackendAIPage {
${globalThis.backendaiclient.is_superadmin && this._isActive() ? html` ` : html``} @@ -692,7 +697,7 @@ export default class BackendAIUserList extends BackendAIPage {

You are inactivating the user - ${this.userEmail} + ${this.signoutUserName} .

${_t('dialog.ask.DoYouWantToProceed')}

@@ -703,7 +708,6 @@ export default class BackendAIUserList extends BackendAIPage { @click="${(e) => this._hideDialog(e)}" > Date: Sun, 21 Jan 2024 16:21:36 +0900 Subject: [PATCH 39/48] remove unnecessary whiteSpace --- src/components/backend-ai-user-list.ts | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/components/backend-ai-user-list.ts b/src/components/backend-ai-user-list.ts index 291d94c06e..02ac3a39b0 100644 --- a/src/components/backend-ai-user-list.ts +++ b/src/components/backend-ai-user-list.ts @@ -41,20 +41,20 @@ type LablupLoadingSpinner = HTMLElementTagNameMap['lablup-loading-spinner']; type BackendAIDialog = HTMLElementTagNameMap['backend-ai-dialog']; /** - Backend AI User List + Backend AI User List - `backend-ai-user-list` is list of user details. - Through this, user information can be read or modified, and the user can be logged out. + `backend-ai-user-list` is list of user details. + Through this, user information can be read or modified, and the user can be logged out. - Example: + Example: - - ... - + + ... + - @group Backend.AI Web UI - @element backend-ai-user-list - */ +@group Backend.AI Web UI + @element backend-ai-user-list + */ @customElement('backend-ai-user-list') export default class BackendAIUserList extends BackendAIPage { From 32fefb0abaf1ff8d96e1cb8d398731ed19eba696 Mon Sep 17 00:00:00 2001 From: gee05053 Date: Mon, 22 Jan 2024 17:29:41 +0900 Subject: [PATCH 40/48] fix:apply dotenv and waitForResponse --- playwright/pages/LoginPage.spec.ts | 34 ++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/playwright/pages/LoginPage.spec.ts b/playwright/pages/LoginPage.spec.ts index f2820c6e5b..0e12a80242 100644 --- a/playwright/pages/LoginPage.spec.ts +++ b/playwright/pages/LoginPage.spec.ts @@ -1,4 +1,9 @@ import { test, expect } from '@playwright/test'; +import dotenv from 'dotenv'; +import path from 'path'; + +dotenv.config(); +dotenv.config({ path: path.resolve(__dirname, '..', '.env') }); test.describe('Login user', () => { test.beforeEach(async ({ page }) => { @@ -6,23 +11,40 @@ test.describe('Login user', () => { }); test('User login success', async ({ page }) => { await page.locator('#id_user_id label').click(); - await page.locator('#id_user_id label').fill('test@lablup.com'); + await page.locator('#id_user_id label').fill(process.env.SUPER_ADMIN_EMAIL); await page.locator('#id_password label').click(); - await page.locator('#id_password label').fill('test123!'); + await page + .locator('#id_password label') + .fill(process.env.SUPER_ADMIN_PASSWORD); await page.locator('#id_api_endpoint label').click(); - await page.locator('#id_api_endpoint label').fill('http://localhost:8090'); + await page.locator('#id_api_endpoint label').fill(process.env.ENDPOINT); await page.locator('#login-button').click(); + await page.waitForResponse(async (response) => { + const responseJSONData = await response.json(); + return ( + response.url() === 'http://localhost:8090/server/login' && + response.status() === 200 && + responseJSONData?.authenticated + ); + }); await expect(page.locator('#app-body')).toBeVisible(); }); test('User login fail', async ({ page }) => { await page.locator('#id_user_id label').click(); - await page.locator('#id_user_id label').fill('test11@lablup.com'); + await page.locator('#id_user_id label').fill('test10@lablup.com'); await page.locator('#id_password label').click(); await page.locator('#id_password label').fill('test123!'); await page.locator('#id_api_endpoint label').click(); - await page.locator('#id_api_endpoint label').fill('http://localhost:8090'); + await page.locator('#id_api_endpoint label').fill(process.env.ENDPOINT); await page.locator('#login-button').click(); - await page.waitForTimeout(1000); + await page.waitForResponse(async (response) => { + const responseJSONData = await response.json(); + return ( + response.url() === 'http://localhost:8090/server/login' && + response.status() === 200 && //todo: Need to change status code after resolving this issue at core. + responseJSONData?.data?.details === 'User credential mismatch.' + ); + }); await expect(page.locator('#app-body')).toBeHidden(); }); }); From a58c74a7bb89af5371bcc322e5ba425cf5b2c38d Mon Sep 17 00:00:00 2001 From: gee05053 Date: Mon, 22 Jan 2024 18:11:29 +0900 Subject: [PATCH 41/48] fix:add .eslintignore and solve eslint error --- .eslintignore | 3 ++- playwright/pages/LoginPage.spec.ts | 20 ++++++++++++-------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/.eslintignore b/.eslintignore index 9d9e4add2c..4893ae96bf 100644 --- a/.eslintignore +++ b/.eslintignore @@ -15,4 +15,5 @@ src/lib/backend.ai-client-node.ts src/lib/backend.ai-client-node-to-es6.js src/lib/backend.ai-client-node-test-native-es6.js src/lib/Chart.min.js -src/lib/json_to_csv.js \ No newline at end of file +src/lib/json_to_csv.js +playwright/* \ No newline at end of file diff --git a/playwright/pages/LoginPage.spec.ts b/playwright/pages/LoginPage.spec.ts index 0e12a80242..2f762d472b 100644 --- a/playwright/pages/LoginPage.spec.ts +++ b/playwright/pages/LoginPage.spec.ts @@ -11,20 +11,23 @@ test.describe('Login user', () => { }); test('User login success', async ({ page }) => { await page.locator('#id_user_id label').click(); - await page.locator('#id_user_id label').fill(process.env.SUPER_ADMIN_EMAIL); + await page + .locator('#id_user_id label') + .fill(process.env.SUPER_ADMIN_EMAIL as string); await page.locator('#id_password label').click(); await page .locator('#id_password label') - .fill(process.env.SUPER_ADMIN_PASSWORD); + .fill(process.env.SUPER_ADMIN_PASSWORD as string); await page.locator('#id_api_endpoint label').click(); - await page.locator('#id_api_endpoint label').fill(process.env.ENDPOINT); + await page + .locator('#id_api_endpoint label') + .fill(process.env.ENDPOINT as string); await page.locator('#login-button').click(); await page.waitForResponse(async (response) => { - const responseJSONData = await response.json(); return ( response.url() === 'http://localhost:8090/server/login' && response.status() === 200 && - responseJSONData?.authenticated + (await response.json()).authenticated ); }); await expect(page.locator('#app-body')).toBeVisible(); @@ -35,14 +38,15 @@ test.describe('Login user', () => { await page.locator('#id_password label').click(); await page.locator('#id_password label').fill('test123!'); await page.locator('#id_api_endpoint label').click(); - await page.locator('#id_api_endpoint label').fill(process.env.ENDPOINT); + await page + .locator('#id_api_endpoint label') + .fill(process.env.ENDPOINT as string); await page.locator('#login-button').click(); await page.waitForResponse(async (response) => { - const responseJSONData = await response.json(); return ( response.url() === 'http://localhost:8090/server/login' && response.status() === 200 && //todo: Need to change status code after resolving this issue at core. - responseJSONData?.data?.details === 'User credential mismatch.' + (await response.json()).data.details === 'User credential mismatch.' ); }); await expect(page.locator('#app-body')).toBeHidden(); From 908e165d0450544b94ae41316d540185ffb97470 Mon Sep 17 00:00:00 2001 From: gee05053 Date: Mon, 22 Jan 2024 18:49:07 +0900 Subject: [PATCH 42/48] fix:modify timeout and apply testid --- playwright.config.ts | 1 + playwright/pages/DataStoragePage.spec.ts | 57 +++++++++++++++++------- 2 files changed, 43 insertions(+), 15 deletions(-) diff --git a/playwright.config.ts b/playwright.config.ts index 358d573d30..794774ce23 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -35,6 +35,7 @@ export default defineConfig({ { name: 'chromium', use: { ...devices['Desktop Chrome'] }, + timeout: 60000 }, { diff --git a/playwright/pages/DataStoragePage.spec.ts b/playwright/pages/DataStoragePage.spec.ts index e51c95ac87..0728068229 100644 --- a/playwright/pages/DataStoragePage.spec.ts +++ b/playwright/pages/DataStoragePage.spec.ts @@ -1,17 +1,28 @@ import { generateRandomString } from '../helper/helper'; import { test, expect } from '@playwright/test'; +import dotenv from 'dotenv'; +import path from 'path'; + +dotenv.config(); +dotenv.config({ path: path.resolve(__dirname, '..', '.env') }); test.describe('Create vfolder', () => { test.beforeEach(async ({ page }) => { await page.goto('http://localhost:9081'); await page.locator('#id_user_id label').click(); - await page.locator('#id_user_id label').fill('test@lablup.com'); + await page + .locator('#id_user_id label') + .fill(process.env.SUPER_ADMIN_EMAIL as string); await page.locator('#id_password label').click(); - await page.locator('#id_password label').fill('test123!'); + await page + .locator('#id_password label') + .fill(process.env.SUPER_ADMIN_PASSWORD as string); await page.locator('#id_api_endpoint label').click(); - await page.locator('#id_api_endpoint label').fill('http://localhost:8090'); + await page + .locator('#id_api_endpoint label') + .fill(process.env.ENDPOINT as string); await page.locator('#login-button').click(); - await page.locator('#data').click(); + await page.getByTestId('data').click(); await page.waitForURL('**/data'); }); test('User can create vfolder', async ({ page }) => { @@ -20,6 +31,13 @@ test.describe('Create vfolder', () => { await page.locator('#add-folder-name').click(); await page.locator('#add-folder-name label').fill(randomVfolderName); await page.locator('#add-button').click(); + await page.waitForResponse( + (response) => + response.url() === + 'http://localhost:8090/func/folders?group_id=2de2b969-1d04-48a6-af16-0bc8adb3c831' && + response.status() === 200, + { timeout: 0 }, + ); await page .getByRole('treegrid') .evaluate(async (e) => (e.scrollTop = e.scrollHeight)); @@ -28,9 +46,7 @@ test.describe('Create vfolder', () => { page.getByText(`folder_open ${randomVfolderName}`, { exact: true }), ).toBeVisible(); await expect( - page.locator( - `lablup-shields[folder-name="${randomVfolderName}"][description="ready"]`, - ), + page.getByTestId(randomVfolderName).getByText('ready'), ).toBeVisible(); }); }); @@ -39,18 +55,24 @@ test.describe('Delete Vfolder', () => { test.beforeEach(async ({ page }) => { await page.goto('http://localhost:9081'); await page.locator('#id_user_id label').click(); - await page.locator('#id_user_id label').fill('test@lablup.com'); + await page + .locator('#id_user_id label') + .fill(process.env.SUPER_ADMIN_EMAIL as string); await page.locator('#id_password label').click(); - await page.locator('#id_password label').fill('test123!'); + await page + .locator('#id_password label') + .fill(process.env.SUPER_ADMIN_PASSWORD as string); await page.locator('#id_api_endpoint label').click(); - await page.locator('#id_api_endpoint label').fill('http://localhost:8090'); + await page + .locator('#id_api_endpoint label') + .fill(process.env.ENDPOINT as string); await page.locator('#login-button').click(); - await page.locator('#data').click(); + await page.getByTestId('data').click(); await page.waitForURL('**/data'); }); test('User can delete vfolder', async ({ page }) => { const deleteVfolderName = - 'PzHsLEJkWPXPdMirzYpR7Dpr530VbEuxX7bAJKSEuN60hSJzv6Q6m5wUh9h0PIKg'; //Write vfolder name you want to delete + '51A28jtJ2sggtOUxceAv9KOJdSQaIQELddXxhaVhyFA1QAgP2EXjf1WMRoMvRXMC'; //Write vfolder name you want to delete await page .getByRole('treegrid') .evaluate(async (e) => (e.scrollTop = e.scrollHeight)); @@ -62,14 +84,19 @@ test.describe('Delete Vfolder', () => { await page.locator('#delete-folder-name').click(); await page.locator('#delete-folder-name label').fill(deleteVfolderName); await page.locator('#delete-button').click(); + await page.waitForResponse( + (response) => + response.url() === + 'http://localhost:8090/func/folders?group_id=2de2b969-1d04-48a6-af16-0bc8adb3c831' && + response.status() === 200, + { timeout: 0 }, + ); await page .getByRole('treegrid') .evaluate(async (e) => (e.scrollTop = e.scrollHeight)); await page.waitForSelector(`div[folder-name="${deleteVfolderName}"]`); await expect( - page.locator( - `lablup-shields[folder-name="${deleteVfolderName}"][description="deleted-complete"]`, - ), + page.getByTestId(deleteVfolderName).getByText('deleted-complete'), ).toBeVisible(); }); }); From 1e5e7473032721e7b174ace473a340fb32419cbd Mon Sep 17 00:00:00 2001 From: gee05053 Date: Mon, 22 Jan 2024 20:56:40 +0900 Subject: [PATCH 43/48] fix:apply dotenv and waitForRequest --- playwright/pages/SessionPage.spec.ts | 74 ++++++++++++++--------- src/components/backend-ai-session-list.ts | 6 +- 2 files changed, 51 insertions(+), 29 deletions(-) diff --git a/playwright/pages/SessionPage.spec.ts b/playwright/pages/SessionPage.spec.ts index a1f853db2b..15c0b8aaa5 100644 --- a/playwright/pages/SessionPage.spec.ts +++ b/playwright/pages/SessionPage.spec.ts @@ -1,17 +1,28 @@ import { generateRandomString } from '../helper/helper'; import { test, expect } from '@playwright/test'; +import dotenv from 'dotenv'; +import path from 'path'; + +dotenv.config(); +dotenv.config({ path: path.resolve(__dirname, '..', '.env') }); test.describe('Create Session', () => { test.beforeEach(async ({ page }) => { await page.goto('http://localhost:9081'); await page.locator('#id_user_id label').click(); - await page.locator('#id_user_id label').fill('test@lablup.com'); + await page + .locator('#id_user_id label') + .fill(process.env.SUPER_ADMIN_EMAIL as string); await page.locator('#id_password label').click(); - await page.locator('#id_password label').fill('test123!'); + await page + .locator('#id_password label') + .fill(process.env.SUPER_ADMIN_PASSWORD as string); await page.locator('#id_api_endpoint label').click(); - await page.locator('#id_api_endpoint label').fill('http://localhost:8090'); + await page + .locator('#id_api_endpoint label') + .fill(process.env.ENDPOINT as string); await page.locator('#login-button').click(); - await page.locator('#session').click(); + await page.getByTestId('session').click(); await page.waitForURL('**/job'); }); test('User can create session', async ({ page }) => { @@ -55,10 +66,16 @@ test.describe('Create Session', () => { .locator('backend-ai-session-view') .locator('#launch-button') .click(); - await page.waitForTimeout(5000); + await page.waitForResponse( + (response) => + response.url() === 'http://localhost:8090/func/session' && + response.status() === 201, + { timeout: 0 }, + ); await page.getByRole('button', { name: 'close' }).click(); - await page.waitForTimeout(2000); - expect(await page.getByText(randomSessionName).isVisible()).toBe(true); + await expect( + page.getByTestId(randomSessionName).getByText('RUNNING'), + ).toBeVisible(); }); }); @@ -66,35 +83,38 @@ test.describe('Delete Session', () => { test.beforeEach(async ({ page }) => { await page.goto('http://localhost:9081'); await page.locator('#id_user_id label').click(); - await page.locator('#id_user_id label').fill('test@lablup.com'); + await page + .locator('#id_user_id label') + .fill(process.env.SUPER_ADMIN_EMAIL as string); await page.locator('#id_password label').click(); - await page.locator('#id_password label').fill('test123!'); + await page + .locator('#id_password label') + .fill(process.env.SUPER_ADMIN_PASSWORD as string); await page.locator('#id_api_endpoint label').click(); - await page.locator('#id_api_endpoint label').fill('http://localhost:8090'); + await page + .locator('#id_api_endpoint label') + .fill(process.env.ENDPOINT as string); await page.locator('#login-button').click(); - await page.locator('#session').click(); + await page.getByTestId('session').click(); await page.waitForURL('**/job'); - await page.waitForTimeout(1000); }); test('User can delete session', async ({ page }) => { - const sessionName = 'ssss'; //Write session name you want to delete - const sessionOwner = 'test@lablup.com'; //Write session owner - await page - .locator(`[id="${sessionName}-power"]`) - .getByLabel('power_settings_new') - .click(); + const deleteSessionName = 'kxCW'; //Write session name you want to delete + await page.getByTestId(deleteSessionName + '-delete').click(); await page .locator(`#terminate-session-dialog`) .locator('mwc-button[class="ok"]') .click(); - await page.waitForTimeout(5000); - expect(await page.getByText(sessionName).isHidden()).toBe(true); - await page.getByRole('tab', { name: 'Finished' }).click(); - await page.waitForTimeout(1000); - expect( - await page - .getByRole('row', { name: `1 ${sessionOwner} ${sessionName}` }) - .isVisible(), - ).toBe(true); + await page.waitForRequest( + async (request) => + request.method() === 'DELETE' && + (await request.response())?.status() === 200, + { timeout: 0 }, + ); + await expect(page.getByText(deleteSessionName)).toBeHidden(); + await page.locator('mwc-tab[title="finished"]').click(); + await expect( + page.getByTestId(deleteSessionName).getByText('TERMINATED'), + ).toBeVisible(); }); }); diff --git a/src/components/backend-ai-session-list.ts b/src/components/backend-ai-session-list.ts index 3db817a1b0..816eff2a59 100644 --- a/src/components/backend-ai-session-list.ts +++ b/src/components/backend-ai-session-list.ts @@ -3020,7 +3020,7 @@ ${rowData.item[this.sessionNameField]} - ${rowData.item.status} + + ${rowData.item.status} + ${!rowData.item.status_data || rowData.item.status_data === '{}' ? html`` : html` From 6448fa4b9c1938314af0f25d3e0c384f4e391cae Mon Sep 17 00:00:00 2001 From: gee05053 Date: Mon, 22 Jan 2024 21:21:30 +0900 Subject: [PATCH 44/48] fix:apply dotenv and data-testid at CredentialPage --- playwright/pages/CredentialPage.spec.ts | 79 ++++++++++++++----------- src/components/backend-ai-user-list.ts | 2 + 2 files changed, 48 insertions(+), 33 deletions(-) diff --git a/playwright/pages/CredentialPage.spec.ts b/playwright/pages/CredentialPage.spec.ts index 5b6eff4a6b..f95fb2308a 100644 --- a/playwright/pages/CredentialPage.spec.ts +++ b/playwright/pages/CredentialPage.spec.ts @@ -1,24 +1,34 @@ import { test, expect } from '@playwright/test'; +import dotenv from 'dotenv'; +import path from 'path'; + +dotenv.config(); +dotenv.config({ path: path.resolve(__dirname, '..', '.env') }); test.describe('Create account', () => { test.beforeEach(async ({ page }) => { await page.goto('http://localhost:9081'); await page.locator('#id_user_id label').click(); - await page.locator('#id_user_id label').fill('test@lablup.com'); + await page + .locator('#id_user_id label') + .fill(process.env.SUPER_ADMIN_EMAIL as string); await page.locator('#id_password label').click(); - await page.locator('#id_password label').fill('test123!'); + await page + .locator('#id_password label') + .fill(process.env.SUPER_ADMIN_PASSWORD as string); await page.locator('#id_api_endpoint label').click(); - await page.locator('#id_api_endpoint label').fill('http://localhost:8090'); + await page + .locator('#id_api_endpoint label') + .fill(process.env.ENDPOINT as string); await page.locator('#login-button').click(); - await page.locator('#credential').click(); + await page.getByTestId('credential').click(); await page.waitForURL('**/credential'); - await page.getByRole('tab', { name: 'Users' }).click(); - await page.getByRole('tab', { name: 'Active', exact: true }).click(); - await page.waitForTimeout(1000); + await page.locator('mwc-tab[title="user-lists"]').click(); + await page.locator('mwc-tab[title="active-user-list"]').click(); }); test('Admin can create account', async ({ page }) => { - const email = 'test4@lablup.com'; //Write new account'email - const userName = 'test4'; //Write new account'userName + const email = 'test6@lablup.com'; //Write new account'email + const userName = 'test6'; //Write new account'userName const password = 'test123!'; //Write new account'password await page.locator('#add-user').click(); await page.locator('#new-user-dialog #id_user_email').click(); @@ -34,15 +44,13 @@ test.describe('Create account', () => { .locator('#new-user-dialog #id_user_confirm label') .fill(password); await page.locator('#new-user-dialog #create-user-button').click(); - await page.waitForTimeout(5000); await expect( page .locator('#active-user-list vaadin-grid-cell-content') .filter({ hasText: email }), ).toBeVisible(); - await page.getByRole('tab', { name: 'Credentials' }).click(); - await page.getByRole('tab', { name: 'Active', exact: true }).click(); - await page.waitForTimeout(1000); + await page.locator('mwc-tab[title="credential-lists"]').click(); + await page.locator('mwc-tab[title="active-credential-list"]').click(); await expect( page .locator('#active-credential-list vaadin-grid-cell-content') @@ -55,43 +63,48 @@ test.describe('Delete account', () => { test.beforeEach(async ({ page }) => { await page.goto('http://localhost:9081'); await page.locator('#id_user_id label').click(); - await page.locator('#id_user_id label').fill('test@lablup.com'); + await page + .locator('#id_user_id label') + .fill(process.env.SUPER_ADMIN_EMAIL as string); await page.locator('#id_password label').click(); - await page.locator('#id_password label').fill('test123!'); + await page + .locator('#id_password label') + .fill(process.env.SUPER_ADMIN_PASSWORD as string); await page.locator('#id_api_endpoint label').click(); - await page.locator('#id_api_endpoint label').fill('http://localhost:8090'); + await page + .locator('#id_api_endpoint label') + .fill(process.env.ENDPOINT as string); await page.locator('#login-button').click(); - await page.locator('#credential').click(); + await page.getByTestId('credential').click(); await page.waitForURL('**/credential'); - await page.getByRole('tab', { name: 'Users' }).click(); - await page.getByRole('tab', { name: 'Active', exact: true }).click(); - await page.waitForTimeout(1000); + await page.locator('mwc-tab[title="user-lists"]').click(); + await page.locator('mwc-tab[title="active-user-list"]').click(); }); test('Admin can delete account', async ({ page }) => { - const email = 'test4@lablup.com'; //Write account's email you want to delete - await page - .locator(`#controls[user-id="${email}"]`) - .locator('mwc-icon-button[icon="delete_forever"]') - .click(); - await page.locator('#active-user-list #deleteOk').click(); - await page.waitForTimeout(5000); + const email = 'test5@lablup.com'; //Write account's email you want to delete + await page.getByTestId(email).getByLabel('delete_forever').click(); + await page.locator('#active-user-list').getByTestId('deleteUser').click(); + await page.waitForResponse( + (response) => + response.url() === 'http://localhost:8090/func/admin/gql' && + response.body().then((b) => { + return b.includes('"delete_user": {"ok": true, "msg": "success"}'); + }), + ); await expect( page.getByRole('gridcell', { name: email, exact: true }), ).toBeHidden(); - await page.getByRole('tab', { name: 'Inactive' }).click(); - await page.waitForTimeout(1000); + await page.locator('mwc-tab[title="inactive-user-list"]').click(); await expect( page.getByRole('gridcell', { name: email, exact: true }), ).toBeVisible(); - await page.getByRole('tab', { name: 'Credentials' }).click(); - await page.waitForTimeout(1000); + await page.locator('mwc-tab[title="credential-lists"]').click(); await expect( page .locator('#active-credential-list vaadin-grid-cell-content') .filter({ hasText: email }), ).toBeHidden(); - await page.getByRole('tab', { name: 'Inactive' }).click(); - await page.waitForTimeout(1000); + await page.locator('mwc-tab[title="inactive-credential-list"]').click(); await expect( page .locator('#inactive-credential-list vaadin-grid-cell-content') diff --git a/src/components/backend-ai-user-list.ts b/src/components/backend-ai-user-list.ts index 02ac3a39b0..1e72044b04 100644 --- a/src/components/backend-ai-user-list.ts +++ b/src/components/backend-ai-user-list.ts @@ -516,6 +516,7 @@ export default class BackendAIUserList extends BackendAIPage { ` @@ -709,6 +710,7 @@ export default class BackendAIUserList extends BackendAIPage { > From ba081d6d321fca47529cd67d11658f043d915a92 Mon Sep 17 00:00:00 2001 From: gee05053 Date: Thu, 8 Feb 2024 17:14:33 +0900 Subject: [PATCH 45/48] fix:update after react-root --- playwright.config.ts | 5 ++++- playwright/pages/LoginPage.spec.ts | 19 ++++++++++++------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/playwright.config.ts b/playwright.config.ts index 794774ce23..7c3a0efa1e 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -38,15 +38,18 @@ export default defineConfig({ timeout: 60000 }, + /* Test firefox browsers { name: 'firefox', use: { ...devices['Desktop Firefox'] }, }, - + */ + /* Test webkit browsers { name: 'webkit', use: { ...devices['Desktop Safari'] }, }, + */ /* Test against mobile viewports. */ // { diff --git a/playwright/pages/LoginPage.spec.ts b/playwright/pages/LoginPage.spec.ts index 2f762d472b..31ac60bc4a 100644 --- a/playwright/pages/LoginPage.spec.ts +++ b/playwright/pages/LoginPage.spec.ts @@ -7,7 +7,7 @@ dotenv.config({ path: path.resolve(__dirname, '..', '.env') }); test.describe('Login user', () => { test.beforeEach(async ({ page }) => { - await page.goto('http://localhost:9081'); + await page.goto(process.env.PAGE_URL as string); }); test('User login success', async ({ page }) => { await page.locator('#id_user_id label').click(); @@ -25,18 +25,22 @@ test.describe('Login user', () => { await page.locator('#login-button').click(); await page.waitForResponse(async (response) => { return ( - response.url() === 'http://localhost:8090/server/login' && + response.url() === `${process.env.ENDPOINT as string}/server/login` && response.status() === 200 && (await response.json()).authenticated ); }); - await expect(page.locator('#app-body')).toBeVisible(); + await expect(page.locator('#app-page')).not.toHaveAttribute('inert'); }); test('User login fail', async ({ page }) => { await page.locator('#id_user_id label').click(); - await page.locator('#id_user_id label').fill('test10@lablup.com'); + await page + .locator('#id_user_id label') + .fill(process.env.INCORRECT_EMAIL as string); await page.locator('#id_password label').click(); - await page.locator('#id_password label').fill('test123!'); + await page + .locator('#id_password label') + .fill(process.env.INCORRECT_PASSWORD as string); await page.locator('#id_api_endpoint label').click(); await page .locator('#id_api_endpoint label') @@ -44,11 +48,12 @@ test.describe('Login user', () => { await page.locator('#login-button').click(); await page.waitForResponse(async (response) => { return ( - response.url() === 'http://localhost:8090/server/login' && + response.url() === `${process.env.ENDPOINT as string}/server/login` && response.status() === 200 && //todo: Need to change status code after resolving this issue at core. (await response.json()).data.details === 'User credential mismatch.' ); }); - await expect(page.locator('#app-body')).toBeHidden(); + await page.waitForTimeout(1000); + await expect(page.locator('#app-page')).toHaveAttribute('inert'); }); }); From 0765b9a3c04bbdd01564b450fa3d3da82ed83ebc Mon Sep 17 00:00:00 2001 From: gee05053 Date: Tue, 13 Feb 2024 14:54:24 +0900 Subject: [PATCH 46/48] modify endpoint url to dotenv --- playwright/pages/CredentialPage.spec.ts | 49 +++++++++++-------- playwright/pages/DataStoragePage.spec.ts | 32 +++++++----- playwright/pages/LoginPage.spec.ts | 4 +- playwright/pages/SessionPage.spec.ts | 29 ++++++----- .../src/components/MainLayout/WebUISider.tsx | 46 ++++++++--------- 5 files changed, 90 insertions(+), 70 deletions(-) diff --git a/playwright/pages/CredentialPage.spec.ts b/playwright/pages/CredentialPage.spec.ts index f95fb2308a..4c5ee7b87b 100644 --- a/playwright/pages/CredentialPage.spec.ts +++ b/playwright/pages/CredentialPage.spec.ts @@ -7,7 +7,7 @@ dotenv.config({ path: path.resolve(__dirname, '..', '.env') }); test.describe('Create account', () => { test.beforeEach(async ({ page }) => { - await page.goto('http://localhost:9081'); + await page.goto(process.env.PAGE_URL as string); await page.locator('#id_user_id label').click(); await page .locator('#id_user_id label') @@ -21,47 +21,48 @@ test.describe('Create account', () => { .locator('#id_api_endpoint label') .fill(process.env.ENDPOINT as string); await page.locator('#login-button').click(); - await page.getByTestId('credential').click(); + await page.getByRole('menu').getByTestId('credential').click(); await page.waitForURL('**/credential'); await page.locator('mwc-tab[title="user-lists"]').click(); await page.locator('mwc-tab[title="active-user-list"]').click(); }); test('Admin can create account', async ({ page }) => { - const email = 'test6@lablup.com'; //Write new account'email - const userName = 'test6'; //Write new account'userName - const password = 'test123!'; //Write new account'password await page.locator('#add-user').click(); await page.locator('#new-user-dialog #id_user_email').click(); - await page.locator('#new-user-dialog #id_user_email label').fill(email); + await page + .locator('#new-user-dialog #id_user_email label') + .fill(process.env.CREATE_USER_EMAIL as string); await page.locator('#new-user-dialog #id_user_name').click(); - await page.locator('#new-user-dialog #id_user_name label').fill(userName); + await page + .locator('#new-user-dialog #id_user_name label') + .fill(process.env.CREATE_USER_NAME as string); await page.locator('#new-user-dialog #id_user_password').click(); await page .locator('#new-user-dialog #id_user_password label') - .fill(password); + .fill(process.env.CREATE_USER_PASSWORD as string); await page.locator('#new-user-dialog #id_user_confirm').click(); await page .locator('#new-user-dialog #id_user_confirm label') - .fill(password); + .fill(process.env.CREATE_USER_PASSWORD as string); await page.locator('#new-user-dialog #create-user-button').click(); await expect( page .locator('#active-user-list vaadin-grid-cell-content') - .filter({ hasText: email }), + .filter({ hasText: process.env.CREATE_USER_EMAIL }), ).toBeVisible(); await page.locator('mwc-tab[title="credential-lists"]').click(); await page.locator('mwc-tab[title="active-credential-list"]').click(); await expect( page .locator('#active-credential-list vaadin-grid-cell-content') - .filter({ hasText: email }), + .filter({ hasText: process.env.CREATE_USER_EMAIL }), ).toBeVisible(); }); }); test.describe('Delete account', () => { test.beforeEach(async ({ page }) => { - await page.goto('http://localhost:9081'); + await page.goto(process.env.PAGE_URL as string); await page.locator('#id_user_id label').click(); await page .locator('#id_user_id label') @@ -75,40 +76,48 @@ test.describe('Delete account', () => { .locator('#id_api_endpoint label') .fill(process.env.ENDPOINT as string); await page.locator('#login-button').click(); - await page.getByTestId('credential').click(); + await page.getByRole('menu').getByTestId('credential').click(); await page.waitForURL('**/credential'); await page.locator('mwc-tab[title="user-lists"]').click(); await page.locator('mwc-tab[title="active-user-list"]').click(); }); test('Admin can delete account', async ({ page }) => { - const email = 'test5@lablup.com'; //Write account's email you want to delete - await page.getByTestId(email).getByLabel('delete_forever').click(); + await page + .getByTestId(process.env.DELETE_USER_EMAIL as string) + .getByLabel('delete_forever') + .click(); await page.locator('#active-user-list').getByTestId('deleteUser').click(); await page.waitForResponse( (response) => - response.url() === 'http://localhost:8090/func/admin/gql' && + response.url() === `${process.env.ENDPOINT}/func/admin/gql` && response.body().then((b) => { return b.includes('"delete_user": {"ok": true, "msg": "success"}'); }), ); await expect( - page.getByRole('gridcell', { name: email, exact: true }), + page.getByRole('gridcell', { + name: process.env.DELETE_USER_EMAIL, + exact: true, + }), ).toBeHidden(); await page.locator('mwc-tab[title="inactive-user-list"]').click(); await expect( - page.getByRole('gridcell', { name: email, exact: true }), + page.getByRole('gridcell', { + name: process.env.DELETE_USER_EMAIL, + exact: true, + }), ).toBeVisible(); await page.locator('mwc-tab[title="credential-lists"]').click(); await expect( page .locator('#active-credential-list vaadin-grid-cell-content') - .filter({ hasText: email }), + .filter({ hasText: process.env.DELETE_USER_EMAIL }), ).toBeHidden(); await page.locator('mwc-tab[title="inactive-credential-list"]').click(); await expect( page .locator('#inactive-credential-list vaadin-grid-cell-content') - .filter({ hasText: email }), + .filter({ hasText: process.env.DELETE_USER_EMAIL }), ).toBeVisible(); }); }); diff --git a/playwright/pages/DataStoragePage.spec.ts b/playwright/pages/DataStoragePage.spec.ts index 0728068229..f608e118cc 100644 --- a/playwright/pages/DataStoragePage.spec.ts +++ b/playwright/pages/DataStoragePage.spec.ts @@ -8,7 +8,7 @@ dotenv.config({ path: path.resolve(__dirname, '..', '.env') }); test.describe('Create vfolder', () => { test.beforeEach(async ({ page }) => { - await page.goto('http://localhost:9081'); + await page.goto(process.env.PAGE_URL as string); await page.locator('#id_user_id label').click(); await page .locator('#id_user_id label') @@ -22,7 +22,7 @@ test.describe('Create vfolder', () => { .locator('#id_api_endpoint label') .fill(process.env.ENDPOINT as string); await page.locator('#login-button').click(); - await page.getByTestId('data').click(); + await page.getByRole('menu').getByTestId('data').click(); await page.waitForURL('**/data'); }); test('User can create vfolder', async ({ page }) => { @@ -34,7 +34,7 @@ test.describe('Create vfolder', () => { await page.waitForResponse( (response) => response.url() === - 'http://localhost:8090/func/folders?group_id=2de2b969-1d04-48a6-af16-0bc8adb3c831' && + `${process.env.ENDPOINT}/func/folders?group_id=2de2b969-1d04-48a6-af16-0bc8adb3c831` && response.status() === 200, { timeout: 0 }, ); @@ -53,7 +53,7 @@ test.describe('Create vfolder', () => { test.describe('Delete Vfolder', () => { test.beforeEach(async ({ page }) => { - await page.goto('http://localhost:9081'); + await page.goto(process.env.PAGE_URL as string); await page.locator('#id_user_id label').click(); await page .locator('#id_user_id label') @@ -67,36 +67,42 @@ test.describe('Delete Vfolder', () => { .locator('#id_api_endpoint label') .fill(process.env.ENDPOINT as string); await page.locator('#login-button').click(); - await page.getByTestId('data').click(); + await page.getByRole('menu').getByTestId('data').click(); await page.waitForURL('**/data'); }); test('User can delete vfolder', async ({ page }) => { - const deleteVfolderName = - '51A28jtJ2sggtOUxceAv9KOJdSQaIQELddXxhaVhyFA1QAgP2EXjf1WMRoMvRXMC'; //Write vfolder name you want to delete await page .getByRole('treegrid') .evaluate(async (e) => (e.scrollTop = e.scrollHeight)); - await page.waitForSelector(`div[folder-name="${deleteVfolderName}"]`); + await page.waitForSelector( + `div[folder-name="${process.env.DELETE_VFOLDER}"]`, + ); await page - .locator(`#controls[folder-name="${deleteVfolderName}"]`) + .locator(`#controls[folder-name="${process.env.DELETE_VFOLDER}"]`) .locator('mwc-icon-button[icon="delete"]') .click(); await page.locator('#delete-folder-name').click(); - await page.locator('#delete-folder-name label').fill(deleteVfolderName); + await page + .locator('#delete-folder-name label') + .fill(process.env.DELETE_VFOLDER as string); await page.locator('#delete-button').click(); await page.waitForResponse( (response) => response.url() === - 'http://localhost:8090/func/folders?group_id=2de2b969-1d04-48a6-af16-0bc8adb3c831' && + `${process.env.ENDPOINT}/func/folders?group_id=2de2b969-1d04-48a6-af16-0bc8adb3c831` && response.status() === 200, { timeout: 0 }, ); await page .getByRole('treegrid') .evaluate(async (e) => (e.scrollTop = e.scrollHeight)); - await page.waitForSelector(`div[folder-name="${deleteVfolderName}"]`); + await page.waitForSelector( + `div[folder-name="${process.env.DELETE_VFOLDER}"]`, + ); await expect( - page.getByTestId(deleteVfolderName).getByText('deleted-complete'), + page + .getByTestId(process.env.DELETE_VFOLDER as string) + .getByText('deleted-complete'), ).toBeVisible(); }); }); diff --git a/playwright/pages/LoginPage.spec.ts b/playwright/pages/LoginPage.spec.ts index 31ac60bc4a..1291d1fe69 100644 --- a/playwright/pages/LoginPage.spec.ts +++ b/playwright/pages/LoginPage.spec.ts @@ -25,7 +25,7 @@ test.describe('Login user', () => { await page.locator('#login-button').click(); await page.waitForResponse(async (response) => { return ( - response.url() === `${process.env.ENDPOINT as string}/server/login` && + response.url() === `${process.env.ENDPOINT}/server/login` && response.status() === 200 && (await response.json()).authenticated ); @@ -48,7 +48,7 @@ test.describe('Login user', () => { await page.locator('#login-button').click(); await page.waitForResponse(async (response) => { return ( - response.url() === `${process.env.ENDPOINT as string}/server/login` && + response.url() === `${process.env.ENDPOINT}/server/login` && response.status() === 200 && //todo: Need to change status code after resolving this issue at core. (await response.json()).data.details === 'User credential mismatch.' ); diff --git a/playwright/pages/SessionPage.spec.ts b/playwright/pages/SessionPage.spec.ts index 15c0b8aaa5..1a07b71f16 100644 --- a/playwright/pages/SessionPage.spec.ts +++ b/playwright/pages/SessionPage.spec.ts @@ -8,7 +8,7 @@ dotenv.config({ path: path.resolve(__dirname, '..', '.env') }); test.describe('Create Session', () => { test.beforeEach(async ({ page }) => { - await page.goto('http://localhost:9081'); + await page.goto(process.env.PAGE_URL as string); await page.locator('#id_user_id label').click(); await page .locator('#id_user_id label') @@ -22,7 +22,7 @@ test.describe('Create Session', () => { .locator('#id_api_endpoint label') .fill(process.env.ENDPOINT as string); await page.locator('#login-button').click(); - await page.getByTestId('session').click(); + await page.getByRole('menu').getByTestId('session').click(); await page.waitForURL('**/job'); }); test('User can create session', async ({ page }) => { @@ -30,8 +30,6 @@ test.describe('Create Session', () => { 4, '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', ); //Make random vfolder name - const version = 'Ubuntu 20.04 aarch64'; //Write version - const mountVfolderName = 'test'; //Write mount vfolder await page .locator('backend-ai-session-view') .locator('#launch-session') @@ -39,7 +37,7 @@ test.describe('Create Session', () => { await page.locator('backend-ai-session-view').locator('#version').click(); await page .locator('backend-ai-session-view') - .getByRole('option', { name: version }) + .getByRole('option', { name: process.env.NEW_SESSION_VERSION }) .click(); await page .locator('backend-ai-session-view') @@ -53,7 +51,9 @@ test.describe('Create Session', () => { .locator('backend-ai-session-view') .locator('#next-button') .click(); - await page.getByText(`${mountVfolderName} local:volume1`).click(); + await page + .getByText(`${process.env.NEW_SESSION_MOUNTED_VFOLDER} local:volume1`) + .click(); await page .locator('backend-ai-session-view') .locator('#next-button') @@ -68,7 +68,7 @@ test.describe('Create Session', () => { .click(); await page.waitForResponse( (response) => - response.url() === 'http://localhost:8090/func/session' && + response.url() === `${process.env.ENDPOINT}/func/session` && response.status() === 201, { timeout: 0 }, ); @@ -81,7 +81,7 @@ test.describe('Create Session', () => { test.describe('Delete Session', () => { test.beforeEach(async ({ page }) => { - await page.goto('http://localhost:9081'); + await page.goto(process.env.PAGE_URL as string); await page.locator('#id_user_id label').click(); await page .locator('#id_user_id label') @@ -95,12 +95,11 @@ test.describe('Delete Session', () => { .locator('#id_api_endpoint label') .fill(process.env.ENDPOINT as string); await page.locator('#login-button').click(); - await page.getByTestId('session').click(); + await page.getByRole('menu').getByTestId('session').click(); await page.waitForURL('**/job'); }); test('User can delete session', async ({ page }) => { - const deleteSessionName = 'kxCW'; //Write session name you want to delete - await page.getByTestId(deleteSessionName + '-delete').click(); + await page.getByTestId(process.env.DELETE_SESSION + '-delete').click(); await page .locator(`#terminate-session-dialog`) .locator('mwc-button[class="ok"]') @@ -111,10 +110,14 @@ test.describe('Delete Session', () => { (await request.response())?.status() === 200, { timeout: 0 }, ); - await expect(page.getByText(deleteSessionName)).toBeHidden(); + await expect( + page.getByText(process.env.DELETE_SESSION as string), + ).toBeHidden(); await page.locator('mwc-tab[title="finished"]').click(); await expect( - page.getByTestId(deleteSessionName).getByText('TERMINATED'), + page + .getByTestId(process.env.DELETE_SESSION as string) + .getByText('TERMINATED'), ).toBeVisible(); }); }); diff --git a/react/src/components/MainLayout/WebUISider.tsx b/react/src/components/MainLayout/WebUISider.tsx index 711f307281..5acf6ef22d 100644 --- a/react/src/components/MainLayout/WebUISider.tsx +++ b/react/src/components/MainLayout/WebUISider.tsx @@ -58,7 +58,7 @@ const WebUISider: React.FC = (props) => { key: 'summary', }, { - label: t('webui.menu.Sessions'), + label:
{t('webui.menu.Sessions')}
, icon: , key: 'job', }, @@ -73,7 +73,7 @@ const WebUISider: React.FC = (props) => { key: 'import', }, { - label: t('webui.menu.Data&Storage'), + label:
{t('webui.menu.Data&Storage')}
, icon: , key: 'data', }, @@ -99,7 +99,7 @@ const WebUISider: React.FC = (props) => { const adminMenu: MenuProps['items'] = [ { - label: t('webui.menu.Users'), + label:
{t('webui.menu.Users')}
, icon: , key: 'credential', }, @@ -305,25 +305,27 @@ const WebUISider: React.FC = (props) => { }, ] : currentUserRole === 'admin' - ? [ - ...generalMenu, - { - type: 'group', - label: ( - - {!props.collapsed && ( - - {t('webui.menu.Administration')} - - )} - - ), - children: [...adminMenu], - }, - ] - : [...generalMenu] + ? [ + ...generalMenu, + { + type: 'group', + label: ( + + {!props.collapsed && ( + + {t('webui.menu.Administration')} + + )} + + ), + children: [...adminMenu], + }, + ] + : [...generalMenu] } /** * Etc menu From fe7a755c3fe41592577e4adce487288b29a9250a Mon Sep 17 00:00:00 2001 From: gee05053 Date: Wed, 21 Feb 2024 11:13:26 +0900 Subject: [PATCH 47/48] fix: remove hard code about group_id and add request test code about creation and deletion --- playwright/pages/DataStoragePage.spec.ts | 25 +++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/playwright/pages/DataStoragePage.spec.ts b/playwright/pages/DataStoragePage.spec.ts index f608e118cc..a7536b9a79 100644 --- a/playwright/pages/DataStoragePage.spec.ts +++ b/playwright/pages/DataStoragePage.spec.ts @@ -33,11 +33,18 @@ test.describe('Create vfolder', () => { await page.locator('#add-button').click(); await page.waitForResponse( (response) => - response.url() === - `${process.env.ENDPOINT}/func/folders?group_id=2de2b969-1d04-48a6-af16-0bc8adb3c831` && + response.url() === `${process.env.ENDPOINT}/func/folders` && + response.status() === 201, + { timeout: 0 }, + ); //POST vfolder create + await page.waitForResponse( + (response) => + response + .url() + .includes(`${process.env.ENDPOINT}/func/folders?group_id`) && response.status() === 200, { timeout: 0 }, - ); + ); //GET vfolder list await page .getByRole('treegrid') .evaluate(async (e) => (e.scrollTop = e.scrollHeight)); @@ -89,10 +96,18 @@ test.describe('Delete Vfolder', () => { await page.waitForResponse( (response) => response.url() === - `${process.env.ENDPOINT}/func/folders?group_id=2de2b969-1d04-48a6-af16-0bc8adb3c831` && + `${process.env.ENDPOINT}/func/folders/${process.env.DELETE_VFOLDER}` && + response.status() === 204, + { timeout: 0 }, + ); //DELETE vfolder + await page.waitForResponse( + (response) => + response + .url() + .includes(`${process.env.ENDPOINT}/func/folders?group_id`) && response.status() === 200, { timeout: 0 }, - ); + ); //GET vfolder list await page .getByRole('treegrid') .evaluate(async (e) => (e.scrollTop = e.scrollHeight)); From 278c09f01d8ccf7cf1d3ca694739cdb30a5906ff Mon Sep 17 00:00:00 2001 From: gee05053 Date: Wed, 21 Feb 2024 14:20:54 +0900 Subject: [PATCH 48/48] feat: add test about show list by group --- playwright.config.ts | 2 +- playwright/pages/DataStoragePage.spec.ts | 72 +++++++++++++++++++++++- react/src/components/ProjectSelect.tsx | 41 +++++++------- src/components/backend-ai-data-view.ts | 2 + 4 files changed, 95 insertions(+), 22 deletions(-) diff --git a/playwright.config.ts b/playwright.config.ts index 7c3a0efa1e..93f848c6f6 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -35,7 +35,7 @@ export default defineConfig({ { name: 'chromium', use: { ...devices['Desktop Chrome'] }, - timeout: 60000 + timeout: 80000 }, /* Test firefox browsers diff --git a/playwright/pages/DataStoragePage.spec.ts b/playwright/pages/DataStoragePage.spec.ts index a7536b9a79..5260380ab9 100644 --- a/playwright/pages/DataStoragePage.spec.ts +++ b/playwright/pages/DataStoragePage.spec.ts @@ -24,12 +24,46 @@ test.describe('Create vfolder', () => { await page.locator('#login-button').click(); await page.getByRole('menu').getByTestId('data').click(); await page.waitForURL('**/data'); + await page.locator('#add-folder').click(); }); - test('User can create vfolder', async ({ page }) => { + test('User can create user vfolder', async ({ page }) => { + const randomVfolderName = generateRandomString(); //Make random vfolder name + await page.locator('#add-folder-name').click(); + await page.locator('#add-folder-name label').fill(randomVfolderName); + await page.locator('#add-button').click(); + await page.waitForResponse( + (response) => + response.url() === `${process.env.ENDPOINT}/func/folders` && + response.status() === 201, + { timeout: 0 }, + ); //POST vfolder create + await page.waitForResponse( + (response) => + response + .url() + .includes(`${process.env.ENDPOINT}/func/folders?group_id`) && + response.status() === 200, + { timeout: 0 }, + ); //GET vfolder list + await page + .getByRole('treegrid') + .evaluate(async (e) => (e.scrollTop = e.scrollHeight)); + await page.waitForSelector(`div[folder-name="${randomVfolderName}"]`); + await expect( + page.getByText(`folder_open ${randomVfolderName}`, { exact: true }), + ).toBeVisible(); + await expect( + page.getByTestId(randomVfolderName).getByText('ready'), + ).toBeVisible(); + }); + test('User can create group vfolder', async ({ page }) => { const randomVfolderName = generateRandomString(); //Make random vfolder name - await page.locator('#add-folder').click(); await page.locator('#add-folder-name').click(); await page.locator('#add-folder-name label').fill(randomVfolderName); + await page.locator('#add-folder-type').click(); + await page.getByTestId('group').click(); + await page.locator('#add-folder-group').click(); + await page.getByTestId(`${process.env.CREATE_VFOLDER_GROUP}`).click(); await page.locator('#add-button').click(); await page.waitForResponse( (response) => @@ -45,6 +79,20 @@ test.describe('Create vfolder', () => { response.status() === 200, { timeout: 0 }, ); //GET vfolder list + await page.getByTestId('projectSelect').click(); + await page + .locator('#rc_select_1') + .fill(`${process.env.CREATE_VFOLDER_GROUP}`); + await page.keyboard.press('Enter'); + await page.waitForTimeout(1000); + await page.waitForResponse( + (response) => + response + .url() + .includes(`${process.env.ENDPOINT}/func/folders?group_id`) && + response.status() === 200, + { timeout: 0 }, + ); //GET vfolder list await page .getByRole('treegrid') .evaluate(async (e) => (e.scrollTop = e.scrollHeight)); @@ -55,6 +103,26 @@ test.describe('Create vfolder', () => { await expect( page.getByTestId(randomVfolderName).getByText('ready'), ).toBeVisible(); + await page.getByTestId('projectSelect').click(); + await page + .locator('#rc_select_1') + .fill(`${process.env.NOT_CREATE_VFOLDER_GROUP}`); + await page.keyboard.press('Enter'); + await page.waitForTimeout(1000); + await page.waitForResponse( + (response) => + response + .url() + .includes(`${process.env.ENDPOINT}/func/folders?group_id`) && + response.status() === 200, + { timeout: 0 }, + ); //GET vfolder list + await page + .getByRole('treegrid') + .evaluate(async (e) => (e.scrollTop = e.scrollHeight)); + await expect( + page.getByText(`folder_open ${randomVfolderName}`, { exact: true }), + ).not.toBeVisible(); }); }); diff --git a/react/src/components/ProjectSelect.tsx b/react/src/components/ProjectSelect.tsx index cce86506d7..7a246dcd40 100644 --- a/react/src/components/ProjectSelect.tsx +++ b/react/src/components/ProjectSelect.tsx @@ -60,25 +60,28 @@ const ProjectSelector: React.FC = ({ } }); return ( - { + setValue(value); + onSelectProject?.(option as ProjectInfo); + }} + placeholder={t('storageHost.quotaSettings.SelectProject')} + {...selectProps} + value={value} + optionFilterProp="projectName" + options={_.map(_.sortBy(projects, 'name'), (project) => { + return { + label: project?.name, + value: project?.id, + projectId: project?.id, + id: project?.name, + projectResourcePolicy: project?.resource_policy, + projectName: project?.name, + }; + })} + /> +
); }; diff --git a/src/components/backend-ai-data-view.ts b/src/components/backend-ai-data-view.ts index 7ac62bc442..cda88ce877 100644 --- a/src/components/backend-ai-data-view.ts +++ b/src/components/backend-ai-data-view.ts @@ -517,6 +517,7 @@ export default class BackendAIData extends BackendAIPage { ? html` ${_t('data.Project')} @@ -536,6 +537,7 @@ export default class BackendAIData extends BackendAIPage { ${this.groupListByUsage.map( (item, idx) => html`