diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..5e4fa3e5 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,16 @@ +version: 2 +updates: + - package-ecosystem: npm + directory: "/tests/UI" + schedule: + interval: weekly + day: monday + time: "04:00" + open-pull-requests-limit: 10 + target-branch: dev + reviewers: + - "PrestaShop/qa-automation" + labels: + - "dependencies" + - "E2E Tests" + - "TE" diff --git a/.github/workflows/ui-test.yml b/.github/workflows/ui-test.yml new file mode 100644 index 00000000..861f385f --- /dev/null +++ b/.github/workflows/ui-test.yml @@ -0,0 +1,110 @@ +name: UI Tests +on: + ## Check each PR + push: + pull_request: + ## Manual execution on branch + workflow_dispatch: + ## Nightly + ### Needs secrets + #### GC_PROJECT_ID + #### GC_SERVICE_KEY + #### NIGHTLY_TOKEN + schedule: + - cron: '0 0 * * *' +jobs: + ui_test: + name: UI Tests + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + - ps-version: '8.0.5' + php-version: '8.1' + - ps-version: '8.1.4' + php-version: '8.1' + - ps-version: 'nightly' + php-version: '8.2' + env: + PS_VERSION: ${{ matrix.ps-version }} + PHP_VERSION: ${{ matrix.php-version }} + steps: + - name: Checkout + uses: actions/checkout@v3.1.0 + + - uses: actions/setup-node@v3 + with: + node-version: 14 + + - name: Build + run: npm install && npm run build + + - name: Start containers + working-directory: tests/UI/ + run: | + docker-compose -f "docker-compose.yml" up -d --build + bash -c 'while [[ "$(curl -L -s -o /dev/null -w %{http_code} http://localhost/en/)" != "200" ]]; do sleep 5; done' + + - name: Install dependencies + working-directory: tests/UI/ + run: npm ci + + - name: Install Playwright Browsers + working-directory: tests/UI/ + run: npx playwright install chromium --with-deps + + - name: Run Playwright tests + working-directory: tests/UI/ + run: npx playwright test + + - name: Export Docker errors + working-directory: tests/UI/ + if: always() + run: docker-compose logs --no-color >& docker-compose.log + + - name: Upload artifact + uses: actions/upload-artifact@v4 + if: always() + with: + name: playwright-report-${{ env.PS_VERSION }} + path: | + tests/UI/reports/ + tests/UI/report.json + tests/UI/docker-compose.log + retention-days: 30 + + # Nightly : Rename file + - name: "Nightly : Rename file" + working-directory: tests/UI/ + if: ${{ github.event_name == 'schedule' }} + run: | + mkdir -p nightly + REPORT_NAME="blockwishlist_$(date +%Y-%m-%d)-${{ env.PS_VERSION }}" + mv report.json nightly/${REPORT_NAME}.json + + # Nightly : Auth GCP + - name: "Nightly : Auth GCP" + uses: google-github-actions/auth@v1 + if: ${{ github.event_name == 'schedule' }} + with: + credentials_json: ${{ secrets.GC_SERVICE_KEY }} + project_id: ${{ secrets.GC_PROJECT_ID }} + + # Nightly : Setup GCP + - name: "Nightly : Setup GCP" + uses: google-github-actions/setup-gcloud@v1 + if: ${{ github.event_name == 'schedule' }} + + # Nightly : Upload to Google Cloud Storage (GCS) + - name: "Nightly : Upload to Google Cloud Storage (GCS)" + working-directory: tests/UI/ + if: ${{ github.event_name == 'schedule' }} + run: gsutil cp -r "nightly/**" gs://prestashop-core-nightly/reports + + # Nightly : Push Report + - name: "Nightly : Push Report" + if: ${{ github.event_name == 'schedule' }} + run: | + REPORT_NAME="blockwishlist_$(date +%Y-%m-%d)-${{ env.PS_VERSION }}" + curl -v "https://api-nightly.prestashop-project.org/import/report/playwright?token=${{ secrets.NIGHTLY_TOKEN }}&filename=${REPORT_NAME}.json" diff --git a/.gitignore b/.gitignore index 83006710..ce688301 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,9 @@ node_modules # mac .DS_Store + +## UI Tests +/tests/UI/.env +/tests/UI/node_modules/ +/tests/UI/report.json +/tests/UI/reports/ diff --git a/package.json b/package.json index 96ae1de8..c7ac5feb 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "watch": "npm run dev", "lint": "eslint -c .eslintrc.js --ext .js,.vue .", "lint-fix": "eslint -c .eslintrc.js --ext .js,.vue . --fix", - "test": "mochapack --webpack-config .webpack/common.js --require tests/UI/setup.js tests/UI/**/*.spec.js" + "test": "mochapack --webpack-config .webpack/common.js --require tests/js/setup.js tests/js/**/*.spec.js" }, "author": "PrestaShop", "license": "AFL-3.0", diff --git a/tests/UI/campaigns/02_configuration/02_statisticsTabSettings.spec.ts b/tests/UI/campaigns/02_configuration/02_statisticsTabSettings.spec.ts new file mode 100644 index 00000000..1cb9d798 --- /dev/null +++ b/tests/UI/campaigns/02_configuration/02_statisticsTabSettings.spec.ts @@ -0,0 +1,175 @@ +import { + // Import utils + testContext, + // Import BO pages + boDashboardPage, + boLoginPage, + boModuleManagerPage, + // Import FO pages + foCategoryPage, + foHomePage, + foLoginPage, + // Import modules + modBlockwishlistBoMain, + modBlockwishlistBoStatistics, + // Import data + dataCustomers, + dataModules, +} from '@prestashop-core/ui-testing'; + +import { test, expect, Page, BrowserContext } from '@playwright/test'; + +const baseContext: string = 'modules_blockwishlist_configuration_statisticsTabSettings'; + +test.describe('Wishlist module - Statistics tab settings', () => { + let browserContext: BrowserContext; + let page: Page; + + test.beforeAll(async ({ browser }) => { + browserContext = await browser.newContext(); + page = await browserContext.newPage(); + }); + test.afterAll(async () => { + await page.close(); + }); + + test('should login in BO', async () => { + await testContext.addContextItem(test.info(), 'testIdentifier', 'loginBO', baseContext); + + await boLoginPage.goTo(page, global.BO.URL); + await boLoginPage.successLogin(page, global.BO.EMAIL, global.BO.PASSWD); + + const pageTitle = await boDashboardPage.getPageTitle(page); + expect(pageTitle).toContain(boDashboardPage.pageTitle); + }); + + test('should go to \'Modules > Module Manager\' page', async () => { + await testContext.addContextItem(test.info(), 'testIdentifier', 'goToModuleManagerPage', baseContext); + + await boDashboardPage.goToSubMenu( + page, + boDashboardPage.modulesParentLink, + boDashboardPage.moduleManagerLink, + ); + await boModuleManagerPage.closeSfToolBar(page); + + const pageTitle = await boModuleManagerPage.getPageTitle(page); + expect(pageTitle).toContain(boModuleManagerPage.pageTitle); + }); + + + test(`should search the module ${dataModules.blockwishlist.name}`, async () => { + await testContext.addContextItem(test.info(), 'testIdentifier', 'searchModule', baseContext); + + const isModuleVisible = await boModuleManagerPage.searchModule(page, dataModules.blockwishlist); + expect(isModuleVisible).toEqual(true); + }); + + test(`should go to the configuration page of the module '${dataModules.blockwishlist.name}'`, async () => { + await testContext.addContextItem(test.info(), 'testIdentifier', 'goToConfigurationPage', baseContext); + + await boModuleManagerPage.goToConfigurationPage(page, dataModules.blockwishlist.tag); + + const pageTitle = await modBlockwishlistBoMain.getPageTitle(page); + expect(pageTitle).toEqual(modBlockwishlistBoMain.pageTitle); + + const isConfigurationTabActive = await modBlockwishlistBoMain.isTabActive(page, 'Configuration'); + expect(isConfigurationTabActive).toEqual(true); + + const isStatisticsTabActive = await modBlockwishlistBoMain.isTabActive(page, 'Statistics'); + expect(isStatisticsTabActive).toEqual(false); + }); + + test('should go on Statistics Tab', async () => { + await testContext.addContextItem(test.info(), 'testIdentifier', 'goToStatisticsTab', baseContext); + + await modBlockwishlistBoMain.goToStatisticsTab(page); + + const pageTitle = await modBlockwishlistBoStatistics.getPageTitle(page); + expect(pageTitle).toEqual(modBlockwishlistBoStatistics.pageTitle); + + const noRecordsFoundText = await modBlockwishlistBoStatistics.getTextForEmptyTable(page); + expect(noRecordsFoundText).toContain('warning No records found'); + }); + + test('should go to the FO', async () => { + await testContext.addContextItem(test.info(), 'testIdentifier', 'goToFO', baseContext); + + page = await modBlockwishlistBoStatistics.viewMyShop(page); + await foHomePage.changeLanguage(page, 'en'); + + const isHomePage = await foHomePage.isHomePage(page); + expect(isHomePage).toEqual(true); + }); + + test('should go to login page', async () => { + await testContext.addContextItem(test.info(), 'testIdentifier', 'goToLoginPage', baseContext); + + await foHomePage.goToLoginPage(page); + + const pageTitle = await foLoginPage.getPageTitle(page); + expect(pageTitle, 'Fail to open FO login page').toContain(foLoginPage.pageTitle); + }); + + test('should sign in with default customer', async () => { + await testContext.addContextItem(test.info(), 'testIdentifier', 'sighInFo', baseContext); + + await foLoginPage.customerLogin(page, dataCustomers.johnDoe); + + const isCustomerConnected = await foLoginPage.isCustomerConnected(page); + expect(isCustomerConnected, 'Customer is not connected').toEqual(true); + }); + + test('should go to all products page', async () => { + await testContext.addContextItem(test.info(), 'testIdentifier', 'goToAllProducts', baseContext); + + await foHomePage.goToAllProductsPage(page); + + const isCategoryPageVisible = await foCategoryPage.isCategoryPage(page); + expect(isCategoryPageVisible).toEqual(true); + }); + + for (let idxProduct: number = 1; idxProduct <= 3; idxProduct++) { + // eslint-disable-next-line no-loop-func + test(`should add product #${idxProduct} to wishlist`, async () => { + await testContext.addContextItem(test.info(), 'testIdentifier', `addToFavorite${idxProduct}`, baseContext); + + const textResult = await foCategoryPage.addToWishList(page, idxProduct); + expect(textResult).toEqual(foCategoryPage.messageAddedToWishlist); + + const isAddedToWishlist = await foCategoryPage.isAddedToWishlist(page, idxProduct); + expect(isAddedToWishlist).toEqual(true); + }); + } + + test('should logout', async () => { + await testContext.addContextItem(test.info(), 'testIdentifier', 'foLogout', baseContext); + + await foCategoryPage.logout(page); + + const isCustomerConnected = await foHomePage.isCustomerConnected(page); + expect(isCustomerConnected).toEqual(false); + }); + + test('should go to BO', async () => { + await testContext.addContextItem(test.info(), 'testIdentifier', 'goToBoBack', baseContext); + + page = await foHomePage.closePage(browserContext, page, 0); + + const pageTitle = await modBlockwishlistBoStatistics.getPageTitle(page); + expect(pageTitle).toContain(modBlockwishlistBoStatistics.pageTitle); + }); + + // @todo : https://github.com/PrestaShop/PrestaShop/issues/33374 + test('should click on the refresh button', async () => { + await testContext.addContextItem(test.info(), 'testIdentifier', 'clickOnRefreshButton', baseContext); + + test.skip(true, 'https://github.com/PrestaShop/PrestaShop/issues/33374'); + + await modBlockwishlistBoStatistics.refreshStatistics(page); + + // Check statistics + const pageTitle = await modBlockwishlistBoStatistics.getPageTitle(page); + expect(pageTitle).toContain(modBlockwishlistBoStatistics.pageTitle); + }); +}); diff --git a/tests/UI/docker-compose.yml b/tests/UI/docker-compose.yml new file mode 100644 index 00000000..079ae6ca --- /dev/null +++ b/tests/UI/docker-compose.yml @@ -0,0 +1,54 @@ +version: '3.7' + +services: + prestashop: + image: prestashop/prestashop:${PS_VERSION}-${PHP_VERSION}-apache + container_name: prestashop + depends_on: + - mysql + environment: + - PS_DEV_MODE=1 + - PS_DOMAIN=localhost + - PS_LANGUAGE=en + - PS_COUNTRY=fr + - PS_INSTALL_AUTO=1 + - PS_FOLDER_ADMIN=admin-dev + - PS_FOLDER_INSTALL=install-dev + - PS_USE_DOCKER_MAILDEV=0 + - ADMIN_MAIL=demo@prestashop.com + - ADMIN_PASSWD=prestashop + - DB_SERVER=mysql + - DB_USER=prestashop + - DB_PASSWD=prestashop + - DB_NAME=prestashop + volumes: + - type: bind + # Local Path + source: ../../ + # Mount Path + target: /var/www/html/modules/blockwishlist + ports: + - 80:80 + mysql: + image: mariadb:lts + container_name: prestashop-mysql + healthcheck: + test: + [ + 'CMD', + 'mysqladmin', + 'ping', + '--host=localhost', + '--user=prestashop', + '--password=prestashop', + ] + interval: 5s + timeout: 10s + retries: 5 + environment: + - MYSQL_HOST=mysql + - MYSQL_USER=prestashop + - MYSQL_PASSWORD=prestashop + - MYSQL_ROOT_PASSWORD=prestashop + - MYSQL_PORT=3306 + - MYSQL_DATABASE=prestashop diff --git a/tests/UI/package-lock.json b/tests/UI/package-lock.json new file mode 100644 index 00000000..6e22a740 --- /dev/null +++ b/tests/UI/package-lock.json @@ -0,0 +1,1001 @@ +{ + "name": "blockwishlist_tests_ui", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "blockwishlist_tests_ui", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "dotenv": "^16.3.1" + }, + "devDependencies": { + "@playwright/test": "^1.40.1", + "@prestashop-core/ui-testing": "^0.0.6", + "@types/node": "^20.11.5", + "pwmochawesome": "^1.1.1", + "typescript": "^5.3.3" + } + }, + "node_modules/@faker-js/faker": { + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-8.3.1.tgz", + "integrity": "sha512-FdgpFxY6V6rLZE9mmIBb9hM0xpfvQOSNOLnzolzKwsE1DH+gC7lEKV1p1IbR0lAYyvYd5a4u3qWJzowUkw1bIw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/fakerjs" + } + ], + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0", + "npm": ">=6.14.13" + } + }, + "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/@prestashop-core/ui-testing": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@prestashop-core/ui-testing/-/ui-testing-0.0.6.tgz", + "integrity": "sha512-aq8oyemHtYXbCFP7bjKytFaJXq2dbc67kQNAzEGKgrOSuOPCTB1UO9CQ6x5aG90MasSBHMlj4sTOZaJuFALUtw==", + "dev": true, + "dependencies": { + "@faker-js/faker": "^8.3.1", + "@playwright/test": "^1.40.1", + "semver": "^7.5.4" + } + }, + "node_modules/@types/node": { + "version": "20.11.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.5.tgz", + "integrity": "sha512-g557vgQjUUfN76MZAN/dt1z3dzcUsimuysco0KeluHgrPdJXkP/XdAURgyO2W9fZWHRtRBiVKzKn8vyOAwlG+w==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/ansi-regex": { + "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" + } + }, + "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==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "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/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "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==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "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==", + "dev": true + }, + "node_modules/dateformat": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", + "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/dotenv": { + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", + "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/motdotla/dotenv?sponsor=1" + } + }, + "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==", + "dev": true + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/fsu": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/fsu/-/fsu-1.1.1.tgz", + "integrity": "sha512-xQVsnjJ/5pQtcKh+KjUoZGzVWn4uNkchxTF6Lwjr4Gf7nQr8fmUfhKJ62zE77+xQg9xnxi5KUps7XGs+VC986A==", + "dev": true + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "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==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-fullwidth-code-point": { + "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" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/lodash.isfunction": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", + "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==", + "dev": true + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "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==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mochawesome-report-generator": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/mochawesome-report-generator/-/mochawesome-report-generator-6.2.0.tgz", + "integrity": "sha512-Ghw8JhQFizF0Vjbtp9B0i//+BOkV5OWcQCPpbO0NGOoxV33o+gKDYU0Pr2pGxkIHnqZ+g5mYiXF7GMNgAcDpSg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.2", + "dateformat": "^4.5.1", + "escape-html": "^1.0.3", + "fs-extra": "^10.0.0", + "fsu": "^1.1.1", + "lodash.isfunction": "^3.0.9", + "opener": "^1.5.2", + "prop-types": "^15.7.2", + "tcomb": "^3.2.17", + "tcomb-validation": "^3.3.0", + "validator": "^13.6.0", + "yargs": "^17.2.1" + }, + "bin": { + "marge": "bin/cli.js" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/opener": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", + "dev": true, + "bin": { + "opener": "bin/opener-bin.js" + } + }, + "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/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/pwmochawesome": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pwmochawesome/-/pwmochawesome-1.1.1.tgz", + "integrity": "sha512-Gceyrsut9tD6fe8vpJoGcR9WNn92aOscTXnFgjmnQB6HbtXXtAhUCOU2HrKw0TWf/+cyD0FMYEeYSL8qvLVTeA==", + "dev": true, + "dependencies": { + "mochawesome-report-generator": "^6.2.0", + "strip-ansi": "^6.0.1", + "uuid": "^9.0.1" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "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==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "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==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "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" + }, + "engines": { + "node": ">=8" + } + }, + "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==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tcomb": { + "version": "3.2.29", + "resolved": "https://registry.npmjs.org/tcomb/-/tcomb-3.2.29.tgz", + "integrity": "sha512-di2Hd1DB2Zfw6StGv861JoAF5h/uQVu/QJp2g8KVbtfKnoHdBQl5M32YWq6mnSYBQ1vFFrns5B1haWJL7rKaOQ==", + "dev": true + }, + "node_modules/tcomb-validation": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/tcomb-validation/-/tcomb-validation-3.4.1.tgz", + "integrity": "sha512-urVVMQOma4RXwiVCa2nM2eqrAomHROHvWPuj6UkDGz/eb5kcy0x6P0dVt6kzpUZtYMNoAqJLWmz1BPtxrtjtrA==", + "dev": true, + "dependencies": { + "tcomb": "^3.0.0" + } + }, + "node_modules/typescript": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "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==", + "dev": true + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/validator": { + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.11.0.tgz", + "integrity": "sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "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==", + "dev": true, + "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/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + } + }, + "dependencies": { + "@faker-js/faker": { + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-8.3.1.tgz", + "integrity": "sha512-FdgpFxY6V6rLZE9mmIBb9hM0xpfvQOSNOLnzolzKwsE1DH+gC7lEKV1p1IbR0lAYyvYd5a4u3qWJzowUkw1bIw==", + "dev": true + }, + "@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, + "requires": { + "playwright": "1.40.1" + } + }, + "@prestashop-core/ui-testing": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@prestashop-core/ui-testing/-/ui-testing-0.0.6.tgz", + "integrity": "sha512-aq8oyemHtYXbCFP7bjKytFaJXq2dbc67kQNAzEGKgrOSuOPCTB1UO9CQ6x5aG90MasSBHMlj4sTOZaJuFALUtw==", + "dev": true, + "requires": { + "@faker-js/faker": "^8.3.1", + "@playwright/test": "^1.40.1", + "semver": "^7.5.4" + } + }, + "@types/node": { + "version": "20.11.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.5.tgz", + "integrity": "sha512-g557vgQjUUfN76MZAN/dt1z3dzcUsimuysco0KeluHgrPdJXkP/XdAURgyO2W9fZWHRtRBiVKzKn8vyOAwlG+w==", + "dev": true, + "requires": { + "undici-types": "~5.26.4" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + } + }, + "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==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "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==", + "dev": true + }, + "dateformat": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", + "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", + "dev": true + }, + "dotenv": { + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", + "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==" + }, + "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==", + "dev": true + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "fsu": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/fsu/-/fsu-1.1.1.tgz", + "integrity": "sha512-xQVsnjJ/5pQtcKh+KjUoZGzVWn4uNkchxTF6Lwjr4Gf7nQr8fmUfhKJ62zE77+xQg9xnxi5KUps7XGs+VC986A==", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "is-fullwidth-code-point": { + "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 + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "lodash.isfunction": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", + "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==", + "dev": true + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "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==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "mochawesome-report-generator": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/mochawesome-report-generator/-/mochawesome-report-generator-6.2.0.tgz", + "integrity": "sha512-Ghw8JhQFizF0Vjbtp9B0i//+BOkV5OWcQCPpbO0NGOoxV33o+gKDYU0Pr2pGxkIHnqZ+g5mYiXF7GMNgAcDpSg==", + "dev": true, + "requires": { + "chalk": "^4.1.2", + "dateformat": "^4.5.1", + "escape-html": "^1.0.3", + "fs-extra": "^10.0.0", + "fsu": "^1.1.1", + "lodash.isfunction": "^3.0.9", + "opener": "^1.5.2", + "prop-types": "^15.7.2", + "tcomb": "^3.2.17", + "tcomb-validation": "^3.3.0", + "validator": "^13.6.0", + "yargs": "^17.2.1" + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true + }, + "opener": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", + "dev": true + }, + "playwright": { + "version": "1.40.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.40.1.tgz", + "integrity": "sha512-2eHI7IioIpQ0bS1Ovg/HszsN/XKNwEG1kbzSDDmADpclKc7CyqkHw7Mg2JCz/bbCxg25QUPcjksoMW7JcIFQmw==", + "dev": true, + "requires": { + "fsevents": "2.3.2", + "playwright-core": "1.40.1" + } + }, + "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 + }, + "prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "pwmochawesome": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pwmochawesome/-/pwmochawesome-1.1.1.tgz", + "integrity": "sha512-Gceyrsut9tD6fe8vpJoGcR9WNn92aOscTXnFgjmnQB6HbtXXtAhUCOU2HrKw0TWf/+cyD0FMYEeYSL8qvLVTeA==", + "dev": true, + "requires": { + "mochawesome-report-generator": "^6.2.0", + "strip-ansi": "^6.0.1", + "uuid": "^9.0.1" + } + }, + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "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==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "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==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "tcomb": { + "version": "3.2.29", + "resolved": "https://registry.npmjs.org/tcomb/-/tcomb-3.2.29.tgz", + "integrity": "sha512-di2Hd1DB2Zfw6StGv861JoAF5h/uQVu/QJp2g8KVbtfKnoHdBQl5M32YWq6mnSYBQ1vFFrns5B1haWJL7rKaOQ==", + "dev": true + }, + "tcomb-validation": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/tcomb-validation/-/tcomb-validation-3.4.1.tgz", + "integrity": "sha512-urVVMQOma4RXwiVCa2nM2eqrAomHROHvWPuj6UkDGz/eb5kcy0x6P0dVt6kzpUZtYMNoAqJLWmz1BPtxrtjtrA==", + "dev": true, + "requires": { + "tcomb": "^3.0.0" + } + }, + "typescript": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "dev": true + }, + "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==", + "dev": true + }, + "universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true + }, + "uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "dev": true + }, + "validator": { + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.11.0.tgz", + "integrity": "sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "requires": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + } + }, + "yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true + } + } +} diff --git a/tests/UI/package.json b/tests/UI/package.json new file mode 100644 index 00000000..d3ba72cd --- /dev/null +++ b/tests/UI/package.json @@ -0,0 +1,19 @@ +{ + "name": "blockwishlist_tests_ui", + "version": "1.0.0", + "description": "", + "scripts": {}, + "keywords": [], + "author": "", + "license": "MIT", + "devDependencies": { + "@playwright/test": "^1.40.1", + "@prestashop-core/ui-testing": "^0.0.6", + "@types/node": "^20.11.5", + "pwmochawesome": "^1.1.1", + "typescript": "^5.3.3" + }, + "dependencies": { + "dotenv": "^16.3.1" + } +} diff --git a/tests/UI/playwright.config.ts b/tests/UI/playwright.config.ts new file mode 100644 index 00000000..0d64da8e --- /dev/null +++ b/tests/UI/playwright.config.ts @@ -0,0 +1,117 @@ +import { defineConfig, devices } from '@playwright/test'; +import { config } from 'dotenv'; +import path from 'path'; + +function loadGlobal(): void { + global.FO = { + URL: process.env.URL_FO || 'http://localhost/', + }; + + /* + Linked to the issue #22581 + */ + global.URLHasPort = (global.FO.URL).match(/:\d+.+/) !== null; + + global.BO = { + URL: process.env.URL_BO || `${global.FO.URL}admin-dev/`, + EMAIL: process.env.LOGIN || 'demo@prestashop.com', + PASSWD: process.env.PASSWD || 'prestashop', + FIRSTNAME: process.env.FIRSTNAME || 'Marc', + LASTNAME: process.env.LASTNAME || 'Beier', + }; + + global.PSConfig = { + parametersFile: process.env.PS_PARAMETERS_FILE || path.resolve(__dirname, '../../../', 'app/config/parameters.php'), + }; + + global.INSTALL = { + URL: process.env.URL_INSTALL || `${global.FO.URL}install-dev/`, + LANGUAGE: process.env.INSTALL_LANGUAGE || 'en', + COUNTRY: process.env.INSTALL_COUNTRY || 'France', + ENABLE_SSL: process.env.ENABLE_SSL === 'true', + DB_SERVER: process.env.DB_SERVER || '127.0.0.1', + DB_NAME: process.env.DB_NAME || 'prestashopdb', + DB_USER: process.env.DB_USER || 'root', + DB_PASSWD: process.env.DB_PASSWD || '', + DB_PREFIX: process.env.DB_PREFIX || 'tst_', + SHOP_NAME: process.env.SHOP_NAME || 'PrestaShop', + }; + + global.BROWSER = { + name: process.env.BROWSER || 'chromium', + lang: process.env.BROWSER_LANG || 'en-GB', + width: process.env.BROWSER_WIDTH ? parseInt(process.env.BROWSER_WIDTH, 10) : 1680, + height: process.env.BROWSER_HEIGHT ? parseInt(process.env.BROWSER_HEIGHT, 10) : 900, + sandboxArgs: ['--no-sandbox', '--disable-setuid-sandbox'], + acceptDownloads: true, + config: { + headless: process.env.HEADLESS ? JSON.parse(process.env.HEADLESS) : true, + timeout: 0, + slowMo: process.env.SLOW_MO ? parseInt(process.env.SLOW_MO, 10) : 5, + }, + interceptErrors: process.env.INTERCEPT_ERRORS ? JSON.parse(process.env.INTERCEPT_ERRORS) : false, + }; + + global.GENERATE_FAILED_STEPS = process.env.GENERATE_FAILED_STEPS ? JSON.parse(process.env.GENERATE_FAILED_STEPS) : false; + + global.SCREENSHOT = { + FOLDER: process.env.SCREENSHOT_FOLDER || './screenshots', + AFTER_FAIL: process.env.TAKE_SCREENSHOT_AFTER_FAIL ? JSON.parse(process.env.TAKE_SCREENSHOT_AFTER_FAIL) : false, + }; + + global.maildevConfig = { + smtpPort: parseInt(process.env.SMTP_PORT ?? '1025', 10), + smtpServer: process.env.SMTP_SERVER || 'localhost', + silent: true, + }; +} + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +config(); +/** + * Load global data from environment variables + */ +loadGlobal(); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './', + /* Run tests in files in serial */ + fullyParallel: false, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + retries: 0, + workers: 1, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: [ + ['list', { printSteps: true }], + ['json', { outputFile: 'report.json' }], + ['html', { outputFolder: 'reports' }], + ], + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Capture screenshot after each test failure */ + screenshot: 'only-on-failure', + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { + ...devices['Desktop Chrome'], + contextOptions: { + screen: { + width: 1680, + height: 900 + } + }, + }, + }, + ], +}); diff --git a/tests/UI/tsconfig.json b/tests/UI/tsconfig.json new file mode 100644 index 00000000..f52e6323 --- /dev/null +++ b/tests/UI/tsconfig.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "noImplicitAny": true, + "noImplicitThis": true, + "module": "es2022", + "target": "es2017", + "strict": true, + "moduleResolution": "node", + "allowSyntheticDefaultImports": true, + "resolveJsonModule": true, + "esModuleInterop": true, + "allowJs": true, + "downlevelIteration": true, + "baseUrl": "./", + "paths": {}, + "typeRoots": [ + "node_modules/@types" + ], + "skipLibCheck": true, + "noEmit": true + }, + "include": ["types/global.d.ts", "campaigns/**/*"], + "exclude": ["node_modules"] +} diff --git a/tests/UI/types/global.d.ts b/tests/UI/types/global.d.ts new file mode 100644 index 00000000..a9a68ab7 --- /dev/null +++ b/tests/UI/types/global.d.ts @@ -0,0 +1,27 @@ +import type { + GlobalInstall, + GlobalFO, + GlobalBO, + GlobalBrowserConfig, + GlobalPSConfig, + GlobalBrowserErrors, + GlobalScreenshot, + GlobalMaildevConfig, + GlobalKeycloakConfig +} from '@prestashop-core/ui-testing'; + +declare global { + var INSTALL: GlobalInstall; + var URLHasPort: boolean; + var FO: GlobalFO; + var BO: GlobalBO; + var PSConfig: GlobalPSConfig; + var BROWSER: GlobalBrowserConfig; + var GENERATE_FAILED_STEPS: any; + var SCREENSHOT: GlobalScreenshot; + var maildevConfig: GlobalMaildevConfig; + var keycloakConfig: GlobalKeycloakConfig; + var browserErrors: GlobalBrowserErrors; +} + +export {}; diff --git a/tests/UI/Button.spec.js b/tests/js/Button.spec.js similarity index 100% rename from tests/UI/Button.spec.js rename to tests/js/Button.spec.js diff --git a/tests/UI/Create.spec.js b/tests/js/Create.spec.js similarity index 100% rename from tests/UI/Create.spec.js rename to tests/js/Create.spec.js diff --git a/tests/UI/Delete.spec.js b/tests/js/Delete.spec.js similarity index 100% rename from tests/UI/Delete.spec.js rename to tests/js/Delete.spec.js diff --git a/tests/UI/List.spec.js b/tests/js/List.spec.js similarity index 100% rename from tests/UI/List.spec.js rename to tests/js/List.spec.js diff --git a/tests/UI/Login.spec.js b/tests/js/Login.spec.js similarity index 100% rename from tests/UI/Login.spec.js rename to tests/js/Login.spec.js diff --git a/tests/UI/Rename.spec.js b/tests/js/Rename.spec.js similarity index 100% rename from tests/UI/Rename.spec.js rename to tests/js/Rename.spec.js diff --git a/tests/UI/Toast.spec.js b/tests/js/Toast.spec.js similarity index 100% rename from tests/UI/Toast.spec.js rename to tests/js/Toast.spec.js diff --git a/tests/UI/setup.js b/tests/js/setup.js similarity index 100% rename from tests/UI/setup.js rename to tests/js/setup.js