From a8e75459b475b2286752fc1fde3f1a1db80693f0 Mon Sep 17 00:00:00 2001 From: Jake Jackson Date: Thu, 16 Apr 2026 14:02:15 +1000 Subject: [PATCH 1/5] Add Playwright E2E tests --- .github/workflows/end-to-end-tests.yml | 117 - .github/workflows/playwright-e2e.yml | 156 + .testcaferc.js | 19 - bin/htaccess-sample | 15 - bin/install-database.sh | 4 - bin/install-gravityforms.sh | 13 - bin/install-post-actions.sh | 6 - bin/install.sh | 40 - package.json | 97 +- .../confirmation-shortcode.test.js | 203 -- .../debug-mode-shortcode.test.js | 48 - tests/e2e/advanced-checks/merge-tags.test.js | 38 - .../advanced-checks/pdf-restriction.test.js | 101 - .../e2e/advanced-checks/pdf-tempalte.test.js | 101 - tests/e2e/auth.js | 28 - tests/e2e/models/Page.js | 138 - .../enable-pdf-security-field.test.js | 30 - .../enable-public-access-field.test.js | 44 - .../advanced/format-field.test.js | 80 - .../advanced/image-dpi-field.test.js | 34 - .../advanced/password-field.test.js | 82 - .../advanced/privileges-field.test.js | 81 - .../advanced/restrict-owner-field.test.js | 41 - .../appearance/font-color-field.test.js | 33 - .../appearance/font-field.test.js | 186 - .../appearance/font-size-field.test.js | 30 - .../paper-orientation-field.test.js | 28 - .../appearance/paper-size-field.test.js | 89 - .../appearance/reverse-text-rtl-field.test.js | 28 - .../general/conditional-logic-field.test.js | 46 - .../general/filename-field.test.js | 67 - .../pdf-settings/general/label-field.test.js | 41 - .../general/notifications-field.test.js | 37 - .../general/template-field.test.js | 160 - .../template/background-color-field.test.js | 33 - .../template/background-image-field.test.js | 68 - .../enable-conditional-logic-field.test.js | 28 - .../template/first-page-footer-field.test.js | 81 - .../template/first-page-header-field.test.js | 81 - .../template/footer-field.test.js | 77 - .../template/header-field.test.js | 79 - .../template/show-empty-fields-test.js | 28 - .../template/show-form-title-field.test.js | 28 - .../template/show-html-fields-field.test.js | 28 - .../template/show-page-names-field.test.js | 28 - ...ow-section-break-description-field.test.js | 28 - .../background-processing-field.test.js | 29 - .../general-settings/debug-mode-field.test.js | 28 - .../default-font-color-field.test.js | 38 - .../default-font-field.test.js | 185 - .../default-font-size-field.test.js | 31 - .../default-owner-restrictions-field.test.js | 30 - .../default-paper-size-field.test.js | 89 - .../default-template-field.test.js | 240 -- .../general-settings/entry-view-field.test.js | 64 - .../logged-out-timeout-field.test.js | 31 - .../reverse-text-rtl-field.test.js | 28 - .../user-restriction-field.test.js | 363 -- tests/e2e/tabs/license/license-field.test.js | 18 - .../license/sample-plugin-license.test.js | 40 - tests/e2e/tabs/tools/fonts-field.test.js | 130 - .../tools/install-core-fonts-field.test.js | 59 - .../tools/uninstall-gravity-pdf-field.test.js | 16 - .../page-model/helpers/advanced-check.js | 179 - .../e2e/utilities/page-model/helpers/field.js | 87 - .../page-model/helpers/font-manager.js | 60 - .../page-model/helpers/media-manager.js | 25 - .../e2e/utilities/page-model/helpers/page.js | 53 - tests/e2e/utilities/page-model/helpers/pdf.js | 265 -- .../page-model/helpers/search-params.js | 13 - .../page-model/helpers/template-manager.js | 70 - .../page-model/tabs/general-settings.js | 74 - .../e2e/utilities/page-model/tabs/license.js | 30 - tests/e2e/utilities/page-model/tabs/tools.js | 49 - .../utilities/resources/background-image.jpg | Bin 11420 -> 0 bytes .../FontManager/FontVariant.test.js | 10 +- .../conditional-logic-pdf.spec.ts | 86 + .../inactive-pdf.spec.ts | 86 + .../multiple-pdfs.spec.ts | 75 + .../entry-list-and-details/single-pdf.spec.ts | 75 + .../core/pdf-access/inactive.spec.ts | 99 + .../core/pdf-access/security.spec.ts | 178 + .../core/pdf-settings/pdf-settings.spec.ts | 410 +++ .../download-mergetag/attributes.spec.ts | 63 + .../text-confirmation.spec.ts | 50 + .../copy-to-clipboard.spec.ts | 36 + .../download-shortcode/inactive-pdf.spec.ts | 77 + .../page-confirmation.spec.ts | 72 + .../redirect-confirmation.spec.ts | 45 + .../text-confirmation.spec.ts | 45 + .../permalinks/managers/font-manager.spec.ts | 201 ++ .../managers/template-manager.spec.ts | 149 + tools/mu-plugins/admin-styles.php | 12 + tools/mu-plugins/gravityforms.php | 45 + tools/mu-plugins/gravitypdf.php | 8 + tools/mu-plugins/mpdf.php | 19 + tools/playwright/config.ts | 114 + .../playwright/data/fonts}/Roboto-Bold.ttf | Bin .../data/fonts}/Roboto-BoldItalic.ttf | Bin .../playwright/data/fonts}/Roboto-Regular.ttf | Bin .../data/fonts}/Roboto-RegularItalic.ttf | Bin tools/playwright/data/forms/standard.json | 1263 +++++++ tools/playwright/data/images/thumbnail.jpg | Bin 0 -> 11142 bytes .../data/template}/test-template.zip | Bin tools/playwright/fixtures/test.ts | 8 + tools/playwright/flaky-tests-reporter.ts | 85 + tools/playwright/global-setup.ts | 28 + tools/playwright/utils/gravityforms.ts | 185 + tools/playwright/utils/gravitypdf.ts | 194 + tools/wp-env/e2e-permalinks.json | 33 + tools/wp-env/e2e.json | 33 + tsconfig.json | 13 + yarn.lock | 3214 +++++++---------- 113 files changed, 5393 insertions(+), 6790 deletions(-) delete mode 100644 .github/workflows/end-to-end-tests.yml create mode 100644 .github/workflows/playwright-e2e.yml delete mode 100644 .testcaferc.js delete mode 100644 bin/htaccess-sample delete mode 100755 bin/install-database.sh delete mode 100755 bin/install-gravityforms.sh delete mode 100644 bin/install-post-actions.sh delete mode 100755 bin/install.sh delete mode 100644 tests/e2e/advanced-checks/confirmation-shortcode.test.js delete mode 100644 tests/e2e/advanced-checks/debug-mode-shortcode.test.js delete mode 100644 tests/e2e/advanced-checks/merge-tags.test.js delete mode 100644 tests/e2e/advanced-checks/pdf-restriction.test.js delete mode 100644 tests/e2e/advanced-checks/pdf-tempalte.test.js delete mode 100644 tests/e2e/auth.js delete mode 100644 tests/e2e/models/Page.js delete mode 100644 tests/e2e/pdf-settings/advanced/enable-pdf-security-field.test.js delete mode 100644 tests/e2e/pdf-settings/advanced/enable-public-access-field.test.js delete mode 100644 tests/e2e/pdf-settings/advanced/format-field.test.js delete mode 100644 tests/e2e/pdf-settings/advanced/image-dpi-field.test.js delete mode 100644 tests/e2e/pdf-settings/advanced/password-field.test.js delete mode 100644 tests/e2e/pdf-settings/advanced/privileges-field.test.js delete mode 100644 tests/e2e/pdf-settings/advanced/restrict-owner-field.test.js delete mode 100644 tests/e2e/pdf-settings/appearance/font-color-field.test.js delete mode 100644 tests/e2e/pdf-settings/appearance/font-field.test.js delete mode 100644 tests/e2e/pdf-settings/appearance/font-size-field.test.js delete mode 100644 tests/e2e/pdf-settings/appearance/paper-orientation-field.test.js delete mode 100644 tests/e2e/pdf-settings/appearance/paper-size-field.test.js delete mode 100644 tests/e2e/pdf-settings/appearance/reverse-text-rtl-field.test.js delete mode 100644 tests/e2e/pdf-settings/general/conditional-logic-field.test.js delete mode 100644 tests/e2e/pdf-settings/general/filename-field.test.js delete mode 100644 tests/e2e/pdf-settings/general/label-field.test.js delete mode 100644 tests/e2e/pdf-settings/general/notifications-field.test.js delete mode 100644 tests/e2e/pdf-settings/general/template-field.test.js delete mode 100644 tests/e2e/pdf-settings/template/background-color-field.test.js delete mode 100644 tests/e2e/pdf-settings/template/background-image-field.test.js delete mode 100644 tests/e2e/pdf-settings/template/enable-conditional-logic-field.test.js delete mode 100644 tests/e2e/pdf-settings/template/first-page-footer-field.test.js delete mode 100644 tests/e2e/pdf-settings/template/first-page-header-field.test.js delete mode 100644 tests/e2e/pdf-settings/template/footer-field.test.js delete mode 100644 tests/e2e/pdf-settings/template/header-field.test.js delete mode 100644 tests/e2e/pdf-settings/template/show-empty-fields-test.js delete mode 100644 tests/e2e/pdf-settings/template/show-form-title-field.test.js delete mode 100644 tests/e2e/pdf-settings/template/show-html-fields-field.test.js delete mode 100644 tests/e2e/pdf-settings/template/show-page-names-field.test.js delete mode 100644 tests/e2e/pdf-settings/template/show-section-break-description-field.test.js delete mode 100644 tests/e2e/tabs/general-settings/background-processing-field.test.js delete mode 100644 tests/e2e/tabs/general-settings/debug-mode-field.test.js delete mode 100644 tests/e2e/tabs/general-settings/default-font-color-field.test.js delete mode 100644 tests/e2e/tabs/general-settings/default-font-field.test.js delete mode 100644 tests/e2e/tabs/general-settings/default-font-size-field.test.js delete mode 100644 tests/e2e/tabs/general-settings/default-owner-restrictions-field.test.js delete mode 100644 tests/e2e/tabs/general-settings/default-paper-size-field.test.js delete mode 100644 tests/e2e/tabs/general-settings/default-template-field.test.js delete mode 100644 tests/e2e/tabs/general-settings/entry-view-field.test.js delete mode 100644 tests/e2e/tabs/general-settings/logged-out-timeout-field.test.js delete mode 100644 tests/e2e/tabs/general-settings/reverse-text-rtl-field.test.js delete mode 100644 tests/e2e/tabs/general-settings/user-restriction-field.test.js delete mode 100644 tests/e2e/tabs/license/license-field.test.js delete mode 100644 tests/e2e/tabs/license/sample-plugin-license.test.js delete mode 100644 tests/e2e/tabs/tools/fonts-field.test.js delete mode 100644 tests/e2e/tabs/tools/install-core-fonts-field.test.js delete mode 100644 tests/e2e/tabs/tools/uninstall-gravity-pdf-field.test.js delete mode 100644 tests/e2e/utilities/page-model/helpers/advanced-check.js delete mode 100644 tests/e2e/utilities/page-model/helpers/field.js delete mode 100644 tests/e2e/utilities/page-model/helpers/font-manager.js delete mode 100644 tests/e2e/utilities/page-model/helpers/media-manager.js delete mode 100644 tests/e2e/utilities/page-model/helpers/page.js delete mode 100644 tests/e2e/utilities/page-model/helpers/pdf.js delete mode 100644 tests/e2e/utilities/page-model/helpers/search-params.js delete mode 100644 tests/e2e/utilities/page-model/helpers/template-manager.js delete mode 100644 tests/e2e/utilities/page-model/tabs/general-settings.js delete mode 100644 tests/e2e/utilities/page-model/tabs/license.js delete mode 100644 tests/e2e/utilities/page-model/tabs/tools.js delete mode 100644 tests/e2e/utilities/resources/background-image.jpg create mode 100644 tests/playwright/core/entry-list-and-details/conditional-logic-pdf.spec.ts create mode 100644 tests/playwright/core/entry-list-and-details/inactive-pdf.spec.ts create mode 100644 tests/playwright/core/entry-list-and-details/multiple-pdfs.spec.ts create mode 100644 tests/playwright/core/entry-list-and-details/single-pdf.spec.ts create mode 100644 tests/playwright/core/pdf-access/inactive.spec.ts create mode 100644 tests/playwright/core/pdf-access/security.spec.ts create mode 100644 tests/playwright/core/pdf-settings/pdf-settings.spec.ts create mode 100644 tests/playwright/permalinks/download-mergetag/attributes.spec.ts create mode 100644 tests/playwright/permalinks/download-mergetag/text-confirmation.spec.ts create mode 100644 tests/playwright/permalinks/download-shortcode/copy-to-clipboard.spec.ts create mode 100644 tests/playwright/permalinks/download-shortcode/inactive-pdf.spec.ts create mode 100644 tests/playwright/permalinks/download-shortcode/page-confirmation.spec.ts create mode 100644 tests/playwright/permalinks/download-shortcode/redirect-confirmation.spec.ts create mode 100644 tests/playwright/permalinks/download-shortcode/text-confirmation.spec.ts create mode 100644 tests/playwright/permalinks/managers/font-manager.spec.ts create mode 100644 tests/playwright/permalinks/managers/template-manager.spec.ts create mode 100644 tools/mu-plugins/admin-styles.php create mode 100644 tools/mu-plugins/gravityforms.php create mode 100644 tools/mu-plugins/gravitypdf.php create mode 100644 tools/mu-plugins/mpdf.php create mode 100644 tools/playwright/config.ts rename {tests/e2e/utilities/resources => tools/playwright/data/fonts}/Roboto-Bold.ttf (100%) rename {tests/e2e/utilities/resources => tools/playwright/data/fonts}/Roboto-BoldItalic.ttf (100%) rename {tests/e2e/utilities/resources => tools/playwright/data/fonts}/Roboto-Regular.ttf (100%) rename {tests/e2e/utilities/resources => tools/playwright/data/fonts}/Roboto-RegularItalic.ttf (100%) create mode 100644 tools/playwright/data/forms/standard.json create mode 100644 tools/playwright/data/images/thumbnail.jpg rename {tests/e2e/utilities/resources => tools/playwright/data/template}/test-template.zip (100%) create mode 100644 tools/playwright/fixtures/test.ts create mode 100644 tools/playwright/flaky-tests-reporter.ts create mode 100644 tools/playwright/global-setup.ts create mode 100644 tools/playwright/utils/gravityforms.ts create mode 100644 tools/playwright/utils/gravitypdf.ts create mode 100644 tools/wp-env/e2e-permalinks.json create mode 100644 tools/wp-env/e2e.json create mode 100644 tsconfig.json diff --git a/.github/workflows/end-to-end-tests.yml b/.github/workflows/end-to-end-tests.yml deleted file mode 100644 index 2c75171d2..000000000 --- a/.github/workflows/end-to-end-tests.yml +++ /dev/null @@ -1,117 +0,0 @@ -name: End-to-end Tests - -on: - pull_request: - -# Cancels all previous workflow runs for pull requests that have not completed. -concurrency: - # The concurrency group contains the workflow name and the branch name for pull requests - # or the commit hash for any other events. - group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.sha }} - cancel-in-progress: true - -env: - GF_LICENSE: ${{ secrets.GF_LICENSE }} - -jobs: - # Runs the end-to-end test suite. - # - # Performs the following steps: - # - Cancels all previous workflow runs for pull requests that have not completed. - # - Set environment variables. - # - Checks out the repository. - # - Logs debug information about the runner container. - # - Installs NodeJS 1 - # - Sets up caching for NPM. - # _ Installs NPM dependencies using install-changed to hash the `package.json` file. - # - Builds WordPress to run from the `build` directory. - # - Starts the WordPress Docker container. - # - Logs general debug information. - # - Logs the running Docker containers. - # - Logs Docker debug information (about both the Docker installation within the runner and the WordPress container). - # - Install WordPress within the Docker container. - # - Run the E2E tests. - e2e-tests: - name: E2E Tests - runs-on: ubuntu-latest - steps: - - name: Configure environment variables - run: | - echo "PHP_FPM_UID=$(id -u)" >> $GITHUB_ENV - echo "PHP_FPM_GID=$(id -g)" >> $GITHUB_ENV - - - name: Checkout repository - uses: actions/checkout@v4 - - # Docs: https://github.com/shivammathur/setup-php - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: 7.4 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Setup Node JS - uses: actions/setup-node@v4 - with: - node-version-file: '.nvmrc' - - - name: Get yarn cache directory path - id: yarn-cache-dir-path - run: echo "dir=$(yarn config get cacheFolder)" >> $GITHUB_OUTPUT - - - name: Cache node modules - uses: actions/cache@v4 - id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`) - with: - path: ${{ steps.yarn-cache-dir-path.outputs.dir }} - key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} - restore-keys: | - ${{ runner.os }}-yarn- - - - name: Log debug information - run: | - npm --version - yarn --version - node --version - curl --version - git --version - php --version - php -i - locale -a - - - name: Install Composer dependencies - run: | - composer install --prefer-dist --no-suggest --no-progress --no-ansi --no-interaction --no-scripts - echo "${PWD}/vendor/bin" >> $GITHUB_PATH - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Install JS Dependencies - if: steps.yarn-cache.outputs.cache-hit != 'true' - run: yarn install - - - name: Build Gravity PDF - run: yarn build - - - name: Install / Setup Gravity PDF + WordPress - run: | - yarn wp-env start - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Run E2E tests - run: yarn test:e2e:headless - - - name: Dump log files on failure - if: failure() - run: | - npm run wp-env run tests-wordpress "cp -r /var/www/html/wp-content/uploads/gravity_forms/logs/ /var/www/html/wp-content/plugins/gravity-pdf/tmp/" - mv tmp screenshots/tmp - - - name: Upload artifacts on failure - uses: actions/upload-artifact@v4 - if: failure() - with: - name: my-artifact - path: screenshots/ diff --git a/.github/workflows/playwright-e2e.yml b/.github/workflows/playwright-e2e.yml new file mode 100644 index 000000000..c2c9215c3 --- /dev/null +++ b/.github/workflows/playwright-e2e.yml @@ -0,0 +1,156 @@ +name: Playwright End-to-End Tests + +on: + schedule: + - cron: "15 19 * * 0,3" # Runs early on Monday and Thursday Sydney time + + pull_request: + types: [ opened, reopened, synchronize, labeled ] + +# Cancels all previous workflow runs for pull requests that have not completed. +concurrency: + # The concurrency group contains the workflow name and the branch name for pull requests + # or the commit hash for any other events. + group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.sha }} + cancel-in-progress: true + +jobs: + # Only run this action if a Pull Request contains the label 'run-tests' + check_for_string_in_pull_request_comment: + name: Should workflow run? + runs-on: ubuntu-latest + steps: + - if: ${{ github.event_name == 'pull_request' && ! contains(github.event.pull_request.labels.*.name, 'run-tests') }} + uses: action-pack/cancel@v1 + + e2e-playwright: + name: Playwright E2E Tests + runs-on: ubuntu-latest + + steps: + - name: Configure environment variables + run: | + echo "PHP_FPM_UID=$(id -u)" >> $GITHUB_ENV + echo "PHP_FPM_GID=$(id -g)" >> $GITHUB_ENV + + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 0 + env: + CHROMATIC_BRANCH: ${{ github.event.pull_request.head.ref || github.ref_name }} + CHROMATIC_SHA: ${{ github.event.pull_request.head.sha || github.ref }} + CHROMATIC_SLUG: ${{ github.repository }} + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: 7.4 + + - name: Setup Node JS + uses: actions/setup-node@v6 + with: + node-version-file: '.nvmrc' + + - name: Log debug information + run: | + npm --version + yarn --version + node --version + curl --version + git --version + php --version + php -i + locale -a + + - name: Install Composer dependencies + run: | + composer install --no-progress --no-ansi --no-interaction + echo "${PWD}/vendor/bin" >> $GITHUB_PATH + + - name: Install JS Dependencies + run: yarn install --frozen-lockfile + + - name: Build Gravity PDF + run: yarn build + + - name: Install playwright browsers + run: npx playwright install + + - name: Install / Setup Gravity PDF + WordPress + run: | + yarn wp-env:e2e start --debug + yarn wp-env:e2e:permalinks start --debug + + - name: Run the tests + run: yarn test:e2e + env: + PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: true + + - uses: actions/upload-artifact@v6 + if: success() + with: + name: test-results + path: ./tmp/artifacts/test-results/chromatic-archives + + - name: Dump log files on failure + if: failure() + run: | + yarn wp-env:e2e run wordpress "cp -r /var/www/html/wp-content/uploads/gravity_forms/logs/ /var/www/html/wp-content/plugins/gravity-pdf/tmp/artifacts/logs" + + - name: Upload artifacts on failure + uses: actions/upload-artifact@v6 + if: failure() + with: + path: tmp/artifacts + + - name: Send Success Email for weekly runner + uses: dawidd6/action-send-mail@v16 + if: ${{ success() && github.event_name != 'pull_request' }} + with: + connection_url: ${{secrets.MAIL_CONNECTION}} + subject: Gravity PDF E2E Tests Completed + to: ${{secrets.MAIL_TO}} + from: ${{secrets.MAIL_FROM}} + body: View results at https://github.com/GravityPDF/gravity-pdf/actions/runs/${{github.run_id}} + + - name: Send Failure Email for weekly runner + uses: dawidd6/action-send-mail@v16 + if: ${{ failure() && github.event_name != 'pull_request' }} + with: + connection_url: ${{secrets.MAIL_CONNECTION}} + subject: Gravity PDF E2E Tests Failed + to: ${{secrets.MAIL_TO}} + from: ${{secrets.MAIL_FROM}} + body: View results at https://github.com/GravityPDF/gravity-pdf/actions/runs/${{github.run_id}} + + chromatic: + name: Run Chromatic + needs: e2e-playwright + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - uses: actions/setup-node@v6 + with: + node-version-file: '.nvmrc' + + - name: Install JS Dependencies + run: yarn install --frozen-lockfile + + - name: Download Playwright test results + uses: actions/download-artifact@v6 + with: + name: test-results + path: ./test-results + + - name: Run Chromatic + uses: chromaui/action@latest + with: + playwright: true + autoAcceptChanges: "development" + projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }} + env: + CHROMATIC_ARCHIVE_LOCATION: ./test-results diff --git a/.testcaferc.js b/.testcaferc.js deleted file mode 100644 index 9a2384c1b..000000000 --- a/.testcaferc.js +++ /dev/null @@ -1,19 +0,0 @@ -const { admin } = require('./tests/e2e/auth') - -module.exports = { - src: 'tests/e2e', - disableNativeAutomation: true, - disableMultipleWindows: true, - skipJsErrors: true, - screenshots: { - takeOnFails: true, - fullPage: true - }, - hooks: { - test: { - before: async t => { - await t.useRole(admin) - } - } - } -} diff --git a/bin/htaccess-sample b/bin/htaccess-sample deleted file mode 100644 index fd77845f4..000000000 --- a/bin/htaccess-sample +++ /dev/null @@ -1,15 +0,0 @@ -# BEGIN WordPress -# The directives (lines) between "BEGIN WordPress" and "END WordPress" are -# dynamically generated, and should only be modified via WordPress filters. -# Any changes to the directives between these markers will be overwritten. - -RewriteEngine On -RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] -RewriteBase / -RewriteRule ^index\.php$ - [L] -RewriteCond %{REQUEST_FILENAME} !-f -RewriteCond %{REQUEST_FILENAME} !-d -RewriteRule . /index.php [L] - - -# END WordPress \ No newline at end of file diff --git a/bin/install-database.sh b/bin/install-database.sh deleted file mode 100755 index 40edc59fe..000000000 --- a/bin/install-database.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash - -npm run wp-env run tests-cli wp option add freshinstall yes -npm run wp-env run tests-cli wp user create editor editor@test.com -- --role=editor --user_pass=password --quiet \ No newline at end of file diff --git a/bin/install-gravityforms.sh b/bin/install-gravityforms.sh deleted file mode 100755 index c6081dc14..000000000 --- a/bin/install-gravityforms.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env bash - -# Add new variables / override existing if .env file exists -if [ -f ".env" ]; then - set -a - source .env - set +a -fi - -# Install in both development + test environments -# --version=beta is not currently supported by add-ons. -npm run wp-env run cli wp gf install -- -- --key=$GF_LICENSE --activate --force --version=latest -npm run wp-env run tests-cli wp gf install -- -- --key=$GF_LICENSE --activate --force --version=latest \ No newline at end of file diff --git a/bin/install-post-actions.sh b/bin/install-post-actions.sh deleted file mode 100644 index 912908a19..000000000 --- a/bin/install-post-actions.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash - -# Install add-ons in the test environment -npm run wp-env run tests-cli wp gf install gravityformspolls -- --key=$GF_LICENSE --activate --force -npm run wp-env run tests-cli wp gf install gravityformsquiz -- --key=$GF_LICENSE --activate --force -npm run wp-env run tests-cli wp gf install gravityformssurvey -- --key=$GF_LICENSE --activate --force diff --git a/bin/install.sh b/bin/install.sh deleted file mode 100755 index 421b8fdab..000000000 --- a/bin/install.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env bash - -GF_LICENSE="${GF_LICENSE:=$1}" - -# Add new variables / override existing if .env file exists -if [[ -f ".env" ]]; then - set -a - source .env - set +a -fi - -# Install Gravity PDF Dependencies -composer install -# this is triggers as post install script -# composer run prefix - -# disable for now as it loops the installation -# Start local environment -#if [[ $PHP_ENABLE_XDEBUG ]]; then -# npm run wp-env start -- --upgrade --xdebug=debug,coverage -#else -# npm run wp-env start -- --upgrade -#fi - -echo "Install Gravity Forms..." -bash ./bin/install-gravityforms.sh - -npm run wp-env run cli wp plugin activate gravityforms gravityformscli gravity-pdf -npm run wp-env run tests-cli wp plugin activate gravityforms gravityformscli gravityformspolls gravityformssurvey gravityformsquiz gravity-pdf gravity-pdf-test-suite - -# Place CLI config file -npm run wp-env run tests-wordpress cp /var/www/html/wp-content/plugins/gravity-pdf/bin/htaccess-sample /var/www/html/.htaccess - -echo "Run Database changes" -bash ./bin/install-database.sh - -if [[ -f "./bin/install-post-actions.sh" ]]; then - echo "Running Post Install Actions..." - bash ./bin/install-post-actions.sh -fi \ No newline at end of file diff --git a/package.json b/package.json index f45e585c7..5080f5b94 100644 --- a/package.json +++ b/package.json @@ -2,18 +2,15 @@ "name": "gravity-pdf", "private": true, "dependencies": { - "@babel/runtime": "^7.26.10", - "algoliasearch": "^5.10.2", + "algoliasearch": "^5.35.0", "classnames": "^2.3.1", - "core-js": "^3.23.4", "history": "^5.3.0", "lodash.debounce": "^4.0.8", "object-to-formdata": "^4.4.2", - "prop-types": "^15.8.1", "react": "^18.3.1", "react-dom": "^18.3.1", "react-dropzone": "^14.2.2", - "react-instantsearch": "^7.13.6", + "react-instantsearch": "^7.16.2", "react-redux": "^9.1.2", "react-router": "^6.27.0", "react-router-dom": "^6.27.0", @@ -24,75 +21,67 @@ "sprintf-js": "^1.1.2" }, "devDependencies": { - "@babel/core": "^7.18.6", + "@babel/core": "^7.27", + "@babel/plugin-transform-modules-commonjs": "^7.27", "@cfaester/enzyme-adapter-react-18": "^0.8.0", - "@playwright/test": "^1.49.0", + "@chromatic-com/playwright": "^0.13.1", + "@playwright/test": "^1.55.0", "@redux-devtools/extension": "^3.3.0", - "@wordpress/babel-preset-default": "^8.11.0", - "@wordpress/env": "^10.10.0", - "@wordpress/eslint-plugin": "^21.4.0", - "@wordpress/scripts": "^30.4.0", + "@wordpress/e2e-test-utils": "^11.29.0", + "@wordpress/e2e-test-utils-playwright": "^1.29.0", + "@wordpress/env": "^11.0.0", + "@wordpress/eslint-plugin": "^22.11.0", + "@wordpress/scripts": "^31.8.0", "babel-jest": "^29.7.0", - "babel-loader": "^9.1.3", "babel-plugin-inline-json-import": "^0.3.2", - "babel-plugin-istanbul": "^7.0.0", "babel-plugin-react-remove-properties": "^0.3.0", "babel-plugin-transform-react-remove-prop-types": "^0.4.24", - "cross-env": "^7.0.3", - "css-loader": "7.1.2", - "css-minimizer-webpack-plugin": "7.0.0", + "chromatic": "^16.3.0", "css.escape": "^1.5.1", - "dotenv": "^16.0.1", "enzyme": "^3.11.0", - "eslint": "^8.52.0", - "file-loader": "^6.2.0", + "eslint": "^8.0", + "eslint-import-resolver-typescript": "^4.4.4", + "eslint-plugin-import-x": "^4.16.1", + "filenamify": "^6.0.0", "jest": "^29.7.0", "jest-environment-jsdom": "^29.7.0", "jest-enzyme": "^7.1.2", "jquery": "^3.6.0", - "json-loader": "^0.5.7", - "mini-css-extract-plugin": "^2.6.1", - "minimatch": "^5.1.8", - "path-to-regexp": "^1.9.0", - "prettier": "^3.3.3", - "react-refresh": "^0.14.2", + "potomatic": "^1.0.1", + "prettier": "^3.6.2", + "prop-types": "^15.8.1", + "puppeteer-core": "^24.17.0", "redux-mock-store": "^1.5.4", - "sass": "^1.53.0", - "sass-loader": "^16.0.2", - "standard": "^17.0.0", - "terser-webpack-plugin": "^5.3.3", - "testcafe": "^3.7.0", - "typescript": "^5.6.3", - "underscore": "^1.3.8", - "url-loader": "^4.1.1", - "webpack": "^5.73.0", - "webpack-cli": "^5.1.0", - "webpack-merge": "^6.0.1", - "zod": "^3.24.1" + "typescript": "5.3.3" }, "scripts": { - "start": "yarn run wp-env start && yarn run dev:hot", - "dev": "WP_DEVTOOL=inline-source-map wp-scripts start --webpack-src-dir=./src/assets/js", - "dev:hot": "yarn run dev --hot", - "dev:build": "yarn run dev --no-watch", + "start": "yarn wp-env start && yarn dev:hot", + "dev": "WP_DEVTOOL=inline-source-map wp-scripts start --webpack-src-dir=./src/assets/js --webpack-no-externals", + "dev:build": "yarn dev -- --no-watch", "build": "wp-scripts build --webpack-src-dir=./src/assets/js --webpack-no-externals", - "wp-env": "wp-env", - "format": "wp-scripts format ./src/assets ./tests/js-unit && yarn run lint:js --fix && yarn run lint:css --fix", + "check-licenses": "wp-scripts check-licenses --prod --gpl2", + "format": "wp-scripts format ./src/assets ./tests/js-unit ./tests/playwright && yarn lint:js --fix && yarn lint:css --fix", "lint:css": "wp-scripts lint-style ./src/assets/**/*.scss ./src/assets/**/*.pcss", - "lint:js": "wp-scripts lint-js ./src/assets/js ./tests/js-unit", - "test:e2e": "cross-env NODE_ENV=test testcafe chrome", - "test:e2e:headless": "cross-env NODE_ENV=test testcafe chrome:headless", - "test:e2e:watch": "cross-env NODE_ENV=test testcafe chrome -L", - "test:php": "npm run wp-env run tests-wordpress env PHP_IDE_CONFIG=serverName=localhost /var/www/html/wp-content/plugins/gravity-pdf/vendor/bin/phpunit -- -c /var/www/html/wp-content/plugins/gravity-pdf/phpunit.xml.dist", - "test:php:multisite": "npm run wp-env run tests-wordpress env PHP_IDE_CONFIG=serverName=localhost /var/www/html/wp-content/plugins/gravity-pdf/vendor/bin/phpunit -- -c /var/www/html/wp-content/plugins/gravity-pdf/tests/phpunit/multisite.xml", + "lint:js": "wp-scripts lint-js ./src/assets/js ./tests/js-unit ./tests/playwright", + "wp-env": "WP_ENV_PORT=8700 wp-env --config=./tools/wp-env/development.json", + "wp-env:integration": "WP_ENV_PORT=8701 wp-env --config=./tools/wp-env/integration.json", + "wp-env:e2e": "WP_ENV_PORT=8702 wp-env --config=./tools/wp-env/e2e.json", + "wp-env:e2e:permalinks": "WP_ENV_PORT=8703 wp-env --config=./tools/wp-env/e2e-permalinks.json", + "test:php": "yarn wp-env:integration run wordpress env PHP_IDE_CONFIG=serverName=localhost /var/www/html/wp-content/plugins/gravity-pdf/vendor/bin/phpunit -- -c /var/www/html/wp-content/plugins/gravity-pdf/tools/phpunit/config.xml", + "test:php:multisite": "yarn wp-env:integration run wordpress env PHP_IDE_CONFIG=serverName=localhost /var/www/html/wp-content/plugins/gravity-pdf/vendor/bin/phpunit -- -c /var/www/html/wp-content/plugins/gravity-pdf/tools/phpunit/config-multisite.xml", + "test:e2e": "wp-scripts test-playwright --config tools/playwright/config.ts", + "test:e2e:debug": "wp-scripts test-playwright --config tools/playwright/config.ts --ui", "test:js": "jest --verbose", "test:js:coverage": "jest --coverage --verbose", "test:js:watch": "jest --watchAll", - "prebuild:core-fonts": "bash bin/json-payload.sh https://api.github.com/repos/GravityPDF/mpdf-core-fonts/contents/ core-fonts.json" - }, - "wp-env": { - "plugin-dir": "gravity-pdf", - "plugin-name": "Gravity PDF" + "prebuild:core-fonts": "bash tools/release/json-payload.sh https://api.github.com/repos/GravityPDF/mpdf-core-fonts/contents/ core-fonts.json", + "i10n": "yarn build && yarn i10n:make-pot && yarn i10n:update-po && yarn i10n:make-mo && yarn i10n:make-json && yarn i10n:make-php", + "i10n:make-pot": "wp i18n make-pot ./ languages/gravity-pdf.pot --include=pdf.php,api.php,gravity-pdf-updater.php,src,build --exclude=tmp,vendor,vendor_prefixed --domain=gravity-pdf --headers='{\"Report-Msgid-Bugs-To\":\"https://gravitypdf.com\"}'", + "i10n:make-json": "wp i18n make-json languages --no-purge", + "i10n:make-php": "wp i18n make-php languages", + "i10n:update-po": "wp i18n update-po languages/gravity-pdf.pot languages", + "i10n:make-mo": "wp i18n make-mo languages", + "i10n:translate": "potomatic --output-dir=./languages --po-file-prefix=gravity-pdf- --pot-file-path=./languages/gravity-pdf.pot --use-dictionary --dictionary-path=./tools/potomatic/dictionaries --target-languages=es_ES,fr_FR,de_DE,de_DE-formal,it_IT,nl_NL,ru_RU,zh_CN" }, "resolutions": { "cheerio": "1.0.0-rc.10" diff --git a/tests/e2e/advanced-checks/confirmation-shortcode.test.js b/tests/e2e/advanced-checks/confirmation-shortcode.test.js deleted file mode 100644 index 92bc09511..000000000 --- a/tests/e2e/advanced-checks/confirmation-shortcode.test.js +++ /dev/null @@ -1,203 +0,0 @@ -import { Selector, RequestLogger } from 'testcafe'; -import { baseURL } from '../auth'; -import { link } from '../utilities/page-model/helpers/field'; -import AdvancedCheck from '../utilities/page-model/helpers/advanced-check'; -// new Page model. Might be used soon as default -import Page from '../models/Page'; - -let shortcodeHolder; -let downloadUrl; -const run = new AdvancedCheck(); -const downloadLogger = RequestLogger( downloadUrl, { - logResponseBody: true, - logResponseHeaders: true, -} ); - -fixture`PDF shortcode - Confirmation Type TEXT, PAGE and REDIRECT text`; - -test( 'should check shortcode confirmation type TEXT is working correctly', async ( t ) => { - // Actions - await run.copyDownloadShortcode( - 'gf_edit_forms&view=settings&subview=PDF&id=3' - ); - shortcodeHolder = await run.shortcodeBox.getAttribute( - 'data-clipboard-text' - ); - await run.navigateConfirmationSection( - 'gf_edit_forms&view=settings&subview=confirmation&id=3' - ); - await t - .click( run.confirmationTextCheckbox ) - .click( run.wysiwgEditorTextTab ) - .click( run.wysiwgEditor ) - .pressKey( 'ctrl+a' ) - .pressKey( 'backspace' ) - .typeText( run.wysiwgEditor, shortcodeHolder, { paste: true } ) - .click( run.saveConfirmationButton ); - - const url = await run.previewLink.href; - await t - .navigateTo( url ) - .typeText( run.formInputField, 'test', { paste: true } ) - .click( run.submitButton ); - downloadUrl = await Selector( '.gravitypdf-download-link' ).getAttribute( - 'href' - ); - - downloadLogger.clear(); - await t - .addRequestHooks( downloadLogger ) - .click( link( '.gform_confirmation_wrapper ', 'Download PDF' ) ) - .wait( 500 ) - .removeRequestHooks( downloadLogger ); - - // Assertions - await t - .expect( - downloadLogger.contains( - ( r ) => - r.response.headers[ 'content-disposition' ] === - 'attachment; filename="Sample.pdf"' - ) - ) - .ok() - .expect( - downloadLogger.contains( - ( r ) => - r.response.headers[ 'content-type' ] === 'application/pdf' - ) - ) - .ok(); -} ); - -test( 'should check if the shortcode confirmation type PAGE is working correctly', async ( t ) => { - // Actions - // copy pdf short code - await run.copyDownloadShortcode( - 'gf_edit_forms&view=settings&subview=PDF&id=3' - ); - shortcodeHolder = await run.shortcodeBox.getAttribute( - 'data-clipboard-text' - ); - await t - .setNativeDialogHandler( () => true ) - .navigateTo( `${ baseURL }/wp-admin/edit.php?post_type=page` ); - - // Create a new page and insert a shortcode block - const name = 'Shortcode confrimation type Page'; - const page = new Page( name ); - await page.add(); - await page.insertBlock( 'shortcode', { - target: '.block-editor-plain-text', - content: shortcodeHolder, - } ); - await page.saveChanges(); - await page.publishChanges(); - - // update form settings - await run.navigateConfirmationSection( - 'gf_edit_forms&view=settings&subview=confirmation&id=3' - ); - - // get first child button - const pageItem = Selector( - 'div[aria-labelledby="gform-page-label"].gform-dropdown__container' - ).find( 'button' ); - - await t - .click( run.confirmationPageCheckbox ) - .click( run.confirmationPageSelectBox ) - .click( pageItem ) - .click( run.queryStringInputBox ) - .pressKey( 'ctrl+a' ) - .pressKey( 'backspace' ) - .typeText( run.queryStringInputBox, 'entry={entry_id}', { - paste: true, - } ) - .click( run.saveConfirmationButton ); - - const url = await run.previewLink.href; - await t - .navigateTo( url ) - .typeText( run.formInputField, 'test', { paste: true } ) - .click( run.submitButton ); - downloadUrl = await Selector( '.gravitypdf-download-link' ).getAttribute( - 'href' - ); - - downloadLogger.clear(); - await t - .addRequestHooks( downloadLogger ) - .click( link( '.entry-content', 'Download PDF' ) ) - .wait( 500 ) - .removeRequestHooks( downloadLogger ); - - // Assertions - await t - .expect( - downloadLogger.contains( - ( r ) => - r.response.headers[ 'content-disposition' ] === - 'attachment; filename="Sample.pdf"' - ) - ) - .ok() - .expect( - downloadLogger.contains( - ( r ) => - r.response.headers[ 'content-type' ] === 'application/pdf' - ) - ) - .ok(); - - // Cleanup - await page.delete(); -} ); - -test( 'should check if the shortcode confirmation type REDIRECT download is working correctly', async ( t ) => { - // Actions - await run.copyDownloadShortcode( - 'gf_edit_forms&view=settings&subview=PDF&id=3' - ); - shortcodeHolder = await run.shortcodeBox.getAttribute( - 'data-clipboard-text' - ); - await run.navigateConfirmationSection( - 'gf_edit_forms&view=settings&subview=confirmation&id=3' - ); - await t - .click( run.confirmationRedirectCheckbox ) - .click( run.redirectInputBox ) - .pressKey( 'ctrl+a' ) - .pressKey( 'backspace' ) - .typeText( run.redirectInputBox, shortcodeHolder, { paste: true } ) - .click( run.saveConfirmationButton ); - - const url = await run.previewLink.href; - await t.navigateTo( url ); - - downloadLogger.clear(); - downloadUrl = `${ baseURL }/?gf_page=preview&id=3`; - await t - .addRequestHooks( downloadLogger ) - .typeText( run.formInputField, 'test', { paste: true } ) - .click( run.submitButton ); - - // Assertions - await t - .expect( - downloadLogger.contains( - ( r ) => - r.response.headers[ 'content-disposition' ] === - 'attachment; filename="Sample.pdf"' - ) - ) - .ok() - .expect( - downloadLogger.contains( - ( r ) => - r.response.headers[ 'content-type' ] === 'application/pdf' - ) - ) - .ok(); -} ); diff --git a/tests/e2e/advanced-checks/debug-mode-shortcode.test.js b/tests/e2e/advanced-checks/debug-mode-shortcode.test.js deleted file mode 100644 index e9069d908..000000000 --- a/tests/e2e/advanced-checks/debug-mode-shortcode.test.js +++ /dev/null @@ -1,48 +0,0 @@ -import AdvancedCheck from '../utilities/page-model/helpers/advanced-check' -import General from '../utilities/page-model/tabs/general-settings' - -let shortcodeHolder -const advancedCheck = new AdvancedCheck() -const general = new General() - -fixture`Debug mode - PDF shortcode test` - -test('should enable debug mode and throw error when PDF is inactive', async t => { - // Actions & Assertions - await advancedCheck.navigateSection('gf_settings&subview=PDF&tab=general#') - await t - .click(advancedCheck.debugModeCheckbox) - .click(general.saveSettings) - .wait(500) - await advancedCheck.copyDownloadShortcode('gf_edit_forms&view=settings&subview=PDF&id=3') - shortcodeHolder = await advancedCheck.shortcodeBox.getAttribute('data-clipboard-text') - await t.click(advancedCheck.toggleSwitch) - await advancedCheck.navigateConfirmationSection('gf_edit_forms&view=settings&subview=confirmation&id=3') - await t - .click(advancedCheck.confirmationTextCheckbox) - .click(advancedCheck.wysiwgEditorTextTab) - .click(advancedCheck.wysiwgEditor) - .pressKey('ctrl+a') - .pressKey('backspace') - .typeText(advancedCheck.wysiwgEditor, shortcodeHolder, { paste: true }) - .click(advancedCheck.saveConfirmationButton) - - const url = await advancedCheck.previewLink.href - await t.navigateTo(url) - .typeText(advancedCheck.formInputField, 'test', { paste: true }) - .click(advancedCheck.submitButton) - .expect(advancedCheck.debugModeErrorMessage.exists).ok() -}) - -test('should reset/clean PDF back to active and debug mode back to disabled for the next test', async t => { - // Actions & Assertions - await advancedCheck.navigateSection('gf_edit_forms&view=settings&subview=PDF&id=3') - await t - .click(advancedCheck.toggleSwitch) - .expect(advancedCheck.toggleSwitch.getAttribute('data-status')).eql('active') - await advancedCheck.navigateLink('gf_settings&subview=PDF&tab=general#') - await t - .click(advancedCheck.debugModeCheckbox) - .click(general.saveSettings) - .expect(advancedCheck.debugModeCheckbox.checked).notOk() -}) diff --git a/tests/e2e/advanced-checks/merge-tags.test.js b/tests/e2e/advanced-checks/merge-tags.test.js deleted file mode 100644 index e20b44fa2..000000000 --- a/tests/e2e/advanced-checks/merge-tags.test.js +++ /dev/null @@ -1,38 +0,0 @@ -import { infoText } from '../utilities/page-model/helpers/field' -import AdvancedCheck from '../utilities/page-model/helpers/advanced-check' - -const advancedCheck = new AdvancedCheck() - -fixture`Form merge tags test` - -test('should check if form merge tags is working properly', async t => { - // Actions - await advancedCheck.navigateConfirmationSection('gf_edit_forms&view=settings&subview=confirmation&id=3') - await t - .click(advancedCheck.confirmationTextCheckbox) - .click(advancedCheck.wysiwgEditorTextTab) - .click(advancedCheck.wysiwgEditor) - .pressKey('ctrl+a') - .pressKey('backspace') - await advancedCheck.pickMergeTag('Text') - await advancedCheck.pickMergeTag('Name (First)') - await advancedCheck.pickMergeTag('Name (Last)') - await advancedCheck.pickMergeTag('Email') - await t - .click(advancedCheck.saveConfirmationButton) - - const url = await advancedCheck.previewLink.href - await t.navigateTo(url) - .typeText(advancedCheck.textInputField, 'texttest', { paste: true }) - .typeText(advancedCheck.fNameInputField, 'firstnametest', { paste: true }) - .typeText(advancedCheck.lNameInputField, 'lastnametest', { paste: true }) - .typeText(advancedCheck.emailInputField, 'email@test.com', { paste: true }) - .click(advancedCheck.submitButton) - - // Assertions - await t - .expect(infoText('texttest', 'div').exists).ok() - .expect(infoText('firstnametest', 'div').exists).ok() - .expect(infoText('lastnametest', 'div').exists).ok() - .expect(infoText('email@test.com', 'div').exists).ok() -}) diff --git a/tests/e2e/advanced-checks/pdf-restriction.test.js b/tests/e2e/advanced-checks/pdf-restriction.test.js deleted file mode 100644 index c78175290..000000000 --- a/tests/e2e/advanced-checks/pdf-restriction.test.js +++ /dev/null @@ -1,101 +0,0 @@ -import { RequestLogger, Role, Selector, t } from 'testcafe'; -import { admin, baseURL, editor } from '../auth'; -import AdvancedCheck from '../utilities/page-model/helpers/advanced-check'; -import Page from '../utilities/page-model/helpers/page'; -import PageModel from '../models/Page'; -import Pdf from '../utilities/page-model/helpers/pdf'; -import { getQueryParam } from '../utilities/page-model/helpers/search-params'; - -let pdfId; -let downloadUrl; -const advancedCheck = new AdvancedCheck(); -const page = new Page(); -const pdf = new Pdf(); -const downloadLogger = RequestLogger(downloadUrl, { - logResponseBody: true, - logResponseHeaders: true, -}); - -fixture`PDF Administrator & Non-Administrator - Restriction Test`; - -test('should throw an error when a non-administrator user try to access a PDF generated by an admin', async (t) => { - // Actions & Assertions - await advancedCheck.navigateSection( - 'gf_edit_forms&view=settings&subview=PDF&id=4' - ); - pdfId = await advancedCheck.shortcodeBox.getAttribute( - 'data-clipboard-text' - ); - pdfId = pdfId.substring(30, 43); - await t - .useRole(editor) - .navigateTo(`${baseURL}?gpdf=1&pid=${pdfId}&lid=4`) - .expect(advancedCheck.pdfRestrictionErrorMessage.exists) - .ok(); -}); - -test("should redirect to WP login page if 'Restrict Owner' is enabled", async (t) => { - // Actions - // Toggle restrict owner checkbox - await pdf.navigatePdf('4'); - // Navigate to pdf info - await t.click(Selector('td.name').find('a').withText('Sample')); - // check if it's publicly accessed then turn off - if (!pdf.restrictOwnerCheckbox.visible) { - await t.click(pdf.enablePublicAccessCheckbox); - } - await t.click(pdf.restrictOwnerCheckbox).click(pdf.saveSettings); - - // Create a new page - await t - .setNativeDialogHandler(() => true) - .navigateTo(`${baseURL}/wp-admin/edit.php?post_type=page`); - const name = 'Restrict Owner Enabled'; - const pageModel = new PageModel(name); - await pageModel.add(); - await pageModel.insertBlock('shortcode', { - target: '.block-editor-plain-text', - content: - '[gravityform id="4" title="false" description="false" ajax="true" tabindex="49"]', - }); - await pageModel.saveChanges(); - await pageModel.publishChanges(); - - // Visit the page as anon user - pdfId = await getQueryParam('post'); - // - await t - .useRole(Role.anonymous()) - .navigateTo(`${baseURL}/?page_id=${pdfId}`) - .typeText(advancedCheck.textInputField, 'texttest', { paste: true }) - .click(advancedCheck.submitButton) - .useRole(admin); - - await pdf.navigate('gf_entries&id=4'); - downloadUrl = await advancedCheck.viewEntryLink.getAttribute('href'); - - downloadLogger.clear(); - - await t - .addRequestHooks(downloadLogger) - .useRole(Role.anonymous()) - .navigateTo(downloadUrl) - .removeRequestHooks(downloadLogger); - - // Assertions - await t - .expect( - downloadLogger.contains( - (r) => r.response.headers['content-type'] === 'application/pdf' - ) - ) - .notOk() - .expect(advancedCheck.pdfRestrictionErrorMessage.exists) - .notOk() - .expect(advancedCheck.wpLoginForm.exists) - .ok(); - - // Cleanup - await t.navigateTo(baseURL); - await pageModel.delete(); -}); diff --git a/tests/e2e/advanced-checks/pdf-tempalte.test.js b/tests/e2e/advanced-checks/pdf-tempalte.test.js deleted file mode 100644 index 75900358e..000000000 --- a/tests/e2e/advanced-checks/pdf-tempalte.test.js +++ /dev/null @@ -1,101 +0,0 @@ -import AdvancedCheck from '../utilities/page-model/helpers/advanced-check' -import { baseURL } from '../auth' - -const advanceCheck = new AdvancedCheck() - -fixture`PDF template test` - -test('should successfully add new PDF template into form template list', async t => { - // Actions & Assertions - await advanceCheck.navigateAddPdf('gf_edit_forms&view=settings&subview=PDF&id=1') - await t.expect(advanceCheck.templateItem.count).eql(1) -}) - -test('should successfully saved toggled switch value for active and inactive template', async t => { - // Actions & Assertions - await advanceCheck.navigateSection('gf_edit_forms&view=settings&subview=PDF&id=1') - await t - .click(advanceCheck.toggleSwitch) - .expect(advanceCheck.toggleSwitch.getAttribute('data-status')).eql('inactive') - .click(advanceCheck.toggleSwitch) - .expect(advanceCheck.toggleSwitch.getAttribute('data-status')).eql('active') -}) - -test('should check that the option \'View PDF\' link is disabled when template is inactive', async t => { - // Actions & Assertions - await advanceCheck.navigateSection('gf_edit_forms&view=settings&subview=PDF&id=1') - await t - .click(advanceCheck.toggleSwitch) - .expect(advanceCheck.toggleSwitch.getAttribute('data-status')).eql('inactive') - await t.navigateTo(`${baseURL}/wp-admin/admin.php?page=gf_entries&id=1`) - await t - .hover(advanceCheck.entryItemSection) - .expect(advanceCheck.viewPdfLink.exists).notOk() -}) - -test('should successfully switch from inactive template to active', async t => { - await advanceCheck.navigateSection('gf_edit_forms&view=settings&subview=PDF&id=1') - await t - .click(advanceCheck.toggleSwitch) - .expect(advanceCheck.toggleSwitch.getAttribute('data-status')).eql('active') -}) - -test('should check that the option \'View PDF\' link is enabled when template is active', async t => { - // Actions & Assertions - await advanceCheck.navigateSection('gf_entries&id=1') - await t - .hover(advanceCheck.entryItemSection) - .expect(advanceCheck.viewPdfLink.exists).ok() -}) - -test('should check that the option \'View PDF\' link is disabled, when the PDF is active but the PDF conditional logic is checked', async t => { - // Actions & Assertions - await advanceCheck.navigateSection('gf_edit_forms&view=settings&subview=PDF&id=1') - await t - .hover(advanceCheck.templateItem) - .click(advanceCheck.editLink) - .click(advanceCheck.conditionalLogicCheckbox) - .click(advanceCheck.addUpdatePdfButton) - await advanceCheck.navigateLink('gf_entries&id=1') - await t - .hover(advanceCheck.entryItemSection) - .expect(advanceCheck.viewPdfLink.exists).notOk() -}) - -test('should successfully edit/update existing template using the edit template link option', async t => { - // Actions & Assertions - await advanceCheck.navigateSection('gf_edit_forms&view=settings&subview=PDF&id=1') - await t - .hover(advanceCheck.templateItem) - .click(advanceCheck.editLink) - .click(advanceCheck.pdfLabelNameInputBox) - .pressKey('ctrl+a') - .pressKey('backspace') - .typeText(advanceCheck.pdfLabelNameInputBox, 'Test PDF Template', { paste: true }) - .click(advanceCheck.pdfFilenameInputBox) - .pressKey('ctrl+a') - .pressKey('backspace') - .typeText(advanceCheck.pdfFilenameInputBox, 'testpdftemplate', { paste: true }) - .click(advanceCheck.addUpdatePdfButton) - .wait(500) - .click(advanceCheck.pdfListSection) - .expect(advanceCheck.templateDetail.innerText).contains('Test PDF Template') -}) - -test('should successfully duplicate existing PDF template using the duplicate link option', async t => { - // Actions & Assertions - await advanceCheck.navigateSection('gf_edit_forms&view=settings&subview=PDF&id=1') - await t - .hover(advanceCheck.templateItem) - .click(advanceCheck.duplicateLink) - await advanceCheck.navigateLink('gf_edit_forms&view=settings&subview=PDF&id=1') - await t.expect(advanceCheck.templateItem.count).eql(2) -}) - -test('reset/clean PDF templates from the list for the next test', async t => { - // Actions - await advanceCheck.navigateDeletePdfEntries('gf_edit_forms&view=settings&subview=PDF&id=1') - - // Assertions - await t.expect(advanceCheck.templateItem.innerText).contains('This form doesn\'t have any PDFs.') -}) diff --git a/tests/e2e/auth.js b/tests/e2e/auth.js deleted file mode 100644 index c3850496d..000000000 --- a/tests/e2e/auth.js +++ /dev/null @@ -1,28 +0,0 @@ -const { Role } = require('testcafe') -const path = require('path') - -require('dotenv').config({ path: path.resolve(process.cwd(), '.env') }) - -const url = process.env.WP_BASE_URL || 'http://localhost' -const port = process.env.WP_ENV_TESTS_PORT || '8889' -const baseURL = url + ':' + port - -const admin = Role(`${baseURL}/wp-login.php`, async t => { - await t - .typeText('#user_login', 'admin', { paste: true }) - .typeText('#user_pass', 'password', { paste: true }) - .click('#wp-submit') -}) - -const editor = Role(`${baseURL}/wp-login.php`, async t => { - await t - .typeText('#user_login', 'editor', { paste: true }) - .typeText('#user_pass', 'password', { paste: true }) - .click('#wp-submit') -}) - -module.exports = { - baseURL: baseURL, - admin: admin, - editor: editor -} diff --git a/tests/e2e/models/Page.js b/tests/e2e/models/Page.js deleted file mode 100644 index 779f1cf26..000000000 --- a/tests/e2e/models/Page.js +++ /dev/null @@ -1,138 +0,0 @@ -import { Selector, t } from 'testcafe'; -import { link } from '../utilities/page-model/helpers/field'; -import { admin, baseURL } from '../auth'; -import { getQueryParam } from '../utilities/page-model/helpers/search-params'; - -class Page { - constructor( name ) { - this.pageId = ''; - this.pageName = name; - this.addNewPageLink = link( '.wrap', 'Add New Page' ); - this.trashLink = Selector( 'a' ).withAttribute( - 'aria-label', - `Move “${ name }” to the Trash` - ); - this.closePopupButton = Selector( 'button' ).withAttribute( - 'aria-label', - 'Close dialog' - ); - this.closePopupPattern = Selector( 'button' ).withAttribute( - 'aria-label', - 'Close' - ); - this.titleField = Selector( '.editor-post-title__input' ); - this.addBlockToolbarIcon = Selector( - 'button.editor-document-tools__inserter-toggle' - ); - this.searchBlock = Selector( '.block-editor-inserter__search' ) - .find( 'input' ) - .withAttribute( 'type', 'search' ); - this.searchResults = Selector( '.block-editor-block-types-list' ); - this.documentPanel = Selector( 'div.editor-sidebar' ); - this.documentPanelToolbarButton = Selector( - 'button.components-button' - ).withAttribute( 'aria-label', 'Settings' ); - this.documentPanelCloseButton = Selector( - 'button.components-button' - ).withAttribute( 'aria-label', 'Close panel' ); - this.saveToolbarButton = Selector( - 'button.components-button' - ).withText( 'Save' ); - this.publishToolbarButton = Selector( - '.editor-post-publish-button__button' - ); - this.confirmPublishButton = Selector( - '.editor-post-publish-panel__header-publish-button button' - ).withText( 'Publish' ); - this.trashButton = Selector( 'button.editor-post-trash' ).withText( - 'Move to trash' - ); - } - - /** - * Creates a new page on this instance. - * Must only be used once per instance to prevent anomalies - * - * @return {Promise} none - */ - async add() { - await t.click( this.addNewPageLink ); - - if ( await this.closePopupButton.exists ) { - await t.click( this.closePopupButton ); - } - - if ( await this.closePopupPattern.exists ) { - await t.click( this.closePopupPattern ); - } - - await t.typeText( this.titleField, this.pageName, { paste: true } ); - } - - /** - * Deletes the page of this instance - * - * @return {Promise} none - */ - async delete() { - await t - .useRole( admin ) - .navigateTo( - `${ baseURL }/wp-admin/post.php?post=${ this.pageId }&action=edit` - ); - - if ( ! ( await this.documentPanel.exists ) ) { - await t.click( this.documentPanelToolbarButton ); - } - - await t.click( this.trashButton ).pressKey( 'enter' ); - } - - /** - * Inserts a block on this page instance - * - * @param { string } block name i.e paragraph, shortcode - * @param { { - * target: string - * content: string - * }= } node content of the block to be added - * - * @return {Promise} none - */ - async insertBlock( block, node ) { - await t - .click( this.addBlockToolbarIcon ) - .typeText( this.searchBlock.filterVisible(), block, { - paste: true, - } ); - - const resultBlock = this.searchResults.find( 'button' ); - - await t.hover( resultBlock ).click( resultBlock ); - - if ( node?.content ) { - await t.typeText( Selector( node.target ), node.content ); - } - } - - /** - * Saves content added to the page - * - * @return {Promise} none - */ - async saveChanges() { - await t.click( this.saveToolbarButton ); - } - - async publishChanges() { - await t - .click( this.publishToolbarButton ) - .click( this.confirmPublishButton ); - - this.pageId = await getQueryParam( 'post' ); - - await t.click( this.documentPanelCloseButton ); - } -} - -export default Page; diff --git a/tests/e2e/pdf-settings/advanced/enable-pdf-security-field.test.js b/tests/e2e/pdf-settings/advanced/enable-pdf-security-field.test.js deleted file mode 100644 index 8e4a583a4..000000000 --- a/tests/e2e/pdf-settings/advanced/enable-pdf-security-field.test.js +++ /dev/null @@ -1,30 +0,0 @@ -import { fieldLabel } from '../../utilities/page-model/helpers/field' -import Pdf from '../../utilities/page-model/helpers/pdf' - -const run = new Pdf() - -fixture`PDF advanced settings - Enable PDF security field test` - -test('should display \'Enable PDF Security\' field', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t.click(run.formatStandardCheckbox) - - // Assertions - await t - .expect(fieldLabel('Enable PDF Security').exists).ok() - .expect(run.enablePdfSecurityCheckbox.exists).ok() -}) - -test('should save toggled checkbox value', async t => { - // Actions & Assertions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(run.formatStandardCheckbox) - .click(run.enablePdfSecurityCheckbox) - .click(run.saveSettings) - .expect(run.enablePdfSecurityCheckbox.checked).ok() - .click(run.enablePdfSecurityCheckbox) - .click(run.saveSettings) - .expect(run.enablePdfSecurityCheckbox.checked).notOk() -}) diff --git a/tests/e2e/pdf-settings/advanced/enable-public-access-field.test.js b/tests/e2e/pdf-settings/advanced/enable-public-access-field.test.js deleted file mode 100644 index d217025dd..000000000 --- a/tests/e2e/pdf-settings/advanced/enable-public-access-field.test.js +++ /dev/null @@ -1,44 +0,0 @@ -import { Selector } from 'testcafe' -import { fieldLabel } from '../../utilities/page-model/helpers/field' -import Pdf from '../../utilities/page-model/helpers/pdf' - -const run = new Pdf() - -fixture`PDF advanced settings - Enable public access field test` - -test('should display \'Enable Public Access\' field', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - - // Assertions - await t - .expect(fieldLabel('Enable Public Access').exists).ok() - .expect(run.enablePublicAccessCheckbox.exists).ok() -}) - -test('should save toggled checkbox value', async t => { - // Actions & Assertions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(run.enablePublicAccessCheckbox) - .click(run.saveSettings) - .expect(run.enablePublicAccessCheckbox.checked).ok() - .click(run.enablePublicAccessCheckbox) - .click(run.saveSettings) - .expect(run.enablePublicAccessCheckbox.checked).notOk() -}) - -test('should hide \'Restrict Owner\' field if \'Enable Public Access\' checkbox is checked', async t => { - // Selectors - const restrictOwnerField = Selector('#gfpdf-settings-field-wrapper-restrict_owner') - - // Actions & Assertions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(run.enablePublicAccessCheckbox) - .click(run.saveSettings()) - .expect(restrictOwnerField.visible).notOk() - .click(run.enablePublicAccessCheckbox) - .click(run.saveSettings()) - .expect(restrictOwnerField.visible).ok() -}) diff --git a/tests/e2e/pdf-settings/advanced/format-field.test.js b/tests/e2e/pdf-settings/advanced/format-field.test.js deleted file mode 100644 index 8d137eeb7..000000000 --- a/tests/e2e/pdf-settings/advanced/format-field.test.js +++ /dev/null @@ -1,80 +0,0 @@ -import { Selector } from 'testcafe' -import { fieldLabel } from '../../utilities/page-model/helpers/field' -import Pdf from '../../utilities/page-model/helpers/pdf' - -const run = new Pdf() - -fixture`PDF advanced settings - Format field test` - -test('should display \'Format\' field', async t => { - // Selectors - const standardLabel = Selector('#gfpdf-settings-field-wrapper-format').find('label').withAttribute('for', 'gfpdf_settings[format][Standard]').withText('Standard') - const pdfA1bLabel = Selector('#gfpdf-settings-field-wrapper-format').find('label').withAttribute('for', 'gfpdf_settings[format][PDFA1B]').withText('PDF/A-1b') - const pdfX1aLabel = Selector('#gfpdf-settings-field-wrapper-format').find('label').withAttribute('for', 'gfpdf_settings[format][PDFX1A]').withText('PDF/X-1a') - - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - - // Assertions - await t - .expect(fieldLabel('Format').exists).ok() - .expect(run.formatStandardCheckbox.exists).ok() - .expect(standardLabel.exists).ok() - .expect(run.formatPdfA1bCheckbox.exists).ok() - .expect(pdfA1bLabel.exists).ok() - .expect(run.formatPdfX1aCheckbox.exists).ok() - .expect(pdfX1aLabel.exists).ok() -}) - -test('should display added fields if \'Standard\' option is checked', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(run.formatStandardCheckbox) - .click(run.enablePdfSecurityCheckbox) - - // Assertions - await t - .expect(run.enablePdfSecurityField.visible).ok() - .expect(run.passwordField.visible).ok() - .expect(run.privilegesField.visible).ok() -}) - -test('should hide \'Standard\' added fields if \'PDF/A-1b\' option is checked', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t.click(run.formatPdfA1bCheckbox) - - // Assertions - await t - .expect(run.enablePdfSecurityField.visible).notOk() - .expect(run.passwordField.visible).notOk() - .expect(run.privilegesField.visible).notOk() -}) - -test('should hide \'Standard\' added fields if \'PDF/X-1a\' option is checked', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t.click(run.formatPdfX1aCheckbox) - - // Assertions - await t - .expect(run.enablePdfSecurityField.visible).notOk() - .expect(run.passwordField.visible).notOk() - .expect(run.privilegesField.visible).notOk() -}) - -test('should save toggled checkbox value', async t => { - // Actions & Assertions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(run.formatStandardCheckbox) - .click(run.saveSettings) - .expect(run.formatStandardCheckbox.checked).ok() - .click(run.formatPdfA1bCheckbox) - .click(run.saveSettings) - .expect(run.formatPdfA1bCheckbox.checked).ok() - .click(run.formatPdfX1aCheckbox) - .click(run.saveSettings) - .expect(run.formatPdfX1aCheckbox.checked).ok() -}) diff --git a/tests/e2e/pdf-settings/advanced/image-dpi-field.test.js b/tests/e2e/pdf-settings/advanced/image-dpi-field.test.js deleted file mode 100644 index 4df4974c1..000000000 --- a/tests/e2e/pdf-settings/advanced/image-dpi-field.test.js +++ /dev/null @@ -1,34 +0,0 @@ -import { fieldLabel } from '../../utilities/page-model/helpers/field' -import Pdf from '../../utilities/page-model/helpers/pdf' - -const run = new Pdf() - -fixture`PDF advanced settings - Image DPI field test` - -test('should display \'Image DPI\' field', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - - // Assertions - await t - .expect(fieldLabel('Image DPI').exists).ok() - .expect(run.imageDpiInputBox.exists).ok() -}) - -test('should save selected image DPI value', async t => { - // Actions & Assertions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(run.imageDpiInputBox) - .pressKey('ctrl+a') - .pressKey('backspace') - .typeText(run.imageDpiInputBox, '98', { paste: true }) - .click(run.saveSettings) - .expect(run.imageDpiInputBox.value).eql('98') - .click(run.imageDpiInputBox) - .pressKey('ctrl+a') - .pressKey('backspace') - .typeText(run.imageDpiInputBox, '96', { paste: true }) - .click(run.saveSettings) - .expect(run.imageDpiInputBox.value).eql('96') -}) diff --git a/tests/e2e/pdf-settings/advanced/password-field.test.js b/tests/e2e/pdf-settings/advanced/password-field.test.js deleted file mode 100644 index acfc83fda..000000000 --- a/tests/e2e/pdf-settings/advanced/password-field.test.js +++ /dev/null @@ -1,82 +0,0 @@ -import { - fieldLabel, - mergeTagsWrapper, - passwordGroupOption, - passwordOptionItem -} from '../../utilities/page-model/helpers/field' -import Pdf from '../../utilities/page-model/helpers/pdf' - -const run = new Pdf() - -fixture`PDF advanced settings - Password field test` - -test('should display \'Password\' field', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t.click(run.formatStandardCheckbox) - - // Assertions - await t - .expect(fieldLabel('Password').exists).ok() - .expect(run.passwordInputBox.exists).ok() - .expect(run.passwordMergeTagsOptionList.exists).ok() -}) - -test('should check that merge tags list option exist', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(run.formatStandardCheckbox) - .click(run.enablePdfSecurityCheckbox) - .click(run.passwordMergeTagsOptionList) - - // Assertions - await t - .expect(mergeTagsWrapper('gfpdf-settings-field-wrapper-password').find('li').count).gt(0) - .expect(passwordGroupOption('Optional form fields').exists).ok() - .expect(passwordOptionItem('Text').exists).ok() - .expect(passwordOptionItem('Name (Prefix)').exists).ok() - .expect(passwordGroupOption('Other').exists).ok() - .expect(passwordOptionItem('User IP Address').exists).ok() - .expect(passwordOptionItem('Date (mm/dd/yyyy)').exists).ok() - .expect(passwordGroupOption('Custom').exists).ok() - .expect(passwordOptionItem('PDF: Sample').exists).ok() -}) - -test('should save selected merge tags', async t => { - // Actions & Assertions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(run.formatStandardCheckbox) - .click(run.enablePdfSecurityCheckbox) - .click(run.passwordMergeTagsOptionList) - .click(passwordOptionItem('Text')) - .click(run.passwordMergeTagsOptionList) - .click(passwordOptionItem('Name (Prefix)')) - .click(run.saveSettings) - .expect(run.passwordInputBox.value).contains('{Text:1}{Name (Prefix):2.2}') - .click(run.passwordInputBox) - .pressKey('ctrl+a') - .pressKey('backspace') - .typeText(run.passwordInputBox, '{Name (Prefix):2.2}', { paste: true }) - .click(run.saveSettings) - .expect(run.passwordInputBox.value).eql('{Name (Prefix):2.2}') - .click(run.passwordInputBox) - .pressKey('ctrl+a') - .pressKey('backspace') - .click(run.saveSettings) - .expect(run.passwordInputBox.value).eql('') -}) - -test('should disable/reset PDF security field and hide password field', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(run.formatStandardCheckbox) - .click(run.enablePdfSecurityCheckbox) - .click(run.saveSettings) - - // Assertions - await t - .expect(run.passwordField.visible).notOk() -}) diff --git a/tests/e2e/pdf-settings/advanced/privileges-field.test.js b/tests/e2e/pdf-settings/advanced/privileges-field.test.js deleted file mode 100644 index ecacb5944..000000000 --- a/tests/e2e/pdf-settings/advanced/privileges-field.test.js +++ /dev/null @@ -1,81 +0,0 @@ -import { fieldLabel } from '../../utilities/page-model/helpers/field' -import Pdf from '../../utilities/page-model/helpers/pdf' - -const run = new Pdf() - -fixture`PDF advanced settings - Privileges field test` - -test('should display \'Privileges\' field', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(run.formatStandardCheckbox) - .click(run.enablePdfSecurityCheckbox) - - // Assertions - await t - .expect(fieldLabel('Privileges').exists).ok() - .expect(run.copyCheckbox.checked).ok() - .expect(run.printLowResolutionCheckbox.checked).ok() - .expect(run.printHighResolutionCheckbox.checked).ok() - .expect(run.modifyCheckbox.checked).ok() - .expect(run.annotateCheckbox.checked).ok() - .expect(run.fillFormsCheckbox.checked).ok() - .expect(run.extractCheckbox.checked).ok() - .expect(run.assembleCheckbox.checked).ok() -}) - -test('should save toggled checkboxes value', async t => { - // Actions & Assertions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(run.formatStandardCheckbox) - .click(run.enablePdfSecurityCheckbox) - .click(run.copyCheckbox) - .click(run.printLowResolutionCheckbox) - .click(run.printHighResolutionCheckbox) - .click(run.modifyCheckbox) - .click(run.annotateCheckbox) - .click(run.fillFormsCheckbox) - .click(run.extractCheckbox) - .click(run.assembleCheckbox) - .click(run.saveSettings) - .expect(run.copyCheckbox.checked).notOk() - .expect(run.printLowResolutionCheckbox.checked).notOk() - .expect(run.printHighResolutionCheckbox.checked).notOk() - .expect(run.modifyCheckbox.checked).notOk() - .expect(run.annotateCheckbox.checked).notOk() - .expect(run.fillFormsCheckbox.checked).notOk() - .expect(run.extractCheckbox.checked).notOk() - .expect(run.assembleCheckbox.checked).notOk() - .click(run.copyCheckbox) - .click(run.printLowResolutionCheckbox) - .click(run.printHighResolutionCheckbox) - .click(run.modifyCheckbox) - .click(run.annotateCheckbox) - .click(run.fillFormsCheckbox) - .click(run.extractCheckbox) - .click(run.assembleCheckbox) - .click(run.saveSettings) - .expect(run.copyCheckbox.checked).ok() - .expect(run.printLowResolutionCheckbox.checked).ok() - .expect(run.printHighResolutionCheckbox.checked).ok() - .expect(run.modifyCheckbox.checked).ok() - .expect(run.annotateCheckbox.checked).ok() - .expect(run.fillFormsCheckbox.checked).ok() - .expect(run.extractCheckbox.checked).ok() - .expect(run.assembleCheckbox.checked).ok() -}) - -test('should disable/reset PDF security field and hide privileges field', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(run.formatStandardCheckbox) - .click(run.enablePdfSecurityCheckbox) - .click(run.saveSettings) - - // Assertions - await t - .expect(run.privilegesField.visible).notOk() -}) diff --git a/tests/e2e/pdf-settings/advanced/restrict-owner-field.test.js b/tests/e2e/pdf-settings/advanced/restrict-owner-field.test.js deleted file mode 100644 index 226dd0e94..000000000 --- a/tests/e2e/pdf-settings/advanced/restrict-owner-field.test.js +++ /dev/null @@ -1,41 +0,0 @@ -import { fieldLabel } from '../../utilities/page-model/helpers/field'; -import Pdf from '../../utilities/page-model/helpers/pdf'; - -const run = new Pdf(); - -fixture`PDF advanced settings - Restrict owner field test`; - -test("should display 'Restrict Owner' field", async (t) => { - // Actions - await run.navigatePdfSection( - 'gf_edit_forms&view=settings&subview=PDF&id=4' - ); - - // Assertions - await t - .expect(fieldLabel('Restrict Owner').exists) - .ok() - .expect(run.restrictOwnerCheckbox.exists) - .ok(); -}); - -test('should save toggled checkbox value', async (t) => { - // Actions & Assertions - await run.navigatePdfSection( - 'gf_edit_forms&view=settings&subview=PDF&id=4' - ); - - // ensure that the end scenario will make the restrict owner option not toggled - if (await run.restrictOwnerCheckbox.checked) { - await t.click(run.restrictOwnerCheckbox).click(run.saveSettings); - await t.expect(await run.restrictOwnerCheckbox.checked).notOk(); - } - - // toggle on - await t.click(run.restrictOwnerCheckbox).click(run.saveSettings); - await t.expect(await run.restrictOwnerCheckbox.checked).ok(); - - // toggle off - await t.click(run.restrictOwnerCheckbox).click(run.saveSettings); - await t.expect(await run.restrictOwnerCheckbox.checked).notOk(); -}); diff --git a/tests/e2e/pdf-settings/appearance/font-color-field.test.js b/tests/e2e/pdf-settings/appearance/font-color-field.test.js deleted file mode 100644 index af8778c8e..000000000 --- a/tests/e2e/pdf-settings/appearance/font-color-field.test.js +++ /dev/null @@ -1,33 +0,0 @@ -import { Selector } from 'testcafe' -import { fieldLabel, button } from '../../utilities/page-model/helpers/field' -import Pdf from '../../utilities/page-model/helpers/pdf' - -const run = new Pdf() - -fixture`PDF appearance settings - Font color field test` - -test('should display \'Font Color\' field', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t.click(button('Select Color')) - - // Assertions - await t - .expect(fieldLabel('Font Color').exists).ok() - .expect(run.fontColorSelectButton.exists).ok() - .expect(run.fontColorInputBox.exists).ok() - .expect(run.fontColorWpPickerContainerActive.exists).ok() - .expect(run.fontColorWpColorPickerBox.exists).ok() -}) - -test('should save selected font color', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(run.fontColorSelectButton) - .click(Selector('#gfpdf-settings-field-wrapper-font_colour').find('a').withAttribute('class', 'iris-palette').nth(3)) - .click(run.saveSettings) - - // Assertions - await t.expect(run.fontColorInputBox.value).eql('#dd9933') -}) diff --git a/tests/e2e/pdf-settings/appearance/font-field.test.js b/tests/e2e/pdf-settings/appearance/font-field.test.js deleted file mode 100644 index ed3093594..000000000 --- a/tests/e2e/pdf-settings/appearance/font-field.test.js +++ /dev/null @@ -1,186 +0,0 @@ -import { - fieldLabel, - dropdownOptionGroup, - dropdownOption -} from '../../utilities/page-model/helpers/field' -import Pdf from '../../utilities/page-model/helpers/pdf' -import FontManager from '../../utilities/page-model/helpers/font-manager' - -const run = new Pdf() -const fontManager = new FontManager() - -fixture`PDF appearance settings - Font field test` - -test('should display \'Font\' field', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - - // Assertions - await t - .expect(fieldLabel('Font').exists).ok() - .expect(run.fontSelectBox.exists).ok() - .expect(fontManager.advancedButton.exists).ok() -}) - -test('should display a dropdown of default fonts option', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t.click(run.fontSelectBox) - - // Assertions - await t - .expect(dropdownOptionGroup('Unicode').exists).ok() - .expect(dropdownOption('Dejavu Sans Condensed').exists).ok() - .expect(dropdownOption('Dejavu Sans').exists).ok() - .expect(dropdownOptionGroup('Indic').exists).ok() - .expect(dropdownOption('Lohit Kannada').exists).ok() - .expect(dropdownOption('Pothana2000').exists).ok() - .expect(dropdownOptionGroup('Arabic').exists).ok() - .expect(dropdownOption('XB Riyaz').exists).ok() - .expect(dropdownOption('Lateef').exists).ok() - .expect(dropdownOptionGroup('Chinese, Japanese, Korean').exists).ok() - .expect(dropdownOption('Sun Ext').exists).ok() - .expect(dropdownOption('Un Batang (Korean)').exists).ok() - .expect(dropdownOptionGroup('Other').exists).ok() - .expect(dropdownOption('Estrangelo Edessa (Syriac)').exists).ok() - .expect(dropdownOption('Kaputa (Sinhala)').exists).ok() -}) - -test('should save selected font', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(run.fontSelectBox) - .click(dropdownOption('MPH 2B Damase')) - .click(run.saveSettings) - - // Assertions - await t - .expect(run.fontSelectBox.value).eql('mph2bdamase') -}) - -test('should check that font manager popup exist', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t.click(fontManager.advancedButton) - - // Assertions - await t - .expect(fontManager.popupHeaderText.exists).ok() - .expect(fontManager.searchBar.exists).ok() - .expect(fontManager.fontListColumn.exists).ok() - .expect(fontManager.addFontColumn.exists).ok() -}) - -test('should display font manager error validation', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(fontManager.advancedButton) - .click(fontManager.addFontButton) - - // Assertions - await t - .expect(fontManager.fontNameFieldErrorValidation.exists).ok() - .expect(fontManager.fontNameFieldErrorValidationMessage.exists).ok() - .expect(fontManager.dropzoneRequiredRegularField.exists).ok() - .expect(fontManager.dropzoneErrorValidationMessage.exists).ok() - .expect(fontManager.addUpdatePanelGeneralErrorValidationMessage.exists).ok() -}) - -test('should successfully add new font', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(fontManager.advancedButton) - .click(fontManager.addFontButton) - .typeText(fontManager.addFontNameInputField, 'Roboto', { paste: true }) - .setFilesToUpload(fontManager.addNewFontRegular, '../../utilities/resources/Roboto-Regular.ttf') - .click(fontManager.addFontButton) - - // Assertions - await t - .expect(fontManager.fontListItem.count).eql(1) - .expect(fontManager.successMessage.exists).ok() -}) - -test('should successfully check toggled state for disabled \'Update Font\' button', async t => { - // Actions && Assertions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(fontManager.advancedButton) - .click(fontManager.fontListItem.nth(0)) - .expect(fontManager.updateFontButton.hasAttribute('disabled')).ok() - .typeText(fontManager.updateFontNameInputField, ' new', { paste: true }) - .expect(fontManager.updateFontButton.hasAttribute('disabled')).notOk() -}) - -test('should successfully close \'update font\' panel using cancel button', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(fontManager.advancedButton) - .click(fontManager.fontListItem.nth(0)) - .click(fontManager.cancelButton) - - // Assertions - await t.expect(fontManager.updateFontPanel.exists).notOk() -}) - -test('should successfully perform font search', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(fontManager.advancedButton) - .typeText(fontManager.searchBar, 'Roboto', { paste: true }) - - // Assertions - await t.expect(fontManager.fontListItem.count).eql(1) -}) - -test('should successfully edit existing font', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(fontManager.advancedButton) - .click(fontManager.fontListItem.nth(0)) - .click(fontManager.updateFontNameInputField) - .pressKey('ctrl+a') - .pressKey('backspace') - .typeText(fontManager.updateFontNameInputField, 'Roboto 2', { paste: true }) - .setFilesToUpload(fontManager.addNewFontItalics, fontManager.robotoFontItalics) - .setFilesToUpload(fontManager.addNewFontBold, fontManager.robotoFontBold) - .setFilesToUpload(fontManager.addNewFontBoldItalics, fontManager.robotoFontBoldItalics) - .click(fontManager.updateFontButton) - - // Assertions - await t - .expect(fontManager.successMessage.exists).ok() - .expect(fontManager.fontName.withText('Roboto 2').exists).ok() - .expect(fontManager.fontVariantsCheck.count).eql(4) -}) - -test('should successfully delete font', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(fontManager.advancedButton) - .click(fontManager.fontListItem.nth(0).find('[class^="dashicons dashicons-trash"]')) - .wait(500) - - // Assertions - await t - .expect(fontManager.fontListItem.count).eql(0) - .expect(fontManager.fontListEmptyMessage.exists).ok() -}) - -test('should be able to close font manager popup', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(fontManager.advancedButton) - .click(fontManager.closeDialog) - - // Assertions - await t.expect(fontManager.fontManagerPopup.exists).notOk() -}) diff --git a/tests/e2e/pdf-settings/appearance/font-size-field.test.js b/tests/e2e/pdf-settings/appearance/font-size-field.test.js deleted file mode 100644 index ee64995ed..000000000 --- a/tests/e2e/pdf-settings/appearance/font-size-field.test.js +++ /dev/null @@ -1,30 +0,0 @@ -import { fieldLabel } from '../../utilities/page-model/helpers/field' -import Pdf from '../../utilities/page-model/helpers/pdf' - -const run = new Pdf() - -fixture`PDF appearance settings - Font size field test` - -test('should display \'Font Size\' field', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - - // Assertions - await t - .expect(fieldLabel('Font Size').exists).ok() - .expect(run.fontSizeInputBox.exists).ok() -}) - -test('should save selected font size', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(run.fontSizeInputBox) - .pressKey('ctrl+a') - .pressKey('backspace') - .typeText(run.fontSizeInputBox, '15', { paste: true }) - .click(run.saveSettings) - - // Assertions - await t.expect(run.fontSizeInputBox.value).eql('15') -}) diff --git a/tests/e2e/pdf-settings/appearance/paper-orientation-field.test.js b/tests/e2e/pdf-settings/appearance/paper-orientation-field.test.js deleted file mode 100644 index 5280c617a..000000000 --- a/tests/e2e/pdf-settings/appearance/paper-orientation-field.test.js +++ /dev/null @@ -1,28 +0,0 @@ -import { fieldLabel, dropdownOption } from '../../utilities/page-model/helpers/field' -import Pdf from '../../utilities/page-model/helpers/pdf' - -const run = new Pdf() - -fixture`PDF appearance settings - Paper orientation field test` - -test('should display \'Paper Orientation\' field', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - - // Assertions - await t - .expect(fieldLabel('Paper Orientation').exists).ok() - .expect(run.paperOrientationSelectBox.exists).ok() -}) - -test('should save selected paper orientation value', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(run.paperOrientationSelectBox) - .click(dropdownOption('Landscape')) - .click(run.saveSettings) - - // Assertions - await t.expect(run.paperOrientationSelectBox.value).eql('landscape') -}) diff --git a/tests/e2e/pdf-settings/appearance/paper-size-field.test.js b/tests/e2e/pdf-settings/appearance/paper-size-field.test.js deleted file mode 100644 index 59bfcc82f..000000000 --- a/tests/e2e/pdf-settings/appearance/paper-size-field.test.js +++ /dev/null @@ -1,89 +0,0 @@ -import { - fieldLabel, - selectBox, - dropdownOptionGroup, - dropdownOption -} from '../../utilities/page-model/helpers/field' -import Pdf from '../../utilities/page-model/helpers/pdf' - -const run = new Pdf() - -fixture`PDF appearance settings - Paper size field test` - -test('should display \'Paper Size\' field', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - - // Assertions - await t - .expect(fieldLabel('Paper Size').exists).ok() - .expect(run.paperSizeSelectBox.exists).ok() -}) - -test('should display a dropdown of paper sizes option', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - - // Assertions - await t - .expect(dropdownOptionGroup('Common Sizes').exists).ok() - .expect(dropdownOption('A4 (210 x 297mm)').exists).ok() - .expect(dropdownOption('Letter (8.5 x 11in)').exists).ok() - .expect(dropdownOption('Custom Paper Size').exists).ok() - .expect(dropdownOptionGroup('"A" Sizes').exists).ok() - .expect(dropdownOption('A0 (841 x 1189mm)').exists).ok() - .expect(dropdownOption('A1 (594 x 841mm)').exists).ok() - .expect(dropdownOptionGroup('"B" Sizes').exists).ok() - .expect(dropdownOption('B0 (1414 x 1000mm)').exists).ok() - .expect(dropdownOption('B1 (1000 x 707mm)').exists).ok() - .expect(dropdownOptionGroup('"C" Sizes').exists).ok() - .expect(dropdownOption('C0 (1297 x 917mm)').exists).ok() - .expect(dropdownOption('C1 (917 x 648mm)').exists).ok() - .expect(dropdownOptionGroup('"RA" and "SRA" Sizes').exists).ok() - .expect(dropdownOption('RA0 (860 x 1220mm)').exists).ok() - .expect(dropdownOption('RA1 (610 x 860mm)').exists).ok() -}) - -test('should save selected paper size', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(run.paperSizeSelectBox) - .click(dropdownOption('Letter (8.5 x 11in)')) - .click(run.saveSettings) - - // Assertions - await t.expect(run.paperSizeSelectBox.value).eql('LETTER') -}) - -test('should save selected custom paper size', async t => { - // Selectors - const widthInputBox = selectBox('small-text gfpdf_settings_custom_pdf_size', 'gfpdf_settings[custom_pdf_size]_width') - const heightInputBox = selectBox('small-text gfpdf_settings_custom_pdf_size', 'gfpdf_settings[custom_pdf_size]_height') - const measurementInputBox = selectBox('gfpdf_settings_custom_pdf_size ', 'gfpdf_settings[custom_pdf_size]_measurement') - - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(run.paperSizeSelectBox) - .click(dropdownOption('Custom Paper Size')) - .click(widthInputBox) - .pressKey('ctrl+a') - .pressKey('backspace') - .typeText(widthInputBox, '2', { paste: true }) - .click(heightInputBox) - .pressKey('ctrl+a') - .pressKey('backspace') - .typeText(heightInputBox, '5', { paste: true }) - .click(measurementInputBox) - .click(dropdownOption('inches')) - .click(run.saveSettings) - - // Assertions - await t - .expect(run.paperSizeSelectBox.value).eql('CUSTOM') - .expect(run.customPaperSizeLabel.exists).ok() - .expect(widthInputBox.value).eql('2') - .expect(heightInputBox.value).eql('5') - .expect(measurementInputBox.value).eql('inches') -}) diff --git a/tests/e2e/pdf-settings/appearance/reverse-text-rtl-field.test.js b/tests/e2e/pdf-settings/appearance/reverse-text-rtl-field.test.js deleted file mode 100644 index e8195a419..000000000 --- a/tests/e2e/pdf-settings/appearance/reverse-text-rtl-field.test.js +++ /dev/null @@ -1,28 +0,0 @@ -import { fieldLabel } from '../../utilities/page-model/helpers/field' -import Pdf from '../../utilities/page-model/helpers/pdf' - -const run = new Pdf() - -fixture`PDF appearance settings - Reverse text (RTL) field test` - -test('should display \'Reverse Text (RTL)\' field', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - - // Assertions - await t - .expect(fieldLabel('Reverse Text (RTL)').exists).ok() - .expect(run.rtlCheckbox.exists).ok() -}) - -test('should save toggled checkbox value', async t => { - // Actions & Assertions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(run.rtlCheckbox) - .click(run.saveSettings) - .expect(run.rtlCheckbox.checked).ok() - .click(run.rtlCheckbox) - .click(run.saveSettings) - .expect(run.rtlCheckbox.checked).notOk() -}) diff --git a/tests/e2e/pdf-settings/general/conditional-logic-field.test.js b/tests/e2e/pdf-settings/general/conditional-logic-field.test.js deleted file mode 100644 index 1c067c328..000000000 --- a/tests/e2e/pdf-settings/general/conditional-logic-field.test.js +++ /dev/null @@ -1,46 +0,0 @@ -import { Selector } from 'testcafe' -import { fieldLabel } from '../../utilities/page-model/helpers/field' -import Pdf from '../../utilities/page-model/helpers/pdf' - -const run = new Pdf() - -fixture`PDF general settings - Conditional logic field test` - -test('should display \'Conditional Logic\' field', async t => { - // Selectors - const checkboxLabel = Selector('#gfpdf-settings-field-wrapper-conditional').find('label').withText('Enable conditional logic') - - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - - // Assertions - await t - .expect(fieldLabel('Conditional Logic').exists).ok() - .expect(run.conditionalLogicCheckbox.exists).ok() - .expect(checkboxLabel.exists).ok() -}) - -test('should save checkbox toggled value', async t => { - // Actions && Assertions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(run.conditionalLogicCheckbox) - .click(run.saveSettings) - .expect(run.conditionalLogicCheckbox.checked).ok() - .click(run.conditionalLogicCheckbox) - .click(run.saveSettings) - .expect(run.conditionalLogicCheckbox.checked).notOk() -}) - -test('should display conditional logic settings field if checkbox is checked', async t => { - // Selectors - const conditionalLogicSettingsField = Selector('#gfpdf-settings-field-wrapper-conditional').find('[class^="gform-settings-field__conditional-logic"][id="gfpdf_conditional_logic_container"]') - - // Actions & Assertions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(run.conditionalLogicCheckbox) - .expect(conditionalLogicSettingsField.visible).ok() - .click(run.conditionalLogicCheckbox) - .expect(conditionalLogicSettingsField.visible).notOk() -}) diff --git a/tests/e2e/pdf-settings/general/filename-field.test.js b/tests/e2e/pdf-settings/general/filename-field.test.js deleted file mode 100644 index c1d1f5782..000000000 --- a/tests/e2e/pdf-settings/general/filename-field.test.js +++ /dev/null @@ -1,67 +0,0 @@ -import { - fieldLabel, - mergeTagsWrapper, - filenameGroupOption, - filenameOptionItem -} from '../../utilities/page-model/helpers/field' -import Pdf from '../../utilities/page-model/helpers/pdf' - -const run = new Pdf() - -fixture`PDF general settings - Filename field test` - -test('should display \'Filename\' field', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - - // Assertions - await t - .expect(fieldLabel('Filename (required)').exists).ok() - .expect(run.filenameInputBox.exists).ok() - .expect(run.filenameMergeTagsOptionList.exists).ok() -}) - -test('should check that merge tags list option exist', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t.click(run.filenameMergeTagsOptionList) - - // Assertions - await t - .expect(mergeTagsWrapper('gfpdf-settings-field-wrapper-filename').find('li').count).gt(0) - .expect(filenameGroupOption('Optional form fields').exists).ok() - .expect(filenameOptionItem('Text').exists).ok() - .expect(filenameOptionItem('Name (Prefix)').exists).ok() - .expect(filenameGroupOption('Other').exists).ok() - .expect(filenameOptionItem('User IP Address').exists).ok() - .expect(filenameOptionItem('Date (mm/dd/yyyy)').exists).ok() - .expect(filenameGroupOption('Custom').exists).ok() - .expect(filenameOptionItem('PDF: Sample').exists).ok() -}) - -test('should save selected merge tags', async t => { - // Actions & Assertions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(run.filenameInputBox) - .pressKey('ctrl+a') - .pressKey('backspace') - .click(run.filenameMergeTagsOptionList) - .click(filenameOptionItem('Text')) - .click(run.filenameMergeTagsOptionList) - .click(filenameOptionItem('Name (Prefix)')) - .click(run.saveSettings) - .expect(run.filenameInputBox.value).eql('{Text:1}{Name (Prefix):2.2}') - .click(run.filenameInputBox) - .pressKey('ctrl+a') - .pressKey('backspace') - .typeText(run.filenameInputBox, '{Text:1}', { paste: true }) - .click(run.saveSettings) - .expect(run.filenameInputBox.value).eql('{Text:1}') - .click(run.filenameInputBox) - .pressKey('ctrl+a') - .pressKey('backspace') - .typeText(run.filenameInputBox, 'sample', { paste: true }) - .click(run.saveSettings) - .expect(run.filenameInputBox.value).eql('sample') -}) diff --git a/tests/e2e/pdf-settings/general/label-field.test.js b/tests/e2e/pdf-settings/general/label-field.test.js deleted file mode 100644 index bd160026d..000000000 --- a/tests/e2e/pdf-settings/general/label-field.test.js +++ /dev/null @@ -1,41 +0,0 @@ -import { Selector } from 'testcafe' -import { fieldLabel } from '../../utilities/page-model/helpers/field' -import Pdf from '../../utilities/page-model/helpers/pdf' - -const run = new Pdf() - -fixture`PDF general settings - Label field test` - -test('should display \'Label\' field', async t => { - // Selectors - const labelInputField = Selector('#gfpdf_settings\\[name\\]') - - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - - // Assertions - await t - .expect(fieldLabel('Label (required)').exists).ok() - .expect(labelInputField.exists).ok() -}) - -test('should save new label', async t => { - // Selectors - const labelInputField = Selector('#gfpdf_settings\\[name\\]') - - // Actions && Assertions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(labelInputField) - .pressKey('ctrl+a') - .pressKey('backspace') - .typeText(labelInputField, 'New sample', { paste: true }) - .click(run.saveSettings) - .expect(labelInputField.value).eql('New sample') - .click(labelInputField) - .pressKey('ctrl+a') - .pressKey('backspace') - .typeText(labelInputField, 'Sample', { paste: true }) - .click(run.saveSettings) - .expect(labelInputField.value).eql('Sample') -}) diff --git a/tests/e2e/pdf-settings/general/notifications-field.test.js b/tests/e2e/pdf-settings/general/notifications-field.test.js deleted file mode 100644 index 76f9ad02f..000000000 --- a/tests/e2e/pdf-settings/general/notifications-field.test.js +++ /dev/null @@ -1,37 +0,0 @@ -import { Selector } from 'testcafe' -import { fieldLabel } from '../../utilities/page-model/helpers/field' -import Pdf from '../../utilities/page-model/helpers/pdf' - -const run = new Pdf() - -fixture`PDF general settings - Notifications field test` - -test('should display \'Notifications\' field', async t => { - // Selectors - const checkbox = Selector('#gfpdf-settings-field-wrapper-notification').find('[class^="gfpdf_settings_notification "]') - const checkboxLabel = Selector('#gfpdf-settings-field-wrapper-notification').find('label').withText('Admin Notification') - - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - - // Assertions - await t - .expect(fieldLabel('Notifications').exists).ok() - .expect(checkbox.exists).ok() - .expect(checkboxLabel.exists).ok() -}) - -test('should save checkbox toggled value', async t => { - // Selectors - const checkbox = Selector('#gfpdf-settings-field-wrapper-notification').find('[class^="gfpdf_settings_notification "]') - - // Actions && Assertions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(checkbox) - .click(run.saveSettings) - .expect(checkbox.checked).ok() - .click(checkbox) - .click(run.saveSettings) - .expect(checkbox.checked).notOk() -}) diff --git a/tests/e2e/pdf-settings/general/template-field.test.js b/tests/e2e/pdf-settings/general/template-field.test.js deleted file mode 100644 index 0f4a6b107..000000000 --- a/tests/e2e/pdf-settings/general/template-field.test.js +++ /dev/null @@ -1,160 +0,0 @@ -import { Selector } from 'testcafe' -import { - fieldLabel, - dropdownOptionGroup, - dropdownOption, - button, - templateDetails -} from '../../utilities/page-model/helpers/field' -import Pdf from '../../utilities/page-model/helpers/pdf' -import TemplateManager from '../../utilities/page-model/helpers/template-manager' - -const run = new Pdf() -const templateManager = new TemplateManager() - -fixture`PDF general settings - Template field test` - -test('should display \'Template\' field', async t => { - // Actions - await templateManager.navigateTemplateManager('gf_edit_forms&view=settings&subview=PDF&id=4&tab=general', false) - - // Assertions - await t - .expect(fieldLabel('Template').exists).ok() - .expect(run.templateSelectBox.exists).ok() - .expect(templateManager.advancedButton.exists).ok() -}) - -test('should display the core templates dropdown option', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - - // Assertions - await t - .expect(dropdownOptionGroup('Core').exists).ok() - .expect(dropdownOption('Blank Slate').exists).ok() - .expect(dropdownOption('Focus Gravity').exists).ok() - .expect(dropdownOption('Rubix').exists).ok() - .expect(dropdownOption('Zadani').exists).ok() -}) - -test('should save selected template', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(run.templateSelectBox) - .click(dropdownOption('Rubix')) - .click(run.saveSettings) - - // Assertions - await t - .expect(run.templateSelectBox.value).eql('rubix') -}) - -test('should check that template manager popup exist', async t => { - // Actions - await templateManager.navigateTemplateManager('gf_edit_forms&view=settings&subview=PDF&id=4') - - // Assertions - await t - .expect(templateManager.popupHeaderText.exists).ok() - .expect(templateManager.closeDialog.exists).ok() - .expect(templateManager.searchBar.exists).ok() - .expect(templateManager.individualThemeBox.exists).ok() - .expect(templateManager.themeScreenshot.exists).ok() - .expect(templateManager.themeAuthor.exists).ok() - .expect(templateManager.themeName.exists).ok() - .expect(templateManager.themeSelectButton.exists).ok() - .expect(templateManager.themeDetailsLink.exists).ok() - .expect(templateManager.dropZoneBox.exists).ok() - .expect(templateManager.addNewTemplateButton.exists).ok() - .expect(templateManager.installationMessage.innerText).contains('If you have a PDF template in .zip format you may install it here. You can also update an existing PDF template (this will override any changes you have made).') -}) - -test('should display individual template details', async t => { - // Selectors - const imageScreenshot = Selector('.screenshot').find('img').getAttribute('src') - - // Actions - await templateManager.navigateTemplateManager('gf_edit_forms&view=settings&subview=PDF&id=4') - await t.click(templateManager.focusGravityTemplateDetails) - - // Assertions - await t - .expect(imageScreenshot).contains('focus-gravity.png') - .expect(templateDetails('theme-name', 'Focus Gravity').exists).ok() - .expect(templateDetails('theme-version', 'Version: ').exists).ok() - .expect(templateDetails('theme-author', 'Gravity PDF').exists).ok() - .expect(templateDetails('theme-author', 'Group: Core').exists).ok() - .expect(templateDetails('theme-description', 'Focus Gravity providing a classic layout which epitomises Gravity Forms Print Preview. It\'s the familiar layout you\'ve come to love. Through the Template tab you can control the PDF header and footer, change the background color or image, and show or hide the form title, page names, HTML fields and the Section Break descriptions.').exists).ok() - .expect(templateDetails('theme-tags', 'Tags: Header, Footer, Background, Optional HTML Fields, Optional Page Fields, Combined Row, Alternate Colors').exists).ok() -}) - -test('should navigate to next and previous template', async t => { - // Actions && Assertions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(run.templateSelectBox) - .click(dropdownOption('Blank Slate')) - .click(templateManager.advancedButton) - .click(templateManager.focusGravityTemplateDetails) - .click(button('Show next template')) - .expect(templateManager.rubixTemplate.exists).ok() - .click(button('Show previous template')) - .expect(templateManager.focusGravityTemplate.exists).ok() - .pressKey('right') - .expect(templateManager.rubixTemplate.exists).ok() - .pressKey('left') - .expect(templateManager.focusGravityTemplate.exists).ok() -}) - -test('should display popup template manager that can be close', async t => { - // Actions & Assertions - await templateManager.navigateTemplateManager('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(templateManager.closeDialog) - .click(templateManager.advancedButton) - .pressKey('esc') - .expect(templateManager.templatePopupBox.exists).notOk() -}) - -test('should successfully search for template', async t => { - // Actions - await templateManager.navigateTemplateManager('gf_edit_forms&view=settings&subview=PDF&id=4') - await t.typeText(templateManager.templateSearchbar, 'rubix', { paste: true }) - - // Assertions - await t - .expect(templateManager.templateSearchbar.exists).ok() - .expect(templateManager.searchResult.count).eql(1) -}) - -test('should successfully upload new template', async t => { - // Actions - await templateManager.navigateTemplateManager('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .setFilesToUpload(templateManager.addNewTemplateButton, templateManager.testTemplate) - .wait(500) - - // Assertions - await t - .expect(templateDetails('notice inline', 'Template successfully installed').exists).ok() - .expect(templateManager.imageScreenshot.exists).ok() - .expect(templateDetails('theme-author', 'Custom').exists).ok() - .expect(templateDetails('theme-name', 'Test Template').exists).ok() - .expect(templateDetails('notice inline', 'PDF Template(s) Successfully Installed / Updated').exists).ok() -}) - -test('should successfully delete new added template', async t => { - // Actions - await templateManager.navigateTemplateManager('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(templateManager.testTemplateDetailsLink) - .click(templateManager.deleteButton) - - // Assertions - await t - .expect(templateManager.imageScreenshot.exists).notOk() - .expect(templateDetails('theme-author', 'Universal (Premium)').exists).notOk() - .expect(templateDetails('theme-name', 'Cellulose').exists).notOk() -}) diff --git a/tests/e2e/pdf-settings/template/background-color-field.test.js b/tests/e2e/pdf-settings/template/background-color-field.test.js deleted file mode 100644 index 435500427..000000000 --- a/tests/e2e/pdf-settings/template/background-color-field.test.js +++ /dev/null @@ -1,33 +0,0 @@ -import { Selector } from 'testcafe' -import { fieldLabel } from '../../utilities/page-model/helpers/field' -import Pdf from '../../utilities/page-model/helpers/pdf' - -const run = new Pdf() - -fixture`PDF template settings - Background color field test` - -test('should display \'Background Color\' field', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t.click(run.backgroundColorSelectButton) - - // Assertions - await t - .expect(fieldLabel('Background Color').exists).ok() - .expect(run.backgroundColorSelectButton.exists).ok() - .expect(run.backgroundColorInputBox.exists).ok() - .expect(run.backgroundColorWpPickerContainerActive.exists).ok() - .expect(run.backgroundColorWpColorPickerBox.exists).ok() -}) - -test('should save selected background color', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(run.backgroundColorSelectButton) - .click(Selector('#gfpdf-settings-field-wrapper-background_color').find('a').withAttribute('class', 'iris-palette').nth(6)) - .click(run.saveSettings) - - // Assertions - await t.expect(run.backgroundColorInputBox.value).eql('#1e73be') -}) diff --git a/tests/e2e/pdf-settings/template/background-image-field.test.js b/tests/e2e/pdf-settings/template/background-image-field.test.js deleted file mode 100644 index ebc3fc86c..000000000 --- a/tests/e2e/pdf-settings/template/background-image-field.test.js +++ /dev/null @@ -1,68 +0,0 @@ -import { fieldLabel, mediaManagerTitle } from '../../utilities/page-model/helpers/field' -import Pdf from '../../utilities/page-model/helpers/pdf' -import MediaManager from '../../utilities/page-model/helpers/media-manager' - -const run = new Pdf() -const mediaManager = new MediaManager() - -fixture`PDF template settings - Background image field test` - -test('should display \'Background Image\' field', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - - // Assertions - await t - .expect(fieldLabel('Background Image').exists).ok() - .expect(run.backgroundImageUploadBox.exists).ok() - .expect(run.backgroundImageUploadFileButton.exists).ok() -}) - -test('should check that upload media manager exist', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t.click(run.backgroundImageUploadFileButton) - - // Assertions - await t - .expect(mediaManager.mediaModalContainer.exists).ok() - .expect(mediaManager.mediaCloseDialog.exists).ok() - .expect(mediaManagerTitle('Select Media').exists).ok() - .expect(mediaManager.uploadFilesPanelLink.exists).ok() - .expect(mediaManager.mediaLibraryPanelLink.exists).ok() - .expect(mediaManager.dropInstructionsText.exists).ok() - .expect(mediaManager.selectFilesButton.exists).ok() - .expect(mediaManager.maxUploadSizeText.exists).ok() -}) - -test('should save uploaded file', async t => { - // Actions & Assertions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(run.backgroundImageUploadFileButton) - .click(mediaManager.uploadFilesPanelLink) - .click(mediaManager.selectFilesButton) - .setFilesToUpload(mediaManager.uploadMediaFilesInputBox, mediaManager.backgroundImage) - .click(mediaManager.selectMediaButton) - .click(run.saveSettings) - .expect(run.backgroundImageUploadBox.value).contains('background-image.jpg') - .click(run.backgroundImageUploadBox) - .pressKey('ctrl+a') - .pressKey('backspace') - .click(run.saveSettings) - .expect(run.backgroundImageUploadBox.value).eql('') -}) - -test('should delete uploaded media file', async t => { - // Actions & Assertions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(run.backgroundImageUploadFileButton) - .click(mediaManager.uploadedMediaFile) - .click(mediaManager.deleteFile) - .expect(mediaManager.uploadedMediaFile.count).eql(0) - .click(mediaManager.mediaCloseDialog) - .click(run.saveSettings) - .click(run.backgroundImageUploadFileButton) - .expect(mediaManager.uploadedMediaFile.count).eql(0) -}) diff --git a/tests/e2e/pdf-settings/template/enable-conditional-logic-field.test.js b/tests/e2e/pdf-settings/template/enable-conditional-logic-field.test.js deleted file mode 100644 index 002842449..000000000 --- a/tests/e2e/pdf-settings/template/enable-conditional-logic-field.test.js +++ /dev/null @@ -1,28 +0,0 @@ -import { fieldLabel } from '../../utilities/page-model/helpers/field' -import Pdf from '../../utilities/page-model/helpers/pdf' - -const run = new Pdf() - -fixture`PDF template settings - Enable conditional logic field test` - -test('should display \'Enable Conditional Logic\' field', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - - // Assertions - await t - .expect(fieldLabel('Show Section Break Description').exists).ok() - .expect(run.enableConditionalLogicCheckbox.exists).ok() -}) - -test('should save toggled checkbox value', async t => { - // Actions & Assertions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(run.enableConditionalLogicCheckbox) - .click(run.saveSettings) - .expect(run.enableConditionalLogicCheckbox.checked).notOk() - .click(run.enableConditionalLogicCheckbox) - .click(run.saveSettings) - .expect(run.enableConditionalLogicCheckbox.checked).ok() -}) diff --git a/tests/e2e/pdf-settings/template/first-page-footer-field.test.js b/tests/e2e/pdf-settings/template/first-page-footer-field.test.js deleted file mode 100644 index f20fae56a..000000000 --- a/tests/e2e/pdf-settings/template/first-page-footer-field.test.js +++ /dev/null @@ -1,81 +0,0 @@ -import { - fieldLabel, - mediaManagerTitle, - addMediaButton -} from '../../utilities/page-model/helpers/field' -import Pdf from '../../utilities/page-model/helpers/pdf' -import MediaManager from '../../utilities/page-model/helpers/media-manager' - -const run = new Pdf() -const mediaManager = new MediaManager() - -fixture`PDF template settings - First page footer field test` - -test('should display \'First Page Footer\' field', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t.click(run.firstPageFooterCheckbox) - - // Assertions - await t - .expect(fieldLabel('First Page Footer').exists).ok() - .expect(run.firstPageFooterCheckbox.exists).ok() - .expect(addMediaButton('gfpdf-settings-field-wrapper-first_footer', 'Add Media').exists).ok() - .expect(run.firstPageFooterWpEditorBox.exists).ok() -}) - -test('should check that upload media manager exist', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(run.firstPageFooterCheckbox) - .click(addMediaButton('gfpdf-settings-field-wrapper-first_footer', 'Add Media')) - - // Assertions - await t - .expect(mediaManager.mediaModalContainer.exists).ok() - .expect(mediaManager.mediaCloseDialog.exists).ok() - .expect(mediaManagerTitle('Add media').exists).ok() - .expect(mediaManager.uploadFilesPanelLink.exists).ok() - .expect(mediaManager.mediaLibraryPanelLink.exists).ok() - .expect(mediaManager.dropInstructionsText.exists).ok() - .expect(mediaManager.selectFilesButton.exists).ok() - .expect(mediaManager.maxUploadSizeText.exists).ok() -}) - -test('should save checkbox toggled value', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(run.firstPageFooterCheckbox) - .click(addMediaButton('gfpdf-settings-field-wrapper-first_footer', 'Add Media')) - .click(mediaManager.uploadFilesPanelLink) - .click(mediaManager.selectFilesButton) - .setFilesToUpload(mediaManager.uploadMediaFilesInputBox, mediaManager.backgroundImage) - .click(mediaManager.insertIntoPostButton) - .click(run.firstPageFooterWpEditorBoxTextPanelLink) - .typeText(run.firstPageFooterWpEditorBoxContentArea, 'test', { paste: true }) - .click(run.saveSettings) - - // Assertions - await t - .expect(run.firstPageFooterWpEditorBoxContentArea.withText('/background-image-300x193.jpg').exists).ok() - .expect(run.firstPageFooterWpEditorBoxContentArea.withText('test').exists).ok() -}) - -test('should delete/reset \'First Page Footer\' field content', async t => { - // Actions & Assertions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(addMediaButton('gfpdf-settings-field-wrapper-first_footer', 'Add Media')) - .click(mediaManager.uploadedMediaFile) - .click(mediaManager.deleteFile) - .expect(mediaManager.uploadedMediaFile.count).eql(0) - .click(mediaManager.mediaCloseDialog) - .click(run.firstPageFooterWpEditorBoxTextPanelLink) - .click(run.firstPageFooterWpEditorBoxContentArea) - .pressKey('ctrl+a') - .pressKey('backspace') - .click(run.saveSettings) - .expect(run.firstPageFooterCheckbox.checked).notOk() -}) diff --git a/tests/e2e/pdf-settings/template/first-page-header-field.test.js b/tests/e2e/pdf-settings/template/first-page-header-field.test.js deleted file mode 100644 index 9a4bcb4db..000000000 --- a/tests/e2e/pdf-settings/template/first-page-header-field.test.js +++ /dev/null @@ -1,81 +0,0 @@ -import { - fieldLabel, - mediaManagerTitle, - addMediaButton -} from '../../utilities/page-model/helpers/field' -import Pdf from '../../utilities/page-model/helpers/pdf' -import MediaManager from '../../utilities/page-model/helpers/media-manager' - -const run = new Pdf() -const mediaManager = new MediaManager() - -fixture`PDF template settings - First page header field test` - -test('should display \'First Page Header\' field', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t.click(run.firstPageHeaderCheckbox) - - // Assertions - await t - .expect(fieldLabel('First Page Header').exists).ok() - .expect(run.firstPageHeaderCheckbox.exists).ok() - .expect(addMediaButton('gfpdf-settings-field-wrapper-first_header', 'Add Media').exists).ok() - .expect(run.firstPageHeaderWpEditorBox.exists).ok() -}) - -test('should check that upload media manager exist', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(run.firstPageHeaderCheckbox) - .click(addMediaButton('gfpdf-settings-field-wrapper-first_header', 'Add Media')) - - // Assertions - await t - .expect(mediaManager.mediaModalContainer.exists).ok() - .expect(mediaManager.mediaCloseDialog.exists).ok() - .expect(mediaManagerTitle('Add media').exists).ok() - .expect(mediaManager.uploadFilesPanelLink.exists).ok() - .expect(mediaManager.mediaLibraryPanelLink.exists).ok() - .expect(mediaManager.dropInstructionsText.exists).ok() - .expect(mediaManager.selectFilesButton.exists).ok() - .expect(mediaManager.maxUploadSizeText.exists).ok() -}) - -test('should save checkbox toggled value', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(run.firstPageHeaderCheckbox) - .click(addMediaButton('gfpdf-settings-field-wrapper-first_header', 'Add Media')) - .click(mediaManager.uploadFilesPanelLink) - .click(mediaManager.selectFilesButton) - .setFilesToUpload(mediaManager.uploadMediaFilesInputBox, mediaManager.backgroundImage) - .click(mediaManager.insertIntoPostButton) - .click(run.firstPageHeaderWpEditorBoxTextPanelLink) - .typeText(run.firstPageHeaderWpEditorBoxContentArea, 'test', { paste: true }) - .click(run.saveSettings) - - // Assertions - await t - .expect(run.firstPageHeaderWpEditorBoxContentArea.withText('/background-image-300x193.jpg').exists).ok() - .expect(run.firstPageHeaderWpEditorBoxContentArea.withText('test').exists).ok() -}) - -test('should delete/reset \'First Page Header\' field content', async t => { - // Actions & Assertions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(addMediaButton('gfpdf-settings-field-wrapper-first_header', 'Add Media')) - .click(mediaManager.uploadedMediaFile) - .click(mediaManager.deleteFile) - .expect(mediaManager.uploadedMediaFile.count).eql(0) - .click(mediaManager.mediaCloseDialog) - .click(run.firstPageHeaderWpEditorBoxTextPanelLink) - .click(run.firstPageHeaderWpEditorBoxContentArea) - .pressKey('ctrl+a') - .pressKey('backspace') - .click(run.saveSettings) - .expect(run.firstPageHeaderCheckbox.checked).notOk() -}) diff --git a/tests/e2e/pdf-settings/template/footer-field.test.js b/tests/e2e/pdf-settings/template/footer-field.test.js deleted file mode 100644 index c8e2d2de2..000000000 --- a/tests/e2e/pdf-settings/template/footer-field.test.js +++ /dev/null @@ -1,77 +0,0 @@ -import { - fieldLabel, - mediaManagerTitle, - addMediaButton -} from '../../utilities/page-model/helpers/field' -import Pdf from '../../utilities/page-model/helpers/pdf' -import MediaManager from '../../utilities/page-model/helpers/media-manager' - -const run = new Pdf() -const mediaManager = new MediaManager() - -fixture`PDF template settings - Footer field test` - -test('should display \'Footer\' field', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - - // Assertions - await t - .expect(fieldLabel('Footer').exists).ok() - .expect(addMediaButton('gfpdf-settings-field-wrapper-footer', 'Add Media').exists).ok() - .expect(run.footerWpEditorBox.exists).ok() -}) - -test('should check that upload media manager exist', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t.click(addMediaButton('gfpdf-settings-field-wrapper-footer', 'Add Media')) - - // Assertions - await t - .expect(mediaManager.mediaModalContainer.exists).ok() - .expect(mediaManager.mediaCloseDialog.exists).ok() - .expect(mediaManagerTitle('Add media').exists).ok() - .expect(mediaManager.uploadFilesPanelLink.exists).ok() - .expect(mediaManager.mediaLibraryPanelLink.exists).ok() - .expect(mediaManager.dropInstructionsText.exists).ok() - .expect(mediaManager.selectFilesButton.exists).ok() - .expect(mediaManager.maxUploadSizeText.exists).ok() -}) - -test('should save added footer data', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(addMediaButton('gfpdf-settings-field-wrapper-footer', 'Add Media')) - .click(mediaManager.uploadFilesPanelLink) - .click(mediaManager.selectFilesButton) - .setFilesToUpload(mediaManager.uploadMediaFilesInputBox, mediaManager.backgroundImage) - .click(mediaManager.insertIntoPostButton) - .click(run.footerWpEditorBoxTextPanelLink) - .typeText(run.footerWpEditorBoxContentArea, 'test', { paste: true }) - .click(run.saveSettings) - - // Assertions - await t - .expect(run.footerWpEditorBoxContentArea.withText('/background-image-300x193.jpg').exists).ok() - .expect(run.footerWpEditorBoxContentArea.withText('test').exists).ok() -}) - -test('should delete/reset footer field content', async t => { - // Actions & Assertions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(addMediaButton('gfpdf-settings-field-wrapper-footer', 'Add Media')) - .click(mediaManager.uploadedMediaFile) - .click(mediaManager.deleteFile) - .expect(mediaManager.uploadedMediaFile.count).eql(0) - .click(mediaManager.mediaCloseDialog) - .click(run.footerWpEditorBoxTextPanelLink) - .click(run.footerWpEditorBoxContentArea) - .pressKey('ctrl+a') - .pressKey('backspace') - .click(run.saveSettings) - .expect(run.footerWpEditorBoxContentArea.withText('/background-image-300x193.jpg').exists).notOk() - .expect(run.footerWpEditorBoxContentArea.withText('test').exists).notOk() -}) diff --git a/tests/e2e/pdf-settings/template/header-field.test.js b/tests/e2e/pdf-settings/template/header-field.test.js deleted file mode 100644 index 03670a674..000000000 --- a/tests/e2e/pdf-settings/template/header-field.test.js +++ /dev/null @@ -1,79 +0,0 @@ -import { - fieldLabel, - mediaManagerTitle, - addMediaButton -} from '../../utilities/page-model/helpers/field' -import Pdf from '../../utilities/page-model/helpers/pdf' -import MediaManager from '../../utilities/page-model/helpers/media-manager' - -const run = new Pdf() -const mediaManager = new MediaManager() - -fixture`PDF template settings - Header field test` - -test('should display \'Header\' field', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - - // Assertions - await t - .expect(fieldLabel('Header').exists).ok() - .expect(addMediaButton('gfpdf-settings-field-wrapper-header', 'Add Media').exists).ok() - .expect(run.headerWpEditorBox.exists).ok() -}) - -test('should check that upload media manager exist', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t.click(addMediaButton('gfpdf-settings-field-wrapper-header', 'Add Media')) - - // Assertions - await t - .expect(mediaManager.mediaModalContainer.exists).ok() - .expect(mediaManager.mediaCloseDialog.exists).ok() - .expect(mediaManagerTitle('Add media').exists).ok() - .expect(mediaManager.uploadFilesPanelLink.exists).ok() - .expect(mediaManager.mediaLibraryPanelLink.exists).ok() - .expect(mediaManager.dropInstructionsText.exists).ok() - .expect(mediaManager.selectFilesButton.exists).ok() - .expect(mediaManager.maxUploadSizeText.exists).ok() -}) - -test('should save added header data', async t => { - // Actions - await t.setTestSpeed(0.4) - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(addMediaButton('gfpdf-settings-field-wrapper-header', 'Add Media')) - .click(mediaManager.uploadFilesPanelLink) - .click(mediaManager.selectFilesButton) - .setFilesToUpload(mediaManager.uploadMediaFilesInputBox, mediaManager.backgroundImage) - .click(mediaManager.insertIntoPostButton) - .click(run.headerWpEditorBoxTextPanelLink) - .typeText(run.headerWpEditorBoxContentArea, 'test', { paste: true }) - .click(run.saveSettings) - - // Assertions - await t - .expect(run.headerWpEditorBoxContentArea.withText('/background-image-300x193.jpg').exists).ok() - .expect(run.headerWpEditorBoxContentArea.withText('test').exists).ok() -}) - -test('should delete/reset header field content', async t => { - // Actions & Assertions - await t.setTestSpeed(0.4) - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(addMediaButton('gfpdf-settings-field-wrapper-header', 'Add Media')) - .click(mediaManager.uploadedMediaFile) - .click(mediaManager.deleteFile) - .expect(mediaManager.uploadedMediaFile.count).eql(0) - .click(mediaManager.mediaCloseDialog) - .click(run.headerWpEditorBoxTextPanelLink) - .click(run.headerWpEditorBoxContentArea) - .pressKey('ctrl+a') - .pressKey('backspace') - .click(run.saveSettings) - .expect(run.headerWpEditorBoxContentArea.withText('/background-image-300x193.jpg').exists).notOk() - .expect(run.headerWpEditorBoxContentArea.withText('test').exists).notOk() -}) diff --git a/tests/e2e/pdf-settings/template/show-empty-fields-test.js b/tests/e2e/pdf-settings/template/show-empty-fields-test.js deleted file mode 100644 index 40a3f24b8..000000000 --- a/tests/e2e/pdf-settings/template/show-empty-fields-test.js +++ /dev/null @@ -1,28 +0,0 @@ -import { fieldLabel } from '../../utilities/page-model/helpers/field' -import Pdf from '../../utilities/page-model/helpers/pdf' - -const run = new Pdf() - -fixture`PDF template settings - Show empty fields field test` - -test('should display \'Show Empty Fields\' field', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - - // Assertions - await t - .expect(fieldLabel('Show Section Break Description').exists).ok() - .expect(run.showEmptyFieldsCheckbox.exists).ok() -}) - -test('should save toggled checkbox value', async t => { - // Actions & Assertions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(run.showEmptyFieldsCheckbox) - .click(run.saveSettings) - .expect(run.showEmptyFieldsCheckbox.checked).ok() - .click(run.showEmptyFieldsCheckbox) - .click(run.saveSettings) - .expect(run.showEmptyFieldsCheckbox.checked).notOk() -}) diff --git a/tests/e2e/pdf-settings/template/show-form-title-field.test.js b/tests/e2e/pdf-settings/template/show-form-title-field.test.js deleted file mode 100644 index d994e72fa..000000000 --- a/tests/e2e/pdf-settings/template/show-form-title-field.test.js +++ /dev/null @@ -1,28 +0,0 @@ -import { fieldLabel } from '../../utilities/page-model/helpers/field' -import Pdf from '../../utilities/page-model/helpers/pdf' - -const run = new Pdf() - -fixture`PDF template settings - Show form title field test` - -test('should display \'Show Form Title\' field', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - - // Assertions - await t - .expect(fieldLabel('Show Form Title').exists).ok() - .expect(run.showFormTitleCheckbox.exists).ok() -}) - -test('should save toggled checkbox value', async t => { - // Actions & Assertions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(run.showFormTitleCheckbox) - .click(run.saveSettings) - .expect(run.showFormTitleCheckbox.checked).notOk() - .click(run.showFormTitleCheckbox) - .click(run.saveSettings) - .expect(run.showFormTitleCheckbox.checked).ok() -}) diff --git a/tests/e2e/pdf-settings/template/show-html-fields-field.test.js b/tests/e2e/pdf-settings/template/show-html-fields-field.test.js deleted file mode 100644 index 1dddb9474..000000000 --- a/tests/e2e/pdf-settings/template/show-html-fields-field.test.js +++ /dev/null @@ -1,28 +0,0 @@ -import { fieldLabel } from '../../utilities/page-model/helpers/field' -import Pdf from '../../utilities/page-model/helpers/pdf' - -const run = new Pdf() - -fixture`PDF template settings - Show HTML fields field test` - -test('should display \'Show HTML Fields\' field', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - - // Assertions - await t - .expect(fieldLabel('Show HTML Fields').exists).ok() - .expect(run.showHtmlFieldsCheckbox.exists).ok() -}) - -test('should save toggled checkbox value', async t => { - // Actions & Assertions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(run.showHtmlFieldsCheckbox) - .click(run.saveSettings) - .expect(run.showHtmlFieldsCheckbox.checked).ok() - .click(run.showHtmlFieldsCheckbox) - .click(run.saveSettings) - .expect(run.showHtmlFieldsCheckbox.checked).notOk() -}) diff --git a/tests/e2e/pdf-settings/template/show-page-names-field.test.js b/tests/e2e/pdf-settings/template/show-page-names-field.test.js deleted file mode 100644 index 093e44ae9..000000000 --- a/tests/e2e/pdf-settings/template/show-page-names-field.test.js +++ /dev/null @@ -1,28 +0,0 @@ -import { fieldLabel } from '../../utilities/page-model/helpers/field' -import Pdf from '../../utilities/page-model/helpers/pdf' - -const run = new Pdf() - -fixture`PDF template settings - Show page names field test` - -test('should display \'Show Page Names\' field', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - - // Assertions - await t - .expect(fieldLabel('Show Page Names').exists).ok() - .expect(run.showPageNamesCheckbox.exists).ok() -}) - -test('should save toggled checkbox value', async t => { - // Actions & Assertions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(run.showPageNamesCheckbox) - .click(run.saveSettings) - .expect(run.showPageNamesCheckbox.checked).ok() - .click(run.showPageNamesCheckbox) - .click(run.saveSettings) - .expect(run.showPageNamesCheckbox.checked).notOk() -}) diff --git a/tests/e2e/pdf-settings/template/show-section-break-description-field.test.js b/tests/e2e/pdf-settings/template/show-section-break-description-field.test.js deleted file mode 100644 index ad6e6dfe9..000000000 --- a/tests/e2e/pdf-settings/template/show-section-break-description-field.test.js +++ /dev/null @@ -1,28 +0,0 @@ -import { fieldLabel } from '../../utilities/page-model/helpers/field' -import Pdf from '../../utilities/page-model/helpers/pdf' - -const run = new Pdf() - -fixture`PDF template settings - Show section break description field test` - -test('should display \'Show Section Break Description\' field', async t => { - // Actions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - - // Assertions - await t - .expect(fieldLabel('Show Section Break Description').exists).ok() - .expect(run.showSectionBreakDescriptionCheckbox.exists).ok() -}) - -test('should save toggled checkbox value', async t => { - // Actions & Assertions - await run.navigatePdfSection('gf_edit_forms&view=settings&subview=PDF&id=4') - await t - .click(run.showSectionBreakDescriptionCheckbox) - .click(run.saveSettings) - .expect(run.showSectionBreakDescriptionCheckbox.checked).ok() - .click(run.showSectionBreakDescriptionCheckbox) - .click(run.saveSettings) - .expect(run.showSectionBreakDescriptionCheckbox.checked).notOk() -}) diff --git a/tests/e2e/tabs/general-settings/background-processing-field.test.js b/tests/e2e/tabs/general-settings/background-processing-field.test.js deleted file mode 100644 index 6ca232445..000000000 --- a/tests/e2e/tabs/general-settings/background-processing-field.test.js +++ /dev/null @@ -1,29 +0,0 @@ -import { fieldHeaderTitle } from '../../utilities/page-model/helpers/field' -import General from '../../utilities/page-model/tabs/general-settings' - -const run = new General() - -fixture`General settings tab - Background processing field test` - -test('should display \'Background Processing\' field', async t => { - // Actions - await run.navigateSettingsTab('gf_settings&subview=PDF&tab=general#') - - // Assertions - await t - .expect(fieldHeaderTitle('Background Processing').exists).ok() - .expect(run.backgroundProcessingCheckbox.exists).ok() -}) - -test('should save toggled \'Background Processing\' value', async t => { - // Actions & Assertions - await run.navigateSettingsTab('gf_settings&subview=PDF&tab=general#') - await t - .click(run.backgroundProcessingCheckbox) - .click(run.saveSettings) - await t.expect(run.backgroundProcessingCheckbox.checked).ok() - await t - .click(run.backgroundProcessingCheckbox) - .click(run.saveSettings) - await t.expect(run.backgroundProcessingCheckbox.checked).notOk() -}) diff --git a/tests/e2e/tabs/general-settings/debug-mode-field.test.js b/tests/e2e/tabs/general-settings/debug-mode-field.test.js deleted file mode 100644 index 6844f1e5a..000000000 --- a/tests/e2e/tabs/general-settings/debug-mode-field.test.js +++ /dev/null @@ -1,28 +0,0 @@ -import { fieldHeaderTitle } from '../../utilities/page-model/helpers/field' -import General from '../../utilities/page-model/tabs/general-settings' - -const run = new General() - -fixture`General settings tab - Debug mode field test` - -test('should display \'Debug Mode\' field', async t => { - // Actions - await run.navigateSettingsTab('gf_settings&subview=PDF&tab=general#') - - // Assertions - await t - .expect(fieldHeaderTitle('Debug Mode').exists).ok() - .expect(run.debugModeCheckbox.exists).ok() -}) - -test('should save toggled \'Debug Mode\' value', async t => { - // Actions & Assertions - await run.navigateSettingsTab('gf_settings&subview=PDF&tab=general#') - await t - .click(run.debugModeCheckbox) - .click(run.saveSettings) - .expect(run.debugModeCheckbox.checked).ok() - .click(run.debugModeCheckbox) - .click(run.saveSettings) - .expect(run.debugModeCheckbox.checked).notOk() -}) diff --git a/tests/e2e/tabs/general-settings/default-font-color-field.test.js b/tests/e2e/tabs/general-settings/default-font-color-field.test.js deleted file mode 100644 index 5ad40e88b..000000000 --- a/tests/e2e/tabs/general-settings/default-font-color-field.test.js +++ /dev/null @@ -1,38 +0,0 @@ -import { Selector } from 'testcafe' -import { fieldLabel } from '../../utilities/page-model/helpers/field' -import General from '../../utilities/page-model/tabs/general-settings' - -const run = new General() - -fixture`General settings tab - Default font color field test` - -test('should display \'Default Font Color\' field', async t => { - // Selectors - const defaultFontColorWpColorPickerBox = Selector('#gfpdf-settings-field-wrapper-default_font_colour').find('[class^="iris-picker iris-border"]') - - // Actions - await run.navigateSettingsTab('gf_settings&subview=PDF&tab=general#') - await t.click(run.defaultFontColorSelectButton) - - // Assertions - await t - .expect(fieldLabel('Default Font Color').exists).ok() - .expect(run.defaultFontColorSelectButton.exists).ok() - .expect(run.defaultFontColorInputBox.exists).ok() - .expect(defaultFontColorWpColorPickerBox.exists).ok() -}) - -test('should save selected font color', async t => { - // Selectors - const colorBoxPicker = Selector('#gfpdf-settings-field-wrapper-default_font_colour').find('a').withAttribute('class', 'iris-palette') - - // Actions - await run.navigateSettingsTab('gf_settings&subview=PDF&tab=general#') - await t - .click(run.defaultFontColorSelectButton) - .click(colorBoxPicker.nth(4)) - .click(run.saveSettings) - - // Assertions - await t.expect(run.defaultFontColorInputBox.value).eql('#eeee22') -}) diff --git a/tests/e2e/tabs/general-settings/default-font-field.test.js b/tests/e2e/tabs/general-settings/default-font-field.test.js deleted file mode 100644 index da597fc22..000000000 --- a/tests/e2e/tabs/general-settings/default-font-field.test.js +++ /dev/null @@ -1,185 +0,0 @@ -import { - fieldLabel, - dropdownOptionGroup, - dropdownOption -} from '../../utilities/page-model/helpers/field' -import General from '../../utilities/page-model/tabs/general-settings' -import FontManager from '../../utilities/page-model/helpers/font-manager' - -const run = new General() -const fontManager = new FontManager() - -fixture`General settings tab - Default font field test` - -test('should display \'Default Font\' field', async t => { - // Actions - await run.navigateSettingsTab('gf_settings&subview=PDF&tab=general#') - - // Assertions - await t - .expect(fieldLabel('Default Font').exists).ok() - .expect(run.defaultFontSelectBox.exists).ok() - .expect(fontManager.advancedButton.exists).ok() -}) - -test('should display a dropdown of default fonts option', async t => { - // Actions - await run.navigateSettingsTab('gf_settings&subview=PDF&tab=general#') - await t.click(run.defaultFontSelectBox) - - // Assertions - await t - .expect(dropdownOptionGroup('Unicode').exists).ok() - .expect(dropdownOption('Dejavu Sans Condensed').exists).ok() - .expect(dropdownOption('Dejavu Sans').exists).ok() - .expect(dropdownOptionGroup('Indic').exists).ok() - .expect(dropdownOption('Lohit Kannada').exists).ok() - .expect(dropdownOption('Pothana2000').exists).ok() - .expect(dropdownOptionGroup('Arabic').exists).ok() - .expect(dropdownOption('XB Riyaz').exists).ok() - .expect(dropdownOption('Lateef').exists).ok() - .expect(dropdownOptionGroup('Chinese, Japanese, Korean').exists).ok() - .expect(dropdownOption('Sun Ext').exists).ok() - .expect(dropdownOption('Un Batang (Korean)').exists).ok() - .expect(dropdownOptionGroup('Other').exists).ok() - .expect(dropdownOption('Estrangelo Edessa (Syriac)').exists).ok() - .expect(dropdownOption('Kaputa (Sinhala)').exists).ok() -}) - -test('should save selected font', async t => { - // Actions - await run.navigateSettingsTab('gf_settings&subview=PDF&tab=general#') - await t - .click(run.defaultFontSelectBox) - .click(dropdownOption('Pothana2000')) - .click(run.defaultFontSelectBox) - .click(dropdownOption('Lohit Kannada')) - .click(run.saveSettings) - - // Assertions - await t.expect(run.defaultFontSelectBox.value).eql('lohitkannada') -}) - -test('should check that font manager popup exist', async t => { - // Actions - await run.navigateSettingsTab('gf_settings&subview=PDF&tab=general#') - await t.click(fontManager.advancedButton) - - // Assertions - await t - .expect(fontManager.popupHeaderText.exists).ok() - .expect(fontManager.searchBar.exists).ok() - .expect(fontManager.fontListColumn.exists).ok() - .expect(fontManager.addFontColumn.exists).ok() -}) - -test('should display font manager error validation', async t => { - // Actions - await run.navigateSettingsTab('gf_settings&subview=PDF&tab=general#') - await t - .click(fontManager.advancedButton) - .click(fontManager.addFontButton) - - // Assertions - await t - .expect(fontManager.fontNameFieldErrorValidation.exists).ok() - .expect(fontManager.fontNameFieldErrorValidationMessage.exists).ok() - .expect(fontManager.dropzoneRequiredRegularField.exists).ok() - .expect(fontManager.dropzoneErrorValidationMessage.exists).ok() - .expect(fontManager.addUpdatePanelGeneralErrorValidationMessage.exists).ok() -}) - -test('should successfully add new font', async t => { - // Actions - await run.navigateSettingsTab('gf_settings&subview=PDF&tab=general#') - await t - .click(fontManager.advancedButton) - .typeText(fontManager.addFontNameInputField, 'Roboto', { paste: true }) - .setFilesToUpload(fontManager.addNewFontRegular, fontManager.robotoFontRegular) - .click(fontManager.addFontButton) - - // Assertions - await t - .expect(fontManager.fontListItem.count).eql(1) - .expect(fontManager.successMessage.exists).ok() -}) - -test('should successfully check toggled state for disabled \'Update Font\' button', async t => { - // Actions & Assertions - await run.navigateSettingsTab('gf_settings&subview=PDF&tab=general#') - await t - .click(fontManager.advancedButton) - .click(fontManager.fontListItem.nth(0)) - .expect(fontManager.updateFontButton.hasAttribute('disabled')).ok() - .typeText(fontManager.updateFontNameInputField, ' new', { paste: true }) - .expect(fontManager.updateFontButton.hasAttribute('disabled')).notOk() -}) - -test('should successfully close \'update font\' panel using cancel button', async t => { - // Actions - await run.navigateSettingsTab('gf_settings&subview=PDF&tab=general#') - await t - .click(fontManager.advancedButton) - .click(fontManager.fontListItem.nth(0)) - .click(fontManager.cancelButton) - - // Assertions - await t.expect(fontManager.updateFontPanel.exists).notOk() -}) - -test('should successfully perform font search', async t => { - // Actions - await run.navigateSettingsTab('gf_settings&subview=PDF&tab=general#') - await t - .click(fontManager.advancedButton) - .typeText(fontManager.searchBar, 'Roboto', { paste: true }) - - // Assertions - await t.expect(fontManager.fontListItem.count).eql(1) -}) - -test('should successfully edit existing font', async t => { - // Actions - await run.navigateSettingsTab('gf_settings&subview=PDF&tab=general#') - await t - .click(fontManager.advancedButton) - .click(fontManager.fontListItem.nth(0)) - .click(fontManager.updateFontNameInputField) - .pressKey('ctrl+a') - .pressKey('backspace') - .typeText(fontManager.updateFontNameInputField, 'Roboto 2', { paste: true }) - .setFilesToUpload(fontManager.addNewFontItalics, fontManager.robotoFontItalics) - .setFilesToUpload(fontManager.addNewFontBold, fontManager.robotoFontBold) - .setFilesToUpload(fontManager.addNewFontBoldItalics, fontManager.robotoFontBoldItalics) - .click(fontManager.updateFontButton) - - // Assertions - await t - .expect(fontManager.successMessage.exists).ok() - .expect(fontManager.fontName.withText('Roboto 2').exists).ok() - .expect(fontManager.fontVariantsCheck.count).eql(4) -}) - -test('should successfully delete font', async t => { - // Actions - await run.navigateSettingsTab('gf_settings&subview=PDF&tab=general#') - await t - .click(fontManager.advancedButton) - .click(fontManager.fontListItem.nth(0).find('[class^="dashicons dashicons-trash"]')) - - // Assertions - await t - .expect(fontManager.fontListItem.count).eql(0) - .expect(fontManager.fontListEmptyMessage.exists).ok() -}) - -test('should be able to close font manager popup', async t => { - // Actions - await run.navigateSettingsTab('gf_settings&subview=PDF&tab=general#') - await t - .click(fontManager.advancedButton) - .click(fontManager.closeDialog) - - // Assertions - await t.expect(fontManager.fontManagerPopup.exists).notOk() -}) diff --git a/tests/e2e/tabs/general-settings/default-font-size-field.test.js b/tests/e2e/tabs/general-settings/default-font-size-field.test.js deleted file mode 100644 index d6de7190f..000000000 --- a/tests/e2e/tabs/general-settings/default-font-size-field.test.js +++ /dev/null @@ -1,31 +0,0 @@ -import { fieldLabel } from '../../utilities/page-model/helpers/field' -import General from '../../utilities/page-model/tabs/general-settings' - -const run = new General() - -fixture`General settings tab - Default font size field test` - -test('should display \'Default Font Size\' field', async t => { - // Actions - await run.navigateSettingsTab('gf_settings&subview=PDF&tab=general#') - - // Assertions - await t - .expect(fieldLabel('Default Font Size').exists).ok() - .expect(run.defaultFontSizeInputBox.exists).ok() -}) - -test('should save selected font size', async t => { - // Actions - await run.navigateSettingsTab('gf_settings&subview=PDF&tab=general#') - await t.click(run.defaultFontSizeInputBox) - await t - .pressKey('ctrl+a') - .pressKey('backspace') - await t - .typeText(run.defaultFontSizeInputBox, '15', { paste: true }) - .click(run.saveSettings) - - // Assertions - await t.expect(run.defaultFontSizeInputBox.value).eql('15') -}) diff --git a/tests/e2e/tabs/general-settings/default-owner-restrictions-field.test.js b/tests/e2e/tabs/general-settings/default-owner-restrictions-field.test.js deleted file mode 100644 index e73b6b753..000000000 --- a/tests/e2e/tabs/general-settings/default-owner-restrictions-field.test.js +++ /dev/null @@ -1,30 +0,0 @@ -import { fieldLabel } from '../../utilities/page-model/helpers/field' -import General from '../../utilities/page-model/tabs/general-settings' - -const run = new General() - -fixture`General settings tab - Default owner restrictions field test` - -test('should display \'Default Owner Restrictions\' field', async t => { - // Actions - await run.navigateSettingsTab('gf_settings&subview=PDF&tab=general#') - - // Assertions - await t - .expect(fieldLabel('Default Owner Restrictions').exists).ok() - .expect(run.defaultOwnerRestrictionsCheckbox.exists).ok() -}) - -test('should save toggled \'Default Owner Restrictions\' value', async t => { - // Actions & Assertions - await run.navigateSettingsTab('gf_settings&subview=PDF&tab=general#') - await t - .click(run.securityCollapsiblePanel) - .click(run.defaultOwnerRestrictionsCheckbox) - .click(run.saveSettings) - .expect(run.defaultOwnerRestrictionsCheckbox.checked).ok() - .click(run.securityCollapsiblePanel) - .click(run.defaultOwnerRestrictionsCheckbox) - .click(run.saveSettings) - .expect(run.defaultOwnerRestrictionsCheckbox.checked).notOk() -}) diff --git a/tests/e2e/tabs/general-settings/default-paper-size-field.test.js b/tests/e2e/tabs/general-settings/default-paper-size-field.test.js deleted file mode 100644 index 73d46a85d..000000000 --- a/tests/e2e/tabs/general-settings/default-paper-size-field.test.js +++ /dev/null @@ -1,89 +0,0 @@ -import { - fieldLabel, - selectBox, - dropdownOptionGroup, - dropdownOption -} from '../../utilities/page-model/helpers/field' -import General from '../../utilities/page-model/tabs/general-settings' - -const run = new General() - -fixture`General settings tab - Default paper size field test` - -test('should display \'Default Paper Size\' field', async t => { - // Actions - await run.navigateSettingsTab('gf_settings&subview=PDF&tab=general#') - - // Assertions - await t - .expect(fieldLabel('Default Paper Size').exists).ok() - .expect(run.defaultPaperSizeSelectBox.exists).ok() -}) - -test('should display a dropdown of paper sizes option', async t => { - // Actions - await run.navigateSettingsTab('gf_settings&subview=PDF&tab=general#') - await t.click(run.defaultPaperSizeSelectBox) - - // Assertions - await t - .expect(dropdownOptionGroup('Common Sizes').exists).ok() - .expect(dropdownOption('A4 (210 x 297mm)').exists).ok() - .expect(dropdownOption('Letter (8.5 x 11in)').exists).ok() - .expect(dropdownOption('Custom Paper Size').exists).ok() - .expect(dropdownOptionGroup('"A" Sizes').exists).ok() - .expect(dropdownOption('A0 (841 x 1189mm)').exists).ok() - .expect(dropdownOption('A1 (594 x 841mm)').exists).ok() - .expect(dropdownOptionGroup('"B" Sizes').exists).ok() - .expect(dropdownOption('B0 (1414 x 1000mm)').exists).ok() - .expect(dropdownOption('B1 (1000 x 707mm)').exists).ok() - .expect(dropdownOptionGroup('"C" Sizes').exists).ok() - .expect(dropdownOption('C0 (1297 x 917mm)').exists).ok() - .expect(dropdownOption('C1 (917 x 648mm)').exists).ok() - .expect(dropdownOptionGroup('"RA" and "SRA" Sizes').exists).ok() - .expect(dropdownOption('RA0 (860 x 1220mm)').exists).ok() - .expect(dropdownOption('RA1 (610 x 860mm)').exists).ok() -}) - -test('should save selected paper size', async t => { - // Actions - await run.navigateSettingsTab('gf_settings&subview=PDF&tab=general#') - await t.click(run.defaultPaperSizeSelectBox) - await t.click(dropdownOption('Letter (8.5 x 11in)')) - await t.click(run.saveSettings) - - // Assertions - await t.expect(run.defaultPaperSizeSelectBox.value).eql('LETTER') -}) - -test('should save selected custom paper size', async t => { - // Selectors - const widthInputBox = selectBox('regular-text gfpdf_settings_default_custom_pdf_size', 'gfpdf_settings[default_custom_pdf_size]_width') - const heightInputBox = selectBox('regular-text gfpdf_settings_default_custom_pdf_size', 'gfpdf_settings[default_custom_pdf_size]_height') - const measurementInputBox = selectBox('gfpdf_settings_default_custom_pdf_size ', 'gfpdf_settings[default_custom_pdf_size]_measurement') - - // Actions - await run.navigateSettingsTab('gf_settings&subview=PDF&tab=general#') - await t - .click(run.defaultPaperSizeSelectBox) - .click(dropdownOption('Custom Paper Size')) - .click(widthInputBox) - .pressKey('ctrl+a') - .pressKey('backspace') - .typeText(widthInputBox, '2', { paste: true }) - .click(heightInputBox) - .pressKey('ctrl+a') - .pressKey('backspace') - .typeText(heightInputBox, '4', { paste: true }) - .click(measurementInputBox) - .click(dropdownOption('inches')) - .click(run.saveSettings) - - // Assertions - await t - .expect(run.defaultPaperSizeSelectBox.value).eql('CUSTOM') - .expect(run.customPaperSizeLabel.exists).ok() - .expect(widthInputBox.value).eql('2') - .expect(heightInputBox.value).eql('4') - .expect(measurementInputBox.value).eql('inches') -}) diff --git a/tests/e2e/tabs/general-settings/default-template-field.test.js b/tests/e2e/tabs/general-settings/default-template-field.test.js deleted file mode 100644 index b868c44c0..000000000 --- a/tests/e2e/tabs/general-settings/default-template-field.test.js +++ /dev/null @@ -1,240 +0,0 @@ -import { Selector } from 'testcafe'; -import { - fieldLabel, - button, - dropdownOptionGroup, - dropdownOption, - templateDetails, -} from '../../utilities/page-model/helpers/field'; -import TemplateManager from '../../utilities/page-model/helpers/template-manager'; -import General from '../../utilities/page-model/tabs/general-settings'; - -const templateManager = new TemplateManager(); -const run = new General(); - -fixture`General settings tab - Default template field test`; - -test( "should display 'Default Template' field", async ( t ) => { - // Actions - await run.navigateSettingsTab( 'gf_settings&subview=PDF&tab=general#' ); - - // Assertions - await t - .expect( fieldLabel( 'Default Template' ).exists ) - .ok() - .expect( run.defaultTemplateSelectBox.exists ) - .ok() - .expect( templateManager.advancedButton.exists ) - .ok(); -} ); - -test( 'should display the core templates dropdown option', async ( t ) => { - // Actions - await run.navigateSettingsTab( 'gf_settings&subview=PDF&tab=general#' ); - - // Assertions - await t - .expect( dropdownOptionGroup( 'Core' ).exists ) - .ok() - .expect( dropdownOption( 'Blank Slate' ).exists ) - .ok() - .expect( dropdownOption( 'Focus Gravity' ).exists ) - .ok() - .expect( dropdownOption( 'Rubix' ).exists ) - .ok() - .expect( dropdownOption( 'Zadani' ).exists ) - .ok(); -} ); - -test( 'should save selected template', async ( t ) => { - // Actions - await run.navigateSettingsTab( 'gf_settings&subview=PDF&tab=general#' ); - await t - .click( run.defaultTemplateSelectBox ) - .click( dropdownOption( 'Rubix' ) ) - .click( run.saveSettings ) - .wait( 500 ); - - // Assertions - await t.expect( run.defaultTemplateSelectBox.value ).eql( 'rubix' ); -} ); - -test( 'should check that template manager popup exist', async ( t ) => { - // Actions - await run.navigateSettingsTab( 'gf_settings&subview=PDF&tab=general#' ); - await t.click( templateManager.advancedButton ); - - // Assertions - await t - .expect( templateManager.popupHeaderText.exists ) - .ok() - .expect( templateManager.closeDialog().exists ) - .ok() - .expect( templateManager.searchBar.exists ) - .ok() - .expect( templateManager.individualThemeBox.exists ) - .ok() - .expect( templateManager.themeScreenshot.exists ) - .ok() - .expect( templateManager.themeAuthor.exists ) - .ok() - .expect( templateManager.themeName.exists ) - .ok() - .expect( templateManager.themeSelectButton.exists ) - .ok() - .expect( templateManager.themeDetailsLink.exists ) - .ok() - .expect( templateManager.dropZoneBox.exists ) - .ok() - .expect( templateManager.addNewTemplateButton.exists ) - .ok() - .expect( templateManager.installationMessage.innerText ) - .contains( - 'If you have a PDF template in .zip format you may install it here. You can also update an existing PDF template (this will override any changes you have made).' - ); -} ); - -test( 'should display individual template details', async ( t ) => { - // Selectors - const imageScreenshot = Selector( '.screenshot' ) - .find( 'img' ) - .getAttribute( 'src' ); - - // Actions - await run.navigateSettingsTab( 'gf_settings&subview=PDF&tab=general#' ); - await t - .click( templateManager.advancedButton ) - .click( templateManager.focusGravityTemplateDetails ); - - // Assertions - await t - .expect( imageScreenshot ) - .contains( 'focus-gravity.png' ) - .expect( templateDetails( 'theme-name', 'Focus Gravity' ).exists ) - .ok() - .expect( templateDetails( 'theme-version', 'Version: ' ).exists ) - .ok() - .expect( templateDetails( 'theme-author', 'Gravity PDF' ).exists ) - .ok() - .expect( templateDetails( 'theme-author', 'Group: Core' ).exists ) - .ok() - .expect( - templateDetails( - 'theme-description', - "Focus Gravity providing a classic layout which epitomises Gravity Forms Print Preview. It's the familiar layout you've come to love. Through the Template tab you can control the PDF header and footer, change the background color or image, and show or hide the form title, page names, HTML fields and the Section Break descriptions." - ).exists - ) - .ok() - .expect( - templateDetails( - 'theme-tags', - 'Tags: Header, Footer, Background, Optional HTML Fields, Optional Page Fields, Combined Row, Alternate Colors' - ).exists - ) - .ok(); -} ); - -test( 'should navigate to next and previous template', async ( t ) => { - // Actions & Assertions - await run.navigateSettingsTab( 'gf_settings&subview=PDF&tab=general#' ); - await t - .click( run.defaultTemplateSelectBox ) - .click( dropdownOption( 'Blank Slate' ) ) - .click( templateManager.advancedButton ) - .click( templateManager.focusGravityTemplateDetails ) - .click( button( 'Show next template' ) ) - .expect( templateManager.rubixTemplate.exists ) - .ok() - .click( button( 'Show previous template' ) ) - .expect( templateManager.focusGravityTemplate.exists ) - .ok() - .pressKey( 'right' ) - .expect( templateManager.rubixTemplate.exists ) - .ok() - .pressKey( 'left' ) - .expect( templateManager.focusGravityTemplate.exists ) - .ok(); -} ); - -test( 'should display popup template manager that can be close', async ( t ) => { - // Actions & Assertions - await run.navigateSettingsTab( 'gf_settings&subview=PDF&tab=general#' ); - await t - .click( templateManager.advancedButton ) - .click( templateManager.closeDialog() ) - .click( templateManager.advancedButton ) - .pressKey( 'esc' ) - .expect( templateManager.templatePopupBox.exists ) - .notOk(); -} ); - -test( 'should successfully search for template', async ( t ) => { - // Actions - await run.navigateSettingsTab( 'gf_settings&subview=PDF&tab=general#' ); - await t - .click( templateManager.advancedButton ) - .typeText( templateManager.templateSearchbar, 'rubix', { - paste: true, - } ); - - // Assertions - await t - .expect( templateManager.templateSearchbar.exists ) - .ok() - .expect( templateManager.searchResult.count ) - .eql( 1 ); -} ); - -test( 'should successfully upload new template', async ( t ) => { - // Actions - await run.navigateSettingsTab( 'gf_settings&subview=PDF&tab=general#' ); - await t - .click( templateManager.advancedButton ) - .setFilesToUpload( - templateManager.addNewTemplateButton, - templateManager.testTemplate - ); - - // Assertions - await t - .expect( - templateDetails( - 'notice inline', - 'Template successfully installed' - ).exists - ) - .ok() - .expect( templateManager.imageScreenshot.exists ) - .ok() - .expect( templateDetails( 'theme-author', 'Custom' ).exists ) - .ok() - .expect( templateDetails( 'theme-name', 'Test Template' ).exists ) - .ok() - .expect( - templateDetails( - 'notice inline', - 'PDF Template(s) Successfully Installed / Updated' - ).exists - ) - .ok(); -} ); - -test( 'should successfully delete new added template', async ( t ) => { - // Actions - await run.navigateSettingsTab( 'gf_settings&subview=PDF&tab=general#' ); - await t - .click( templateManager.advancedButton ) - .click( templateManager.testTemplateDetailsLink ) - .click( templateManager.deleteButton ); - - // Assertions - await t - .expect( templateManager.imageScreenshot.exists ) - .notOk() - .expect( - templateDetails( 'theme-author', 'Universal (Premium)' ).exists - ) - .notOk() - .expect( templateDetails( 'theme-name', 'Cellulose' ).exists ) - .notOk(); -} ); diff --git a/tests/e2e/tabs/general-settings/entry-view-field.test.js b/tests/e2e/tabs/general-settings/entry-view-field.test.js deleted file mode 100644 index 363320edc..000000000 --- a/tests/e2e/tabs/general-settings/entry-view-field.test.js +++ /dev/null @@ -1,64 +0,0 @@ -import { Selector } from 'testcafe' -import { fieldHeaderTitle } from '../../utilities/page-model/helpers/field' -import General from '../../utilities/page-model/tabs/general-settings' - -const run = new General() - -fixture`General settings tab - Entry view field test` - -test('should display \'Entry View\' field', async t => { - // Actions - await run.navigateSettingsTab('gf_settings&subview=PDF&tab=general#') - - // Assertions - await t - .expect(fieldHeaderTitle('Entry View').exists).ok() - .expect(run.entryViewViewOption.exists).ok() - .expect(run.entryViewDownlaodOption.exists).ok() -}) - -test('should save toggled value for \'Entry View\' field', async t => { - // Actions & Assertions - await run.navigateSettingsTab('gf_settings&subview=PDF&tab=general#') - await t - .click(run.entryViewDownlaodOption) - .click(run.saveSettings) - .expect(run.entryViewViewOption.checked).notOk() - .expect(run.entryViewDownlaodOption.checked).ok() - .click(run.entryViewViewOption) - .click(run.saveSettings) - .expect(run.entryViewDownlaodOption.checked).notOk() - .expect(run.entryViewViewOption.checked).ok() -}) - -test('should display "Download PDF" as an option on the Entry List page instead of "View PDF" when "Download" is selected', async t => { - // Selectors - const downloadPdfLink = Selector('a').withText('Download PDF') - - // Actions - await run.navigateSettingsTab('gf_settings&subview=PDF&tab=general#') - await t - .click(run.entryViewDownlaodOption) - .click(run.saveSettings) - await run.navigatePdfEntries('gf_entries&id=3') - await t.hover(run.viewEntryItem) - - // Assertions - await t.expect(downloadPdfLink.exists).ok() -}) - -test('should display "View PDF" as an option on the Entry List page instead of "Download PDF" when "View" is selected', async t => { - // Selectors - const viewPdfLink = Selector('a').withText('View PDF') - - // Actions - await run.navigateSettingsTab('gf_settings&subview=PDF&tab=general#') - await t - .click(run.entryViewViewOption) - .click(run.saveSettings) - await run.navigatePdfEntries('gf_entries&id=3') - await t.hover(run.viewEntryItem) - - // Assertions - await t.expect(viewPdfLink.exists).ok() -}) diff --git a/tests/e2e/tabs/general-settings/logged-out-timeout-field.test.js b/tests/e2e/tabs/general-settings/logged-out-timeout-field.test.js deleted file mode 100644 index 9429b07e2..000000000 --- a/tests/e2e/tabs/general-settings/logged-out-timeout-field.test.js +++ /dev/null @@ -1,31 +0,0 @@ -import { fieldLabel } from '../../utilities/page-model/helpers/field' -import General from '../../utilities/page-model/tabs/general-settings' - -const run = new General() - -fixture`General settings tab - Logged out timeout field test` - -test('should display \'Logged Out Timeout\' field', async t => { - // Actions - await run.navigateSettingsTab('gf_settings&subview=PDF&tab=general#') - - // Assertions - await t - .expect(fieldLabel('Logged Out Timeout').exists).ok() - .expect(run.loggedOutTimeoutInputBox.exists).ok() -}) - -test('should save updated value for time limit', async t => { - // Actions - await run.navigateSettingsTab('gf_settings&subview=PDF&tab=general#') - await t - .click(run.securityCollapsiblePanel) - .click(run.loggedOutTimeoutInputBox) - .pressKey('ctrl+a') - .pressKey('backspace') - .typeText(run.loggedOutTimeoutInputBox, '34', { paste: true }) - .click(run.saveSettings) - - // Assertions - await t.expect(run.loggedOutTimeoutInputBox.value).eql('34') -}) diff --git a/tests/e2e/tabs/general-settings/reverse-text-rtl-field.test.js b/tests/e2e/tabs/general-settings/reverse-text-rtl-field.test.js deleted file mode 100644 index 1b164d252..000000000 --- a/tests/e2e/tabs/general-settings/reverse-text-rtl-field.test.js +++ /dev/null @@ -1,28 +0,0 @@ -import { fieldLabel } from '../../utilities/page-model/helpers/field' -import General from '../../utilities/page-model/tabs/general-settings' - -const run = new General() - -fixture`General settings tab - Reverse text (RTL) field test` - -test('should display \'Reverse Text (RTL)\' field', async t => { - // Actions - await run.navigateSettingsTab('gf_settings&subview=PDF&tab=general#') - - // Assertions - await t - .expect(fieldLabel('Reverse Text (RTL)').exists).ok() - .expect(run.reverseTextRtlCheckbox.exists).ok() -}) - -test('should save toggled checkbox value', async t => { - // Actions & Assertions - await run.navigateSettingsTab('gf_settings&subview=PDF&tab=general#') - await t - .click(run.reverseTextRtlCheckbox) - .click(run.saveSettings) - .expect(run.reverseTextRtlCheckbox.checked).ok() - .click(run.reverseTextRtlCheckbox) - .click(run.saveSettings) - .expect(run.reverseTextRtlCheckbox.checked).notOk() -}) diff --git a/tests/e2e/tabs/general-settings/user-restriction-field.test.js b/tests/e2e/tabs/general-settings/user-restriction-field.test.js deleted file mode 100644 index f1ea78ee3..000000000 --- a/tests/e2e/tabs/general-settings/user-restriction-field.test.js +++ /dev/null @@ -1,363 +0,0 @@ -import { fieldLabel, userRestrictionOption } from '../../utilities/page-model/helpers/field' -import General from '../../utilities/page-model/tabs/general-settings' - -const run = new General() - -fixture`General settings tab - User restriction field test` - -test('should display \'User Restriction\' field', async t => { - // Actions - await run.navigateSettingsTab('gf_settings&subview=PDF&tab=general#') - - // Assertions - await t - .expect(fieldLabel('User Restriction').exists).ok() - .expect(userRestrictionOption('gravityforms_edit_forms').exists).ok() - .expect(userRestrictionOption('gravityforms_delete_forms').exists).ok() - .expect(userRestrictionOption('gravityforms_create_form').exists).ok() - .expect(userRestrictionOption('gravityforms_view_entries').exists).ok() - .expect(userRestrictionOption('gravityforms_edit_entries').exists).ok() - .expect(userRestrictionOption('gravityforms_delete_entries').exists).ok() - .expect(userRestrictionOption('gravityforms_view_settings').exists).ok() - .expect(userRestrictionOption('gravityforms_edit_settings').exists).ok() - .expect(userRestrictionOption('gravityforms_export_entries').exists).ok() - .expect(userRestrictionOption('gravityforms_uninstall').exists).ok() - .expect(userRestrictionOption('gravityforms_view_entry_notes').exists).ok() - .expect(userRestrictionOption('gravityforms_edit_entry_notes').exists).ok() - .expect(userRestrictionOption('gravityforms_view_updates').exists).ok() - .expect(userRestrictionOption('gravityforms_view_addons').exists).ok() - .expect(userRestrictionOption('gravityforms_preview_forms').exists).ok() - .expect(userRestrictionOption('gravityforms_system_status').exists).ok() - .expect(userRestrictionOption('gravityforms_logging').exists).ok() - .expect(userRestrictionOption('gravityforms_api_settings').exists).ok() -}) - -test('should save selected user restriction capabilities', async t => { - // Actions && Assertions - await run.navigateSettingsTab('gf_settings&subview=PDF&tab=general#') - await t - .click(run.securityCollapsiblePanel) - .click(run.userRestrictionOption.nth(0)) - .click(run.userRestrictionOption.nth(1)) - .click(run.userRestrictionOption.nth(2)) - .click(run.userRestrictionOption.nth(4)) - .click(run.userRestrictionOption.nth(5)) - .click(run.userRestrictionOption.nth(6)) - .click(run.userRestrictionOption.nth(7)) - .click(run.userRestrictionOption.nth(8)) - .click(run.userRestrictionOption.nth(9)) - .click(run.userRestrictionOption.nth(10)) - .click(run.userRestrictionOption.nth(11)) - .click(run.userRestrictionOption.nth(12)) - .click(run.userRestrictionOption.nth(13)) - .click(run.userRestrictionOption.nth(14)) - .click(run.userRestrictionOption.nth(15)) - .click(run.userRestrictionOption.nth(16)) - .click(run.userRestrictionOption.nth(17)) - .click(run.userRestrictionOption.nth(18)) - .click(run.userRestrictionOption.nth(19)) - .click(run.userRestrictionOption.nth(20)) - .click(run.userRestrictionOption.nth(21)) - .click(run.userRestrictionOption.nth(22)) - .click(run.userRestrictionOption.nth(23)) - .click(run.userRestrictionOption.nth(24)) - .click(run.userRestrictionOption.nth(25)) - .click(run.userRestrictionOption.nth(26)) - .click(run.userRestrictionOption.nth(27)) - .click(run.userRestrictionOption.nth(28)) - .click(run.userRestrictionOption.nth(29)) - .click(run.userRestrictionOption.nth(30)) - .click(run.userRestrictionOption.nth(31)) - .click(run.userRestrictionOption.nth(32)) - .click(run.userRestrictionOption.nth(33)) - .click(run.userRestrictionOption.nth(34)) - .click(run.userRestrictionOption.nth(35)) - .click(run.userRestrictionOption.nth(36)) - .click(run.userRestrictionOption.nth(37)) - .click(run.userRestrictionOption.nth(38)) - .click(run.userRestrictionOption.nth(39)) - .click(run.userRestrictionOption.nth(40)) - .click(run.userRestrictionOption.nth(41)) - .click(run.userRestrictionOption.nth(42)) - .click(run.userRestrictionOption.nth(43)) - .click(run.userRestrictionOption.nth(44)) - .click(run.userRestrictionOption.nth(45)) - .click(run.userRestrictionOption.nth(46)) - .click(run.userRestrictionOption.nth(47)) - .click(run.userRestrictionOption.nth(48)) - .click(run.userRestrictionOption.nth(49)) - .click(run.userRestrictionOption.nth(50)) - .click(run.userRestrictionOption.nth(51)) - .click(run.userRestrictionOption.nth(52)) - .click(run.userRestrictionOption.nth(53)) - .click(run.userRestrictionOption.nth(54)) - .click(run.userRestrictionOption.nth(55)) - .click(run.userRestrictionOption.nth(56)) - .click(run.userRestrictionOption.nth(57)) - .click(run.userRestrictionOption.nth(58)) - .click(run.userRestrictionOption.nth(59)) - .click(run.userRestrictionOption.nth(60)) - .click(run.userRestrictionOption.nth(61)) - .click(run.userRestrictionOption.nth(62)) - .click(run.userRestrictionOption.nth(63)) - .click(run.userRestrictionOption.nth(64)) - .click(run.userRestrictionOption.nth(65)) - .click(run.userRestrictionOption.nth(66)) - .click(run.userRestrictionOption.nth(67)) - .click(run.userRestrictionOption.nth(68)) - .click(run.userRestrictionOption.nth(69)) - .click(run.userRestrictionOption.nth(70)) - .click(run.userRestrictionOption.nth(71)) - .click(run.userRestrictionOption.nth(72)) - .click(run.userRestrictionOption.nth(73)) - .click(run.userRestrictionOption.nth(74)) - .click(run.userRestrictionOption.nth(75)) - .click(run.userRestrictionOption.nth(76)) - .click(run.userRestrictionOption.nth(77)) - .click(run.userRestrictionOption.nth(78)) - .click(run.saveSettings) - .expect(run.userRestrictionOption.nth(0).checked).ok() - .expect(run.userRestrictionOption.nth(1).checked).ok() - .expect(run.userRestrictionOption.nth(2).checked).ok() - .expect(run.userRestrictionOption.nth(3).checked).ok() - .expect(run.userRestrictionOption.nth(4).checked).ok() - .expect(run.userRestrictionOption.nth(5).checked).ok() - .expect(run.userRestrictionOption.nth(6).checked).ok() - .expect(run.userRestrictionOption.nth(7).checked).ok() - .expect(run.userRestrictionOption.nth(8).checked).ok() - .expect(run.userRestrictionOption.nth(9).checked).ok() - .expect(run.userRestrictionOption.nth(10).checked).ok() - .expect(run.userRestrictionOption.nth(11).checked).ok() - .expect(run.userRestrictionOption.nth(12).checked).ok() - .expect(run.userRestrictionOption.nth(13).checked).ok() - .expect(run.userRestrictionOption.nth(14).checked).ok() - .expect(run.userRestrictionOption.nth(15).checked).ok() - .expect(run.userRestrictionOption.nth(16).checked).ok() - .expect(run.userRestrictionOption.nth(17).checked).ok() - .expect(run.userRestrictionOption.nth(18).checked).ok() - .expect(run.userRestrictionOption.nth(19).checked).ok() - .expect(run.userRestrictionOption.nth(20).checked).ok() - .expect(run.userRestrictionOption.nth(21).checked).ok() - .expect(run.userRestrictionOption.nth(22).checked).ok() - .expect(run.userRestrictionOption.nth(23).checked).ok() - .expect(run.userRestrictionOption.nth(24).checked).ok() - .expect(run.userRestrictionOption.nth(25).checked).ok() - .expect(run.userRestrictionOption.nth(26).checked).ok() - .expect(run.userRestrictionOption.nth(27).checked).ok() - .expect(run.userRestrictionOption.nth(28).checked).ok() - .expect(run.userRestrictionOption.nth(29).checked).ok() - .expect(run.userRestrictionOption.nth(30).checked).ok() - .expect(run.userRestrictionOption.nth(31).checked).ok() - .expect(run.userRestrictionOption.nth(32).checked).ok() - .expect(run.userRestrictionOption.nth(33).checked).ok() - .expect(run.userRestrictionOption.nth(34).checked).ok() - .expect(run.userRestrictionOption.nth(35).checked).ok() - .expect(run.userRestrictionOption.nth(36).checked).ok() - .expect(run.userRestrictionOption.nth(37).checked).ok() - .expect(run.userRestrictionOption.nth(38).checked).ok() - .expect(run.userRestrictionOption.nth(39).checked).ok() - .expect(run.userRestrictionOption.nth(40).checked).ok() - .expect(run.userRestrictionOption.nth(41).checked).ok() - .expect(run.userRestrictionOption.nth(42).checked).ok() - .expect(run.userRestrictionOption.nth(43).checked).ok() - .expect(run.userRestrictionOption.nth(44).checked).ok() - .expect(run.userRestrictionOption.nth(45).checked).ok() - .expect(run.userRestrictionOption.nth(46).checked).ok() - .expect(run.userRestrictionOption.nth(47).checked).ok() - .expect(run.userRestrictionOption.nth(48).checked).ok() - .expect(run.userRestrictionOption.nth(49).checked).ok() - .expect(run.userRestrictionOption.nth(50).checked).ok() - .expect(run.userRestrictionOption.nth(51).checked).ok() - .expect(run.userRestrictionOption.nth(52).checked).ok() - .expect(run.userRestrictionOption.nth(53).checked).ok() - .expect(run.userRestrictionOption.nth(54).checked).ok() - .expect(run.userRestrictionOption.nth(55).checked).ok() - .expect(run.userRestrictionOption.nth(56).checked).ok() - .expect(run.userRestrictionOption.nth(57).checked).ok() - .expect(run.userRestrictionOption.nth(58).checked).ok() - .expect(run.userRestrictionOption.nth(59).checked).ok() - .expect(run.userRestrictionOption.nth(60).checked).ok() - .expect(run.userRestrictionOption.nth(61).checked).ok() - .expect(run.userRestrictionOption.nth(62).checked).ok() - .expect(run.userRestrictionOption.nth(63).checked).ok() - .expect(run.userRestrictionOption.nth(64).checked).ok() - .expect(run.userRestrictionOption.nth(65).checked).ok() - .expect(run.userRestrictionOption.nth(66).checked).ok() - .expect(run.userRestrictionOption.nth(67).checked).ok() - .expect(run.userRestrictionOption.nth(68).checked).ok() - .expect(run.userRestrictionOption.nth(69).checked).ok() - .expect(run.userRestrictionOption.nth(70).checked).ok() - .expect(run.userRestrictionOption.nth(71).checked).ok() - .expect(run.userRestrictionOption.nth(72).checked).ok() - .expect(run.userRestrictionOption.nth(73).checked).ok() - .expect(run.userRestrictionOption.nth(74).checked).ok() - .expect(run.userRestrictionOption.nth(75).checked).ok() - .expect(run.userRestrictionOption.nth(76).checked).ok() - .expect(run.userRestrictionOption.nth(77).checked).ok() - .expect(run.userRestrictionOption.nth(78).checked).ok() -}) - -test('should save selected user restriction capabilities', async t => { - // Actions && Assertions - await run.navigateSettingsTab('gf_settings&subview=PDF&tab=general#') - await t - .click(run.securityCollapsiblePanel) - .click(run.userRestrictionOption.nth(0)) - .click(run.userRestrictionOption.nth(1)) - .click(run.userRestrictionOption.nth(2)) - .click(run.userRestrictionOption.nth(4)) - .click(run.userRestrictionOption.nth(5)) - .click(run.userRestrictionOption.nth(6)) - .click(run.userRestrictionOption.nth(7)) - .click(run.userRestrictionOption.nth(8)) - .click(run.userRestrictionOption.nth(9)) - .click(run.userRestrictionOption.nth(10)) - .click(run.userRestrictionOption.nth(11)) - .click(run.userRestrictionOption.nth(12)) - .click(run.userRestrictionOption.nth(13)) - .click(run.userRestrictionOption.nth(14)) - .click(run.userRestrictionOption.nth(15)) - .click(run.userRestrictionOption.nth(16)) - .click(run.userRestrictionOption.nth(17)) - .click(run.userRestrictionOption.nth(18)) - .click(run.userRestrictionOption.nth(19)) - .click(run.userRestrictionOption.nth(20)) - .click(run.userRestrictionOption.nth(21)) - .click(run.userRestrictionOption.nth(22)) - .click(run.userRestrictionOption.nth(23)) - .click(run.userRestrictionOption.nth(24)) - .click(run.userRestrictionOption.nth(25)) - .click(run.userRestrictionOption.nth(26)) - .click(run.userRestrictionOption.nth(27)) - .click(run.userRestrictionOption.nth(28)) - .click(run.userRestrictionOption.nth(29)) - .click(run.userRestrictionOption.nth(30)) - .click(run.userRestrictionOption.nth(31)) - .click(run.userRestrictionOption.nth(32)) - .click(run.userRestrictionOption.nth(33)) - .click(run.userRestrictionOption.nth(34)) - .click(run.userRestrictionOption.nth(35)) - .click(run.userRestrictionOption.nth(36)) - .click(run.userRestrictionOption.nth(37)) - .click(run.userRestrictionOption.nth(38)) - .click(run.userRestrictionOption.nth(39)) - .click(run.userRestrictionOption.nth(40)) - .click(run.userRestrictionOption.nth(41)) - .click(run.userRestrictionOption.nth(42)) - .click(run.userRestrictionOption.nth(43)) - .click(run.userRestrictionOption.nth(44)) - .click(run.userRestrictionOption.nth(45)) - .click(run.userRestrictionOption.nth(46)) - .click(run.userRestrictionOption.nth(47)) - .click(run.userRestrictionOption.nth(48)) - .click(run.userRestrictionOption.nth(49)) - .click(run.userRestrictionOption.nth(50)) - .click(run.userRestrictionOption.nth(51)) - .click(run.userRestrictionOption.nth(52)) - .click(run.userRestrictionOption.nth(53)) - .click(run.userRestrictionOption.nth(54)) - .click(run.userRestrictionOption.nth(55)) - .click(run.userRestrictionOption.nth(56)) - .click(run.userRestrictionOption.nth(57)) - .click(run.userRestrictionOption.nth(58)) - .click(run.userRestrictionOption.nth(59)) - .click(run.userRestrictionOption.nth(60)) - .click(run.userRestrictionOption.nth(61)) - .click(run.userRestrictionOption.nth(62)) - .click(run.userRestrictionOption.nth(63)) - .click(run.userRestrictionOption.nth(64)) - .click(run.userRestrictionOption.nth(65)) - .click(run.userRestrictionOption.nth(66)) - .click(run.userRestrictionOption.nth(67)) - .click(run.userRestrictionOption.nth(68)) - .click(run.userRestrictionOption.nth(69)) - .click(run.userRestrictionOption.nth(70)) - .click(run.userRestrictionOption.nth(71)) - .click(run.userRestrictionOption.nth(72)) - .click(run.userRestrictionOption.nth(73)) - .click(run.userRestrictionOption.nth(74)) - .click(run.userRestrictionOption.nth(75)) - .click(run.userRestrictionOption.nth(76)) - .click(run.userRestrictionOption.nth(77)) - .click(run.userRestrictionOption.nth(78)) - .click(run.saveSettings) - .expect(run.userRestrictionOption.nth(0).checked).notOk() - .expect(run.userRestrictionOption.nth(1).checked).notOk() - .expect(run.userRestrictionOption.nth(2).checked).notOk() - .expect(run.userRestrictionOption.nth(3).checked).ok() - .expect(run.userRestrictionOption.nth(4).checked).notOk() - .expect(run.userRestrictionOption.nth(5).checked).notOk() - .expect(run.userRestrictionOption.nth(6).checked).notOk() - .expect(run.userRestrictionOption.nth(7).checked).notOk() - .expect(run.userRestrictionOption.nth(8).checked).notOk() - .expect(run.userRestrictionOption.nth(9).checked).notOk() - .expect(run.userRestrictionOption.nth(10).checked).notOk() - .expect(run.userRestrictionOption.nth(11).checked).notOk() - .expect(run.userRestrictionOption.nth(12).checked).notOk() - .expect(run.userRestrictionOption.nth(13).checked).notOk() - .expect(run.userRestrictionOption.nth(14).checked).notOk() - .expect(run.userRestrictionOption.nth(15).checked).notOk() - .expect(run.userRestrictionOption.nth(16).checked).notOk() - .expect(run.userRestrictionOption.nth(17).checked).notOk() - .expect(run.userRestrictionOption.nth(18).checked).notOk() - .expect(run.userRestrictionOption.nth(19).checked).notOk() - .expect(run.userRestrictionOption.nth(20).checked).notOk() - .expect(run.userRestrictionOption.nth(21).checked).notOk() - .expect(run.userRestrictionOption.nth(22).checked).notOk() - .expect(run.userRestrictionOption.nth(23).checked).notOk() - .expect(run.userRestrictionOption.nth(24).checked).notOk() - .expect(run.userRestrictionOption.nth(25).checked).notOk() - .expect(run.userRestrictionOption.nth(26).checked).notOk() - .expect(run.userRestrictionOption.nth(27).checked).notOk() - .expect(run.userRestrictionOption.nth(28).checked).notOk() - .expect(run.userRestrictionOption.nth(29).checked).notOk() - .expect(run.userRestrictionOption.nth(30).checked).notOk() - .expect(run.userRestrictionOption.nth(31).checked).notOk() - .expect(run.userRestrictionOption.nth(32).checked).notOk() - .expect(run.userRestrictionOption.nth(33).checked).notOk() - .expect(run.userRestrictionOption.nth(34).checked).notOk() - .expect(run.userRestrictionOption.nth(35).checked).notOk() - .expect(run.userRestrictionOption.nth(36).checked).notOk() - .expect(run.userRestrictionOption.nth(37).checked).notOk() - .expect(run.userRestrictionOption.nth(38).checked).notOk() - .expect(run.userRestrictionOption.nth(39).checked).notOk() - .expect(run.userRestrictionOption.nth(40).checked).notOk() - .expect(run.userRestrictionOption.nth(41).checked).notOk() - .expect(run.userRestrictionOption.nth(42).checked).notOk() - .expect(run.userRestrictionOption.nth(43).checked).notOk() - .expect(run.userRestrictionOption.nth(44).checked).notOk() - .expect(run.userRestrictionOption.nth(45).checked).notOk() - .expect(run.userRestrictionOption.nth(46).checked).notOk() - .expect(run.userRestrictionOption.nth(47).checked).notOk() - .expect(run.userRestrictionOption.nth(48).checked).notOk() - .expect(run.userRestrictionOption.nth(49).checked).notOk() - .expect(run.userRestrictionOption.nth(50).checked).notOk() - .expect(run.userRestrictionOption.nth(51).checked).notOk() - .expect(run.userRestrictionOption.nth(52).checked).notOk() - .expect(run.userRestrictionOption.nth(53).checked).notOk() - .expect(run.userRestrictionOption.nth(54).checked).notOk() - .expect(run.userRestrictionOption.nth(55).checked).notOk() - .expect(run.userRestrictionOption.nth(56).checked).notOk() - .expect(run.userRestrictionOption.nth(57).checked).notOk() - .expect(run.userRestrictionOption.nth(58).checked).notOk() - .expect(run.userRestrictionOption.nth(59).checked).notOk() - .expect(run.userRestrictionOption.nth(60).checked).notOk() - .expect(run.userRestrictionOption.nth(61).checked).notOk() - .expect(run.userRestrictionOption.nth(62).checked).notOk() - .expect(run.userRestrictionOption.nth(63).checked).notOk() - .expect(run.userRestrictionOption.nth(64).checked).notOk() - .expect(run.userRestrictionOption.nth(65).checked).notOk() - .expect(run.userRestrictionOption.nth(66).checked).notOk() - .expect(run.userRestrictionOption.nth(67).checked).notOk() - .expect(run.userRestrictionOption.nth(68).checked).notOk() - .expect(run.userRestrictionOption.nth(69).checked).notOk() - .expect(run.userRestrictionOption.nth(70).checked).notOk() - .expect(run.userRestrictionOption.nth(71).checked).notOk() - .expect(run.userRestrictionOption.nth(72).checked).notOk() - .expect(run.userRestrictionOption.nth(73).checked).notOk() - .expect(run.userRestrictionOption.nth(74).checked).notOk() - .expect(run.userRestrictionOption.nth(75).checked).notOk() - .expect(run.userRestrictionOption.nth(76).checked).notOk() - .expect(run.userRestrictionOption.nth(77).checked).notOk() - .expect(run.userRestrictionOption.nth(78).checked).notOk() -}) diff --git a/tests/e2e/tabs/license/license-field.test.js b/tests/e2e/tabs/license/license-field.test.js deleted file mode 100644 index b4b6609bf..000000000 --- a/tests/e2e/tabs/license/license-field.test.js +++ /dev/null @@ -1,18 +0,0 @@ -import { fieldHeaderTitle } from '../../utilities/page-model/helpers/field' -import License from '../../utilities/page-model/tabs/license' -import Pdf from '../../utilities/page-model/helpers/pdf' - -const license = new License() -const pdf = new Pdf() - -fixture`License tab - License field test` - -test('should display \'License\' field information', async t => { - // Actions - await pdf.navigate('gf_settings&subview=PDF&tab=license') - - // Assertions - await t - .expect(fieldHeaderTitle('Licensing').exists).ok() - .expect(license.saveSettings.exists).ok() -}) diff --git a/tests/e2e/tabs/license/sample-plugin-license.test.js b/tests/e2e/tabs/license/sample-plugin-license.test.js deleted file mode 100644 index 9e538b575..000000000 --- a/tests/e2e/tabs/license/sample-plugin-license.test.js +++ /dev/null @@ -1,40 +0,0 @@ -import License from '../../utilities/page-model/tabs/license' - -const run = new License() - -fixture`License tab - Sample plugin / extension test` - -test('should display error message for invalid license key', async t => { - // Actions - await run.navigateCoreBooster('gf_settings&subview=PDF&tab=license') - await t - .typeText(run.samplePluginInputBox, run.invalidLicenseKey, { paste: true, replace: true }) - .click(run.saveSettings) - - // Assertions - await t - .expect(run.invalidLicenseKeyMessage.exists).ok() - .expect(run.deactivateLinkMessage.exists).notOk() -}) - -test('should display success message and deactivation option for active license key', async t => { - // Actions - await run.navigateCoreBooster('gf_settings&subview=PDF&tab=license') - await t - .typeText(run.samplePluginInputBox, run.validLicenseKey, { paste: true, replace: true }) - .click(run.saveSettings) - - // Assertions - await t - .expect(run.successMessage.exists).ok() - .expect(run.deactivateLinkMessage.exists).ok() -}) - -test('should deactivate license and display deactivated message', async t => { - // Actions - await run.navigateCoreBooster('gf_settings&subview=PDF&tab=license') - await t.click(run.deactivateLink) - - // Assertions - await t.expect(run.deactivatedMessage.exists).ok() -}) diff --git a/tests/e2e/tabs/tools/fonts-field.test.js b/tests/e2e/tabs/tools/fonts-field.test.js deleted file mode 100644 index b4a26e08d..000000000 --- a/tests/e2e/tabs/tools/fonts-field.test.js +++ /dev/null @@ -1,130 +0,0 @@ -import { button, fieldHeaderTitle } from '../../utilities/page-model/helpers/field' -import Tools from '../../utilities/page-model/tabs/tools' -import FontManager from '../../utilities/page-model/helpers/font-manager' - -const run = new Tools() -const fontManager = new FontManager() - -fixture`Tools tab - Fonts field test` - -test('should display \'Fonts\' field', async t => { - // Actions - await run.navigateSettingsTab('gf_settings&subview=PDF&tab=tools#') - - // Assertions - await t - .expect(fieldHeaderTitle('Fonts').exists).ok() - .expect(button('Manage').exists).ok() -}) - -test('should check that font manager popup exist', async t => { - // Actions - await fontManager.navigateFontManager('gf_settings&subview=PDF&tab=tools#') - - // Assertions - await t - .expect(fontManager.popupHeaderText.exists).ok() - .expect(fontManager.searchBar.exists).ok() - .expect(fontManager.fontListColumn.exists).ok() - .expect(fontManager.addFontColumn.exists).ok() -}) - -test('should display error validation', async t => { - // Actions - await fontManager.navigateFontManager('gf_settings&subview=PDF&tab=tools#') - await t.click(fontManager.addFontButton) - - // Assertions - await t - .expect(fontManager.fontNameFieldErrorValidation.exists).ok() - .expect(fontManager.fontNameFieldErrorValidationMessage.exists).ok() - .expect(fontManager.dropzoneRequiredRegularField.exists).ok() - .expect(fontManager.dropzoneErrorValidationMessage.exists).ok() - .expect(fontManager.addUpdatePanelGeneralErrorValidationMessage.exists).ok() -}) - -test('should successfully add new font', async t => { - // Actions - await fontManager.navigateFontManager('gf_settings&subview=PDF&tab=tools#') - await t - .typeText(fontManager.addFontNameInputField, 'Roboto', { paste: true }) - .setFilesToUpload(fontManager.addNewFontRegular, fontManager.robotoFontRegular) - .click(fontManager.addFontButton) - - // Assertions - await t - .expect(fontManager.fontListItem.count).eql(1) - .expect(fontManager.successMessage.exists).ok() -}) - -test('should successfully check toggled state for disabled \'Update Font\' button', async t => { - // Actions && Assertions - await fontManager.navigateFontManager('gf_settings&subview=PDF&tab=tools#') - await t - .click(fontManager.fontListItem.nth(0)) - .expect(fontManager.updateFontButton.hasAttribute('disabled')).ok() - .typeText(fontManager.updateFontNameInputField, ' new', { paste: true }) - .expect(fontManager.updateFontButton.hasAttribute('disabled')).notOk() -}) - -test('should successfully close \'update font\' panel using cancel button', async t => { - // Actions - await fontManager.navigateFontManager('gf_settings&subview=PDF&tab=tools#') - await t - .click(fontManager.fontListItem.nth(0)) - .click(fontManager.cancelButton) - - // Assertions - await t.expect(fontManager.updateFontPanel.exists).notOk() -}) - -test('should successfully perform font search', async t => { - // Actions - await fontManager.navigateFontManager('gf_settings&subview=PDF&tab=tools#') - await t.typeText(fontManager.searchBar, 'Roboto', { paste: true }) - - // Assertions - await t.expect(fontManager.fontListItem.count).eql(1) -}) - -test('should successfully edit existing font', async t => { - // Actions - await fontManager.navigateFontManager('gf_settings&subview=PDF&tab=tools#') - await t - .click(fontManager.fontListItem.nth(0)) - .click(fontManager.updateFontNameInputField) - .pressKey('ctrl+a') - .pressKey('backspace') - .typeText(fontManager.updateFontNameInputField, 'Roboto 2', { paste: true }) - .setFilesToUpload(fontManager.addNewFontItalics, fontManager.robotoFontItalics) - .setFilesToUpload(fontManager.addNewFontBold, fontManager.robotoFontBold) - .setFilesToUpload(fontManager.addNewFontBoldItalics, fontManager.robotoFontBoldItalics) - .click(fontManager.updateFontButton) - - // Assertions - await t - .expect(fontManager.successMessage.exists).ok() - .expect(fontManager.fontListItem.nth(0).find('[class^="font-name"]').withText('Roboto 2').exists).ok() - .expect(fontManager.fontListItem.nth(0).find('[class^="dashicons dashicons-yes"]').count).eql(4) -}) - -test('should successfully delete font', async t => { - // Actions - await fontManager.navigateFontManager('gf_settings&subview=PDF&tab=tools#') - await t - .click(fontManager.fontListItem.nth(0).find('[class^="dashicons dashicons-trash"]')) - - // Assertions - await t - .expect(fontManager.fontListItem.count).eql(0) - .expect(fontManager.fontListEmptyMessage.exists).ok() -}) - -test('should be able to close font manager popup', async t => { - // Actions - await fontManager.navigateFontManager('gf_settings&subview=PDF&tab=tools#') - await t.click(fontManager.closeDialog) - - // Assertions - await t.expect(fontManager.fontManagerPopup.exists).notOk() -}) diff --git a/tests/e2e/tabs/tools/install-core-fonts-field.test.js b/tests/e2e/tabs/tools/install-core-fonts-field.test.js deleted file mode 100644 index 346c8f13a..000000000 --- a/tests/e2e/tabs/tools/install-core-fonts-field.test.js +++ /dev/null @@ -1,59 +0,0 @@ -import { RequestMock } from 'testcafe'; -import { baseURL } from '../../auth'; -import { fieldHeaderTitle } from '../../utilities/page-model/helpers/field'; -import Tools from '../../utilities/page-model/tabs/tools'; - -const mockSuccess = RequestMock() - .onRequestTo( `${ baseURL }/wp-admin/admin-ajax.php` ) - .respond( {}, 200, { 'access-Control-Allow-Origin': '*' } ); - -fixture`Tools tab - Install core fonts field test`.requestHooks( mockSuccess ); - -test( "should display 'Install Core Fonts' field", async ( t ) => { - const run = new Tools(); - // Actions - await run.navigateToToolsTab(); - - // Assertions - await t - .expect( fieldHeaderTitle( 'Install Core Fonts' ).exists ) - .ok() - .expect( run.downloadCoreFontsButton.exists ) - .ok(); -} ); - -test( 'should return download core fonts successful response', async ( t ) => { - const run = new Tools(); - // Actions - await run.navigateToToolsTab(); - await t.click( run.downloadCoreFontsButton ); - - // Assertions - await t - .expect( run.downloadSuccess.exists ) - .ok() - .expect( run.allSuccessfullyInstalled.exists ) - .ok(); -} ); - -const mockGithubError = RequestMock() - .onRequestTo( - `${ baseURL }/wp-content/plugins/gravity-pdf/build/payload/core-fonts.json` - ) - .respond( { ok: false }, 500, { - 'Access-Control-Allow-Origin': '*', - } ); - -fixture`Tools tab - Install core fonts field test failure`.requestHooks( - mockGithubError -); - -test( 'should return download core fonts error/failed response', async ( t ) => { - const run = new Tools(); - // Actions - await run.navigateToToolsTab(); - await t.click( run.downloadCoreFontsButton ); - - // Assertions - await t.expect( run.downloadFailed.exists ).ok(); -} ); diff --git a/tests/e2e/tabs/tools/uninstall-gravity-pdf-field.test.js b/tests/e2e/tabs/tools/uninstall-gravity-pdf-field.test.js deleted file mode 100644 index 6ed272fdf..000000000 --- a/tests/e2e/tabs/tools/uninstall-gravity-pdf-field.test.js +++ /dev/null @@ -1,16 +0,0 @@ -import Tools from '../../utilities/page-model/tabs/tools' - -const run = new Tools() - -fixture`Tools tab - Uninstall Gravity PDF field test` - -test('should display \'Uninstall Gravity PDF\' field', async t => { - // Actions - await run.navigateSettingsTab('gf_settings&subview=uninstall') - - // Assertions - await t - .expect(run.uninstallPanelTitle.exists).ok() - .expect(run.uninstallPanelDescription.exists).ok() - .expect(run.uninstallGravityPdfButton.exists).ok() -}) diff --git a/tests/e2e/utilities/page-model/helpers/advanced-check.js b/tests/e2e/utilities/page-model/helpers/advanced-check.js deleted file mode 100644 index 6542763fa..000000000 --- a/tests/e2e/utilities/page-model/helpers/advanced-check.js +++ /dev/null @@ -1,179 +0,0 @@ -import { Selector, t } from 'testcafe'; -import { admin, baseURL } from '../../../auth'; -import { link, listItem } from '../helpers/field'; -import Pdf from '../helpers/pdf'; - -const pdf = new Pdf(); - -class AdvancedCheck { - constructor () { - // Shortcode section - this.confirmationTextCheckbox = Selector('#gform-settings-radio-choice-type0').find('input').withAttribute('id', 'type0') - this.confirmationPageCheckbox = Selector('#gform-settings-radio-choice-type1').find('input').withAttribute('id', 'type1') - this.confirmationRedirectCheckbox = Selector('#gform-settings-radio-choice-type2').find('input').withAttribute('id', 'type2') - this.shortcodeBox = Selector('button').withAttribute('aria-label', 'Copy the Sample PDF shortcode to the clipboard') - this.confirmationPageSelectBox = Selector('#gform_setting_page').find('button#gform-page-control') - this.queryStringInputBox = Selector('#gform_setting_queryString').find('[id="queryString"]') - this.wysiwgEditorTextTab = Selector('#gform-settings-section-confirmations').find('.wp-editor-tabs').find('button').withText('Code') - this.wysiwgEditor = Selector('div').find('textarea[class^="merge-tag-support"]') - this.redirectInputBox = Selector('#gform_setting_url').find('[id="url"]') - this.previewLink = Selector('#gf_toolbar_buttons_container a').addCustomDOMProperties({ - href: el => el.href - }) - this.saveConfirmationButton = Selector('.gform-settings-save-container').find('button').withText('Save Confirmation') - this.formInputField = Selector('input').withAttribute('name', 'input_1') - this.submitButton = Selector('input').withAttribute('value', 'Submit') - - // General Settings - Debug Mode field - this.debugModeCheckbox = Selector( '#gfpdf-fieldset-debug_mode' ).find( - '[id="gfpdf_settings[debug_mode]"]' - ); - this.debugModeErrorMessage = Selector( 'div' ).withText( - 'PDF link not displayed because PDF is inactive.' - ); - - // Merge tags section - this.mergeTagsButton = Selector( '#gform_setting_message' ).find( - 'button.gform-dropdown__control' - ); - this.textInputField = Selector( 'input' ).withAttribute( - 'name', - 'input_1' - ); - this.fNameInputField = Selector( '.name_first' ).find( - 'input[type^="text"]' - ); - this.lNameInputField = Selector( '.name_last' ).find( - 'input[type^="text"]' - ); - this.emailInputField = Selector( 'input' ).withAttribute( - 'name', - 'input_3' - ); - - // PDF restriction section - this.pdfRestrictionErrorMessage = Selector( 'div' ) - .withAttribute( 'class', 'wp-die-message' ) - .withText( 'You do not have access to view this PDF.' ); - this.viewEntryLink = Selector( '.entry_unread' ) - .find( 'a.gravitypdf-download-link' ) - .nth( 1 ); - this.wpLoginForm = Selector( '#login' ) - .find( 'form' ) - .withAttribute( 'name', 'loginform' ); - - // Pdf template section - this.addNewButton = Selector( '.tablenav' ) - .find( 'a' ) - .withText( 'Add New' ); - this.pdfLabelNameInputBox = Selector( - '#gfpdf-fieldset-gfpdf_form_settings_general' - ).find( '[id="gfpdf_settings[name]"]' ); - this.pdfFilenameInputBox = Selector( - '#gfpdf-fieldset-gfpdf_form_settings_general' - ).find( '[id="gfpdf_settings[filename]"]' ); - this.addUpdatePdfButton = Selector( - '#submit-and-promo-container' - ).find( '[id="submit"]' ); - this.templateItem = Selector( '#the-list' ).find( 'tr' ); - this.pdfListSection = Selector( '.gform-settings__navigation' ) - .find( 'a' ) - .withText( 'PDF' ); - this.toggleSwitch = Selector( '#the-list' ).find( - '.check-column button' - ); - this.entryItemSection = - Selector( '#the-list' ).find( 'td.column-primary' ); - this.viewPdfLink = Selector( '#the-list' ) - .find( 'a' ) - .withText( 'View PDF' ); - this.editLink = Selector( '#the-list' ) - .find( 'span' ) - .withText( 'Edit' ); - this.conditionalLogicCheckbox = Selector( - '#gfpdf-fieldset-gfpdf_form_settings_general' - ).find( '[id="gfpdf_conditional_logic"]' ); - this.templateDetail = Selector( '#the-list' ) - .find( 'tr' ) - .nth( 0 ) - .find( 'td' ) - .nth( 0 ); - this.duplicateLink = Selector( '#the-list' ) - .find( 'a' ) - .withText( 'Duplicate' ); - this.deletePDF = Selector( '.submitdelete' ); - } - - async copyDownloadShortcode( uri ) { - await pdf.navigate( uri ); - await t.click( this.shortcodeBox ); - } - - async navigateConfirmationSection( uri ) { - await pdf.navigate( uri ); - - await t.click( link( '#the-list', 'Default Confirmation' ) ); - } - - async navigateLink( uri ) { - await pdf.navigate( uri ); - } - - async navigateSection( uri ) { - await pdf.navigate( uri ); - } - - async pickMergeTag( text ) { - await t - .click( this.mergeTagsButton ) - .click( listItem( text ) ) - .pressKey( 'enter' ); - } - - async toggleRestrictOwnerCheckbox( uri ) { - await pdf.navigate( uri ); - - await t - .click( Selector( 'td.name' ).find( 'a' ).withText( 'Sample' ) ) - .click( pdf.restrictOwnerCheckbox ) - .click( pdf.saveSettings ); - } - - async submitNewPdfEntry() { - await t - .typeText( this.textInputField, 'texttest', { paste: true } ) - .click( this.submitButton ) - .wait( 500 ); - } - - async navigateAddPdf( uri ) { - await pdf.navigate( uri ); - - await t - .click( this.addNewButton ) - .typeText( this.pdfLabelNameInputBox, 'Test PDF Template', { - paste: true, - } ) - .typeText( this.pdfFilenameInputBox, 'testpdftemplate', { - paste: true, - } ) - .click( this.addUpdatePdfButton ) - .click( this.pdfListSection ); - } - - async navigateDeletePdfEntries( uri ) { - await pdf.navigate( uri ); - - const template = await this.templateItem.count; - if ( template > 0 ) { - for ( let i = 0; i < template; i++ ) { - await t - .hover( this.templateItem ) - .click( this.deletePDF ) - .wait( 500 ); - } - } - } -} - -export default AdvancedCheck; diff --git a/tests/e2e/utilities/page-model/helpers/field.js b/tests/e2e/utilities/page-model/helpers/field.js deleted file mode 100644 index c73e67c70..000000000 --- a/tests/e2e/utilities/page-model/helpers/field.js +++ /dev/null @@ -1,87 +0,0 @@ -import { Selector } from 'testcafe' - -// Field header title -export function fieldHeaderTitle (text) { - return Selector('legend').withText(text) -} - -// Field label -export function fieldLabel (text, style = 'div') { - return Selector(style).withText(text) -} - -// Select box -export function selectBox (style, id) { - return Selector('div').find(`[class^="${style}"][id="${id}"]`) -} - -// Button -export function button (text) { - return Selector('button').withText(text) -} - -// Dropdown options -export function dropdownOptionGroup (text) { - return Selector('optgroup').withAttribute('label', text) -} - -export function dropdownOption (text) { - return Selector('option').withText(text) -} - -// Item in the list -export function listItem (text) { - return Selector('li.gform-dropdown__item').find('span').withText(text) -} - -// Info text -export function infoText (text, style = 'td') { - return Selector(style).withText(text) -} - -// Template details -export function templateDetails (style, text) { - return Selector('div').find(`[class^="${style}"]`).withText(`${text}`) -} - -// Link -export function link (style, text) { - return Selector(`${style}`).find('a').withText(text) -} - -// User restriction option -export function userRestrictionOption (value) { - return Selector('.gfpdf-settings-multicheck-wrapper').find(`[value="${value}"]`) -} - -export function mediaManagerTitle (text) { - return Selector('.media-frame-title').withText(`${text}`) -} - -// Add media button -export function addMediaButton (id, text) { - return Selector(`#${id}`).find('button').withText(`${text}`) -} - -// Merge tags -export function mergeTagsWrapper (id) { - return Selector(`div#${id}`).find('ul.gform-dropdown__list') -} - -// Merge tags for password -export function passwordGroupOption (text) { - return mergeTagsWrapper('gfpdf-settings-field-wrapper-password').find('li.gform-dropdown__group').withText(`${text}`) -} - -export function passwordOptionItem (text) { - return mergeTagsWrapper('gfpdf-settings-field-wrapper-password').find('li').find('button').withText(`${text}`) -} - -// Merge tags for filename -export function filenameGroupOption (text) { - return mergeTagsWrapper('gfpdf-settings-field-wrapper-filename').find('li.gform-dropdown__group').withText(`${text}`) -} - -export function filenameOptionItem (text) { - return mergeTagsWrapper('gfpdf-settings-field-wrapper-filename').find('li').find('button').withText(`${text}`) -} diff --git a/tests/e2e/utilities/page-model/helpers/font-manager.js b/tests/e2e/utilities/page-model/helpers/font-manager.js deleted file mode 100644 index 012a7e05d..000000000 --- a/tests/e2e/utilities/page-model/helpers/font-manager.js +++ /dev/null @@ -1,60 +0,0 @@ -import { Selector, t } from 'testcafe' -import { admin, baseURL } from '../../../auth' -import { button } from './field' - -class FontManager { - constructor () { - this.advancedButton = Selector('#gfpdf-settings-field-wrapper-font-container').find('button').withText('Manage') - this.fontManagerPopup = Selector('div').find('[class^="container theme-wrap font-manager"]') - - // Header section - this.popupHeaderText = Selector('h1').withText('Font Manager') - this.closeDialog = Selector('.theme-header').find('button').withText('Close dialog') - - // Search bar section - this.searchBar = Selector('#font-manager-search-box') - - // Font list section - this.fontListColumn = Selector('.font-list-column') - this.fontListItem = Selector('.font-list-item') - this.fontName = Selector('.font-list-item').nth(0).find('[class^="font-name"]') - this.fontVariantsCheck = Selector('.font-list-item').nth(0).find('[class^="dashicons dashicons-yes"]') - - // Add and update font panel section - this.addFontColumn = Selector('.add-update-font-column') - this.addFontNameInputField = Selector('#gfpdf-add-font-name-input') - this.addNewFontRegular = Selector('#gfpdf-font-files-setting').find('input').withAttribute('aria-labelledby', 'gfpdf-font-variant-regular addFont gfpdf-font-files-label') - this.addNewFontItalics = Selector('#gfpdf-font-files-setting').find('input').withAttribute('aria-labelledby', 'gfpdf-font-variant-italics updateFont gfpdf-font-files-label') - this.addNewFontBold = Selector('#gfpdf-font-files-setting').find('input').withAttribute('aria-labelledby', 'gfpdf-font-variant-bold updateFont gfpdf-font-files-label') - this.addNewFontBoldItalics = Selector('#gfpdf-font-files-setting').find('input').withAttribute('aria-labelledby', 'gfpdf-font-variant-bolditalics updateFont gfpdf-font-files-label') - this.updateFontPanel = Selector('#gfpdf-font-manager-container').find('[class^="update-font show"]') - this.updateFontNameInputField = Selector('#gfpdf-update-font-name-input') - this.addFontButton = Selector('.footer').find('button').withText('Add Font →') - this.updateFontButton = Selector('.footer').find('button').withText('Update Font →') - this.cancelButton = Selector('.footer').find('[class^="button gfpdf-button primary cancel"]') - - // Success and error message - this.fontListEmptyMessage = Selector('.alert-message').withText('Font list empty.') - this.fontNameFieldErrorValidation = Selector('.input-label-validation-error') - this.fontNameFieldErrorValidationMessage = Selector('.required').withText('Please choose a name contains letters and/or numbers (and a space if you want it).') - this.dropzoneRequiredRegularField = Selector('#gfpdf-font-files-setting').find('[class^="drop-zone required"]') - this.dropzoneErrorValidationMessage = Selector('.gfpdf-font-filename').withText('Add a .ttf font file.') - this.addUpdatePanelGeneralErrorValidationMessage = Selector('.footer').withText(' Resolve the highlighted issues above and then try again.') - this.successMessage = Selector('.success').withText('Your font has been saved.') - - // Resources - this.robotoFontRegular = '../../utilities/resources/Roboto-Regular.ttf' - this.robotoFontItalics = '../../utilities/resources/Roboto-RegularItalic.ttf' - this.robotoFontBold = '../../utilities/resources/Roboto-Bold.ttf' - this.robotoFontBoldItalics = '../../utilities/resources/Roboto-BoldItalic.ttf' - } - - async navigateFontManager (address) { - await t - .setNativeDialogHandler(() => true) - .navigateTo(`${baseURL}/wp-admin/admin.php?page=${address}`) - .click(button('Manage')) - } -} - -export default FontManager diff --git a/tests/e2e/utilities/page-model/helpers/media-manager.js b/tests/e2e/utilities/page-model/helpers/media-manager.js deleted file mode 100644 index 89a46f5e9..000000000 --- a/tests/e2e/utilities/page-model/helpers/media-manager.js +++ /dev/null @@ -1,25 +0,0 @@ -import { Selector } from 'testcafe' - -class MediaManager { - constructor () { - this.mediaModalContainer = Selector('.supports-drag-drop').find('[class^="media-modal wp-core-ui"]') - this.mediaCloseDialog = Selector('.media-modal').find('[class^="media-modal-close"]') - this.uploadFilesPanelLink = Selector('.media-frame-router').find('[id="menu-item-upload"]') - this.mediaLibraryPanelLink = Selector('.media-frame-router').find('[id="menu-item-browse"]') - this.dropInstructionsText = Selector('.media-frame-content').withText('Drop files to upload') - this.selectFilesButton = Selector('.upload-ui').find('button').withText('Select Files') - this.maxUploadSizeText = Selector('.media-frame-content').find('[class^="max-upload-size"]') - this.uploadMediaFilesInputBox = Selector('.media-modal-content').find('input').withAttribute('type', 'file') - this.uploadedMediaFile = Selector('.media-frame-content').find('li').withAttribute('role', 'checkbox') - this.deleteFile = Selector('.media-sidebar').find('button').withText('Delete permanently') - - // Buttons - this.selectMediaButton = Selector('.media-toolbar').find('button').withText('Select Media') - this.insertIntoPostButton = Selector('.media-toolbar').find('button').withText('Insert into post') - - // Resources - this.backgroundImage = '../../utilities/resources/background-image.jpg' - } -} - -export default MediaManager diff --git a/tests/e2e/utilities/page-model/helpers/page.js b/tests/e2e/utilities/page-model/helpers/page.js deleted file mode 100644 index af967ecea..000000000 --- a/tests/e2e/utilities/page-model/helpers/page.js +++ /dev/null @@ -1,53 +0,0 @@ -import { Selector, t } from 'testcafe' -import { baseURL } from '../../../auth' -import { link } from './field' - -class Page { - constructor () { - this.testPageLink = link('#the-list', 'Test-page') - this.closePopupButton = Selector('button').withAttribute('aria-label', 'Close dialog') - this.closePopupPattern = Selector('button').withAttribute('aria-label', 'Close') - this.titleField = Selector('.editor-post-title__input') - this.addBlockIcon = Selector('button.editor-document-tools__inserter-toggle') - this.searchBlock = Selector('.block-editor-inserter__search').find('input').withAttribute('type', 'search') - this.paragraphButton = Selector('button.editor-block-list-item-paragraph\\/paragraph') - this.shortcodeLink = Selector('button.editor-block-list-item-shortcode') - this.shortcodeTextarea = Selector('textarea').withAttribute('placeholder', 'Write shortcode here…') - this.trashLink = Selector('a').withAttribute('aria-label', 'Move “Test-page” to the Trash') - this.publishButton = Selector('.editor-post-publish-button__button') - this.confirmPublishButton = Selector('.editor-post-publish-panel__header-publish-button button').withText('Publish') - this.updateButton = this.publishButton - } - - async navigatePage () { - await t - .setNativeDialogHandler(() => true) - .navigateTo(`${baseURL}/wp-admin/edit.php?post_type=page`) - } - - async addNewPage () { - await t.click(link('.wrap', 'Add Page')) - - if (await this.closePopupButton.exists) await t.click(this.closePopupButton) - if (await this.closePopupPattern.exists) await t.click(this.closePopupPattern) - - await t - .typeText(this.titleField, 'Test-page', { paste: true }) - .click(this.addBlockIcon) - .typeText(this.searchBlock.filterVisible(), 'paragraph', { paste: true }) - .click(this.paragraphButton) - .wait(500) - .typeText(Selector('p.is-selected'), 'Content', { paste: true }) - .click(this.publishButton) - .click(this.confirmPublishButton) - } - - async deleteTestPage () { - await t - .navigateTo(`${baseURL}/wp-admin/edit.php?post_type=page`) - .hover(link('#the-list', 'Test-page')) - .click(this.trashLink) - } -} - -export default Page diff --git a/tests/e2e/utilities/page-model/helpers/pdf.js b/tests/e2e/utilities/page-model/helpers/pdf.js deleted file mode 100644 index 8105f994e..000000000 --- a/tests/e2e/utilities/page-model/helpers/pdf.js +++ /dev/null @@ -1,265 +0,0 @@ -import { Selector, t } from 'testcafe'; -import { admin, baseURL } from '../../../auth'; -import { selectBox } from './field'; - -class Pdf { - constructor() { - this.template = Selector('.alternate'); - this.saveSettings = Selector('#submit-and-promo-container').find( - 'input' - ); - - // General - Template field - this.templateSelectBox = selectBox( - 'gfpdf_settings_template large', - 'gfpdf_settings[template]' - ); - - // General - Filename field - this.filenameInputBox = Selector( - '#gfpdf-settings-field-wrapper-filename' - ).find('[id="gfpdf_settings[filename]"]'); - this.filenameMergeTagsOptionList = Selector( - '#gfpdf-settings-field-wrapper-filename' - ).find('button.gform-dropdown__control'); - - // General - Conditional Logic field - this.conditionalLogicCheckbox = Selector( - '#gfpdf-settings-field-wrapper-conditional' - ).find('[id="gfpdf_conditional_logic"]'); - - // Appearance - Paper Size field - this.paperSizeSelectBox = Selector( - '#gfpdf-settings-field-wrapper-pdf_size' - ).find('[id="gfpdf_settings[pdf_size]"]'); - - // Appearance - Paper Orientation field - this.paperOrientationSelectBox = selectBox( - 'gfpdf_settings_orientation large', - 'gfpdf_settings[orientation]' - ); - - // Appearance - Custom Paper Size field - this.customPaperSizeLabel = Selector( - '#gfpdf-settings-field-wrapper-custom_pdf_size' - ) - .find('[class^="gform-settings-panel__title"]') - .withText('Custom Paper Size'); - - // Appearance - Font field - this.fontSelectBox = selectBox( - 'gfpdf_settings_font ', - 'gfpdf_settings[font]' - ); - - // Appearance - Font Size field - this.fontSizeInputBox = selectBox( - 'small-text gfpdf_settings_font_size ', - 'gfpdf_settings[font_size]' - ); - - // Appearance - Font Color field - this.fontColorSelectButton = Selector( - '#gfpdf-settings-field-wrapper-font_colour' - ) - .find('button') - .withText('Select Color'); - this.fontColorWpPickerContainerActive = Selector( - '#gfpdf-settings-field-wrapper-font_colour' - ).find('[class^="wp-picker-container wp-picker-active"]'); - this.fontColorWpColorPickerBox = Selector( - '#gfpdf-settings-field-wrapper-font_colour' - ).find('[class^="iris-picker iris-border"]'); - this.fontColorInputBox = Selector( - '#gfpdf-settings-field-wrapper-font_colour' - ).find('[id="gfpdf_settings[font_colour]"]'); - - // Appearance - Reverse Text (RTL) field - this.rtlCheckbox = Selector('#gfpdf-settings-field-wrapper-rtl').find( - '[id="gfpdf_settings[rtl]"]' - ); - - // Template - Show Form Title field - this.showFormTitleCheckbox = Selector( - '#gfpdf-settings-field-wrapper-show_form_title' - ).find('[id="gfpdf_settings[show_form_title]"]'); - - // Template - Show Page Names field - this.showPageNamesCheckbox = Selector( - '#gfpdf-settings-field-wrapper-show_page_names' - ).find('[id="gfpdf_settings[show_page_names]"]'); - - // Template - Show HTML Fields field - this.showHtmlFieldsCheckbox = Selector( - '#gfpdf-settings-field-wrapper-show_html' - ).find('[id="gfpdf_settings[show_html]"]'); - - // Template - Show Section Break Description field - this.showSectionBreakDescriptionCheckbox = Selector( - '#gfpdf-settings-field-wrapper-show_section_content' - ).find('[id="gfpdf_settings[show_section_content]"]'); - - // Template - Enable Conditional Logic field - this.enableConditionalLogicCheckbox = Selector( - '#gfpdf-settings-field-wrapper-enable_conditional' - ).find('[id="gfpdf_settings[enable_conditional]"]'); - - // Template - Show Empty Fields field - this.showEmptyFieldsCheckbox = Selector( - '#gfpdf-settings-field-wrapper-show_empty' - ).find('[id="gfpdf_settings[show_empty]"]'); - - // Template - Background Color field - this.backgroundColorInputBox = Selector( - '#gfpdf-settings-field-wrapper-background_color' - ).find('[id="gfpdf_settings[background_color]"]'); - this.backgroundColorWpPickerContainerActive = Selector( - '#gfpdf-settings-field-wrapper-background_color' - ).find('[class^="wp-picker-container wp-picker-active"]'); - this.backgroundColorWpColorPickerBox = Selector( - '#gfpdf-settings-field-wrapper-font_colour' - ).find('[class^="iris-picker iris-border"]'); - this.backgroundColorSelectButton = Selector( - '#gfpdf-settings-field-wrapper-background_color' - ) - .find('button') - .withText('Select Color'); - - // Template - Background Image field - this.backgroundImageUploadBox = selectBox( - 'regular-text gfpdf_settings_background_image ', - 'gfpdf_settings[background_image]' - ); - this.backgroundImageUploadFileButton = Selector( - '.gfpdf-upload-setting-container' - ) - .find('input') - .withAttribute('type', 'button'); - - // Template - Header field - this.headerWpEditorBox = Selector('#gfpdf-settings-field-wrapper-header').find('[id="wp-gfpdf_settings_header-editor-container"]') - this.headerWpEditorBoxTextPanelLink = Selector('#gfpdf-settings-field-wrapper-header').find('.wp-editor-tabs').find('button').withText('Code') - this.headerWpEditorBoxContentArea = Selector('#gfpdf-settings-field-wrapper-header').find('[class^="gfpdf_settings_header"]') - - // Template - First Page Header field - this.firstPageHeaderCheckbox = Selector('#gfpdf-settings-field-wrapper-first_header').find('[class^="gfpdf-input-toggle"]') - this.firstPageHeaderWpEditorBox = Selector('#gfpdf-settings-field-wrapper-first_header').find('[id="wp-gfpdf_settings_first_header-editor-container"]') - this.firstPageHeaderWpEditorBoxTextPanelLink = Selector('#gfpdf-settings-field-wrapper-first_header').find('.wp-editor-tabs').find('button').withText('Code') - this.firstPageHeaderWpEditorBoxContentArea = Selector('#gfpdf-settings-field-wrapper-first_header').find('[class^="gfpdf_settings_first_header"]') - - // Template - Footer field - this.footerWpEditorBox = Selector('#gfpdf-settings-field-wrapper-footer').find('[id="wp-gfpdf_settings_footer-editor-container"]') - this.footerWpEditorBoxTextPanelLink = Selector('#gfpdf-settings-field-wrapper-footer').find('.wp-editor-tabs').find('button').withText('Code') - this.footerWpEditorBoxContentArea = Selector('#gfpdf-settings-field-wrapper-footer').find('[class^="gfpdf_settings_footer"]') - - // Template - First Page Footer field - this.firstPageFooterCheckbox = Selector('#gfpdf-settings-field-wrapper-first_footer').find('[class^="gfpdf-input-toggle"]') - this.firstPageFooterWpEditorBox = Selector('#gfpdf-settings-field-wrapper-first_footer').find('[id="wp-gfpdf_settings_first_footer-editor-container"]') - this.firstPageFooterWpEditorBoxTextPanelLink = Selector('#gfpdf-settings-field-wrapper-first_footer').find('.wp-editor-tabs').find('button').withText('Code') - this.firstPageFooterWpEditorBoxContentArea = Selector('#gfpdf-settings-field-wrapper-first_footer').find('[class^="gfpdf_settings_first_footer"]') - - // Advanced - Format field - this.formatStandardCheckbox = Selector( - '#gfpdf-settings-field-wrapper-format' - ).find('[id="gfpdf_settings[format][Standard]"]'); - this.formatPdfA1bCheckbox = Selector( - '#gfpdf-settings-field-wrapper-format' - ).find('[id="gfpdf_settings[format][PDFA1B]"]'); - this.formatPdfX1aCheckbox = Selector( - '#gfpdf-settings-field-wrapper-format' - ).find('[id="gfpdf_settings[format][PDFX1A]"]'); - this.enablePdfSecurityField = Selector( - '#gfpdf-settings-field-wrapper-security' - ); - this.enablePdfSecurityCheckbox = Selector( - '#gfpdf-settings-field-wrapper-security' - ).find('[id="gfpdf_settings[security]"]'); - this.passwordField = Selector('#gfpdf-settings-field-wrapper-password'); - this.privilegesField = Selector( - '#gfpdf-settings-field-wrapper-privileges' - ); - - // Advanced - Enable PDF Security field - this.enablePdfSecurityCheckbox = Selector( - '#gfpdf-settings-field-wrapper-security' - ).find('[id="gfpdf_settings[security]"]'); - - // Advanced - Password field - this.passwordInputBox = Selector( - '#gfpdf-settings-field-wrapper-password' - ).find('[id="gfpdf_settings[password]"]'); - this.passwordMergeTagsOptionList = Selector( - '#gfpdf-settings-field-wrapper-password' - ).find('button.gform-dropdown__control'); - - // Advanced - Privileges field - this.copyCheckbox = Selector( - '#gfpdf-settings-field-wrapper-privileges' - ).find('[id="gfpdf_settings[privileges][copy]"]'); - this.printLowResolutionCheckbox = Selector( - '#gfpdf-settings-field-wrapper-privileges' - ).find('[id="gfpdf_settings[privileges][print]"]'); - this.printHighResolutionCheckbox = Selector( - '#gfpdf-settings-field-wrapper-privileges' - ).find('[id="gfpdf_settings[privileges][print-highres]"]'); - this.modifyCheckbox = Selector( - '#gfpdf-settings-field-wrapper-privileges' - ).find('[id="gfpdf_settings[privileges][modify]"]'); - this.annotateCheckbox = Selector( - '#gfpdf-settings-field-wrapper-privileges' - ).find('[id="gfpdf_settings[privileges][annot-forms]"]'); - this.fillFormsCheckbox = Selector( - '#gfpdf-settings-field-wrapper-privileges' - ).find('[id="gfpdf_settings[privileges][fill-forms]"]'); - this.extractCheckbox = Selector( - '#gfpdf-settings-field-wrapper-privileges' - ).find('[id="gfpdf_settings[privileges][extract]"]'); - this.assembleCheckbox = Selector( - '#gfpdf-settings-field-wrapper-privileges' - ).find('[id="gfpdf_settings[privileges][assemble]"]'); - - // Advanced - Image DPI field - this.imageDpiInputBox = Selector( - '#gfpdf-settings-field-wrapper-image_dpi' - ).find('[id="gfpdf_settings[image_dpi]"]'); - - // Advanced - Enable Public Access field - this.enablePublicAccessCheckbox = Selector( - '#gfpdf-settings-field-wrapper-public_access' - ).find('[id="gfpdf_settings[public_access]"]'); - - // Advanced - Restrict Owner field - this.restrictOwnerCheckbox = Selector( - '#gfpdf-settings-field-wrapper-restrict_owner' - ).find('[id="gfpdf_settings[restrict_owner]"]'); - } - - async navigatePdfSection(uri) { - await this.navigate(uri); - await t.click( - Selector('#the-list').find('a').nth(0).withText('Sample') - ); - } - - async navigate(uri) { - await t - .setNativeDialogHandler(() => true) - .navigateTo(`${baseURL}/wp-admin/admin.php?page=${uri}`); - } - - /** - * Navigates to pdf section with a given id - * @param { string | number } id - * - * @return {Promise} none - */ - async navigatePdf(id) { - await t - .setNativeDialogHandler(() => true) - .navigateTo( - `${baseURL}/wp-admin/admin.php?page=gf_edit_forms&view=settings&subview=PDF&id=${id}` - ); - } -} - -export default Pdf; diff --git a/tests/e2e/utilities/page-model/helpers/search-params.js b/tests/e2e/utilities/page-model/helpers/search-params.js deleted file mode 100644 index b2007b12e..000000000 --- a/tests/e2e/utilities/page-model/helpers/search-params.js +++ /dev/null @@ -1,13 +0,0 @@ -import { ClientFunction } from 'testcafe'; - -/** - * Provides the ability to use Client APIs specifically url search params - * - * @param { string } param - * - * @return { string } param value - */ -export const getQueryParam = ClientFunction( ( param ) => { - const urlParams = new URLSearchParams( window.location.search ); - return urlParams.get( param ); -} ); diff --git a/tests/e2e/utilities/page-model/helpers/template-manager.js b/tests/e2e/utilities/page-model/helpers/template-manager.js deleted file mode 100644 index 1f16b507d..000000000 --- a/tests/e2e/utilities/page-model/helpers/template-manager.js +++ /dev/null @@ -1,70 +0,0 @@ -import { Selector, t } from 'testcafe'; -import { baseURL } from '../../../auth'; -import { button } from './field'; -import Pdf from './pdf'; - -const pdf = new Pdf(); - -class TemplateManager { - constructor() { - this.advancedButton = Selector( '#gpdf-advance-template-selector' ) - .find( 'button' ) - .withText( 'Manage' ); - this.templatePopupBox = Selector( 'div' ).find( - '[class^="container theme-wrap"]' - ); - this.closeDialog = button( 'Close dialog' ); - this.popupHeaderText = Selector( 'div.theme-header>h1' ).withText( - 'Installed PDFs' - ); - this.searchBar = Selector( '#wp-filter-search-input' ); - this.individualThemeBox = Selector( '.theme' ); - this.themeScreenshot = Selector( '.theme-screenshot' ); - this.themeAuthor = Selector( '.theme-author' ); - this.themeName = Selector( '.theme-name' ); - this.themeSelectButton = Selector( 'button' ).withText( 'Select' ); - this.themeDetailsLink = - Selector( 'span' ).withText( 'Template Details' ); - this.dropZoneBox = Selector( '.dropzone' ); - this.installationMessage = Selector( 'div' ); - this.focusGravityTemplateDetails = Selector( '.theme-wrap' ) - .find( 'div' ) - .withAttribute( 'data-slug', 'focus-gravity' ) - .withText( 'Template Details' ); - this.focusGravityTemplate = Selector( 'div' ) - .find( '[class^="theme-name"]' ) - .withText( 'Focus Gravity' ); - this.rubixTemplate = Selector( 'div' ) - .find( '[class^="theme-name"]' ) - .withText( 'Rubix' ); - this.templateSearchbar = Selector( '#wp-filter-search-input' ); - this.searchResult = Selector( '.theme-author' ); - this.addNewTemplateButton = Selector( 'input' ).withAttribute( - 'type', - 'file' - ); - this.testTemplate = '../../utilities/resources/test-template.zip'; - this.imageScreenshot = Selector( '.theme-screenshot' ) - .find( 'img' ) - .withAttribute( - 'src', - `${ baseURL }/wp-content/uploads/PDF_EXTENDED_TEMPLATES/images/test-template.png` - ); - this.deleteButton = Selector( '.button' ).withText( 'Delete' ); - this.testTemplateDetailsLink = Selector( - '.theme[data-slug="test-template"]' - ) - .find( 'span' ) - .withText( 'Template Details' ); - } - - async navigateTemplateManager( address, shouldClickAdvancedButton = true ) { - await pdf.navigatePdfSection( address ); - - if ( shouldClickAdvancedButton ) { - await t.click( this.advancedButton ); - } - } -} - -export default TemplateManager; diff --git a/tests/e2e/utilities/page-model/tabs/general-settings.js b/tests/e2e/utilities/page-model/tabs/general-settings.js deleted file mode 100644 index af6013314..000000000 --- a/tests/e2e/utilities/page-model/tabs/general-settings.js +++ /dev/null @@ -1,74 +0,0 @@ -import { Selector, t } from 'testcafe' -import { admin, baseURL } from '../../../auth' - -class General { - constructor () { - // Fieldset collapsible link - this.securityCollapsiblePanel = Selector('#gfpdf-fieldset-gfpdf_settings_general_security').find('[id="gform_settings_section_collapsed_gfpdf_settings_general_security"]') - - // General Settings - Default Template field - this.defaultTemplateSelectBox = Selector('#gfpdf-settings-field-wrapper-default_template').find('[id="gfpdf_settings[default_template]"]') - - // General Settings - Default Font field - this.defaultFontSelectBox = Selector('#gfpdf-settings-field-wrapper-default_font').find('select').withAttribute('name', 'gfpdf_settings[default_font]') - - // General Settings - Default Paper Size field - this.defaultPaperSizeSelectBox = Selector('#gfpdf-settings-field-wrapper-default_pdf_size').find('[id="gfpdf_settings[default_pdf_size]"]') - - // General Settings - Custom Paper Size field - this.customPaperSizeLabel = Selector('#gfpdf-settings-field-wrapper-default_custom_pdf_size').find('[class^="gform-settings-panel__title"]').withText('Custom Paper Size') - - // General Settings - Reverse Text (RTL) field - this.reverseTextRtlCheckbox = Selector('#gfpdf-settings-field-wrapper-default_rtl').find('[id="gfpdf_settings[default_rtl]"]') - - // General Settings - Default Font Size field - this.defaultFontSizeInputBox = Selector('#gfpdf-settings-field-wrapper-default_font_size').find('[id="gfpdf_settings[default_font_size]"]') - - // General Settings - Default Font Color field - this.defaultFontColorSelectButton = Selector('#gfpdf-settings-field-wrapper-default_font_colour').find('[class^="button wp-color-result ed_button"]').withText('Select Color') - this.defaultFontColorInputBox = Selector('#gfpdf-settings-field-wrapper-default_font_colour').find('[id="gfpdf_settings[default_font_colour]"]') - - // General Settings - Entry View field - this.entryViewViewOption = Selector('#gfpdf-fieldset-default_action').find('[id="gfpdf_settings[default_action][View]"]') - this.entryViewDownlaodOption = Selector('#gfpdf-fieldset-default_action').find('[id="gfpdf_settings[default_action][Download]"]') - - // General Settings - Background Processing field - this.backgroundProcessingCheckbox = Selector('#gfpdf-fieldset-background_processing').find('[id="gfpdf_settings[background_processing]"]') - - // General Settings - Debug Mode field - this.debugModeCheckbox = Selector('#gfpdf-fieldset-debug_mode').find('[id="gfpdf_settings[debug_mode]"]') - - // General Settings - Logged Out Timeout field - this.loggedOutTimeoutInputBox = Selector('#gfpdf-fieldset-gfpdf_settings_general_security').find('[id="gfpdf_settings[logged_out_timeout]"]') - - // General Settings - Default Owner Restrictions field - this.defaultOwnerRestrictionsCheckbox = Selector('#gfpdf-settings-field-wrapper-default_restrict_owner').find('[id="gfpdf_settings[default_restrict_owner]"]') - - // General Settings - User Restriction field - this.userRestrictionOption = Selector('#gfpdf-settings-field-wrapper-admin_capabilities').find('input') - - this.entries = Selector('#the-list').find('tr').withText('Sample 2').find('span').withText('Entries') - this.list = Selector('.gf-locking ').withText('Sample 2') - this.template = Selector('.alternate') - this.testTemplateDetailsLink = Selector('.theme[data-slug="test-template"]').find('span').withText('Template Details') - - this.addNewTemplate = Selector('input').withAttribute('type', 'file') - this.saveSettings = Selector('#submit-and-promo-container').find('input') - - // PDF entries section - this.viewEntryItem = Selector('#the-list').find('td.column-primary') - } - - async navigateSettingsTab (text) { - await t - .setNativeDialogHandler(() => true) - .navigateTo(`${baseURL}/wp-admin/admin.php?page=${text}`) - } - - async navigatePdfEntries (text) { - await t - .navigateTo(`${baseURL}/wp-admin/admin.php?page=${text}`) - } -} - -export default General diff --git a/tests/e2e/utilities/page-model/tabs/license.js b/tests/e2e/utilities/page-model/tabs/license.js deleted file mode 100644 index 60f4aa6ce..000000000 --- a/tests/e2e/utilities/page-model/tabs/license.js +++ /dev/null @@ -1,30 +0,0 @@ -import { Selector, t } from 'testcafe' -import Pdf from '../helpers/pdf' - -const pdf = new Pdf() - -class License { - constructor () { - // Core Booster field - this.samplePluginInputBox = Selector('#gfpdf-fieldset-license_gravity-pdf-example-plugin').find('[id="gfpdf_settings[license_gravity-pdf-example-plugin]"]') - this.validLicenseKey = '987654321' - this.invalidLicenseKey = '123456789' - this.invalidLicenseKeyMessage = Selector('.gforms_note_error').withText('This license key is invalid. Please check your key has been entered correctly.') - this.deactivateLinkMessage = Selector('button').withText('Deactivate License') - this.successMessage = Selector('.gforms_note_success').withText('Your support license key has been activated for this domain.') - this.deactivateLink = Selector('.gfpdf-deactivate-license') - this.deactivatedMessage = Selector('.success').withText('License deactivated.') - - this.saveSettings = Selector('#submit-and-promo-container').find('input') - } - - async navigateCoreBooster (uri) { - await pdf.navigate(uri) - await t - .click(this.samplePluginInputBox) - .selectText(this.samplePluginInputBox, 32, 0) - .pressKey('backspace') - } -} - -export default License diff --git a/tests/e2e/utilities/page-model/tabs/tools.js b/tests/e2e/utilities/page-model/tabs/tools.js deleted file mode 100644 index 35aae86bd..000000000 --- a/tests/e2e/utilities/page-model/tabs/tools.js +++ /dev/null @@ -1,49 +0,0 @@ -import { Selector, t } from 'testcafe'; -import { baseURL } from '../../../auth'; - -class Tools { - constructor() { - // Install Core Fonts field - this.downloadCoreFontsButton = Selector( - '#gfpdf-fieldset-install_core_fonts' - ) - .find( 'button' ) - .withText( 'Download Core Fonts' ); - this.pendingResult = Selector( '.gfpdf-core-font-status-pending' ); - this.downloadSuccess = Selector( '.gfpdf-core-font-status-success' ); - this.allSuccessfullyInstalled = Selector( - '.gfpdf-core-font-status-success' - ).withText( 'ALL CORE FONTS SUCCESSFULLY INSTALLED' ); - this.downloadFailed = Selector( '.gfpdf-core-font-status-error' ); - this.retryDownload = Selector( 'button' ).withText( - 'Retry Failed Downloads?' - ); - - // Uninstall Gravity PDF field - this.uninstallPanelTitle = Selector( '.addon-uninstall-text' ) - .find( 'h4' ) - .withText( 'Gravity PDF' ); - this.uninstallPanelDescription = Selector( '.addon-uninstall-text' ) - .find( 'div' ) - .withText( 'This operation deletes ALL Gravity PDF settings.' ); - this.uninstallGravityPdfButton = Selector( '.addon-uninstall-button' ) - .find( 'button' ) - .withText( 'Uninstall' ); - } - - async navigateSettingsTab( address ) { - await t - .setNativeDialogHandler( () => true ) - .navigateTo( `${ baseURL }/wp-admin/admin.php?page=${ address }` ); - } - - async navigateToToolsTab() { - await t - .setNativeDialogHandler( () => true ) - .navigateTo( - `${ baseURL }/wp-admin/admin.php?page=gf_settings&subview=PDF&tab=tools#/` - ); - } -} - -export default Tools; diff --git a/tests/e2e/utilities/resources/background-image.jpg b/tests/e2e/utilities/resources/background-image.jpg deleted file mode 100644 index 0ca1d75339746eb9de5ac398a655a3ef5db81169..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11420 zcmeGhTW}j!^{&>EUy5z{(S)Qe8^v~-f~=<>5_J5yOOtA?JBz~ zKQa`Ww9w&?xGf#{V3HKN$0w2r(NelfcL!CB#z;vbw^f54nJSb%t7;)}h?MilB zH>RnF8FV$ek8{pF=iGDeIrrYZrB_Sm>#mH=idlpb33Mw$r~x@CglMQywtbLMMx8o@ z0i=#`-=rJ{9N7TgUamt&s;gWFDrzILV?OXdL2a_?-=}V=>g&fG&`t1vnhKD5C)5`n z5m6nKxbHhqFrXLyHT~;BgtoSsf?7xm@eg9U((lp3$l1`) z(AeN?Y;?Mso0?r+txjia*M^Rcu8xikE+sr>ewY0Q#wzRZ#;;g09 z=;FE-2BlvjR|CqSqcr74HWx*^sM6~&$fnY>)OOI)PLTu(<3z)Xsk1xk8ycIMsijB? z*=Q5lhNwD)K)WZw0 z`kwjJ#q*aqt^bB6Pd(H-`e>RTJ9AtgSbuinf^hjq4?pu_@efz-*!tLsFFpPEvoHPe zZ{Payug<;s-rd>hFMsXZKl$~`Z~c96=VWf?ktd$|>2t5V{k{v?Y@lr&(W%~H?e zes*=_FRqUKrPYz2dp8p>-=6NXaxIw zXeb&_)Zu`GQ0tAOgJ_XTo1vu{pPp-eBe9J{k+j$nEt^J?a%BXxCp_$ z33(g*u}dS=Tu?<>-&@oRMID+r4x({QPh}KEA{2317X-OTf&s2$f|#V@b}Q+d5@#_* zRMc@Fj5c@*>K-;Pq{sH90b~d>I*hA|l1&MEv9LFDKLNp;Fm=VN+AL1sE7)f z6>2J2)X*YqqLMC`HF9Q(qNIy5VF~y~LLE!obC+R_&tMid4`h`Qw^xmLZ$TFoSp)of zOc^WavN;GCWJa|b$()w38ZlLlRT{EhY3$BOnuXbu)2FS*SY8^n8eqo?>nOKBS2l!U zC6wG5je$0>Ga;1Z8HQJinH|a-xJlAZRlW)qm9D0Xs(gAv*6-MolIa`2=k z=>$GLEA2>HjT*t&vVztq3A#1Q%A~p>h-*RG8oMgbq zRc^;Um;*^|oT?Nirv#W>SfQevGtJk65lPS~s_43smlQcy?&35tScNM1Iuo80b5qrb zW)lIrS@hUf=ywerj7<;Lov{g0#E*IjuB9v#itP^?-bY_1uqK2`B$a(~9f4x6y_fX= zgw?*8$htz>jU&cIT?fE~_B{gKg}m7;U?j+4lZQl=A;-S{4GV&g5fr)? za+9W?K(IfQA%y2YppCG<8CoyR>31-CDb#3x6dbWd1Lkddr)>v#EBwoLyBXKW(ZulP zjkrlqKxSx*0;98HQyMm+K$5#<4%gQ$Y7adoPKk%J`gTb!y0 zEJP)oAh{^vsD~r4Bcl{$UR&bLobCr43EJ2NtaS#!CF>MLt@Ui2=91QOB|~&*lE?|# z-O_ICaMU6>c7g+NJN)ZOBR*Ost3IbH#lj+xLs7+?XvNa86z0B{z<|d(wx}yR1zAv8 zUEl$L(sKoKD`+x^F$81c`5Xhq$31?!s7i}A6k`0vkc5_7yy-YtNl&x6MN}=EAW3Oq zR*!4D(uv(>SZgrBi-;Si6!qYUB<4&@wHkxpWrAVk^}LW}izLi8P7A8O4EfzAcrkf% zCKppAMXfTf%itf~X(6Bs+M~$W){VMSfbCins^eIb1Oe|Vs53(Xjm=OT5uV-YHR@i7*(5f3pvqQ3$ec9o;>hk#7IfzW9N;CZwGt_8Jg zL+#p7yEc5-4e9z^8w@Yq41S2v>CMh5W4%|~v*Ws^`8f^ZsajZfoLjzHlJ)X(r(F z4|;urUVqTz^GAFGkzkl9CpSn_`D`RPdPi9nw1(Z~LCws}^vwkO6gB7dhr?m7FW?OX zJV4>m=473n^~l;5lf$T>ajHn}77XSH=jNh5>;_GZA><1d+huKK67rlySAeaL25y7E@Tk{F1di z3kywV9(O84VyeKxEg}s!2y>z;SKI3EVO8V;+&P3{H~v88@%uc1a2kIg8;Aq~pYjbw zd_IFT0jq$A%gM6D_-ooCVucs8b012|bCIl~=2@_jm}hf>_x^&ABjOT?NL~Plyd?J=svm=Na}Dz9K)EJ~ z3|Ws6mc!TaVK;}@iomvTyYf{WSWxIXINDj$-&%w$Qt#2km?#c zy|Uuhwoq13yn02iUh%R?xhYo82@rd|Zafq(j#9>ic$dxy2)`5z+WC=z|-u>=rQ}k>CTJEEov}x{_v$(X#UAlU1w9> z+8NIA(4!YFA0JKgJ^f=h^y&i>g84Z7!7sD;IT+a~2fX=Hw4HW%5#_RNru`%B@EUyR zh`S?j@z}|_(+lS>MUz`HYUh0LaIE{uQ=!x-r=2UmG<(QN_%BZ zrPciH`ouH3RP(p%WyzYqT`x=4_P6V0$=d#Qy)604Ta#z-f%5%{i;vT { const wrapper = mount( ); - const component = findByTestAttr(wrapper, 'input-add'); + const component = findByTestAttr( + wrapper, + 'component-FontVariant-add' + ); expect(component.length).toBe(1); }); test('render delete input field', () => { const wrapper = mount(); - const component = findByTestAttr(wrapper, 'input-delete'); + const component = findByTestAttr( + wrapper, + 'component-FontVariant-delete' + ); expect(component.length).toBe(4); }); diff --git a/tests/playwright/core/entry-list-and-details/conditional-logic-pdf.spec.ts b/tests/playwright/core/entry-list-and-details/conditional-logic-pdf.spec.ts new file mode 100644 index 000000000..41577cdaa --- /dev/null +++ b/tests/playwright/core/entry-list-and-details/conditional-logic-pdf.spec.ts @@ -0,0 +1,86 @@ +import type { Admin, RequestUtils } from '@wordpress/e2e-test-utils-playwright'; +import type { Page } from '@playwright/test'; +import { expect } from '@wordpress/e2e-test-utils-playwright'; +import { test } from '@self:playwright/fixtures/test'; +import Pdf from '@self:playwright/utils/gravitypdf'; + +test.describe('Conditional PDF', () => { + let form = null; + let pdf = null; + let entry1 = null; + let entry2 = null; + + test.beforeEach( + async ({ + requestUtils, + page, + admin, + }: { + requestUtils: RequestUtils; + page: Page; + admin: Admin; + }) => { + // setup form and inactive PDF + pdf = new Pdf(requestUtils, admin, page); + form = await pdf.createForm('Conditional PDF'); + + // setup PDF with conditional logic + const pdfId = await pdf.createPdf(form.id, 'Conditional PDF'); + await page + .getByRole('checkbox', { + name: 'Enable conditional logic', + exact: true, + }) + .check(); + await pdf.addOrUpdatePdf(); + + // create entry + entry1 = await pdf.createEntry({ form_id: form.id }); + entry2 = await pdf.createEntry({ + form_id: form.id, + 1: 'First Choice', + }); + } + ); + + test('Entry List', async ({ + requestUtils, + page, + admin, + }: { + requestUtils: RequestUtils; + page: Page; + admin: Admin; + }) => { + await pdf.navigateToEntryList(form.id); + await expect(page.getByRole('link', { name: 'View PDF' })).toHaveCount( + 1 + ); + }); + + test('Entry Detail', async ({ + requestUtils, + page, + admin, + }: { + requestUtils: RequestUtils; + page: Page; + admin: Admin; + }) => { + await pdf.navigateToEntryDetail(entry1.form_id, entry1.id); + await expect( + page.getByRole('link', { name: 'View', exact: true }) + ).not.toBeAttached(); + await expect( + page.getByRole('link', { name: 'Download', exact: true }) + ).not.toBeAttached(); + + await pdf.navigateToEntryDetail(entry2.form_id, entry2.id); + await expect( + page.getByRole('link', { name: 'View', exact: true }) + ).toBeAttached(); + await expect( + page.getByRole('link', { name: 'Download', exact: true }) + ).toBeAttached(); + }); +}); diff --git a/tests/playwright/core/entry-list-and-details/inactive-pdf.spec.ts b/tests/playwright/core/entry-list-and-details/inactive-pdf.spec.ts new file mode 100644 index 000000000..385976cb9 --- /dev/null +++ b/tests/playwright/core/entry-list-and-details/inactive-pdf.spec.ts @@ -0,0 +1,86 @@ +import type { Admin, RequestUtils } from '@wordpress/e2e-test-utils-playwright'; +import type { Page } from '@playwright/test'; +import { expect } from '@wordpress/e2e-test-utils-playwright'; +import { test } from '@self:playwright/fixtures/test'; +import Pdf from '@self:playwright/utils/gravitypdf'; + +test.describe('Inactive PDF', () => { + let form = null; + let pdf = null; + let entry = null; + + test.beforeEach( + async ({ + requestUtils, + page, + admin, + }: { + requestUtils: RequestUtils; + page: Page; + admin: Admin; + }) => { + // setup form and inactive PDF + pdf = new Pdf(requestUtils, admin, page); + form = await pdf.createForm('Inactive PDF'); + + const pdfId = await pdf.createPdf(form.id, 'Inactive PDF'); + await pdf.navigateToFormPdfList(form.id); + await page + .getByRole('button', { name: 'Active', exact: true }) + .click(); + + // create entry + entry = await pdf.createEntry({ form_id: form.id }); + } + ); + + test('Entry List', async ({ + requestUtils, + page, + admin, + }: { + requestUtils: RequestUtils; + page: Page; + admin: Admin; + }) => { + await pdf.navigateToEntryList(form.id); + await expect( + page.getByRole('link', { name: 'View PDF' }) + ).not.toBeAttached(); + + await pdf.createPdf(form.id, 'Active PDF'); + + await pdf.navigateToEntryList(form.id); + await expect( + page.getByRole('link', { name: 'View PDF' }) + ).toBeAttached(); + }); + + test('Entry Detail', async ({ + requestUtils, + page, + admin, + }: { + requestUtils: RequestUtils; + page: Page; + admin: Admin; + }) => { + await pdf.navigateToEntryDetail(entry.form_id, entry.id); + await expect( + page.getByRole('link', { name: 'View', exact: true }) + ).not.toBeAttached(); + await expect( + page.getByRole('link', { name: 'Download', exact: true }) + ).not.toBeAttached(); + + await pdf.createPdf(form.id, 'Active PDF'); + + await pdf.navigateToEntryDetail(entry.form_id, entry.id); + await expect( + page.getByRole('link', { name: 'View', exact: true }) + ).toBeAttached(); + await expect( + page.getByRole('link', { name: 'Download', exact: true }) + ).toBeAttached(); + }); +}); diff --git a/tests/playwright/core/entry-list-and-details/multiple-pdfs.spec.ts b/tests/playwright/core/entry-list-and-details/multiple-pdfs.spec.ts new file mode 100644 index 000000000..96f6ec1ed --- /dev/null +++ b/tests/playwright/core/entry-list-and-details/multiple-pdfs.spec.ts @@ -0,0 +1,75 @@ +import { expect } from '@wordpress/e2e-test-utils-playwright'; +import { takeSnapshot } from '@chromatic-com/playwright'; +import type { Admin, RequestUtils } from '@wordpress/e2e-test-utils-playwright'; +import type { Page } from '@playwright/test'; +import { test } from '@self:playwright/fixtures/test'; +import Pdf from '@self:playwright/utils/gravitypdf'; + +test.describe('Multiple PDF', () => { + let form = null; + let pdf = null; + let entry = null; + + test.beforeEach( + async ({ + requestUtils, + page, + admin, + }: { + requestUtils: RequestUtils; + page: Page; + admin: Admin; + }) => { + // setup form + pdf = new Pdf(requestUtils, admin, page); + form = await pdf.createForm('Multiple PDF'); + + // setup PDF + for (let i = 1; i <= 2; i++) { + await pdf.createPdf(form.id, `Multiple #${i}`); + } + + // create entry + entry = await pdf.createEntry({ form_id: form.id }); + } + ); + + test('Entry List, View', async ({ + requestUtils, + page, + admin, + }: { + requestUtils: RequestUtils; + page: Page; + admin: Admin; + }, testinfo) => { + await pdf.navigateToEntryList(form.id); + const pdfLink = page.getByRole('link', { name: 'View PDFs' }); + await page.locator('.has-row-actions').first().hover(); + await pdfLink.hover(); + + await takeSnapshot(page, testinfo); + + await pdf.downloadAndVerifyPdf( + page.getByRole('link', { name: 'Multiple #2' }), + 'Multiple #2.pdf' + ); + }); + + test('Entry Details', async ({ + requestUtils, + page, + admin, + }: { + requestUtils: RequestUtils; + page: Page; + admin: Admin; + }, testinfo) => { + await pdf.navigateToEntryDetail(entry.form_id, entry.id); + await expect( + page.getByLabel('View or download Multiple #2.pdf') + ).toBeAttached(); + + await takeSnapshot(page, testinfo); + }); +}); diff --git a/tests/playwright/core/entry-list-and-details/single-pdf.spec.ts b/tests/playwright/core/entry-list-and-details/single-pdf.spec.ts new file mode 100644 index 000000000..f3fd8bdd3 --- /dev/null +++ b/tests/playwright/core/entry-list-and-details/single-pdf.spec.ts @@ -0,0 +1,75 @@ +import type { Admin, RequestUtils } from '@wordpress/e2e-test-utils-playwright'; +import type { Page } from '@playwright/test'; +import { test } from '@self:playwright/fixtures/test'; +import Pdf from '@self:playwright/utils/gravitypdf'; +import { takeSnapshot } from '@chromatic-com/playwright'; + +test.describe('Single PDF', () => { + let form = null; + let pdf = null; + let entry = null; + + test.beforeEach( + async ({ + requestUtils, + page, + admin, + }: { + requestUtils: RequestUtils; + page: Page; + admin: Admin; + }) => { + // setup form + pdf = new Pdf(requestUtils, admin, page); + form = await pdf.createForm('Single PDF'); + + // setup PDF + await pdf.setGlobalPdfSetting('View', true); + await pdf.createPdf(form.id, 'Single #1'); + + // create entry + entry = await pdf.createEntry({ form_id: form.id }); + } + ); + + test('Entry List, View', async ({ + requestUtils, + page, + admin, + }: { + requestUtils: RequestUtils; + page: Page; + admin: Admin; + }, testinfo) => { + await pdf.navigateToEntryList(form.id); + const pdfLink = page.getByRole('link', { name: 'View PDF' }); + await page.locator('.has-row-actions').first().hover(); + + await takeSnapshot(page, testinfo); + await pdf.downloadAndVerifyPdf(pdfLink, 'Single #1.pdf'); + }); + + test('Entry Details', async ({ + requestUtils, + page, + admin, + }: { + requestUtils: RequestUtils; + page: Page; + admin: Admin; + }) => { + await pdf.navigateToEntryDetail(entry.form_id, entry.id); + + const viewPdfLink = page.getByRole('link', { + name: 'View', + exact: true, + }); + const downloadPdfLink = page.getByRole('link', { + name: 'Download', + exact: true, + }); + + await pdf.downloadAndVerifyPdf(viewPdfLink, 'Single #1.pdf'); + await pdf.downloadAndVerifyPdf(downloadPdfLink, 'Single #1.pdf'); + }); +}); diff --git a/tests/playwright/core/pdf-access/inactive.spec.ts b/tests/playwright/core/pdf-access/inactive.spec.ts new file mode 100644 index 000000000..18232f137 --- /dev/null +++ b/tests/playwright/core/pdf-access/inactive.spec.ts @@ -0,0 +1,99 @@ +import type { Admin, RequestUtils } from '@wordpress/e2e-test-utils-playwright'; +import { expect } from '@wordpress/e2e-test-utils-playwright'; +import type { Page } from '@playwright/test'; +import { test } from '@self:playwright/fixtures/test'; +import Pdf from '@self:playwright/utils/gravitypdf'; + +test.describe('Advanced Template Checks', () => { + let pdf: Pdf; + let form: any; + + test.beforeEach( + async ({ + requestUtils, + page, + admin, + }: { + requestUtils: RequestUtils; + page: Page; + admin: Admin; + }) => { + pdf = new Pdf(requestUtils, admin, page); + form = await pdf.createForm('Advanced Template Checks'); + } + ); + + test('should successfully saved toggled switch value for active and inactive template', async ({ + page, + }) => { + await pdf.navigateToFormPdfList(form.id); + const pdfId = await pdf.createPdf(form.id, 'Toggle Test'); + + await pdf.navigateToFormPdfList(form.id); + const toggle = page + .locator(`#gfpdf-${pdfId}`) + .locator('button.gform-status-indicator'); + + // Toggle off + await toggle.click(); + await expect(toggle).toHaveAttribute('data-status', 'inactive'); + + // Toggle on + await toggle.click(); + await expect(toggle).toHaveAttribute('data-status', 'active'); + }); + + test('should check that "View PDF" link is hidden when template is inactive', async ({ + page, + }) => { + await pdf.navigateToFormPdfList(form.id); + const pdfId = await pdf.createPdf(form.id, 'Inactive Test'); + + await pdf.navigateToFormPdfList(form.id); + const toggle = page + .locator(`#gfpdf-${pdfId}`) + .locator('button.gform-status-indicator'); + await toggle.click(); + + const entry = await pdf.createEntry({ form_id: form.id }); + await pdf.navigateToEntryList(form.id); + + // Entry list selectors might vary, using a common one + await page.locator('td.column-primary').first().hover(); + await expect( + page.locator('.gravitypdf-download-link') + ).not.toBeVisible(); + }); + + test('should check that "View PDF" link is hidden when conditional logic fails', async ({ + page, + }) => { + await pdf.navigateToFormPdfList(form.id); + const pdfId = await pdf.createPdf(form.id, 'Conditional Test'); + + await pdf.navigateToFormPdf(form.id, pdfId); + await page + .getByText('Enable conditional logic', { exact: true }) + .check(); + + await page.locator('#gfpdf_rule_value_0').selectOption('Third Choice'); + await pdf.addOrUpdatePdf(); + + await pdf.createEntry({ form_id: form.id }); + await pdf.navigateToEntryList(form.id); + + await page.locator('td.column-primary').first().hover(); + await expect(page.getByText('View PDF')).not.toBeVisible(); + }); + + test('should successfully duplicate existing PDF', async ({ page }) => { + await pdf.navigateToFormPdfList(form.id); + await pdf.createPdf(form.id, 'Source PDF'); + + await pdf.navigateToFormPdfList(form.id); + await page.locator('.name').first().hover(); + await page.getByRole('link', { name: 'Duplicate' }).click(); + + await expect(page.locator('tr[id^="gfpdf-"]')).toHaveCount(2); + }); +}); diff --git a/tests/playwright/core/pdf-access/security.spec.ts b/tests/playwright/core/pdf-access/security.spec.ts new file mode 100644 index 000000000..1133742cf --- /dev/null +++ b/tests/playwright/core/pdf-access/security.spec.ts @@ -0,0 +1,178 @@ +import * as crypto from 'node:crypto'; +import type { Admin, RequestUtils } from '@wordpress/e2e-test-utils-playwright'; +import { expect } from '@wordpress/e2e-test-utils-playwright'; +import type { Page } from '@playwright/test'; +import { test } from '@self:playwright/fixtures/test'; +import Pdf from '@self:playwright/utils/gravitypdf'; + +test.describe('PDF Security and Access Policies', () => { + let pdf: Pdf; + let form: any; + + test.beforeEach( + async ({ + requestUtils, + page, + admin, + }: { + requestUtils: RequestUtils; + page: Page; + admin: Admin; + }) => { + pdf = new Pdf(requestUtils, admin, page); + form = await pdf.createForm('Restriction Test'); + } + ); + + test('should download a PDF for an anonymous user with the same IP', async ({ + requestUtils, + page, + admin, + }: { + requestUtils: RequestUtils; + page: Page; + admin: Admin; + }) => { + const pdfId = await pdf.createPdf(form.id, 'Accessible PDF'); + const entry = await pdf.createEntry({ + form_id: form.id, + }); + + // Visit as anonymous user + await admin.context.clearCookies(); + await pdf.gotoPdfAndVerify( + `/?gpdf=1&pid=${pdfId}&lid=${entry.id}`, + 'Accessible PDF.pdf' + ); + }); + + test('should show the login page when an anonymous user with a different IP tries to access a PDF', async ({ + requestUtils, + page, + admin, + }: { + requestUtils: RequestUtils; + page: Page; + admin: Admin; + }) => { + const pdfId = await pdf.createPdf(form.id, 'Restricted PDF'); + const entry = await pdf.createEntry({ + form_id: form.id, + ip: '10.0.0.1', + }); + + // Visit as anonymous user + await admin.context.clearCookies(); + await page.goto(`/?gpdf=1&pid=${pdfId}&lid=${entry.id}`); + + // Should redirect to login + await expect( + page.getByRole('button', { name: 'Log In' }) + ).toBeVisible(); + }); + + test('should show error if "Restrict Owner" is enabled and visiting as that user', async ({ + requestUtils, + page, + admin, + }: { + requestUtils: RequestUtils; + page: Page; + admin: Admin; + }) => { + const userId = crypto.randomBytes(20).toString('hex'); + const user = await requestUtils.createUser({ + username: userId, + email: `${userId}@example.com`, + password: '123456', + }); + + await pdf.navigateToNewFormPdf(form.id); + const pdfId = await pdf.createPdf(form.id, 'Restrict Owner'); + + await pdf.navigateToFormPdf(form.id, pdfId); + await pdf.checkField('Restrict Owner', true); + await pdf.addOrUpdatePdf(); + + const entry = await pdf.createEntry({ + form_id: form.id, + created_by: user.id, + }); + + // Log in as the entry creator user + await admin.context.clearCookies(); + await page.goto('/wp-login.php'); + await page.getByLabel('Username or Email Address').fill(userId); + await page.getByLabel('Password', { exact: true }).fill('123456'); + await page.getByRole('button', { name: 'Log In' }).click(); + + await page.goto(`/?gpdf=1&pid=${pdfId}&lid=${entry.id}`); + + // Should show access denied error + await expect( + page.getByText('You do not have access to view this PDF.') + ).toBeVisible(); + }); + + test('should download PDF when "Restrict Owner" is enabled and downloading as current user', async ({ + requestUtils, + page, + admin, + }: { + requestUtils: RequestUtils; + page: Page; + admin: Admin; + }) => { + const userPass = crypto.randomBytes(20).toString('hex'); + const user = await requestUtils.createUser({ + username: crypto.randomBytes(20).toString('hex'), + email: crypto.randomBytes(20).toString('hex') + '@example.com', + password: userPass, + }); + + await pdf.navigateToNewFormPdf(form.id); + const pdfId = await pdf.createPdf(form.id, 'Restrict Owner'); + + await pdf.navigateToFormPdf(form.id, pdfId); + await pdf.checkField('Restrict Owner', true); + await pdf.addOrUpdatePdf(); + + const entry = await pdf.createEntry({ + form_id: form.id, + created_by: user.id, + }); + + // Visit the PDF link as anon (clear cookies to simulate anonymous user) + await page.context().clearCookies(); + await page.goto(`/?gpdf=1&pid=${pdfId}&lid=${entry.id}`); + + // Should redirect to login + await expect(page.locator('#login form')).toBeVisible(); + }); + + test('should allow access to a public PDF for anonymous users', async ({ + requestUtils, + page, + admin, + }: { + requestUtils: RequestUtils; + page: Page; + admin: Admin; + }) => { + await pdf.navigateToNewFormPdf(form.id); + const pdfId = await pdf.createPdf(form.id, 'Public PDF'); + + await pdf.navigateToFormPdf(form.id, pdfId); + await pdf.checkField('Enable Public Access', true); + await pdf.addOrUpdatePdf(); + + const entry = await pdf.createEntry({ form_id: form.id }); + + // Visit as anonymous user + await page.context().clearCookies(); + await pdf.gotoPdfAndVerify( + `/?gpdf=1&pid=${pdfId}&lid=${entry.id}`, + 'Public PDF.pdf' + ); + }); +}); diff --git a/tests/playwright/core/pdf-settings/pdf-settings.spec.ts b/tests/playwright/core/pdf-settings/pdf-settings.spec.ts new file mode 100644 index 000000000..79cd976c1 --- /dev/null +++ b/tests/playwright/core/pdf-settings/pdf-settings.spec.ts @@ -0,0 +1,410 @@ +import type { Admin, RequestUtils } from '@wordpress/e2e-test-utils-playwright'; +import { expect } from '@wordpress/e2e-test-utils-playwright'; +import type { Page } from '@playwright/test'; +import { test, resourcesPath } from '@self:playwright/fixtures/test'; +import Pdf from '@self:playwright/utils/gravitypdf'; +import * as path from 'node:path'; +import { takeSnapshot } from '@chromatic-com/playwright'; + +test.describe('Form PDF Settings', () => { + let pdf = null; + let form = null; + + test.beforeEach( + async ({ + requestUtils, + page, + admin, + }: { + requestUtils: RequestUtils; + page: Page; + admin: Admin; + }) => { + // setup form and inactive PDF + pdf = new Pdf(requestUtils, admin, page); + form = await pdf.createForm('Form PDF Settings'); + + // Reset TinyMCE to default to the Visual tab + await pdf.navigateToNewFormPdf(form.id); + for (const button of await page + .getByRole('button', { name: /^Visual$/ }) + .all()) { + await button.click(); + } + } + ); + + test.describe('General', () => { + test('Label', async () => { + await pdf.fillField('Label', 'Test Label'); + await pdf.addOrUpdatePdf(); + await expect(pdf.page.getByLabel('Label')).toHaveValue( + 'Test Label' + ); + }); + + test('Filename', async ({}, testinfo) => { + await pdf.createPdf(form.id, 'Filename'); + + await pdf.page.getByRole('textbox', { name: 'Filename' }).click(); + await pdf.page.getByTitle('Insert Merge Tags').nth(0).click(); + await pdf.page + .getByRole('textbox', { name: 'Search Merge Tags' }) + .fill('date'); + await pdf.page + .getByRole('button', { name: 'Date (dd/mm/yyyy)' }) + .click(); + await pdf.page.getByRole('textbox', { name: 'Filename' }).click(); + await pdf.page + .getByRole('textbox', { name: 'Filename' }) + .pressSequentially('-{entry_id}'); + await pdf.addOrUpdatePdf(); + + await takeSnapshot(pdf.page, testinfo); + }); + + test('Notifications', async () => { + const elements = pdf.page + .locator('#gfpdf-settings-field-wrapper-notification') + .getByRole('checkbox'); + + await expect(elements).toHaveCount(1); + + // Add another Notification + await pdf.addNotification(form.id, 'User Notification'); + + await pdf.createPdf(form.id, 'PDF Notification'); + await expect(elements).toHaveCount(2); + + await pdf.page + .getByRole('checkbox', { name: 'User Notification' }) + .click(); + await pdf.addOrUpdatePdf(); + + await expect( + pdf.page.getByRole('checkbox', { name: 'Admin Notification' }) + ).not.toBeChecked(); + await expect( + pdf.page.getByRole('checkbox', { name: 'User Notification' }) + ).toBeChecked(); + }); + + test('Conditional Logic', async ({}, testinfo) => { + await pdf.createPdf(form.id, 'Conditional Logic'); + + await pdf.page + .getByRole('checkbox', { + name: 'Enable conditional logic', + exact: true, + }) + .check(); + + await pdf.page.locator('#gfpdf_action_type').selectOption('hide'); + await pdf.page.locator('#gfpdf_logic_type').selectOption('any'); + await pdf.page + .locator('#gfpdf_rule_value_0') + .selectOption('Second Choice'); + + await pdf.page.getByTitle('add another rule').first().click(); + await pdf.page + .locator('#gfpdf_rule_field_1') + .selectOption('status'); + + await pdf.page.locator('#gfpdf_rule_value_1').selectOption('spam'); + await pdf.addOrUpdatePdf(); + + await takeSnapshot(pdf.page, testinfo); + + // Entry 1: Radio = "Second Choice" → PDF hidden by conditional logic + const entry1 = await pdf.createEntry({ + form_id: form.id, + 1: 'Second Choice', + }); + + await pdf.navigateToEntryList(form.id); + await expect( + pdf.page.getByRole('link', { name: 'View PDF' }) + ).not.toBeAttached(); + + await pdf.navigateToEntryDetail(entry1.form_id, entry1.id); + await expect( + pdf.page.getByRole('link', { name: 'View', exact: true }) + ).not.toBeAttached(); + await expect( + pdf.page.getByRole('link', { name: 'Download', exact: true }) + ).not.toBeAttached(); + + // Entry 2: Radio = "First Choice" → PDF passes conditional logic + const entry2 = await pdf.createEntry({ + form_id: form.id, + 1: 'First Choice', + }); + + await pdf.navigateToEntryList(form.id); + await expect( + pdf.page.getByRole('link', { name: 'View PDF' }) + ).toBeAttached(); + + await pdf.navigateToEntryDetail(entry2.form_id, entry2.id); + await expect( + pdf.page.getByRole('link', { name: 'View', exact: true }) + ).toBeAttached(); + await expect( + pdf.page.getByRole('link', { name: 'Download', exact: true }) + ).toBeAttached(); + }); + }); + + test.describe('Appearance', () => { + test('Paper', async ({}, testinfo) => { + await pdf.createPdf(form.id, 'Paper'); + + await pdf.selectField('Paper Size', 'CUSTOM'); + + await pdf.page + .locator('#gfpdf_settings\\[custom_pdf_size\\]_measurement') + .selectOption('inches'); + + await pdf.page + .locator('#gfpdf_settings\\[custom_pdf_size\\]_width') + .fill('5'); + + await pdf.page + .locator('#gfpdf_settings\\[custom_pdf_size\\]_height') + .fill('7'); + await pdf.selectField('Paper Orientation', 'landscape'); + + await pdf.addOrUpdatePdf(); + + await pdf.page.waitForTimeout(500); + + await takeSnapshot(pdf.page, testinfo); + }); + + test('Color Picker', async ({}, testinfo) => { + await pdf.createPdf(form.id, 'Color Picker'); + + await pdf.page + .getByRole('button', { name: 'Select Color' }) + .first() + .click(); + + await pdf.page + .locator('.iris-square-inner.iris-square-vert') + .first() + .click({ position: { x: 100, y: 100 } }); + await pdf.page.getByRole('textbox', { name: 'Font Color' }).click(); + + await expect( + pdf.page.getByRole('textbox', { name: 'Font Color' }) + ).toHaveValue('#898989'); + + await takeSnapshot(pdf.page, testinfo); + }); + + test('Reverse Text RTL', async () => { + await pdf.checkField('Reverse Text (RTL)', true); + await pdf.addOrUpdatePdf(); + + await expect( + pdf.page.getByLabel('Reverse Text (RTL)') + ).toBeChecked(); + }); + + test('Background Image / File Upload', async () => { + await pdf.createPdf(form.id, 'File Upload'); + + await pdf.page.getByRole('button', { name: 'Upload File' }).click(); + await pdf.page.getByRole('tab', { name: 'Upload files' }).click(); + await pdf.page + .locator('input[type=file]') + .setInputFiles( + path.join(resourcesPath, 'images', 'thumbnail.jpg') + ); + + await pdf.page + .getByRole('button', { name: 'Select Media' }) + .click(); + + await expect( + pdf.page.getByRole('textbox', { name: 'Background Image' }) + ).toHaveValue(/^http:\/\/localhost.+/); + }); + }); + + test.describe('Template', () => { + test('Rich Text Editor / Header / Footer', async ({}, testinfo) => { + await pdf.createPdf(form.id, 'Rich Text Editor'); + + await pdf.checkRichTextEditor( + pdf.page.locator('#gfpdf-settings-field-wrapper-header') + ); + + await pdf.page + .getByRole('checkbox', { + name: 'Use different header on first', + }) + .check(); + + await pdf.checkRichTextEditor( + pdf.page.locator('#gfpdf-settings-field-wrapper-first_header') + ); + + await takeSnapshot(pdf.page, testinfo); + }); + + test('Show Empty Fields', async () => { + await pdf.checkField('Show Empty Fields', true); + await pdf.addOrUpdatePdf(); + await expect( + pdf.page.getByLabel('Show Empty Fields') + ).toBeChecked(); + }); + + test('Show Form Title', async () => { + await pdf.checkField('Show Form Title', true); + await pdf.addOrUpdatePdf(); + await expect(pdf.page.getByLabel('Show Form Title')).toBeChecked(); + }); + + test('Show Page Names', async () => { + await pdf.checkField('Show Page Names', true); + await pdf.addOrUpdatePdf(); + await expect(pdf.page.getByLabel('Show Page Names')).toBeChecked(); + }); + + test('Show HTML Fields', async () => { + await pdf.checkField('Show HTML Fields', true); + await pdf.addOrUpdatePdf(); + await expect(pdf.page.getByLabel('Show HTML Fields')).toBeChecked(); + }); + + test('Show Section Break Description', async () => { + await pdf.checkField('Show Section Break Description', true); + await pdf.addOrUpdatePdf(); + await expect( + pdf.page.getByLabel('Show Section Break Description') + ).toBeChecked(); + }); + + test('Background Color', async () => { + // Set the color via JavaScript since the wp-color-picker input + // is enhanced and not directly fillable + await pdf.page.evaluate(() => { + const input = document.querySelector( + '#gfpdf_settings\\[background_color\\]' + ) as HTMLInputElement; + if (input) { + input.value = '#1e73be'; + input.dispatchEvent(new Event('change', { bubbles: true })); + } + }); + + await pdf.addOrUpdatePdf(); + + await expect( + pdf.page.locator('#gfpdf_settings\\[background_color\\]') + ).toHaveValue('#1e73be'); + }); + }); + + test.describe('Advanced', () => { + test('PDF Security', async ({}, testinfo) => { + await pdf.createPdf(form.id, 'PDF Security'); + + await expect( + pdf.page.getByRole('textbox', { name: 'Password' }) + ).not.toBeVisible(); + + await expect( + pdf.page.getByRole('checkbox', { + name: 'Print - High Resolution', + }) + ).not.toBeVisible(); + + await pdf.page.getByText('Enable PDF Security').first().click(); + + await expect( + pdf.page.getByRole('textbox', { name: 'Password' }) + ).toBeVisible(); + + await expect( + pdf.page.getByRole('checkbox', { + name: 'Print - High Resolution', + }) + ).toBeVisible(); + + await pdf.page.getByRole('radio', { name: 'PDF/A-1b' }).check(); + + await expect( + pdf.page.getByText('Enable PDF Security').first() + ).not.toBeVisible(); + + await expect( + pdf.page.getByRole('textbox', { name: 'Password' }) + ).not.toBeVisible(); + + await expect( + pdf.page.getByRole('checkbox', { + name: 'Print - High Resolution', + }) + ).not.toBeVisible(); + + await pdf.page.getByRole('radio', { name: 'Standard' }).check(); + + await expect( + pdf.page.getByRole('textbox', { name: 'Password' }) + ).toBeVisible(); + + await expect( + pdf.page.getByRole('checkbox', { + name: 'Print - High Resolution', + }) + ).toBeVisible(); + + await pdf.page + .locator('#gfpdf-settings-field-wrapper-password') + .getByTitle('Insert Merge Tags') + .click(); + + await pdf.page + .getByRole('button', { name: 'Date (dd/mm/yyyy)' }) + .click(); + + await takeSnapshot(pdf.page, testinfo); + }); + + test('Public Access', async () => { + await pdf.checkField('Enable Public Access', true); + await pdf.addOrUpdatePdf(); + await expect( + pdf.page.getByLabel('Enable Public Access') + ).toBeChecked(); + }); + + test('Format', async () => { + await pdf.chooseField('Standard', 'Standard'); + await pdf.chooseField('PDF/A-1b', 'PDF/A-1b'); + + await pdf.addOrUpdatePdf(); + + await expect( + pdf.page.locator('#gfpdf_settings\\[format\\]\\[PDFA1B\\]') + ).toBeChecked(); + }); + + test('Image DPI', async () => { + await pdf.fillField('Image DPI', '150'); + await pdf.addOrUpdatePdf(); + + await expect(pdf.page.getByLabel('Image DPI')).toHaveValue('150'); + }); + + test('Restrict Owner', async () => { + await pdf.checkField('Restrict Owner', true); + await pdf.addOrUpdatePdf(); + + await expect(pdf.page.getByLabel('Restrict Owner')).toBeChecked(); + }); + }); +}); diff --git a/tests/playwright/permalinks/download-mergetag/attributes.spec.ts b/tests/playwright/permalinks/download-mergetag/attributes.spec.ts new file mode 100644 index 000000000..b3680e5ce --- /dev/null +++ b/tests/playwright/permalinks/download-mergetag/attributes.spec.ts @@ -0,0 +1,63 @@ +import { test, expect } from '@wordpress/e2e-test-utils-playwright'; +import type { Admin, RequestUtils } from '@wordpress/e2e-test-utils-playwright'; +import type { Page } from '@playwright/test'; +import Pdf from '@self:playwright/utils/gravitypdf'; + +test.describe('Mergetag attributes', () => { + let pdf = null; + let form = null; + let pdfId = null; + + test.beforeEach( + async ({ + requestUtils, + page, + admin, + }: { + requestUtils: RequestUtils; + page: Page; + admin: Admin; + }) => { + pdf = new Pdf(requestUtils, admin, page); + + // setup form and PDF + form = await pdf.createForm('Mergetag Attributes'); + await pdf.navigateToFormPreview(form.id); + await pdf.submitForm(); + pdfId = await pdf.createPdf(form.id, 'Mergetag'); + + // setup default confirmation + await pdf.navigateToFormConfirmation(form.id); + + // Clear confirmation message and use the mergetag selector + const content = ` + PDF URL: {Mergetag:pdf:${pdfId}} + `; + await pdf.setRichTextContent('#gform_setting_message', content); + await pdf.submitForm(); + } + ); + + test('Check merge tag generates a URL', async ({ + requestUtils, + page, + admin, + }: { + requestUtils: RequestUtils; + page: Page; + admin: Admin; + }) => { + // preview and submit form + await pdf.navigateToFormPreview(form.id); + await pdf.submitForm(); + + // verify the results + const confirmation = await page.locator('#preview_form_container'); + + await expect(confirmation).toContainText( + new RegExp( + `PDF URL: http:\/\/(.+?)\/(\\?gpdf=1&pid=${pdfId}&lid=([0-9]+)|pdf\/${pdfId}\/([0-9]+)\/)` + ) + ); + }); +}); diff --git a/tests/playwright/permalinks/download-mergetag/text-confirmation.spec.ts b/tests/playwright/permalinks/download-mergetag/text-confirmation.spec.ts new file mode 100644 index 000000000..505a3d5c2 --- /dev/null +++ b/tests/playwright/permalinks/download-mergetag/text-confirmation.spec.ts @@ -0,0 +1,50 @@ +import type { Admin, RequestUtils } from '@wordpress/e2e-test-utils-playwright'; +import type { Page } from '@playwright/test'; +import { test } from '@self:playwright/fixtures/test'; +import Pdf from '@self:playwright/utils/gravitypdf'; + +test.describe('{Label:pdf:[id]} Merge Tag', () => { + test('Text Confirmation Mergetag Selector', async ({ + requestUtils, + page, + admin, + }: { + requestUtils: RequestUtils; + page: Page; + admin: Admin; + }) => { + const pdf = new Pdf(requestUtils, admin, page); + + // setup form and PDF + const form = await pdf.createForm('Text Confirmation Mergetag'); + await pdf.navigateToFormPreview(form.id); + await pdf.submitForm(); + await pdf.createPdf(form.id, 'Text Confirmation Mergetag Document'); + + // setup default confirmation + await pdf.navigateToFormConfirmation(form.id); + + // Clear confirmation message and use the mergetag selector + await pdf.setRichTextContent('#gform_setting_message', 'View PDF', + true + ); + await pdf.submitForm(); + + // preview and submit form + await pdf.navigateToFormPreview(form.id); + await pdf.submitForm(); + + // verify the results + const pdfLink = await page.getByRole('link', { name: 'View PDF' }); + + await pdf.downloadAndVerifyPdf( + pdfLink, + 'Text Confirmation Mergetag Document.pdf' + ); + }); +}); diff --git a/tests/playwright/permalinks/download-shortcode/copy-to-clipboard.spec.ts b/tests/playwright/permalinks/download-shortcode/copy-to-clipboard.spec.ts new file mode 100644 index 000000000..05b574a68 --- /dev/null +++ b/tests/playwright/permalinks/download-shortcode/copy-to-clipboard.spec.ts @@ -0,0 +1,36 @@ +import type { Admin, RequestUtils } from '@wordpress/e2e-test-utils-playwright'; +import type { Page } from '@playwright/test'; +import { expect } from '@wordpress/e2e-test-utils-playwright'; +import { test } from '@self:playwright/fixtures/test'; +import Pdf from '@self:playwright/utils/gravitypdf'; +import { takeSnapshot } from '@chromatic-com/playwright'; + +test.describe('[gravitypdf] Shortcode', () => { + test('Copy to Clipboard', async ({ + requestUtils, + page, + admin, + }: { + requestUtils: RequestUtils; + page: Page; + admin: Admin; + }, testinfo) => { + const pdfLabel = 'PDF Clipboard'; + + const pdf = new Pdf(requestUtils, admin, page); + const form = await pdf.createForm('Copy to Clipboard'); + const pdfId = await pdf.createPdf(form.id, pdfLabel); + await pdf.copyDownloadShortcodeToClipboard(form.id, pdfId); + + await takeSnapshot(page, testinfo); + + // Add a new PDF and paste into the Label + await pdf.navigateToNewFormPdf(form.id); + + const label = page.getByLabel('Label'); + await label.press('ControlOrMeta+v'); + await expect(label).toHaveValue( + `[gravitypdf name="${pdfLabel}" id="${pdfId}" text="Download PDF"]` + ); + }); +}); diff --git a/tests/playwright/permalinks/download-shortcode/inactive-pdf.spec.ts b/tests/playwright/permalinks/download-shortcode/inactive-pdf.spec.ts new file mode 100644 index 000000000..490a40e02 --- /dev/null +++ b/tests/playwright/permalinks/download-shortcode/inactive-pdf.spec.ts @@ -0,0 +1,77 @@ +import type { Admin, RequestUtils } from '@wordpress/e2e-test-utils-playwright'; +import type { Page } from '@playwright/test'; +import { expect } from '@wordpress/e2e-test-utils-playwright'; +import { test } from '@self:playwright/fixtures/test'; +import Pdf from '@self:playwright/utils/gravitypdf'; + +test.describe('[gravitypdf] Shortcode', () => { + let pdf = null; + let form = null; + + test.beforeEach( + async ({ + requestUtils, + page, + admin, + }: { + requestUtils: RequestUtils; + page: Page; + admin: Admin; + }) => { + // setup form and inactive PDF + pdf = new Pdf(requestUtils, admin, page); + form = await pdf.createForm('Inactive PDF on Text Confirmation'); + + const pdfId = await pdf.createPdf(form.id, 'Inactive PDF Document'); + await pdf.navigateToFormPdfList(form.id); + await page + .getByRole('button', { name: 'Active', exact: true }) + .click(); + + // setup default confirmation + await pdf.navigateToFormConfirmation(form.id); + await pdf.setRichTextContent( + '#gform_setting_message', + `[gravitypdf id="${pdfId}"]` + ); + await pdf.submitForm(); + } + ); + + test('Disabled PDF, Debug Mode', async ({ + requestUtils, + page, + admin, + }: { + requestUtils: RequestUtils; + page: Page; + admin: Admin; + }) => { + await pdf.setGlobalPdfSetting('Debug Mode', true); + + // preview and submit form + await pdf.navigateToFormPreview(form.id); + await pdf.submitForm(); + + // verify the results + await expect( + page.getByRole('link', { name: 'Download PDF' }) + ).not.toBeAttached(); + await expect(page.getByText('PDF link not displayed')).toContainText( + 'Admin Only Message' + ); + + await pdf.setGlobalPdfSetting('Debug Mode', false); + + // preview and submit form + await pdf.navigateToFormPreview(form.id); + await pdf.submitForm(); + + // verify the results + await expect( + page.getByRole('link', { name: 'Download PDF' }) + ).not.toBeAttached(); + + await expect(page.locator('.gform_confirmation_message')).toBeEmpty(); + }); +}); diff --git a/tests/playwright/permalinks/download-shortcode/page-confirmation.spec.ts b/tests/playwright/permalinks/download-shortcode/page-confirmation.spec.ts new file mode 100644 index 000000000..7836f53a2 --- /dev/null +++ b/tests/playwright/permalinks/download-shortcode/page-confirmation.spec.ts @@ -0,0 +1,72 @@ +import type { + Admin, + Editor, + RequestUtils, +} from '@wordpress/e2e-test-utils-playwright'; +import type { Page } from '@playwright/test'; +import { test } from '@self:playwright/fixtures/test'; +import Pdf from '@self:playwright/utils/gravitypdf'; + +test.describe('[gravitypdf] Shortcode', () => { + test('Page confirmation', async ({ + requestUtils, + page, + admin, + editor, + }: { + requestUtils: RequestUtils; + page: Page; + admin: Admin; + editor: Editor; + }) => { + const pdf = new Pdf(requestUtils, admin, page); + + // setup form and PDF + const form = await pdf.createForm('Page Confirmation'); + const pdfId = await pdf.createPdf( + form.id, + 'Page Confirmation Document' + ); + + // Create Page with shortcode embedded + await admin.createNewPost({ + postType: 'page', + title: 'Gravity PDF Page Confirmation Form', + }); + + await editor.setContent( + '[gravitypdf id="' + + pdfId + + '"]' + ); + await editor.publishPost(); + + // setup default confirmation + await pdf.navigateToFormConfirmation(form.id); + await page.getByRole('radio', { name: 'Page' }).check(); + await page.getByRole('button', { name: 'Select a Page' }).click(); + await page + .getByRole('textbox', { name: 'Search all' }) + .fill('Gravity PDF Page Confirmation Form'); + await page + .getByRole('button', { name: 'Gravity PDF Page Confirmation Form' }) + .first() + .click(); + await page + .getByRole('textbox', { name: 'Data via Query' }) + .fill('entry={entry_id}'); + await pdf.submitForm(); + + // preview and submit form + await pdf.navigateToFormPreview(form.id); + await pdf.submitForm(); + + // verify the results + const pdfLink = page.getByRole('link', { name: 'Download PDF' }); + + await pdf.downloadAndVerifyPdf( + pdfLink, + 'Page Confirmation Document.pdf' + ); + }); +}); diff --git a/tests/playwright/permalinks/download-shortcode/redirect-confirmation.spec.ts b/tests/playwright/permalinks/download-shortcode/redirect-confirmation.spec.ts new file mode 100644 index 000000000..9c332ac2d --- /dev/null +++ b/tests/playwright/permalinks/download-shortcode/redirect-confirmation.spec.ts @@ -0,0 +1,45 @@ +import type { + Admin, + Editor, + RequestUtils, +} from '@wordpress/e2e-test-utils-playwright'; +import type { Page } from '@playwright/test'; +import { test } from '@self:playwright/fixtures/test'; +import Pdf from '@self:playwright/utils/gravitypdf'; + +test.describe('[gravitypdf] Shortcode', () => { + test('Redirect confirmation', async ({ + requestUtils, + page, + admin, + }: { + requestUtils: RequestUtils; + page: Page; + admin: Admin; + editor: Editor; + }) => { + const pdf = new Pdf(requestUtils, admin, page); + + // setup form and PDF + const form = await pdf.createForm('Redirect Confirmation'); + const pdfId = await pdf.createPdf( + form.id, + 'Redirect Confirmation Document' + ); + + // setup default confirmation + await pdf.navigateToFormConfirmation(form.id); + await page.getByRole('radio', { name: 'Redirect' }).check(); + await page + .getByRole('textbox', { name: 'Redirect URL' }) + .fill('[gravitypdf id="' + pdfId + '"]'); + await pdf.submitForm(); + + // preview and submit form + await pdf.navigateToFormPreview(form.id); + await pdf.downloadAndVerifyPdf( + page.getByRole('button', { name: /(save|submit)/i }), + 'Redirect Confirmation Document.pdf' + ); + }); +}); diff --git a/tests/playwright/permalinks/download-shortcode/text-confirmation.spec.ts b/tests/playwright/permalinks/download-shortcode/text-confirmation.spec.ts new file mode 100644 index 000000000..01a292c7f --- /dev/null +++ b/tests/playwright/permalinks/download-shortcode/text-confirmation.spec.ts @@ -0,0 +1,45 @@ +import type { Admin, RequestUtils } from '@wordpress/e2e-test-utils-playwright'; +import type { Page } from '@playwright/test'; +import { test } from '@self:playwright/fixtures/test'; +import Pdf from '@self:playwright/utils/gravitypdf'; + +test.describe('[gravitypdf] Shortcode', () => { + test('Text confirmation', async ({ + requestUtils, + page, + admin, + }: { + requestUtils: RequestUtils; + page: Page; + admin: Admin; + }) => { + const pdf = new Pdf(requestUtils, admin, page); + + // setup form and PDF + const form = await pdf.createForm('Text Confirmation'); + const pdfId = await pdf.createPdf( + form.id, + 'Text Confirmation Document' + ); + + // setup default confirmation + await pdf.navigateToFormConfirmation(form.id); + await pdf.setRichTextContent( + '#gform_setting_message', + `[gravitypdf id="${pdfId}"]` + ); + await pdf.submitForm(); + + // preview and submit form + await pdf.navigateToFormPreview(form.id); + await pdf.submitForm(); + + // verify the results + const pdfLink = page.getByRole('link', { name: 'Download PDF' }); + + await pdf.downloadAndVerifyPdf( + pdfLink, + 'Text Confirmation Document.pdf' + ); + }); +}); diff --git a/tests/playwright/permalinks/managers/font-manager.spec.ts b/tests/playwright/permalinks/managers/font-manager.spec.ts new file mode 100644 index 000000000..cb4a9ceb8 --- /dev/null +++ b/tests/playwright/permalinks/managers/font-manager.spec.ts @@ -0,0 +1,201 @@ +import type { Admin, RequestUtils } from '@wordpress/e2e-test-utils-playwright'; +import { expect } from '@wordpress/e2e-test-utils-playwright'; +import type { Page } from '@playwright/test'; +import { test, resourcesPath } from '@self:playwright/fixtures/test'; +import Pdf from '@self:playwright/utils/gravitypdf'; +import * as path from 'path'; + +test.describe('Font Manager', () => { + let pdf: Pdf; + let form: any; + + test.beforeEach( + async ({ + requestUtils, + page, + admin, + }: { + requestUtils: RequestUtils; + page: Page; + admin: Admin; + }) => { + pdf = new Pdf(requestUtils, admin, page); + form = await pdf.createForm('Font Manager'); + } + ); + + test('should display "Font" field and open Font Manager', async ({ + page, + }) => { + await pdf.navigateToNewFormPdf(form.id); + + await expect(page.getByLabel('Font', { exact: true })).toBeVisible(); + await page + .locator('#gfpdf-settings-field-wrapper-font-container') + .getByRole('button', { name: 'Manage' }) + .click(); + await expect( + page.getByRole('heading', { name: 'Font Manager', exact: true }) + ).toBeVisible(); + }); + + test('should display a dropdown of default fonts option', async ({ + page, + }) => { + await pdf.navigateToNewFormPdf(form.id); + + const select = await page.getByLabel('Font', { exact: true }); + + await expect( + select.locator('optgroup[label="Unicode"]') + ).toBeAttached(); + + await expect(select.locator('optgroup[label="Indic"]')).toBeAttached(); + + await select.selectOption('Dejavu Sans Condensed'); + await select.selectOption('Lohit Kannada'); + }); + + test('should save selected font', async ({ page }) => { + await pdf.navigateToNewFormPdf(form.id); + await page + .getByLabel('Font', { exact: true }) + .selectOption('mph2bdamase'); + + await pdf.addOrUpdatePdf(); + + await expect(page.getByLabel('Font', { exact: true })).toHaveValue( + 'mph2bdamase' + ); + }); + + test('should display font manager error validation', async ({ page }) => { + await pdf.navigateToNewFormPdf(form.id); + await page + .locator('#gfpdf-settings-field-wrapper-font-container') + .getByRole('button', { name: 'Manage' }) + .click(); + + await page + .getByRole('button', { name: 'Add font' }) + .filter({ visible: true }) + .click(); + + await expect( + page.locator('.input-label-validation-error') + ).toBeVisible(); + await expect( + page.getByText( + 'Please choose a name contains letters and/or numbers (and a space if you want it).' + ) + ).toBeVisible(); + await expect(page.locator('.drop-zone.required')).toBeVisible(); + }); + + test('should successfully add, search, edit, and delete new font', async ({ + page, + }) => { + await pdf.navigateToNewFormPdf(form.id); + await page + .locator('#gfpdf-settings-field-wrapper-font-container') + .getByRole('button', { name: 'Manage' }) + .click(); + + // Add Font + await page + .locator('[data-test="component-AddFont"]') + .getByRole('textbox', { name: 'Font Name' }) + .fill('Roboto'); + + await page + .locator('#gfpdf-font-variant-regular-addFont') + .setInputFiles( + path.join(resourcesPath, 'fonts', 'Roboto-Regular.ttf') + ); + + await page + .getByRole('button', { name: 'Add font' }) + .filter({ visible: true }) + .click(); + + await expect(page.getByText('Your font has been saved.')).toBeVisible(); + const fontItems = page.locator('.font-list-item'); + await expect(fontItems).toHaveCount(1); + + // Search Font + await page.locator('#font-manager-search-box').fill('Arial'); + await expect(fontItems).toHaveCount(0); + await page.locator('#font-manager-search-box').fill('Roboto'); + await expect(fontItems).toHaveCount(1); + + const updateButton = page.getByRole('button', { name: 'Update Font' }); + await expect(updateButton).toBeDisabled(); + + await page.locator('#gfpdf-update-font-name-input').fill('Roboto 2'); + await expect(updateButton).not.toBeDisabled(); + + // Cancel button + await page.getByRole('button', { name: 'Cancel' }).click(); + await expect(page.locator('.update-font.show')).not.toBeVisible(); + + // Edit Font properly + await fontItems.first().click(); + await page.locator('#gfpdf-update-font-name-input').fill('Roboto 2'); + await page + .locator('#gfpdf-font-variant-italics-updateFont') + .setInputFiles( + path.join(resourcesPath, 'fonts', 'Roboto-RegularItalic.ttf') + ); + await page + .locator('#gfpdf-font-variant-bold-updateFont') + .setInputFiles( + path.join(resourcesPath, 'fonts', 'Roboto-Bold.ttf') + ); + await page + .locator('#gfpdf-font-variant-bolditalics-updateFont') + .setInputFiles( + path.join(resourcesPath, 'fonts', 'Roboto-BoldItalic.ttf') + ); + + await updateButton.click(); + await expect(page.getByText('Your font has been saved.')).toBeVisible(); + await expect(page.getByText('Roboto 2')).toBeVisible(); + + // Delete Font + page.on('dialog', (dialog) => dialog.accept()); + await fontItems.locator('.dashicons-trash').click(); + await expect(page.getByText('Font list empty.')).toBeVisible(); + }); + + test('should be able to close font manager popup with button', async ({ + page, + }) => { + await pdf.navigateToNewFormPdf(form.id); + await page + .locator('#gfpdf-settings-field-wrapper-font-container') + .getByRole('button', { name: 'Manage' }) + .click(); + + const popup = await page.locator('.container.theme-wrap.font-manager'); + + await expect(popup).toBeVisible(); + await page.locator('[data-test="component-CloseDialog"]').click(); + await expect(popup).not.toBeVisible(); + }); + + test('should be able to close font manager popup with esc key', async ({ + page, + }) => { + await pdf.navigateToNewFormPdf(form.id); + await page + .locator('#gfpdf-settings-field-wrapper-font-container') + .getByRole('button', { name: 'Manage' }) + .click(); + + const popup = await page.locator('.container.theme-wrap.font-manager'); + + await expect(popup).toBeVisible(); + await page.keyboard.press('Escape'); + await expect(popup).not.toBeVisible(); + }); +}); diff --git a/tests/playwright/permalinks/managers/template-manager.spec.ts b/tests/playwright/permalinks/managers/template-manager.spec.ts new file mode 100644 index 000000000..9134a8083 --- /dev/null +++ b/tests/playwright/permalinks/managers/template-manager.spec.ts @@ -0,0 +1,149 @@ +import type { Admin, RequestUtils } from '@wordpress/e2e-test-utils-playwright'; +import { expect } from '@wordpress/e2e-test-utils-playwright'; +import type { Page } from '@playwright/test'; +import { test, resourcesPath } from '@self:playwright/fixtures/test'; +import Pdf from '@self:playwright/utils/gravitypdf'; +import * as path from 'path'; + +test.describe('Template Manager', () => { + let pdf: Pdf; + let form: any; + + test.beforeEach( + async ({ + requestUtils, + page, + admin, + }: { + requestUtils: RequestUtils; + page: Page; + admin: Admin; + }) => { + pdf = new Pdf(requestUtils, admin, page); + form = await pdf.createForm('Template Manager'); + } + ); + + test('should display "Template" field and open Template Manager', async ({ + page, + }) => { + await pdf.navigateToNewFormPdf(form.id); + + const select = page + .getByRole('group', { name: 'General' }) + .getByLabel('Template', { exact: true }); + + await expect(select).toBeVisible(); + await page.locator('[data-test="component-templateButton"]').click(); + await expect( + page.getByRole('heading', { name: 'Installed PDFs' }) + ).toBeVisible(); + }); + + test('should display default core templates', async ({ page }) => { + await pdf.navigateToNewFormPdf(form.id); + + const select = page + .getByRole('group', { name: 'General' }) + .getByLabel('Template', { exact: true }); + + await expect(select.locator('optgroup[label="Core"]')).toBeAttached(); + await select.selectOption('Blank Slate'); + await select.selectOption('Focus Gravity'); + }); + + test('should save selected template', async ({ page }) => { + await pdf.navigateToNewFormPdf(form.id); + + const select = page + .getByRole('group', { name: 'General' }) + .getByLabel('Template', { exact: true }); + + await select.selectOption('rubix'); + await pdf.addOrUpdatePdf(); + + await expect(select).toHaveValue('rubix'); + }); + + test('should successfully search, upload, show details, and delete template', async ({ + page, + }) => { + await pdf.navigateToNewFormPdf(form.id); + await page.locator('[data-test="component-templateButton"]').click(); + + // Search + await page.locator('#wp-filter-search-input').fill('rubix'); + await expect( + page.locator('[data-test=component-templateListItem]') + ).toHaveCount(1); + await expect(page.locator('[data-test=component-name]')).toHaveText( + 'Rubix' + ); + + // Clear search before upload to ensure upload area is accessible + await page.locator('#wp-filter-search-input').fill(''); + + // Upload + await page + .locator( + '[data-test=component-templateUploader] input[type="file"]' + ) + .setInputFiles( + path.join(resourcesPath, 'template', 'test-template.zip') + ); + + // Wait for test template to appear in the list (upload success indicator) + await expect( + page.locator('.theme[data-slug="test-template"]') + ).toBeVisible(); + + // Template Details + await page + .getByRole('option', { name: 'Custom Test Template Details' }) + .locator('[data-test="component-templateDetails"]') + .click(); + + await expect( + page + .locator('[data-test="component-name"]') + .getByText('Test Template') + ).toBeAttached(); + + await expect( + page.locator('[data-test="component-group"]').getByText('Custom') + ).toBeAttached(); + + // Delete + page.on('dialog', (dialog) => dialog.accept()); + await page + .locator('[data-test="component-templateDeleteButton"]') + .click(); + + await expect( + page.locator('.theme[data-slug="test-template"]') + ).not.toBeVisible(); + }); + + test('should be able to close template manager popup button', async ({ + page, + }) => { + await pdf.navigateToNewFormPdf(form.id); + await page.locator('[data-test="component-templateButton"]').click(); + + const popup = page.locator('.container.theme-wrap'); + await page.locator('[data-test="component-CloseDialog"]').click(); + await expect(popup).not.toBeVisible(); + }); + + test('should be able to close template manager popup escape', async ({ + page, + }) => { + await pdf.navigateToNewFormPdf(form.id); + await page.locator('[data-test="component-templateButton"]').click(); + + const popup = page.locator('.container.theme-wrap'); + await popup.focus(); + await page.keyboard.press('Escape'); + await expect(popup).not.toBeVisible(); + }); +}); diff --git a/tools/mu-plugins/admin-styles.php b/tools/mu-plugins/admin-styles.php new file mode 100644 index 000000000..a4d68823b --- /dev/null +++ b/tools/mu-plugins/admin-styles.php @@ -0,0 +1,12 @@ +.row-actions { position: static !important; }' . PHP_EOL; +} + +add_action( 'admin_head', 'override_website_fonts_for_consistent_snapshot_testing' ); diff --git a/tools/mu-plugins/gravityforms.php b/tools/mu-plugins/gravityforms.php new file mode 100644 index 000000000..6fc3622ec --- /dev/null +++ b/tools/mu-plugins/gravityforms.php @@ -0,0 +1,45 @@ +update_plugin_settings( + [ + 'enabled' => '1', + 'version' => 'v2', + ] + ); + }, + 1000 +); diff --git a/tools/mu-plugins/gravitypdf.php b/tools/mu-plugins/gravitypdf.php new file mode 100644 index 000000000..8bd13fa02 --- /dev/null +++ b/tools/mu-plugins/gravitypdf.php @@ -0,0 +1,8 @@ + 'c', + 'biDirectional' => false, + ] + ); +}; + +add_filter( 'gfpdf_mpdf_class_config', $config ); diff --git a/tools/playwright/config.ts b/tools/playwright/config.ts new file mode 100644 index 000000000..d0a373c32 --- /dev/null +++ b/tools/playwright/config.ts @@ -0,0 +1,114 @@ +import { defineConfig, devices } from '@playwright/test'; +import * as path from 'path'; + +process.env.WP_ARTIFACTS_PATH = path.join(process.cwd(), 'tmp/artifacts'); + +import baseConfig = require('@wordpress/scripts/config/playwright.config.js'); + +const config = defineConfig({ + ...baseConfig, + + fullyParallel: true, + workers: 4, + quiet: !!process.env.CI, + maxFailures: process.env.CI ? 5 : 0, + + testDir: undefined, + + reporter: process.env.CI + ? [['github'], ['./flaky-tests-reporter.ts']] + : 'list', + + // Remove the global setup as we now use setup projects per server + globalSetup: undefined, + + webServer: [ + { + ...baseConfig.webServer, + command: 'yarn wp-env:e2e start', + name: 'Core', + port: 8702, + }, + ], + + expect: { + toHaveScreenshot: { maxDiffPixelRatio: 0.1 }, + }, + + use: { + ...baseConfig.use, + baseURL: undefined, + disableAutoSnapshot: true, + ignoreSelectors: [ + '#wpadminbar', + '#adminmenumain', + '#gform-form-toolbar', + ], + }, + + projects: [ + { + name: 'setup-core', + testDir: path.join(process.cwd(), 'tools/playwright'), + testMatch: /.*global-setup\.ts/, + use: { + baseURL: 'http://localhost:8702', + storageState: { cookies: [], origins: [] }, + }, + metadata: { + storageStatePath: path.join( + process.cwd(), + 'tmp/artifacts/storage-states/e2e.json' + ), + }, + }, + + { + name: 'setup-core-with-permalinks', + testDir: path.join(process.cwd(), 'tools/playwright'), + testMatch: /.*global-setup\.ts/, + use: { + baseURL: 'http://localhost:8703', + storageState: { cookies: [], origins: [] }, + }, + metadata: { + storageStatePath: path.join( + process.cwd(), + 'tmp/artifacts/storage-states/e2e-permalinks.json' + ), + }, + }, + + { + name: 'core', + dependencies: ['setup-core'], + testDir: path.join(process.cwd(), 'tests/playwright'), + testMatch: /(core|permalinks)\/.*(test|spec).(js|ts|mjs)/, + use: { + ...devices['Desktop Chrome'], + baseURL: 'http://localhost:8702', + storageState: path.join( + process.cwd(), + 'tmp/artifacts/storage-states/e2e.json' + ), + }, + }, + + { + name: 'core-with-permalinks', + dependencies: ['setup-core-with-permalinks'], + testDir: path.join(process.cwd(), 'tests/playwright'), + testMatch: /permalinks\/.*(test|spec).(js|ts|mjs)/, + use: { + ...devices['Desktop Chrome'], + baseURL: 'http://localhost:8703', + storageState: path.join( + process.cwd(), + 'tmp/artifacts/storage-states/e2e-permalinks.json' + ), + }, + }, + ], +}); + +export default config; diff --git a/tests/e2e/utilities/resources/Roboto-Bold.ttf b/tools/playwright/data/fonts/Roboto-Bold.ttf similarity index 100% rename from tests/e2e/utilities/resources/Roboto-Bold.ttf rename to tools/playwright/data/fonts/Roboto-Bold.ttf diff --git a/tests/e2e/utilities/resources/Roboto-BoldItalic.ttf b/tools/playwright/data/fonts/Roboto-BoldItalic.ttf similarity index 100% rename from tests/e2e/utilities/resources/Roboto-BoldItalic.ttf rename to tools/playwright/data/fonts/Roboto-BoldItalic.ttf diff --git a/tests/e2e/utilities/resources/Roboto-Regular.ttf b/tools/playwright/data/fonts/Roboto-Regular.ttf similarity index 100% rename from tests/e2e/utilities/resources/Roboto-Regular.ttf rename to tools/playwright/data/fonts/Roboto-Regular.ttf diff --git a/tests/e2e/utilities/resources/Roboto-RegularItalic.ttf b/tools/playwright/data/fonts/Roboto-RegularItalic.ttf similarity index 100% rename from tests/e2e/utilities/resources/Roboto-RegularItalic.ttf rename to tools/playwright/data/fonts/Roboto-RegularItalic.ttf diff --git a/tools/playwright/data/forms/standard.json b/tools/playwright/data/forms/standard.json new file mode 100644 index 000000000..5f2d7ce4d --- /dev/null +++ b/tools/playwright/data/forms/standard.json @@ -0,0 +1,1263 @@ +{ + "title": "Standard test", + "description": "", + "labelPlacement": "top_label", + "descriptionPlacement": "below", + "button": { + "type": "text", + "text": "Submit", + "imageUrl": "", + "conditionalLogic": { + "actionType": "show", + "logicType": "all", + "rules": [ + { + "fieldId": "2", + "operator": "isnot", + "value": "First Choice" + } + ] + } + }, + "fields": [ + { + "type": "radio", + "adminLabel": "", + "adminOnly": "", + "allowsPrepopulate": false, + "defaultValue": "", + "description": "", + "content": "", + "cssClass": "", + "errorMessage": "", + "id": 1, + "inputName": "", + "isRequired": false, + "label": "Radio", + "noDuplicates": "", + "size": "medium", + "postCustomFieldName": "", + "displayAllCategories": false, + "displayCaption": "", + "displayDescription": "", + "displayTitle": "", + "inputType": "", + "rangeMin": "", + "rangeMax": "", + "calendarIconUrl": "", + "dateFormat": "", + "phoneFormat": "", + "defaultCountry": "", + "defaultProvince": "", + "defaultState": "", + "hideAddress2": "", + "hideCountry": "", + "hideState": "", + "inputs": null, + "nameFormat": "", + "allowedExtensions": "", + "captchaType": "", + "captchaTheme": "", + "simpleCaptchaSize": "", + "simpleCaptchaFontColor": "", + "simpleCaptchaBackgroundColor": "", + "failed_validation": "", + "productField": "", + "enablePasswordInput": "", + "maxLength": "", + "enablePrice": "", + "basePrice": "", + "choices": [ + { + "text": "First Choice", + "value": "First Choice", + "isSelected": false, + "price": "" + }, + { + "text": "Second Choice", + "value": "Second Choice", + "isSelected": false, + "price": "" + }, + { + "text": "Third Choice", + "value": "Third Choice", + "isSelected": false, + "price": "" + } + ], + "formId": 68, + "descriptionPlacement": "below", + "calculationFormula": "", + "calculationRounding": "", + "enableCalculation": "", + "disableQuantity": false, + "inputMask": false, + "inputMaskValue": "", + "displayOnly": "", + "labelPlacement": "", + "subLabelPlacement": "", + "placeholder": "", + "multipleFiles": false, + "maxFiles": "", + "conditionalLogic": "" + }, + { + "type": "checkbox", + "adminLabel": "", + "adminOnly": "", + "allowsPrepopulate": false, + "defaultValue": "", + "description": "", + "content": "", + "cssClass": "", + "errorMessage": "", + "id": 2, + "inputName": "", + "isRequired": false, + "label": "Checkbox", + "noDuplicates": "", + "size": "medium", + "postCustomFieldName": "", + "displayAllCategories": false, + "displayCaption": "", + "displayDescription": "", + "displayTitle": "", + "inputType": "", + "rangeMin": "", + "rangeMax": "", + "calendarIconUrl": "", + "dateFormat": "", + "phoneFormat": "", + "defaultCountry": "", + "defaultProvince": "", + "defaultState": "", + "hideAddress2": "", + "hideCountry": "", + "hideState": "", + "inputs": [ + { + "id": 2.1, + "label": "First Choice", + "name": "" + }, + { + "id": 2.2, + "label": "Second Choice", + "name": "" + }, + { + "id": 2.3, + "label": "Third Choice", + "name": "" + } + ], + "nameFormat": "", + "allowedExtensions": "", + "captchaType": "", + "captchaTheme": "", + "simpleCaptchaSize": "", + "simpleCaptchaFontColor": "", + "simpleCaptchaBackgroundColor": "", + "failed_validation": "", + "productField": "", + "enablePasswordInput": "", + "maxLength": "", + "enablePrice": "", + "basePrice": "", + "choices": [ + { + "text": "First Choice", + "value": "First Choice", + "isSelected": false, + "price": "" + }, + { + "text": "Second Choice", + "value": "Second Choice", + "isSelected": false, + "price": "" + }, + { + "text": "Third Choice", + "value": "Third Choice", + "isSelected": false, + "price": "" + } + ], + "formId": 68, + "descriptionPlacement": "below", + "calculationFormula": "", + "calculationRounding": "", + "enableCalculation": "", + "disableQuantity": false, + "inputMask": false, + "inputMaskValue": "", + "displayOnly": "", + "labelPlacement": "", + "subLabelPlacement": "", + "placeholder": "", + "multipleFiles": false, + "maxFiles": "", + "conditionalLogic": "" + }, + { + "type": "html", + "adminLabel": "", + "adminOnly": "", + "allowsPrepopulate": false, + "defaultValue": "", + "description": "", + "content": "", + "cssClass": "", + "errorMessage": "", + "id": 3, + "inputName": "", + "isRequired": false, + "label": "HTML Block", + "noDuplicates": "", + "size": "medium", + "postCustomFieldName": "", + "displayAllCategories": false, + "displayCaption": "", + "displayDescription": "", + "displayTitle": "", + "inputType": "", + "rangeMin": "", + "rangeMax": "", + "calendarIconUrl": "", + "dateFormat": "", + "phoneFormat": "", + "defaultCountry": "", + "defaultProvince": "", + "defaultState": "", + "hideAddress2": "", + "hideCountry": "", + "hideState": "", + "inputs": null, + "nameFormat": "", + "allowedExtensions": "", + "captchaType": "", + "captchaTheme": "", + "simpleCaptchaSize": "", + "simpleCaptchaFontColor": "", + "simpleCaptchaBackgroundColor": "", + "failed_validation": "", + "productField": "", + "enablePasswordInput": "", + "maxLength": "", + "enablePrice": "", + "basePrice": "", + "displayOnly": true, + "formId": 68, + "descriptionPlacement": "below", + "labelPlacement": "", + "subLabelPlacement": "", + "placeholder": "", + "multipleFiles": false, + "maxFiles": "", + "calculationFormula": "", + "calculationRounding": "", + "enableCalculation": "", + "disableQuantity": false, + "inputMask": false, + "inputMaskValue": "", + "choices": "", + "conditionalLogic": "" + }, + { + "type": "multiselect", + "adminLabel": "", + "adminOnly": "", + "allowsPrepopulate": false, + "defaultValue": "", + "description": "", + "content": "", + "cssClass": "", + "errorMessage": "", + "id": 4, + "inputName": "", + "isRequired": false, + "label": "Multi select", + "noDuplicates": "", + "size": "medium", + "postCustomFieldName": "", + "displayAllCategories": false, + "displayCaption": "", + "displayDescription": "", + "displayTitle": "", + "inputType": "", + "rangeMin": "", + "rangeMax": "", + "calendarIconUrl": "", + "dateFormat": "", + "phoneFormat": "", + "defaultCountry": "", + "defaultProvince": "", + "defaultState": "", + "hideAddress2": "", + "hideCountry": "", + "hideState": "", + "inputs": null, + "nameFormat": "", + "allowedExtensions": "", + "captchaType": "", + "captchaTheme": "", + "simpleCaptchaSize": "", + "simpleCaptchaFontColor": "", + "simpleCaptchaBackgroundColor": "", + "failed_validation": "", + "productField": "", + "enablePasswordInput": "", + "maxLength": "", + "enablePrice": "", + "basePrice": "", + "choices": [ + { + "text": "First Choice", + "value": "First Choice", + "isSelected": false, + "price": "" + }, + { + "text": "Second Choice", + "value": "Second Choice", + "isSelected": false, + "price": "" + }, + { + "text": "Third Choice", + "value": "Third Choice", + "isSelected": false, + "price": "" + } + ], + "calculationFormula": "", + "calculationRounding": "", + "enableCalculation": "", + "disableQuantity": false, + "inputMask": false, + "inputMaskValue": "", + "formId": 68, + "descriptionPlacement": "below", + "displayOnly": "", + "conditionalLogic": "" + }, + { + "type": "text", + "adminLabel": "", + "adminOnly": "", + "allowsPrepopulate": false, + "defaultValue": "", + "description": "", + "content": "", + "cssClass": "", + "errorMessage": "", + "id": 5, + "inputName": "", + "isRequired": false, + "label": "Untitled", + "noDuplicates": "", + "size": "medium", + "postCustomFieldName": "", + "displayAllCategories": false, + "displayCaption": "", + "displayDescription": "", + "displayTitle": "", + "inputType": "", + "rangeMin": "", + "rangeMax": "", + "calendarIconUrl": "", + "dateFormat": "", + "phoneFormat": "", + "defaultCountry": "", + "defaultProvince": "", + "defaultState": "", + "hideAddress2": "", + "hideCountry": "", + "hideState": "", + "inputs": null, + "nameFormat": "", + "allowedExtensions": "", + "captchaType": "", + "captchaTheme": "", + "simpleCaptchaSize": "", + "simpleCaptchaFontColor": "", + "simpleCaptchaBackgroundColor": "", + "failed_validation": "", + "productField": "", + "enablePasswordInput": "", + "maxLength": "", + "enablePrice": "", + "basePrice": "", + "formId": 68, + "descriptionPlacement": "below", + "displayOnly": "", + "labelPlacement": "", + "subLabelPlacement": "", + "placeholder": "", + "multipleFiles": false, + "maxFiles": "", + "calculationFormula": "", + "calculationRounding": "", + "enableCalculation": "", + "disableQuantity": false, + "inputMask": false, + "inputMaskValue": "", + "choices": "", + "conditionalLogic": "" + }, + { + "type": "textarea", + "adminLabel": "", + "adminOnly": "", + "allowsPrepopulate": false, + "defaultValue": "", + "description": "", + "content": "", + "cssClass": "", + "errorMessage": "", + "id": 6, + "inputName": "", + "isRequired": false, + "label": "Untitled", + "noDuplicates": "", + "size": "medium", + "postCustomFieldName": "", + "displayAllCategories": false, + "displayCaption": "", + "displayDescription": "", + "displayTitle": "", + "inputType": "", + "rangeMin": "", + "rangeMax": "", + "calendarIconUrl": "", + "dateFormat": "", + "phoneFormat": "", + "defaultCountry": "", + "defaultProvince": "", + "defaultState": "", + "hideAddress2": "", + "hideCountry": "", + "hideState": "", + "inputs": null, + "nameFormat": "", + "allowedExtensions": "", + "captchaType": "", + "captchaTheme": "", + "simpleCaptchaSize": "", + "simpleCaptchaFontColor": "", + "simpleCaptchaBackgroundColor": "", + "failed_validation": "", + "productField": "", + "enablePasswordInput": "", + "maxLength": "", + "enablePrice": "", + "basePrice": "", + "formId": 68, + "descriptionPlacement": "below", + "displayOnly": "", + "labelPlacement": "", + "subLabelPlacement": "", + "placeholder": "", + "multipleFiles": false, + "maxFiles": "", + "calculationFormula": "", + "calculationRounding": "", + "enableCalculation": "", + "disableQuantity": false, + "inputMask": false, + "inputMaskValue": "", + "choices": "", + "conditionalLogic": "" + }, + { + "type": "select", + "adminLabel": "", + "adminOnly": "", + "allowsPrepopulate": false, + "defaultValue": "", + "description": "", + "content": "", + "cssClass": "", + "errorMessage": "", + "id": 7, + "inputName": "", + "isRequired": false, + "label": "Untitled", + "noDuplicates": "", + "size": "medium", + "postCustomFieldName": "", + "displayAllCategories": false, + "displayCaption": "", + "displayDescription": "", + "displayTitle": "", + "inputType": "", + "rangeMin": "", + "rangeMax": "", + "calendarIconUrl": "", + "dateFormat": "", + "phoneFormat": "", + "defaultCountry": "", + "defaultProvince": "", + "defaultState": "", + "hideAddress2": "", + "hideCountry": "", + "hideState": "", + "inputs": null, + "nameFormat": "", + "allowedExtensions": "", + "captchaType": "", + "captchaTheme": "", + "simpleCaptchaSize": "", + "simpleCaptchaFontColor": "", + "simpleCaptchaBackgroundColor": "", + "failed_validation": "", + "productField": "", + "enablePasswordInput": "", + "maxLength": "", + "enablePrice": "", + "basePrice": "", + "choices": [ + { + "text": "First Choice", + "value": "First Choice", + "isSelected": false, + "price": "" + }, + { + "text": "Second Choice", + "value": "Second Choice", + "isSelected": false, + "price": "" + }, + { + "text": "Third Choice", + "value": "Third Choice", + "isSelected": false, + "price": "" + } + ], + "formId": 68, + "descriptionPlacement": "below", + "displayOnly": "", + "labelPlacement": "", + "subLabelPlacement": "", + "placeholder": "", + "multipleFiles": false, + "maxFiles": "", + "calculationFormula": "", + "calculationRounding": "", + "enableCalculation": "", + "disableQuantity": false, + "inputMask": false, + "inputMaskValue": "", + "conditionalLogic": "" + }, + { + "type": "number", + "adminLabel": "", + "adminOnly": "", + "allowsPrepopulate": false, + "defaultValue": "", + "description": "", + "content": "", + "cssClass": "", + "errorMessage": "", + "id": 8, + "inputName": "", + "isRequired": false, + "label": "Number", + "noDuplicates": "", + "size": "medium", + "postCustomFieldName": "", + "displayAllCategories": false, + "displayCaption": "", + "displayDescription": "", + "displayTitle": "", + "inputType": "", + "rangeMin": "", + "rangeMax": "", + "calendarIconUrl": "", + "dateFormat": "", + "phoneFormat": "", + "defaultCountry": "", + "defaultProvince": "", + "defaultState": "", + "hideAddress2": "", + "hideCountry": "", + "hideState": "", + "inputs": null, + "nameFormat": "", + "allowedExtensions": "", + "captchaType": "", + "captchaTheme": "", + "simpleCaptchaSize": "", + "simpleCaptchaFontColor": "", + "simpleCaptchaBackgroundColor": "", + "failed_validation": "", + "productField": "", + "enablePasswordInput": "", + "maxLength": "", + "enablePrice": "", + "basePrice": "", + "numberFormat": "decimal_dot", + "formId": 68, + "descriptionPlacement": "below", + "displayOnly": "", + "labelPlacement": "", + "subLabelPlacement": "", + "placeholder": "", + "multipleFiles": false, + "maxFiles": "", + "calculationFormula": "", + "calculationRounding": "", + "enableCalculation": "", + "disableQuantity": false, + "inputMask": false, + "inputMaskValue": "", + "choices": "", + "conditionalLogic": "" + }, + { + "type": "radio", + "adminLabel": "", + "adminOnly": "", + "allowsPrepopulate": false, + "defaultValue": "", + "description": "", + "content": "", + "cssClass": "", + "errorMessage": "", + "id": 9, + "inputName": "", + "isRequired": false, + "label": "Untitled", + "noDuplicates": "", + "size": "medium", + "postCustomFieldName": "", + "displayAllCategories": false, + "displayCaption": "", + "displayDescription": "", + "displayTitle": "", + "inputType": "", + "rangeMin": "", + "rangeMax": "", + "calendarIconUrl": "", + "dateFormat": "", + "phoneFormat": "", + "defaultCountry": "", + "defaultProvince": "", + "defaultState": "", + "hideAddress2": "", + "hideCountry": "", + "hideState": "", + "inputs": null, + "nameFormat": "", + "allowedExtensions": "", + "captchaType": "", + "captchaTheme": "", + "simpleCaptchaSize": "", + "simpleCaptchaFontColor": "", + "simpleCaptchaBackgroundColor": "", + "failed_validation": "", + "productField": "", + "enablePasswordInput": "", + "maxLength": "", + "enablePrice": "", + "basePrice": "", + "choices": [ + { + "text": "First Choice", + "value": "First Choice", + "isSelected": false, + "price": "" + }, + { + "text": "Second Choice", + "value": "Second Choice", + "isSelected": false, + "price": "" + }, + { + "text": "Third Choice", + "value": "Third Choice", + "isSelected": false, + "price": "" + } + ], + "formId": 68, + "descriptionPlacement": "below", + "displayOnly": "", + "labelPlacement": "", + "subLabelPlacement": "", + "placeholder": "", + "multipleFiles": false, + "maxFiles": "", + "calculationFormula": "", + "calculationRounding": "", + "enableCalculation": "", + "disableQuantity": false, + "inputMask": false, + "inputMaskValue": "", + "conditionalLogic": "" + }, + { + "type": "date", + "adminLabel": "", + "adminOnly": "", + "allowsPrepopulate": false, + "defaultValue": "", + "description": "", + "content": "", + "cssClass": "", + "errorMessage": "", + "id": 10, + "inputName": "", + "isRequired": false, + "label": "Date", + "noDuplicates": "", + "size": "medium", + "postCustomFieldName": "", + "displayAllCategories": false, + "displayCaption": "", + "displayDescription": "", + "displayTitle": "", + "inputType": "", + "rangeMin": "", + "rangeMax": "", + "calendarIconType": "", + "calendarIconUrl": "", + "dateType": "datepicker", + "dateFormat": "", + "phoneFormat": "", + "defaultCountry": "", + "defaultProvince": "", + "defaultState": "", + "hideAddress2": "", + "hideCountry": "", + "hideState": "", + "inputs": null, + "nameFormat": "", + "allowedExtensions": "", + "captchaType": "", + "captchaTheme": "", + "simpleCaptchaSize": "", + "simpleCaptchaFontColor": "", + "simpleCaptchaBackgroundColor": "", + "failed_validation": "", + "productField": "", + "enablePasswordInput": "", + "maxLength": "", + "enablePrice": "", + "basePrice": "", + "formId": 68, + "descriptionPlacement": "below", + "displayOnly": "", + "labelPlacement": "", + "subLabelPlacement": "", + "placeholder": "", + "multipleFiles": false, + "maxFiles": "", + "calculationFormula": "", + "calculationRounding": "", + "enableCalculation": "", + "disableQuantity": false, + "inputMask": false, + "inputMaskValue": "", + "choices": "", + "conditionalLogic": "" + }, + { + "type": "time", + "adminLabel": "", + "adminOnly": "", + "allowsPrepopulate": false, + "defaultValue": "", + "description": "", + "content": "", + "cssClass": "", + "errorMessage": "", + "id": 11, + "inputName": "", + "isRequired": false, + "label": "Time", + "noDuplicates": "", + "size": "medium", + "postCustomFieldName": "", + "displayAllCategories": false, + "displayCaption": "", + "displayDescription": "", + "displayTitle": "", + "inputType": "", + "rangeMin": "", + "rangeMax": "", + "calendarIconUrl": "", + "dateFormat": "", + "phoneFormat": "", + "defaultCountry": "", + "defaultProvince": "", + "defaultState": "", + "hideAddress2": "", + "hideCountry": "", + "hideState": "", + "inputs": [ + { + "id": "11.1", + "label": "HH", + "name": "" + }, + { + "id": "11.2", + "label": "MM", + "name": "" + }, + { + "id": "11.3", + "label": "AM/PM", + "name": "" + } + ], + "nameFormat": "", + "allowedExtensions": "", + "captchaType": "", + "captchaTheme": "", + "simpleCaptchaSize": "", + "simpleCaptchaFontColor": "", + "simpleCaptchaBackgroundColor": "", + "failed_validation": "", + "productField": "", + "enablePasswordInput": "", + "maxLength": "", + "enablePrice": "", + "basePrice": "", + "formId": 68, + "descriptionPlacement": "below", + "displayOnly": "", + "labelPlacement": "", + "subLabelPlacement": "", + "placeholder": "", + "multipleFiles": false, + "maxFiles": "", + "calculationFormula": "", + "calculationRounding": "", + "enableCalculation": "", + "disableQuantity": false, + "inputMask": false, + "inputMaskValue": "", + "choices": "", + "conditionalLogic": "" + }, + { + "type": "phone", + "adminLabel": "", + "adminOnly": "", + "allowsPrepopulate": false, + "defaultValue": "", + "description": "", + "content": "", + "cssClass": "", + "errorMessage": "", + "id": 12, + "inputName": "", + "isRequired": false, + "label": "Phone", + "noDuplicates": "", + "size": "medium", + "postCustomFieldName": "", + "displayAllCategories": false, + "displayCaption": "", + "displayDescription": "", + "displayTitle": "", + "inputType": "", + "rangeMin": "", + "rangeMax": "", + "calendarIconUrl": "", + "dateFormat": "", + "phoneFormat": "standard", + "defaultCountry": "", + "defaultProvince": "", + "defaultState": "", + "hideAddress2": "", + "hideCountry": "", + "hideState": "", + "inputs": null, + "nameFormat": "", + "allowedExtensions": "", + "captchaType": "", + "captchaTheme": "", + "simpleCaptchaSize": "", + "simpleCaptchaFontColor": "", + "simpleCaptchaBackgroundColor": "", + "failed_validation": "", + "productField": "", + "enablePasswordInput": "", + "maxLength": "", + "enablePrice": "", + "basePrice": "", + "formId": 68, + "descriptionPlacement": "below", + "displayOnly": "", + "labelPlacement": "", + "subLabelPlacement": "", + "placeholder": "", + "multipleFiles": false, + "maxFiles": "", + "calculationFormula": "", + "calculationRounding": "", + "enableCalculation": "", + "disableQuantity": false, + "inputMask": false, + "inputMaskValue": "", + "choices": "", + "conditionalLogic": "" + }, + { + "type": "address", + "adminLabel": "", + "adminOnly": "", + "allowsPrepopulate": false, + "defaultValue": "", + "description": "", + "content": "", + "cssClass": "", + "errorMessage": "", + "id": 13, + "inputName": "", + "isRequired": false, + "label": "Address", + "noDuplicates": "", + "size": "medium", + "postCustomFieldName": "", + "displayAllCategories": false, + "displayCaption": "", + "displayDescription": "", + "displayTitle": "", + "inputType": "", + "rangeMin": "", + "rangeMax": "", + "calendarIconUrl": "", + "dateFormat": "", + "phoneFormat": "", + "addressType": "", + "defaultCountry": "", + "defaultProvince": "", + "defaultState": "", + "inputs": [ + { + "id": 13.1, + "label": "Street Address", + "name": "" + }, + { + "id": 13.2, + "label": "Address Line 2", + "name": "" + }, + { + "id": 13.3, + "label": "City", + "name": "" + }, + { + "id": 13.4, + "label": "State / Province", + "name": "" + }, + { + "id": 13.5, + "label": "ZIP / Postal Code", + "name": "" + }, + { + "id": 13.6, + "label": "Country", + "name": "" + } + ], + "nameFormat": "", + "allowedExtensions": "", + "captchaType": "", + "captchaTheme": "", + "simpleCaptchaSize": "", + "simpleCaptchaFontColor": "", + "simpleCaptchaBackgroundColor": "", + "failed_validation": "", + "productField": "", + "enablePasswordInput": "", + "maxLength": "", + "enablePrice": "", + "basePrice": "", + "formId": 68, + "descriptionPlacement": "below", + "displayOnly": "", + "labelPlacement": "", + "subLabelPlacement": "", + "placeholder": "", + "multipleFiles": false, + "maxFiles": "", + "calculationFormula": "", + "calculationRounding": "", + "enableCalculation": "", + "disableQuantity": false, + "inputMask": false, + "inputMaskValue": "", + "choices": "", + "conditionalLogic": "" + }, + { + "type": "website", + "adminLabel": "", + "adminOnly": "", + "allowsPrepopulate": false, + "defaultValue": "", + "description": "", + "content": "", + "cssClass": "", + "errorMessage": "", + "id": 14, + "inputName": "", + "isRequired": false, + "label": "Website", + "noDuplicates": "", + "size": "medium", + "postCustomFieldName": "", + "displayAllCategories": false, + "displayCaption": "", + "displayDescription": "", + "displayTitle": "", + "inputType": "", + "rangeMin": "", + "rangeMax": "", + "calendarIconUrl": "", + "dateFormat": "", + "phoneFormat": "", + "defaultCountry": "", + "defaultProvince": "", + "defaultState": "", + "hideAddress2": "", + "hideCountry": "", + "hideState": "", + "inputs": null, + "nameFormat": "", + "allowedExtensions": "", + "captchaType": "", + "captchaTheme": "", + "simpleCaptchaSize": "", + "simpleCaptchaFontColor": "", + "simpleCaptchaBackgroundColor": "", + "failed_validation": "", + "productField": "", + "enablePasswordInput": "", + "maxLength": "", + "enablePrice": "", + "basePrice": "", + "formId": 68, + "descriptionPlacement": "below", + "displayOnly": "", + "labelPlacement": "", + "subLabelPlacement": "", + "placeholder": "", + "multipleFiles": false, + "maxFiles": "", + "calculationFormula": "", + "calculationRounding": "", + "enableCalculation": "", + "disableQuantity": false, + "inputMask": false, + "inputMaskValue": "", + "choices": "", + "conditionalLogic": "" + }, + { + "type": "list", + "adminLabel": "", + "adminOnly": "", + "allowsPrepopulate": false, + "defaultValue": "", + "description": "", + "content": "", + "cssClass": "", + "errorMessage": "", + "id": 15, + "inputName": "", + "isRequired": false, + "label": "List", + "noDuplicates": "", + "size": "medium", + "postCustomFieldName": "", + "displayAllCategories": false, + "displayCaption": "", + "displayDescription": "", + "displayTitle": "", + "inputType": "", + "rangeMin": "", + "rangeMax": "", + "calendarIconUrl": "", + "dateFormat": "", + "phoneFormat": "", + "defaultCountry": "", + "defaultProvince": "", + "defaultState": "", + "hideAddress2": "", + "hideCountry": "", + "hideState": "", + "inputs": null, + "nameFormat": "", + "allowedExtensions": "", + "captchaType": "", + "captchaTheme": "", + "simpleCaptchaSize": "", + "simpleCaptchaFontColor": "", + "simpleCaptchaBackgroundColor": "", + "failed_validation": "", + "productField": "", + "enablePasswordInput": "", + "maxLength": "", + "enablePrice": "", + "basePrice": "", + "formId": 68, + "descriptionPlacement": "below", + "displayOnly": "", + "labelPlacement": "", + "subLabelPlacement": "", + "placeholder": "", + "multipleFiles": false, + "maxFiles": "", + "calculationFormula": "", + "calculationRounding": "", + "enableCalculation": "", + "disableQuantity": false, + "inputMask": false, + "inputMaskValue": "", + "choices": "", + "conditionalLogic": "" + } + ], + "id": 68, + "useCurrentUserAsAuthor": true, + "postContentTemplateEnabled": false, + "postTitleTemplateEnabled": false, + "postTitleTemplate": "", + "postContentTemplate": "", + "lastPageButton": null, + "pagination": null, + "firstPageCssClass": null, + "gravityformsquiz": { + "grading": "none", + "passPercent": "50", + "failConfirmationMessage": "Quiz Results: You Failed!\nCorrect Answers: {quiz_score}\nPercentage: {quiz_percent}%", + "passConfirmationMessage": "Quiz Results: You Passed!\nCorrect Answers: {quiz_score}\nPercentage: {quiz_percent}%", + "letterConfirmationMessage": "Quiz Grade: {quiz_grade}\nCorrect Answers: {quiz_score}\nPercentage: {quiz_percent}%", + "grades": [ + { + "text": "A", + "value": 90 + }, + { + "text": "B", + "value": 80 + }, + { + "text": "C", + "value": 70 + }, + { + "text": "D", + "value": 60 + }, + { + "text": "E", + "value": 0 + } + ], + "passConfirmationDisableAutoformat": false, + "failConfirmationDisableAutoformat": false, + "letterConfirmationDisableAutoformat": false, + "shuffleFields": false + }, + "gravityformspolls": { + "displayResults": true, + "showResultsLink": true, + "showPercentages": true, + "showCounts": true, + "blockRepeatVoters": false, + "style": "green", + "cookie": "1 month" + }, + "cssClass": "", + "enableHoneypot": "", + "enableAnimation": "", + "limitEntries": "", + "limitEntriesCount": "", + "limitEntriesPeriod": "", + "limitEntriesMessage": "", + "scheduleForm": "", + "scheduleStart": "", + "scheduleStartHour": "", + "scheduleStartMinute": "", + "scheduleStartAmpm": "", + "scheduleEnd": "", + "scheduleEndHour": "", + "scheduleEndMinute": "", + "scheduleEndAmpm": "", + "schedulePendingMessage": "", + "scheduleMessage": "", + "requireLogin": "", + "requireLoginMessage": "", + "is_active": "1", + "is_trash": "0", + "date_created": "2013-03-21 21:13:56", + "confirmations": [ + { + "id": "514b78146ede6", + "name": "Default Confirmation", + "isDefault": true, + "type": "message", + "message": "Thanks for contacting us! We will get in touch with you shortly.", + "url": "", + "pageId": "", + "queryString": "" + } + ], + "notifications": [ + { + "id": "52246fd7af858", + "name": "Admin Notification", + "event": "form_submission", + "to": "stevehenty@gmail.com", + "toType": "email", + "bcc": "", + "subject": "ser", + "message": "esr", + "from": "{admin_email}", + "fromName": "", + "replyTo": "", + "routing": null, + "conditionalLogic": { + "actionType": "show", + "logicType": "all", + "rules": [ + { + "fieldId": "2", + "operator": "is", + "value": "Third Choice" + }, + { + "fieldId": "6", + "operator": "is", + "value": "zdfgdf666" + }, + { + "fieldId": "1", + "operator": "is", + "value": "Third Choice" + } + ] + }, + "disableAutoformat": "", + "isActive": false + } + ] +} diff --git a/tools/playwright/data/images/thumbnail.jpg b/tools/playwright/data/images/thumbnail.jpg new file mode 100644 index 0000000000000000000000000000000000000000..000fe84a1d3c4b0316d16290a7eef2cfa6d3b94f GIT binary patch literal 11142 zcmb_?2UwF!x9&#~P!U7~>7Z2U2{lwv=>k%fE=_tT5NZV6f{3s|iXwsvNGBq_i*#v1 zfY4ij&>_?i0-Wf-&;Iw`=iK|;=bSrvCf|H()~s3Ynl)=?GC3PPn*}awscEVKBqRVp zLi_+{b3nZ+%=s|@Xle=qQ~&@_09Q!Jepda;EF|ZCJ+q1Ltbde?h-HC4cu0w5deVRM zJ4ccK;x{4Ee`*^K=)3*?5V8M8(Ab1(+Pn-OJs< z&xQ-;?&jeu2UFz##U@8A|0Ij?D_!9FBPsaUKbAANtM&&g@lBEc59t8`0ippCqMkmE zVju_vA|?(N1A|3~93sAf9)3135f5K(qNKlzy6fO;=i}_<=j`dh^;5KsttZq^k)Quh zu79ayZ}(?6UQi#mU!B<7i8;7AxI1|G`4WME{-&k9ot&SupPR!!6jyQc`v=9%`6m)N zHyaN}MShrwy~AT0sGA?ZlA(>emz#r#nzNgO?@x1aiE#P;B3V1T+c-K{`#C|~Z9Qz9 z-K<@_9IZi8;xJ;i28oMGx!Nj-{Y2vC{FknNQU2b$*ngwrFSfs!OQJ_D~{A=)S?0?!!{BJh)gZ`BDuO|ORlA7&LL0~Dcv=js+36g*e~CPQ^%Wws+%HG*^fB`E zbW^%xEWCXD0yhOErKDwKA#!)_s;a4LXlfZ68Jj$KXliChjERm;&Mv-wQ2zi} zU{K`K-=0N9KaWX#m6V*4`ua`U$E@s}Pq}&d1z*a_D=Mq1Yihr>w6?W(bas6oL=Fv) zphm~W=jPE1i%Xd0l~wG{?%w{vA?^tO6Bh|U_NU4ITU>NRT%_dWWaN}TagmS)5HlGa z`MK*LiYqGmls4YX-)R!{!UA@Ja0X-~J;kuivf(2;a;s3KSqkY9 zppD;yc9F`(fS5v96NbnVF-VQhC@%-}Rj*Q-2ZhO;0bCzr1oi>q*ERFd>6i(^Xkx!o&g>PAp-)Fg@O)%RDtgn%nC$qxW}6q8cY zeR3m1N}U#-S!(FAn!4U@`rvkpEOQ63Q>BU@WO<+R6{*-Bd8zNP-yHg>^3Pme7g|n8 zBkb)zx~i|C7OIXc2Jw0n-EpmtDc* zgYT1lk%(JLi4k<%Zc1Hxa&wu|%12o=ia@(`^SyoenjuN-F?x@w=$4tl$0s-QxndK- zJM`l{cSlnFb$#1u+3XXRB{KW6$oQ{jafdf6_W7c!s)mA=YJnvC-3c;I)CzuZNGKf} z-$B6a$|p>1%zaAD_|$q)}1h3dmYMF&a~tl zflO$Q)267S`8;y25(xg0?@SdO(V#$0L)h&%yB9i5)qZPbGGJ}x=!YJcePl*8+pPT= z02+UC6`rAaq9YH+hqZqGo5`jR(v-w&#&UhYbQX;aG7>BXxV_`5(Va({b7?d55&pF^$nq1HY&>(2-$8^JJvPzA|{RAyAGS zmJG`#Tslcow$B_l8=vm~I>Q-ay?xl>d0qlX)=|qBndfpz{Jv@VOSQgTwMvxxeat17 z(y8ceoL9zKMRX_T2-zht8aV~hTfAf{ec34d=HI#J;xwW4R?4PrHq|&)z{X+V| zVJ&p%TFQe5j1N-2@Eo8_$`l(~>D5#;Z88`&?UGrkW8>I0ST(pFtVgYfo&o1Pu&8f= z=0 zpqWG2`K>1Da@t`F{BmK0&E?hc%{RhzL4>r-DEA-s3*L}sZXO!-*K1ANTA338cLQE3 zU1=%4+72%bF`aWw@%ajlMpuuB@cBD%6%?65$e24hQ5|35SmNwbk|V=EP)s}U zMfqZ5sw+?mOPl1(_>q=l_Dp13_i>)BIH9s&F1ic%F^;3q$J;Aki$+jTGhe>?49KKt zI;K1w&0yZ8DL$49F?xu$Etbxlv%F(gB}}1V{_={V8s#{|_KUdH(*-&!UPK5xu5``^ z-3q@{@B1Mz_{ACEihE#zjQEWQ#JAJVc8+WFba}DVdL<`!1x_RNC|f!`PVY^7^RB%; zAt#z=wsf^6f>vue>e~#3RV(!a>6fe&tO~OL^?L64m)L(-Eg1G;1Eg zUNEaFKa(wBx_1v+@hblg-7~n9o~LyDmliKX+^AlF>}*jy^W&tPlzCsbO7mRk9p+~} zr`@&jBdmkHYduZfU~~CA_N=(Y^?WL*uW&15yo_|PInPSb`7i?kf_fgij zUZpDz`+f#c5wwb=nt%{FtYFRK1n3MU?1A|e5N-MAVac)XMvbGlJWohE=j-KLo3`)G zjH25FyAfeMoaZp$!Xu>fH03}!^PB8x?ehdhjyGU=_WJB6)NFKCq4$(bhPTHyDQdO0 zGQjT%<(Pu{L-?Cj!)9-L5w?z}68Em+k8c)PFy@EoK4UK5ud05lx%}?c86YhVFtLUD z(5PEgFL-C>wK1c);#Y9^Fj>Uj4J<9;^5Nx;m|h5(!Sr`sK_QoE1!1+{+VxGq0R5 zsgkq{#mkgc^sSnPIU0x>bc6PiY%vg{mI@}Gk0%&PzLM+;XP!f67r5k;$RGPz+&lqS zS8h1HOT1;AT>0+nCbgVn9@he0d@4Cz`cj(2BxWW@k!8nq+fmGKxcF1nGq415CqKMj zdG18wzF}lScx?P4{tUSDu)@*t$N9WZLXjw7K;wcbnq%Py?XEcc}Jy!JF$^iF_LjyWA}~NY(k$Kz4Yn37&pamY=j_9A`eKmNYL_gS{3f_9~L&E#-k# ziUaeJ+3LEwyqYGbq(AC>)zbYj@`DcH_6kZlaL$J4Ns3jF5`rJ&kr!WJKGKEPtPTpztp=g_>iP_^F+0g za3!F_@giA7^_sOef$1b(a>{lSc^@V6tOi`Gv68QVI4{&i!ks95vrnt_zHdiYHAlYJ zX280o3+zG(%ecXdm>_;=u)KVoy#J=|#b}r>Lu?$4X*&x81kHRb!_t@L&NpepH=(uJ z_+)K(V%?5E&KXSF3xkm02-I#1QTuTlDWE?s9!?nHdr%bbWh zDA?v%>Vd79#yosj`1MeRuH5bYZ|d6G(L*x#5RFvqLIvI{1_3QANeAx?lX;&@ty$_B`@No7JaswItcn_0C^JbjU&U#4=LL7u=rG% zQNQ%7V5R%-5<@E|$6L5d?cFB9ZVIn1J59`&2{#rXdeiKy-R>G0L2{lM3wBIbR;&ui z=D_{MO@e0b!mVNOsQFl08daG0eEgLK!{TUI+UPwc*!GbcpKh9#wm|du99dM-$1J(( z7-Z514%7Pv&gu(d=i$wk#8}FC>2>`XaM^6NRPAfQ^jJ}UxjPTDnI_Nj`M!V$!(o?* zGx;FIYrtQ$W=`>%kugBe_#rU24vbFW8(adVKVq<=mDd$o%p`6%n`Il7VX(eKWy*R( zUr%}kuSr;lvlXvel|TOtMV3?Nfd|5K*=p(Qx7btEo`#gp&y3}^oic$x)y&OY#`$ab zkJq|pu#NZ?_er0tz7y(5>SkNKRO4WLUO4fhQQ~Ok1q7{^iJX6{{ZPJ9x99>p^v zgH3{|dnB`*I9ZQwP;P7(+u8`HfJx>Zlw_|JmzTtA&#VDn3v{eTD~2cb0{%fu=C)UE z^BV_^eNJlJpuqWPW`MV5exoXb9`S?P!Cep*itH| zjeIR4YpF!jDYOGKg}ZnjAU9kK3|o-M!hKU(jK5`65vZ;bQ+0 zkzX&=#R^inQK-(bqN2JO|BS$CQiQo(84#tzzwR}5AYu^pttM+f=Xu^{aZy2+=yRFC zkP_~WGk{Ut$hk#+F5_a4S-r#aj_t>+mkcWN&ETUIUux-+ER#atv3MNDzVdcap6>sK zzzJ8a*I^~i?zo~^FVP#-rGB^MZ>u@Hx&Jl< zqK_U6e`HjU$`jtvhNXQPxUZ=dBGQ5DVPhZviW${d64$BAq4v1Q5dKb}W3GN1_T0H= zQ7F6d?G3!zcCnUz6bno$yx6o|@RQBAHzh*CPY3UZoB?BR+ONsPzOA=Mv-Q2>?`2iH z&~=I?daUsoFq=Mosk9MGxxsuaYGww1WYz6kL{Pz5XH#|kc$_>QyhRVw`hG*=LoZLf zQsMit_6}8BPs!y8ZHbA8aCu!Vc_C_Xeh7bLMmkyNraE(f&~a6ZbyfUE>fA%_^H^HT z5y^c+rl__I&VhP8cR|6YiPCRd&7}6Wh$?j2)wBqS3)hHPa}jQ19XjGdObcNphpGb# z%J5$95$D8^& zousthnRaOwac?k#AIDn~Vu?FCGY@l~Lv{_!#ENxRdB#du?n3LHk^EcK9_O5@-i_VU z##^DFxqfmdFFBdf56NG$6~FGo%KOL7f_D9ECa= z8|^K5l8%s&#ax$g>0~#C)4+DkLv(JFZpCt~dJJ!*Gxe?gOI;8&6ZZ}ToguWg(*vbu zo730N-K?%mH`FOHpFW(atU8YGf<=jREDgCBz>4lcvIM53_-Z_g7X6N;%R{A=R*_*G zIK6f``Q-=rzQXK@>DB=q(RjFMCM3pKh{yeg&|?{cJ6Sg$bWu~eJrFztwsm?h8gV*r z)3z(BYt}rTx>Q+X=bC?uGtW?}?qN?14aGKFT#lX@wt;epRjohk3*CIIk$oG^*GjG4{F%xcGLFF;Z8` zYuH&=aH}xD1z*P*r$0v{Irsf_)bChn$H*2`{zk!EuHLzqEyl@-4fm96p0(X}FBa?W zb#xH2A|Ov&GAnb#%b>FpTja3Q?_`Za!IqC%&Bye8)I=&?z>+`~@ACZvkBnZSvVJr| z!badEpNw%YkHv9mJAFg(<5mBg}xQpF=sq@7#asoHmjUov86AY#+TGr(Pbbz)IP}z&DDE|O2=Xox?LTZ zR#Uu3jCUqgg#|rU&VXtiYonrZWm&>C;#toh2gy}+bw(>k!RZv_VN9xl3`H!)+vQLy z8LEAuUW!fc^oUaPYX;eN-lUDwIA>y$8z-+6f)(Gr%WRW(r#Lv!aGxv1mLwG69Q}5s zM?V~gW!XyFwvAr5ADUL|;QhX%RG!(AS$5dk%~y%dZ1E(8MF{=QXfzxG$)53?6xU|n zu&jC%I_uldQL&4NZ<#p?T0pe+h*G5iMG0**O-z=9D zx#B{5iq4ew;HO*>UYgBZvyN$dj@xIzZ~G5fE>;VBiY!_v$k3@O+@orth%pvuAtz<0 z;%0*~;4~4$&`2kB2GC4)6^5KU$tPIOtt|>4q?~e>N6dxKe!TSHZaq@;z7TDrNVd(e zN{N>BSoi5g$o35t<%qDGL^Ct^y(N3?Zr*l(HL>@qqkwW*NU)7BxkD0N<;4#XxAWQP zu+{6Y&YRYlbeomowvkz8c>ZA3g6B}3Z--5FIq_4l;Eu+d-5)LxLzR#k=mCCM*owvE zFibEm{j*QKAPs zkl3O;7pD%9+HHzgo=rFdzHGhxZSpfLz+`*sWbg90ULMTTthVyq`uouvO=NZKt?IRy< zznkhyV0y&#oFWYyi*a7Dnjsqcl!g?i>MdzveYKGuH_`mSWzNG~yRK}+I*jEj7%Z!|ZV2WpN$G~)4SN-Z?I270VN`an z>{9fLu-y#Si!o2lwT%rf_`7Sa`K?bKvu1#aJGCn~G9$ZyIlUMq(SZ`KFNuTg?B;r3 zhTp3?k&|qB2z!*X7S`~b`&9krNrv-Xt-*^A8@u@BXW=;R2Tx9!Z%K)9t{#NRH6+7`ak?LAMk$TJ|!^rqI9I&0aQPdvS>kXSOc$+c%bJ^f5e8LXtA z8z(Xv-hV8(b9L1w9~l|zDfl_*raa!9c>K!3foIT zl;w+4L69SZ(rt&*$8UgDs0y7YtTcd!7i*zMUD(op&b$SV`jYww+i~ z-s=qFeD$7Pb-nA|U{ftFI5EN0d~rc7F&T(Tcuj9T81QXtO#J|Q5~sio#+l!Xw8S>_ zRuS|RponPCdewr-rxa?gH4Keio(;O)@~Y3MhD7PZ=4Uc9%PCt66}8TQ`xkkFsS|&{ zd~m6g35`^w2~^k#lNX)~dPASD&h_yN#?0kmkGn>}=(=$+|J7B9L5rb}dxb8zkO!rx zJ71G zKa@09^_Va_gfl=+XaJK+P~JbW*w!tW(HEfLbVdUljjuZ}gH^@QRGqA_b&dsmkX?y9 z+-&zXW}+|faBpwn02AJ3uAK;q@KLG{Yx;32H9&ngIaS;I!LVObX18TMp=NfDxW%rk z*eGbIpQ_s548D{Z&FsB9i~Y)}1M1d=oDt-Dk@jc1FF&o={ z{|7Ypbd%toWoVYe$sC5WHPkn*>Gv~W4fVxI37p9OL?ak#>qYqq=wGI;sK}Ne?KE;6%5?pUaec`7$@e4&DU<-olC*dr`ND2`Mkr;m zw^6fAf$44iVRyg%a(|Ppl8OC|6=a8Tgyz)vxa5rLL;!v>ev%QlpY1|-wIOB%>M%ZS z%M%{{wRw_?TVZ3RAMzDJj(as1KejdhvU~v6KbIT6j|6{qhO(1s)x2FIzrvR?`8}6k zJ}CmyjOZ=2eu0dAj3y&1O2>|dw8V{K@FU*{=5K~L%WJltY^fLn*3Wq;gL^5 zDV5Su3uCd@_n&vEDbt%QYSu})H*gwP`R)`%)ZcRrsZy=TS7w|bNzc=+}G#qEtoWcha4-G{hreNMT6KB;i=aOzMZo;vq*@LgC1aZz7l*lR1E@^ z>}JRh(fHlzn2`RDmU2Px)Ty2FB=X7d4wbcxQ12O3g28!ng@fkRAm6QxQ{VQmx#hqP zAH7}tVQ%5e3*5VRw>(L{5>Ce@3pRl-MA*LYI#j%siQ22 z+R94Kc)QWGu%;-+eTa0bObV zPLH_Np`VVfy2p{b&1O>3fEH!t*;7VOV)uxbp2s+0N8U7dE0npp>lA;$_)O&FjyID) zpBZms`~m_OxV+IAjc06WjSUa;(E!-e*)VKCD22F2o4-kzC{+I5Z+evZ>vHji9U;L> zjrLU|%o^S4@fHivez=7rYOna%-TMi1NTx+bJ#-^uy6LxI$z8_vhMY>Xl7r2Rsh>xC zJs`2}Q)b$cn0#QEBhxD#$+3KQb*2ck0w2ZtQhQ>v!eL zK1N?}S|{^1>FG4_HX%HVHtN0kxi=IrvB$B{eomFOeugT_ID3o7A>nZW^x^Azx|*{Y z=oM@3mU+fmW*SYl^hgxb>|vk!8DKF|6vpj0tKHmAv7}Vf0pY0TLe)j|B|&T#HvABL z$jWz6%dO&##!f6Y(CE`!=gP$LtU~M5g)@MDwJ?*tH2SynM5EY+(`x=)WE^hIN_{?) zslH2K_q-d(mT8Boi;3q%&JM|hkbK)(WcZxvGF6wY>@w|ruqGFA{k9OTDk&4%^l1xU zkkO5d3q-GVFjTs}Rr|!yrgiwD)=V^If2Ft>VGAy*LAI$+1tWya`m+KWj|s>6SekPC zM3wrT-pSbrP+SmpU$!GBaJcu#M|Y`%8^Gh^?}sYqNa!~?Get~w&1U%SA5zAD4T=lX z>NGeL6CM)?ud^O~F-f@D4n~vZ4c;L8jMoYD6+L4%p8CT0P&r zHvL44ZOEar-fqX5acm8Se;EwI4+$SB`kyMot+z|)ReD-8TX$$JP6YCp>qvw4IZs>! zNMA3It!XfEMCA?{U61BY^q!FX(8=GZcV}YdmYXR}Xp=Q6Et!{{3ZiiOu1TlZ z4N>W*p%SOwhR-F2pqmoNl~cIZO0IO#mh09j{8efCN^XI<-^gJT0rWYQCjcFX!`o%R zl~+s#mmjgWth^dMW`k#(xB^N(BnrW2fFLX>56EbMw8Q%m$OdS8Rp!*r^5#jfpV=E9 z^;43ej-VD+^QscX=2duqNLm#~){TT+`Z$;(1t_js856U>=p&!-byc~G(573(&#uWa z85#=0j|>zIXUcr4bnV6y?!V(X)S0MltToTw|1haqRE_oqLP70ddCnH4+_WZ+iU_b; z@MS$*c>j^2P`_#)C91URH1iZutR)(~JW7BOsyG)d#oKkINASEeWtDGN%8*#`6h_+h z9Qdn|@iV|IP`d9_$1Pcq6@nq2EG^D}d%=%u-cG45PNnb!+hcYW?AU2nW*ADkx~BTs z6|47^;~BI}`xOq98k#sg8Q0S)4=kniHXAd8+1Yrm^YWBz)uF78MXHYC zt24dV`l~qg+u<#-v@Wz`K9XnChg}-B9 zze@5@#tkY>gptqBi`6Imh0aVG1$8^ zydx3ocevJ(>+-uss~?*kn_Vo~1iJ)oK-J*Y_%Z*0pYFFH*OM{j+7YBj_MX0~pZdHt z#v?;br*d;T&maAJAezk)fxzI9hdvZ?PlE8LSM|+Qr-{EtjpTgS5g6O7nCJ}EDE<*v z^D!o`%As&f`L!lLhhsxZ6Dn`Sw~HB|#S&e!_;!!VS2SnwRU_RE&C01X?FW_d`*wQM zt~r&*(abTK`f-`>)Dwde;Vc3r+Ewh9hj6^siK(r=Dg&2H3MD0zETKt|_~#7ev$6jG DwRyI3 literal 0 HcmV?d00001 diff --git a/tests/e2e/utilities/resources/test-template.zip b/tools/playwright/data/template/test-template.zip similarity index 100% rename from tests/e2e/utilities/resources/test-template.zip rename to tools/playwright/data/template/test-template.zip diff --git a/tools/playwright/fixtures/test.ts b/tools/playwright/fixtures/test.ts new file mode 100644 index 000000000..09d26cb90 --- /dev/null +++ b/tools/playwright/fixtures/test.ts @@ -0,0 +1,8 @@ +import { mergeTests } from '@playwright/test'; +import { test as wpTests } from '@wordpress/e2e-test-utils-playwright'; +import { test as chromeTests } from '@chromatic-com/playwright'; +import * as path from 'node:path'; + +export const test = mergeTests(wpTests, chromeTests); + +export const resourcesPath = path.join(__dirname, '..', 'data'); diff --git a/tools/playwright/flaky-tests-reporter.ts b/tools/playwright/flaky-tests-reporter.ts new file mode 100644 index 000000000..99045dbfd --- /dev/null +++ b/tools/playwright/flaky-tests-reporter.ts @@ -0,0 +1,85 @@ +/** + * A **flaky** test is defined as a test which passed after auto-retrying. + * - By default, all tests run once if they pass. + * - If a test fails, it will automatically re-run at most 2 times. + * - If it pass after retrying (below 2 times), then it's marked as **flaky** + * but displayed as **passed** in the original test suite. + * - If it fail all 3 times, then it's a **failed** test. + */ +import { writeFileSync, mkdirSync } from 'fs'; +import type { Reporter, TestCase, TestResult } from '@playwright/test/reporter'; +import config from './config'; +import filenamify from 'filenamify'; + +type FormattedTestResult = Omit; + +// Remove "steps" to prevent stringify circular structure. +function formatTestResult(testResult: TestResult): FormattedTestResult { + const result = { ...testResult, steps: undefined }; + delete result.steps; + return result; +} + +class FlakyTestsReporter implements Reporter { + failingTestCaseResults = new Map(); + + onBegin() { + try { + mkdirSync(config.outputDir + '/flaky-tests', { + recursive: true, + }); + } catch (err) { + if ( + err instanceof Error && + (err as NodeJS.ErrnoException).code === 'EEXIST' + ) { + // Ignore the error if the directory already exists. + } else { + throw err; + } + } + } + + onTestEnd(test: TestCase, testCaseResult: TestResult) { + const testPath = test.location.file; + const testTitle = test.title; + + switch (test.outcome()) { + case 'unexpected': { + if (!this.failingTestCaseResults.has(testTitle)) { + this.failingTestCaseResults.set(testTitle, []); + } + this.failingTestCaseResults + .get(testTitle)! + .push(formatTestResult(testCaseResult)); + break; + } + case 'flaky': { + writeFileSync( + `"${config.outputDir}/flaky-tests/${filenamify(testTitle)}.json`, + JSON.stringify({ + version: 1, + runner: '@playwright/test', + title: testTitle, + path: testPath, + results: this.failingTestCaseResults.get(testTitle), + }), + 'utf-8' + ); + break; + } + default: + break; + } + } + + onEnd() { + this.failingTestCaseResults.clear(); + } + + printsToStdio() { + return false; + } +} + +module.exports = FlakyTestsReporter; diff --git a/tools/playwright/global-setup.ts b/tools/playwright/global-setup.ts new file mode 100644 index 000000000..48ae93f5e --- /dev/null +++ b/tools/playwright/global-setup.ts @@ -0,0 +1,28 @@ +import { test as setup } from '@playwright/test'; + +setup('setup', async ({ request }, testInfo) => { + const storageStatePath = testInfo.project.metadata + .storageStatePath as string; + + process.env.WP_BASE_URL = testInfo.project.use.baseURL as string; + process.env.STORAGE_STATE_PATH = storageStatePath; + + const { RequestUtils } = + await import('@wordpress/e2e-test-utils-playwright'); + const requestUtils = new RequestUtils(request, { + storageStatePath, + }); + + // Authenticate and save the storageState to disk. + await requestUtils.setupRest(); + + // Reset the test environment before running the tests. + await Promise.all([ + requestUtils.activatePlugin('gravity-forms'), + requestUtils.activatePlugin('gravity-pdf'), + requestUtils.activateTheme('twentytwentyfive'), + requestUtils.deleteAllPosts(), + requestUtils.deleteAllBlocks(), + requestUtils.resetPreferences(), + ]); +}); diff --git a/tools/playwright/utils/gravityforms.ts b/tools/playwright/utils/gravityforms.ts new file mode 100644 index 000000000..a388f17dc --- /dev/null +++ b/tools/playwright/utils/gravityforms.ts @@ -0,0 +1,185 @@ +import { readFile } from 'fs/promises'; +import type { Admin, RequestUtils } from '@wordpress/e2e-test-utils-playwright'; +import type { Page } from '@playwright/test'; +import { expect } from '@playwright/test'; + +type Form = { + id: number; + title: string; +}; + +type Entry = { + form_id: number; + created_by?: number; + ip?: string; +}; + +export default class GravityForms { + protected requestUtils: RequestUtils; + protected admin: Admin; + protected page: Page; + + constructor(requestUtils: RequestUtils, admin: Admin, page: Page) { + this.requestUtils = requestUtils; + this.admin = admin; + this.page = page; + } + + /* + * Form management + */ + async createForm(title: string, type: string = 'standard.json') { + const formJson: string = await readFile( + __dirname + '/../data/forms/' + type, + 'utf8' + ); + + const form: Form = JSON.parse(formJson); + + form.title = title; + + return await this.requestUtils.rest({ + method: 'POST', + path: `/gf/v2/forms`, + data: { ...form }, + }); + } + + async createEntry(entry: Entry) { + return await this.requestUtils.rest({ + method: 'POST', + path: `/gf/v2/entries`, + data: { ...entry }, + }); + } + + async getFormIdByName(name: string): Promise { + await this.navigateToFormList(); + const search = this.page.getByRole('searchbox'); + await search.fill(name); + await search.press('Enter'); + + return Number.parseInt( + await this.page.locator('.id > a').first().innerText() + ); + } + + async navigateToFormList() { + await this.admin.visitAdminPage('admin.php', 'page=gf_edit_forms'); + } + + async navigateToFormByName(name: string) { + const id = await this.getFormIdByName(name); + await this.navigateToFormById(id); + } + + async navigateToFormById(formId: number) { + await this.admin.visitAdminPage( + 'admin.php', + 'page=gf_edit_forms&id=' + formId + ); + } + + async saveFormEditor() { + await this.page.getByRole('button', { name: 'Save Form' }).click(); + await this.page.waitForTimeout(3500); + } + + async navigateToFormSettingsById(formId: number, subview = '') { + await this.admin.visitAdminPage( + 'admin.php', + `page=gf_edit_forms&view=settings&subview=settings&id=${formId}&subview=${subview}` + ); + } + + async navigateToFormConfirmation( + formId: number, + label = 'Default Confirmation' + ) { + await this.navigateToFormSettingsById(formId, 'confirmation'); + + await this.page + .locator('#the-list') + .getByRole('link', { name: label + ' (Edit)', exact: true }) + .click(); + } + + async navigateToEntryList(formId: number) { + await this.admin.visitAdminPage( + 'admin.php', + `page=gf_entries&id=${formId}` + ); + } + + async navigateToEntryDetail(formId: number, entryId: number) { + await this.admin.visitAdminPage( + 'admin.php', + `page=gf_entries&view=entry&id=${formId}&lid=${entryId}` + ); + } + + async navigateToFormPreview(formId: number) { + await this.page.goto('/?gf_page=preview&id=' + formId); + } + + /* + * Settings management + */ + async addNotification(formId: number, name: string) { + await this.admin.visitAdminPage( + 'admin.php', + `subview=notification&page=gf_edit_forms&view=settings&id=${formId}` + ); + + await this.page.getByRole('link', { name: 'Add New' }).click(); + + await this.page + .getByRole('textbox', { name: 'Name' }) + .first() + .fill(name); + await this.page + .getByRole('textbox', { name: 'Send To Email' }) + .fill('hi@example.com'); + await this.page + .getByRole('textbox', { name: 'Subject' }) + .fill('Subject'); + await this.setRichTextContent('#gform_setting_message', 'Message'); + + await this.page + .getByRole('button', { name: 'Update Notification' }) + .click(); + } + + async setRichTextContent( + containerSelector: string, + content: string, + append = false + ) { + const container = await this.page.locator(containerSelector); + + // swap to code view + container + .getByRole('button', { name: /^Code$/ }) + .first() + .click(); + + const textbox = await container.getByRole('textbox').last(); + + if (append) { + content = (await textbox.inputValue()) + content; + } + + await textbox.fill(content); + + await this.page.waitForTimeout(500); + + expect(await textbox.inputValue()).toEqual(content); + } + + async submitForm() { + await this.page + .getByRole('button', { name: /(save|submit)/i }) + .last() + .click(); + } +} diff --git a/tools/playwright/utils/gravitypdf.ts b/tools/playwright/utils/gravitypdf.ts new file mode 100644 index 000000000..7520d60e9 --- /dev/null +++ b/tools/playwright/utils/gravitypdf.ts @@ -0,0 +1,194 @@ +import { expect } from '@wordpress/e2e-test-utils-playwright'; +import type { Locator } from '@playwright/test'; +import type { Readable } from 'stream'; +import { URL } from 'node:url'; +import GravityForms from '@self:playwright/utils/gravityforms'; + +export default class Pdf extends GravityForms { + async navigateToGlobalPdfSettings() { + await this.admin.visitAdminPage( + 'admin.php', + 'page=gf_settings&subview=PDF' + ); + } + + async setGlobalPdfSetting(label: string, value: any) { + await this.navigateToGlobalPdfSettings(); + + const setting = this.page.getByLabel(label).first(); + + switch (await setting.getAttribute('type')) { + case 'checkbox': + // eslint-disable-next-line no-unused-expressions + value ? await setting.check() : await setting.uncheck(); + break; + + case 'radio': + // eslint-disable-next-line no-unused-expressions + value ? await setting.check() : await setting.uncheck(); + } + + await this.page.getByRole('button', { name: 'Save Settings' }).click(); + } + + async fillField(label: string, value: string) { + await this.page.getByLabel(label).fill(value); + } + + async selectField(label: string, value: string) { + await this.page.getByLabel(label).selectOption(value); + } + + async checkField(label: string, value: boolean) { + const checkbox = this.page.getByLabel(label); + // eslint-disable-next-line no-unused-expressions + value ? await checkbox.check() : await checkbox.uncheck(); + } + + async chooseField(label: string, value: string) { + await this.page.getByRole('radio', { name: value }).check(); + } + + async navigateToFormPdfList(formId: number) { + await this.navigateToFormSettingsById(formId, 'PDF'); + } + + async createPdf(formId: number, label: string) { + await this.navigateToNewFormPdf(formId); + await this.page.getByLabel('Label').fill(label); + await this.page.getByLabel('Filename').fill(label); + await this.addOrUpdatePdf(); + + // return PDF ID (@TODO update with the REST API settings once implemented) + const pdfUrl = new URL(this.page.url()); + + return pdfUrl.searchParams.get('pid'); + } + + async addOrUpdatePdf() { + const addButton = this.page.getByRole('button', { name: 'Add PDF' }); + + if ((await addButton.count()) > 0) { + await addButton.first().click(); + } else { + await this.page + .getByRole('button', { name: 'Update PDF' }) + .first() + .click(); + } + + await expect( + this.page.getByRole('button', { name: 'Manage PDF Templates' }) + ).toBeVisible(); + } + + async navigateToNewFormPdf(formId: number) { + await this.navigateToFormPdfList(formId); + await this.page.getByRole('link', { name: 'Add new PDF' }).click(); + await expect( + this.page.getByRole('button', { name: 'Manage PDF Templates' }) + ).toBeVisible(); + } + + async navigateToFormPdf(formId: number, pdfId: string) { + await this.admin.visitAdminPage( + 'admin.php', + `page=gf_edit_forms&view=settings&subview=PDF&id=${formId}&pid=${pdfId}` + ); + await expect( + this.page.getByRole('button', { name: 'Manage PDF Templates' }) + ).toBeVisible(); + } + + async copyDownloadShortcodeToClipboard(formId: number, pdfId: string) { + await this.navigateToFormPdfList(formId); + await this.page.locator(`#gfpdf-${pdfId}`).getByRole('dialog').click(); + } + + async checkRichTextEditor(container: Locator) { + // Merge Tag Selector + await container.getByTitle('Insert Merge Tags').click(); + await container.getByRole('button', { name: 'Radio' }).click(); + await container.getByTitle('Insert Merge Tags').click(); + await container.getByRole('button', { name: 'Entry Id' }).click(); + + // Add Media + await container.getByRole('button', { name: 'Add Media' }).click(); + await this.page.getByRole('tab', { name: 'Upload files' }).click(); + await this.page + .locator('.media-modal-content:visible') + .locator('input[type=file]') + .setInputFiles(__dirname + '/../data/images/thumbnail.jpg'); + await this.page + .getByRole('button', { name: 'Insert into Post' }) + .click(); + + // Code View + await container + .getByRole('button', { name: /^Code$/ }) + .first() + .click(); + + await expect(container.getByRole('textbox').last()).toHaveValue( + /^\{Radio:1}\{entry_id}=0.4.22" - js-md4 "^0.3.2" - underscore "~1.12.1" - -httpreq@>=0.4.22: - version "1.1.1" - resolved "https://registry.yarnpkg.com/httpreq/-/httpreq-1.1.1.tgz#b8818316cdfd6b1bfb0f68b822fa1306cd24be68" - integrity sha512-uhSZLPPD2VXXOSN8Cni3kIsoFHaU2pT/nySEU/fHr/ePbqHYr0jeiQRmUKLEirC09SFPsdMoA7LU7UXMd/w0Kw== - https-proxy-agent@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" @@ -9406,20 +9481,17 @@ https-proxy-agent@^7.0.6: agent-base "^7.1.2" debug "4" -human-signals@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" - integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== - human-signals@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== -humanize-duration@^3.25.0: - version "3.33.2" - resolved "https://registry.yarnpkg.com/humanize-duration/-/humanize-duration-3.33.2.tgz#2e41986eabb00cb5ad0eef616a78233099dbdac4" - integrity sha512-K7Ny/ULO1hDm2nnhvAY+SJV1skxFb61fd073SG1IWJl+D44ULrruCuTyjHKjBVVcSuTlnY99DKtgEG39CM5QOQ== +humanize-ms@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" + integrity sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ== + dependencies: + ms "^2.0.0" iconv-lite@0.4.24, iconv-lite@~0.4.24: version "0.4.24" @@ -9428,14 +9500,7 @@ iconv-lite@0.4.24, iconv-lite@~0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3" -iconv-lite@0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.5.1.tgz#b2425d3c7b18f7219f2ca663d103bddb91718d64" - integrity sha512-ONHr16SQvKZNSqjQT9gy5z24Jw+uqfO02/ngBSBoqChZ+W8qXX7GPRa1RoUnzGADw8K63R1BXUMzarCVQBpY8Q== - dependencies: - safer-buffer ">= 2.1.2 < 3" - -iconv-lite@0.6.3, iconv-lite@^0.6.3: +iconv-lite@0.6.3, iconv-lite@^0.6.2, iconv-lite@^0.6.3: version "0.6.3" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== @@ -9454,7 +9519,7 @@ icss-utils@^5.0.0, icss-utils@^5.1.0: resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== -ieee754@^1.1.13: +ieee754@^1.1.13, ieee754@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== @@ -9466,7 +9531,7 @@ ignore-walk@^4.0.1: dependencies: minimatch "^3.0.4" -ignore@5.3.2, ignore@^5.1.1, ignore@^5.1.4, ignore@^5.1.9, ignore@^5.2.0, ignore@^5.2.4: +ignore@5.3.2, ignore@^5.1.4, ignore@^5.1.9, ignore@^5.2.0, ignore@^5.2.4: version "5.3.2" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== @@ -9514,11 +9579,6 @@ import-in-the-middle@^1.14.2, import-in-the-middle@^1.8.1: cjs-module-lexer "^1.2.2" module-details-from-path "^1.0.3" -import-lazy@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-3.1.0.tgz#891279202c8a2280fdbd6674dbd8da1a1dfc67cc" - integrity sha512-8/gvXvX2JMn0F+CDlSC4l6kOmVaLOO3XLkksI7CI3Ud95KDYJuYur2b9P/PUt/i/pDAMd/DulQsNbbbmRRsDIQ== - import-local@^3.0.2: version "3.2.0" resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.2.0.tgz#c3d5c745798c02a6f8b897726aba5100186ee260" @@ -9532,15 +9592,6 @@ imurmurhash@^0.1.4: resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== -indent-string@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-1.2.2.tgz#db99bcc583eb6abbb1e48dcbb1999a986041cb6b" - integrity sha512-Z1vqf6lDC3f4N2mWqRywY6odjRatPNGDZgUr4DY9MLC14+Fp2/y+CI/RnNGlb8hD6ckscE/8DlZUwHUaiDBshg== - dependencies: - get-stdin "^4.0.1" - minimist "^1.1.0" - repeating "^1.1.0" - indent-string@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" @@ -9735,13 +9786,6 @@ is-callable@^1.1.5, is-callable@^1.2.7: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== -is-ci@^1.0.10: - version "1.2.1" - resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.2.1.tgz#e3779c8ee17fccf428488f6e281187f2e632841c" - integrity sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg== - dependencies: - ci-info "^1.5.0" - is-ci@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" @@ -9749,7 +9793,7 @@ is-ci@^2.0.0: dependencies: ci-info "^2.0.0" -is-core-module@^2.11.0, is-core-module@^2.16.1, is-core-module@^2.5.0: +is-core-module@^2.16.1, is-core-module@^2.5.0: version "2.16.1" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.16.1.tgz#2a98801a849f43e2add644fbb6bc6229b19a4ef4" integrity sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w== @@ -9801,10 +9845,10 @@ is-docker@^2.0.0, is-docker@^2.1.1: resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== -is-es2016-keyword@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-es2016-keyword/-/is-es2016-keyword-1.0.0.tgz#f6e54e110c5e4f8d265e69d2ed0eaf8cf5f47718" - integrity sha512-JtZWPUwjdbQ1LIo9OSZ8MdkWEve198ors27vH+RzUUvZXXZkzXCxFnlUhzWYxy5IexQSRiXVw9j2q/tHMmkVYQ== +is-docker@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-3.0.0.tgz#90093aa3106277d8a77a5910dbae71747e15a200" + integrity sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ== is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" @@ -9818,11 +9862,6 @@ is-extendable@^1.0.1: dependencies: is-plain-object "^2.0.4" -is-extglob@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" - integrity sha512-7Q+VbVafe6x2T+Tu6NcOf6sRklazEPmBoB3IWk3WdGZM2iGUwU/Oe3Wtq5lSEkDTTlpp8yx+5t4pzO/i9Ty1ww== - is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" @@ -9835,16 +9874,23 @@ is-finalizationregistry@^1.1.0: dependencies: call-bound "^1.0.3" -is-finite@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.1.0.tgz#904135c77fb42c0641d6aa1bcdbc4daa8da082f3" - integrity sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w== - is-fullwidth-code-point@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== +is-fullwidth-code-point@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz#fae3167c729e7463f8461ce512b080a49268aa88" + integrity sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ== + +is-fullwidth-code-point@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz#046b2a6d4f6b156b2233d3207d4b5a9783999b98" + integrity sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ== + dependencies: + get-east-asian-width "^1.3.1" + is-generator-fn@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" @@ -9861,13 +9907,6 @@ is-generator-function@^1.0.10: has-tostringtag "^1.0.2" safe-regex-test "^1.1.0" -is-glob@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" - integrity sha512-a1dBeB19NXsf/E0+FHqkagizel/LQw2DjSQpvQrj3zT+jYPpaUCryPnrQajXKFLCMuf4I6FhRpaGtw4lPrG6Eg== - dependencies: - is-extglob "^1.0.0" - is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" @@ -9875,6 +9914,13 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: dependencies: is-extglob "^2.1.1" +is-inside-container@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-inside-container/-/is-inside-container-1.0.0.tgz#e81fba699662eb31dbdaf26766a61d4814717ea4" + integrity sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA== + dependencies: + is-docker "^3.0.0" + is-interactive@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" @@ -9910,31 +9956,7 @@ is-number@^7.0.0: resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== -is-path-cwd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" - integrity sha512-cnS56eR9SPAscL77ik76ATVqoPARTqPIVkMDVxRaWH06zT+6+CzIroYRJ0VVvm0Z1zfAvxvz9i/D3Ppjaqt5Nw== - -is-path-cwd@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" - integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== - -is-path-in-cwd@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz#5ac48b345ef675339bd6c7a48a912110b241cf52" - integrity sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ== - dependencies: - is-path-inside "^1.0.0" - -is-path-inside@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" - integrity sha512-qhsCR/Esx4U4hg/9I19OVUAJkGWtjRYHMRgUMZE2TDdj+Ag+kttZanLupfddNyglzz50cUlmWzUaI37GDfNx/g== - dependencies: - path-is-inside "^1.0.1" - -is-path-inside@^3.0.1, is-path-inside@^3.0.3: +is-path-inside@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== @@ -9961,11 +9983,6 @@ is-plain-object@^5.0.0: resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344" integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q== -is-podman@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-podman/-/is-podman-1.0.1.tgz#284a7ba1e6987fff8af5d71d97a29d2a85b7996a" - integrity sha512-+5vbtF5FIg262iUa7gOIseIWTx0740RHiax7oSmJMhbfSoBIMQ/IacKKgfnGj65JGeH9lGEVQcdkDwhn1Em1mQ== - is-potential-custom-element-name@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" @@ -10042,11 +10059,6 @@ is-unicode-supported@^0.1.0: resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== -is-utf8@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" - integrity sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q== - is-weakmap@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.2.tgz#bf72615d649dfe5f699079c54b83e47d1ae19cfd" @@ -10084,10 +10096,12 @@ is-wsl@^2.2.0: dependencies: is-docker "^2.0.0" -isarray@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ== +is-wsl@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-3.1.1.tgz#327897b26832a3eb117da6c27492d04ca132594f" + integrity sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw== + dependencies: + is-inside-container "^1.0.0" isarray@1.0.0, isarray@~1.0.0: version "1.0.0" @@ -10155,7 +10169,7 @@ istanbul-lib-instrument@^5.0.4: istanbul-lib-coverage "^3.2.0" semver "^6.3.0" -istanbul-lib-instrument@^6.0.0, istanbul-lib-instrument@^6.0.2: +istanbul-lib-instrument@^6.0.0: version "6.0.3" resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz#fa15401df6c15874bcb2105f773325d78c666765" integrity sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q== @@ -10353,7 +10367,7 @@ jest-environment-jsdom@^24.0.0: jest-util "^24.9.0" jsdom "^11.5.1" -jest-environment-jsdom@^29.6.2, jest-environment-jsdom@^29.7.0: +jest-environment-jsdom@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-29.7.0.tgz#d206fa3551933c3fd519e5dfdb58a0f5139a837f" integrity sha512-k9iQbsf9OyOfdzWH8HDmrRT0gSIcX+FLNW7IQq94tFX0gynPwqDTW0Ho6iMVNjGz/nb+l/vW3dWM2bbLLpkbXA== @@ -10367,6 +10381,15 @@ jest-environment-jsdom@^29.6.2, jest-environment-jsdom@^29.7.0: jest-util "^29.7.0" jsdom "^20.0.0" +jest-environment-jsdom@^30.2.0: + version "30.3.0" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-30.3.0.tgz#6bf80519643333ae2faa07b5660d80451d328578" + integrity sha512-RLEOJy6ip1lpw0yqJ8tB3i88FC7VBz7i00Zvl2qF71IdxjS98gC9/0SPWYIBVXHm5hgCYK0PAlSlnHGGy9RoMg== + dependencies: + "@jest/environment" "30.3.0" + "@jest/environment-jsdom-abstract" "30.3.0" + jsdom "^26.1.0" + jest-environment-node@^29.6.2, jest-environment-node@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.7.0.tgz#0b93e111dda8ec120bc8300e6d1fb9576e164376" @@ -10449,6 +10472,21 @@ jest-matcher-utils@^29.6.2, jest-matcher-utils@^29.7.0: jest-get-type "^29.6.3" pretty-format "^29.7.0" +jest-message-util@30.3.0: + version "30.3.0" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-30.3.0.tgz#4d723544d36890ba862ac3961db52db5b0d1ba39" + integrity sha512-Z/j4Bo+4ySJ+JPJN3b2Qbl9hDq3VrXmnjjGEWD/x0BCXeOXPTV1iZYYzl2X8c1MaCOL+ewMyNBcm88sboE6YWw== + dependencies: + "@babel/code-frame" "^7.27.1" + "@jest/types" "30.3.0" + "@types/stack-utils" "^2.0.3" + chalk "^4.1.2" + graceful-fs "^4.2.11" + picomatch "^4.0.3" + pretty-format "30.3.0" + slash "^3.0.0" + stack-utils "^2.0.6" + jest-message-util@^24.9.0: version "24.9.0" resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-24.9.0.tgz#527f54a1e380f5e202a8d1149b0ec872f43119e3" @@ -10478,6 +10516,15 @@ jest-message-util@^29.7.0: slash "^3.0.0" stack-utils "^2.0.3" +jest-mock@30.3.0: + version "30.3.0" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-30.3.0.tgz#e0fa4184a596a6c4fdec53d4f412158418923747" + integrity sha512-OTzICK8CpE+t4ndhKrwlIdbM6Pn8j00lvmSmq5ejiO+KxukbLjgOflKWMn3KE34EZdQm5RqTuKj+5RIEniYhog== + dependencies: + "@jest/types" "30.3.0" + "@types/node" "*" + jest-util "30.3.0" + jest-mock@^24.9.0: version "24.9.0" resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-24.9.0.tgz#c22835541ee379b908673ad51087a2185c13f1c6" @@ -10499,6 +10546,11 @@ jest-pnp-resolver@^1.2.2: resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz#930b1546164d4ad5937d5540e711d4d38d4cad2e" integrity sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w== +jest-regex-util@30.0.1: + version "30.0.1" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-30.0.1.tgz#f17c1de3958b67dfe485354f5a10093298f2a49b" + integrity sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA== + jest-regex-util@^24.9.0: version "24.9.0" resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-24.9.0.tgz#c13fb3380bde22bf6575432c493ea8fe37965636" @@ -10618,6 +10670,18 @@ jest-snapshot@^29.7.0: pretty-format "^29.7.0" semver "^7.5.3" +jest-util@30.3.0: + version "30.3.0" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-30.3.0.tgz#95a4fbacf2dac20e768e2f1744b70519f2ba7980" + integrity sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg== + dependencies: + "@jest/types" "30.3.0" + "@types/node" "*" + chalk "^4.1.2" + ci-info "^4.2.0" + graceful-fs "^4.2.11" + picomatch "^4.0.3" + jest-util@^24.9.0: version "24.9.0" resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-24.9.0.tgz#7396814e48536d2e85a37de3e4c431d7cb140162" @@ -10724,6 +10788,11 @@ joi@^18.0.1: "@hapi/topo" "^6.0.2" "@standard-schema/spec" "^1.1.0" +jose@^5.1.0: + version "5.10.0" + resolved "https://registry.yarnpkg.com/jose/-/jose-5.10.0.tgz#c37346a099d6467c401351a9a0c2161e0f52c4be" + integrity sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg== + jpeg-js@^0.4.1, jpeg-js@^0.4.4: version "0.4.4" resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.4.4.tgz#a9f1c6f1f9f0fa80cdb3484ed9635054d28936aa" @@ -10739,16 +10808,6 @@ js-library-detector@^6.7.0: resolved "https://registry.yarnpkg.com/js-library-detector/-/js-library-detector-6.7.0.tgz#5075c71fcf835b71133bca13363b91509a39235a" integrity sha512-c80Qupofp43y4cJ7+8TTDN/AsDwLi5oOm/plBrWI+iQt485vKXCco+yVmOwEgdo9VOdsYTuV0UlTeetVPTriXA== -js-md4@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/js-md4/-/js-md4-0.3.2.tgz#cd3b3dc045b0c404556c81ddb5756c23e59d7cf5" - integrity sha512-/GDnfQYsltsjRswQhN9fhv3EMw2sCpUdrdxyWDOUK7eyD++r3gRhzgiQgc/x4MAv2i1iuQ4lxO5mvqM3vj4bwA== - -js-tokens@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" - integrity sha512-RjTcuD4xjtthQkaWH7dFlH85L+QaVtSoOyGdZ3g6HFhS9dFNDfLyqgm2NFe2X6cQpeFmt0452FJjFG5UameExg== - "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -10843,6 +10902,32 @@ jsdom@^20.0.0: ws "^8.11.0" xml-name-validator "^4.0.0" +jsdom@^26.1.0: + version "26.1.0" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-26.1.0.tgz#ab5f1c1cafc04bd878725490974ea5e8bf0c72b3" + integrity sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg== + dependencies: + cssstyle "^4.2.1" + data-urls "^5.0.0" + decimal.js "^10.5.0" + html-encoding-sniffer "^4.0.0" + http-proxy-agent "^7.0.2" + https-proxy-agent "^7.0.6" + is-potential-custom-element-name "^1.0.1" + nwsapi "^2.2.16" + parse5 "^7.2.1" + rrweb-cssom "^0.8.0" + saxes "^6.0.0" + symbol-tree "^3.2.4" + tough-cookie "^5.1.1" + w3c-xmlserializer "^5.0.0" + webidl-conversions "^7.0.0" + whatwg-encoding "^3.1.1" + whatwg-mimetype "^4.0.0" + whatwg-url "^14.1.1" + ws "^8.18.0" + xml-name-validator "^5.0.0" + jsesc@^3.0.2, jsesc@~3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d" @@ -10853,11 +10938,6 @@ json-buffer@3.0.1: resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== -json-loader@^0.5.7: - version "0.5.7" - resolved "https://registry.yarnpkg.com/json-loader/-/json-loader-0.5.7.tgz#dca14a70235ff82f0ac9a3abeb60d337a365185d" - integrity sha512-QLPs8Dj7lnf3e3QYS1zkCo+4ZwqOiF9d/nZnYozTISxXWCfNs9yuky5rJw4/W34s7POaNlbZmQGaB5NiXCbP4w== - json-parse-better-errors@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" @@ -10910,7 +10990,7 @@ json5@^1.0.2: dependencies: minimist "^1.2.0" -json5@^2.1.2, json5@^2.2.2, json5@^2.2.3: +json5@^2.1.2, json5@^2.2.3: version "2.2.3" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== @@ -11149,7 +11229,7 @@ lighthouse@^12.2.2: yargs "^17.3.1" yargs-parser "^21.0.0" -lilconfig@^3.1.1, lilconfig@^3.1.3: +lilconfig@^3.1.1: version "3.1.3" resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.1.3.tgz#a1bcfd6257f9585bf5ae14ceeebb7b559025e4c4" integrity sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw== @@ -11166,12 +11246,17 @@ linkify-it@^3.0.1: dependencies: uc.micro "^1.0.1" -linux-platform-info@^0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/linux-platform-info/-/linux-platform-info-0.0.3.tgz#2dae324385e66e3d755bec83f86c7beea61ceb83" - integrity sha512-FZhfFOIz0i4EGAvM4fQz+eayE9YzMuTx45tbygWYBttNapyiODg85BnAlQ1xnahEkvIM87T98XhXSfW8JAClHg== +listr2@^8.0.0: + version "8.3.3" + resolved "https://registry.yarnpkg.com/listr2/-/listr2-8.3.3.tgz#815fc8f738260ff220981bf9e866b3e11e8121bf" + integrity sha512-LWzX2KsqcB1wqQ4AHgYb4RsDXauQiqhjLk+6hjbaeHG4zpjjVAB6wC/gz6X0l+Du1cN3pUB5ZlrvTbhGSNnUQQ== dependencies: - os-family "^1.0.0" + cli-truncate "^4.0.0" + colorette "^2.0.20" + eventemitter3 "^5.0.1" + log-update "^6.1.0" + rfdc "^1.4.1" + wrap-ansi "^9.0.0" load-json-file@^4.0.0: version "4.0.0" @@ -11183,17 +11268,6 @@ load-json-file@^4.0.0: pify "^3.0.0" strip-bom "^3.0.0" -load-json-file@^5.2.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-5.3.0.tgz#4d3c1e01fa1c03ea78a60ac7af932c9ce53403f3" - integrity sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw== - dependencies: - graceful-fs "^4.1.15" - parse-json "^4.0.0" - pify "^4.0.1" - strip-bom "^3.0.0" - type-fest "^0.3.0" - loader-runner@^4.3.1: version "4.3.1" resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.1.tgz#6c76ed29b0ccce9af379208299f07f876de737e3" @@ -11373,7 +11447,7 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ== -"lodash@4.6.1 || ^4.16.1", lodash@^4.14.0, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.21: +lodash@^4.17.19, lodash@^4.17.21: version "4.18.1" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.18.1.tgz#ff2b66c1f6326d59513de2407bf881439812771c" integrity sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q== @@ -11393,15 +11467,16 @@ log-symbols@^4.1.0: chalk "^4.1.0" is-unicode-supported "^0.1.0" -log-update-async-hook@^2.0.7: - version "2.0.7" - resolved "https://registry.yarnpkg.com/log-update-async-hook/-/log-update-async-hook-2.0.7.tgz#48042bae63ed5ad1a67a6601d88934e60f1f38f8" - integrity sha512-V9KpD1AZUBd/oiZ+/Xsgd5rRP9awhgtRiDv5Am4VQCixiDnAbXMdt/yKz41kCzYZtVbwC6YCxnWEF3zjNEwktA== +log-update@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/log-update/-/log-update-6.1.0.tgz#1a04ff38166f94647ae1af562f4bd6a15b1b7cd4" + integrity sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w== dependencies: - ansi-escapes "^4.3.2" - async-exit-hook "^1.1.2" - onetime "^2.0.1" - wrap-ansi "^7.0.0" + ansi-escapes "^7.0.0" + cli-cursor "^5.0.0" + slice-ansi "^7.1.0" + strip-ansi "^7.1.0" + wrap-ansi "^9.0.0" loglevel@^1.9.2: version "1.9.2" @@ -11420,6 +11495,11 @@ loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: dependencies: js-tokens "^3.0.0 || ^4.0.0" +loupe@^3.1.0, loupe@^3.1.4: + version "3.2.1" + resolved "https://registry.yarnpkg.com/loupe/-/loupe-3.2.1.tgz#0095cf56dc5b7a9a7c08ff5b1a8796ec8ad17e76" + integrity sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ== + lower-case@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28" @@ -11432,12 +11512,7 @@ lowercase-keys@^2.0.0: resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== -lru-cache@11.0.2: - version "11.0.2" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-11.0.2.tgz#fbd8e7cf8211f5e7e5d91905c415a3f55755ca39" - integrity sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA== - -lru-cache@^10.2.0: +lru-cache@^10.2.0, lru-cache@^10.4.3: version "10.4.3" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== @@ -11466,18 +11541,6 @@ lru-cache@^7.14.1: resolved "https://registry.yarnpkg.com/@wolfy1339/lru-cache/-/lru-cache-11.0.2-patch.1.tgz#bb648b660478099c9022ee71a00b80603daf7294" integrity sha512-BgYZfL2ADCXKOw2wJtkM3slhHotawWkgIRRxq4wEybnZQPjvAp71SPX35xepMykTw8gXlzWcWPTY31hlbnRsDA== -macos-release@^3.0.1: - version "3.4.0" - resolved "https://registry.yarnpkg.com/macos-release/-/macos-release-3.4.0.tgz#1b223706b13106c158e2b40cb81ba35dd74d7856" - integrity sha512-wpGPwyg/xrSp4H4Db4xYSeAr6+cFQGHfspHzDUdYxswDnUW0L5Ov63UuJiSr8NMSpyaChO4u1n0MXUvVPtrN6A== - -make-dir@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" - integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== - dependencies: - semver "^6.0.0" - make-dir@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" @@ -11568,13 +11631,6 @@ marky@^1.2.2: resolved "https://registry.yarnpkg.com/marky/-/marky-1.3.0.tgz#422b63b0baf65022f02eda61a238eccdbbc14997" integrity sha512-ocnPZQLNpvbedwTy9kNrQEsknEfgvcLMvOtz3sFeWApDq1MXH1TqkCIx58xlpESsfwQOnuBO9beyQuNGzVvuhQ== -match-url-wildcard@0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/match-url-wildcard/-/match-url-wildcard-0.0.4.tgz#c8533da7ec0901eddf01fc0893effa68d4e727d6" - integrity sha512-R1XhQaamUZPWLOPtp4ig5j+3jctN+skhgRmEQTUamMzmNtRG69QEirQs0NZKLtHMR7tzWpmtnS4Eqv65DcgXUA== - dependencies: - escape-string-regexp "^1.0.5" - math-intrinsics@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9" @@ -11664,19 +11720,12 @@ merge-descriptors@1.0.3: resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.3.tgz#d80319a65f3c7935351e5cfdac8f9318504dbed5" integrity sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ== -merge-stream@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-1.0.1.tgz#4041202d508a342ba00174008df0c251b8c135e1" - integrity sha512-e6RM36aegd4f+r8BZCcYXlO2P3H6xbUM6ktL2Xmf45GAOit9bI4z6/3VU7JwllVO1L7u0UDSg/EhzQ5lmMLolA== - dependencies: - readable-stream "^2.0.1" - merge-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== -merge2@^1.2.3, merge2@^1.3.0, merge2@^1.4.1: +merge2@^1.3.0, merge2@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== @@ -11723,7 +11772,7 @@ mime-db@1.52.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== -"mime-db@>= 1.43.0 < 2", mime-db@^1.41.0: +"mime-db@>= 1.43.0 < 2": version "1.54.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.54.0.tgz#cddb3ee4f9c64530dff640236661d42cb6a314f5" integrity sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ== @@ -11745,21 +11794,16 @@ mime@^3.0.0: resolved "https://registry.yarnpkg.com/mime/-/mime-3.0.0.tgz#b374550dca3a0c18443b0c950a6a58f1931cf7a7" integrity sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A== -mime@~1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" - integrity sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ== - -mimic-fn@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" - integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== - mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== +mimic-function@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/mimic-function/-/mimic-function-5.0.1.tgz#acbe2b3349f99b9deaca7fb70e48b83e94e67076" + integrity sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA== + mimic-response@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" @@ -11775,7 +11819,7 @@ min-indent@^1.0.0: resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== -mini-css-extract-plugin@^2.6.1, mini-css-extract-plugin@^2.9.2: +mini-css-extract-plugin@^2.9.2: version "2.10.2" resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.10.2.tgz#5c85ec9450c05d26e32531b465a15a08c3a57253" integrity sha512-AOSS0IdEB95ayVkxn5oGzNQwqAi2J0Jb/kKm43t7H73s8+f5873g0yuj0PNvK4dO75mu5DHg4nlgp4k6Kga8eg== @@ -11788,13 +11832,6 @@ minimalistic-assert@^1.0.0: resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== -minimatch@*: - version "10.2.5" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-10.2.5.tgz#bd48687a0be38ed2961399105600f832095861d1" - integrity sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg== - dependencies: - brace-expansion "^5.0.5" - minimatch@9.0.3: version "9.0.3" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" @@ -11809,13 +11846,6 @@ minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: dependencies: brace-expansion "^1.1.7" -minimatch@^5.0.1, minimatch@^5.1.8: - version "5.1.9" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.9.tgz#1293ef15db0098b394540e8f9f744f9fda8dee4b" - integrity sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw== - dependencies: - brace-expansion "^2.0.1" - minimatch@^9.0.0, minimatch@^9.0.4: version "9.0.9" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.9.tgz#9b0cb9fcb78087f6fd7eababe2511c4d3d60574e" @@ -11823,6 +11853,13 @@ minimatch@^9.0.0, minimatch@^9.0.4: dependencies: brace-expansion "^2.0.2" +"minimatch@^9.0.3 || ^10.1.2": + version "10.2.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-10.2.5.tgz#bd48687a0be38ed2961399105600f832095861d1" + integrity sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg== + dependencies: + brace-expansion "^5.0.5" + minimatch@~3.0.5: version "3.0.8" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.8.tgz#5e6a59bd11e2ab0de1cfb843eb2d82e546c321c1" @@ -11839,7 +11876,7 @@ minimist-options@4.1.0: is-plain-obj "^1.1.0" kind-of "^6.0.3" -minimist@^1.1.0, minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6, minimist@^1.2.8: +minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6, minimist@^1.2.8: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== @@ -11894,16 +11931,6 @@ module-details-from-path@^1.0.3: resolved "https://registry.yarnpkg.com/module-details-from-path/-/module-details-from-path-1.0.4.tgz#b662fdcd93f6c83d3f25289da0ce81c8d9685b94" integrity sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w== -moment-duration-format-commonjs@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/moment-duration-format-commonjs/-/moment-duration-format-commonjs-1.0.1.tgz#ca8776466dba736a30cb7cda4e07026b5aec8cf1" - integrity sha512-KhKZRH21/+ihNRWrmdNFOyBptFi7nAWZFeFsRRpXkzgk/Yublb4fxyP0jU6EY1VDxUL/VUPdCmm/wAnpbfXdfw== - -moment@^2.14.1, moment@^2.29.4: - version "2.30.1" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae" - integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how== - moo@^0.5.0: version "0.5.3" resolved "https://registry.yarnpkg.com/moo/-/moo-0.5.3.tgz#dfcdb40ff6f1a03c34af5df7f9717cecfa88c38c" @@ -11919,12 +11946,7 @@ ms@2.0.0: resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== -ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -ms@2.1.3, ms@^2.1.1, ms@^2.1.3: +ms@2.1.3, ms@^2.0.0, ms@^2.1.1, ms@^2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== @@ -11937,11 +11959,6 @@ multicast-dns@^7.2.5: dns-packet "^5.2.2" thunky "^1.0.2" -mustache@^2.1.1, mustache@^2.1.2, mustache@^2.2.1: - version "2.3.2" - resolved "https://registry.yarnpkg.com/mustache/-/mustache-2.3.2.tgz#a6d4d9c3f91d13359ab889a812954f9230a3d0c5" - integrity sha512-KpMNwdQsYz3O/SBS1qJ/o3sqUJ5wSb8gb0pul8CO0S56b9Y2ALm8zCfsjPXsqGFfoNBkDwZuZIAjhsZI03gYVQ== - mute-stream@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" @@ -11957,7 +11974,7 @@ nan@^2.12.1, nan@^2.24.0: resolved "https://registry.yarnpkg.com/nan/-/nan-2.26.2.tgz#2e5e25764224c737b9897790b57c3294d4dcee9c" integrity sha512-0tTvBTYkt3tdGw22nrAy50x7gpbGCCFH3AFcyS5WiUu7Eu4vWlri1woE6qHBSfy11vksDqkiwjOnlR7WV8G1Hw== -nanoid@^3.1.12, nanoid@^3.1.31, nanoid@^3.3.11: +nanoid@^3.3.11: version "3.3.11" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b" integrity sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w== @@ -12037,6 +12054,11 @@ node-addon-api@^7.0.0: resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-7.1.1.tgz#1aba6693b0f255258a049d621329329322aad558" integrity sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ== +node-domexception@1.0.0, node-domexception@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" + integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== + node-exports-info@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/node-exports-info/-/node-exports-info-1.6.0.tgz#1aedafb01a966059c9a5e791a94a94d93f5c2a13" @@ -12047,6 +12069,22 @@ node-exports-info@^1.6.0: object.entries "^1.1.9" semver "^6.3.1" +node-fetch@2.7.0, node-fetch@^2.6.7: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + +node-fetch@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.3.2.tgz#d1e889bacdf733b4ff3b2b243eb7a12866a0b78b" + integrity sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA== + dependencies: + data-uri-to-buffer "^4.0.0" + fetch-blob "^3.1.4" + formdata-polyfill "^4.0.10" + node-forge@^1: version "1.4.0" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.4.0.tgz#1c7b7d8bdc2d078739f58287d589d903a11b2fc2" @@ -12158,7 +12196,7 @@ npm-run-path@^2.0.0: dependencies: path-key "^2.0.0" -npm-run-path@^4.0.0, npm-run-path@^4.0.1: +npm-run-path@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== @@ -12172,7 +12210,7 @@ nth-check@^2.0.1: dependencies: boolbase "^1.0.0" -nwsapi@^2.0.7, nwsapi@^2.2.2: +nwsapi@^2.0.7, nwsapi@^2.2.16, nwsapi@^2.2.2: version "2.2.23" resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.23.tgz#59712c3a88e6de2bb0b6ccc1070397267019cf6c" integrity sha512-7wfH4sLbt4M0gCDzGE6vzQBo0bfTKjU7Sfpqy/7gs1qBfYz2vEJH6vXcBKpO3+6Yu1telwd0t9HpyOoLEQQbIQ== @@ -12182,7 +12220,7 @@ oauth-sign@~0.9.0: resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -object-assign@^4.0.1, object-assign@^4.1.1: +object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== @@ -12347,13 +12385,6 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" -onetime@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" - integrity sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ== - dependencies: - mimic-fn "^1.0.0" - onetime@^5.1.0, onetime@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" @@ -12361,6 +12392,23 @@ onetime@^5.1.0, onetime@^5.1.2: dependencies: mimic-fn "^2.1.0" +onetime@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-7.0.0.tgz#9f16c92d8c9ef5120e3acd9dd9957cceecc1ab60" + integrity sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ== + dependencies: + mimic-function "^5.0.0" + +open@^10.2.0: + version "10.2.0" + resolved "https://registry.yarnpkg.com/open/-/open-10.2.0.tgz#b9d855be007620e80b6fb05fac98141fe62db73c" + integrity sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA== + dependencies: + default-browser "^5.2.1" + define-lazy-prop "^3.0.0" + is-inside-container "^1.0.0" + wsl-utils "^0.1.0" + open@^8.0.9, open@^8.4.0: version "8.4.2" resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9" @@ -12370,6 +12418,19 @@ open@^8.0.9, open@^8.4.0: is-docker "^2.1.1" is-wsl "^2.2.0" +openai@^4.0.0: + version "4.104.0" + resolved "https://registry.yarnpkg.com/openai/-/openai-4.104.0.tgz#c489765dc051b95019845dab64b0e5207cae4d30" + integrity sha512-p99EFNsA/yX6UhVO93f5kJsDRLAg+CTA2RBqdHK4RtK8u5IJw32Hyb2dTGKbnnFmnuoBv5r7Z2CURI9sGZpSuA== + dependencies: + "@types/node" "^18.11.18" + "@types/node-fetch" "^2.6.4" + abort-controller "^3.0.0" + agentkeepalive "^4.2.1" + form-data-encoder "1.7.2" + formdata-node "^4.3.2" + node-fetch "^2.6.7" + opener@^1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598" @@ -12413,11 +12474,6 @@ ora@^4.0.2: strip-ansi "^6.0.0" wcwidth "^1.0.1" -os-family@^1.0.0, os-family@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/os-family/-/os-family-1.1.0.tgz#8a89cb617dd1631b8ef9506be830144f626c214e" - integrity sha512-E3Orl5pvDJXnVmpaAA2TeNNpNhTMl4o5HghuWhOivBjEiTnJSrMYSa5uZMek1lBEvu8kKEsa2YgVcGFVDqX/9w== - os-homedir@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" @@ -12442,11 +12498,6 @@ p-finally@^1.0.0: resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" integrity sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow== -p-finally@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-2.0.1.tgz#bd6fcaa9c559a096b680806f4d657b3f0f240561" - integrity sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw== - p-limit@^2.0.0, p-limit@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" @@ -12496,18 +12547,6 @@ p-locate@^6.0.0: dependencies: p-limit "^4.0.0" -p-map@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.2.0.tgz#e4e94f311eabbc8633a1e79908165fca26241b6b" - integrity sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA== - -p-map@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-3.0.0.tgz#d704d9af8a2ba684e2600d9a215983d4141a979d" - integrity sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ== - dependencies: - aggregate-error "^3.0.0" - p-retry@^4.5.0: version "4.6.2" resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.6.2.tgz#9baae7184057edd4e17231cee04264106e092a16" @@ -12613,22 +12652,12 @@ parse5@4.0.0: resolved "https://registry.yarnpkg.com/parse5/-/parse5-4.0.0.tgz#6d78656e3da8d78b4ec0b906f7c08ef1dfe3f608" integrity sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA== -parse5@^1.5.0: - version "1.5.1" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-1.5.1.tgz#9b7f3b0de32be78dc2401b17573ccaf0f6f59d94" - integrity sha512-w2jx/0tJzvgKwZa58sj2vAYq/S/K1QJfIB3cWYea/Iu1scFPDQQ3IQiVZTHWtRBwAjv2Yd7S/xeZf3XqLDb3bA== - -parse5@^2.1.5: - version "2.2.3" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-2.2.3.tgz#0c4fc41c1000c5e6b93d48b03f8083837834e9f6" - integrity sha512-yJQdbcT+hCt6HD+BuuUvjHUdNwerQIKSJSm7tXjtp6oIH5Mxbzlt/VIIeWxblsgcDt1+E7kxPeilD5McWswStA== - parse5@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== -parse5@^7.0.0, parse5@^7.1.1, parse5@^7.1.2: +parse5@^7.0.0, parse5@^7.1.1, parse5@^7.2.1: version "7.3.0" resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.3.0.tgz#d7e224fa72399c7a175099f45fc2ad024b05ec05" integrity sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw== @@ -12686,11 +12715,6 @@ path-is-absolute@^1.0.0: resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== -path-is-inside@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" - integrity sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w== - path-key@^2.0.0, path-key@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" @@ -12714,13 +12738,6 @@ path-scurry@^1.11.1: lru-cache "^10.2.0" minipass "^5.0.0 || ^6.0.2 || ^7.0.0" -path-to-regexp@^1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.9.0.tgz#5dc0753acbf8521ca2e0f137b4578b917b10cf24" - integrity sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g== - dependencies: - isarray "0.0.1" - path-to-regexp@~0.1.12: version "0.1.13" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.13.tgz#9b22ec16bc3ab88d05a0c7e369869421401ab17d" @@ -12738,10 +12755,10 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== -pathval@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" - integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== +pathval@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-2.0.1.tgz#8855c5a2899af072d6ac05d11e46045ad0dc605d" + integrity sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ== pend@~1.2.0: version "1.2.0" @@ -12789,7 +12806,7 @@ picomatch@^4.0.3, picomatch@^4.0.4: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.4.tgz#fd6f5e00a143086e074dffe4c924b8fb293b0589" integrity sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A== -pify@2.3.0, pify@^2.0.0, pify@^2.2.0, pify@^2.3.0: +pify@2.3.0, pify@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog== @@ -12804,43 +12821,11 @@ pify@^4.0.1: resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== -pinkie-promise@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-1.0.0.tgz#d1da67f5482563bb7cf57f286ae2822ecfbf3670" - integrity sha512-5mvtVNse2Ml9zpFKkWBpGsTPwm3DKhs+c95prO/F6E7d6DN0FPqxs6LONpLNpyD7Iheb7QN4BbUoKJgo+DnkQA== - dependencies: - pinkie "^1.0.0" - -pinkie-promise@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" - integrity sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw== - dependencies: - pinkie "^2.0.0" - -pinkie@2.0.4, pinkie@^2.0.0, pinkie@^2.0.1, pinkie@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - integrity sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg== - -pinkie@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-1.0.0.tgz#5a47f28ba1015d0201bda7bf0f358e47bec8c7e4" - integrity sha512-VFVaU1ysKakao68ktZm76PIdOhvEfoNNRaGkyLln9Os7r0/MCxqHjHyBM7dT3pgTiBybqiPtpqKfpENwdBp50Q== - pirates@^4.0.1, pirates@^4.0.4: version "4.0.7" resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.7.tgz#643b4a18c4257c8a65104b73f3049ce9a0a15e22" integrity sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA== -pkg-conf@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/pkg-conf/-/pkg-conf-3.1.0.tgz#d9f9c75ea1bae0e77938cde045b276dac7cc69ae" - integrity sha512-m0OTbR/5VPNPqO1ph6Fqbj7Hv6QU7gR/tQW40ZqrL1rjgCU85W6C1bJn0BItuJqnR98PWzw7Z8hHeChD1WrgdQ== - dependencies: - find-up "^3.0.0" - load-json-file "^5.2.0" - pkg-dir@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" @@ -12855,13 +12840,6 @@ pkg-dir@^7.0.0: dependencies: find-up "^6.3.0" -pkg-up@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-3.1.0.tgz#100ec235cc150e4fd42519412596a28512a0def5" - integrity sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA== - dependencies: - find-up "^3.0.0" - playwright-core@1.59.1: version "1.59.1" resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.59.1.tgz#d8a2b28bcb8f2bd08ef3df93b02ae83c813244b2" @@ -12888,11 +12866,6 @@ pn@^1.1.0: resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb" integrity sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA== -pngjs@^3.3.1: - version "3.4.0" - resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.4.0.tgz#99ca7d725965fb655814eaf65f38f12bbdbf555f" - integrity sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w== - posix-character-classes@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" @@ -12903,14 +12876,6 @@ possible-typed-array-names@^1.0.0: resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz#93e3582bc0e5426586d9d07b79ee40fc841de4ae" integrity sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg== -postcss-calc@^10.1.1: - version "10.1.1" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-10.1.1.tgz#52b385f2e628239686eb6e3a16207a43f36064ca" - integrity sha512-NYEsLHh8DgG/PRH2+G9BTuUdtf9ViS+vdoQ0YA5OQdGsfN4ztiwtDWNtBl9EKeqNMFnIu8IKZ0cLxEQ5r5KVMw== - dependencies: - postcss-selector-parser "^7.0.0" - postcss-value-parser "^4.2.0" - postcss-calc@^9.0.1: version "9.0.1" resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-9.0.1.tgz#a744fd592438a93d6de0f1434c572670361eb6c6" @@ -12929,16 +12894,6 @@ postcss-colormin@^6.1.0: colord "^2.9.3" postcss-value-parser "^4.2.0" -postcss-colormin@^7.0.8: - version "7.0.8" - resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-7.0.8.tgz#457eb63f4438cb5799b01975c5a1604155eb4d7e" - integrity sha512-VX0JOZx0jECwGK0GZejIKvXIU+80S1zkjet31FVUYPZ4O+IPU3ZlntrPdPKT2HnKRMOkc0wy3m/v+c4UNta02g== - dependencies: - "@colordx/core" "^5.0.3" - browserslist "^4.28.2" - caniuse-api "^3.0.0" - postcss-value-parser "^4.2.0" - postcss-convert-values@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-6.1.0.tgz#3498387f8efedb817cbc63901d45bd1ceaa40f48" @@ -12947,56 +12902,26 @@ postcss-convert-values@^6.1.0: browserslist "^4.23.0" postcss-value-parser "^4.2.0" -postcss-convert-values@^7.0.10: - version "7.0.10" - resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-7.0.10.tgz#cbf8bedef3acae5373ed9c98c4f289b72926adb3" - integrity sha512-hVqVH3cDkPyxL4Q0xpCquRAXjJDZ6hbpjC+PNWn8ZgHmNX3RZxLtruC3U2LY9EuNe+tp4QkcsZxg0htokmjydg== - dependencies: - browserslist "^4.28.2" - postcss-value-parser "^4.2.0" - postcss-discard-comments@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-6.0.2.tgz#e768dcfdc33e0216380623652b0a4f69f4678b6c" integrity sha512-65w/uIqhSBBfQmYnG92FO1mWZjJ4GL5b8atm5Yw2UgrwD7HiNiSSNwJor1eCFGzUgYnN/iIknhNRVqjrrpuglw== -postcss-discard-comments@^7.0.6: - version "7.0.6" - resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-7.0.6.tgz#4e9c696a83391d90b3ffa4485ac144e555db443c" - integrity sha512-Sq+Fzj1Eg5/CPf1ERb0wS1Im5cvE2gDXCE+si4HCn1sf+jpQZxDI4DXEp8t77B/ImzDceWE2ebJQFXdqZ6GRJw== - dependencies: - postcss-selector-parser "^7.1.1" - postcss-discard-duplicates@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-6.0.3.tgz#d121e893c38dc58a67277f75bb58ba43fce4c3eb" integrity sha512-+JA0DCvc5XvFAxwx6f/e68gQu/7Z9ud584VLmcgto28eB8FqSFZwtrLwB5Kcp70eIoWP/HXqz4wpo8rD8gpsTw== -postcss-discard-duplicates@^7.0.2: - version "7.0.2" - resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-7.0.2.tgz#9cf3e659d4f94b046eef6f93679490c0250a8e4e" - integrity sha512-eTonaQvPZ/3i1ASDHOKkYwAybiM45zFIc7KXils4mQmHLqIswXD9XNOKEVxtTFnsmwYzF66u4LMgSr0abDlh5w== - postcss-discard-empty@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-6.0.3.tgz#ee39c327219bb70473a066f772621f81435a79d9" integrity sha512-znyno9cHKQsK6PtxL5D19Fj9uwSzC2mB74cpT66fhgOadEUPyXFkbgwm5tvc3bt3NAy8ltE5MrghxovZRVnOjQ== -postcss-discard-empty@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-7.0.1.tgz#b6c57e8b5c69023169abea30dceb93f98a2ffd9f" - integrity sha512-cFrJKZvcg/uxB6Ijr4l6qmn3pXQBna9zyrPC+sK0zjbkDUZew+6xDltSF7OeB7rAtzaaMVYSdbod+sZOCWnMOg== - postcss-discard-overridden@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-6.0.2.tgz#4e9f9c62ecd2df46e8fdb44dc17e189776572e2d" integrity sha512-j87xzI4LUggC5zND7KdjsI25APtyMuynXZSujByMaav2roV6OZX+8AaCUcZSWqckZpjAjRyFDdpqybgjFO0HJQ== -postcss-discard-overridden@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-7.0.1.tgz#bd9c9bc5e4548d3b6e67e7f8d64f2c9d745ae2a0" - integrity sha512-7c3MMjjSZ/qYrx3uc1940GSOzN1Iqjtlqe8uoSg+qdVPYyRb0TILSqqmtlSFuE4mTDECwsm397Ya7iXGzfF7lg== - postcss-import@^16.1.1: version "16.1.1" resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-16.1.1.tgz#cfbe79e6c9232b0dbbe1c18f35308825cfe8ff2a" @@ -13028,14 +12953,6 @@ postcss-merge-longhand@^6.0.5: postcss-value-parser "^4.2.0" stylehacks "^6.1.1" -postcss-merge-longhand@^7.0.5: - version "7.0.5" - resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-7.0.5.tgz#e1b126e92f583815482e8b1e82c47d2435a20421" - integrity sha512-Kpu5v4Ys6QI59FxmxtNB/iHUVDn9Y9sYw66D6+SZoIk4QTz1prC4aYkhIESu+ieG1iylod1f8MILMs1Em3mmIw== - dependencies: - postcss-value-parser "^4.2.0" - stylehacks "^7.0.5" - postcss-merge-rules@^6.1.1: version "6.1.1" resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-6.1.1.tgz#7aa539dceddab56019469c0edd7d22b64c3dea9d" @@ -13046,16 +12963,6 @@ postcss-merge-rules@^6.1.1: cssnano-utils "^4.0.2" postcss-selector-parser "^6.0.16" -postcss-merge-rules@^7.0.9: - version "7.0.9" - resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-7.0.9.tgz#e281067714de26fa7d0ab50b706bd29b24fc7442" - integrity sha512-XKMXkHAegyLeIymVylg1Ro4NNHITInHPvmvybsIUximYfsg5fRw2b5TeqLTQwwg5cXEDVa556AAxvMve1MJuJA== - dependencies: - browserslist "^4.28.2" - caniuse-api "^3.0.0" - cssnano-utils "^5.0.1" - postcss-selector-parser "^7.1.1" - postcss-minify-font-values@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-6.1.0.tgz#a0e574c02ee3f299be2846369211f3b957ea4c59" @@ -13063,13 +12970,6 @@ postcss-minify-font-values@^6.1.0: dependencies: postcss-value-parser "^4.2.0" -postcss-minify-font-values@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-7.0.1.tgz#6fb4770131b31fd5a2014bd84e32f386a3406664" - integrity sha512-2m1uiuJeTplll+tq4ENOQSzB8LRnSUChBv7oSyFLsJRtUgAAJGP6LLz0/8lkinTgxrmJSPOEhgY1bMXOQ4ZXhQ== - dependencies: - postcss-value-parser "^4.2.0" - postcss-minify-gradients@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-6.0.3.tgz#ca3eb55a7bdb48a1e187a55c6377be918743dbd6" @@ -13079,15 +12979,6 @@ postcss-minify-gradients@^6.0.3: cssnano-utils "^4.0.2" postcss-value-parser "^4.2.0" -postcss-minify-gradients@^7.0.3: - version "7.0.3" - resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-7.0.3.tgz#5a866f18b3ae3f4bdbab78fc0776d38c87537bb4" - integrity sha512-2znRFq3Pg+Zo0ttzQxO7qIJdY2er1TOZbclHW2qMqBcHMmz+i6nn3roAyG3kuEDQTzbzd3gn24TAIifEfth1PQ== - dependencies: - "@colordx/core" "^5.0.3" - cssnano-utils "^5.0.1" - postcss-value-parser "^4.2.0" - postcss-minify-params@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-6.1.0.tgz#54551dec77b9a45a29c3cb5953bf7325a399ba08" @@ -13097,15 +12988,6 @@ postcss-minify-params@^6.1.0: cssnano-utils "^4.0.2" postcss-value-parser "^4.2.0" -postcss-minify-params@^7.0.7: - version "7.0.7" - resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-7.0.7.tgz#afc93ae5958ddbcb3fa22e2178263b22e55d341e" - integrity sha512-OPmvW/9sjPEPQYnS2Sh6jvMW54wqk1IjjEMB8k/7V8SUIie71yMy3HQ9+w/ZHoL1YvgDGBQ/mCxP3n0Y/RxgqA== - dependencies: - browserslist "^4.28.2" - cssnano-utils "^5.0.1" - postcss-value-parser "^4.2.0" - postcss-minify-selectors@^6.0.4: version "6.0.4" resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-6.0.4.tgz#197f7d72e6dd19eed47916d575d69dc38b396aff" @@ -13113,14 +12995,6 @@ postcss-minify-selectors@^6.0.4: dependencies: postcss-selector-parser "^6.0.16" -postcss-minify-selectors@^7.0.6: - version "7.0.6" - resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-7.0.6.tgz#1e0240e1fa3372d81d3f0586591f1e8d2ae21e16" - integrity sha512-lIbC0jy3AAwDxEgciZlBullDiMBeBCT+fz5G8RcA9MWqh/hfUkpOI3vNDUNEZHgokaoiv0juB9Y8fGcON7rU/A== - dependencies: - cssesc "^3.0.0" - postcss-selector-parser "^7.1.1" - postcss-modules-extract-imports@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz#b4497cb85a9c0c4b5aabeb759bb25e8d89f15002" @@ -13154,11 +13028,6 @@ postcss-normalize-charset@^6.0.2: resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-6.0.2.tgz#1ec25c435057a8001dac942942a95ffe66f721e1" integrity sha512-a8N9czmdnrjPHa3DeFlwqst5eaL5W8jYu3EBbTTkI5FHkfMhFZh1EGbku6jhHhIzTA6tquI2P42NtZ59M/H/kQ== -postcss-normalize-charset@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-7.0.1.tgz#bccc3f7c5f4440883608eea8b444c8f41ce55ff6" - integrity sha512-sn413ofhSQHlZFae//m9FTOfkmiZ+YQXsbosqOWRiVQncU2BA3daX3n0VF3cG6rGLSFVc5Di/yns0dFfh8NFgQ== - postcss-normalize-display-values@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-6.0.2.tgz#54f02764fed0b288d5363cbb140d6950dbbdd535" @@ -13166,13 +13035,6 @@ postcss-normalize-display-values@^6.0.2: dependencies: postcss-value-parser "^4.2.0" -postcss-normalize-display-values@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-7.0.1.tgz#feb40277d89a7f677b67a84cac999f0306e38235" - integrity sha512-E5nnB26XjSYz/mGITm6JgiDpAbVuAkzXwLzRZtts19jHDUBFxZ0BkXAehy0uimrOjYJbocby4FVswA/5noOxrQ== - dependencies: - postcss-value-parser "^4.2.0" - postcss-normalize-positions@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-6.0.2.tgz#e982d284ec878b9b819796266f640852dbbb723a" @@ -13180,13 +13042,6 @@ postcss-normalize-positions@^6.0.2: dependencies: postcss-value-parser "^4.2.0" -postcss-normalize-positions@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-7.0.1.tgz#c771c0d33034455205f060b999d8557c2308d22c" - integrity sha512-pB/SzrIP2l50ZIYu+yQZyMNmnAcwyYb9R1fVWPRxm4zcUFCY2ign7rcntGFuMXDdd9L2pPNUgoODDk91PzRZuQ== - dependencies: - postcss-value-parser "^4.2.0" - postcss-normalize-repeat-style@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-6.0.2.tgz#f8006942fd0617c73f049dd8b6201c3a3040ecf3" @@ -13194,13 +13049,6 @@ postcss-normalize-repeat-style@^6.0.2: dependencies: postcss-value-parser "^4.2.0" -postcss-normalize-repeat-style@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-7.0.1.tgz#05fe4d838eedbd996436c5cab78feef9bb1ae57b" - integrity sha512-NsSQJ8zj8TIDiF0ig44Byo3Jk9e4gNt9x2VIlJudnQQ5DhWAHJPF4Tr1ITwyHio2BUi/I6Iv0HRO7beHYOloYQ== - dependencies: - postcss-value-parser "^4.2.0" - postcss-normalize-string@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-6.0.2.tgz#e3cc6ad5c95581acd1fc8774b309dd7c06e5e363" @@ -13208,13 +13056,6 @@ postcss-normalize-string@^6.0.2: dependencies: postcss-value-parser "^4.2.0" -postcss-normalize-string@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-7.0.1.tgz#0f111e7b5dfb6de6ab19f09d9e1c16fabeee232f" - integrity sha512-QByrI7hAhsoze992kpbMlJSbZ8FuCEc1OT9EFbZ6HldXNpsdpZr+YXC5di3UEv0+jeZlHbZcoCADgb7a+lPmmQ== - dependencies: - postcss-value-parser "^4.2.0" - postcss-normalize-timing-functions@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-6.0.2.tgz#40cb8726cef999de984527cbd9d1db1f3e9062c0" @@ -13222,13 +13063,6 @@ postcss-normalize-timing-functions@^6.0.2: dependencies: postcss-value-parser "^4.2.0" -postcss-normalize-timing-functions@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-7.0.1.tgz#7b645a36f113fec49d95d56386c9980316c71216" - integrity sha512-bHifyuuSNdKKsnNJ0s8fmfLMlvsQwYVxIoUBnowIVl2ZAdrkYQNGVB4RxjfpvkMjipqvbz0u7feBZybkl/6NJg== - dependencies: - postcss-value-parser "^4.2.0" - postcss-normalize-unicode@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-6.1.0.tgz#aaf8bbd34c306e230777e80f7f12a4b7d27ce06e" @@ -13237,14 +13071,6 @@ postcss-normalize-unicode@^6.1.0: browserslist "^4.23.0" postcss-value-parser "^4.2.0" -postcss-normalize-unicode@^7.0.7: - version "7.0.7" - resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-7.0.7.tgz#c94d2cd291bbe37dd25b8fe1a683a507c0709d41" - integrity sha512-Kfm0mC3gTnOC+SsLgxQqNEZStRxJgBaYrMpBe9fDVB0/MjC1G++FAeDW2YxYc5Mbvav12/7mOBSOTW7HK9Knwg== - dependencies: - browserslist "^4.28.2" - postcss-value-parser "^4.2.0" - postcss-normalize-url@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-6.0.2.tgz#292792386be51a8de9a454cb7b5c58ae22db0f79" @@ -13252,13 +13078,6 @@ postcss-normalize-url@^6.0.2: dependencies: postcss-value-parser "^4.2.0" -postcss-normalize-url@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-7.0.1.tgz#d6471a22b6747ce93d7038c16eb9f1ba8b307e25" - integrity sha512-sUcD2cWtyK1AOL/82Fwy1aIVm/wwj5SdZkgZ3QiUzSzQQofrbq15jWJ3BA7Z+yVRwamCjJgZJN0I9IS7c6tgeQ== - dependencies: - postcss-value-parser "^4.2.0" - postcss-normalize-whitespace@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-6.0.2.tgz#fbb009e6ebd312f8b2efb225c2fcc7cf32b400cd" @@ -13266,13 +13085,6 @@ postcss-normalize-whitespace@^6.0.2: dependencies: postcss-value-parser "^4.2.0" -postcss-normalize-whitespace@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-7.0.1.tgz#ab8e9ff1f3213f3f3851c0a7d0e4ce4716777cea" - integrity sha512-vsbgFHMFQrJBJKrUFJNZ2pgBeBkC2IvvoHjz1to0/0Xk7sII24T0qFOiJzG6Fu3zJoq/0yI4rKWi7WhApW+EFA== - dependencies: - postcss-value-parser "^4.2.0" - postcss-ordered-values@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-6.0.2.tgz#366bb663919707093451ab70c3f99c05672aaae5" @@ -13281,14 +13093,6 @@ postcss-ordered-values@^6.0.2: cssnano-utils "^4.0.2" postcss-value-parser "^4.2.0" -postcss-ordered-values@^7.0.2: - version "7.0.2" - resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-7.0.2.tgz#0e803fbb9601e254270481772252de9a8c905f48" - integrity sha512-AMJjt1ECBffF7CEON/Y0rekRLS6KsePU6PRP08UqYW4UGFRnTXNrByUzYK1h8AC7UWTZdQ9O3Oq9kFIhm0SFEw== - dependencies: - cssnano-utils "^5.0.1" - postcss-value-parser "^4.2.0" - postcss-reduce-initial@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-6.1.0.tgz#4401297d8e35cb6e92c8e9586963e267105586ba" @@ -13297,14 +13101,6 @@ postcss-reduce-initial@^6.1.0: browserslist "^4.23.0" caniuse-api "^3.0.0" -postcss-reduce-initial@^7.0.7: - version "7.0.7" - resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-7.0.7.tgz#a4c9f976ed1279e6bc59560fe45b3e3df9c434d4" - integrity sha512-evetDQPqkgrzHoP8g3HjE3KgH0j2W0je2Vt1pfTaO2KvmjulStxGC2IGeI2y0pdLi6ryEGc4nD08zpDRP9ge8w== - dependencies: - browserslist "^4.28.2" - caniuse-api "^3.0.0" - postcss-reduce-transforms@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-6.0.2.tgz#6fa2c586bdc091a7373caeee4be75a0f3e12965d" @@ -13312,13 +13108,6 @@ postcss-reduce-transforms@^6.0.2: dependencies: postcss-value-parser "^4.2.0" -postcss-reduce-transforms@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-7.0.1.tgz#f87111264b0dfa07e1f708d7e6401578707be5d6" - integrity sha512-MhyEbfrm+Mlp/36hvZ9mT9DaO7dbncU0CvWI8V93LRkY6IYlu38OPg3FObnuKTUxJ4qA8HpurdQOo5CyqqO76g== - dependencies: - postcss-value-parser "^4.2.0" - postcss-resolve-nested-selector@^0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.6.tgz#3d84dec809f34de020372c41b039956966896686" @@ -13358,14 +13147,6 @@ postcss-svgo@^6.0.3: postcss-value-parser "^4.2.0" svgo "^3.2.0" -postcss-svgo@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-7.1.1.tgz#14b90fd2a1b1f27bcb2d0ef0444f954237e7883c" - integrity sha512-zU9H9oEDrUFKa0JB7w+IYL7Qs9ey1mZyjhbf0KLxwJDdDRtoPvCmaEfknzqfHj44QS9VD6c5sJnBAVYTLRg/Sg== - dependencies: - postcss-value-parser "^4.2.0" - svgo "^4.0.1" - postcss-unique-selectors@^6.0.4: version "6.0.4" resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-6.0.4.tgz#983ab308896b4bf3f2baaf2336e14e52c11a2088" @@ -13373,19 +13154,12 @@ postcss-unique-selectors@^6.0.4: dependencies: postcss-selector-parser "^6.0.16" -postcss-unique-selectors@^7.0.5: - version "7.0.5" - resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-7.0.5.tgz#a7dd5652c95f459176e5f135c021473e4ee58874" - integrity sha512-3QoYmEt4qg/rUWDn6Tc8+ZVPmbp4G1hXDtCNWDx0st8SjtCbRcxRXDDM1QrEiXGG3A45zscSJFb4QH90LViyxg== - dependencies: - postcss-selector-parser "^7.1.1" - postcss-value-parser@^4.0.0, postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== -postcss@^8.4.21, postcss@^8.4.33, postcss@^8.4.38, postcss@^8.4.41, postcss@^8.4.5, postcss@^8.5.6: +postcss@^8.4.21, postcss@^8.4.33, postcss@^8.4.41, postcss@^8.4.5, postcss@^8.5.6: version "8.5.9" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.9.tgz#f6ee9e0b94f0f19c97d2f172bfbd7fc71fe1cca4" integrity sha512-7a70Nsot+EMX9fFU3064K/kdHWZqGVY+BADLyXc8Dfv+mTLLVl6JzJpPaCZ2kQL9gIJvKXSLMHhqdRRjwQeFtw== @@ -13394,6 +13168,15 @@ postcss@^8.4.21, postcss@^8.4.33, postcss@^8.4.38, postcss@^8.4.41, postcss@^8.4 picocolors "^1.1.1" source-map-js "^1.2.1" +postcss@^8.4.38: + version "8.5.10" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.10.tgz#8992d8c30acf3f12169e7c09514a12fed7e48356" + integrity sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ== + dependencies: + nanoid "^3.3.11" + picocolors "^1.1.1" + source-map-js "^1.2.1" + postgres-array@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-2.0.0.tgz#48f8fce054fbc69671999329b8834b772652d82e" @@ -13416,6 +13199,22 @@ postgres-interval@^1.1.0: dependencies: xtend "^4.0.0" +potomatic@^1.0.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/potomatic/-/potomatic-1.2.0.tgz#61eb8e17297cab19f798557acd73a46e48a7b77e" + integrity sha512-vmx9IwG9G2BCGvmxH4CW3F+NgyEvESTblyx5O2tZooA2fCJ7ZouTcbzPf9vXHMpLv+hXMg16uMGOyCw34RSQ4A== + dependencies: + chalk "^5.3.0" + commander "^12.0.0" + dotenv "^16.5.0" + extract-zip "^2.0.1" + gettext-parser "^8.0.0" + listr2 "^8.0.0" + node-fetch "^3.3.2" + openai "^4.0.0" + tiktoken "^1.0.21" + zod "^3.25.23" + preact@^10.10.0: version "10.29.1" resolved "https://registry.yarnpkg.com/preact/-/preact-10.29.1.tgz#2a5b936efe91cfe1e773cdb55dceb55d148d1d4b" @@ -13438,7 +13237,7 @@ prettier-linter-helpers@^1.0.1: dependencies: fast-diff "^1.1.2" -prettier@^3.3.3: +prettier@^3.6.2: version "3.8.2" resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.8.2.tgz#4f52e502193c9aa5b384c3d00852003e551bbd9f" integrity sha512-8c3mgTe0ASwWAJK+78dpviD+A8EqhndQPUBpNUIPt6+xWlIigCwfN01lWr9MAede4uqXGTEKeQWTvzb3vjia0Q== @@ -13448,6 +13247,15 @@ prettier@^3.3.3: resolved "https://registry.yarnpkg.com/wp-prettier/-/wp-prettier-3.0.3.tgz#2b30647d044b83afd10dacfc2805d55fc180d852" integrity sha512-X4UlrxDTH8oom9qXlcjnydsjAOD2BmB6yFmvS4Z2zdTzqqpRWb+fbqrH412+l+OUXmbzJlSXjlMFYPgYG12IAA== +pretty-format@30.3.0: + version "30.3.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-30.3.0.tgz#e977eed4bcd1b6195faed418af8eac68b9ea1f29" + integrity sha512-oG4T3wCbfeuvljnyAzhBvpN45E8iOTXCU/TD3zXW80HA3dQ4ahdqMkWGiPWZvjpQwlbyHrPTWUAqUzGzv4l1JQ== + dependencies: + "@jest/schemas" "30.0.5" + ansi-styles "^5.2.0" + react-is "^18.3.1" + pretty-format@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812" @@ -13457,28 +13265,21 @@ pretty-format@^29.7.0: ansi-styles "^5.0.0" react-is "^18.0.0" -pretty-hrtime@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" - integrity sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A== - process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== +process@^0.11.10: + version "0.11.10" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== + progress@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== -promisify-event@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/promisify-event/-/promisify-event-1.0.0.tgz#bd7523ea06b70162f370979016b53a686c60e90f" - integrity sha512-mshw5LiFmdtphcuUGKyd3t6zmmgIVxrdZ8v4R1INAXHvMemUsDCqIUeq5QUIqqDfed8ZZ6uhov1PqhrdBvHOIA== - dependencies: - pinkie-promise "^2.0.0" - prompts@^2.0.1, prompts@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" @@ -13560,7 +13361,7 @@ puppeteer-core@^23.10.1: typed-query-selector "^2.12.0" ws "^8.18.0" -puppeteer-core@^24.17.1: +puppeteer-core@^24.17.0, puppeteer-core@^24.17.1: version "24.40.0" resolved "https://registry.yarnpkg.com/puppeteer-core/-/puppeteer-core-24.40.0.tgz#1f389cd9432cb077f703ca2cb6758490cdccbc7e" integrity sha512-MWL3XbUCfVgGR0gRsidzT6oKJT2QydPLhMITU6HoVWiiv4gkb6gJi3pcdAa8q4HwjBTbqISOWVP4aJiiyUJvag== @@ -13585,11 +13386,6 @@ qified@^0.9.0: dependencies: hookified "^2.1.1" -qrcode-terminal@^0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/qrcode-terminal/-/qrcode-terminal-0.10.0.tgz#a76a48e2610a18f97fa3a2bd532b682acff86c53" - integrity sha512-ZvWjbAj4MWAj6bnCc9CnculsXnJr7eoKsvH/8rVpZbqYxP2z05HNQa43ZVwe/dVRcFxgfFHE2CkUqn0sCyLfHw== - qs@^6.5.1: version "6.15.1" resolved "https://registry.yarnpkg.com/qs/-/qs-6.15.1.tgz#bdb55aed06bfac257a90c44a446a73fba5575c8f" @@ -13700,7 +13496,7 @@ react-instantsearch-core@7.29.0: zod "^3.25.76 || ^4" zod-to-json-schema "3.24.6" -react-instantsearch@^7.13.6: +react-instantsearch@^7.16.2: version "7.29.0" resolved "https://registry.yarnpkg.com/react-instantsearch/-/react-instantsearch-7.29.0.tgz#274ab2745f087266379fe44adcb861c3d168dde6" integrity sha512-+foJJVVsSLNY3K5rkB2dGEUoOyLMGTZsl9I8Zwwf/nZQqwoqH0QIvkenlJh7deyAq1/u19bq+H5EVX2d+EjRJQ== @@ -13715,7 +13511,7 @@ react-is@^16.12.0, react-is@^16.13.1: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== -"react-is@^16.12.0 || ^17.0.0 || ^18.0.0", react-is@^18.0.0, react-is@^18.2.0: +"react-is@^16.12.0 || ^17.0.0 || ^18.0.0", react-is@^18.0.0, react-is@^18.2.0, react-is@^18.3.1: version "18.3.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e" integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg== @@ -13728,7 +13524,7 @@ react-redux@^9.1.2: "@types/use-sync-external-store" "^0.0.6" use-sync-external-store "^1.4.0" -react-refresh@^0.14.0, react-refresh@^0.14.2: +react-refresh@^0.14.0: version "0.14.2" resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.2.tgz#3833da01ce32da470f1f936b9d477da5c7028bf9" integrity sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA== @@ -13775,13 +13571,6 @@ read-cache@^1.0.0: dependencies: pify "^2.3.0" -read-file-relative@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/read-file-relative/-/read-file-relative-1.2.0.tgz#98f7d96eaa21d2b4c7a2febd63d2fc8cf35e9f9b" - integrity sha512-lwZUlN2tQyPa62/XmVtX1MeNLVutlRWwqvclWU8YpOCgjKdhg2zyNkeFjy7Rnjo3txhKCy5FGgAi+vx59gvkYg== - dependencies: - callsite "^1.0.0" - read-pkg-up@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-4.0.0.tgz#1b221c6088ba7799601c808f91161c66e58f8978" @@ -13840,6 +13629,17 @@ readable-stream@^2.0.1, readable-stream@^2.2.2: string_decoder "~1.1.1" util-deprecate "~1.0.1" +readable-stream@^4.5.2: + version "4.7.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-4.7.0.tgz#cedbd8a1146c13dfff8dab14068028d58c15ac91" + integrity sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg== + dependencies: + abort-controller "^3.0.0" + buffer "^6.0.3" + events "^3.3.0" + process "^0.11.10" + string_decoder "^1.3.0" + readdirp@^4.0.1: version "4.1.2" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-4.1.2.tgz#eb85801435fbf2a7ee58f19e0921b068fc69948d" @@ -13859,6 +13659,17 @@ realpath-native@^1.1.0: dependencies: util.promisify "^1.0.0" +recast@^0.23.5: + version "0.23.11" + resolved "https://registry.yarnpkg.com/recast/-/recast-0.23.11.tgz#8885570bb28cf773ba1dc600da7f502f7883f73f" + integrity sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA== + dependencies: + ast-types "^0.16.1" + esprima "~4.0.0" + source-map "~0.6.1" + tiny-invariant "^1.3.3" + tslib "^2.0.1" + rechoir@^0.8.0: version "0.8.0" resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.8.0.tgz#49f866e0d32146142da3ad8f0eff352b3215ff22" @@ -13946,11 +13757,6 @@ regexp.prototype.flags@^1.5.3, regexp.prototype.flags@^1.5.4: gopd "^1.2.0" set-function-name "^2.0.2" -regexpp@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" - integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== - regexpu-core@^6.3.1: version "6.4.0" resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-6.4.0.tgz#3580ce0c4faedef599eccb146612436b62a176e5" @@ -13975,6 +13781,11 @@ regjsparser@^0.13.0: dependencies: jsesc "~3.1.0" +remove-accents@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/remove-accents/-/remove-accents-0.5.0.tgz#77991f37ba212afba162e375b627631315bed687" + integrity sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A== + remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" @@ -13990,18 +13801,6 @@ repeat-string@^1.6.1: resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w== -repeating@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/repeating/-/repeating-1.1.3.tgz#3d4114218877537494f97f77f9785fab810fa4ac" - integrity sha512-Nh30JLeMHdoI+AsQ5eblhZ7YlTsM9wiJQe/AHIunlK3KWzvXhXb36IJ7K1IOeRjIOtzMjdUHjwXUFxKJoPTSOg== - dependencies: - is-finite "^1.0.0" - -replicator@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/replicator/-/replicator-1.0.5.tgz#f1e56df7e276a62afe80c2248b8ac03896f4708f" - integrity sha512-saxS4y7NFkLMa92BR4bPHR41GD+f/qoDAwD2xZmN+MpDXgibkxwLO2qk7dCHYtskSkd/bWS8Jy6kC5MZUkg1tw== - request-promise-core@1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.4.tgz#3eedd4223208d419867b78ce815167d10593a22f" @@ -14078,11 +13877,6 @@ requires-port@^1.0.0: resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== -reselect@^4.1.7: - version "4.1.8" - resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.1.8.tgz#3f5dc671ea168dccdeb3e141236f69f02eaec524" - integrity sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ== - reselect@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/reselect/-/reselect-5.1.1.tgz#c766b1eb5d558291e5e550298adb0becc24bb72e" @@ -14100,13 +13894,6 @@ resolve-bin@^0.4.0: dependencies: find-parent-dir "~0.3.0" -resolve-cwd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-1.0.0.tgz#4eaeea41ed040d1702457df64a42b2b07d246f9f" - integrity sha512-ac27EnKWWlc2yQ/5GCoCGecqVJ9MSmgiwvUYOS+9A+M0dn1FdP5mnsDZ9gwx+lAvh/d7f4RFn4jLfggRRYxPxw== - dependencies: - resolve-from "^2.0.0" - resolve-cwd@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" @@ -14122,11 +13909,6 @@ resolve-dir@^0.1.0: expand-tilde "^1.2.2" global-modules "^0.2.3" -resolve-from@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57" - integrity sha512-qpFcKaXsq8+oRoLilkwyc7zHGF5i9Q2/25NIgLQQ/+VVv9rU4qvr6nXVAw1DsnXJyQkZsR4Ytfbtg5ehfcUssQ== - resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" @@ -14152,7 +13934,7 @@ resolve.exports@^2.0.0: resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.3.tgz#41955e6f1b4013b7586f873749a635dea07ebe3f" integrity sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A== -resolve@^1.1.7, resolve@^1.10.0, resolve@^1.14.2, resolve@^1.20.0, resolve@^1.22.1, resolve@^1.22.11, resolve@^1.22.8: +resolve@^1.1.7, resolve@^1.10.0, resolve@^1.20.0, resolve@^1.22.11, resolve@^1.22.8: version "1.22.12" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.12.tgz#f5b2a680897c69c238a13cd16b15671f8b73549f" integrity sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA== @@ -14189,6 +13971,14 @@ restore-cursor@^3.1.0: onetime "^5.1.0" signal-exit "^3.0.2" +restore-cursor@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-5.1.0.tgz#0766d95699efacb14150993f55baf0953ea1ebe7" + integrity sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA== + dependencies: + onetime "^7.0.0" + signal-exit "^4.1.0" + ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" @@ -14204,14 +13994,12 @@ reusify@^1.0.4: resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.1.0.tgz#0fe13b9522e1473f51b558ee796e08f11f9b489f" integrity sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw== -rimraf@^2.2.8: - version "2.7.1" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" - integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== - dependencies: - glob "^7.1.3" +rfdc@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.4.1.tgz#778f76c4fb731d93414e8f925fbecf64cce7f6ca" + integrity sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA== -rimraf@^3.0.0, rimraf@^3.0.2: +rimraf@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== @@ -14230,6 +14018,11 @@ robots-parser@^3.0.1: resolved "https://registry.yarnpkg.com/robots-parser/-/robots-parser-3.0.1.tgz#3d8a3cdfa8ac240cbb062a4bd16fcc0e0fb9ed23" integrity sha512-s+pyvQeIKIZ0dx5iJiQk1tPLJAWln39+MI5jtM8wnyws+G5azk+dMnMX0qfbqNetKKNgcWWOdi0sfm+FbQbgdQ== +rrweb-cssom@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz#3021d1b4352fbf3b614aaeed0bc0d5739abe0bc2" + integrity sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw== + rst-selector-parser@^2.2.3: version "2.2.3" resolved "https://registry.yarnpkg.com/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz#81b230ea2fcc6066c89e3472de794285d9b03d91" @@ -14253,6 +14046,11 @@ rtlcss@^4.3.0: postcss "^8.4.21" strip-json-comments "^3.1.1" +run-applescript@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/run-applescript/-/run-applescript-7.1.0.tgz#2e9e54c4664ec3106c5b5630e249d3d6595c4911" + integrity sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q== + run-con@~1.2.10: version "1.2.12" resolved "https://registry.yarnpkg.com/run-con/-/run-con-1.2.12.tgz#51c319910e45a3bd71ee773564a89d96635c8c64" @@ -14288,7 +14086,7 @@ safe-array-concat@^1.1.3: has-symbols "^1.1.0" isarray "^2.0.5" -safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.2, safe-buffer@^5.2.1, safe-buffer@~5.2.0: +safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.1, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -14342,21 +14140,14 @@ sane@^4.0.3: minimist "^1.1.1" walker "~1.0.5" -sanitize-filename@^1.6.0: - version "1.6.4" - resolved "https://registry.yarnpkg.com/sanitize-filename/-/sanitize-filename-1.6.4.tgz#b6b39ebed9bd1a1898b85c5c03089da74590d6f8" - integrity sha512-9ZyI08PsvdQl2r/bBIGubpVdR3RR9sY6RDiWFPreA21C/EFlQhmgo20UZlNjZMMZNubusLhAQozkA0Od5J21Eg== - dependencies: - truncate-utf8-bytes "^1.0.0" - -sass-loader@^16.0.2, sass-loader@^16.0.3: +sass-loader@^16.0.3: version "16.0.7" resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-16.0.7.tgz#d1f8723b795805831d41b5825e3d9cd72cb939e7" integrity sha512-w6q+fRHourZ+e+xA1kcsF27iGM6jdB8teexYCfdUw0sYgcDNeZESnDNT9sUmmPm3ooziwUJXGwZJSTF3kOdBfA== dependencies: neo-async "^2.6.2" -sass@^1.53.0, sass@^1.54.0: +sass@^1.54.0: version "1.99.0" resolved "https://registry.yarnpkg.com/sass/-/sass-1.99.0.tgz#ff9d1594da4886249dfaafabbeea2dea2dc74b26" integrity sha512-kgW13M54DUB7IsIRM5LvJkNlpH+WhMpooUcaWGFARkF1Tc82v9mIWkCbCYf+MBvpIUBSeSOTilpZjEPr2VYE6Q== @@ -14428,19 +14219,12 @@ selfsigned@^2.1.1: resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== -semver@7.5.3: - version "7.5.3" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.3.tgz#161ce8c2c6b4b3bdca6caadc9fa3317a4c4fe88e" - integrity sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ== - dependencies: - lru-cache "^6.0.0" - semver@^6.0.0, semver@^6.3.0, semver@^6.3.1: version "6.3.1" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.0.0, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.2, semver@^7.5.3, semver@^7.5.4, semver@^7.6.3, semver@^7.7.1, semver@^7.7.4: +semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.2, semver@^7.5.3, semver@^7.5.4, semver@^7.6.3, semver@^7.7.1, semver@^7.7.2, semver@^7.7.3, semver@^7.7.4: version "7.7.4" resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.4.tgz#28464e36060e991fa7a11d0279d2d3f3b57a7e8a" integrity sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA== @@ -14473,7 +14257,7 @@ sentence-case@^3.0.4: tslib "^2.0.3" upper-case-first "^2.0.2" -serialize-javascript@^6.0.0, serialize-javascript@^6.0.2: +serialize-javascript@^6.0.0: version "6.0.2" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== @@ -14503,11 +14287,6 @@ serve-static@~1.16.2: parseurl "~1.3.3" send "~0.19.1" -set-cookie-parser@^2.5.1: - version "2.7.2" - resolved "https://registry.yarnpkg.com/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz#ccd08673a9ae5d2e44ea2a2de25089e67c7edf68" - integrity sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw== - set-function-length@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" @@ -14727,6 +14506,22 @@ slice-ansi@^4.0.0: astral-regex "^2.0.0" is-fullwidth-code-point "^3.0.0" +slice-ansi@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-5.0.0.tgz#b73063c57aa96f9cd881654b15294d95d285c42a" + integrity sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ== + dependencies: + ansi-styles "^6.0.0" + is-fullwidth-code-point "^4.0.0" + +slice-ansi@^7.1.0: + version "7.1.2" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-7.1.2.tgz#adf7be70aa6d72162d907cd0e6d5c11f507b5403" + integrity sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w== + dependencies: + ansi-styles "^6.2.1" + is-fullwidth-code-point "^5.0.0" + smart-buffer@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" @@ -14829,7 +14624,7 @@ source-map-support@0.5.13: buffer-from "^1.0.0" source-map "^0.6.0" -source-map-support@^0.5.16, source-map-support@~0.5.20: +source-map-support@~0.5.20: version "0.5.21" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== @@ -14975,7 +14770,7 @@ stack-utils@^1.0.1: dependencies: escape-string-regexp "^2.0.0" -stack-utils@^2.0.3: +stack-utils@^2.0.3, stack-utils@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ== @@ -14987,31 +14782,6 @@ stackframe@^1.3.4: resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.3.4.tgz#b881a004c8c149a5e8efef37d51b16e412943310" integrity sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw== -standard-engine@^15.1.0: - version "15.1.0" - resolved "https://registry.yarnpkg.com/standard-engine/-/standard-engine-15.1.0.tgz#717409a002edd13cd57f6554fdd3464d9a22a774" - integrity sha512-VHysfoyxFu/ukT+9v49d4BRXIokFRZuH3z1VRxzFArZdjSCFpro6rEIU3ji7e4AoAtuSfKBkiOmsrDqKW5ZSRw== - dependencies: - get-stdin "^8.0.0" - minimist "^1.2.6" - pkg-conf "^3.1.0" - xdg-basedir "^4.0.0" - -standard@^17.0.0: - version "17.1.2" - resolved "https://registry.yarnpkg.com/standard/-/standard-17.1.2.tgz#fc7e365e401569fee2a840d2a3862d218ef78092" - integrity sha512-WLm12WoXveKkvnPnPnaFUUHuOB2cUdAsJ4AiGHL2G0UNMrcRAWY2WriQaV8IQ3oRmYr0AWUbLNr94ekYFAHOrA== - dependencies: - eslint "^8.41.0" - eslint-config-standard "17.1.0" - eslint-config-standard-jsx "^11.0.0" - eslint-plugin-import "^2.27.5" - eslint-plugin-n "^15.7.0" - eslint-plugin-promise "^6.1.1" - eslint-plugin-react "^7.36.1" - standard-engine "^15.1.0" - version-guard "^1.1.1" - static-extend@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" @@ -15043,6 +14813,24 @@ stop-iteration-iterator@^1.1.0: es-errors "^1.3.0" internal-slot "^1.1.0" +storybook@10.2.13: + version "10.2.13" + resolved "https://registry.yarnpkg.com/storybook/-/storybook-10.2.13.tgz#b646f8908867d9a0da778c79e3738e9fcae599eb" + integrity sha512-heMfJjOfbHvL+wlCAwFZlSxcakyJ5yQDam6e9k2RRArB1veJhRnsjO6lO1hOXjJYrqxfHA/ldIugbBVlCDqfvQ== + dependencies: + "@storybook/global" "^5.0.0" + "@storybook/icons" "^2.0.1" + "@testing-library/jest-dom" "^6.6.3" + "@testing-library/user-event" "^14.6.1" + "@vitest/expect" "3.2.4" + "@vitest/spy" "3.2.4" + esbuild "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0 || ^0.26.0 || ^0.27.0" + open "^10.2.0" + recast "^0.23.5" + semver "^7.7.3" + use-sync-external-store "^1.5.0" + ws "^8.18.0" + streamx@^2.12.5, streamx@^2.15.0, streamx@^2.25.0: version "2.25.0" resolved "https://registry.yarnpkg.com/streamx/-/streamx-2.25.0.tgz#cc967e99390fda8b918b1eeaf3bc437637c8c7af" @@ -15087,6 +14875,15 @@ string-width@^5.0.1, string-width@^5.1.2: emoji-regex "^9.2.2" strip-ansi "^7.0.1" +string-width@^7.0.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-7.2.0.tgz#b5bb8e2165ce275d4d43476dd2700ad9091db6dc" + integrity sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ== + dependencies: + emoji-regex "^10.3.0" + get-east-asian-width "^1.0.0" + strip-ansi "^7.1.0" + string.prototype.includes@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz#eceef21283640761a81dbe16d6c7171a4edf7d92" @@ -15155,7 +14952,7 @@ string.prototype.trimstart@^1.0.8: define-properties "^1.2.1" es-object-atoms "^1.0.0" -string_decoder@^1.1.1: +string_decoder@^1.1.1, string_decoder@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== @@ -15183,20 +14980,13 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: dependencies: ansi-regex "^5.0.1" -strip-ansi@^7.0.1: +strip-ansi@^7.0.1, strip-ansi@^7.1.0: version "7.2.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.2.0.tgz#d22a269522836a627af8d04b5c3fd2c7fa3e32e3" integrity sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w== dependencies: ansi-regex "^6.2.2" -strip-bom@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" - integrity sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g== - dependencies: - is-utf8 "^0.2.0" - strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" @@ -15266,14 +15056,6 @@ stylehacks@^6.1.1: browserslist "^4.23.0" postcss-selector-parser "^6.0.16" -stylehacks@^7.0.5: - version "7.0.9" - resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-7.0.9.tgz#7efc8fed8155364a7e2760c496d65c992a255cb2" - integrity sha512-dgipCLBa16sZDoQ8BmXdRwV4SmFAxZ4KtbMhV0buow62M/2l6Jq6AkVsKUY/QFr8+VjgzXO5UVHx1f+vvY9DXw== - dependencies: - browserslist "^4.28.2" - postcss-selector-parser "^7.1.1" - stylelint-config-recommended-scss@^14.1.0: version "14.1.0" resolved "https://registry.yarnpkg.com/stylelint-config-recommended-scss/-/stylelint-config-recommended-scss-14.1.0.tgz#1a5855655cddcb5f77c10f38c76567adf2bb9aa3" @@ -15375,14 +15157,6 @@ supports-color@^8.0.0: dependencies: has-flag "^4.0.0" -supports-hyperlinks@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz#3943544347c1ff90b15effb03fc14ae45ec10624" - integrity sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA== - dependencies: - has-flag "^4.0.0" - supports-color "^7.0.0" - supports-hyperlinks@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-3.2.0.tgz#b8e485b179681dea496a1e7abdf8985bd3145461" @@ -15419,19 +15193,6 @@ svgo@^3.0.2, svgo@^3.2.0: picocolors "^1.0.0" sax "^1.5.0" -svgo@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/svgo/-/svgo-4.0.1.tgz#c82dacd04ee9f1d55cd4e0b7f9a214c86670e3ee" - integrity sha512-XDpWUOPC6FEibaLzjfe0ucaV0YrOjYotGJO1WpF0Zd+n6ZGEQUsSugaoLq9QkEZtAfQIxT42UChcssDVPP3+/w== - dependencies: - commander "^11.1.0" - css-select "^5.1.0" - css-tree "^3.0.1" - css-what "^6.1.0" - csso "^5.0.5" - picocolors "^1.1.1" - sax "^1.5.0" - symbol-tree@^3.2.2, symbol-tree@^3.2.4: version "3.2.4" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" @@ -15455,6 +15216,13 @@ table@^6.9.0: string-width "^4.2.3" strip-ansi "^6.0.1" +tannin@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/tannin/-/tannin-1.2.0.tgz#1da6fe65280dca4c3d84efb075b077b1b94362a6" + integrity sha512-U7GgX/RcSeUETbV7gYgoz8PD7Ni4y95pgIP/Z6ayI3CfhSujwKEBlGFTCRN+Aqnuyf4AN2yHL+L8x+TCGjb9uA== + dependencies: + "@tannin/plural-forms" "^1.1.0" + tapable@^2.2.1, tapable@^2.3.0: version "2.3.2" resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.3.2.tgz#86755feabad08d82a26b891db044808c6ad00f15" @@ -15488,15 +15256,7 @@ teex@^1.0.1: dependencies: streamx "^2.12.5" -terminal-link@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994" - integrity sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ== - dependencies: - ansi-escapes "^4.2.1" - supports-hyperlinks "^2.0.0" - -terser-webpack-plugin@^5.3.10, terser-webpack-plugin@^5.3.17, terser-webpack-plugin@^5.3.3: +terser-webpack-plugin@^5.3.10, terser-webpack-plugin@^5.3.17: version "5.4.0" resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.4.0.tgz#95fc4cf4437e587be11ecf37d08636089174d76b" integrity sha512-Bn5vxm48flOIfkdl5CaD2+1CiUVbonWQ3KQPyP7/EuIl9Gbzq/gQFOzaMFUEgVjB1396tcK0SG8XcNJ/2kDH8g== @@ -15535,212 +15295,6 @@ test-exclude@^6.0.0: glob "^7.1.4" minimatch "^3.0.4" -testcafe-browser-tools@2.0.26: - version "2.0.26" - resolved "https://registry.yarnpkg.com/testcafe-browser-tools/-/testcafe-browser-tools-2.0.26.tgz#38b5c0c2cd438895de12ee53cae11c64bd33aab9" - integrity sha512-nTKSJhBzn9BmnOs0xVzXMu8dN2Gu13Ca3x3SJr/zF6ZdKjXO82JlbHu55dt5MFoWjzAQmwlqBkSxPaYicsTgUw== - dependencies: - array-find "^1.0.0" - debug "^4.3.1" - dedent "^0.7.0" - del "^5.1.0" - execa "^3.3.0" - fs-extra "^10.0.0" - graceful-fs "^4.1.11" - linux-platform-info "^0.0.3" - lodash "^4.17.15" - mkdirp "^0.5.1" - mustache "^2.1.2" - nanoid "^3.1.31" - os-family "^1.0.0" - pify "^2.3.0" - pinkie "^2.0.1" - read-file-relative "^1.2.0" - which-promise "^1.0.0" - -testcafe-hammerhead@31.7.7, testcafe-hammerhead@>=19.4.0: - version "31.7.7" - resolved "https://registry.yarnpkg.com/testcafe-hammerhead/-/testcafe-hammerhead-31.7.7.tgz#28d6c5169f6b3618d481b8c3c08c9256c224038b" - integrity sha512-vSI/ak8MTuDENCMLGNyPS+tsf7hLisQfaBDYB6NCY5y/arz26cad86P6+eIrm3ncH3SsnFcm+BmkmNjJxzPyoQ== - dependencies: - "@adobe/css-tools" "^4.3.0-rc.1" - "@electron/asar" "^3.2.3" - acorn-hammerhead "0.6.2" - bowser "1.6.0" - crypto-md5 "^1.0.0" - debug "4.3.1" - esotope-hammerhead "0.6.9" - http-cache-semantics "^4.1.0" - httpntlm "^1.8.10" - iconv-lite "0.5.1" - lodash "^4.17.21" - lru-cache "11.0.2" - match-url-wildcard "0.0.4" - merge-stream "^1.0.1" - mime "~1.4.1" - mustache "^2.1.1" - nanoid "^3.1.12" - os-family "^1.0.0" - parse5 "^7.1.2" - pinkie "2.0.4" - read-file-relative "^1.2.0" - semver "7.5.3" - tough-cookie "4.1.3" - tunnel-agent "0.6.0" - ws "^7.4.6" - -testcafe-legacy-api@5.1.8: - version "5.1.8" - resolved "https://registry.yarnpkg.com/testcafe-legacy-api/-/testcafe-legacy-api-5.1.8.tgz#fc02eaa45293eb69c036c0e7af5a0b9a51640fcb" - integrity sha512-Jp/8xPQ+tjr2iS569Og8fFRaSx/7h/N/t6DVzhWpVNO3D5AtPkGmSjCAABh7tHkUwrKfBI7sLuVaxekiT5PWTA== - dependencies: - async "3.2.3" - dedent "^0.6.0" - highlight-es "^1.0.0" - lodash "^4.14.0" - moment "^2.14.1" - mustache "^2.2.1" - os-family "^1.0.0" - parse5 "^2.1.5" - pify "^2.3.0" - pinkie "^2.0.1" - read-file-relative "^1.2.0" - strip-bom "^2.0.0" - testcafe-hammerhead ">=19.4.0" - -testcafe-reporter-json@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/testcafe-reporter-json/-/testcafe-reporter-json-2.2.0.tgz#bb061e054489abdb62add745dd979896b618ea91" - integrity sha512-wfpNaZgGP2WoqdmnIXOyxcpwSzdH1HvzXSN397lJkXOrQrwhuGUThPDvyzPnZqxZSzXdDUvIPJm55tCMWbfymQ== - -testcafe-reporter-list@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/testcafe-reporter-list/-/testcafe-reporter-list-2.2.0.tgz#57e77d8b7dd0b246454300d229e58b8ccec8ce48" - integrity sha512-+6Q2CC+2B90OYED2Yx6GoBIMUYd5tADNUbOHu3Hgdd3qskzjBdKwpdDt0b7w0w7oYDO1/Uu4HDBTDud3lWpD4Q== - -testcafe-reporter-minimal@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/testcafe-reporter-minimal/-/testcafe-reporter-minimal-2.2.0.tgz#d12624bb6f6b98543ca52512b01002cad23b657d" - integrity sha512-iUSWI+Z+kVUAsGegMmEXKDiMPZHDxq+smo4utWwc3wI3Tk6jT8PbNvsROQAjwkMKDmnpo6To5vtyvzvK+zKGXA== - -testcafe-reporter-spec@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/testcafe-reporter-spec/-/testcafe-reporter-spec-2.2.0.tgz#5c17095da6c680702f34bffb8e3d53bf465125ea" - integrity sha512-4jUN75Y7eaHQfSjiCLBXt/TvJMW76kBaZGC74sq03FJNBLoo8ibkEFzfjDJzNDCRYo+P7FjCx3vxGrzgfQU26w== - -testcafe-reporter-xunit@^2.2.1: - version "2.2.3" - resolved "https://registry.yarnpkg.com/testcafe-reporter-xunit/-/testcafe-reporter-xunit-2.2.3.tgz#3636884e0351867e4b1beacf00545febad939d3f" - integrity sha512-aGyc+MZPsTNwd9SeKJSjFNwEZfILzFnObzOImaDbsf57disTQfEY+9japXWav/Ef5Cv04UEW24bTFl2Q4f8xwg== - -testcafe-selector-generator@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/testcafe-selector-generator/-/testcafe-selector-generator-0.1.0.tgz#852c86f71565e5d9320da625c2260d040cbed786" - integrity sha512-MTw+RigHsEYmFgzUFNErDxui1nTYUk6nm2bmfacQiKPdhJ9AHW/wue4J/l44mhN8x3E8NgOUkHHOI+1TDFXiLQ== - -testcafe@^3.7.0: - version "3.7.4" - resolved "https://registry.yarnpkg.com/testcafe/-/testcafe-3.7.4.tgz#5daaab6a19992ea8eebcc97f7b94d754564a910c" - integrity sha512-RADoEWAfGCQ1q08zr4kRQ+bEOhOiI3hmzF2s5dFv835ndERdE44V14DVqeOWGEFm0o+x6IYHyWhmQp0g9mz4ZQ== - dependencies: - "@babel/core" "^7.23.2" - "@babel/plugin-proposal-decorators" "^7.23.2" - "@babel/plugin-syntax-dynamic-import" "^7.8.3" - "@babel/plugin-syntax-import-meta" "^7.10.4" - "@babel/plugin-transform-async-generator-functions" "^7.25.4" - "@babel/plugin-transform-async-to-generator" "^7.22.5" - "@babel/plugin-transform-class-properties" "^7.25.4" - "@babel/plugin-transform-class-static-block" "^7.24.7" - "@babel/plugin-transform-exponentiation-operator" "^7.22.5" - "@babel/plugin-transform-for-of" "^7.22.15" - "@babel/plugin-transform-object-rest-spread" "^7.24.7" - "@babel/plugin-transform-private-methods" "^7.25.4" - "@babel/plugin-transform-runtime" "7.23.3" - "@babel/preset-env" "^7.23.2" - "@babel/preset-flow" "^7.22.15" - "@babel/preset-react" "^7.22.15" - "@babel/runtime" "^7.23.2" - "@devexpress/bin-v8-flags-filter" "^1.3.0" - "@devexpress/callsite-record" "^4.1.6" - "@types/node" "20.14.5" - address "^2.0.2" - async-exit-hook "^1.1.2" - babel-plugin-module-resolver "5.0.0" - babel-plugin-syntax-trailing-function-commas "^6.22.0" - bowser "^2.8.1" - callsite "^1.0.0" - chai "4.3.4" - chalk "^2.3.0" - chrome-remote-interface "^0.32.2" - coffeescript "^2.3.1" - commander "^8.3.0" - debug "^4.3.1" - dedent "^0.4.0" - del "^3.0.0" - device-specs "^1.0.0" - devtools-protocol "0.0.1109433" - diff "^8.0.3" - elegant-spinner "^1.0.1" - email-validator "^2.0.4" - emittery "^0.4.1" - error-stack-parser "^2.1.4" - execa "^4.0.3" - get-os-info "^1.0.2" - globby "^11.0.4" - graceful-fs "^4.1.11" - graphlib "^2.1.5" - http-status-codes "^2.2.0" - humanize-duration "^3.25.0" - import-lazy "^3.1.0" - indent-string "^1.2.2" - is-ci "^1.0.10" - is-docker "^2.0.0" - is-glob "^2.0.1" - is-podman "^1.0.1" - is-stream "^2.0.0" - json5 "^2.2.2" - lodash "^4.17.21" - log-update-async-hook "^2.0.7" - make-dir "^3.0.0" - mime-db "^1.41.0" - moment "^2.29.4" - moment-duration-format-commonjs "^1.0.0" - mustache "^2.1.2" - nanoid "^3.1.31" - os-family "^1.0.0" - parse5 "^1.5.0" - pify "^2.3.0" - pinkie "^2.0.4" - pngjs "^3.3.1" - pretty-hrtime "^1.0.3" - promisify-event "^1.0.0" - prompts "^2.4.2" - qrcode-terminal "^0.10.0" - read-file-relative "^1.2.0" - replicator "^1.0.5" - resolve-cwd "^1.0.0" - resolve-from "^4.0.0" - sanitize-filename "^1.6.0" - semver "^7.5.3" - set-cookie-parser "^2.5.1" - source-map-support "^0.5.16" - strip-bom "^2.0.0" - testcafe-browser-tools "2.0.26" - testcafe-hammerhead "31.7.7" - testcafe-legacy-api "5.1.8" - testcafe-reporter-json "^2.1.0" - testcafe-reporter-list "^2.2.0" - testcafe-reporter-minimal "^2.2.0" - testcafe-reporter-spec "^2.2.0" - testcafe-reporter-xunit "^2.2.1" - testcafe-selector-generator "^0.1.0" - time-limit-promise "^1.0.2" - tmp "0.2.5" - tree-kill "^1.2.2" - typescript "4.7.4" - unquote "^1.1.1" - url-to-options "^2.0.0" - text-decoder@^1.1.0: version "1.2.7" resolved "https://registry.yarnpkg.com/text-decoder/-/text-decoder-1.2.7.tgz#5d073a9a74b9c0a9d28dfadcab96b604af57d8ba" @@ -15773,10 +15327,15 @@ thunky@^1.0.2: resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== -time-limit-promise@^1.0.2: - version "1.0.4" - resolved "https://registry.yarnpkg.com/time-limit-promise/-/time-limit-promise-1.0.4.tgz#33e928212273c70d52153c28ad2a7e3319b975f9" - integrity sha512-FLHDDsIDducw7MBcRWlFtW2Tm50DoKOSFf0Nzx17qwXj8REXCte0eUkHrJl9QU3Bl9arG3XNYX0PcHpZ9xyuLw== +tiktoken@^1.0.21: + version "1.0.22" + resolved "https://registry.yarnpkg.com/tiktoken/-/tiktoken-1.0.22.tgz#a6c674839228bb88f32dfe646dff47193762f7d3" + integrity sha512-PKvy1rVF1RibfF3JlXBSP0Jrcw2uq3yXdgcEXtKTYn3QJ/cBRBHDnrJ5jHky+MENZ6DIPwNUGWpkVx+7joCpNA== + +tiny-invariant@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.3.tgz#46680b7a873a0d5d10005995eb90a70d74d60127" + integrity sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg== tinyglobby@^0.2.14: version "0.2.16" @@ -15786,6 +15345,21 @@ tinyglobby@^0.2.14: fdir "^6.5.0" picomatch "^4.0.4" +tinyrainbow@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/tinyrainbow/-/tinyrainbow-2.0.0.tgz#9509b2162436315e80e3eee0fcce4474d2444294" + integrity sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw== + +tinyspy@^4.0.3: + version "4.0.4" + resolved "https://registry.yarnpkg.com/tinyspy/-/tinyspy-4.0.4.tgz#d77a002fb53a88aa1429b419c1c92492e0c81f78" + integrity sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q== + +tldts-core@^6.1.86: + version "6.1.86" + resolved "https://registry.yarnpkg.com/tldts-core/-/tldts-core-6.1.86.tgz#a93e6ed9d505cb54c542ce43feb14c73913265d8" + integrity sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA== + tldts-core@^7.0.28: version "7.0.28" resolved "https://registry.yarnpkg.com/tldts-core/-/tldts-core-7.0.28.tgz#28c256edae2ed177b2a8338a51caf81d41580ecf" @@ -15798,6 +15372,13 @@ tldts-icann@^7.0.12: dependencies: tldts-core "^7.0.28" +tldts@^6.1.32: + version "6.1.86" + resolved "https://registry.yarnpkg.com/tldts/-/tldts-6.1.86.tgz#087e0555b31b9725ee48ca7e77edc56115cd82f7" + integrity sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ== + dependencies: + tldts-core "^6.1.86" + tmp-promise@3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/tmp-promise/-/tmp-promise-3.0.3.tgz#60a1a1cc98c988674fcbfd23b6e3367bdeac4ce7" @@ -15805,7 +15386,7 @@ tmp-promise@3.0.3: dependencies: tmp "^0.2.0" -tmp@0.2.5, tmp@^0.2.0: +tmp@^0.2.0: version "0.2.5" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.5.tgz#b06bcd23f0f3c8357b426891726d16015abfd8f8" integrity sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow== @@ -15866,16 +15447,6 @@ totalist@^3.0.0: resolved "https://registry.yarnpkg.com/totalist/-/totalist-3.0.1.tgz#ba3a3d600c915b1a97872348f79c127475f6acf8" integrity sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ== -tough-cookie@4.1.3: - version "4.1.3" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.3.tgz#97b9adb0728b42280aa3d814b6b999b2ff0318bf" - integrity sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw== - dependencies: - psl "^1.1.33" - punycode "^2.1.1" - universalify "^0.2.0" - url-parse "^1.5.3" - tough-cookie@^2.3.3, tough-cookie@^2.3.4, tough-cookie@~2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" @@ -15894,6 +15465,13 @@ tough-cookie@^4.1.2: universalify "^0.2.0" url-parse "^1.5.3" +tough-cookie@^5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-5.1.2.tgz#66d774b4a1d9e12dc75089725af3ac75ec31bed7" + integrity sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A== + dependencies: + tldts "^6.1.32" + tr46@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09" @@ -15908,6 +15486,18 @@ tr46@^3.0.0: dependencies: punycode "^2.1.1" +tr46@^5.1.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-5.1.1.tgz#96ae867cddb8fdb64a49cc3059a8d428bcf238ca" + integrity sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw== + dependencies: + punycode "^2.3.1" + +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + tree-kill@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" @@ -15925,18 +15515,16 @@ trim-repeated@^1.0.0: dependencies: escape-string-regexp "^1.0.2" -truncate-utf8-bytes@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz#405923909592d56f78a5818434b0b78489ca5f2b" - integrity sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ== - dependencies: - utf8-byte-length "^1.0.1" - ts-api-utils@^1.0.1: version "1.4.3" resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.4.3.tgz#bfc2215fe6528fecab2b0fba570a2e8a4263b064" integrity sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw== +ts-dedent@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/ts-dedent/-/ts-dedent-2.2.0.tgz#39e4bd297cd036292ae2394eb3412be63f563bb5" + integrity sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ== + tsconfig-paths@^3.15.0: version "3.15.0" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz#5299ec605e55b1abb23ec939ef15edaf483070d4" @@ -15952,7 +15540,7 @@ tslib@^1.8.1: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.2.0, tslib@^2.4.0, tslib@^2.7.0, tslib@^2.8.0: +tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.2.0, tslib@^2.4.0, tslib@^2.4.1, tslib@^2.7.0, tslib@^2.8.0: version "2.8.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== @@ -15964,7 +15552,7 @@ tsutils@^3.21.0: dependencies: tslib "^1.8.1" -tunnel-agent@0.6.0, tunnel-agent@^0.6.0: +tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w== @@ -15995,11 +15583,6 @@ type-detect@4.0.8: resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== -type-detect@^4.0.0, type-detect@^4.0.5: - version "4.1.0" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.1.0.tgz#deb2453e8f08dcae7ae98c626b13dddb0155906c" - integrity sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw== - type-fest@^0.18.0: version "0.18.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.18.1.tgz#db4bc151a4a2cf4eebf9add5db75508db6cc841f" @@ -16015,11 +15598,6 @@ type-fest@^0.21.3: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== -type-fest@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.3.1.tgz#63d00d204e059474fe5e1b7c011112bbd1dc29e1" - integrity sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ== - type-fest@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" @@ -16122,15 +15700,10 @@ typescript-tuple@^2.2.1: dependencies: typescript-compare "^0.0.2" -typescript@4.7.4: - version "4.7.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.4.tgz#1a88596d1cf47d59507a1bcdfb5b9dfe4d488235" - integrity sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ== - -typescript@^5.6.3: - version "5.9.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.9.3.tgz#5b4f59e15310ab17a216f5d6cf53ee476ede670f" - integrity sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw== +typescript@5.3.3: + version "5.3.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37" + integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw== uc.micro@^1.0.1, uc.micro@^1.0.5: version "1.0.6" @@ -16155,16 +15728,6 @@ unbzip2-stream@^1.4.3: buffer "^5.2.1" through "^2.3.8" -underscore@^1.3.8: - version "1.13.8" - resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.13.8.tgz#a93a21186c049dbf0e847496dba72b7bd8c1e92b" - integrity sha512-DXtD3ZtEQzc7M8m4cXotyHR+FAS18C64asBYY5vqZexfYryNNnDc02W4hKg3rdQuqOYas1jkseX0+nZXjTXnvQ== - -underscore@~1.12.1: - version "1.12.1" - resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.12.1.tgz#7bb8cc9b3d397e201cf8553336d262544ead829e" - integrity sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw== - undici-types@~5.26.4: version "5.26.5" resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" @@ -16236,12 +15799,7 @@ unpipe@~1.0.0: resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== -unquote@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/unquote/-/unquote-1.1.1.tgz#8fded7324ec6e88a0ff8b905e7c098cdc086d544" - integrity sha512-vRCqFv6UhXpWxZPyGDh/F3ZpNv8/qo7w6iufLpQg9aKnQ71qM4B5KiI7Mia9COcjEhrO9LueHpMYjYzsWH3OIg== - -unrs-resolver@^1.7.11: +unrs-resolver@^1.7.11, unrs-resolver@^1.9.2: version "1.11.1" resolved "https://registry.yarnpkg.com/unrs-resolver/-/unrs-resolver-1.11.1.tgz#be9cd8686c99ef53ecb96df2a473c64d304048a9" integrity sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg== @@ -16327,12 +15885,7 @@ url-parse@^1.5.3: querystringify "^2.1.1" requires-port "^1.0.0" -url-to-options@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/url-to-options/-/url-to-options-2.0.0.tgz#416bfe77868b168b8aa7b72d74e7c29a97dca69d" - integrity sha512-mfONnc9dqO0J41wUh/El+plDskrIJRcyLcx6WjEGYW2K11RnjPDAgeoNFCallADaYJfcWIvAlYyZPBw02AbfIQ== - -use-sync-external-store@^1.0.0, use-sync-external-store@^1.4.0: +use-sync-external-store@^1.0.0, use-sync-external-store@^1.4.0, use-sync-external-store@^1.5.0: version "1.6.0" resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz#b174bfa65cb2b526732d9f2ac0a408027876f32d" integrity sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w== @@ -16342,11 +15895,6 @@ use@^3.1.0: resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== -utf8-byte-length@^1.0.1: - version "1.0.5" - resolved "https://registry.yarnpkg.com/utf8-byte-length/-/utf8-byte-length-1.0.5.tgz#f9f63910d15536ee2b2d5dd4665389715eac5c1e" - integrity sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA== - util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" @@ -16421,11 +15969,6 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" -version-guard@^1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/version-guard/-/version-guard-1.1.3.tgz#5a39b9d195f94cb10d469553aa9951e1917da5d2" - integrity sha512-JwPr6erhX53EWH/HCSzfy1tTFrtPXUe927wdM1jqBBeYp1OM+qPHjWbsvv6pIBduqdgxxS+ScfG7S28pzyr2DQ== - w3c-hr-time@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd" @@ -16440,6 +15983,13 @@ w3c-xmlserializer@^4.0.0: dependencies: xml-name-validator "^4.0.0" +w3c-xmlserializer@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz#f925ba26855158594d907313cedd1476c5967f6c" + integrity sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA== + dependencies: + xml-name-validator "^5.0.0" + wait-on@^8.0.1: version "8.0.5" resolved "https://registry.yarnpkg.com/wait-on/-/wait-on-8.0.5.tgz#63169c6979aea15cbfc813d91e4cf2513958632b" @@ -16485,6 +16035,16 @@ wcwidth@^1.0.1: dependencies: defaults "^1.0.3" +web-streams-polyfill@4.0.0-beta.3: + version "4.0.0-beta.3" + resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz#2898486b74f5156095e473efe989dcf185047a38" + integrity sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug== + +web-streams-polyfill@^3.0.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz#2073b91a2fdb1fbfbd401e7de0ac9f8214cecb4b" + integrity sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw== + web-vitals@^4.2.1: version "4.2.4" resolved "https://registry.yarnpkg.com/web-vitals/-/web-vitals-4.2.4.tgz#1d20bc8590a37769bd0902b289550936069184b7" @@ -16495,6 +16055,11 @@ webdriver-bidi-protocol@0.4.1: resolved "https://registry.yarnpkg.com/webdriver-bidi-protocol/-/webdriver-bidi-protocol-0.4.1.tgz#d411e7b8e158408d83bb166b0b4f1054fa3f077e" integrity sha512-ARrjNjtWRRs2w4Tk7nqrf2gBI0QXWuOmMCx2hU+1jUt6d00MjMxURrhxhGbrsoiZKJrhTSTzbIrc554iKI10qw== +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + webidl-conversions@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" @@ -16523,7 +16088,7 @@ webpack-bundle-analyzer@^4.9.1: sirv "^2.0.3" ws "^7.3.1" -webpack-cli@^5.1.0, webpack-cli@^5.1.4: +webpack-cli@^5.1.4: version "5.1.4" resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-5.1.4.tgz#c8e046ba7eaae4911d7e71e2b25b776fcc35759b" integrity sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg== @@ -16598,21 +16163,12 @@ webpack-merge@^5.7.3: flat "^5.0.2" wildcard "^2.0.0" -webpack-merge@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-6.0.1.tgz#50c776868e080574725abc5869bd6e4ef0a16c6a" - integrity sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg== - dependencies: - clone-deep "^4.0.1" - flat "^5.0.2" - wildcard "^2.0.1" - webpack-sources@^3.3.4: version "3.3.4" resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.3.4.tgz#a338b95eb484ecc75fbb196cbe8a2890618b4891" integrity sha512-7tP1PdV4vF+lYPnkMR0jMY5/la2ub5Fc/8VQrrU+lXkiM6C4TjVfGw7iKfyhnTQOsD+6Q/iKw0eFciziRgD58Q== -webpack@^5.73.0, webpack@^5.97.0: +webpack@^5.97.0: version "5.106.1" resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.106.1.tgz#0a3eeb43a50e4f67fbecd206e1e6fc2c89fc2b6f" integrity sha512-EW8af29ak8Oaf4T8k8YsajjrDBDYgnKZ5er6ljWFJsXABfTNowQfvHLftwcepVgdz+IoLSdEAbBiM9DFXoll9w== @@ -16671,6 +16227,13 @@ whatwg-encoding@^2.0.0: dependencies: iconv-lite "0.6.3" +whatwg-encoding@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz#d0f4ef769905d426e1688f3e34381a99b60b76e5" + integrity sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ== + dependencies: + iconv-lite "0.6.3" + whatwg-mimetype@^2.1.0, whatwg-mimetype@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" @@ -16681,6 +16244,11 @@ whatwg-mimetype@^3.0.0: resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz#5fa1a7623867ff1af6ca3dc72ad6b8a4208beba7" integrity sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q== +whatwg-mimetype@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz#bc1bf94a985dc50388d54a9258ac405c3ca2fc0a" + integrity sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg== + whatwg-url@^11.0.0: version "11.0.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-11.0.0.tgz#0a849eebb5faf2119b901bb76fd795c2848d4018" @@ -16689,6 +16257,22 @@ whatwg-url@^11.0.0: tr46 "^3.0.0" webidl-conversions "^7.0.0" +whatwg-url@^14.0.0, whatwg-url@^14.1.1: + version "14.2.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-14.2.0.tgz#4ee02d5d725155dae004f6ae95c73e7ef5d95663" + integrity sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw== + dependencies: + tr46 "^5.1.0" + webidl-conversions "^7.0.0" + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + whatwg-url@^6.4.1: version "6.5.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-6.5.0.tgz#f2df02bff176fd65070df74ad5ccbb5a199965a8" @@ -16752,15 +16336,6 @@ which-collection@^1.0.2: is-weakmap "^2.0.2" is-weakset "^2.0.3" -which-promise@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/which-promise/-/which-promise-1.0.0.tgz#20b721df05b35b706176ffa10b0909aba4603035" - integrity sha512-15ahjtDr3H+RBtTrvBcKhOFhIEiN3RZSCevDPWtBys+QUivZX9cYyNJcyWNIrUMVsgGrEuIThif9jxeEAQFauw== - dependencies: - pify "^2.2.0" - pinkie-promise "^1.0.0" - which "^1.1.2" - which-typed-array@^1.1.16, which-typed-array@^1.1.19: version "1.1.20" resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.20.tgz#3fdb7adfafe0ea69157b1509f3a1cd892bd1d122" @@ -16774,7 +16349,7 @@ which-typed-array@^1.1.16, which-typed-array@^1.1.19: gopd "^1.2.0" has-tostringtag "^1.0.2" -which@^1.1.2, which@^1.2.12, which@^1.2.9, which@^1.3.1: +which@^1.2.12, which@^1.2.9, which@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== @@ -16788,18 +16363,11 @@ which@^2.0.1: dependencies: isexe "^2.0.0" -wildcard@^2.0.0, wildcard@^2.0.1: +wildcard@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.1.tgz#5ab10d02487198954836b6349f74fff961e10f67" integrity sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ== -windows-release@^5.0.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/windows-release/-/windows-release-5.1.1.tgz#7ac7019f9baeaea6c00ec889b11824f46c12ee8d" - integrity sha512-NMD00arvqcq2nwqc5Q6KtrSRHK+fVD31erE5FEMahAw5PmVCgD7MUXodq3pdZSUkqA9Cda2iWx6s1XYwiJWRmw== - dependencies: - execa "^5.1.1" - word-wrap@^1.2.5, word-wrap@~1.2.3: version "1.2.5" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" @@ -16841,6 +16409,15 @@ wrap-ansi@^8.1.0: string-width "^5.0.1" strip-ansi "^7.0.1" +wrap-ansi@^9.0.0: + version "9.0.2" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-9.0.2.tgz#956832dea9494306e6d209eb871643bb873d7c98" + integrity sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww== + dependencies: + ansi-styles "^6.2.1" + string-width "^7.0.0" + strip-ansi "^7.1.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" @@ -16883,7 +16460,7 @@ ws@^5.2.0: dependencies: async-limiter "~1.0.0" -ws@^7.0.0, ws@^7.2.0, ws@^7.3.1, ws@^7.4.6: +ws@^7.0.0, ws@^7.3.1: version "7.5.10" resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9" integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ== @@ -16893,10 +16470,12 @@ ws@^8.11.0, ws@^8.13.0, ws@^8.18.0, ws@^8.19.0: resolved "https://registry.yarnpkg.com/ws/-/ws-8.20.0.tgz#4cd9532358eba60bc863aad1623dfb045a4d4af8" integrity sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA== -xdg-basedir@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13" - integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q== +wsl-utils@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/wsl-utils/-/wsl-utils-0.1.0.tgz#8783d4df671d4d50365be2ee4c71917a0557baab" + integrity sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw== + dependencies: + is-wsl "^3.1.0" xdg-basedir@^5.1.0: version "5.1.0" @@ -16913,6 +16492,11 @@ xml-name-validator@^4.0.0: resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-4.0.0.tgz#79a006e2e63149a8600f15430f0a4725d1524835" integrity sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw== +xml-name-validator@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-5.0.0.tgz#82be9b957f7afdacf961e5980f1bf227c0bf7673" + integrity sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg== + xml2js@0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.6.2.tgz#dd0b630083aa09c161e25a4d0901e2b2a929b499" @@ -17017,7 +16601,7 @@ zod@3.23.8: resolved "https://registry.yarnpkg.com/zod/-/zod-3.23.8.tgz#e37b957b5d52079769fb8097099b592f0ef4067d" integrity sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g== -zod@^3.24.1: +zod@^3.24.1, zod@^3.25.23: version "3.25.76" resolved "https://registry.yarnpkg.com/zod/-/zod-3.25.76.tgz#26841c3f6fd22a6a2760e7ccb719179768471e34" integrity sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ== From 349f89c89a0f2eb1a2053e1040aa8157f8a739eb Mon Sep 17 00:00:00 2001 From: Jake Jackson Date: Thu, 16 Apr 2026 14:02:38 +1000 Subject: [PATCH 2/5] Modernize toolchain and update dependencies --- .claude/CLAUDE.md | 138 +- .env.example | 8 +- .eslintignore | 6 +- .eslintrc.js | 14 +- .gitattributes | 14 +- .github/workflows/coding-standards.yml | 73 +- .github/workflows/deployment.yml | 16 +- .github/workflows/javascript-tests.yml | 37 +- .github/workflows/phpunit.tests.yml | 79 +- .github/workflows/playwright-e2e.yml | 3 + .gitignore | 4 + .nvmrc | 2 +- .wp-env.json | 29 - babel.config.js | 37 +- bin/deploy.sh | 105 -- composer.json | 62 +- composer.lock | 1507 +++++++++++++++-- jest.config.js | 4 + phpcompat.xml.dist | 40 - phpunit.xml.dist | 18 - src/Helper/Helper_Form.php | 2 +- ...Helper_Interface_Extension_Uninstaller.php | 4 +- src/Helper/Helper_Logger.php | 2 +- src/Helper/Log/Logger.php | 14 +- src/Helper/Log/MonoLoggerPsrLog2And3.php | 2 +- .../common/setupLicenseDeactivation.js | 56 +- .../components/FontManager/AddFont.test.js | 4 +- .../FontManager/AddUpdateFontFooter.test.js | 4 +- .../FontManager/FontVariantLabel.test.js | 4 +- .../components/FontManager/UpdateFont.test.js | 2 +- tests/js-unit/setupTests.js | 3 + tests/phpunit/multisite.xml | 21 - .../mu-plugins/error-deprecation-notices.php | 10 +- .../php-scoper/cleanup.sh | 2 + .../php-scoper/config}/monolog.php | 0 .../php-scoper/config}/mpdf.php | 0 .../php-scoper/config}/querypath.php | 0 .../php-scoper/config}/upload.php | 0 .../php-scoper/config}/url-signer.php | 0 .../php-scoper/prefix.sh | 13 +- tools/phpcs/config-php-compatibility.xml | 34 + phpcs.xml.dist => tools/phpcs/config.xml | 15 +- .../phpunit}/Mocks/zapier-mock.php | 0 {tests => tools}/phpunit/bootstrap.php | 8 +- tools/phpunit/config-multisite.xml | 27 + tools/phpunit/config.xml | 23 + .../entries}/all-form-euro-product-entry.json | 0 .../entries}/all-form-fields-entries.json | 0 .../data/entries}/gravityform-1-entries.json | 0 .../non-group-products-form-entries.json | 0 .../data/entries}/repeater-consent-entry.json | 0 .../data/entries}/repeater-empty-entry.json | 0 .../phpunit/data}/fonts/Chewy.ttf | Bin .../phpunit/data}/fonts/DejaVuSans-Bold.ttf | Bin .../phpunit/data}/fonts/DejaVuSans.ttf | Bin .../data}/fonts/DejaVuSansCondensed.ttf | Bin .../data}/fonts/DejaVuSerifCondensed.ttf | Bin .../phpunit/data}/fonts/chewy-LICENSE.txt | 0 .../phpunit/data/forms}/all-form-fields.json | 0 .../forms}/form-settings-sample-input.json | 0 .../phpunit/data/forms}/form-settings.json | 0 .../phpunit/data/forms}/gravityform-1.json | 0 .../phpunit/data/forms}/gravityform-2.json | 0 .../phpunit/data/forms}/latest-posts.json | 0 .../data/forms}/migration_v3_to_v4.json | 0 .../data/forms}/non-group-products-form.json | 0 .../phpunit/data/forms}/number-fields.json | 0 .../data/forms}/repeater-consent-form.json | 0 .../data/forms}/repeater-empty-form.json | 0 .../phpunit/data/forms/standard.json | 0 .../phpunit/data/images/test-media.png | Bin .../phpunit/data/pdf}/options-settings.json | 0 .../phpunit/data/pdf}/shortcode-data.json | 0 .../phpunit/gravityforms-factory.php | 94 +- {tests => tools}/phpunit/wp-tests-config.php | 2 +- tools/potomatic/dictionaries/dictionary.json | 11 + tools/potomatic/translate.sh | 29 + {bin => tools/release}/build.sh | 59 +- {bin => tools/release}/json-payload.sh | 0 tools/wp-env/development.json | 28 + tools/wp-env/integration.json | 28 + webpack-configs/development.js | 12 - webpack-configs/production.js | 27 - webpack.config.js | 10 +- 84 files changed, 1947 insertions(+), 799 deletions(-) delete mode 100644 .wp-env.json delete mode 100755 bin/deploy.sh delete mode 100644 phpcompat.xml.dist delete mode 100644 phpunit.xml.dist delete mode 100644 tests/phpunit/multisite.xml rename bin/vendor-cleanup.sh => tools/php-scoper/cleanup.sh (95%) rename {.php-scoper => tools/php-scoper/config}/monolog.php (100%) rename {.php-scoper => tools/php-scoper/config}/mpdf.php (100%) rename {.php-scoper => tools/php-scoper/config}/querypath.php (100%) rename {.php-scoper => tools/php-scoper/config}/upload.php (100%) rename {.php-scoper => tools/php-scoper/config}/url-signer.php (100%) rename bin/vendor-prefix.sh => tools/php-scoper/prefix.sh (70%) create mode 100644 tools/phpcs/config-php-compatibility.xml rename phpcs.xml.dist => tools/phpcs/config.xml (91%) rename {tests/phpunit/unit-tests => tools/phpunit}/Mocks/zapier-mock.php (100%) rename {tests => tools}/phpunit/bootstrap.php (93%) create mode 100644 tools/phpunit/config-multisite.xml create mode 100644 tools/phpunit/config.xml rename {tests/phpunit/unit-tests/json => tools/phpunit/data/entries}/all-form-euro-product-entry.json (100%) rename {tests/phpunit/unit-tests/json => tools/phpunit/data/entries}/all-form-fields-entries.json (100%) rename {tests/phpunit/unit-tests/json => tools/phpunit/data/entries}/gravityform-1-entries.json (100%) rename {tests/phpunit/unit-tests/json => tools/phpunit/data/entries}/non-group-products-form-entries.json (100%) rename {tests/phpunit/unit-tests/json => tools/phpunit/data/entries}/repeater-consent-entry.json (100%) rename {tests/phpunit/unit-tests/json => tools/phpunit/data/entries}/repeater-empty-entry.json (100%) rename {tests/phpunit/unit-tests => tools/phpunit/data}/fonts/Chewy.ttf (100%) rename {tests/phpunit/unit-tests => tools/phpunit/data}/fonts/DejaVuSans-Bold.ttf (100%) rename {tests/phpunit/unit-tests => tools/phpunit/data}/fonts/DejaVuSans.ttf (100%) rename {tests/phpunit/unit-tests => tools/phpunit/data}/fonts/DejaVuSansCondensed.ttf (100%) rename {tests/phpunit/unit-tests => tools/phpunit/data}/fonts/DejaVuSerifCondensed.ttf (100%) rename {tests/phpunit/unit-tests => tools/phpunit/data}/fonts/chewy-LICENSE.txt (100%) rename {tests/phpunit/unit-tests/json => tools/phpunit/data/forms}/all-form-fields.json (100%) rename {tests/phpunit/unit-tests/json => tools/phpunit/data/forms}/form-settings-sample-input.json (100%) rename {tests/phpunit/unit-tests/json => tools/phpunit/data/forms}/form-settings.json (100%) rename {tests/phpunit/unit-tests/json => tools/phpunit/data/forms}/gravityform-1.json (100%) rename {tests/phpunit/unit-tests/json => tools/phpunit/data/forms}/gravityform-2.json (100%) rename {tests/phpunit/unit-tests/json => tools/phpunit/data/forms}/latest-posts.json (100%) rename {tests/phpunit/unit-tests/json => tools/phpunit/data/forms}/migration_v3_to_v4.json (100%) rename {tests/phpunit/unit-tests/json => tools/phpunit/data/forms}/non-group-products-form.json (100%) rename {tests/phpunit/unit-tests/json => tools/phpunit/data/forms}/number-fields.json (100%) rename {tests/phpunit/unit-tests/json => tools/phpunit/data/forms}/repeater-consent-form.json (100%) rename {tests/phpunit/unit-tests/json => tools/phpunit/data/forms}/repeater-empty-form.json (100%) rename {tests => tools}/phpunit/data/forms/standard.json (100%) rename {tests => tools}/phpunit/data/images/test-media.png (100%) rename {tests/phpunit/unit-tests/json => tools/phpunit/data/pdf}/options-settings.json (100%) rename {tests/phpunit/unit-tests/json => tools/phpunit/data/pdf}/shortcode-data.json (100%) rename {tests => tools}/phpunit/gravityforms-factory.php (86%) rename {tests => tools}/phpunit/wp-tests-config.php (99%) create mode 100644 tools/potomatic/dictionaries/dictionary.json create mode 100644 tools/potomatic/translate.sh rename {bin => tools/release}/build.sh (50%) rename {bin => tools/release}/json-payload.sh (100%) create mode 100644 tools/wp-env/development.json create mode 100644 tools/wp-env/integration.json delete mode 100644 webpack-configs/development.js delete mode 100644 webpack-configs/production.js diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md index 03f54d897..418d6d208 100644 --- a/.claude/CLAUDE.md +++ b/.claude/CLAUDE.md @@ -1,6 +1,89 @@ # CLAUDE.md -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. +## Core Principles + +### Skills-First Workflow + +**EVERY user request follows this sequence:** + +Request → Load Skills → Gather Context → Execute + +Skills contain critical workflows and protocols not in base context. +Loading them first prevents missing key instructions. + +### Context Management Strategy + +**Central AI should conserve context to extend pre-compaction capacity**: + +- Delegate file explorations and low-lift tasks to sub-agents +- Reserve context for coordination, user communication, and strategic decisions +- For straightforward tasks with clear scope: skip heavy orchestration, execute directly + +**Sub-agents should maximize context collection**: + +- Sub-agent context windows are temporary +- After execution, unused capacity = wasted opportunity +- Instruct sub-agents to read all relevant files, load skills, and gather examples + +### Routing Decision + +**Direct Execution**: + +- Simple/bounded task with clear scope +- Single-component changes +- Quick fixes and trivial modifications + +**Sub-Agent Delegation**: + +- Complex/multi-phase implementations +- Tasks requiring specialized domain expertise +- Work that benefits from isolated context + +**Master Orchestrator**: + +- Ambiguous requirements needing research +- Architectural decisions with wide impact +- Multi-day features requiring session management + +### Operational Protocols + +#### Agent Coordination + +**Parallel** (REQUIRED when applicable): + +- Multiple Task tool invocations in single message +- Independent tasks execute simultaneously +- Bash commands run in parallel + +**Sequential** (ENFORCE for dependencies): + +- Database → API → Frontend +- Research → Planning → Implementation +- Implementation → Testing → Security + +#### Quality Self-Checks + +Before finalizing code, verify: + +- All inputs have validation +- Authentication/authorization checks exist +- All external calls have error handling +- Import paths verified against existing codebase examples + +### Coding Best Practices + +**Priority Order** (when trade-offs arise): +Correctness > Maintainability > Performance > Brevity + +#### Task Complexity Assessment + +Before starting, classify: + +- **Trivial** (single file, obvious fix) → execute directly +- **Moderate** (2-5 files, clear scope) → brief planning then execute +- **Complex** (architectural impact, ambiguous requirements) → full research first + +Match effort to complexity. Don't over-engineer trivial tasks or under-plan complex ones. ## Project Overview @@ -11,35 +94,55 @@ Gravity PDF is a WordPress plugin that generates PDF documents from Gravity Form ### JavaScript ```bash -yarn dev # Start webpack dev server with hot reload -yarn build # Production webpack build -yarn test:js # Run Jest unit tests +yarn dev # Start webpack dev server with hot reload +yarn dev:build # One-shot webpack build without watching +yarn build # Production webpack build +yarn test:js # Run Jest unit tests +yarn test:js:watch # Run Jest in watch mode yarn test:js -- tests/js-unit/react/sagas/fontManager.test.js # Run single test file yarn test:js -- --testNamePattern="test name" # Run single test by name -yarn lint:js # ESLint check -yarn lint:css # Sass/CSS lint check -yarn format # Auto-fix JS/CSS/PHP formatting +yarn lint:js # ESLint check +yarn lint:js --fix # Auto-fix ESLint errors (e.g. JSDoc alignment) +yarn lint:css # Sass/CSS lint check +yarn format # Auto-fix JS/CSS/PHP formatting ``` ### PHP ```bash -npm run test:php # Run PHPUnit in Docker (wp-env required) -npm run test:php -- --filter TestClassName # Run single test class -npm run test:php -- --filter testMethod # Run single test method -npm run test:php:multisite # Run multisite PHPUnit tests +yarn test:php # Run PHPUnit in Docker (`yarn wp-env:integration start` required) +yarn test:php -- --filter TestClassName # Run single test class +yarn test:php -- --filter testMethod # Run single test method +yarn test:php:multisite # Run multisite PHPUnit tests composer lint # PHPCS check composer lint:fix # PHPCS auto-fix ``` -PHP tests run inside a Docker container via `wp-env` — you cannot run PHPUnit directly. Start the environment first with `yarn wp-env start`. +PHP tests run inside a Docker container via `wp-env` — you cannot run PHPUnit directly. Start the environment first with `yarn wp-env:integration start`. + +### E2E Tests (Playwright) + +```bash +yarn wp-env:e2e start && yarn wp-env:e2e:permalinks start # Start dedicated E2E environment (port 8702 and 8703) +yarn test:e2e # Run all Playwright tests (headless) +yarn test:e2e:debug # Open Playwright UI for interactive debugging +``` + +E2E tests live in `tests/playwright/` and are split into two projects: +- `core/` — tests against the standard environment (port 8702, plain permalinks) +- `permalinks/` — tests against an environment with pretty permalinks (port 8703, started automatically) + +Artifacts (screenshots, traces) are written to `tmp/artifacts/`. ### Environment ```bash -yarn wp-env start # Start Docker WordPress dev environment -yarn wp-env stop # Stop Docker environment -yarn start # Start environment + hot reload dev server +yarn wp-env start # Start dev environment (port 8700) +yarn wp-env:integration start # Start PHP test environment (port 8701) +yarn wp-env:e2e start # Start E2E test environment (port 8702) +yarn wp-env:e2e:permalinks start # Start E2E test environment with pretty permalinks enabled (port 8703) +yarn wp-env stop # Stop the default dev environment +yarn start # Start dev environment + hot reload dev server ``` ## Architecture @@ -80,11 +183,12 @@ Legacy jQuery code coexists with the React app; they are separate bundles and do - **PHP tests**: `tests/phpunit/` mirrors `src/` structure. Extends `WP_UnitTestCase`. Mock data in `tests/phpunit/unit-tests/Mocks/`. - **JS tests**: `tests/js-unit/` mirrors React source structure. Uses Jest + Enzyme. Coverage threshold: 75%. -- **E2E tests**: `tests/e2e/` uses TestCafe against a running WordPress instance. +- **E2E tests (Playwright)**: `yarn test:e2e` — config at `tools/playwright/config.ts`. Use `yarn test:e2e:playwright` for the interactive UI mode. ### Key Constraints - PRs must target the `development` branch (not `main`) +- Each PR should contain a single commit - Minimum PHP 7.3 compatibility required - jQuery is an external (provided by WordPress); never bundle it -- Run `composer prefix` after adding new Composer dependencies to namespace them via php-scoper \ No newline at end of file +- Run `composer prefix` after adding new Composer dependencies to namespace them via php-scoper diff --git a/.env.example b/.env.example index 190a7563b..ff867a250 100644 --- a/.env.example +++ b/.env.example @@ -1,4 +1,4 @@ -# Add a valid Gravity Forms license key. To run PHPUnit locally you will need an Elite License. -GF_LICENSE=00000000000000000000000000000000 -WP_BASE_URL=http://localhost -WP_ENV_TESTS_PORT=8889 \ No newline at end of file +# Enable AI Translations +# Usage: +# composer run translate +POTOMATIC_OPENAI_API_KEY= diff --git a/.eslintignore b/.eslintignore index 0f1616700..c5e533e40 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,4 +1,4 @@ -.cache -build -node_modules +.cache +build +node_modules vendor \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js index 57657cb06..7cd3cf39c 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -29,7 +29,19 @@ module.exports = { rules: { 'no-alert': 'off', 'jest/no-done-callback': 'off', - camelcase: 'off', + 'camelcase': 'off', 'jsdoc/empty-tags': ['off', { tags: ['package'] }], + '@typescript-eslint/no-unused-vars': 'off' }, + settings: { + jsdoc: { + mode: 'closure', + }, + "import/resolver": { + node: { + extensions: ['.js', '.jsx', '.ts', '.tsx'], + }, + "typescript": {} + } + }, }; diff --git a/.gitattributes b/.gitattributes index 1e6527add..a593e25cd 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,16 +1,4 @@ -/.coveralls.yml export-ignore -/.eslintrc export-ignore -/.gitattributes export-ignore -/.gitignore export-ignore /.github export-ignore -/.docker export-ignore -/jest.config.js export-ignore -/node_modules export-ignore -/phpcs.xml.dist export-ignore -/phpcompat.xml.dist export-ignore -/phpunit.xml.dist export-ignore -/.env.example export-ignore /tests export-ignore -/tmp export-ignore -*.sh eol=lf \ No newline at end of file +*.sh eol=lf diff --git a/.github/workflows/coding-standards.yml b/.github/workflows/coding-standards.yml index bf67e2707..f9e6b76a6 100644 --- a/.github/workflows/coding-standards.yml +++ b/.github/workflows/coding-standards.yml @@ -10,92 +10,59 @@ concurrency: group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.sha }} cancel-in-progress: true - jobs: - # Runs PHP coding standards checks. - # - # Violations are reported inline with annotations. - # - # Performs the following steps: - # - Checks out the repository. - # - Configures caching for Composer. - # - Sets up PHP. - # - Logs debug information. - # - Installs Composer dependencies (from cache if possible). - # - Logs PHP_CodeSniffer debug information. - # - Runs PHPCS on the full codebase with warnings suppressed. - # - Runs PHPCS on the `tests` directory without warnings suppressed. + # Only run this action if a Pull Request contains the label 'run-tests' + check_for_string_in_pull_request_comment: + name: Should workflow run? + runs-on: ubuntu-latest + steps: + - if: ${{ github.event_name == 'pull_request' && ! contains(github.event.pull_request.labels.*.name, 'run-tests') }} + uses: action-pack/cancel@v1 + phpcs: name: PHP coding standards runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: 7.4 tools: composer, cs2pr - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Log debug information run: | php --version composer --version + - name: Add auth details for private composer packages + run: composer config http-basic.composer.gravity.io ${{ secrets.GF_LICENSE }} http://localhost + - name: Install Composer dependencies run: | composer install --prefer-dist --no-suggest --no-progress --no-ansi --no-interaction --no-scripts echo "${PWD}/vendor/bin" >> $GITHUB_PATH - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Log PHPCS debug information - run: composer run lint -- -i + run: composer run phpcs:lint . - name: Run PHP compatibility tests - run: composer run lint -- --standard=phpcompat.xml.dist -q --report=checkstyle | cs2pr - - - name: Run PHPCS on all plugin files - run: composer run lint -- -q -n --report=checkstyle | cs2pr - - # Runs the JavaScript coding standards checks. - # - # Performs the following steps: - # - Checks out the repository. - # - Logs debug information about the runner container. - # - Installs NodeJS - # - Sets up caching for NPM. - # - Logs updated debug information. - # _ Installs NPM dependencies using install-changed to hash the `package.json` file. - # - Run the Run ESLint checks. + run: composer run phpcs:compatibility . + jshint: name: JavaScript coding standards runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Setup Node JS - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version-file: '.nvmrc' - - name: Get yarn cache directory path - id: yarn-cache-dir-path - run: echo "dir=$(yarn config get cacheFolder)" >> $GITHUB_OUTPUT - - - name: Cache node modules - uses: actions/cache@v4 - id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`) - with: - path: ${{ steps.yarn-cache-dir-path.outputs.dir }} - key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} - restore-keys: | - ${{ runner.os }}-yarn- - - name: Log debug information run: | npm --version @@ -106,8 +73,10 @@ jobs: locale -a - name: Install Dependencies - if: steps.cache-nodemodules.outputs.cache-hit != 'true' - run: yarn install + run: yarn install --frozen-lockfile - name: Run ESLint run: yarn lint:js + + - name: Run CSS Lint + run: yarn lint:css diff --git a/.github/workflows/deployment.yml b/.github/workflows/deployment.yml index e00f852fc..1ac820895 100644 --- a/.github/workflows/deployment.yml +++ b/.github/workflows/deployment.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Setup PHP uses: shivammathur/setup-php@v2 @@ -25,22 +25,12 @@ jobs: uses: devops-actions/action-get-tag@v1.0.2 - name: Setup Node JS - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version-file: '.nvmrc' - - name: General debug information - run: | - npm --version - node --version - yarn --version - curl --version - git --version - php --version - composer --version - - name: Gravity PDF Build - run: bash ./bin/build.sh $SOURCE_TAG + run: bash ./tools/release/build.sh $SOURCE_TAG env: SOURCE_TAG: ${{steps.tag.outputs.tag}} diff --git a/.github/workflows/javascript-tests.yml b/.github/workflows/javascript-tests.yml index d5398667c..5499bbd7f 100644 --- a/.github/workflows/javascript-tests.yml +++ b/.github/workflows/javascript-tests.yml @@ -11,55 +11,32 @@ concurrency: cancel-in-progress: true jobs: - # Runs the QUnit tests for WordPress. - # - # Performs the following steps: - # - Cancels all previous workflow runs for pull requests that have not completed. - # - Checks out the repository. - # - Logs debug information about the runner container. - # - Installs NodeJS 12 - # - Sets up caching for NPM. - # - Logs updated debug information. - # _ Installs NPM dependencies using install-changed to hash the `package.json` file. - # - Run the WordPress QUnit tests. test-js: name: JavaScript Test runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Setup Node JS - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version-file: '.nvmrc' - - name: Get yarn cache directory path - id: yarn-cache-dir-path - run: echo "dir=$(yarn config get cacheFolder)" >> $GITHUB_OUTPUT - - - name: Cache node modules - uses: actions/cache@v4 - id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`) - with: - path: ${{ steps.yarn-cache-dir-path.outputs.dir }} - key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} - restore-keys: | - ${{ runner.os }}-yarn- - - name: Log debug information run: | node --version yarn --version - name: Install Dependencies - if: steps.cache-nodemodules.outputs.cache-hit != 'true' - run: yarn install + run: yarn install --frozen-lockfile - name: Run Jest tests run: yarn test:js:coverage - name: Code Coverage Upload - uses: codecov/codecov-action@v4 + uses: codecov/codecov-action@v6 + with: + directory: ./tmp/jest-coverage env: - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} \ No newline at end of file + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/phpunit.tests.yml b/.github/workflows/phpunit.tests.yml index a6ceb6b33..cb8681ac8 100644 --- a/.github/workflows/phpunit.tests.yml +++ b/.github/workflows/phpunit.tests.yml @@ -14,28 +14,14 @@ env: GF_LICENSE: ${{ secrets.GF_LICENSE }} jobs: - # Runs the PHPUnit tests for WordPress. - # - # Performs the following steps: - # - Set environment variables. - # - Sets up the environment variables needed for testing with memcached (if desired). - # - Downloads the built WordPress artifact from the previous job. - # - Unzips the artifact. - # - Installs NodeJS - # - Sets up caching for NPM. - # _ Installs NPM dependencies using install-changed to hash the `package.json` file. - # - Configures caching for Composer. - # _ Installs Composer dependencies (if desired). - # - Logs Docker debug information (about both the Docker installation within the runner). - # - Starts the WordPress Docker container. - # - Starts the memcached server after the Docker network has been created (if desired). - # - Logs WordPress Docker container debug information. - # - Logs debug general information. - # - Logs the running Docker containers. - # - Logs debug information about what's installed within the WordPress Docker containers. - # - Install WordPress within the Docker container. - # - Run the PHPUnit tests. - # - Reports test results to the Distributed Hosting Tests. + # Only run this action if a Pull Request contains the label 'run-tests' + check_for_string_in_pull_request_comment: + name: Should workflow run? + runs-on: ubuntu-latest + steps: + - if: ${{ github.event_name == 'pull_request' && ! contains(github.event.pull_request.labels.*.name, 'run-tests') }} + uses: action-pack/cancel@v1 + test-php: name: ${{ matrix.php }}${{ matrix.multisite && ' multisite' || '' }} on ${{ matrix.os }} runs-on: ${{ matrix.os }} @@ -63,34 +49,18 @@ jobs: echo "PHP_FPM_GID=$(id -g)" >> $GITHUB_ENV - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 - # Docs: https://github.com/shivammathur/setup-php - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: 7.4 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Setup Node JS - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version-file: '.nvmrc' - - name: Get yarn cache directory path - id: yarn-cache-dir-path - run: echo "dir=$(yarn config get cacheFolder)" >> $GITHUB_OUTPUT - - - name: Cache node modules - uses: actions/cache@v4 - id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`) - with: - path: ${{ steps.yarn-cache-dir-path.outputs.dir }} - key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} - restore-keys: | - ${{ runner.os }}-yarn- - - name: Log debug information run: | npm --version @@ -102,54 +72,45 @@ jobs: php -i locale -a + - name: Add auth details for private composer packages + run: composer config http-basic.composer.gravity.io ${{ secrets.GF_LICENSE }} http://localhost + - name: Install Composer dependencies run: | - composer install --prefer-dist --no-suggest --no-progress --no-ansi --no-interaction --no-scripts + composer install --no-progress --no-ansi --no-interaction echo "${PWD}/vendor/bin" >> $GITHUB_PATH - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Install JS Dependencies - if: steps.cache-nodemodules.outputs.cache-hit != 'true' - run: yarn install + run: yarn install --frozen-lockfile - name: Install / Setup Gravity PDF + WordPress if: ${{ ! matrix.report }} - run: | - yarn wp-env start - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: yarn wp-env:integration start --debug - name: Install / Setup Gravity PDF + WordPress if: ${{ matrix.report }} - run: | - PHP_ENABLE_XDEBUG=true yarn wp-env start - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: yarn wp-env:integration start --xdebug=debug - name: Run PHPUnit tests if: ${{ ! matrix.multisite }} run: | yarn test:php --do-not-cache-result --verbose - yarn test:php --group ajax --do-not-cache-result --verbose - name: Run Multisite PHPUnit tests if: ${{ matrix.multisite }} run: | yarn test:php:multisite --verbose - yarn test:php:multisite --group ajax --verbose - name: Generate Code Coverage Report for PHP if: ${{ matrix.report }} run: | - yarn run test:php --do-not-cache-result --verbose --coverage-clover=/var/www/html/wp-content/plugins/gravity-pdf/tmp/coverage/report-xml/php-coverage1.xml - yarn run test:php --group ajax --do-not-cache-result --verbose --coverage-clover=/var/www/html/wp-content/plugins/gravity-pdf/tmp/coverage/report-xml/php-coverage2.xml + yarn test:php --do-not-cache-result --verbose --coverage-clover=/var/www/html/wp-content/plugins/gravity-pdf/tmp/coverage/report-xml/php-coverage1.xml - name: Code Coverage Upload - uses: codecov/codecov-action@v4 + uses: codecov/codecov-action@v6 if: ${{ matrix.report }} env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} with: - files: tmp/coverage/report-xml/php-coverage1.xml + directory: tmp/coverage/report-xml diff --git a/.github/workflows/playwright-e2e.yml b/.github/workflows/playwright-e2e.yml index c2c9215c3..c64e8373e 100644 --- a/.github/workflows/playwright-e2e.yml +++ b/.github/workflows/playwright-e2e.yml @@ -63,6 +63,9 @@ jobs: php -i locale -a + - name: Add auth details for private composer packages + run: composer config http-basic.composer.gravity.io ${{ secrets.GF_LICENSE }} http://localhost + - name: Install Composer dependencies run: | composer install --no-progress --no-ansi --no-interaction diff --git a/.gitignore b/.gitignore index 20e2af315..15aaec899 100644 --- a/.gitignore +++ b/.gitignore @@ -41,6 +41,7 @@ build/assets/* /coverage /screenshots /artifacts +/tests/playwright/artifacts # Others _notes @@ -52,4 +53,7 @@ Thumbs.db # Environment File .env +auth.json .claude/settings.local.json +.claude/worktrees +.claude/plans diff --git a/.nvmrc b/.nvmrc index 2edeafb09..cabf43b5d 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -20 \ No newline at end of file +24 \ No newline at end of file diff --git a/.wp-env.json b/.wp-env.json deleted file mode 100644 index a23dd9ef8..000000000 --- a/.wp-env.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "core": "https://wordpress.org/latest.zip", - "phpVersion": "8.3", - "plugins": [ - "gravityforms/gravityformscli", - "." - ], - "lifecycleScripts": { - "afterStart": "bash bin/install.sh" - }, - "mappings": { - "wp-cli.yml": "./tools/wp-env/wp-cli.yml", - "wp-content/mu-plugins": "./tools/mu-plugins" - }, - "env": { - "tests": { - "plugins": [ - "gravityforms/gravityformscli", - "GravityPDF/gravity-pdf-test-suite", - "." - ], - "config": { - "WP_DEBUG": true, - "WP_DEBUG_DISPLAY": false, - "WP_DEBUG_LOG": "/var/www/html/wp-content/plugins/gravity-pdf/tmp/debug.log" - } - } - } -} \ No newline at end of file diff --git a/babel.config.js b/babel.config.js index cfccf6082..470dcb0b0 100644 --- a/babel.config.js +++ b/babel.config.js @@ -1,35 +1,4 @@ -const { hasArgInCLI } = require( '@wordpress/scripts/utils' ); -const defaultConfig = require( '@wordpress/scripts/config/webpack.config' ); - -const isProduction = defaultConfig.mode === 'production'; -const hasReactFastRefresh = hasArgInCLI( '--hot' ) && ! isProduction; - -module.exports = ( api ) => { - api.cache.using( () => process.env.NODE_ENV === 'production' ); - - const plugins = [ - 'babel-plugin-inline-json-import', - '@babel/plugin-transform-modules-commonjs', - ]; - - if ( hasReactFastRefresh ) { - plugins.push( 'react-refresh/babel' ); - } - - if ( isProduction ) { - plugins.push( - ...[ - [ - 'react-remove-properties', - { properties: [ 'data-test' ] }, - ], - 'transform-react-remove-prop-types', - ] - ); - } - - return { - presets: [ '@wordpress/babel-preset-default' ], - plugins, - }; +module.exports = { + presets: [ '@wordpress/babel-preset-default' ], + plugins: [ 'babel-plugin-inline-json-import' ], }; diff --git a/bin/deploy.sh b/bin/deploy.sh deleted file mode 100755 index 5185e0bcd..000000000 --- a/bin/deploy.sh +++ /dev/null @@ -1,105 +0,0 @@ -#!/usr/bin/env bash - -if [[ -z "$GITHUB_ACTION" ]]; then - echo "Script is only to be run by Github Action" 1>&2 - exit 1 -fi - -if [[ -z "$WP_ORG_PASSWORD" ]]; then - echo "WordPress.org password not set" 1>&2 - exit 1 -fi - -PROJECT_ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )" -PLUGIN_BUILDS_PATH="$PROJECT_ROOT/tmp/package/wporg" - -# Ensure the current build directory exists -if [ ! -d "$PLUGIN_BUILDS_PATH/$SOURCE_TAG" ]; then - echo "Built directory $PLUGIN_BUILDS_PATH/$SOURCE_TAG does not exist" 1>&2 - exit 1 -fi - -# Check if the tag exists for the version we are building -TAG=$(svn ls "https://plugins.svn.wordpress.org/$PLUGIN/tags/$SOURCE_TAG") -error=$? -if [ $error == 0 ]; then - # Tag exists, don't deploy - echo "Tag already exists for version $SOURCE_TAG, aborting deployment" - exit 1 -fi - -# Create Tags -echo "Begin Tag Deployment" -svn --no-auth-cache --non-interactive --username "$WP_ORG_USERNAME" --password "$WP_ORG_PASSWORD" mkdir "https://plugins.svn.wordpress.org/$PLUGIN/tags/$SOURCE_TAG" -m "Create tag $SOURCE_TAG" - -cd "$PLUGIN_BUILDS_PATH" - -# Checkout the SVN tag -svn co -q "https://plugins.svn.wordpress.org/$PLUGIN/tags/$SOURCE_TAG" svn - -# Add new version tag -rsync -r -p $SOURCE_TAG/* svn - -# Add new files to SVN -svn stat svn | grep '^?' | awk '{print $2}' | xargs -I x svn add x@ -# Remove deleted files from SVN -svn stat svn | grep '^!' | awk '{print $2}' | xargs -I x svn rm --force x@ -svn stat svn - -# Commit to SVN -svn ci --no-auth-cache --non-interactive --username "$WP_ORG_USERNAME" --password "$WP_ORG_PASSWORD" svn -m "Deploy version $SOURCE_TAG" - -# Remove SVN temp dir -rm -fR svn - -# Create Trunk -echo "End Tag Deployment" -echo "Begin Trunk Deployment" -svn co -q "http://svn.wp-plugins.org/$PLUGIN/trunk" svn - -# Move out the trunk directory to a temp location -mv svn svn-trunk - -# Copy our new version of the plugin into trunk -rsync -r -p $SOURCE_TAG/* svn - -# Remove the readme.txt file from the plugin, and back in the copied version -cp svn-trunk/readme.txt svn - -# Copy all the .svn folders from the checked out copy of trunk to the new trunk. -# This is necessary as the Travis container runs Subversion 1.6 which has .svn dirs in every sub dir -TARGET="$PLUGIN_BUILDS_PATH/svn" -cd "$PLUGIN_BUILDS_PATH/svn-trunk" - -# Find all .svn dirs in sub dirs -SVN_DIRS=`find . -type d -iname .svn` - -for SVN_DIR in $SVN_DIRS; do - SOURCE_DIR=${SVN_DIR/.} - TARGET_DIR=$TARGET${SOURCE_DIR/.svn} - TARGET_SVN_DIR=$TARGET${SVN_DIR/.} - if [ -d "$TARGET_DIR" ]; then - # Copy the .svn directory to trunk dir - cp -r $SVN_DIR $TARGET_SVN_DIR - fi -done - -# Back to builds dir -cd "$PLUGIN_BUILDS_PATH" - -# Remove checked out dir -rm -fR svn-trunk - -# Add new files to SVN -svn stat svn | grep '^?' | awk '{print $2}' | xargs -I x svn add x@ -# Remove deleted files from SVN -svn stat svn | grep '^!' | awk '{print $2}' | xargs -I x svn rm --force x@ -svn stat svn - -# Commit to SVN -svn ci --no-auth-cache --non-interactive --username "$WP_ORG_USERNAME" --password "$WP_ORG_PASSWORD" svn -m "Deploy trunk for $SOURCE_TAG" - -# Remove SVN temp dir -rm -fR svn - -echo "End Trunk Deployment" diff --git a/composer.json b/composer.json index e6b6ad3f1..e75f1f2b1 100644 --- a/composer.json +++ b/composer.json @@ -3,26 +3,32 @@ "license": "GPL-2.0-or-later", "homepage": "https://gravitypdf.com", "scripts": { - "lint": "@php ./vendor/squizlabs/php_codesniffer/bin/phpcs", - "lint:fix": "@php ./vendor/squizlabs/php_codesniffer/bin/phpcbf", - "lint:compat": "@php ./vendor/squizlabs/php_codesniffer/bin/phpcs --standard=phpcompat.xml.dist", - "prefix": "bash ./bin/vendor-prefix.sh", - "post-install-cmd": "@composer prefix" - }, - "config": { - "preferred-install": "dist", - "autoloader-suffix": "GravityPDFPlugin", - "platform": { - "php": "7.3.0" - }, - "allow-plugins": { - "dealerdirect/phpcodesniffer-composer-installer": true - } + "phpcs:lint": "./vendor/bin/phpcs --standard=./tools/phpcs/config.xml", + "phpcs:fix": "./vendor/bin/phpcbf --standard=./tools/phpcs/config.xml", + "phpcs:compatibility": "./vendor/bin/phpcs --standard=./tools/phpcs/config-php-compatibility.xml", + "release": "bash ./tools/release/build.sh", + "translate": "bash ./tools/potomatic/translate.sh", + "prefix": "bash ./tools/php-scoper/prefix.sh", + "post-install-cmd": [ + "@composer prefix", + "yarn && yarn build" + ], + "post-update-cmd": [ + "@composer prefix" + ] }, "repositories": [ { "type": "vcs", "url": "https://github.com/GravityPDF/url-signer" + }, + + { + "type": "composer", + "url": "https://composer.gravity.io", + "only": [ + "gravity/*" + ] } ], "require": { @@ -39,18 +45,34 @@ "wp-coding-standards/wpcs": "^3.0.0", "phpcompatibility/phpcompatibility-wp": "*", "roave/security-advisories": "dev-master", - "yoast/phpunit-polyfills": "^3.0", + "yoast/phpunit-polyfills": "^4.0", "wp-phpunit/wp-phpunit": "^6.4", - "humbug/php-scoper": "^0.15.0" + "humbug/php-scoper": "^0.15.0", + "gravity/gravityforms": "*", + "gravity/gravityformspolls": "*", + "gravity/gravityformssurvey": "*", + "gravity/gravityformsquiz": "*" + }, + "suggest": { + "roots/wordpress-full": "Install to do step debugging on the WordPress codebase." }, "autoload": { "psr-4": { - "GFPDF\\": "src/", - "Psr\\Http\\Message\\": "vendor/psr/http-message/src", - "Psr\\Log\\": "vendor/psr/log/Psr/Log" + "GFPDF\\": "src/" }, "classmap": [ "vendor_prefixed/" ] + }, + "config": { + "preferred-install": "dist", + "autoloader-suffix": "GravityPDFPlugin", + "platform": { + "php": "7.3.0" + }, + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true, + "composer/installers": false + } } } diff --git a/composer.lock b/composer.lock index 05e91d0c1..9b8d7b5d7 100644 --- a/composer.lock +++ b/composer.lock @@ -4,25 +4,25 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "5c19d9d7fef8e66c105ac41e8aa93b3d", + "content-hash": "a39414df586126fa227d1c6ef031a423", "packages": [ { "name": "gravitypdf/querypath", - "version": "4.1.0", + "version": "4.2.0", "source": { "type": "git", "url": "https://github.com/GravityPDF/querypath.git", - "reference": "32b08b5b5295fa3b84baeb91685c66ca86b1c591" + "reference": "6599a112e2f0759c6a05b364641dfcff7247ab7e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/GravityPDF/querypath/zipball/32b08b5b5295fa3b84baeb91685c66ca86b1c591", - "reference": "32b08b5b5295fa3b84baeb91685c66ca86b1c591", + "url": "https://api.github.com/repos/GravityPDF/querypath/zipball/6599a112e2f0759c6a05b364641dfcff7247ab7e", + "reference": "6599a112e2f0759c6a05b364641dfcff7247ab7e", "shasum": "" }, "require": { "masterminds/html5": "^2.0", - "php": "^7.1 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" + "php": "^7.1 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" }, "replace": { "arthurkushman/query-path": "3.1.4", @@ -48,7 +48,7 @@ "license": [ "MIT" ], - "description": "PHP library for HTML(5)/XML querying (CSS 4 or XPath) and processing (like jQuery) with PHP8.3 support", + "description": "PHP library for HTML(5)/XML querying (CSS 4 or XPath) and processing (like jQuery) with PHP 7.0 to 8.5 support", "homepage": "https://github.com/gravitypdf/querypath", "keywords": [ "css", @@ -68,25 +68,25 @@ "type": "paypal" } ], - "time": "2025-02-04T05:00:04+00:00" + "time": "2026-03-17T06:14:13+00:00" }, { "name": "gravitypdf/upload", - "version": "3.0.1", + "version": "3.1.0", "source": { "type": "git", "url": "https://github.com/GravityPDF/Upload.git", - "reference": "88fe102a492843fa2ca45a753e263828cc7854e1" + "reference": "7fff246f86d9b8f6277a0561ce28d2c229633e49" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/GravityPDF/Upload/zipball/88fe102a492843fa2ca45a753e263828cc7854e1", - "reference": "88fe102a492843fa2ca45a753e263828cc7854e1", + "url": "https://api.github.com/repos/GravityPDF/Upload/zipball/7fff246f86d9b8f6277a0561ce28d2c229633e49", + "reference": "7fff246f86d9b8f6277a0561ce28d2c229633e49", "shasum": "" }, "require": { "ext-fileinfo": "*", - "php": "^7.3 || ~8.0.0 || ~8.1.0 || ~8.2.0" + "php": "^7.3 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" }, "replace": { "codeguy/upload": "1.3.2" @@ -129,7 +129,7 @@ "issues": "https://github.com/gravitypdf/upload/issues", "source": "https://github.com/gravitypdf/upload" }, - "time": "2022-12-11T23:50:26+00:00" + "time": "2026-03-11T04:07:56+00:00" }, { "name": "league/uri", @@ -456,16 +456,16 @@ }, { "name": "monolog/monolog", - "version": "2.9.3", + "version": "2.11.0", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "a30bfe2e142720dfa990d0a7e573997f5d884215" + "reference": "37308608e599f34a1a4845b16440047ec98a172a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/a30bfe2e142720dfa990d0a7e573997f5d884215", - "reference": "a30bfe2e142720dfa990d0a7e573997f5d884215", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/37308608e599f34a1a4845b16440047ec98a172a", + "reference": "37308608e599f34a1a4845b16440047ec98a172a", "shasum": "" }, "require": { @@ -542,7 +542,7 @@ ], "support": { "issues": "https://github.com/Seldaek/monolog/issues", - "source": "https://github.com/Seldaek/monolog/tree/2.9.3" + "source": "https://github.com/Seldaek/monolog/tree/2.11.0" }, "funding": [ { @@ -554,20 +554,20 @@ "type": "tidelift" } ], - "time": "2024-04-12T20:52:51+00:00" + "time": "2026-01-01T13:05:00+00:00" }, { "name": "mpdf/mpdf", - "version": "v8.2.7", + "version": "v8.3.1", "source": { "type": "git", "url": "https://github.com/mpdf/mpdf.git", - "reference": "b59670a09498689c33ce639bac8f5ba26721dab3" + "reference": "2a454ec334109911fdb323a284c19dbf3f049810" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mpdf/mpdf/zipball/b59670a09498689c33ce639bac8f5ba26721dab3", - "reference": "b59670a09498689c33ce639bac8f5ba26721dab3", + "url": "https://api.github.com/repos/mpdf/mpdf/zipball/2a454ec334109911fdb323a284c19dbf3f049810", + "reference": "2a454ec334109911fdb323a284c19dbf3f049810", "shasum": "" }, "require": { @@ -591,6 +591,7 @@ }, "suggest": { "ext-bcmath": "Needed for generation of some types of barcodes", + "ext-imagick": "Needed if developing the Mpdf library", "ext-xml": "Needed mainly for SVG manipulation", "ext-zlib": "Needed for compression of embedded resources, such as fonts" }, @@ -635,7 +636,7 @@ "type": "custom" } ], - "time": "2025-12-01T10:18:02+00:00" + "time": "2026-03-11T10:58:44+00:00" }, { "name": "mpdf/psr-http-message-shim", @@ -1012,27 +1013,27 @@ }, { "name": "setasign/fpdi", - "version": "v2.6.4", + "version": "v2.6.6", "source": { "type": "git", "url": "https://github.com/Setasign/FPDI.git", - "reference": "4b53852fde2734ec6a07e458a085db627c60eada" + "reference": "de0cf35911be3e9ea63b48e0f307883b1c7c48ac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Setasign/FPDI/zipball/4b53852fde2734ec6a07e458a085db627c60eada", - "reference": "4b53852fde2734ec6a07e458a085db627c60eada", + "url": "https://api.github.com/repos/Setasign/FPDI/zipball/de0cf35911be3e9ea63b48e0f307883b1c7c48ac", + "reference": "de0cf35911be3e9ea63b48e0f307883b1c7c48ac", "shasum": "" }, "require": { "ext-zlib": "*", - "php": "^7.1 || ^8.0" + "php": ">=7.2 <=8.5.99999" }, "conflict": { "setasign/tfpdf": "<1.31" }, "require-dev": { - "phpunit/phpunit": "^7", + "phpunit/phpunit": "^8.5.52", "setasign/fpdf": "~1.8.6", "setasign/tfpdf": "~1.33", "squizlabs/php_codesniffer": "^3.5", @@ -1072,7 +1073,7 @@ ], "support": { "issues": "https://github.com/Setasign/FPDI/issues", - "source": "https://github.com/Setasign/FPDI/tree/v2.6.4" + "source": "https://github.com/Setasign/FPDI/tree/v2.6.6" }, "funding": [ { @@ -1080,7 +1081,7 @@ "type": "tidelift" } ], - "time": "2025-08-05T09:57:14+00:00" + "time": "2026-03-13T08:38:20+00:00" }, { "name": "spatie/url-signer", @@ -1147,6 +1148,225 @@ } ], "packages-dev": [ + { + "name": "composer/installers", + "version": "v2.3.0", + "source": { + "type": "git", + "url": "https://github.com/composer/installers.git", + "reference": "12fb2dfe5e16183de69e784a7b84046c43d97e8e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/installers/zipball/12fb2dfe5e16183de69e784a7b84046c43d97e8e", + "reference": "12fb2dfe5e16183de69e784a7b84046c43d97e8e", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0 || ^2.0", + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "composer/composer": "^1.10.27 || ^2.7", + "composer/semver": "^1.7.2 || ^3.4.0", + "phpstan/phpstan": "^1.11", + "phpstan/phpstan-phpunit": "^1", + "symfony/phpunit-bridge": "^7.1.1", + "symfony/process": "^5 || ^6 || ^7" + }, + "type": "composer-plugin", + "extra": { + "class": "Composer\\Installers\\Plugin", + "branch-alias": { + "dev-main": "2.x-dev" + }, + "plugin-modifies-install-path": true + }, + "autoload": { + "psr-4": { + "Composer\\Installers\\": "src/Composer/Installers" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kyle Robinson Young", + "email": "kyle@dontkry.com", + "homepage": "https://github.com/shama" + } + ], + "description": "A multi-framework Composer library installer", + "homepage": "https://composer.github.io/installers/", + "keywords": [ + "Dolibarr", + "Eliasis", + "Hurad", + "ImageCMS", + "Kanboard", + "Lan Management System", + "MODX Evo", + "MantisBT", + "Mautic", + "Maya", + "OXID", + "Plentymarkets", + "Porto", + "RadPHP", + "SMF", + "Starbug", + "Thelia", + "Whmcs", + "WolfCMS", + "agl", + "annotatecms", + "attogram", + "bitrix", + "cakephp", + "chef", + "cockpit", + "codeigniter", + "concrete5", + "concreteCMS", + "croogo", + "dokuwiki", + "drupal", + "eZ Platform", + "elgg", + "expressionengine", + "fuelphp", + "grav", + "installer", + "itop", + "known", + "kohana", + "laravel", + "lavalite", + "lithium", + "magento", + "majima", + "mako", + "matomo", + "mediawiki", + "miaoxing", + "modulework", + "modx", + "moodle", + "osclass", + "pantheon", + "phpbb", + "piwik", + "ppi", + "processwire", + "puppet", + "pxcms", + "reindex", + "roundcube", + "shopware", + "silverstripe", + "sydes", + "sylius", + "tastyigniter", + "wordpress", + "yawik", + "zend", + "zikula" + ], + "support": { + "issues": "https://github.com/composer/installers/issues", + "source": "https://github.com/composer/installers/tree/v2.3.0" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2024-06-24T20:46:46+00:00" + }, + { + "name": "composer/package-versions-deprecated", + "version": "1.11.99.5", + "source": { + "type": "git", + "url": "https://github.com/composer/package-versions-deprecated.git", + "reference": "b4f54f74ef3453349c24a845d22392cd31e65f1d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/package-versions-deprecated/zipball/b4f54f74ef3453349c24a845d22392cd31e65f1d", + "reference": "b4f54f74ef3453349c24a845d22392cd31e65f1d", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.1.0 || ^2.0", + "php": "^7 || ^8" + }, + "replace": { + "ocramius/package-versions": "1.11.99" + }, + "require-dev": { + "composer/composer": "^1.9.3 || ^2.0@dev", + "ext-zip": "^1.13", + "phpunit/phpunit": "^6.5 || ^7" + }, + "type": "composer-plugin", + "extra": { + "class": "PackageVersions\\Installer", + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "PackageVersions\\": "src/PackageVersions" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be" + } + ], + "description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)", + "support": { + "issues": "https://github.com/composer/package-versions-deprecated/issues", + "source": "https://github.com/composer/package-versions-deprecated/tree/1.11.99.5" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2022-01-17T14:14:24+00:00" + }, { "name": "dealerdirect/phpcodesniffer-composer-installer", "version": "v1.2.0", @@ -1313,6 +1533,183 @@ ], "time": "2022-12-30T00:15:36+00:00" }, + { + "name": "gravity/gravityforms", + "version": "2.9.31", + "dist": { + "type": "zip", + "url": "https://composer.gravity.io/downloads/?plugin=gravityforms&version=2.9.31" + }, + "require": { + "composer/installers": "^1.0 || ^2.0" + }, + "type": "wordpress-plugin" + }, + { + "name": "gravity/gravityformspolls", + "version": "4.4.0", + "dist": { + "type": "zip", + "url": "https://composer.gravity.io/downloads/?plugin=gravityformspolls&version=4.4.0" + }, + "require": { + "composer/installers": "^1.0 || ^2.0" + }, + "type": "wordpress-plugin" + }, + { + "name": "gravity/gravityformsquiz", + "version": "4.3.0", + "dist": { + "type": "zip", + "url": "https://composer.gravity.io/downloads/?plugin=gravityformsquiz&version=4.3.0" + }, + "require": { + "composer/installers": "^1.0 || ^2.0" + }, + "type": "wordpress-plugin" + }, + { + "name": "gravity/gravityformssurvey", + "version": "4.2.1", + "dist": { + "type": "zip", + "url": "https://composer.gravity.io/downloads/?plugin=gravityformssurvey&version=4.2.1" + }, + "require": { + "composer/installers": "^1.0 || ^2.0" + }, + "type": "wordpress-plugin" + }, + { + "name": "humbug/php-scoper", + "version": "0.15.0", + "source": { + "type": "git", + "url": "https://github.com/humbug/php-scoper.git", + "reference": "98c92f2ec5e12756d59ce04dfad34f9fce6c19c3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/humbug/php-scoper/zipball/98c92f2ec5e12756d59ce04dfad34f9fce6c19c3", + "reference": "98c92f2ec5e12756d59ce04dfad34f9fce6c19c3", + "shasum": "" + }, + "require": { + "composer/package-versions-deprecated": "^1.8", + "jetbrains/phpstorm-stubs": "^2020.2", + "nikic/php-parser": "^4.0", + "php": "^7.3 || ^8.0", + "symfony/console": "^3.2 || ^4.0", + "symfony/filesystem": "^3.2 || ^4.0", + "symfony/finder": "^3.2 || ^4.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.1", + "humbug/box": "^3.11", + "phpspec/prophecy-phpunit": "^2.0", + "phpunit/phpunit": "^9.0" + }, + "bin": [ + "bin/php-scoper" + ], + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": false + }, + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "files": [ + "src/functions.php", + "src/json.php" + ], + "psr-4": { + "Humbug\\PhpScoper\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + }, + { + "name": "Théo Fidry", + "email": "theo.fidry@gmail.com" + }, + { + "name": "Pádraic Brady", + "email": "padraic.brady@gmail.com" + } + ], + "description": "Prefixes all PHP namespaces in a file or directory.", + "support": { + "issues": "https://github.com/humbug/php-scoper/issues", + "source": "https://github.com/humbug/php-scoper/tree/0.15.0" + }, + "funding": [ + { + "url": "https://github.com/theofidry", + "type": "github" + } + ], + "time": "2021-05-10T20:50:20+00:00" + }, + { + "name": "jetbrains/phpstorm-stubs", + "version": "v2020.3", + "source": { + "type": "git", + "url": "https://github.com/JetBrains/phpstorm-stubs.git", + "reference": "daf8849db40acded37b13231a291c7536922955b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/JetBrains/phpstorm-stubs/zipball/daf8849db40acded37b13231a291c7536922955b", + "reference": "daf8849db40acded37b13231a291c7536922955b", + "shasum": "" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.16", + "nikic/php-parser": "dev-master", + "php": "^8.0", + "phpdocumentor/reflection-docblock": "dev-master", + "phpunit/phpunit": "^9" + }, + "type": "library", + "autoload": { + "files": [ + "PhpStormStubsMap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "description": "PHP runtime & extensions header files for PhpStorm", + "homepage": "https://www.jetbrains.com/phpstorm", + "keywords": [ + "autocomplete", + "code", + "inference", + "inspection", + "jetbrains", + "phpstorm", + "stubs", + "type" + ], + "support": { + "source": "https://github.com/JetBrains/phpstorm-stubs/tree/v2020.3" + }, + "time": "2020-11-24T13:58:53+00:00" + }, { "name": "nikic/php-parser", "version": "v4.19.5", @@ -2191,16 +2588,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.6.31", + "version": "9.6.34", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "945d0b7f346a084ce5549e95289962972c4272e5" + "reference": "b36f02317466907a230d3aa1d34467041271ef4a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/945d0b7f346a084ce5549e95289962972c4272e5", - "reference": "945d0b7f346a084ce5549e95289962972c4272e5", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/b36f02317466907a230d3aa1d34467041271ef4a", + "reference": "b36f02317466907a230d3aa1d34467041271ef4a", "shasum": "" }, "require": { @@ -2222,7 +2619,7 @@ "phpunit/php-timer": "^5.0.3", "sebastian/cli-parser": "^1.0.2", "sebastian/code-unit": "^1.0.8", - "sebastian/comparator": "^4.0.9", + "sebastian/comparator": "^4.0.10", "sebastian/diff": "^4.0.6", "sebastian/environment": "^5.1.5", "sebastian/exporter": "^4.0.8", @@ -2274,7 +2671,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.31" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.34" }, "funding": [ { @@ -2298,7 +2695,55 @@ "type": "tidelift" } ], - "time": "2025-12-06T07:45:52+00:00" + "time": "2026-01-27T05:45:00+00:00" + }, + { + "name": "psr/container", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/8622567409010282b7aeebe4bb841fe98b58dcaf", + "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/1.1.1" + }, + "time": "2021-03-05T17:36:06+00:00" }, { "name": "roave/security-advisories", @@ -2306,18 +2751,18 @@ "source": { "type": "git", "url": "https://github.com/Roave/SecurityAdvisories.git", - "reference": "e63317470a1b96346be224a68f9e64567e1001c3" + "reference": "cb0cd5e07a530b16b21f52bbfc0c6f142d00d1ca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/e63317470a1b96346be224a68f9e64567e1001c3", - "reference": "e63317470a1b96346be224a68f9e64567e1001c3", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/cb0cd5e07a530b16b21f52bbfc0c6f142d00d1ca", + "reference": "cb0cd5e07a530b16b21f52bbfc0c6f142d00d1ca", "shasum": "" }, "conflict": { "3f/pygmentize": "<1.2", "adaptcms/adaptcms": "<=1.3", - "admidio/admidio": "<=4.3.16", + "admidio/admidio": "<5.0.8", "adodb/adodb-php": "<=5.22.9", "aheinze/cockpit": "<2.2", "aimeos/ai-admin-graphql": ">=2022.04.1,<2022.10.10|>=2023.04.1,<2023.10.6|>=2024.04.1,<2024.07.2", @@ -2326,12 +2771,14 @@ "aimeos/ai-cms-grapesjs": ">=2021.04.1,<2021.10.8|>=2022.04.1,<2022.10.9|>=2023.04.1,<2023.10.15|>=2024.04.1,<2024.10.8|>=2025.04.1,<2025.10.2", "aimeos/ai-controller-frontend": "<2020.10.15|>=2021.04.1,<2021.10.8|>=2022.04.1,<2022.10.8|>=2023.04.1,<2023.10.9|==2024.04.1", "aimeos/aimeos-core": ">=2022.04.1,<2022.10.17|>=2023.04.1,<2023.10.17|>=2024.04.1,<2024.04.7", + "aimeos/aimeos-laravel": "==2021.10", "aimeos/aimeos-typo3": "<19.10.12|>=20,<20.10.5", "airesvsg/acf-to-rest-api": "<=3.1", "akaunting/akaunting": "<2.1.13", "akeneo/pim-community-dev": "<5.0.119|>=6,<6.0.53", - "alextselegidis/easyappointments": "<1.5.2.0-beta1", + "alextselegidis/easyappointments": "<=1.5.2", "alexusmai/laravel-file-manager": "<=3.3.1", + "algolia/algoliasearch-magento-2": "<=3.16.1|>=3.17.0.0-beta1,<=3.17.1", "alt-design/alt-redirect": "<1.6.4", "altcha-org/altcha": "<1.3.1", "alterphp/easyadmin-extension-bundle": ">=1.2,<1.2.11|>=1.3,<1.3.1", @@ -2340,6 +2787,7 @@ "amphp/artax": "<1.0.6|>=2,<2.0.6", "amphp/http": "<=1.7.2|>=2,<=2.1", "amphp/http-client": ">=4,<4.4", + "amphp/http-server": ">=2.0.0.0-RC1-dev,<2.1.10|>=3.0.0.0-beta1,<3.4.4", "anchorcms/anchor-cms": "<=0.12.7", "andreapollastri/cipi": "<=3.1.15", "andrewhaine/silverstripe-form-capture": ">=0.2,<=0.2.3|>=1,<1.0.2|>=2,<2.2.5", @@ -2356,27 +2804,30 @@ "athlon1600/php-proxy": "<=5.1", "athlon1600/php-proxy-app": "<=3", "athlon1600/youtube-downloader": "<=4", + "aureuserp/aureuserp": "<1.3.0.0-beta1", "austintoddj/canvas": "<=3.4.2", - "auth0/auth0-php": ">=3.3,<8.18", - "auth0/login": "<7.20", - "auth0/symfony": "<=5.5", - "auth0/wordpress": "<=5.4", + "auth0/auth0-php": ">=3.3,<=8.18", + "auth0/login": "<=7.20", + "auth0/symfony": "<=5.7", + "auth0/wordpress": "<=5.5", "automad/automad": "<2.0.0.0-alpha5", "automattic/jetpack": "<9.8", "awesome-support/awesome-support": "<=6.0.7", - "aws/aws-sdk-php": "<3.368", - "azuracast/azuracast": "<=0.23.1", + "aws/aws-sdk-php": "<=3.371.3", + "ayacoo/redirect-tab": "<2.1.2|>=3,<3.1.7|>=4,<4.0.5", + "azuracast/azuracast": "<=0.23.3", "b13/seo_basics": "<0.8.2", "backdrop/backdrop": "<=1.32", "backpack/crud": "<3.4.9", - "bacula-web/bacula-web": "<8.0.0.0-RC2-dev", - "badaso/core": "<2.7", - "bagisto/bagisto": "<2.1", + "backpack/filemanager": "<2.0.2|>=3,<3.0.9", + "bacula-web/bacula-web": "<9.7.1", + "badaso/core": "<=2.9.11", + "bagisto/bagisto": "<2.3.10", "barrelstrength/sprout-base-email": "<1.2.7", "barrelstrength/sprout-forms": "<3.9", "barryvdh/laravel-translation-manager": "<0.6.8", "barzahlen/barzahlen-php": "<2.0.1", - "baserproject/basercms": "<=5.1.1", + "baserproject/basercms": "<=5.2.2", "bassjobsen/bootstrap-3-typeahead": ">4.0.2", "bbpress/bbpress": "<2.6.5", "bcit-ci/codeigniter": "<3.1.3", @@ -2404,7 +2855,7 @@ "bytefury/crater": "<6.0.2", "cachethq/cachet": "<2.5.1", "cadmium-org/cadmium-cms": "<=0.4.9", - "cakephp/cakephp": "<3.10.3|>=4,<4.0.10|>=4.1,<4.1.4|>=4.2,<4.2.12|>=4.3,<4.3.11|>=4.4,<4.4.10", + "cakephp/cakephp": "<3.10.3|>=4,<4.0.10|>=4.1,<4.1.4|>=4.2,<4.2.12|>=4.3,<4.3.11|>=4.4,<4.4.10|>=5.2.10,<5.2.12|==5.3", "cakephp/database": ">=4.2,<4.2.12|>=4.3,<4.3.11|>=4.4,<4.4.10", "cardgate/magento2": "<2.0.33", "cardgate/woocommerce": "<=3.1.15", @@ -2415,15 +2866,17 @@ "causal/oidc": "<4", "cecil/cecil": "<7.47.1", "centreon/centreon": "<22.10.15", + "cesargb/laravel-magiclink": ">=2,<2.25.1", "cesnet/simplesamlphp-module-proxystatistics": "<3.1", "chriskacerguis/codeigniter-restserver": "<=2.7.1", "chrome-php/chrome": "<1.14", + "ci4-cms-erp/ci4ms": "<=0.31.3", "civicrm/civicrm-core": ">=4.2,<4.2.9|>=4.3,<4.3.3", "ckeditor/ckeditor": "<4.25", "clickstorm/cs-seo": ">=6,<6.8|>=7,<7.5|>=8,<8.4|>=9,<9.3", "co-stack/fal_sftp": "<0.2.6", - "cockpit-hq/cockpit": "<2.11.4", - "code16/sharp": "<9.11.1", + "cockpit-hq/cockpit": "<2.13.5", + "code16/sharp": "<9.20", "codeception/codeception": "<3.1.3|>=4,<4.1.22", "codeigniter/framework": "<3.1.10", "codeigniter4/framework": "<4.6.2", @@ -2434,7 +2887,7 @@ "commerceteam/commerce": ">=0.9.6,<0.9.9", "components/jquery": ">=1.0.3,<3.5", "composer/composer": "<1.10.27|>=2,<2.2.26|>=2.3,<2.9.3", - "concrete5/concrete5": "<9.4.3", + "concrete5/concrete5": "<9.4.8", "concrete5/core": "<8.5.8|>=9,<9.1", "contao-components/mediaelement": ">=2.14.2,<2.21.1", "contao/comments-bundle": ">=2,<4.13.40|>=5.0.0.0-RC1-dev,<5.3.4", @@ -2443,10 +2896,20 @@ "contao/core-bundle": "<4.13.57|>=5,<5.3.42|>=5.4,<5.6.5", "contao/listing-bundle": ">=3,<=3.5.30|>=4,<4.4.8", "contao/managed-edition": "<=1.5", + "coreshop/core-shop": "<4.1.9", "corveda/phpsandbox": "<1.3.5", "cosenary/instagram": "<=2.3", - "craftcms/cms": "<4.6.2|>=5,<=5.2.2", - "croogo/croogo": "<4", + "couleurcitron/tarteaucitron-wp": "<0.3", + "cpsit/typo3-mailqueue": "<0.4.5|>=0.5,<0.5.2", + "craftcms/aws-s3": ">=2.0.2,<=2.2.4", + "craftcms/azure-blob": ">=2.0.0.0-beta1,<=2.1", + "craftcms/cms": "<=4.17.7|>=5,<=5.9.13", + "craftcms/commerce": ">=4,<4.11|>=5,<5.6", + "craftcms/composer": ">=4.0.0.0-RC1-dev,<=4.10|>=5.0.0.0-RC1-dev,<=5.5.1", + "craftcms/craft": ">=3.5,<=4.16.17|>=5.0.0.0-RC1-dev,<=5.8.21", + "craftcms/google-cloud": ">=2.0.0.0-beta1,<=2.2", + "craftcms/webhooks": ">=3,<3.2", + "croogo/croogo": "<=4.0.7", "cuyz/valinor": "<0.12", "czim/file-handling": "<1.5|>=2,<2.3", "czproject/git-php": "<4.0.3", @@ -2463,10 +2926,11 @@ "derhansen/sf_event_mgt": "<4.3.1|>=5,<5.1.1|>=7,<7.4", "desperado/xml-bundle": "<=0.1.7", "dev-lancer/minecraft-motd-parser": "<=1.0.5", - "devcode-it/openstamanager": "<=2.9.4", + "devcode-it/openstamanager": "<=2.10.1", "devgroup/dotplant": "<2020.09.14-dev", "digimix/wp-svg-upload": "<=1", "directmailteam/direct-mail": "<6.0.3|>=7,<7.0.3|>=8,<9.5.2", + "directorytree/imapengine": "<1.22.3", "dl/yag": "<3.0.1", "dmk/webkitpdf": "<1.1.4", "dnadesign/silverstripe-elemental": "<5.3.12", @@ -2479,9 +2943,10 @@ "doctrine/mongodb-odm": "<1.0.2", "doctrine/mongodb-odm-bundle": "<3.0.1", "doctrine/orm": ">=1,<1.2.4|>=2,<2.4.8|>=2.5,<2.5.1|>=2.8.3,<2.8.4", - "dolibarr/dolibarr": "<21.0.3", + "dolibarr/dolibarr": "<=22.0.4", "dompdf/dompdf": "<2.0.4", "doublethreedigital/guest-entries": "<3.1.2", + "dreamfactory/df-core": "<1.0.4", "drupal-pattern-lab/unified-twig-extensions": "<=0.1", "drupal/access_code": "<2.0.5", "drupal/acquia_dam": "<1.1.5", @@ -2493,7 +2958,7 @@ "drupal/commerce_alphabank_redirect": "<1.0.3", "drupal/commerce_eurobank_redirect": "<2.1.1", "drupal/config_split": "<1.10|>=2,<2.0.2", - "drupal/core": ">=6,<6.38|>=7,<7.102|>=8,<10.4.9|>=10.5,<10.5.6|>=11,<11.1.9|>=11.2,<11.2.8", + "drupal/core": ">=6,<6.38|>=7,<7.103|>=8,<10.4.9|>=10.5,<10.5.6|>=11,<11.1.9|>=11.2,<11.2.8", "drupal/core-recommended": ">=7,<7.102|>=8,<10.2.11|>=10.3,<10.3.9|>=11,<11.0.8", "drupal/currency": "<3.5", "drupal/drupal": ">=5,<5.11|>=6,<6.38|>=7,<7.102|>=8,<10.2.11|>=10.3,<10.3.9|>=11,<11.0.8", @@ -2520,10 +2985,10 @@ "drupal/umami_analytics": "<1.0.1", "duncanmcclean/guest-entries": "<3.1.2", "dweeves/magmi": "<=0.7.24", - "ec-cube/ec-cube": "<2.4.4|>=2.11,<=2.17.1|>=3,<=3.0.18.0-patch4|>=4,<=4.1.2", + "ec-cube/ec-cube": "<2.4.4|>=2.11,<=2.17.1|>=3,<=3.0.18.0-patch4|>=4,<=4.3.1", "ecodev/newsletter": "<=4", "ectouch/ectouch": "<=2.7.2", - "egroupware/egroupware": "<23.1.20240624", + "egroupware/egroupware": "<23.1.20260113|>=26.0.20251208,<26.0.20260113", "elefant/cms": "<2.0.7", "elgg/elgg": "<3.3.24|>=4,<4.0.5", "elijaa/phpmemcacheadmin": "<=1.3", @@ -2546,18 +3011,18 @@ "ezsystems/ezplatform-admin-ui-assets": ">=4,<4.2.1|>=5,<5.0.1|>=5.1,<5.1.1|>=5.3.0.0-beta1,<5.3.5", "ezsystems/ezplatform-graphql": ">=1.0.0.0-RC1-dev,<1.0.13|>=2.0.0.0-beta1,<2.3.12", "ezsystems/ezplatform-http-cache": "<2.3.16", - "ezsystems/ezplatform-kernel": "<1.2.5.1-dev|>=1.3,<1.3.35", + "ezsystems/ezplatform-kernel": "<=1.2.5|>=1.3,<1.3.35", "ezsystems/ezplatform-rest": ">=1.2,<=1.2.2|>=1.3,<1.3.8", "ezsystems/ezplatform-richtext": ">=2.3,<2.3.26|>=3.3,<3.3.40", "ezsystems/ezplatform-solr-search-engine": ">=1.7,<1.7.12|>=2,<2.0.2|>=3.3,<3.3.15", "ezsystems/ezplatform-user": ">=1,<1.0.1", - "ezsystems/ezpublish-kernel": "<6.13.8.2-dev|>=7,<7.5.31", + "ezsystems/ezpublish-kernel": "<=6.13.8.1|>=7,<7.5.31", "ezsystems/ezpublish-legacy": "<=2017.12.7.3|>=2018.6,<=2019.03.5.1", "ezsystems/platform-ui-assets-bundle": ">=4.2,<4.2.3", "ezsystems/repository-forms": ">=2.3,<2.3.2.1-dev|>=2.5,<2.5.15", "ezyang/htmlpurifier": "<=4.2", "facade/ignition": "<1.16.15|>=2,<2.4.2|>=2.5,<2.5.2", - "facturascripts/facturascripts": "<=2025.4|==2025.11|==2025.41|==2025.43", + "facturascripts/facturascripts": "<2025.81", "fastly/magento2": "<1.2.26", "feehi/cms": "<=2.1.1", "feehi/feehicms": "<=2.1.1", @@ -2565,11 +3030,11 @@ "filament/actions": ">=3.2,<3.2.123", "filament/filament": ">=4,<4.3.1", "filament/infolists": ">=3,<3.2.115", - "filament/tables": ">=3,<3.2.115", + "filament/tables": ">=3,<3.2.115|>=4,<4.8.5|>=5,<5.3.5", "filegator/filegator": "<7.8", "filp/whoops": "<2.1.13", "fineuploader/php-traditional-server": "<=1.2.2", - "firebase/php-jwt": "<6", + "firebase/php-jwt": "<7", "fisharebest/webtrees": "<=2.1.18", "fixpunkt/fp-masterquiz": "<2.2.1|>=3,<3.5.2", "fixpunkt/fp-newsletter": "<1.1.1|>=1.2,<2.1.2|>=2.2,<3.2.6", @@ -2577,6 +3042,7 @@ "flarum/flarum": "<0.1.0.0-beta8", "flarum/framework": "<1.8.10", "flarum/mentions": "<1.6.3", + "flarum/nicknames": "<1.8.3", "flarum/sticky": ">=0.1.0.0-beta14,<=0.1.0.0-beta15", "flarum/tags": "<=0.1.0.0-beta13", "floriangaerber/magnesium": "<0.3.1", @@ -2598,17 +3064,18 @@ "friendsoftypo3/mediace": ">=7.6.2,<7.6.5", "friendsoftypo3/openid": ">=4.5,<4.5.31|>=4.7,<4.7.16|>=6,<6.0.11|>=6.1,<6.1.6", "froala/wysiwyg-editor": "<=4.3", - "froxlor/froxlor": "<=2.2.5", + "frosh/adminer-platform": "<2.2.1", + "froxlor/froxlor": "<=2.3.4", "frozennode/administrator": "<=5.0.12", "fuel/core": "<1.8.1", - "funadmin/funadmin": "<=5.0.2", + "funadmin/funadmin": "<=7.1.0.0-RC4", "gaoming13/wechat-php-sdk": "<=1.10.2", "genix/cms": "<=1.1.11", "georgringer/news": "<1.3.3", "geshi/geshi": "<=1.0.9.1", - "getformwork/formwork": "<2.2", + "getformwork/formwork": "<=2.3.3", "getgrav/grav": "<1.11.0.0-beta1", - "getkirby/cms": "<3.9.8.3-dev|>=3.10,<3.10.1.2-dev|>=4,<4.7.1|>=5,<5.1.4", + "getkirby/cms": "<=5.2.1", "getkirby/kirby": "<3.9.8.3-dev|>=3.10,<3.10.1.2-dev|>=4,<4.7.1", "getkirby/panel": "<2.5.14", "getkirby/starterkit": "<=3.7.0.2", @@ -2617,12 +3084,12 @@ "globalpayments/php-sdk": "<2", "goalgorilla/open_social": "<12.3.11|>=12.4,<12.4.10|>=13.0.0.0-alpha1,<13.0.0.0-alpha11", "gogentooss/samlbase": "<1.2.7", - "google/protobuf": "<3.4", + "google/protobuf": "<4.33.6", "gos/web-socket-bundle": "<1.10.4|>=2,<2.6.1|>=3,<3.3", "gp247/core": "<1.1.24", "gree/jose": "<2.2.1", "gregwar/rst": "<1.0.3", - "grumpydictator/firefly-iii": "<6.1.17", + "grumpydictator/firefly-iii": "<6.1.17|>=6.4.23,<=6.5", "gugoan/economizzer": "<=0.9.0.0-beta1", "guzzlehttp/guzzle": "<6.5.8|>=7,<7.4.5", "guzzlehttp/oauth-subscriber": "<0.8.1", @@ -2637,6 +3104,7 @@ "hjue/justwriting": "<=1", "hov/jobfair": "<1.0.13|>=2,<2.0.2", "httpsoft/http-message": "<1.0.12", + "hybridauth/hybridauth": "<=3.12.2", "hyn/multi-tenant": ">=5.6,<5.7.2", "ibexa/admin-ui": ">=4.2,<4.2.3|>=4.6,<4.6.25|>=5,<5.0.3", "ibexa/admin-ui-assets": ">=4.6.0.0-alpha1,<4.6.21", @@ -2648,7 +3116,7 @@ "ibexa/solr": ">=4.5,<4.5.4", "ibexa/user": ">=4,<4.4.3|>=5,<5.0.4", "icecoder/icecoder": "<=8.1", - "idno/known": "<=1.3.1", + "idno/known": "<1.6.4", "ilicmiljan/secure-props": ">=1.2,<1.2.2", "illuminate/auth": "<5.5.10", "illuminate/cookie": ">=4,<=4.0.11|>=4.1,<6.18.31|>=7,<7.22.4", @@ -2665,10 +3133,12 @@ "innologi/typo3-appointments": "<2.0.6", "intelliants/subrion": "<4.2.2", "inter-mediator/inter-mediator": "==5.5", + "invoiceninja/invoiceninja": "<5.13.4", "ipl/web": "<0.10.1", "islandora/crayfish": "<4.1", "islandora/islandora": ">=2,<2.4.1", "ivankristianto/phpwhois": "<=4.3", + "j0k3r/graby": "<=2.5", "jackalope/jackalope-doctrine-dbal": "<1.7.4", "jambagecom/div2007": "<0.10.2", "james-heinrich/getid3": "<1.9.21", @@ -2677,6 +3147,7 @@ "jbartels/wec-map": "<3.0.3", "jcbrand/converse.js": "<3.3.3", "joelbutcher/socialstream": "<5.6|>=6,<6.2", + "johnbillion/query-monitor": "<3.20.4", "johnbillion/wp-crontrol": "<1.16.2|>=1.17,<1.19.2", "joomla/application": "<1.0.13", "joomla/archive": "<1.1.12|>=2,<2.0.1", @@ -2694,17 +3165,19 @@ "juzaweb/cms": "<=3.4.2", "jweiland/events2": "<8.3.8|>=9,<9.0.6", "jweiland/kk-downloader": "<1.2.2", + "kantorge/yaffa": "<=2", "kazist/phpwhois": "<=4.2.6", + "kelvinmo/simplejwt": "<=1.1", "kelvinmo/simplexrd": "<3.1.1", "kevinpapst/kimai2": "<1.16.7", "khodakhah/nodcms": "<=3", - "kimai/kimai": "<=2.20.1", + "kimai/kimai": "<=2.52", "kitodo/presentation": "<3.2.3|>=3.3,<3.3.4", "klaviyo/magento2-extension": ">=1,<3", "knplabs/knp-snappy": "<=1.4.2", "kohana/core": "<3.3.3", "koillection/koillection": "<1.6.12", - "krayin/laravel-crm": "<=1.3", + "krayin/laravel-crm": "<=2.2", "kreait/firebase-php": ">=3.2,<3.8.1", "kumbiaphp/kumbiapp": "<=1.1.1", "la-haute-societe/tcpdf": "<6.2.22", @@ -2714,26 +3187,28 @@ "lara-zeus/artemis": ">=1,<=1.0.6", "lara-zeus/dynamic-dashboard": ">=3,<=3.0.1", "laravel/fortify": "<1.11.1", - "laravel/framework": "<6.20.44|>=7,<7.30.6|>=8,<8.75", + "laravel/framework": "<10.48.29|>=11,<11.44.1|>=12,<12.1.1", "laravel/laravel": ">=5.4,<5.4.22", + "laravel/passport": ">=13,<13.7.1", "laravel/pulse": "<1.3.1", - "laravel/reverb": "<1.4", + "laravel/reverb": "<1.7", "laravel/socialite": ">=1,<2.0.10", "latte/latte": "<2.10.8", - "lavalite/cms": "<=9|==10.1", + "lavalite/cms": "<=10.1", "lavitto/typo3-form-to-database": "<2.2.5|>=3,<3.2.2|>=4,<4.2.3|>=5,<5.0.2", "lcobucci/jwt": ">=3.4,<3.4.6|>=4,<4.0.4|>=4.1,<4.1.5", - "league/commonmark": "<2.7", + "league/commonmark": "<=2.8.1", "league/flysystem": "<1.1.4|>=2,<2.1.1", "league/oauth2-server": ">=8.3.2,<8.4.2|>=8.5,<8.5.3", "leantime/leantime": "<3.3", "lexik/jwt-authentication-bundle": "<2.10.7|>=2.11,<2.11.3", "libreform/libreform": ">=2,<=2.0.8", - "librenms/librenms": "<25.12", + "librenms/librenms": "<26.3", "liftkit/database": "<2.13.2", "lightsaml/lightsaml": "<1.3.5", - "limesurvey/limesurvey": "<6.5.12", + "limesurvey/limesurvey": "<6.15.4", "livehelperchat/livehelperchat": "<=3.91", + "livewire-filemanager/filemanager": "<=1.0.4", "livewire/livewire": "<2.12.7|>=3.0.0.0-beta1,<3.6.4", "livewire/volt": "<1.7", "lms/routes": "<2.1.1", @@ -2754,12 +3229,12 @@ "maikuolan/phpmussel": ">=1,<1.6", "mainwp/mainwp": "<=4.4.3.3", "manogi/nova-tiptap": "<=3.2.6", - "mantisbt/mantisbt": "<2.27.2", + "mantisbt/mantisbt": "<2.28.1", "marcwillmann/turn": "<0.3.3", "marshmallow/nova-tiptap": "<5.7", "matomo/matomo": "<1.11", "matyhtf/framework": "<3.0.6", - "mautic/core": "<5.2.9|>=6,<6.0.7", + "mautic/core": "<5.2.10|>=6,<6.0.8|>=7.0.0.0-alpha,<7.0.1", "mautic/core-lib": ">=1.0.0.0-beta,<4.4.13|>=5.0.0.0-alpha,<5.1.1", "mautic/grapes-js-builder-bundle": ">=4,<4.4.18|>=5,<5.2.9|>=6,<6.0.7", "maximebf/debugbar": "<1.19", @@ -2781,10 +3256,11 @@ "microsoft/microsoft-graph": ">=1.16,<1.109.1|>=2,<2.0.1", "microsoft/microsoft-graph-beta": "<2.0.1", "microsoft/microsoft-graph-core": "<2.0.2", - "microweber/microweber": "<=2.0.19", + "microweber/microweber": "<2.0.20", "mikehaertl/php-shellcommand": "<1.6.1", "mineadmin/mineadmin": "<=3.0.9", "miniorange/miniorange-saml": "<1.4.3", + "miraheze/ts-portal": "<=33", "mittwald/typo3_forum": "<1.2.1", "mobiledetect/mobiledetectlib": "<2.8.32", "modx/revolution": "<=3.1", @@ -2792,7 +3268,8 @@ "mongodb/mongodb": ">=1,<1.9.2", "mongodb/mongodb-extension": "<1.21.2", "monolog/monolog": ">=1.8,<1.12", - "moodle/moodle": "<4.3.6|>=4.4.0.0-beta,<4.4.2", + "moodle/moodle": "<4.5.9|>=5.0.0.0-beta,<5.0.5|>=5.1.0.0-beta,<5.1.2", + "moonshine/moonshine": "<=3.12.5", "mos/cimage": "<0.7.19", "movim/moxl": ">=0.8,<=0.10", "movingbytes/social-network": "<=1.2.1", @@ -2836,7 +3313,7 @@ "october/cms": "<1.0.469|==1.0.469|==1.0.471|==1.1.1", "october/october": "<3.7.5", "october/rain": "<1.0.472|>=1.1,<1.1.2", - "october/system": "<3.7.5", + "october/system": "<=3.7.12|>=4,<=4.0.11", "oliverklee/phpunit": "<3.5.15", "omeka/omeka-s": "<4.0.3", "onelogin/php-saml": "<2.21.1|>=3,<3.8.1|>=4,<4.3.1", @@ -2844,10 +3321,10 @@ "open-web-analytics/open-web-analytics": "<1.8.1", "opencart/opencart": ">=0", "openid/php-openid": "<2.3", - "openmage/magento-lts": "<20.16", + "openmage/magento-lts": "<20.16.1", "opensolutions/vimbadmin": "<=3.0.15", - "opensource-workshop/connect-cms": "<1.7.2|>=2,<2.3.2", - "orchid/platform": ">=9,<9.4.4|>=14.0.0.0-alpha4,<14.5", + "opensource-workshop/connect-cms": "<1.41.1|>=2,<2.41.1", + "orchid/platform": ">=8,<14.43", "oro/calendar-bundle": ">=4.2,<=4.2.6|>=5,<=5.0.6|>=5.1,<5.1.1", "oro/commerce": ">=4.1,<5.0.11|>=5.1,<5.1.1", "oro/crm": ">=1.7,<1.7.4|>=3.1,<4.1.17|>=4.2,<4.2.7", @@ -2876,6 +3353,7 @@ "pear/pear": "<=1.10.1", "pegasus/google-for-jobs": "<1.5.1|>=2,<2.1.1", "personnummer/personnummer": "<3.0.2", + "ph7software/ph7builder": "<=17.9.1", "phanan/koel": "<5.1.4", "phenx/php-svg-lib": "<0.5.2", "php-censor/php-censor": "<2.0.13|>=2.1,<2.1.5", @@ -2886,33 +3364,35 @@ "phpmailer/phpmailer": "<6.5", "phpmussel/phpmussel": ">=1,<1.6", "phpmyadmin/phpmyadmin": "<5.2.2", - "phpmyfaq/phpmyfaq": "<=4.0.13", + "phpmyfaq/phpmyfaq": "<=4.1", "phpoffice/common": "<0.2.9", "phpoffice/math": "<=0.2", "phpoffice/phpexcel": "<=1.8.2", "phpoffice/phpspreadsheet": "<1.30|>=2,<2.1.12|>=2.2,<2.4|>=3,<3.10|>=4,<5", "phppgadmin/phppgadmin": "<=7.13", - "phpseclib/phpseclib": "<2.0.47|>=3,<3.0.36", + "phpseclib/phpseclib": "<2.0.53|>=3,<3.0.51", "phpservermon/phpservermon": "<3.6", "phpsysinfo/phpsysinfo": "<3.4.3", - "phpunit/phpunit": ">=4.8.19,<4.8.28|>=5.0.10,<5.6.3", + "phpunit/phpunit": "<8.5.52|>=9,<9.6.33|>=10,<10.5.62|>=11,<11.5.50|>=12,<12.5.8", "phpwhois/phpwhois": "<=4.2.5", "phpxmlrpc/extras": "<0.6.1", "phpxmlrpc/phpxmlrpc": "<4.9.2", + "phraseanet/phraseanet": "==4.0.3", "pi/pi": "<=2.5", - "pimcore/admin-ui-classic-bundle": "<1.7.6", + "pimcore/admin-ui-classic-bundle": "<=1.7.15|>=2.0.0.0-RC1-dev,<=2.2.2", "pimcore/customer-management-framework-bundle": "<4.2.1", "pimcore/data-hub": "<1.2.4", "pimcore/data-importer": "<1.8.9|>=1.9,<1.9.3", "pimcore/demo": "<10.3", "pimcore/ecommerce-framework-bundle": "<1.0.10", "pimcore/perspective-editor": "<1.5.1", - "pimcore/pimcore": "<11.5.4", + "pimcore/pimcore": "<=11.5.14.1|>=12,<12.3.3", + "pimcore/web2print-tools-bundle": "<=5.2.1|>=6.0.0.0-RC1-dev,<=6.1", "piwik/piwik": "<1.11", "pixelfed/pixelfed": "<0.12.5", "plotly/plotly.js": "<2.25.2", "pocketmine/bedrock-protocol": "<8.0.2", - "pocketmine/pocketmine-mp": "<5.32.1", + "pocketmine/pocketmine-mp": "<5.41.1", "pocketmine/raklib": ">=0.14,<0.14.6|>=0.15,<0.15.1", "pressbooks/pressbooks": "<5.18", "prestashop/autoupgrade": ">=4,<4.10.1", @@ -2920,7 +3400,7 @@ "prestashop/blockwishlist": ">=2,<2.1.1", "prestashop/contactform": ">=1.0.1,<4.3", "prestashop/gamification": "<2.3.2", - "prestashop/prestashop": "<8.2.3", + "prestashop/prestashop": "<8.2.5|>=9.0.0.0-alpha1,<9.1", "prestashop/productcomments": "<5.0.2", "prestashop/ps_checkout": "<4.4.1|>=5,<5.0.5", "prestashop/ps_contactinfo": "<=3.3.2", @@ -2931,12 +3411,14 @@ "processwire/processwire": "<=3.0.246", "propel/propel": ">=2.0.0.0-alpha1,<=2.0.0.0-alpha7", "propel/propel1": ">=1,<=1.7.1", - "pterodactyl/panel": "<1.12", + "psy/psysh": "<=0.11.22|>=0.12,<=0.12.18", + "pterodactyl/panel": "<1.12.1", "ptheofan/yii2-statemachine": ">=2.0.0.0-RC1-dev,<=2", "ptrofimov/beanstalk_console": "<1.7.14", "pubnub/pubnub": "<6.1", "punktde/pt_extbase": "<1.5.1", "pusher/pusher-php-server": "<2.2.1", + "putyourlightson/craft-sprig": ">=2,<2.15.2|>=3,<3.7.2", "pwweb/laravel-core": "<=0.3.6.0-beta", "pxlrbt/filament-excel": "<1.1.14|>=2.0.0.0-alpha,<2.3.3", "pyrocms/pyrocms": "<=3.9.1", @@ -2945,25 +3427,28 @@ "rainlab/blog-plugin": "<1.4.1", "rainlab/debugbar-plugin": "<3.1", "rainlab/user-plugin": "<=1.4.5", + "ralffreit/mfa-email": "<1.0.7|==2", "rankmath/seo-by-rank-math": "<=1.0.95", "rap2hpoutre/laravel-log-viewer": "<0.13", "react/http": ">=0.7,<1.9", "really-simple-plugins/complianz-gdpr": "<6.4.2", - "redaxo/source": "<=5.20.1", + "redaxo/source": "<5.21", "remdex/livehelperchat": "<4.29", "renolit/reint-downloadmanager": "<4.0.2|>=5,<5.0.1", "reportico-web/reportico": "<=8.1", - "rhukster/dom-sanitizer": "<1.0.7", + "rhukster/dom-sanitizer": "<1.0.10", "rmccue/requests": ">=1.6,<1.8", - "robrichards/xmlseclibs": "<=3.1.3", + "roadiz/documents": "<2.3.42|>=2.4,<2.5.44|>=2.6,<2.6.28|>=2.7,<2.7.9", + "robrichards/xmlseclibs": "<3.1.5", "roots/soil": "<4.1", - "roundcube/roundcubemail": "<1.5.10|>=1.6,<1.6.11", + "roundcube/roundcubemail": "<1.5.10|>=1.6,<1.6.11|>=1.7.0.0-beta,<1.7.0.0-RC5-dev", "rudloff/alltube": "<3.0.3", "rudloff/rtmpdump-bin": "<=2.3.1", "s-cart/core": "<=9.0.5", "s-cart/s-cart": "<6.9", "sabberworm/php-css-parser": ">=1,<1.0.1|>=2,<2.0.1|>=3,<3.0.1|>=4,<4.0.1|>=5,<5.0.9|>=5.1,<5.1.3|>=5.2,<5.2.1|>=6,<6.0.2|>=7,<7.0.4|>=8,<8.0.1|>=8.1,<8.1.1|>=8.2,<8.2.1|>=8.3,<8.3.1", "sabre/dav": ">=1.6,<1.7.11|>=1.8,<1.8.9", + "saloonphp/saloon": "<4", "samwilson/unlinked-wikibase": "<1.42", "scheb/two-factor-bundle": "<3.26|>=4,<4.11", "sensiolabs/connect": "<4.2.3", @@ -2971,10 +3456,10 @@ "setasign/fpdi": "<2.6.4", "sfroemken/url_redirect": "<=1.2.1", "sheng/yiicms": "<1.2.1", - "shopware/core": "<6.6.10.9-dev|>=6.7,<6.7.4.1-dev", - "shopware/platform": "<6.6.10.7-dev|>=6.7,<6.7.3.1-dev", + "shopware/core": "<6.6.10.15-dev|>=6.7,<6.7.8.1-dev", + "shopware/platform": "<6.6.10.15-dev|>=6.7,<6.7.8.1-dev", "shopware/production": "<=6.3.5.2", - "shopware/shopware": "<=5.7.17|>=6.4.6,<6.6.10.10-dev|>=6.7,<6.7.5.1-dev", + "shopware/shopware": "<=5.7.17|>=6.4.6,<6.6.10.10-dev|>=6.7,<6.7.6.1-dev", "shopware/storefront": "<6.6.10.10-dev|>=6.7,<6.7.5.1-dev", "shopxo/shopxo": "<=6.4", "showdoc/showdoc": "<2.10.4", @@ -3006,7 +3491,7 @@ "simplesamlphp/simplesamlphp-module-openid": "<1", "simplesamlphp/simplesamlphp-module-openidprovider": "<0.9", "simplesamlphp/xml-common": "<1.20", - "simplesamlphp/xml-security": "==1.6.11", + "simplesamlphp/xml-security": "<1.13.9|>=2,<2.3.1", "simplito/elliptic-php": "<1.0.6", "sitegeist/fluid-components": "<3.5", "sjbr/sr-feuser-register": "<2.6.2|>=5.1,<12.5", @@ -3016,10 +3501,10 @@ "slim/slim": "<2.6", "slub/slub-events": "<3.0.3", "smarty/smarty": "<4.5.3|>=5,<5.1.1", - "snipe/snipe-it": "<=8.3.4", + "snipe/snipe-it": "<8.3.7", "socalnick/scn-social-auth": "<1.15.2", "socialiteproviders/steam": "<1.1", - "solspace/craft-freeform": ">=5,<5.10.16", + "solspace/craft-freeform": "<4.1.29|>=5,<=5.14.6", "soosyze/soosyze": "<=2", "spatie/browsershot": "<5.0.5", "spatie/image-optimizer": "<1.7.3", @@ -3034,14 +3519,14 @@ "starcitizentools/short-description": ">=4,<4.0.1", "starcitizentools/tabber-neue": ">=1.9.1,<2.7.2|>=3,<3.1.1", "starcitizenwiki/embedvideo": "<=4", - "statamic/cms": "<=5.22", + "statamic/cms": "<5.73.16|>=6,<6.7.2", "stormpath/sdk": "<9.9.99", "studio-42/elfinder": "<=2.1.64", "studiomitte/friendlycaptcha": "<0.1.4", "subhh/libconnect": "<7.0.8|>=8,<8.1", "sukohi/surpass": "<1", "sulu/form-bundle": ">=2,<2.5.3", - "sulu/sulu": "<1.6.44|>=2,<2.5.25|>=2.6,<2.6.9|>=3.0.0.0-alpha1,<3.0.0.0-alpha3", + "sulu/sulu": "<2.6.22|>=3,<3.0.5", "sumocoders/framework-user-bundle": "<1.4", "superbig/craft-audit": "<3.0.2", "svewap/a21glossary": "<=0.4.10", @@ -3053,7 +3538,7 @@ "sylius/grid-bundle": "<1.10.1", "sylius/paypal-plugin": "<1.6.2|>=1.7,<1.7.2|>=2,<2.0.2", "sylius/resource-bundle": ">=1,<1.3.14|>=1.4,<1.4.7|>=1.5,<1.5.2|>=1.6,<1.6.4", - "sylius/sylius": "<1.12.19|>=1.13.0.0-alpha1,<1.13.4", + "sylius/sylius": "<1.9.12|>=1.10,<1.10.16|>=1.11,<1.11.17|>=1.12,<=1.12.22|>=1.13,<=1.13.14|>=1.14,<=1.14.17|>=2,<=2.0.15|>=2.1,<=2.1.11|>=2.2,<=2.2.2", "symbiote/silverstripe-multivaluefield": ">=3,<3.1", "symbiote/silverstripe-queuedjobs": ">=3,<3.0.2|>=3.1,<3.1.4|>=4,<4.0.7|>=4.1,<4.1.2|>=4.2,<4.2.4|>=4.3,<4.3.3|>=4.4,<4.4.3|>=4.5,<4.5.1|>=4.6,<4.6.4", "symbiote/silverstripe-seed": "<6.0.3", @@ -3064,8 +3549,8 @@ "symfony/error-handler": ">=4.4,<4.4.4|>=5,<5.0.4", "symfony/form": ">=2.3,<2.3.35|>=2.4,<2.6.12|>=2.7,<2.7.50|>=2.8,<2.8.49|>=3,<3.4.20|>=4,<4.0.15|>=4.1,<4.1.9|>=4.2,<4.2.1", "symfony/framework-bundle": ">=2,<2.3.18|>=2.4,<2.4.8|>=2.5,<2.5.2|>=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7|>=5.3.14,<5.3.15|>=5.4.3,<5.4.4|>=6.0.3,<6.0.4", - "symfony/http-client": ">=4.3,<5.4.46|>=6,<6.4.14|>=7,<7.1.7", - "symfony/http-foundation": "<5.4.46|>=6,<6.4.14|>=7,<7.1.7", + "symfony/http-client": ">=4.3,<5.4.47|>=6,<6.4.15|>=7,<7.1.8", + "symfony/http-foundation": "<5.4.50|>=6,<6.4.29|>=7,<7.3.7", "symfony/http-kernel": ">=2,<4.4.50|>=5,<5.4.20|>=6,<6.0.20|>=6.1,<6.1.12|>=6.2,<6.2.6", "symfony/intl": ">=2.7,<2.7.38|>=2.8,<2.8.31|>=3,<3.2.14|>=3.3,<3.3.13", "symfony/maker-bundle": ">=1.27,<1.29.2|>=1.30,<1.31.1", @@ -3073,7 +3558,7 @@ "symfony/phpunit-bridge": ">=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", "symfony/polyfill": ">=1,<1.10", "symfony/polyfill-php55": ">=1,<1.10", - "symfony/process": "<5.4.46|>=6,<6.4.14|>=7,<7.1.7", + "symfony/process": "<5.4.51|>=6,<6.4.33|>=7,<7.1.7|>=7.3,<7.3.11|>=7.4,<7.4.5|>=8,<8.0.5", "symfony/proxy-manager-bridge": ">=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", "symfony/routing": ">=2,<2.0.19", "symfony/runtime": ">=5.3,<5.4.46|>=6,<6.4.14|>=7,<7.1.7", @@ -3084,7 +3569,7 @@ "symfony/security-guard": ">=2.8,<3.4.48|>=4,<4.4.23|>=5,<5.2.8", "symfony/security-http": ">=2.3,<2.3.41|>=2.4,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.2.12|>=4.3,<4.3.8|>=4.4,<4.4.7|>=5,<5.0.7|>=5.1,<5.2.8|>=5.3,<5.4.47|>=6,<6.4.15|>=7,<7.1.8", "symfony/serializer": ">=2,<2.0.11|>=4.1,<4.4.35|>=5,<5.3.12", - "symfony/symfony": "<5.4.46|>=6,<6.4.14|>=7,<7.1.7", + "symfony/symfony": "<5.4.51|>=6,<6.4.33|>=7,<7.3.11|>=7.4,<7.4.5|>=8,<8.0.5", "symfony/translation": ">=2,<2.0.17", "symfony/twig-bridge": ">=2,<4.4.51|>=5,<5.4.31|>=6,<6.3.8", "symfony/ux-autocomplete": "<2.11.2", @@ -3108,7 +3593,7 @@ "thelia/thelia": ">=2.1,<2.1.3", "theonedemon/phpwhois": "<=4.2.5", "thinkcmf/thinkcmf": "<6.0.8", - "thorsten/phpmyfaq": "<4.0.16|>=4.1.0.0-alpha,<=4.1.0.0-beta2", + "thorsten/phpmyfaq": "<4.1.1", "tikiwiki/tiki-manager": "<=17.1", "timber/timber": ">=0.16.6,<1.23.1|>=1.24,<1.24.1|>=2,<2.1", "tinymce/tinymce": "<7.2", @@ -3126,11 +3611,12 @@ "ttskch/pagination-service-provider": "<1", "twbs/bootstrap": "<3.4.1|>=4,<4.3.1", "twig/twig": "<3.11.2|>=3.12,<3.14.1|>=3.16,<3.19", + "typicms/core": "<16.1.7", "typo3/cms": "<9.5.29|>=10,<10.4.35|>=11,<11.5.23|>=12,<12.2", - "typo3/cms-backend": "<4.1.14|>=4.2,<4.2.15|>=4.3,<4.3.7|>=4.4,<4.4.4|>=7,<=7.6.50|>=8,<=8.7.39|>=9,<9.5.55|>=10,<10.4.54|>=11,<11.5.48|>=12,<12.4.37|>=13,<13.4.18", + "typo3/cms-backend": "<4.1.14|>=4.2,<4.2.15|>=4.3,<4.3.7|>=4.4,<4.4.4|>=7,<=7.6.50|>=8,<=8.7.39|>=9,<9.5.55|>=10,<=10.4.54|>=11,<=11.5.48|>=12,<=12.4.40|>=13,<=13.4.22|>=14,<=14.0.1", "typo3/cms-belog": ">=10,<=10.4.47|>=11,<=11.5.41|>=12,<=12.4.24|>=13,<=13.4.2", "typo3/cms-beuser": ">=9,<9.5.55|>=10,<10.4.54|>=11,<11.5.48|>=12,<12.4.37|>=13,<13.4.18", - "typo3/cms-core": "<=8.7.56|>=9,<9.5.55|>=10,<10.4.54|>=11,<11.5.48|>=12,<12.4.37|>=13,<13.4.18", + "typo3/cms-core": "<=8.7.56|>=9,<9.5.55|>=10,<=10.4.54|>=11,<=11.5.48|>=12,<=12.4.40|>=13,<=13.4.22|>=14,<=14.0.1", "typo3/cms-dashboard": ">=10,<10.4.54|>=11,<11.5.48|>=12,<12.4.37|>=13,<13.4.18", "typo3/cms-extbase": "<6.2.24|>=7,<7.6.8|==8.1.1", "typo3/cms-extensionmanager": ">=10,<=10.4.47|>=11,<=11.5.41|>=12,<=12.4.24|>=13,<=13.4.2", @@ -3142,7 +3628,8 @@ "typo3/cms-install": "<4.1.14|>=4.2,<4.2.16|>=4.3,<4.3.9|>=4.4,<4.4.5|>=12.2,<12.4.8|==13.4.2", "typo3/cms-lowlevel": ">=11,<=11.5.41", "typo3/cms-recordlist": ">=11,<11.5.48", - "typo3/cms-recycler": ">=9,<9.5.55|>=10,<10.4.54|>=11,<11.5.48|>=12,<12.4.37|>=13,<13.4.18", + "typo3/cms-recycler": ">=9,<9.5.55|>=10,<=10.4.54|>=11,<=11.5.48|>=12,<=12.4.40|>=13,<=13.4.22|>=14,<=14.0.1", + "typo3/cms-redirects": ">=10,<=10.4.54|>=11,<=11.5.48|>=12,<=12.4.40|>=13,<=13.4.22|>=14,<=14.0.1", "typo3/cms-rte-ckeditor": ">=9.5,<9.5.42|>=10,<10.4.39|>=11,<11.5.30", "typo3/cms-scheduler": ">=11,<=11.5.41", "typo3/cms-setup": ">=9,<=9.5.50|>=10,<=10.4.49|>=11,<=11.5.43|>=12,<=12.4.30|>=13,<=13.4.11", @@ -3156,8 +3643,9 @@ "typo3fluid/fluid": ">=2,<2.0.8|>=2.1,<2.1.7|>=2.2,<2.2.4|>=2.3,<2.3.7|>=2.4,<2.4.4|>=2.5,<2.5.11|>=2.6,<2.6.10", "ua-parser/uap-php": "<3.8", "uasoft-indonesia/badaso": "<=2.9.7", - "unisharp/laravel-filemanager": "<2.6.4", - "unopim/unopim": "<0.1.4", + "unisharp/laravel-filemanager": "<2.9.1", + "universal-omega/dynamic-page-list3": "<3.6.4", + "unopim/unopim": "<=0.3", "userfrosting/userfrosting": ">=0.3.1,<4.6.3", "usmanhalalit/pixie": "<1.0.3|>=2,<2.0.2", "uvdesk/community-skeleton": "<=1.1.1", @@ -3171,28 +3659,30 @@ "vertexvaar/falsftp": "<0.2.6", "villagedefrance/opencart-overclocked": "<=1.11.1", "vova07/yii2-fileapi-widget": "<0.1.9", - "vrana/adminer": "<=4.8.1", + "vrana/adminer": "<5.4.2", "vufind/vufind": ">=2,<9.1.1", "waldhacker/hcaptcha": "<2.1.2", "wallabag/tcpdf": "<6.2.22", "wallabag/wallabag": "<2.6.11", "wanglelecc/laracms": "<=1.0.3", "wapplersystems/a21glossary": "<=0.4.10", - "web-auth/webauthn-framework": ">=3.3,<3.3.4|>=4.5,<4.9", - "web-auth/webauthn-lib": ">=4.5,<4.9", + "web-auth/webauthn-framework": ">=3.3,<3.3.4|>=4.5,<4.9|>=5.2,<5.2.4", + "web-auth/webauthn-lib": ">=4.5,<4.9|>=5.2,<5.2.4", + "web-auth/webauthn-symfony-bundle": ">=5.2,<5.2.4", "web-feet/coastercms": "==5.5", "web-tp3/wec_map": "<3.0.3", "webbuilders-group/silverstripe-kapost-bridge": "<0.4", "webcoast/deferred-image-processing": "<1.0.2", "webklex/laravel-imap": "<5.3", "webklex/php-imap": "<5.3", + "webonyx/graphql-php": "<=15.31.4", "webpa/webpa": "<3.1.2", "webreinvent/vaahcms": "<=2.3.1", "wikibase/wikibase": "<=1.39.3", "wikimedia/parsoid": "<0.12.2", "willdurand/js-translation-bundle": "<2.1.1", - "winter/wn-backend-module": "<1.2.4", - "winter/wn-cms-module": "<1.0.476|>=1.1,<1.1.11|>=1.2,<1.2.7", + "winter/wn-backend-module": "<1.2.12", + "winter/wn-cms-module": "<=1.2.9", "winter/wn-dusk-plugin": "<2.1", "winter/wn-system-module": "<1.2.4", "wintercms/winter": "<=1.2.3", @@ -3204,11 +3694,13 @@ "wpanel/wpanel4-cms": "<=4.3.1", "wpcloud/wp-stateless": "<3.2", "wpglobus/wpglobus": "<=1.9.6", - "wwbn/avideo": "<14.3", + "wpmetabox/meta-box": "<5.11.2", + "wwbn/avideo": "<=26", "xataface/xataface": "<3", "xpressengine/xpressengine": "<3.0.15", "yab/quarx": "<2.4.5", - "yeswiki/yeswiki": "<=4.5.4", + "yansongda/pay": "<=3.7.19", + "yeswiki/yeswiki": "<4.6", "yetiforce/yetiforce-crm": "<6.5", "yidashi/yii2cmf": "<=2", "yii2mod/yii2-cms": "<1.9.2", @@ -3223,6 +3715,7 @@ "yiisoft/yii2-redis": "<2.0.20", "yikesinc/yikes-inc-easy-mailchimp-extender": "<6.8.6", "yoast-seo-for-typo3/yoast_seo": "<7.2.3", + "yoast/duplicate-post": "<=4.5", "yourls/yourls": "<=1.10.2", "yuan1994/tpadmin": "<=1.3.12", "yungifez/skuul": "<=2.6.5", @@ -3263,7 +3756,8 @@ "zf-commons/zfc-user": "<1.2.2", "zfcampus/zf-apigility-doctrine": ">=1,<1.0.3", "zfr/zfr-oauth2-server-module": "<0.1.2", - "zoujingli/thinkadmin": "<=6.1.53" + "zoujingli/thinkadmin": "<=6.1.53", + "zumba/json-serializer": "<3.2.3" }, "type": "metapackage", "notification-url": "https://packagist.org/downloads/", @@ -3300,7 +3794,7 @@ "type": "tidelift" } ], - "time": "2024-11-07T19:04:57+00:00" + "time": "2026-04-14T01:37:23+00:00" }, { "name": "sebastian/cli-parser", @@ -3471,16 +3965,16 @@ }, { "name": "sebastian/comparator", - "version": "4.0.9", + "version": "4.0.10", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "67a2df3a62639eab2cc5906065e9805d4fd5dfc5" + "reference": "e4df00b9b3571187db2831ae9aada2c6efbd715d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/67a2df3a62639eab2cc5906065e9805d4fd5dfc5", - "reference": "67a2df3a62639eab2cc5906065e9805d4fd5dfc5", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/e4df00b9b3571187db2831ae9aada2c6efbd715d", + "reference": "e4df00b9b3571187db2831ae9aada2c6efbd715d", "shasum": "" }, "require": { @@ -3533,7 +4027,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.9" + "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.10" }, "funding": [ { @@ -3553,7 +4047,7 @@ "type": "tidelift" } ], - "time": "2025-08-10T06:51:50+00:00" + "time": "2026-01-24T09:22:56+00:00" }, { "name": "sebastian/complexity", @@ -4315,16 +4809,16 @@ }, { "name": "squizlabs/php_codesniffer", - "version": "3.10.3", + "version": "3.13.5", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", - "reference": "62d32998e820bddc40f99f8251958aed187a5c9c" + "reference": "0ca86845ce43291e8f5692c7356fccf3bcf02bf4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/62d32998e820bddc40f99f8251958aed187a5c9c", - "reference": "62d32998e820bddc40f99f8251958aed187a5c9c", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/0ca86845ce43291e8f5692c7356fccf3bcf02bf4", + "reference": "0ca86845ce43291e8f5692c7356fccf3bcf02bf4", "shasum": "" }, "require": { @@ -4390,7 +4884,704 @@ "type": "thanks_dev" } ], - "time": "2024-09-18T10:38:58+00:00" + "time": "2025-11-04T16:30:35+00:00" + }, + { + "name": "symfony/console", + "version": "v4.4.49", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "33fa45ffc81fdcc1ca368d4946da859c8cdb58d9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/33fa45ffc81fdcc1ca368d4946da859c8cdb58d9", + "reference": "33fa45ffc81fdcc1ca368d4946da859c8cdb58d9", + "shasum": "" + }, + "require": { + "php": ">=7.1.3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php73": "^1.8", + "symfony/polyfill-php80": "^1.16", + "symfony/service-contracts": "^1.1|^2" + }, + "conflict": { + "psr/log": ">=3", + "symfony/dependency-injection": "<3.4", + "symfony/event-dispatcher": "<4.3|>=5", + "symfony/lock": "<4.4", + "symfony/process": "<3.3" + }, + "provide": { + "psr/log-implementation": "1.0|2.0" + }, + "require-dev": { + "psr/log": "^1|^2", + "symfony/config": "^3.4|^4.0|^5.0", + "symfony/dependency-injection": "^3.4|^4.0|^5.0", + "symfony/event-dispatcher": "^4.3", + "symfony/lock": "^4.4|^5.0", + "symfony/process": "^3.4|^4.0|^5.0", + "symfony/var-dumper": "^4.3|^5.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Eases the creation of beautiful and testable command line interfaces", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/console/tree/v4.4.49" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-05T17:10:16+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v2.5.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "605389f2a7e5625f273b53960dc46aeaf9c62918" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/605389f2a7e5625f273b53960dc46aeaf9c62918", + "reference": "605389f2a7e5625f273b53960dc46aeaf9c62918", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "2.5-dev" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.4" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:11:13+00:00" + }, + { + "name": "symfony/filesystem", + "version": "v4.4.42", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "815412ee8971209bd4c1eecd5f4f481eacd44bf5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/815412ee8971209bd4c1eecd5f4f481eacd44bf5", + "reference": "815412ee8971209bd4c1eecd5f4f481eacd44bf5", + "shasum": "" + }, + "require": { + "php": ">=7.1.3", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-php80": "^1.16" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides basic utilities for the filesystem", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/filesystem/tree/v4.4.42" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-05-20T08:49:14+00:00" + }, + { + "name": "symfony/finder", + "version": "v4.4.44", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "66bd787edb5e42ff59d3523f623895af05043e4f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/66bd787edb5e42ff59d3523f623895af05043e4f", + "reference": "66bd787edb5e42ff59d3523f623895af05043e4f", + "shasum": "" + }, + "require": { + "php": ">=7.1.3", + "symfony/polyfill-php80": "^1.16" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Finds files and directories via an intuitive fluent interface", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/finder/tree/v4.4.44" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-07-29T07:35:46+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.34.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "141046a8f9477948ff284fa65be2095baafb94f2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/141046a8f9477948ff284fa65be2095baafb94f2", + "reference": "141046a8f9477948ff284fa65be2095baafb94f2", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.34.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-04-10T16:19:22+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.34.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "6a21eb99c6973357967f6ce3708cd55a6bec6315" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6a21eb99c6973357967f6ce3708cd55a6bec6315", + "reference": "6a21eb99c6973357967f6ce3708cd55a6bec6315", + "shasum": "" + }, + "require": { + "ext-iconv": "*", + "php": ">=7.2" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.34.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-04-10T17:25:58+00:00" + }, + { + "name": "symfony/polyfill-php73", + "version": "v1.34.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php73.git", + "reference": "0f68c03565dcaaf25a890667542e8bd75fe7e5bb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/0f68c03565dcaaf25a890667542e8bd75fe7e5bb", + "reference": "0f68c03565dcaaf25a890667542e8bd75fe7e5bb", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php73\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php73/tree/v1.34.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.34.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "dfb55726c3a76ea3b6459fcfda1ec2d80a682411" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/dfb55726c3a76ea3b6459fcfda1ec2d80a682411", + "reference": "dfb55726c3a76ea3b6459fcfda1ec2d80a682411", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.34.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-04-10T16:19:22+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v2.5.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "f37b419f7aea2e9abf10abd261832cace12e3300" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f37b419f7aea2e9abf10abd261832cace12e3300", + "reference": "f37b419f7aea2e9abf10abd261832cace12e3300", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "psr/container": "^1.1", + "symfony/deprecation-contracts": "^2.1|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "suggest": { + "symfony/service-implementation": "" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "2.5-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v2.5.4" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:11:13+00:00" }, { "name": "theseer/tokenizer", @@ -4510,16 +5701,16 @@ }, { "name": "wp-phpunit/wp-phpunit", - "version": "6.6.2", + "version": "6.9.4", "source": { "type": "git", "url": "https://github.com/wp-phpunit/wp-phpunit.git", - "reference": "7a1d3a2150033a3d3e19de40aa5b2ef2fee36bc3" + "reference": "15fd216bf6516670d8d07b938675925bfa5c15b0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-phpunit/wp-phpunit/zipball/7a1d3a2150033a3d3e19de40aa5b2ef2fee36bc3", - "reference": "7a1d3a2150033a3d3e19de40aa5b2ef2fee36bc3", + "url": "https://api.github.com/repos/wp-phpunit/wp-phpunit/zipball/15fd216bf6516670d8d07b938675925bfa5c15b0", + "reference": "15fd216bf6516670d8d07b938675925bfa5c15b0", "shasum": "" }, "type": "library", @@ -4554,25 +5745,25 @@ "issues": "https://github.com/wp-phpunit/issues", "source": "https://github.com/wp-phpunit/wp-phpunit" }, - "time": "2024-07-17T01:13:44+00:00" + "time": "2026-02-04T01:48:23+00:00" }, { "name": "yoast/phpunit-polyfills", - "version": "3.1.2", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/Yoast/PHPUnit-Polyfills.git", - "reference": "9cf2ccd990eadfc4a1e390592d4731e590b2c618" + "reference": "134921bfca9b02d8f374c48381451da1d98402f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Yoast/PHPUnit-Polyfills/zipball/9cf2ccd990eadfc4a1e390592d4731e590b2c618", - "reference": "9cf2ccd990eadfc4a1e390592d4731e590b2c618", + "url": "https://api.github.com/repos/Yoast/PHPUnit-Polyfills/zipball/134921bfca9b02d8f374c48381451da1d98402f9", + "reference": "134921bfca9b02d8f374c48381451da1d98402f9", "shasum": "" }, "require": { - "php": ">=7.0", - "phpunit/phpunit": "^6.4.4 || ^7.0 || ^8.0 || ^9.0 || ^11.0" + "php": ">=7.1", + "phpunit/phpunit": "^7.5 || ^8.0 || ^9.0 || ^11.0 || ^12.0" }, "require-dev": { "php-parallel-lint/php-console-highlighter": "^1.0.0", @@ -4617,7 +5808,7 @@ "security": "https://github.com/Yoast/PHPUnit-Polyfills/security/policy", "source": "https://github.com/Yoast/PHPUnit-Polyfills" }, - "time": "2025-02-09T18:36:24+00:00" + "time": "2025-02-09T18:58:54+00:00" } ], "aliases": [], @@ -4634,5 +5825,5 @@ "platform-overrides": { "php": "7.3.0" }, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.9.0" } diff --git a/jest.config.js b/jest.config.js index 12173d52e..31da1be06 100644 --- a/jest.config.js +++ b/jest.config.js @@ -19,5 +19,9 @@ module.exports = { }, }, setupFilesAfterEnv: [ './tests/js-unit/setupTests.js' ], + coverageDirectory: './tmp/jest-coverage', testEnvironment: 'jsdom', + testEnvironmentOptions: { + customExportConditions: [ 'require', 'node', 'node-addons' ], + }, }; diff --git a/phpcompat.xml.dist b/phpcompat.xml.dist deleted file mode 100644 index 8e5bf5903..000000000 --- a/phpcompat.xml.dist +++ /dev/null @@ -1,40 +0,0 @@ - - - Apply PHP compatibility checks to Gravity PDF - - - - - - - - - - - - - - - - - - - - - - - - - - ./src/ - ./pdf.php - ./api.php - ./gravity-pdf-updater.php - - - /.php-scoper/* - /node_modules/* - \ No newline at end of file diff --git a/phpunit.xml.dist b/phpunit.xml.dist deleted file mode 100644 index eb7b3ea3f..000000000 --- a/phpunit.xml.dist +++ /dev/null @@ -1,18 +0,0 @@ - - - - - ./src/ - - - - - ./tests/phpunit/unit-tests - - - - - ajax - - - diff --git a/src/Helper/Helper_Form.php b/src/Helper/Helper_Form.php index b5541d80c..1337dbe66 100644 --- a/src/Helper/Helper_Form.php +++ b/src/Helper/Helper_Form.php @@ -33,7 +33,7 @@ class Helper_Form extends Helper_Abstract_Form { * @since 4.0 */ public function get_version() { - return GFCommon::$version; + return \GFForms::$version; } /** diff --git a/src/Helper/Helper_Interface_Extension_Uninstaller.php b/src/Helper/Helper_Interface_Extension_Uninstaller.php index 1af8e4d0e..f28bc4b9c 100644 --- a/src/Helper/Helper_Interface_Extension_Uninstaller.php +++ b/src/Helper/Helper_Interface_Extension_Uninstaller.php @@ -14,7 +14,7 @@ } /** - * @since 6.14.0 + * @since 6.15.0 */ interface Helper_Interface_Extension_Uninstaller { @@ -22,7 +22,7 @@ interface Helper_Interface_Extension_Uninstaller { * Run a custom uninstall action when the Gravity PDF uninstaller is running * * @return void - * @since 6.14 + * @since 6.15.0 */ public function uninstall(); } diff --git a/src/Helper/Helper_Logger.php b/src/Helper/Helper_Logger.php index 77354b6de..cd49d84a5 100644 --- a/src/Helper/Helper_Logger.php +++ b/src/Helper/Helper_Logger.php @@ -16,7 +16,7 @@ } /** - * @since 6.14.0 Moved logic into \GFPDF\Helper\Log\Logger + * @since 6.15.0 Moved logic into \GFPDF\Helper\Log\Logger */ class Helper_Logger extends Logger { diff --git a/src/Helper/Log/Logger.php b/src/Helper/Log/Logger.php index be66b93f3..bf18564b0 100644 --- a/src/Helper/Log/Logger.php +++ b/src/Helper/Log/Logger.php @@ -26,7 +26,7 @@ /** * Enable Logging for Gravity PDF et al. * - * @since 6.14.0 Moved from \GFPDF\Helper\Helper_Logger + * @since 6.15.0 Moved from \GFPDF\Helper\Helper_Logger */ class Logger { @@ -56,7 +56,7 @@ class Logger { /** * Defines the maximum file size for a log file. * - * @since 6.14.0 + * @since 6.15.0 * @internal copied from \GFLogging to do log rotations */ protected $max_file_size = 5242880; @@ -64,7 +64,7 @@ class Logger { /** * Defines the maximum number of log files to store for a plugin. * - * @since 6.14.0 + * @since 6.15.0 * @internal copied from \GFLogging to do log rotations */ protected $max_file_count = 10; @@ -72,7 +72,7 @@ class Logger { /** * Defines the date format for logged messages. * - * @since 6.14.0 + * @since 6.15.0 * @internal copied from \GFLogging to do log rotations */ protected $date_format_log_file = 'YmdGis'; @@ -160,7 +160,7 @@ protected function setup_logger() { * @return void * * @since 4.2 - * @since 6.14.0 Dropped support for separate GF Logging plugin + Gravity Forms < 2.5 + * @since 6.15.0 Dropped support for separate GF Logging plugin + Gravity Forms < 2.5 */ protected function setup_gravityforms_logging() { /* Skip if dependency or setting not available/enabled */ @@ -232,7 +232,7 @@ protected function setup_gravityforms_logging() { * * @param string $file_path Path to log. * - * @since 6.14.0 + * @since 6.15.0 * @internal copied from \GFLogging::maybe_reset_logs() */ protected function rotate_logs( $file_path ) { @@ -288,7 +288,7 @@ function ( $a, $b ) { * This is a temporary measure. Over time our plugins will be updated to support both \Psr\Log\LoggerInterface and '\GFPDF_Vendor\Psr\Log\LoggerInterface' and this won't be required. * * @return LoggerInterface - * @since 6.14.0 + * @since 6.15.0 * */ protected function get_monolog() { diff --git a/src/Helper/Log/MonoLoggerPsrLog2And3.php b/src/Helper/Log/MonoLoggerPsrLog2And3.php index 399643617..d10d8f740 100644 --- a/src/Helper/Log/MonoLoggerPsrLog2And3.php +++ b/src/Helper/Log/MonoLoggerPsrLog2And3.php @@ -16,7 +16,7 @@ /** * PSR\Log v2/v3 Compatible Monolog Proxy class * - * @since 6.14.0 + * @since 6.15.0 * * phpcs:disable Generic.PHP.Syntax.PHPSyntax */ diff --git a/src/assets/js/admin/settings/common/setupLicenseDeactivation.js b/src/assets/js/admin/settings/common/setupLicenseDeactivation.js index 217d94ba3..1e5f2059a 100644 --- a/src/assets/js/admin/settings/common/setupLicenseDeactivation.js +++ b/src/assets/js/admin/settings/common/setupLicenseDeactivation.js @@ -31,28 +31,48 @@ export function setupLicenseDeactivation() { /* Remove our loading spinner */ $spinner.remove(); - /* cleanup inputs */ - $('#gfpdf_settings\\[license_' + slug + '\\]').val(''); - $('#gfpdf_settings\\[license_' + slug + '_message\\]').val(''); - $('#gfpdf_settings\\[license_' + slug + '_status\\]').val(''); - $container.find('button').remove(); - - if (response.success) { - $container - .find('#message') - .removeClass('error') - .addClass('success') - .html(response.success); - } else { - /* Show error message */ + /* update UI to reflect deactivation */ + postLicenseDeactivation( + response.success ?? response.error, + slug, $container - .find('#message') - .removeClass('success') - .addClass('error') - .html(response.error); + ); + + /* handle any shared licenses that were also deactivated */ + if (response.success && Array.isArray(response?.extra)) { + response.extra.forEach((item) => + postLicenseDeactivation( + response.success, + item, + $('#gfpdf-settings-field-wrapper-license_' + item) + ) + ); } }); return false; }); } + +function postLicenseDeactivation(status, slug, $container) { + /* cleanup inputs */ + $('#gfpdf_settings\\[license_' + slug + '\\]').val(''); + $('#gfpdf_settings\\[license_' + slug + '_message\\]').val(''); + $('#gfpdf_settings\\[license_' + slug + '_status\\]').val(''); + $container.find('button').remove(); + + if (status) { + $container + .find('#message') + .removeClass('error') + .addClass('success') + .html(status); + } else { + /* Show error message */ + $container + .find('#message') + .removeClass('success') + .addClass('error') + .html(status); + } +} diff --git a/tests/js-unit/react/components/FontManager/AddFont.test.js b/tests/js-unit/react/components/FontManager/AddFont.test.js index 70697740d..c1a9e91ce 100644 --- a/tests/js-unit/react/components/FontManager/AddFont.test.js +++ b/tests/js-unit/react/components/FontManager/AddFont.test.js @@ -47,7 +47,7 @@ describe('FontManager - AddFont.js', () => { test('render font name validation error', () => { const wrapper = shallow(); - expect(wrapper.find('span.required').length).toBe(1); + expect(wrapper.find('span.required[role="alert"]').length).toBe(1); }); test('hide font name validation error', () => { @@ -56,7 +56,7 @@ describe('FontManager - AddFont.js', () => { ); - expect(wrapper.find('span.required').length).toBe(0); + expect(wrapper.find('span.required[role="alert"]').length).toBe(0); }); test('render font files label text', () => { diff --git a/tests/js-unit/react/components/FontManager/AddUpdateFontFooter.test.js b/tests/js-unit/react/components/FontManager/AddUpdateFontFooter.test.js index ee7666583..61a98cc55 100644 --- a/tests/js-unit/react/components/FontManager/AddUpdateFontFooter.test.js +++ b/tests/js-unit/react/components/FontManager/AddUpdateFontFooter.test.js @@ -96,7 +96,7 @@ describe('FontManager - AddFontFooter.js', () => { test('render cancel button', () => { const wrapper = shallow( - + ); expect(wrapper.find('button.cancel').length).toBe(1); @@ -109,7 +109,7 @@ describe('FontManager - AddFontFooter.js', () => { test('render update font button', () => { const wrapper = shallow( - + ); expect(wrapper.find('button').at(1).text()).toBe('Update Font →'); diff --git a/tests/js-unit/react/components/FontManager/FontVariantLabel.test.js b/tests/js-unit/react/components/FontManager/FontVariantLabel.test.js index 733901789..952c7d37c 100644 --- a/tests/js-unit/react/components/FontManager/FontVariantLabel.test.js +++ b/tests/js-unit/react/components/FontManager/FontVariantLabel.test.js @@ -15,7 +15,9 @@ describe('FontManager - FontVariantLabel.js', () => { ); expect(component.length).toBe(1); - expect(wrapper.find('span').text()).toBe('Regular'); + expect(wrapper.find('span').first().text()).toBe( + 'Regular (required)' + ); }); }); }); diff --git a/tests/js-unit/react/components/FontManager/UpdateFont.test.js b/tests/js-unit/react/components/FontManager/UpdateFont.test.js index 6691f9239..ae3a78aeb 100644 --- a/tests/js-unit/react/components/FontManager/UpdateFont.test.js +++ b/tests/js-unit/react/components/FontManager/UpdateFont.test.js @@ -46,7 +46,7 @@ describe('FontManager - UpdateFont.js', () => { }); test('render font name validation error', () => { - expect(wrapper.find('span.required').length).toBe(1); + expect(wrapper.find('span.required[role="alert"]').length).toBe(1); }); test('render component', () => { diff --git a/tests/js-unit/setupTests.js b/tests/js-unit/setupTests.js index 61887cf6b..a2bff96a7 100644 --- a/tests/js-unit/setupTests.js +++ b/tests/js-unit/setupTests.js @@ -44,6 +44,9 @@ window.GFPDF = { manage: 'Advanced', closeDialog: 'Close dialog', searchBoxResetTitle: 'Clear search.', + fontManagerTitle: 'Font Manager', + fontUserDefinedGroup: 'User-Defined Fonts', + fontManagerRequiredLabel: '(required)', }; window.gfpdf_migration_multisite_ids = []; diff --git a/tests/phpunit/multisite.xml b/tests/phpunit/multisite.xml deleted file mode 100644 index dfa52af16..000000000 --- a/tests/phpunit/multisite.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - ../../src/ - - - - - - - - ./unit-tests - - - - - ajax - - - diff --git a/tools/mu-plugins/error-deprecation-notices.php b/tools/mu-plugins/error-deprecation-notices.php index e80444fd3..eb1b3d8b6 100644 --- a/tools/mu-plugins/error-deprecation-notices.php +++ b/tools/mu-plugins/error-deprecation-notices.php @@ -1,6 +1,8 @@ + + Apply PHP compatibility checks + + + + + + + + + + + + + + + + + + + + + + + /node_modules/* + /vendor/* + /vendor_prefixed/* + /languages/* + /.claude/* + diff --git a/phpcs.xml.dist b/tools/phpcs/config.xml similarity index 91% rename from phpcs.xml.dist rename to tools/phpcs/config.xml index c5730b127..73be5c194 100644 --- a/phpcs.xml.dist +++ b/tools/phpcs/config.xml @@ -1,5 +1,5 @@ - + Customise the WordPress Coding Standard @@ -14,17 +14,12 @@ --> - - - - . - @@ -77,7 +72,7 @@ - + @@ -93,12 +88,12 @@ - /wordpress/* /tmp/* /vendor/* /vendor_prefixed/* /node_modules/* - /.php-scoper/* /build/* /tools/* - \ No newline at end of file + /languages/* + /.claude/* + diff --git a/tests/phpunit/unit-tests/Mocks/zapier-mock.php b/tools/phpunit/Mocks/zapier-mock.php similarity index 100% rename from tests/phpunit/unit-tests/Mocks/zapier-mock.php rename to tools/phpunit/Mocks/zapier-mock.php diff --git a/tests/phpunit/bootstrap.php b/tools/phpunit/bootstrap.php similarity index 93% rename from tests/phpunit/bootstrap.php rename to tools/phpunit/bootstrap.php index 03a23145f..e25436b60 100644 --- a/tests/phpunit/bootstrap.php +++ b/tools/phpunit/bootstrap.php @@ -17,7 +17,7 @@ function auth_redirect() { } /* Define custom config to override the URL used for the test site */ -define( 'WP_TESTS_CONFIG_FILE_PATH', '/var/www/html/wp-content/plugins/gravity-pdf/tests/phpunit/wp-tests-config.php' ); +define( 'WP_TESTS_CONFIG_FILE_PATH', '/var/www/html/wp-content/plugins/gravity-pdf/tools/phpunit/wp-tests-config.php' ); /** * Gravity PDF Unit Tests Bootstrap @@ -88,7 +88,7 @@ public function __construct() { * @since 6.3 */ public function mocks() { - require_once 'unit-tests/Mocks/zapier-mock.php'; + require_once __DIR__ . '/Mocks/zapier-mock.php'; } /** @@ -147,7 +147,7 @@ public function create_stubs() { ]; foreach ( $forms as $json ) { - $form = json_decode( trim( file_get_contents( dirname( __FILE__ ) . '/unit-tests/json/' . $json ) ), true ); + $form = json_decode( trim( file_get_contents( __DIR__ . '/data/forms/' . $json ) ), true ); $form_id = GFAPI::add_form( $form ); $this->form[ substr( $json, 0, -5 ) ] = GFAPI::get_form( $form_id ); } @@ -162,7 +162,7 @@ public function create_stubs() { ]; foreach ( $entries as $id => $json ) { - $entries = json_decode( trim( file_get_contents( dirname( __FILE__ ) . '/unit-tests/json/' . $json ) ), true ); + $entries = json_decode( trim( file_get_contents( __DIR__ . '/data/entries/' . $json ) ), true ); $entry_ids = GFAPI::add_entries( $entries, $this->form[ $id ]['id'] ); /* Loop through our new entry IDs and get the actual entries */ diff --git a/tools/phpunit/config-multisite.xml b/tools/phpunit/config-multisite.xml new file mode 100644 index 000000000..c3b5033ad --- /dev/null +++ b/tools/phpunit/config-multisite.xml @@ -0,0 +1,27 @@ + + + + + + + + + ../../tests/phpunit/unit-tests/ + + + + + + ../../src/ + ../../pdf.php + ../../api.php + ../../gravity-pdf-updater.php + + + diff --git a/tools/phpunit/config.xml b/tools/phpunit/config.xml new file mode 100644 index 000000000..39c15105d --- /dev/null +++ b/tools/phpunit/config.xml @@ -0,0 +1,23 @@ + + + + + ../../tests/phpunit/unit-tests/ + + + + + + ../../src/ + ../../pdf.php + ../../api.php + ../../gravity-pdf-updater.php + + + diff --git a/tests/phpunit/unit-tests/json/all-form-euro-product-entry.json b/tools/phpunit/data/entries/all-form-euro-product-entry.json similarity index 100% rename from tests/phpunit/unit-tests/json/all-form-euro-product-entry.json rename to tools/phpunit/data/entries/all-form-euro-product-entry.json diff --git a/tests/phpunit/unit-tests/json/all-form-fields-entries.json b/tools/phpunit/data/entries/all-form-fields-entries.json similarity index 100% rename from tests/phpunit/unit-tests/json/all-form-fields-entries.json rename to tools/phpunit/data/entries/all-form-fields-entries.json diff --git a/tests/phpunit/unit-tests/json/gravityform-1-entries.json b/tools/phpunit/data/entries/gravityform-1-entries.json similarity index 100% rename from tests/phpunit/unit-tests/json/gravityform-1-entries.json rename to tools/phpunit/data/entries/gravityform-1-entries.json diff --git a/tests/phpunit/unit-tests/json/non-group-products-form-entries.json b/tools/phpunit/data/entries/non-group-products-form-entries.json similarity index 100% rename from tests/phpunit/unit-tests/json/non-group-products-form-entries.json rename to tools/phpunit/data/entries/non-group-products-form-entries.json diff --git a/tests/phpunit/unit-tests/json/repeater-consent-entry.json b/tools/phpunit/data/entries/repeater-consent-entry.json similarity index 100% rename from tests/phpunit/unit-tests/json/repeater-consent-entry.json rename to tools/phpunit/data/entries/repeater-consent-entry.json diff --git a/tests/phpunit/unit-tests/json/repeater-empty-entry.json b/tools/phpunit/data/entries/repeater-empty-entry.json similarity index 100% rename from tests/phpunit/unit-tests/json/repeater-empty-entry.json rename to tools/phpunit/data/entries/repeater-empty-entry.json diff --git a/tests/phpunit/unit-tests/fonts/Chewy.ttf b/tools/phpunit/data/fonts/Chewy.ttf similarity index 100% rename from tests/phpunit/unit-tests/fonts/Chewy.ttf rename to tools/phpunit/data/fonts/Chewy.ttf diff --git a/tests/phpunit/unit-tests/fonts/DejaVuSans-Bold.ttf b/tools/phpunit/data/fonts/DejaVuSans-Bold.ttf similarity index 100% rename from tests/phpunit/unit-tests/fonts/DejaVuSans-Bold.ttf rename to tools/phpunit/data/fonts/DejaVuSans-Bold.ttf diff --git a/tests/phpunit/unit-tests/fonts/DejaVuSans.ttf b/tools/phpunit/data/fonts/DejaVuSans.ttf similarity index 100% rename from tests/phpunit/unit-tests/fonts/DejaVuSans.ttf rename to tools/phpunit/data/fonts/DejaVuSans.ttf diff --git a/tests/phpunit/unit-tests/fonts/DejaVuSansCondensed.ttf b/tools/phpunit/data/fonts/DejaVuSansCondensed.ttf similarity index 100% rename from tests/phpunit/unit-tests/fonts/DejaVuSansCondensed.ttf rename to tools/phpunit/data/fonts/DejaVuSansCondensed.ttf diff --git a/tests/phpunit/unit-tests/fonts/DejaVuSerifCondensed.ttf b/tools/phpunit/data/fonts/DejaVuSerifCondensed.ttf similarity index 100% rename from tests/phpunit/unit-tests/fonts/DejaVuSerifCondensed.ttf rename to tools/phpunit/data/fonts/DejaVuSerifCondensed.ttf diff --git a/tests/phpunit/unit-tests/fonts/chewy-LICENSE.txt b/tools/phpunit/data/fonts/chewy-LICENSE.txt similarity index 100% rename from tests/phpunit/unit-tests/fonts/chewy-LICENSE.txt rename to tools/phpunit/data/fonts/chewy-LICENSE.txt diff --git a/tests/phpunit/unit-tests/json/all-form-fields.json b/tools/phpunit/data/forms/all-form-fields.json similarity index 100% rename from tests/phpunit/unit-tests/json/all-form-fields.json rename to tools/phpunit/data/forms/all-form-fields.json diff --git a/tests/phpunit/unit-tests/json/form-settings-sample-input.json b/tools/phpunit/data/forms/form-settings-sample-input.json similarity index 100% rename from tests/phpunit/unit-tests/json/form-settings-sample-input.json rename to tools/phpunit/data/forms/form-settings-sample-input.json diff --git a/tests/phpunit/unit-tests/json/form-settings.json b/tools/phpunit/data/forms/form-settings.json similarity index 100% rename from tests/phpunit/unit-tests/json/form-settings.json rename to tools/phpunit/data/forms/form-settings.json diff --git a/tests/phpunit/unit-tests/json/gravityform-1.json b/tools/phpunit/data/forms/gravityform-1.json similarity index 100% rename from tests/phpunit/unit-tests/json/gravityform-1.json rename to tools/phpunit/data/forms/gravityform-1.json diff --git a/tests/phpunit/unit-tests/json/gravityform-2.json b/tools/phpunit/data/forms/gravityform-2.json similarity index 100% rename from tests/phpunit/unit-tests/json/gravityform-2.json rename to tools/phpunit/data/forms/gravityform-2.json diff --git a/tests/phpunit/unit-tests/json/latest-posts.json b/tools/phpunit/data/forms/latest-posts.json similarity index 100% rename from tests/phpunit/unit-tests/json/latest-posts.json rename to tools/phpunit/data/forms/latest-posts.json diff --git a/tests/phpunit/unit-tests/json/migration_v3_to_v4.json b/tools/phpunit/data/forms/migration_v3_to_v4.json similarity index 100% rename from tests/phpunit/unit-tests/json/migration_v3_to_v4.json rename to tools/phpunit/data/forms/migration_v3_to_v4.json diff --git a/tests/phpunit/unit-tests/json/non-group-products-form.json b/tools/phpunit/data/forms/non-group-products-form.json similarity index 100% rename from tests/phpunit/unit-tests/json/non-group-products-form.json rename to tools/phpunit/data/forms/non-group-products-form.json diff --git a/tests/phpunit/unit-tests/json/number-fields.json b/tools/phpunit/data/forms/number-fields.json similarity index 100% rename from tests/phpunit/unit-tests/json/number-fields.json rename to tools/phpunit/data/forms/number-fields.json diff --git a/tests/phpunit/unit-tests/json/repeater-consent-form.json b/tools/phpunit/data/forms/repeater-consent-form.json similarity index 100% rename from tests/phpunit/unit-tests/json/repeater-consent-form.json rename to tools/phpunit/data/forms/repeater-consent-form.json diff --git a/tests/phpunit/unit-tests/json/repeater-empty-form.json b/tools/phpunit/data/forms/repeater-empty-form.json similarity index 100% rename from tests/phpunit/unit-tests/json/repeater-empty-form.json rename to tools/phpunit/data/forms/repeater-empty-form.json diff --git a/tests/phpunit/data/forms/standard.json b/tools/phpunit/data/forms/standard.json similarity index 100% rename from tests/phpunit/data/forms/standard.json rename to tools/phpunit/data/forms/standard.json diff --git a/tests/phpunit/data/images/test-media.png b/tools/phpunit/data/images/test-media.png similarity index 100% rename from tests/phpunit/data/images/test-media.png rename to tools/phpunit/data/images/test-media.png diff --git a/tests/phpunit/unit-tests/json/options-settings.json b/tools/phpunit/data/pdf/options-settings.json similarity index 100% rename from tests/phpunit/unit-tests/json/options-settings.json rename to tools/phpunit/data/pdf/options-settings.json diff --git a/tests/phpunit/unit-tests/json/shortcode-data.json b/tools/phpunit/data/pdf/shortcode-data.json similarity index 100% rename from tests/phpunit/unit-tests/json/shortcode-data.json rename to tools/phpunit/data/pdf/shortcode-data.json diff --git a/tests/phpunit/gravityforms-factory.php b/tools/phpunit/gravityforms-factory.php similarity index 86% rename from tests/phpunit/gravityforms-factory.php rename to tools/phpunit/gravityforms-factory.php index aa37bb8cb..8fe689884 100644 --- a/tests/phpunit/gravityforms-factory.php +++ b/tools/phpunit/gravityforms-factory.php @@ -19,7 +19,7 @@ class GF_UnitTest_Factory { public $form_filename; - function __construct( $form_filename = "" ) { + function __construct( $form_filename = '' ) { $this->form_filename = $form_filename; $this->form = new GF_UnitTest_Factory_For_Form( $this ); $this->entry = new GF_UnitTest_Factory_For_Entry( $this ); @@ -35,10 +35,10 @@ function __construct( $factory = null ) { $filename = $this->factory->form_filename; if ( empty( $filename ) ) { - $filename = "standard.json"; + $filename = 'standard.json'; } - $form_json = file_get_contents( dirname( __FILE__ ) . "/data/forms/" . $filename ); + $form_json = file_get_contents( __DIR__ . '/data/forms/' . $filename ); $forms = json_decode( $form_json, true ); $form = $forms[0]; @@ -77,7 +77,7 @@ function get_form_by_id( $form_id ) { * @return array A form array as returned by Gravity Forms */ function import_and_get( $filename ) { - $form_json = file_get_contents( dirname( __FILE__ ) . "/data/forms/" . $filename ); + $form_json = file_get_contents( __DIR__ . '/data/forms/' . $filename ); $forms = json_decode( $form_json, true ); $form = $forms[0]; @@ -96,9 +96,9 @@ function create_many_random( $count, $form_id ) { $form = $this->factory->form->get_form_by_id( $form_id ); $results = []; - for ( $i = 0; $i < $count; $i++ ) { + for ( $i = 0; $i < $count; $i ++ ) { $entry = $this->generate_random_entry_object( $form ); - $entry["form_id"] = $form_id; + $entry['form_id'] = $form_id; $results[] = $this->create( $entry ); } @@ -107,60 +107,33 @@ function create_many_random( $count, $form_id ) { function generate_random_entry_object( $form ) { - $fields = $form["fields"]; + $fields = $form['fields']; foreach ( $fields as $field ) { /* @var GF_Field $field */ $type = GFFormsModel::get_input_type( $field ); - if ( in_array( $type, [ "html", "page", "section" ] ) ) { + if ( in_array( $type, [ 'html', 'page', 'section' ] ) ) { continue; } $inputs = $field->get_entry_inputs(); if ( is_array( $inputs ) ) { foreach ( $inputs as $index => $input ) { - $entry[ (string) $input["id"] ] = isset( $field["choices"] ) && is_array( $field["choices"] ) ? $field["choices"][ $index ]["value"] : $this->_get_random_value( $field ); + $entry[ (string) $input['id'] ] = isset( $field['choices'] ) && is_array( $field['choices'] ) ? $field['choices'][ $index ]['value'] : $this->_get_random_value( $field ); } } else { - $entry[ (string) $field["id"] ] = $this->_get_random_value( $field ); + $entry[ (string) $field['id'] ] = $this->_get_random_value( $field ); } } return $entry; } - private function _get_random_value( $field ) { - $type = GFFormsModel::get_input_type( $field ); - switch ( $type ) { - case "number" : - $value = rand( 0, 10 ); - break; - case "date" : - $value = date( 'Y-m-d', strtotime( '+' . mt_rand( 0, 30 ) . ' days' ) ); - break; - case "time" : - $ampm = [ "am", "pm" ]; - $value = sprintf( "%02d:%02d %s", rand( 1, 12 ), rand( 1, 60 ), $ampm[ array_rand( $ampm ) ] ); - break; - case "list" : - $value = serialize( [ "testvalue" . uniqid(), "testvalue" . uniqid(), "testvalue" . uniqid() ] ); - break; - case "website" : - $value = "http://website" . uniqid() . ".com"; - break; - case "phone" : - $value = sprintf( "(%03d)%03d-%04d", rand( 1, 999 ), rand( 1, 999 ), rand( 1, 9999 ) ); - break; - default : - $value = "testvalue" . uniqid(); - } - - return $value; - } - function get_entry_by_id( $entry_id ) { return $this->get_object_by_id( $entry_id ); - } function create_object( $entry ) { - return GFAPI::add_entry( $entry ); -} + } + + function create_object( $entry ) { + return GFAPI::add_entry( $entry ); + } /** * Imports and returns an entry from a json file. @@ -171,7 +144,7 @@ function get_entry_by_id( $entry_id ) { * @return array */ public function import_and_get( $filename, $form_id ) { - $entry = json_decode( file_get_contents( dirname( __FILE__ ) . "/data/forms/" . $filename ), true ); + $entry = json_decode( file_get_contents( __DIR__ . '/data/forms/' . $filename ), true ); return $this->create_and_get( [ 'form_id' => $form_id ], $entry ); } @@ -182,12 +155,39 @@ function update_object( $entry_id, $entry ) { return GFAPI::update_entry( $entry ); } - - function get_object_by_id( $entry_id ) { return GFAPI::get_entry( $entry_id ); } + private function _get_random_value( $field ) { + $type = GFFormsModel::get_input_type( $field ); + switch ( $type ) { + case 'number' : + $value = rand( 0, 10 ); + break; + case 'date' : + $value = date( 'Y-m-d', strtotime( '+' . mt_rand( 0, 30 ) . ' days' ) ); + break; + case 'time' : + $ampm = [ 'am', 'pm' ]; + $value = sprintf( '%02d:%02d %s', rand( 1, 12 ), rand( 1, 60 ), $ampm[ array_rand( $ampm ) ] ); + break; + case 'list' : + $value = serialize( [ 'testvalue' . uniqid(), 'testvalue' . uniqid(), 'testvalue' . uniqid() ] ); + break; + case 'website' : + $value = 'http://website' . uniqid() . '.com'; + break; + case 'phone' : + $value = sprintf( '(%03d)%03d-%04d', rand( 1, 999 ), rand( 1, 999 ), rand( 1, 9999 ) ); + break; + default : + $value = 'testvalue' . uniqid(); + } + + return $value; + } + } class GF_UnitTest_Factory_For_Pdf extends GF_UnitTest_Factory_For_Thing { @@ -323,7 +323,7 @@ abstract function update_object( $object, $fields ); function create_many( $count, $args = [], $generation_definitions = null ) { $results = []; - for ( $i = 0; $i < $count; $i++ ) { + for ( $i = 0; $i < $count; $i ++ ) { $results[] = $this->create( $args, $generation_definitions ); } @@ -362,7 +362,7 @@ function __construct( $template_string = '%s', $start = 1 ) { function next() { $generated = sprintf( $this->template_string, $this->next ); - $this->next++; + $this->next ++; return $generated; } diff --git a/tests/phpunit/wp-tests-config.php b/tools/phpunit/wp-tests-config.php similarity index 99% rename from tests/phpunit/wp-tests-config.php rename to tools/phpunit/wp-tests-config.php index cdccd3366..8ad5e975d 100644 --- a/tests/phpunit/wp-tests-config.php +++ b/tools/phpunit/wp-tests-config.php @@ -137,4 +137,4 @@ function getenv_docker( $env, $default ) { if ( ! defined( 'ABSPATH' ) ) { define( 'ABSPATH', '/var/www/html/' ); define( 'WP_DEFAULT_THEME', 'default' ); -} \ No newline at end of file +} diff --git a/tools/potomatic/dictionaries/dictionary.json b/tools/potomatic/dictionaries/dictionary.json new file mode 100644 index 000000000..35389152b --- /dev/null +++ b/tools/potomatic/dictionaries/dictionary.json @@ -0,0 +1,11 @@ +{ + "WordPress": "WordPress", + "Gravity Forms": "Gravity Forms", + "REST API": "REST API", + "Block Editor": "Block Editor", + "Multisite": "Multisite", + "Gravity PDF": "Gravity PDF", + "https://gravitypdf.com": "https://gravitypdf.com", + "Blue Liquid Designs": "Blue Liquid Designs", + "https://blueliquiddesigns.com.au": "https://blueliquiddesigns.com.au" +} diff --git a/tools/potomatic/translate.sh b/tools/potomatic/translate.sh new file mode 100644 index 000000000..bf0279eb2 --- /dev/null +++ b/tools/potomatic/translate.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash + +POTOMATIC_OPENAI_API_KEY=$1 + +# Add new variables / override existing if .env file exists +if [ -f ".env" ]; then + set -a + source .env + set +a +fi + +if [ "$POTOMATIC_OPENAI_API_KEY" == "" ]; then + echo "usage: $0 " + exit 1 +fi + +# Rebuild Pot File +yarn i10n:make-pot + +# AI Translation +yarn i10n:translate -- --abort-on-failure --api-key=$POTOMATIC_OPENAI_API_KEY +if [ "$?" != 0 ]; then + exit 1 +fi + +# Build MO/PHP/JSON +yarn i10n:make-mo +yarn i10n:make-json +yarn i10n:make-php diff --git a/bin/build.sh b/tools/release/build.sh similarity index 50% rename from bin/build.sh rename to tools/release/build.sh index 76b031f4b..f88b02f43 100755 --- a/bin/build.sh +++ b/tools/release/build.sh @@ -13,6 +13,9 @@ PACKAGE_DIR="${TMP_DIR}${VERSION}" WORKING_DIR=$PWD PACKAGE_NAME="gravity-pdf" +# Ensure a fresh build +rm -f -r "${PACKAGE_DIR}" + # Create the working directory mkdir -p ${PACKAGE_DIR} @@ -20,8 +23,9 @@ mkdir -p ${PACKAGE_DIR} git archive HEAD ${BRANCH} --output ${PACKAGE_DIR}/package.tar.gz tar -zxf ${PACKAGE_DIR}/package.tar.gz --directory ${PACKAGE_DIR} && rm -f ${PACKAGE_DIR}/package.tar.gz -# Run Composer -yarn install --cwd ${PACKAGE_DIR} +# Run Build +yarn install --frozen-lockfile --cwd ${PACKAGE_DIR} +yarn i10n yarn --cwd ${PACKAGE_DIR} build # Install all dependencies (including dev) @@ -29,49 +33,42 @@ yarn --cwd ${PACKAGE_DIR} build composer install --prefer-dist --working-dir ${PACKAGE_DIR} # Run vendor cleanup - Ensures that there's no dev dependencies on production -PLUGIN_DIR="$PACKAGE_DIR" bash ./bin/vendor-cleanup.sh +PLUGIN_DIR="$PACKAGE_DIR" bash ./tools/php-scoper/cleanup.sh # Cleanup Node JS rm -f -R ${PACKAGE_DIR}/node_modules # Cleanup additional build files FILES=( -"${PACKAGE_DIR}/composer.json" -"${PACKAGE_DIR}/composer.lock" -"${PACKAGE_DIR}/package.json" -"${PACKAGE_DIR}/yarn.lock" -"${PACKAGE_DIR}/.babelrc" -"${PACKAGE_DIR}/webpack.config.js" -"${PACKAGE_DIR}/php-scoper.phar" -"${PACKAGE_DIR}/vendor_prefixed/.gitkeep" -"${PACKAGE_DIR}/.nvmrc" -"${PACKAGE_DIR}/.wp-env.json" -"${PACKAGE_DIR}/.testcaferc.js" -"${PACKAGE_DIR}/.eslintignore" -"${PACKAGE_DIR}/.eslintrc.js" -"${PACKAGE_DIR}/babel.config.js" -"${PACKAGE_DIR}/.browserslistrc" +"composer.json" +"composer.lock" +"package.json" +"yarn.lock" +".gitignore" +".stylelintrc.json" +"webpack.config.js" +".nvmrc" +".env.example" +"tsconfig.json" +".browserslistrc" +".eslintignore" +".eslintrc.js" +".gitattributes" +"babel.config.js" +"jest.config.js" ) +echo "$PWD" for i in "${FILES[@]}" do - rm -f ${i} + rm -f "${PACKAGE_DIR}/${i}" done -rm -f -R "${PACKAGE_DIR}/src/assets/scss" -rm -f -R "${PACKAGE_DIR}/src/assets/js" -rm -f -R "${PACKAGE_DIR}/bin" -rm -f -R "${PACKAGE_DIR}/.php-scoper" -rm -f -R "${PACKAGE_DIR}/webpack-configs" +rm -f -R "${PACKAGE_DIR}/tmp" rm -f -R "${PACKAGE_DIR}/tools" +rm -f -R "${PACKAGE_DIR}/.claude" -# Generate language files -cd "${PACKAGE_DIR}" -npm install --global wp-pot-cli -wp-pot --domain gravity-pdf --src 'src/**/*.php' --src 'pdf.php' --src 'api.php' --src 'gravity-pdf-updater.php' --package 'Gravity PDF' --dest-file src/assets/languages/gravity-pdf.pot > /dev/null - -# Create zip package -cd "../" +cd "${PACKAGE_DIR}/../" rm -r -f "${PACKAGE_NAME}" mv ${VERSION} "${PACKAGE_NAME}" diff --git a/bin/json-payload.sh b/tools/release/json-payload.sh similarity index 100% rename from bin/json-payload.sh rename to tools/release/json-payload.sh diff --git a/tools/wp-env/development.json b/tools/wp-env/development.json new file mode 100644 index 000000000..a8f6f2d0e --- /dev/null +++ b/tools/wp-env/development.json @@ -0,0 +1,28 @@ +{ + "$schema": "https://schemas.wp.org/trunk/wp-env.json", + "core": "https://wordpress.org/latest.zip", + "phpVersion": "8.5", + "plugins": [], + "mappings": { + "wp-cli.yml": "./tools/wp-env/wp-cli.yml", + "wp-content/mu-plugins": "./tools/mu-plugins", + "wp-content/plugins/gravityforms": "./vendor/gravity/gravityforms", + "wp-content/plugins/gravity-pdf": "." + }, + "config": { + "WP_DEBUG": true, + "WP_DEBUG_DISPLAY": true, + "WP_DEBUG_LOG": "/var/www/html/wp-content/plugins/gravity-pdf/tmp/debug.log", + "SCRIPT_DEBUG": true + }, + "testsEnvironment": false, + "env": { + "tests": { + "port": 8701 + } + }, + "lifecycleScripts": { + "afterStart": "yarn wp-env run cli wp plugin activate gravityforms gravity-pdf && yarn wp-env run cli wp rewrite structure '/%postname%/' --hard", + "afterReset": "yarn wp-env run cli wp plugin activate gravityforms gravity-pdf && yarn wp-env run cli wp rewrite structure '/%postname%/' --hard" + } +} diff --git a/tools/wp-env/integration.json b/tools/wp-env/integration.json new file mode 100644 index 000000000..a2c52bda0 --- /dev/null +++ b/tools/wp-env/integration.json @@ -0,0 +1,28 @@ +{ + "$schema": "https://schemas.wp.org/trunk/wp-env.json", + "core": "https://wordpress.org/nightly-builds/wordpress-latest.zip", + "phpVersion": "8.5", + "plugins": [], + "mappings": { + "wp-cli.yml": "./tools/wp-env/wp-cli.yml", + "wp-content/mu-plugins": "./tools/mu-plugins", + "wp-content/plugins/gravityforms": "./vendor/gravity/gravityforms", + "wp-content/plugins/gravityformspolls": "./vendor/gravity/gravityformspolls", + "wp-content/plugins/gravityformsquiz": "./vendor/gravity/gravityformsquiz", + "wp-content/plugins/gravityformssurvey": "./vendor/gravity/gravityformssurvey", + "wp-content/plugins/gravity-pdf": "." + }, + "config": { + "WP_DEBUG": true, + "WP_DEBUG_DISPLAY": false, + "WP_DEBUG_LOG": "/var/www/html/wp-content/plugins/gravity-pdf/tmp/debug.log", + "TEST_SUITE": true, + "SCRIPT_DEBUG": true + }, + "testsEnvironment": false, + "env": { + "tests": { + "port": 8703 + } + } +} diff --git a/webpack-configs/development.js b/webpack-configs/development.js deleted file mode 100644 index 8f24b62b4..000000000 --- a/webpack-configs/development.js +++ /dev/null @@ -1,12 +0,0 @@ -const MiniCssExtractPlugin = require('mini-css-extract-plugin') - -module.exports = { - mode: 'development', - devtool: 'eval-source-map', - plugins: [ - new MiniCssExtractPlugin({ - filename: 'assets/css/gfpdf-styles.min.css', - chunkFilename: '[id].css' - }) - ] -} diff --git a/webpack-configs/production.js b/webpack-configs/production.js deleted file mode 100644 index 1f1d9a388..000000000 --- a/webpack-configs/production.js +++ /dev/null @@ -1,27 +0,0 @@ -const MiniCssExtractPlugin = require('mini-css-extract-plugin') -const CssMinimizerPlugin = require('css-minimizer-webpack-plugin') -const TerserPlugin = require('terser-webpack-plugin') - -module.exports = { - mode: 'production', - devtool: false, - plugins: [ - new MiniCssExtractPlugin({ - filename: 'assets/css/gfpdf-styles.min.css', - chunkFilename: '[id].min.css' - }), - new TerserPlugin({ - extractComments: false, - parallel: true, - terserOptions: { - ecma: 6 - } - }) - ], - optimization: { - minimize: true, - minimizer: [ - new CssMinimizerPlugin() - ] - } -} diff --git a/webpack.config.js b/webpack.config.js index f9130152b..f300fa78d 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,5 +1,5 @@ -const defaultConfig = require( '@wordpress/scripts/config/webpack.config' ); -const { resolve } = require( 'path' ); +const defaultConfig = require('@wordpress/scripts/config/webpack.config'); +const { resolve } = require('path'); module.exports = { ...defaultConfig, @@ -8,10 +8,14 @@ module.exports = { 'gfpdf-entries': './src/assets/js/legacy/gfpdf-entries.js', admin: './src/assets/js/admin/bootstrap.js', }, + optimization: { + ...defaultConfig.optimization, + concatenateModules: false, + }, output: { ...defaultConfig.output, filename: '[name].min.js', - path: resolve( process.cwd(), 'build/assets' ), + path: resolve(process.cwd(), 'build/assets'), }, externals: { ...defaultConfig.externals, From aeddc1a90877425b58aa68d697f671f17dee6299 Mon Sep 17 00:00:00 2001 From: Jake Jackson Date: Thu, 16 Apr 2026 14:03:02 +1000 Subject: [PATCH 3/5] Update for WordPress 7.0 and PHP 8.5 compatibility --- src/Helper/Helper_Abstract_Fields.php | 2 +- .../Component/FontManager/_font-manager.scss | 182 +++++++++--------- .../scss/Component/HelpTab/_help-tab.scss | 36 ++-- src/assets/scss/Component/_button.scss | 20 +- src/assets/scss/Component/_color-picker.scss | 6 +- src/assets/scss/Component/_rich-text.scss | 19 -- .../scss/Component/_template-manager.scss | 4 + src/assets/scss/Pages/_pdf-settings.scss | 16 +- .../Test_Controller_Custom_Fonts.php | 16 +- .../Controller/Test_Controller_Settings.php | 4 +- .../Helper/Fields/Test_Field_Image_Choice.php | 4 +- .../Helper/Fields/Test_Field_Survey.php | 4 +- .../unit-tests/Model/Test_Model_Settings.php | 37 ++-- .../phpunit/unit-tests/Statics/Test_kses.php | 10 +- tests/phpunit/unit-tests/test-ajax.php | 2 +- tests/phpunit/unit-tests/test-api.php | 10 +- tests/phpunit/unit-tests/test-form-data.php | 4 +- .../phpunit/unit-tests/test-form-settings.php | 2 +- .../phpunit/unit-tests/test-gravity-forms.php | 4 +- tests/phpunit/unit-tests/test-logger.php | 2 +- tests/phpunit/unit-tests/test-options-api.php | 2 +- tests/phpunit/unit-tests/test-pre-checks.php | 2 +- tests/phpunit/unit-tests/test-shortcodes.php | 4 +- .../unit-tests/test-slow-pdf-processes.php | 2 +- 24 files changed, 193 insertions(+), 201 deletions(-) diff --git a/src/Helper/Helper_Abstract_Fields.php b/src/Helper/Helper_Abstract_Fields.php index 569945ad0..dc9844187 100644 --- a/src/Helper/Helper_Abstract_Fields.php +++ b/src/Helper/Helper_Abstract_Fields.php @@ -242,7 +242,7 @@ final public function get_value() { * @credit Zack Katz (Gravity View author) * @fixed Gravity Forms 1.9.13.25 */ - if ( class_exists( 'GFCache' ) && version_compare( GFCommon::$version, '1.9.13.25', '<' ) ) { + if ( class_exists( 'GFCache' ) && version_compare( \GFForms::$version, '1.9.13.25', '<' ) ) { GFCache::set( 'GFFormsModel::get_lead_field_value_' . $this->entry['id'] . '_' . $this->field->id, false, false, 0 ); } diff --git a/src/assets/scss/Component/FontManager/_font-manager.scss b/src/assets/scss/Component/FontManager/_font-manager.scss index 452677ff0..310c1d916 100644 --- a/src/assets/scss/Component/FontManager/_font-manager.scss +++ b/src/assets/scss/Component/FontManager/_font-manager.scss @@ -176,127 +176,125 @@ } } - form { - h2 { - font-size: 1.8em; - margin: 0.5rem 0; + h2 { + font-size: 1.8em; + margin: 0.5rem 0; - & + p { - margin: 0; - } + & + p { + margin: 0; } + } - label { - display: block; - margin-top: 1rem; - font-size: 1rem; - font-weight: 600; + label { + display: block; + margin-top: 1rem; + font-size: 1rem; + font-weight: 600; - & + p { - margin: 0.325rem 0; - } + & + p { + margin: 0.325rem 0; } + } - .required { - color: base.$validation-error-color; - font-size: 0.8rem; - } + .required { + color: base.$validation-error-color; + font-size: 0.8rem; + } - #gfpdf-font-files-setting { - display: grid; - grid-template-columns: 50% 50%; - grid-template-rows: 1fr 1fr; - gap: 1rem; - margin: 0.75rem 0; - width: 96%; + #gfpdf-font-files-setting { + display: grid; + grid-template-columns: 50% 50%; + grid-template-rows: 1fr 1fr; + gap: 1rem; + margin: 0.75rem 0; + width: 96%; - a { - color: unset; + a { + color: unset; - &:focus { - box-shadow: unset; - } + &:focus { + box-shadow: unset; } + } - .drop-zone { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - border: 5px dashed base.$lighter-highlight-color; - height: 160px; - transition: all 0.3s ease-out; + .drop-zone { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + border: 5px dashed base.$lighter-highlight-color; + height: 160px; + transition: all 0.3s ease-out; - &:hover, - &.active { - background-color: base.$lighter-highlight-color; - border: 5px solid base.$lighter-highlight-color; + &:hover, + &.active { + background-color: base.$lighter-highlight-color; + border: 5px solid base.$lighter-highlight-color; - .dashicons { - background-color: #ffffff; - color: base.$highlight-color; - } - } - - &:focus { - outline: none; - border: 5px dashed base.$default-text-color; + .dashicons { + background-color: #ffffff; + color: base.$highlight-color; } + } - &.required { - border: 5px dashed base.$error-color; - - .dashicons { - background-color: base.$error-color; - color: #ffffff; - } + &:focus { + outline: none; + border: 5px dashed base.$default-text-color; + } - &:focus { - border-color: base.$default-text-color; - } - } + &.required { + border: 5px dashed base.$error-color; - &.error { - background-color: base.$validation-error-color; - border-color: base.$validation-error-color; + .dashicons { + background-color: base.$error-color; color: #ffffff; } - input { - display: none; + &:focus { + border-color: base.$default-text-color; } + } + + &.error { + background-color: base.$validation-error-color; + border-color: base.$validation-error-color; + color: #ffffff; + } + + input { + display: none; + } - .gfpdf-font-filename { - overflow: hidden; - text-align: center; + .gfpdf-font-filename { + overflow: hidden; + text-align: center; - &.required { - color: base.$validation-error-color; - } + &.required { + color: base.$validation-error-color; } + } - .dashicons { - width: 70px; - height: 70px; - margin: 0.675rem; - background-color: base.$lighter-highlight-color; - border-radius: 50%; - font-size: 3.2rem; - color: base.$highlight-color; - cursor: pointer; + .dashicons { + width: 70px; + height: 70px; + margin: 0.675rem; + background-color: base.$lighter-highlight-color; + border-radius: 50%; + font-size: 3.2rem; + color: base.$highlight-color; + cursor: pointer; - &:before { - margin-left: -1px; - vertical-align: middle; - } + &:before { + margin-left: -1px; + vertical-align: middle; } + } - .dashicons-trash { - font-size: 2.9rem; + .dashicons-trash { + font-size: 2.9rem; - &:before { - margin-left: 3px; - } + &:before { + margin-left: 3px; } } } diff --git a/src/assets/scss/Component/HelpTab/_help-tab.scss b/src/assets/scss/Component/HelpTab/_help-tab.scss index 89d1379a1..17340587d 100644 --- a/src/assets/scss/Component/HelpTab/_help-tab.scss +++ b/src/assets/scss/Component/HelpTab/_help-tab.scss @@ -47,14 +47,14 @@ text-align: center; .button-large { - background: #007cba; + background: var(--wp-admin-theme-color, '#007cba'); border: none; - height: 35px; - line-height: 33px; - padding: 0 17px 9px; + height: 40px; + line-height: 40px; + padding: 0 16px; &:hover { - background: #0071a1; + background: var(--wp-admin-theme-color-darker-10, '#0071a1'); } } } @@ -89,6 +89,8 @@ background: #fff; box-shadow: 0 1px 1px 0 rgba(85, 95, 110, .2); padding: 16px 16px 16px 46px; + min-height: 40px; + line-height: normal; vertical-align: middle; white-space: normal; font-size: inherit; @@ -130,7 +132,6 @@ border: 0; border-radius: 4px 0 0 4px; background-color: hsla(0, 0%, 100%, 0); - padding-top: 16px; width: 46px; height: 100%; vertical-align: middle; @@ -176,7 +177,6 @@ border: 0; background: none; cursor: pointer; - padding-top: 8px; font-size: inherit; -webkit-user-select: none; -moz-user-select: none; @@ -222,7 +222,7 @@ padding-block: 1rem; .group-name { - color: #2a31a3; + color: var(--wp-admin-theme-color-darker-20, '#2a31a3'); font-size: 0.85rem; font-weight: 600; line-height: 32px; @@ -245,12 +245,12 @@ text-decoration: none; mark { - color: #2a31a3; + color: var(--wp-admin-theme-color-darker-20, '#2a31a3'); background: none; } &:hover { - background-color: #2a31a3; + background-color: var(--wp-admin-theme-color-darker-20, '#2a31a3'); mark { color: #fff; @@ -270,11 +270,6 @@ text-overflow: ellipsis; } } - - .hit-action { - color: #fff; - display: flex; - } } } @@ -315,19 +310,10 @@ font-size: 0.75rem; } } - - .hit-action { - align-items: center; - color: rgb(150, 159, 175); - display: none; - height: 22px; - stroke-width: 1.4; - width: 22px; - } } } } } } } -} \ No newline at end of file +} diff --git a/src/assets/scss/Component/_button.scss b/src/assets/scss/Component/_button.scss index 50eab98e9..11c03f1db 100644 --- a/src/assets/scss/Component/_button.scss +++ b/src/assets/scss/Component/_button.scss @@ -2,14 +2,30 @@ #tab_PDF { + .button:not(.wp-editor-wrap .button):not(.wp-picker-container .button) { + @include button.reset; + line-height: 2.95; + + &:not(.primary):hover { + border-color: unset; + background-color: unset; + } + } + /* Template and Font Manager Advanced Button */ - #gpdf-advance-template-selector, #gpdf-advance-font-manager-selector { + #gfpdf-template-container, #gfpdf-font-manager-container { display: inline-block; vertical-align: top; button { @include button.reset; - line-height: 2.95; + min-height: 32px; + line-height: 2.30769231; + + &.primary:hover { + background: #242748; + border-color: #242748; + } } } } diff --git a/src/assets/scss/Component/_color-picker.scss b/src/assets/scss/Component/_color-picker.scss index b3f04c346..c036e716b 100644 --- a/src/assets/scss/Component/_color-picker.scss +++ b/src/assets/scss/Component/_color-picker.scss @@ -3,13 +3,14 @@ #tab_PDF { .wp-picker-container { - button { + .button { padding: 0 0 0 35px; border-width: 1px; border-style: solid; border-color: rgb(144, 146, 178); border-image: initial; height: auto; + line-height: 2.7; .wp-color-result-text { font-size: 0.875rem; @@ -24,7 +25,8 @@ input[type="text"] { width: 5.25rem; font-size: 1rem; + height: 42px; } } } -} \ No newline at end of file +} diff --git a/src/assets/scss/Component/_rich-text.scss b/src/assets/scss/Component/_rich-text.scss index 983e4b305..bfa303248 100644 --- a/src/assets/scss/Component/_rich-text.scss +++ b/src/assets/scss/Component/_rich-text.scss @@ -1,5 +1,3 @@ -@use '../Mixins/button'; - #tab_PDF { /* Rich Text field */ @@ -12,21 +10,4 @@ top: 3rem; } } - - .wp-editor-wrap { - .wp-editor-tools { - button { - @include button.reset; - margin: 0; - } - - .wp-editor-tabs button { - margin-left: 5px; - } - } - - .quicktags-toolbar .button { - @include button.reset; - } - } } diff --git a/src/assets/scss/Component/_template-manager.scss b/src/assets/scss/Component/_template-manager.scss index ff7e00f85..5962c9607 100644 --- a/src/assets/scss/Component/_template-manager.scss +++ b/src/assets/scss/Component/_template-manager.scss @@ -26,6 +26,10 @@ display: block; } + &.active .theme-name { + background: #1d2327; + } + .theme-actions { opacity: 1; left: inherit; diff --git a/src/assets/scss/Pages/_pdf-settings.scss b/src/assets/scss/Pages/_pdf-settings.scss index b006e2bec..b5f697543 100644 --- a/src/assets/scss/Pages/_pdf-settings.scss +++ b/src/assets/scss/Pages/_pdf-settings.scss @@ -12,6 +12,10 @@ } /* Merge tag box */ + .gform-settings-input__container--with-merge-tag { + width: 100%; + } + .all-merge-tags { &.textarea { .tooltip-merge-tag { @@ -45,17 +49,7 @@ .gfpdf-gf-2-6 { .gfpdf-settings-field-wrapper { .wp-editor-wrap { - margin-right: 0rem; - } - } - - .wp-media-buttons { - .all-merge-tags { - top: -0.15rem; - } - - .gform-icon--merge-tag { - font-size: 2.25rem; + margin-right: 0; } } } diff --git a/tests/phpunit/unit-tests/Controller/Test_Controller_Custom_Fonts.php b/tests/phpunit/unit-tests/Controller/Test_Controller_Custom_Fonts.php index 402e7ec6a..0fc151d97 100644 --- a/tests/phpunit/unit-tests/Controller/Test_Controller_Custom_Fonts.php +++ b/tests/phpunit/unit-tests/Controller/Test_Controller_Custom_Fonts.php @@ -87,7 +87,7 @@ public function set_up() { foreach ( $fonts as $font ) { $tmp_font = get_temp_dir() . $font; - copy( __DIR__ . '/../fonts/' . $font, $tmp_font ); + copy( PDF_PLUGIN_DIR . '/tools/phpunit/data/fonts/' . $font, $tmp_font ); $this->test_fonts[] = $tmp_font; } @@ -196,7 +196,7 @@ public function test_add_item_font_validation_failed() { $request->set_param( 'label', 'Font' ); /* JSON file masquerading as a ttf file */ - $test_file = __DIR__ . '/../json/all-form-fields.json'; + $test_file = PDF_PLUGIN_DIR . '/tools/phpunit/data/forms/all-form-fields.json'; $_FILES = [ 'regular' => [ @@ -215,7 +215,7 @@ public function test_add_item_font_validation_failed() { $this->assertSame( 400, $response->get_status() ); /* TTF file masquerading as a JSON file */ - $test_file = __DIR__ . '/../fonts/DejaVuSans.ttf'; + $test_file = PDF_PLUGIN_DIR . '/tools/phpunit/data/fonts/DejaVuSans.ttf'; $_FILES = [ 'regular' => [ @@ -301,7 +301,7 @@ public function test_update_item_permission_failed() { GPDFAPI::add_pdf_font( [ 'font_name' => 'Lato', - 'regular' => __DIR__ . '/../fonts/DejaVuSans.ttf', + 'regular' => PDF_PLUGIN_DIR . '/tools/phpunit/data/fonts/DejaVuSans.ttf', ] ); @@ -318,7 +318,7 @@ public function test_update_item_basic_validation_failed() { GPDFAPI::add_pdf_font( [ 'font_name' => 'Lato', - 'regular' => __DIR__ . '/../fonts/DejaVuSans.ttf', + 'regular' => PDF_PLUGIN_DIR . '/tools/phpunit/data/fonts/DejaVuSans.ttf', ] ); @@ -349,7 +349,7 @@ public function test_update_item_font_validation_failed() { GPDFAPI::add_pdf_font( [ 'font_name' => 'Lato', - 'regular' => __DIR__ . '/../fonts/DejaVuSans.ttf', + 'regular' => PDF_PLUGIN_DIR . '/tools/phpunit/data/fonts/DejaVuSans.ttf', ] ); @@ -358,7 +358,7 @@ public function test_update_item_font_validation_failed() { $request = new WP_REST_Request( 'POST', '/' . Helper_Data::REST_API_BASENAME . 'v1/fonts/lato' ); /* JSON file masquerading as a ttf file */ - $test_file = __DIR__ . '/../json/all-form-fields.json'; + $test_file = PDF_PLUGIN_DIR . '/tools/phpunit/data/forms/all-form-fields.json'; $_FILES = [ 'regular' => [ @@ -377,7 +377,7 @@ public function test_update_item_font_validation_failed() { $this->assertSame( 400, $response->get_status() ); /* TTF file masquerading as a JSON file */ - $test_file = __DIR__ . '/../fonts/DejaVuSans.ttf'; + $test_file = PDF_PLUGIN_DIR . '/tools/phpunit/data/fonts/DejaVuSans.ttf'; $_FILES = [ 'regular' => [ diff --git a/tests/phpunit/unit-tests/Controller/Test_Controller_Settings.php b/tests/phpunit/unit-tests/Controller/Test_Controller_Settings.php index 4a94e0357..64b4a62ff 100644 --- a/tests/phpunit/unit-tests/Controller/Test_Controller_Settings.php +++ b/tests/phpunit/unit-tests/Controller/Test_Controller_Settings.php @@ -34,6 +34,8 @@ public function set_up() { parent::set_up(); + remove_all_actions( 'init' ); + $model = $gfpdf->singleton->get_class( 'Model_Settings' ); $view = $gfpdf->singleton->get_class( 'View_Settings' ); @@ -61,7 +63,7 @@ public function test_bulk_license_check_schedule_with_addons() { ); $addon->init(); - $this->controller->add_filters(); + $this->controller->init(); do_action( 'init' ); $this->assertNotFalse( wp_next_scheduled( 'gfpdf_bulk_license_check' ) ); diff --git a/tests/phpunit/unit-tests/Helper/Fields/Test_Field_Image_Choice.php b/tests/phpunit/unit-tests/Helper/Fields/Test_Field_Image_Choice.php index c7b03d9fa..8d122d432 100644 --- a/tests/phpunit/unit-tests/Helper/Fields/Test_Field_Image_Choice.php +++ b/tests/phpunit/unit-tests/Helper/Fields/Test_Field_Image_Choice.php @@ -64,8 +64,8 @@ public function set_up() { protected function get_choices( $id ) { $wp_factory = static::factory(); - $media_id1 = $wp_factory->attachment->create_upload_object( __DIR__ . '/../../../data/images/test-media.png' ); - $media_id2 = $wp_factory->attachment->create_upload_object( __DIR__ . '/../../../data/images/test-media.png' ); + $media_id1 = $wp_factory->attachment->create_upload_object( PDF_PLUGIN_DIR . '/tools/phpunit/data/images/test-media.png' ); + $media_id2 = $wp_factory->attachment->create_upload_object( PDF_PLUGIN_DIR . '/tools/phpunit/data/images/test-media.png' ); $choices = [ [ diff --git a/tests/phpunit/unit-tests/Helper/Fields/Test_Field_Survey.php b/tests/phpunit/unit-tests/Helper/Fields/Test_Field_Survey.php index 169cd96ba..d6f5410c9 100644 --- a/tests/phpunit/unit-tests/Helper/Fields/Test_Field_Survey.php +++ b/tests/phpunit/unit-tests/Helper/Fields/Test_Field_Survey.php @@ -53,7 +53,7 @@ public function set_up() { public function test_html() { $html = $this->pdf_field->html(); - $this->assertStringContainsString( "", $html ); - $this->assertStringContainsString( "", $html ); + $this->assertStringContainsString( '
', $html ); + $this->assertStringContainsString( '', $html ); } } diff --git a/tests/phpunit/unit-tests/Model/Test_Model_Settings.php b/tests/phpunit/unit-tests/Model/Test_Model_Settings.php index 6bdfc21ed..ce9047dc8 100644 --- a/tests/phpunit/unit-tests/Model/Test_Model_Settings.php +++ b/tests/phpunit/unit-tests/Model/Test_Model_Settings.php @@ -46,6 +46,8 @@ public function set_up() { parent::set_up(); + remove_all_actions( 'init' ); + $this->model = new Model_Settings( $gfpdf->gform, $gfpdf->log, $gfpdf->notices, $gfpdf->options, $gfpdf->data, $gfpdf->misc, $gfpdf->templates ); $this->addon = new ModelSettingsAddon( @@ -78,30 +80,31 @@ public function set_up() { $this->addon1->set_edd_download_id( 10 ); - $this->addon->init(); - $this->addon1->init(); + $data = \GPDFAPI::get_data_class(); + $data->updater = null; + $data->addon = []; } public function tear_down() { parent::tear_down(); + $data = \GPDFAPI::get_data_class(); + $data->updater = null; $data->addon = []; } public function test_license_bulk_get_version_api_params_skipped() { /* Check skipped when not initialized */ - $data = \GPDFAPI::get_data_class(); - $data->updater = null; - $data->addon = []; $this->assertTrue( $this->model->licensing_bulk_get_version_api_params( true ) ); } public function test_license_bulk_get_version_api_params_core_plugin() { - $data = \GPDFAPI::get_data_class(); - $data->addon = []; + $this->addon->init(); + do_action( 'init' ); $params = $this->model->licensing_bulk_get_version_api_params( [] ); + $this->assertArrayHasKey( 'edd_action', $params ); $this->assertArrayHasKey( 'products', $params ); $this->assertCount( 1, $params['products'] ); @@ -111,24 +114,27 @@ public function test_license_bulk_get_version_api_params_core_plugin() { } public function test_licensing_bulk_get_version_api_response() { + $this->addon->init(); + $this->addon1->init(); + do_action( 'init' ); $params = $this->model->licensing_bulk_get_version_api_params( [] ); $this->assertArrayHasKey( 'edd_action', $params ); $this->assertArrayHasKey( 'products', $params ); - $this->assertCount( 3, $params['products'] ); + $this->assertCount( 2, $params['products'] ); $this->assertArrayHasKey( 'license', $params['products'][0] ); $this->assertArrayHasKey( 'item_id', $params['products'][0] ); $this->assertArrayHasKey( 'url', $params['products'][0] ); $this->assertArrayHasKey( 'license', $params['products'][1] ); $this->assertArrayHasKey( 'item_id', $params['products'][1] ); $this->assertArrayHasKey( 'url', $params['products'][1] ); - $this->assertArrayHasKey( 'license', $params['products'][2] ); - $this->assertArrayHasKey( 'item_id', $params['products'][2] ); - $this->assertArrayHasKey( 'url', $params['products'][2] ); } public function test_licensing_bulk_license_check_success() { + $this->addon->init(); + $this->addon1->init(); + do_action( 'init' ); $data = \GPDFAPI::get_data_class(); @@ -164,13 +170,13 @@ public function test_licensing_bulk_license_check_success() { } public function test_licensing_bulk_license_check_no_addons() { - $data = \GPDFAPI::get_data_class(); - $data->addon = []; - $this->assertFalse( $this->model->licensing_bulk_license_check() ); } public function test_licensing_bulk_license_check_bad_status_code() { + $this->addon->init(); + $this->addon1->init(); + do_action( 'init' ); wp_clear_scheduled_hook( 'gfpdf_bulk_license_check' ); @@ -198,6 +204,9 @@ public function test_licensing_bulk_license_check_bad_status_code() { } public function test_licensing_bulk_license_check_bad_response() { + $this->addon->init(); + $this->addon1->init(); + do_action( 'init' ); wp_clear_scheduled_hook( 'gfpdf_bulk_license_check' ); diff --git a/tests/phpunit/unit-tests/Statics/Test_kses.php b/tests/phpunit/unit-tests/Statics/Test_kses.php index 9e0495eba..0692ae7ff 100644 --- a/tests/phpunit/unit-tests/Statics/Test_kses.php +++ b/tests/phpunit/unit-tests/Statics/Test_kses.php @@ -73,8 +73,8 @@ public function provider_parse_pdf_tags_and_attributes(): array { [ '' ], [ '' ], [ '' ], - [ '' ], - [ 'Content More content' ], + [ '' ], + [ 'Content More content' ], [ 'Content here' ], [ 'Content here' ], [ '' ], @@ -82,9 +82,9 @@ public function provider_parse_pdf_tags_and_attributes(): array { [ '' ], [ '' ], [ '' ], - [ '' ], - [''], - [ '' ], + [ '' ], + [ ''], + [ '' ], [ '' ], [ 'Icon'] ]; diff --git a/tests/phpunit/unit-tests/test-ajax.php b/tests/phpunit/unit-tests/test-ajax.php index 082042b28..d99c93523 100644 --- a/tests/phpunit/unit-tests/test-ajax.php +++ b/tests/phpunit/unit-tests/test-ajax.php @@ -79,7 +79,7 @@ public static function set_up_before_class() { * @since 4.0 */ private function import_form() { - $json = json_decode( trim( file_get_contents( dirname( __FILE__ ) . '/json/form-settings.json' ) ), true ); + $json = json_decode( trim( file_get_contents( PDF_PLUGIN_DIR . '/tools/phpunit/data/forms/form-settings.json' ) ), true ); $this->form_id = GFAPI::add_form( $json ); } diff --git a/tests/phpunit/unit-tests/test-api.php b/tests/phpunit/unit-tests/test-api.php index 6bce6aba4..74344762e 100644 --- a/tests/phpunit/unit-tests/test-api.php +++ b/tests/phpunit/unit-tests/test-api.php @@ -207,12 +207,12 @@ public function test_likert_table() { $entry = $GLOBALS['GFPDF_Test']->entries['all-form-fields'][0]; $table = GPDFAPI::likert_table( $entry, 26, true ); - $this->assertNotFalse( strpos( $table, "class='gsurvey-likert-choice-label'" ) ); + $this->assertStringContainsString( 'class="gsurvey-likert-choice-label"', $table ); ob_start(); GPDFAPI::likert_table( $entry, 26 ); $table = ob_get_clean(); - $this->assertNotFalse( strpos( $table, "class='gsurvey-likert-choice-label'" ) ); + $this->assertStringContainsString( 'class="gsurvey-likert-choice-label"', $table ); } /** @@ -236,7 +236,7 @@ public function test_add_pdf_font() { $this->assertEquals( 'font_validation_error', $results->get_error_code() ); /* Test we correctly install the font */ - $ttf_file = __DIR__ . '/fonts/Chewy.ttf'; + $ttf_file = PDF_PLUGIN_DIR . '/tools/phpunit/data/fonts/Chewy.ttf'; $font = [ 'font_name' => 'Test', @@ -254,7 +254,7 @@ public function test_add_pdf_font() { } public function test_add_pdf_font_duplicate() { - $ttf_file = __DIR__ . '/fonts/Chewy.ttf'; + $ttf_file = PDF_PLUGIN_DIR . '/tools/phpunit/data/fonts/Chewy.ttf'; $font = [ 'font_name' => 'Test', @@ -284,7 +284,7 @@ public function test_delete_pdf_font() { $this->assertEquals( 'invalid_font_id', $results->get_error_code() ); /* Add a font and then see if we can remove it */ - $ttf_file = __DIR__ . '/fonts/Chewy.ttf'; + $ttf_file = PDF_PLUGIN_DIR . '/tools/phpunit/data/fonts/Chewy.ttf'; $font = [ 'font_name' => 'Test', diff --git a/tests/phpunit/unit-tests/test-form-data.php b/tests/phpunit/unit-tests/test-form-data.php index c1442a7ab..e6fa2f30c 100644 --- a/tests/phpunit/unit-tests/test-form-data.php +++ b/tests/phpunit/unit-tests/test-form-data.php @@ -267,7 +267,7 @@ public function test_field_number() { * Test that number fields will use the local currency set in the entry */ public function test_field_number_currency() { - $form_json = json_decode( trim( file_get_contents( dirname( __FILE__ ) . '/json/number-fields.json' ) ), true ); + $form_json = json_decode( trim( file_get_contents( PDF_PLUGIN_DIR . '/tools/phpunit/data/forms/number-fields.json' ) ), true ); $form_id = GFAPI::add_form( $form_json ); $entry_id = GFAPI::add_entry( @@ -1536,7 +1536,7 @@ public function test_empty_fields() { * Ensure the Product data calculations are correct when using Euros (or similar comma/decimal switched currency) */ public function test_euro_product_data() { - $json = json_decode( trim( file_get_contents( dirname( __FILE__ ) . '/json/all-form-euro-product-entry.json' ) ), true ); + $json = json_decode( trim( file_get_contents( PDF_PLUGIN_DIR . '/tools/phpunit/data/entries/all-form-euro-product-entry.json' ) ), true ); $json['form_id'] = $this->form['id']; $entry_id = GFAPI::add_entry( $json ); $entry = GFAPI::get_entry( $entry_id ); diff --git a/tests/phpunit/unit-tests/test-form-settings.php b/tests/phpunit/unit-tests/test-form-settings.php index f639ef899..260c714fb 100644 --- a/tests/phpunit/unit-tests/test-form-settings.php +++ b/tests/phpunit/unit-tests/test-form-settings.php @@ -473,7 +473,7 @@ public function test_settings_sanitize() { remove_all_filters( 'gfpdf_form_settings_sanitize_hidden' ); /* get faux input data */ - $input = json_decode( file_get_contents( dirname( __FILE__ ) . '/json/form-settings-sample-input.json' ), true ); + $input = json_decode( file_get_contents( PDF_PLUGIN_DIR . '/tools/phpunit/data/forms/form-settings-sample-input.json' ), true ); /* Set up global filters we can check */ add_filter( diff --git a/tests/phpunit/unit-tests/test-gravity-forms.php b/tests/phpunit/unit-tests/test-gravity-forms.php index b235ad9c3..85fefc868 100644 --- a/tests/phpunit/unit-tests/test-gravity-forms.php +++ b/tests/phpunit/unit-tests/test-gravity-forms.php @@ -492,13 +492,13 @@ public function provider_ip_testing() { } /** - * Test that GFCommon::$version will produce + * Test that \GFForms::$version will produce * the expected result. * * @since 3.6 */ public function test_gf_version() { - $version = GFCommon::$version; + $version = \GFForms::$version; /* which the version number is a string before we try to match it */ $this->assertEquals( true, is_string( $version ) ); diff --git a/tests/phpunit/unit-tests/test-logger.php b/tests/phpunit/unit-tests/test-logger.php index 456470c58..130a95ca9 100644 --- a/tests/phpunit/unit-tests/test-logger.php +++ b/tests/phpunit/unit-tests/test-logger.php @@ -66,7 +66,7 @@ public function test_register_gf_logger() { } /** - * @since 6.14.0 + * @since 6.15.0 */ public function test_logs_rotate() { $gf_logger = \GFLogging::get_instance(); diff --git a/tests/phpunit/unit-tests/test-options-api.php b/tests/phpunit/unit-tests/test-options-api.php index c9f10ce26..4260954a9 100644 --- a/tests/phpunit/unit-tests/test-options-api.php +++ b/tests/phpunit/unit-tests/test-options-api.php @@ -56,7 +56,7 @@ public function set_up() { $this->options = \GPDFAPI::get_options_class(); /* load settings in database */ - update_option( 'gfpdf_settings', json_decode( file_get_contents( dirname( __FILE__ ) . '/json/options-settings.json' ), true ) ); + update_option( 'gfpdf_settings', json_decode( file_get_contents( PDF_PLUGIN_DIR . '/tools/phpunit/data/pdf/options-settings.json' ), true ) ); /* Load a form / form PDF settings into database */ $this->form_id = $GLOBALS['GFPDF_Test']->form['form-settings']['id']; diff --git a/tests/phpunit/unit-tests/test-pre-checks.php b/tests/phpunit/unit-tests/test-pre-checks.php index 22139b579..dc19a13b1 100644 --- a/tests/phpunit/unit-tests/test-pre-checks.php +++ b/tests/phpunit/unit-tests/test-pre-checks.php @@ -106,7 +106,7 @@ public function test_check_wordpress( $min_version, $test_wp_version, $expected */ public function test_check_gravityforms( $min_version, $test_gf_version, $expected ) { /* set up our current Gravity Forms version and the min version */ - GFCommon::$version = $test_gf_version; + \GFForms::$version = $test_gf_version; $this->gravitypdf->required_gf_version = $min_version; /* run our test */ diff --git a/tests/phpunit/unit-tests/test-shortcodes.php b/tests/phpunit/unit-tests/test-shortcodes.php index 1825a7d55..87e7c2359 100644 --- a/tests/phpunit/unit-tests/test-shortcodes.php +++ b/tests/phpunit/unit-tests/test-shortcodes.php @@ -388,7 +388,7 @@ public function test_gravitypdf_notification() { public function test_add_shortcode_attr() { /* Setup our test data */ - $content = json_decode( trim( file_get_contents( dirname( __FILE__ ) . '/json/shortcode-data.json' ) ), true ); + $content = json_decode( trim( file_get_contents( PDF_PLUGIN_DIR . '/tools/phpunit/data/pdf/shortcode-data.json' ) ), true ); $shortcodes = $this->model->get_shortcode_information( 'gravitypdf', $content ); @@ -481,7 +481,7 @@ public function test_gravitypdf_redirect_confirmation_shortcode_processing() { * @since 4.0 */ public function test_get_shortcode_information() { - $content = json_decode( trim( file_get_contents( dirname( __FILE__ ) . '/json/shortcode-data.json' ) ), true ); + $content = json_decode( trim( file_get_contents( PDF_PLUGIN_DIR . '/tools/phpunit/data/pdf/shortcode-data.json' ) ), true ); $this->assertCount( 0, $this->model->get_shortcode_information( 'gravitypdf', [] ) ); diff --git a/tests/phpunit/unit-tests/test-slow-pdf-processes.php b/tests/phpunit/unit-tests/test-slow-pdf-processes.php index 029003592..03765dee4 100644 --- a/tests/phpunit/unit-tests/test-slow-pdf-processes.php +++ b/tests/phpunit/unit-tests/test-slow-pdf-processes.php @@ -74,7 +74,7 @@ public function set_up() { $this->controller = new Controller_PDF( $this->model, $this->view, $gfpdf->gform, $gfpdf->log, $gfpdf->misc ); - $fonts = glob( dirname( __FILE__ ) . '/fonts/' . '*.[tT][tT][fF]' ); + $fonts = glob( PDF_PLUGIN_DIR . '/tools/phpunit/data/fonts/' . '*.[tT][tT][fF]' ); $fonts = ( is_array( $fonts ) ) ? $fonts : []; foreach ( $fonts as $font ) { From 3c087eec05ccb78b4a7c9b71f0e9f586751c3700 Mon Sep 17 00:00:00 2001 From: Jake Jackson Date: Thu, 16 Apr 2026 14:03:02 +1000 Subject: [PATCH 4/5] Fix various bugs --- .claude/CLAUDE.md | 5 + .github/workflows/playwright-e2e.yml | 9 +- api.php | 1 + pdf.php | 86 ++---------- src/Controller/Controller_Custom_Fonts.php | 1 + src/Controller/Controller_Export_Entries.php | 1 + src/Controller/Controller_Settings.php | 2 +- src/Helper/Fields/Field_Products.php | 2 +- src/Helper/Helper_Abstract_Addon.php | 45 ++++--- src/Helper/Helper_Abstract_Options.php | 12 +- src/Helper/Helper_Abstract_View.php | 2 + src/Helper/Helper_Data.php | 21 ++- src/Helper/Helper_Options_Fields.php | 14 ++ src/Helper/Helper_PDF.php | 1 + src/Helper/Helper_PDF_List_Table.php | 7 +- .../Licensing/EDD_SL_Plugin_Updater.php | 15 ++- src/Model/Model_Form_Settings.php | 3 +- src/Model/Model_Install.php | 2 + src/Model/Model_PDF.php | 1 + src/Model/Model_Settings.php | 15 ++- src/Model/Model_System_Report.php | 1 + src/Model/Model_Templates.php | 2 + src/Model/Model_Uninstall.php | 6 +- src/View/View_Settings.php | 1 + src/View/View_System_Report.php | 4 + src/View/html/GravityForms/fieldset.php | 2 +- src/View/html/GravityForms/settings_field.php | 53 +++++--- src/View/html/PDF/entry_detailed_pdf.php | 1 + src/View/html/Settings/general.php | 2 +- src/View/html/Settings/help.php | 2 +- src/View/html/Settings/licence-info.php | 1 + src/View/html/Settings/tools.php | 2 +- src/assets/js/react/api/fontManager.js | 6 +- .../react/components/FontManager/AddFont.js | 30 ++--- .../FontManager/AddUpdateFontFooter.js | 12 +- .../components/FontManager/FontListItems.js | 4 +- .../components/FontManager/FontManager.js | 3 +- .../components/FontManager/FontManagerBody.js | 18 ++- .../components/FontManager/FontVariant.js | 15 ++- .../FontManager/FontVariantLabel.js | 18 +-- .../react/components/FontManager/SearchBox.js | 4 +- .../components/FontManager/TemplateTooltip.js | 2 +- .../components/FontManager/UpdateFont.js | 31 ++--- .../js/react/components/Help/DisplayResult.js | 19 --- .../components/Template/TemplateContainer.js | 2 +- src/assets/js/react/sagas/coreFonts.js | 2 +- src/assets/js/react/sagas/fontManager.js | 24 ++-- src/assets/js/react/sagas/templates.js | 4 +- src/bootstrap.php | 3 +- .../core/global-settings/license.spec.ts | 124 +++++++++++++++++ .../core/global-settings/tools.spec.ts | 125 ++++++++++++++++++ .../core/pdf-access/inactive.spec.ts | 5 +- .../core/pdf-settings/pdf-settings.spec.ts | 31 +++-- .../permalinks/managers/font-manager.spec.ts | 4 +- .../managers/template-manager.spec.ts | 47 ++++--- tools/mu-plugins/admin-styles.php | 2 +- tools/mu-plugins/gravitypdf.php | 48 ++++++- tools/mu-plugins/requests.php | 91 +++++++++++++ tools/playwright/flaky-tests-reporter.ts | 14 +- tools/playwright/utils/gravityforms.ts | 18 ++- tools/playwright/utils/gravitypdf.ts | 6 +- 61 files changed, 720 insertions(+), 314 deletions(-) create mode 100644 tests/playwright/core/global-settings/license.spec.ts create mode 100644 tests/playwright/core/global-settings/tools.spec.ts create mode 100644 tools/mu-plugins/requests.php diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md index 418d6d208..dca312aeb 100644 --- a/.claude/CLAUDE.md +++ b/.claude/CLAUDE.md @@ -11,6 +11,11 @@ Request → Load Skills → Gather Context → Execute Skills contain critical workflows and protocols not in base context. Loading them first prevents missing key instructions. +### Planning + +When creating plans, always save them to: ./claude/plans/YYYY-MM-DD-.md +Never use the default plan location. Use the ./claude/plans/ directory. + ### Context Management Strategy **Central AI should conserve context to extend pre-compaction capacity**: diff --git a/.github/workflows/playwright-e2e.yml b/.github/workflows/playwright-e2e.yml index c64e8373e..1c66e5e6a 100644 --- a/.github/workflows/playwright-e2e.yml +++ b/.github/workflows/playwright-e2e.yml @@ -94,12 +94,11 @@ jobs: if: success() with: name: test-results - path: ./tmp/artifacts/test-results/chromatic-archives + path: ./tmp/artifacts/test-results - name: Dump log files on failure if: failure() - run: | - yarn wp-env:e2e run wordpress "cp -r /var/www/html/wp-content/uploads/gravity_forms/logs/ /var/www/html/wp-content/plugins/gravity-pdf/tmp/artifacts/logs" + run: yarn wp-env:e2e run wordpress "cp" "-r" "/var/www/html/wp-content/uploads/gravity_forms/logs/" "/var/www/html/wp-content/plugins/gravity-pdf/tmp/artifacts/logs" - name: Upload artifacts on failure uses: actions/upload-artifact@v6 @@ -144,7 +143,7 @@ jobs: run: yarn install --frozen-lockfile - name: Download Playwright test results - uses: actions/download-artifact@v6 + uses: actions/download-artifact@v8 with: name: test-results path: ./test-results @@ -155,5 +154,3 @@ jobs: playwright: true autoAcceptChanges: "development" projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }} - env: - CHROMATIC_ARCHIVE_LOCATION: ./test-results diff --git a/api.php b/api.php index 9dd172946..54b13ab7e 100644 --- a/api.php +++ b/api.php @@ -404,6 +404,7 @@ public static function add_plugin_option( $key, $value ) { /* Check the option doesn't already exist */ if ( null !== $options->get_option( $key, null ) ) { + /* translators: %s: option key name */ return new WP_Error( 'option_exists', esc_html__( 'The option key %s already exists. Use GPDFAPI::update_plugin_option instead', 'gravity-pdf' ) ); } diff --git a/pdf.php b/pdf.php index ca4f51c69..49766703a 100644 --- a/pdf.php +++ b/pdf.php @@ -8,7 +8,7 @@ Plugin URI: https://gravitypdf.com Update URI: https://gravitypdf.com Text Domain: gravity-pdf -Domain Path: /src/assets/languages +Domain Path: /languages Requires at least: 5.3 Requires PHP: 7.3 License: GPL-2.0 @@ -47,13 +47,11 @@ /* * Add our activation hook and deactivation hooks */ - require_once PDF_PLUGIN_DIR . 'src/Controller/Controller_Activation.php'; + require_once __DIR__ . '/src/Controller/Controller_Activation.php'; + require_once __DIR__ . '/gravity-pdf-updater.php'; + register_deactivation_hook( __FILE__, array( 'Controller_Activation', 'deactivation' ) ); - /* If canonical plugin load the plugin updater */ - if ( is_file( __DIR__ . '/gravity-pdf-updater.php' ) ) { - require_once __DIR__ . '/gravity-pdf-updater.php'; - } /** * Plugin initialization class @@ -149,13 +147,7 @@ public function init() { public function plugins_loaded() { /* Register language files early so startup errors can be translated */ - load_plugin_textdomain( 'gravity-pdf', false, dirname( plugin_basename( __FILE__ ) ) . '/src/assets/languages/' ); - - /* Notify administrator current version is not canonical */ - if ( ! is_file( __DIR__ . '/gravity-pdf-updater.php' ) ) { - add_action( 'admin_init', [ $this, 'maybe_display_canonical_plugin_notice' ] ); - add_action( 'after_plugin_row', [ $this, 'maybe_display_canonical_plugin_notice_below_plugin' ], 10, 2 ); - } + load_plugin_textdomain( 'gravity-pdf', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' ); /* Check minimum requirements are met */ $this->is_compatible_wordpress_version(); @@ -220,7 +212,7 @@ public function is_compatible_wordpress_version() { public function check_gravity_forms() { /* Gravity Forms version not compatible */ - if ( ! class_exists( 'GFCommon' ) ) { + if ( ! class_exists( '\GFForms' ) ) { $this->notices[] = static function () { /* translators: 1. HTML Anchor Open Tag 2. HTML Anchor Open Tag 3. Html Anchor Close Tag */ return sprintf( esc_html__( '%1$sGravity Forms%3$s is required to use Gravity PDF. %2$sGet more information%3$s.', 'gravity-pdf' ), '', '', '' ); @@ -229,7 +221,7 @@ public function check_gravity_forms() { return false; } - if ( ! version_compare( GFCommon::$version, $this->required_gf_version, '>=' ) ) { + if ( ! version_compare( \GFForms::$version, $this->required_gf_version, '>=' ) ) { $this->notices[] = function () { /* translators: 1. HTML Anchor Open Tag 2. HTML Anchor Close Tag 3. Plugin version number 4. Html Anchor Open Tag */ return sprintf( esc_html__( '%1$sGravity Forms%2$s version %3$s or higher is required. %4$sGet more information%2$s.', 'gravity-pdf' ), '', '', $this->required_gf_version, '' ); @@ -513,34 +505,9 @@ public function notice_body_content() { * @return void * * @since 6.12 + * @deprecated */ - public function maybe_display_canonical_plugin_notice() { - if ( ! method_exists( '\GFCommon', 'add_dismissible_message' ) ) { - return; - } - - $message = wp_kses( - sprintf( - __( 'The Gravity PDF plugin has a new home! In order to get updates direct from GravityPDF.com %1$syou need to perform a one-time download of the plugin%2$s.', 'gravity-pdf' ), - '', - '', - ), - [ - 'a' => [ - 'href' => true, - 'target' => true, - ], - ] - ); - - \GFCommon::add_dismissible_message( - $message, - 'gravity-pdf-canonical-plugin-notice', - 'warning', - 'install_plugins', - true - ); - } + public function maybe_display_canonical_plugin_notice() {} /** * Notify administrator they are not using the canonical version of Gravity PDF @@ -548,40 +515,9 @@ public function maybe_display_canonical_plugin_notice() { * @return void * * @since 6.12 + * @deprecated */ - public function maybe_display_canonical_plugin_notice_below_plugin( $plugin_file, $plugin_data ) { - if ( ! isset( $plugin_data['TextDomain'] ) || $plugin_data['TextDomain'] !== 'gravity-forms-pdf-extended' ) { - return; - } - - printf( - '', - esc_attr( $plugin_data['slug'] ), - esc_attr( $plugin_data['plugin'] ), - 'active' - ); - - echo ''; - echo ''; - } + public function maybe_display_canonical_plugin_notice_below_plugin( $plugin_file, $plugin_data ) {} } } diff --git a/src/Controller/Controller_Custom_Fonts.php b/src/Controller/Controller_Custom_Fonts.php index 0adb9d69f..29b7305fc 100644 --- a/src/Controller/Controller_Custom_Fonts.php +++ b/src/Controller/Controller_Custom_Fonts.php @@ -543,6 +543,7 @@ protected function does_fonts_support_otl( array $files ): bool { foreach ( $files as $id => $file ) { if ( ! isset( $file['name'] ) || ! is_file( $this->font_dir_path . $file['name'] ) ) { + /* translators: %s: font filename */ $errors[ $id ] = sprintf( __( 'Cannot find %s.', 'gravity-pdf' ), $file['name'] ); continue; } diff --git a/src/Controller/Controller_Export_Entries.php b/src/Controller/Controller_Export_Entries.php index efb010414..f9991e86c 100644 --- a/src/Controller/Controller_Export_Entries.php +++ b/src/Controller/Controller_Export_Entries.php @@ -51,6 +51,7 @@ public function add_pdfs_to_export_fields( $form ) { $form['fields'][] = [ 'id' => 'gpdf_' . $pdf['id'], + /* translators: %s: PDF name */ 'label' => sprintf( __( 'PDF: %s', 'gravity-pdf' ), $pdf['name'] ), ]; } diff --git a/src/Controller/Controller_Settings.php b/src/Controller/Controller_Settings.php index 1cfb36dbe..c4665a56e 100644 --- a/src/Controller/Controller_Settings.php +++ b/src/Controller/Controller_Settings.php @@ -310,7 +310,7 @@ public function disable_tools_on_view_cap( $nav ) { * * @return void * - * @since 6.14.0 + * @since 6.15.0 */ protected function maybe_schedule_network_update_check() { if ( ! is_multisite() || get_current_blog_id() === 1 || is_plugin_active_for_network( PDF_PLUGIN_BASENAME ) ) { diff --git a/src/Helper/Fields/Field_Products.php b/src/Helper/Fields/Field_Products.php index d5b9b5388..a4b7c750c 100644 --- a/src/Helper/Fields/Field_Products.php +++ b/src/Helper/Fields/Field_Products.php @@ -218,7 +218,7 @@ class="subtotal totals"> + class="shipping totals"> diff --git a/src/Helper/Helper_Abstract_Addon.php b/src/Helper/Helper_Abstract_Addon.php index d83ba0a0b..91bdd0c24 100644 --- a/src/Helper/Helper_Abstract_Addon.php +++ b/src/Helper/Helper_Abstract_Addon.php @@ -127,37 +127,37 @@ abstract class Helper_Abstract_Addon { /** * @var EDD_SL_Plugin_Updater - * @since 6.14.0 + * @since 6.15.0 */ protected $plugin_updater; /** * @var string The current license key for this addon - * @since 6.14.0 + * @since 6.15.0 */ protected $license_key = ''; /** * @var string The current license key status (retrieved from the API) for this addon - * @since 6.14.0 + * @since 6.15.0 */ protected $license_key_status = ''; /** * @var string The current license key message for this addon (based on the status) - * @since 6.14.0 + * @since 6.15.0 */ protected $license_key_message = ''; /** * @var bool Whether the addon activated the license based on another addon activation - * @since 6.14.0 + * @since 6.15.0 */ protected $license_auto_activated = false; /** * @var bool Whether the addon deactivated the license based on another addon deactivation - * @since 6.14.0 + * @since 6.15.0 */ protected $license_auto_deactivated = false; @@ -291,12 +291,12 @@ final public function get_addon_documentation_slug() { /** * @return EDD_SL_Plugin_Updater|null - * @since 6.14.0 + * @since 6.15.0 */ public function get_plugin_updater() { $updater = $this->plugin_updater; if ( ! $updater ) { - _doing_it_wrong( __METHOD__, 'This method should not be called before the "init" hook (priority 1)', '6.14.0' ); + _doing_it_wrong( __METHOD__, 'This method should not be called before the "init" hook (priority 1)', '6.15.0' ); } return $updater; @@ -418,13 +418,13 @@ function ( $class_object ) { * * @return void * @since 4.2 - * @depecated 6.14.0 Use self::central_plugin_updater() + * @depecated 6.15.0 Use self::central_plugin_updater() */ public function plugin_updater() {} /** * @return array - * @since 6.14.0 + * @since 6.15.0 */ public function get_default_api_params() { return [ @@ -617,7 +617,7 @@ final public function get_addon_setting_value( string $name, $fallback = '' ) { * @param bool $use_database Fetch license info from the database * * @since 4.2 - * @since 6.14.0 Get license info stored in the object + * @since 6.15.0 Get license info stored in the object */ public function get_license_info( $use_database = false ) { if ( $use_database ) { @@ -645,7 +645,7 @@ public function get_license_info( $use_database = false ) { * @param bool $use_database Whether to update the database or not. A DB update will auto-call Model_Settings::maybe_active_licenses(), which may not be ideal * * @since 4.2 - * @since 6.14.0 Added + * @since 6.15.0 Added */ public function update_license_info( $license_info, $use_database = false ) { $this->license_key = $license_info['license'] ?? ''; @@ -718,7 +718,7 @@ final public function get_license_key() { * * @return false|string * - * @since 6.14.0 + * @since 6.15.0 */ final public function get_license_key_from_constant() { $slug = $this->get_slug(); @@ -770,7 +770,7 @@ final public function get_license_message() { * Whether the addon activated the license based on another addon activation * * @return bool - * @since 6.14.0 + * @since 6.15.0 */ final public function has_license_auto_activated() { return $this->license_auto_activated; @@ -780,7 +780,7 @@ final public function has_license_auto_activated() { * Whether the addon deactivated the license based on another addon deactivation. * * @return bool - * @since 6.14.0 + * @since 6.15.0 */ final public function has_license_auto_deactivated() { return $this->license_auto_deactivated; @@ -794,7 +794,7 @@ final public function has_license_auto_deactivated() { * * @since 4.2 * - * @depreacted 6.14.0 Handled in bulk via Model_Settings::licensing_bulk_license_check() + * @depreacted 6.15.0 Handled in bulk via Model_Settings::licensing_bulk_license_check() */ final public function maybe_schedule_license_check() { if ( ! wp_next_scheduled( 'gfpdf_' . $this->get_slug() . '_license_check' ) ) { @@ -874,7 +874,7 @@ public function schedule_license_check() { * * @return bool * - * @since 6.14.0 + * @since 6.15.0 */ public function update_license_status_from_response( $license_key, $response, $use_database = false ) { $response_code = wp_remote_retrieve_response_code( $response ); @@ -979,6 +979,7 @@ public function license_registration() {
tag, 2: Add-on name, 3: Closing tag, 4: Opening tag, 5: Closing tag */ esc_html__( '%1$sRegister your copy of %2$s%3$s to receive access to automatic upgrades and support. Need a license key? %4$sPurchase one now%5$s.', 'gravity-pdf' @@ -1033,7 +1034,7 @@ public function plugin_row_meta( $links, $file ) { * * @return array The API response and license status * - * @since 6.14.0 + * @since 6.15.0 */ public function activate_license( $license_key = '', $use_database = false ) { @@ -1070,7 +1071,7 @@ public function activate_license( $license_key = '', $use_database = false ) { * * @return void * - * @since 6.14.0 + * @since 6.15.0 */ public function maybe_auto_activate_license( $response, $addon, $use_database ) { /* skip if current addon doing licence activation */ @@ -1103,7 +1104,7 @@ public function maybe_auto_activate_license( $response, $addon, $use_database ) * * @return bool * - * @since 6.14.0 + * @since 6.15.0 */ public function deactivate_license() { $response = wp_remote_post( @@ -1147,7 +1148,7 @@ public function deactivate_license() { * * @return void * - * @since 6.14.0 + * @since 6.15.0 */ public function maybe_auto_deactivate_license( $response, $addon ) { /* skip if current addon doing licence activation */ @@ -1178,7 +1179,7 @@ public function maybe_auto_deactivate_license( $response, $addon ) { /** * Delete the add-on update information * - * @since 6.14.0 + * @since 6.15.0 * @return void */ public function flush_update_cache() { diff --git a/src/Helper/Helper_Abstract_Options.php b/src/Helper/Helper_Abstract_Options.php index 1fcaf9ba6..e7e285b49 100644 --- a/src/Helper/Helper_Abstract_Options.php +++ b/src/Helper/Helper_Abstract_Options.php @@ -1741,7 +1741,7 @@ public function license_callback( $args ) { - start_toggle_input( $toggle, $value ); ?> + start_toggle_input( $toggle, $value, $args['id'] ); ?>
@@ -2065,7 +2065,7 @@ public function rich_editor_callback( $args ) { ?> - start_toggle_input( $toggle, $value ); ?> + start_toggle_input( $toggle, $value, $args['id'] ); ?>
@@ -2464,6 +2464,7 @@ public function hook_callback( $args ) { * */ public function missing_callback( $args ) { + /* translators: %s: setting ID */ echo wp_kses_post( sprintf( __( 'The callback used for the %s setting is missing.', 'gravity-pdf' ), "{$args['id']}" ) ); } @@ -2496,12 +2497,14 @@ public function create_toggle_input( $toggle, $html, $value ) { * * @param string $toggle The text to be used in the toggle * @param string $value Whether the field currently has a value + * @param string $element_id The base ID for the toggle * * @return void * * @since 6.4 + * @since 6.14 Added $element_id */ - public function start_toggle_input( $toggle, $value ) { + public function start_toggle_input( $toggle, $value, $element_id = '' ) { $has_value = ! empty( $value ) ? 1 : 0; ?> @@ -2509,6 +2512,7 @@ public function start_toggle_input( $toggle, $value ) {
'; - echo '

'; - - echo wp_kses( - sprintf( - __( 'The Gravity PDF plugin has a new home! In order to get updates direct from GravityPDF.com %1$syou need to perform a one-time download of the plugin%2$s.', 'gravity-pdf' ), - '', - '', - ), - [ - 'a' => [ - 'href' => true, - 'target' => true, - ], - ] - ); - - echo '

'; - echo '