Merge branch 'trunk' into fix/27902
This commit is contained in:
commit
31d4b8f7e7
|
@ -8,8 +8,12 @@ coverage:
|
|||
range: "50...100"
|
||||
|
||||
status:
|
||||
project: off
|
||||
patch: off
|
||||
project:
|
||||
default:
|
||||
informational: true
|
||||
patch:
|
||||
default:
|
||||
informational: true
|
||||
changes: off
|
||||
|
||||
parsers:
|
||||
|
|
|
@ -13,7 +13,7 @@ There are many ways to contribute to the project!
|
|||
|
||||
If you wish to contribute code, please read the information in the sections below. Then [fork](https://help.github.com/articles/fork-a-repo/) WooCommerce, commit your changes, and [submit a pull request](https://help.github.com/articles/using-pull-requests/) 🎉
|
||||
|
||||
We use the `good first issue` label to mark issues that are suitable for new contributors. You can find all the issues with this label [here](https://github.com/woocommerce/woocommerce/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22).
|
||||
We use the `good first issue` label to mark issues that are suitable for new contributors. You can find all the issues with this label [here](https://github.com/woocommerce/woocommerce/issues?q=is%3Aopen+is%3Aissue+label%3A%22type%3A+good+first+issue%22).
|
||||
|
||||
WooCommerce is licensed under the GPLv3+, and all contributions to the project will be released under the same license. You maintain copyright over any contribution you make, and by submitting a pull request, you are agreeing to release that contribution under the GPLv3+ license.
|
||||
|
||||
|
@ -26,8 +26,8 @@ If you have questions about the process to contribute code or want to discuss de
|
|||
- [Minification of SCSS and JS](https://github.com/woocommerce/woocommerce/wiki/Minification-of-SCSS-and-JS)
|
||||
- [Naming conventions](https://github.com/woocommerce/woocommerce/wiki/Naming-conventions)
|
||||
- [String localisation guidelines](https://github.com/woocommerce/woocommerce/wiki/String-localisation-guidelines)
|
||||
- [Running unit tests](https://github.com/woocommerce/woocommerce/blob/trunk/tests/README.md)
|
||||
- [Running e2e tests](https://github.com/woocommerce/woocommerce/wiki/End-to-end-Testing)
|
||||
- [Running unit tests](https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce/tests/README.md)
|
||||
- [Running e2e tests](https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce/tests/e2e/README.md)
|
||||
|
||||
## Coding Guidelines and Development 🛠
|
||||
|
||||
|
@ -41,15 +41,14 @@ If you have questions about the process to contribute code or want to discuss de
|
|||
- Make sure to write good and detailed commit messages (see [this post](https://chris.beams.io/posts/git-commit/) for more on this) and follow all the applicable sections of the pull request template.
|
||||
- Please avoid modifying the changelog directly or updating the .pot files. These will be updated by the WooCommerce team.
|
||||
|
||||
If you are contributing code to the (Javascript-driven) WooCommerce Admin project or to Gutenberg blocks, note that these are developed in external packages.
|
||||
If you are contributing code to the (Javascript-driven) Gutenberg blocks, note that it's developed in an external package.
|
||||
|
||||
- [WooCommerce Admin](https://github.com/woocommerce/woocommerce-admin)
|
||||
- [Blocks](https://github.com/woocommerce/woocommerce-gutenberg-products-block)
|
||||
|
||||
## Feature Requests 🚀
|
||||
|
||||
Feature requests can be [submitted to our issue tracker](https://github.com/woocommerce/woocommerce/issues/new?template=6-Feature-request.md). Be sure to include a description of the expected behavior and use case, and before submitting a request, please search for similar ones in the closed issues.
|
||||
Feature requests can be [submitted to our issue tracker](https://github.com/woocommerce/woocommerce/issues/new?assignees=&labels=type%3A+enhancement%2Cstatus%3A+awaiting+triage&template=2-enhancement.yml&title=%5BEnhancement%5D%3A+). Be sure to include a description of the expected behavior and use case, and before submitting a request, please search for similar ones in the closed issues.
|
||||
|
||||
Feature request issues will remain closed until we see sufficient interest via comments and [👍 reactions](https://help.github.com/articles/about-discussions-in-issues-and-pull-requests/) from the community.
|
||||
|
||||
You can see a [list of current feature requests which require votes here](https://github.com/woocommerce/woocommerce/issues?q=is%3Aclosed+label%3A%22type%3A+enhancement%22+label%3A%22votes+needed%22+sort%3Areactions-%2B1-desc).
|
||||
You can see a [list of current feature requests which require votes here](https://github.com/woocommerce/woocommerce/issues?q=is%3Aissue+sort%3Areactions-%2B1-desc+label%3A%22needs%3A+votes%22+).
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
name: ✨ Enhancement Request
|
||||
description: If you have an idea to improve an existing feature in core or need something for development (such as a new hook) please let us know or submit a Pull Request!
|
||||
title: "[Enhancement]: "
|
||||
labels: ["type: enhancement"]
|
||||
labels: ["type: enhancement", "status: awaiting triage"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
|
@ -10,7 +10,7 @@ body:
|
|||
|
||||
Please provide us with the information requested in this form.
|
||||
|
||||
Make sure to look through [existing `type: enhancement` issues](https://github.com/woocommerce/woocommerce/issues?q=is%3Aopen+is%3Aissue+label%3A%22type%3A+enhancement%22) and [existing `votes needed` issues](https://github.com/woocommerce/woocommerce/issues?q=is%3Aissue+sort%3Areactions-%2B1-desc+label%3A%22votes+needed%22) to see whether your idea is already being discussed.
|
||||
Make sure to look through [existing `type: enhancement` issues](https://github.com/woocommerce/woocommerce/issues?q=is%3Aopen+is%3Aissue+label%3A%22type%3A+enhancement%22) and [existing `votes needed` issues](https://github.com/woocommerce/woocommerce/issues?q=is%3Aissue+sort%3Areactions-%2B1-desc+label%3A%22needs%3A+votes%22+) to see whether your idea is already being discussed.
|
||||
Feel free to contribute to any existing issues.
|
||||
Search tip: You can filter our issues using [our enhancement label](https://github.com/woocommerce/woocommerce/issues?q=is%3Aissue+label%3A%22type%3A+enhancement%22+).
|
||||
Search tip: Make use of [GitHub's search syntax to refine your search](https://help.github.com/en/github/searching-for-information-on-github/searching-issues-and-pull-requests).
|
||||
|
|
|
@ -6,9 +6,6 @@ contact_links:
|
|||
- name: ❓ Support Question
|
||||
url: https://woocommerce.com/document/woocommerce-self-service-guide/
|
||||
about: If you have a question please see our docs or use our forums, helpdesk, or Slack community!
|
||||
- name: WooCommerce Admin
|
||||
url: https://github.com/woocommerce/woocommerce-admin
|
||||
about: Please report issues for WooCommerce Admin (such as Analytics and Onboarding) directly to it's repository.
|
||||
- name: WooCommerce Blocks
|
||||
url: https://github.com/woocommerce/woocommerce-gutenberg-products-block
|
||||
about: Please report issues for WooCommerce Blocks directly to it's repository.
|
||||
|
|
|
@ -25,13 +25,10 @@ Closes # .
|
|||
* [ ] Have you added an explanation of what your changes do and why you'd like us to include them?
|
||||
* [ ] Have you written new tests for your changes, as applicable?
|
||||
* [ ] Have you successfully run tests with your changes locally?
|
||||
* [ ] Have you created a changelog file by running `pnpm nx affected --target=changelog`?
|
||||
|
||||
<!-- Mark completed items with an [x] -->
|
||||
|
||||
### Changelog entry
|
||||
|
||||
> Enter a summary of all changes on this Pull Request. This will appear in the changelog if accepted.
|
||||
|
||||
### FOR PR REVIEWER ONLY:
|
||||
|
||||
* [ ] I have reviewed that everything is sanitized/escaped appropriately for any SQL or XSS injection possibilities. I made sure Linting is not ignored or disabled.
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
'package: @woocommerce/api':
|
||||
- packages/js/api/**/*
|
||||
|
||||
'package: @woocommerce/e2e-utils':
|
||||
- packages/js/e2e-utils/**/*
|
||||
|
||||
'package: @woocommerce/e2e-environment':
|
||||
- packages/js/e2e-environment/**/*
|
||||
|
||||
'package: @woocommerce/api-core-tests':
|
||||
- packages/js/api-core-tests/**/*
|
||||
|
||||
'package: @woocommerce/e2e-core-tests':
|
||||
- packages/js/e2e-core-tests/**/*
|
||||
|
||||
'package: @woocommerce/admin-e2e-tests':
|
||||
- packages/js/admin-e2e-tests/**/*
|
||||
|
||||
'package: @woocommerce/components':
|
||||
- packages/js/components/**/*
|
||||
|
||||
'package: @woocommerce/csv-export':
|
||||
- packages/js/csv-export/**/*
|
||||
|
||||
'package: @woocommerce/currency':
|
||||
- packages/js/currency/**/*
|
||||
|
||||
'package: @woocommerce/customer-effort-score':
|
||||
- packages/js/customer-effort-score/**/*
|
||||
|
||||
'package: @woocommerce/data':
|
||||
- packages/js/data/**/*
|
||||
|
||||
'package: @woocommerce/date':
|
||||
- packages/js/date/**/*
|
||||
|
||||
'package: dependency-extraction-webpack-plugin':
|
||||
- packages/js/dependency-extraction-webpack-plugin/**/*
|
||||
|
||||
'package: @woocommerce/eslint-plugin':
|
||||
- packages/js/eslint-plugin/**/*
|
||||
|
||||
'package: @woocommerce/experimental':
|
||||
- packages/js/experimental/**/*
|
||||
|
||||
'package: @woocommerce/explat':
|
||||
- packages/js/explat/**/*
|
||||
|
||||
'package: @woocommerce/js-tests':
|
||||
- packages/js/js-tests/**/*
|
||||
|
||||
'package: @woocommerce/navigation':
|
||||
- packages/js/navigation/**/*
|
||||
|
||||
'package: @woocommerce/notices':
|
||||
- packages/js/notices/**/*
|
||||
|
||||
'package: @woocommerce/number':
|
||||
- packages/js/number/**/*
|
||||
|
||||
'package: @woocommerce/onboarding':
|
||||
- packages/js/onboarding/**/*
|
||||
|
||||
'package: @woocommerce/style-build':
|
||||
- packages/js/style-build/**/*
|
||||
|
||||
'package: @woocommerce/tracks':
|
||||
- packages/js/tracks/**/*
|
||||
|
||||
'plugin: woocommerce':
|
||||
- plugins/woocommerce/**/*
|
||||
|
||||
'focus: react admin':
|
||||
- plugins/woocommerce/src/Admin/**/*
|
||||
- plugins/woocommerce/src/Internal/Admin/**/*
|
||||
- plugins/woocommerce-admin/**/*
|
|
@ -9,10 +9,10 @@ on:
|
|||
jobs:
|
||||
build:
|
||||
name: Build release zip file
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ github.event.inputs.ref || github.ref }}
|
||||
- name: Build the zip file
|
||||
|
|
|
@ -5,10 +5,10 @@ on:
|
|||
jobs:
|
||||
build:
|
||||
name: Build release asset
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
- name: Build
|
||||
id: build
|
||||
uses: woocommerce/action-build@trunk
|
||||
|
@ -25,7 +25,7 @@ jobs:
|
|||
if: github.event.release.prerelease == false && github.event.release.draft == false && github.repository_owner == 'woocommerce'
|
||||
name: Update Code Reference
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Invoke Code Reference build and deploy workflow
|
||||
uses: aurelien-baudet/workflow-dispatch@v2
|
||||
|
@ -35,3 +35,16 @@ jobs:
|
|||
token: ${{ secrets.CUSTOM_GH_TOKEN }}
|
||||
ref: refs/heads/trunk
|
||||
inputs: '{ "version": "${{ github.event.release.tag_name }}" }'
|
||||
run-release-smoke-tests:
|
||||
name: Execute Smoke test release
|
||||
needs: build
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Invoke release smoke testing workflow
|
||||
uses: aurelien-baudet/workflow-dispatch@v2
|
||||
with:
|
||||
workflow: Smoke test release
|
||||
repo: ${{ github.repository }}
|
||||
token: ${{ secrets.E2E_WORKFLOW_GH_TOKEN }}
|
||||
ref: refs/heads/trunk
|
||||
inputs: '{ "release_id": "${{ github.event.release.id }}" }'
|
||||
|
|
|
@ -7,24 +7,26 @@ on:
|
|||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
working-directory: plugins/woocommerce
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
jobs:
|
||||
test:
|
||||
name: PHP ${{ matrix.php }} WP ${{ matrix.wp }}
|
||||
timeout-minutes: 15
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 20
|
||||
runs-on: ubuntu-20.04
|
||||
continue-on-error: ${{ matrix.wp == 'nightly' }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
php: [ '7.0', '7.1', '7.2', '7.3', '7.4', '8.0' ]
|
||||
php: [ '7.2', '7.3', '7.4', '8.0' ]
|
||||
wp: [ 'latest' ]
|
||||
include:
|
||||
- wp: nightly
|
||||
php: '7.4'
|
||||
- wp: '5.7'
|
||||
- wp: '5.8'
|
||||
php: 7.2
|
||||
- wp: '5.6'
|
||||
- wp: '5.7'
|
||||
php: 7.2
|
||||
services:
|
||||
database:
|
||||
|
@ -36,7 +38,7 @@ jobs:
|
|||
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=5
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
|
@ -51,25 +53,33 @@ jobs:
|
|||
php --version
|
||||
composer --version
|
||||
|
||||
- name: Get cached composer directories
|
||||
uses: actions/cache@v2
|
||||
- name: Get cached composer and pnpm directories
|
||||
uses: actions/cache@v3
|
||||
id: cache-deps
|
||||
with:
|
||||
path: |
|
||||
./packages
|
||||
./vendor
|
||||
key: ${{ runner.os }}-${{ hashFiles('./composer.lock') }}
|
||||
~/.pnpm-store
|
||||
plugins/woocommerce/packages
|
||||
plugins/woocommerce/**/vendor
|
||||
key: ${{ runner.os }}-npm-composer-${{ hashFiles('**/composer.lock', '**/pnpm-lock.yaml') }}
|
||||
|
||||
- name: Install PNPM and install dependencies
|
||||
run: |
|
||||
npm install -g pnpm
|
||||
pnpm install
|
||||
- name: Install PNPM
|
||||
run: npm install -g pnpm
|
||||
|
||||
- name: Setup and install composer
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Install Composer dependencies
|
||||
if: steps.cache-deps.outputs.cache-hit != 'true'
|
||||
run: pnpm nx composer-install woocommerce
|
||||
|
||||
- name: Build Admin feature config
|
||||
run: pnpm nx build:feature-config woocommerce
|
||||
|
||||
- name: Add PHP8 Compatibility.
|
||||
run: |
|
||||
if [ "$(php -r "echo version_compare(PHP_VERSION,'8.0','>=');")" ]; then
|
||||
cd plugins/woocommerce
|
||||
curl -L https://github.com/woocommerce/phpunit/archive/add-compatibility-with-php8-to-phpunit-7.zip -o /tmp/phpunit-7.5-fork.zip
|
||||
unzip -d /tmp/phpunit-7.5-fork /tmp/phpunit-7.5-fork.zip
|
||||
composer bin phpunit config --unset platform
|
||||
|
@ -80,6 +90,7 @@ jobs:
|
|||
fi
|
||||
|
||||
- name: Init DB and WP
|
||||
working-directory: plugins/woocommerce
|
||||
run: ./tests/bin/install.sh woo_test root root 127.0.0.1 ${{ matrix.wp }}
|
||||
|
||||
- name: Run tests
|
||||
|
|
|
@ -1,70 +1,64 @@
|
|||
name: Mirrors
|
||||
on:
|
||||
push:
|
||||
branches: ['trunk', 'release/**']
|
||||
push:
|
||||
branches: ["trunk", "release/**"]
|
||||
jobs:
|
||||
build:
|
||||
name: Build WooCommerce zip
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Build
|
||||
id: build
|
||||
uses: woocommerce/action-build@trunk
|
||||
env:
|
||||
BUILD_ENV: mirrors
|
||||
|
||||
- name: Upload PR zip
|
||||
uses: actions/upload-artifact@v2
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
name: woocommerce
|
||||
path: ${{ steps.build.outputs.zip_path }}
|
||||
retention-days: 7
|
||||
|
||||
mirror:
|
||||
name: Push to Mirror
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build]
|
||||
steps:
|
||||
- name: Create directories
|
||||
run: |
|
||||
mkdir -p tmp/woocommerce-build
|
||||
mkdir -p monorepo
|
||||
|
||||
- name: Checkout monorepo
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
path: monorepo
|
||||
|
||||
- name: Download WooCommerce ZIP
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: woocommerce
|
||||
path: tmp/woocommerce-build
|
||||
|
||||
- name: Extract and replace WooCommerce zip.
|
||||
working-directory: tmp/woocommerce-build
|
||||
run: |
|
||||
mkdir -p woocommerce/woocommerce-production
|
||||
unzip woocommerce.zip -d woocommerce/woocommerce-production
|
||||
mv woocommerce/woocommerce-production/woocommerce/* woocommerce/woocommerce-production
|
||||
rm -rf woocommerce/woocommerce-production/woocommerce
|
||||
|
||||
- name: Set up mirror
|
||||
working-directory: tmp/woocommerce-build
|
||||
run: |
|
||||
touch mirrors.txt
|
||||
echo "woocommerce/woocommerce-production" >> mirrors.txt
|
||||
|
||||
- name: Push to mirror
|
||||
uses: Automattic/action-push-to-mirrors@v1
|
||||
with:
|
||||
source-directory: ${{ github.workspace }}/monorepo
|
||||
token: ${{ secrets.API_TOKEN_GITHUB }}
|
||||
username: matticbot
|
||||
working-directory: ${{ github.workspace }}/tmp/woocommerce-build
|
||||
timeout-minutes: 5 # 2021-01-18: Successful runs seem to take about half a minute.
|
||||
build:
|
||||
if: github.repository == 'woocommerce/woocommerce'
|
||||
name: Build WooCommerce zip
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
- name: Build
|
||||
id: build
|
||||
uses: woocommerce/action-build@trunk
|
||||
env:
|
||||
BUILD_ENV: mirrors
|
||||
- name: Upload PR zip
|
||||
uses: actions/upload-artifact@v2
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
name: woocommerce
|
||||
path: ${{ steps.build.outputs.zip_path }}
|
||||
retention-days: 7
|
||||
mirror:
|
||||
if: github.repository == 'woocommerce/woocommerce'
|
||||
name: Push to Mirror
|
||||
runs-on: ubuntu-20.04
|
||||
needs: [build]
|
||||
steps:
|
||||
- name: Create directories
|
||||
run: |
|
||||
mkdir -p tmp/woocommerce-build
|
||||
mkdir -p monorepo
|
||||
- name: Checkout monorepo
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
path: monorepo
|
||||
- name: Download WooCommerce ZIP
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: woocommerce
|
||||
path: tmp/woocommerce-build
|
||||
- name: Extract and replace WooCommerce zip.
|
||||
working-directory: tmp/woocommerce-build
|
||||
run: |
|
||||
mkdir -p woocommerce/woocommerce-production
|
||||
unzip woocommerce.zip -d woocommerce/woocommerce-production
|
||||
mv woocommerce/woocommerce-production/woocommerce/* woocommerce/woocommerce-production
|
||||
rm -rf woocommerce/woocommerce-production/woocommerce
|
||||
- name: Set up mirror
|
||||
working-directory: tmp/woocommerce-build
|
||||
run: |
|
||||
touch mirrors.txt
|
||||
echo "woocommerce/woocommerce-production" >> mirrors.txt
|
||||
- name: Push to mirror
|
||||
uses: Automattic/action-push-to-mirrors@v1
|
||||
with:
|
||||
source-directory: ${{ github.workspace }}/monorepo
|
||||
token: ${{ secrets.API_TOKEN_GITHUB }}
|
||||
username: matticbot
|
||||
working-directory: ${{ github.workspace }}/tmp/woocommerce-build
|
||||
timeout-minutes: 5 # 2021-01-18: Successful runs seem to take about half a minute.
|
||||
|
|
|
@ -10,10 +10,10 @@ jobs:
|
|||
fail-fast: false
|
||||
matrix:
|
||||
build: [trunk]
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ matrix.build }}
|
||||
- name: Build
|
||||
|
@ -32,7 +32,7 @@ jobs:
|
|||
max_releases: 1
|
||||
update:
|
||||
name: Update nightly tag commit ref
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Update nightly tag
|
||||
uses: richardsimko/github-tag-action@v1.0.5
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
name: Build zip for PR
|
||||
on: pull_request
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build zip for PR
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Build
|
||||
id: build
|
||||
|
@ -15,7 +19,7 @@ jobs:
|
|||
BUILD_ENV: e2e
|
||||
|
||||
- name: Upload PR zip
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
|
@ -25,7 +29,7 @@ jobs:
|
|||
|
||||
e2e-tests-run:
|
||||
name: Runs E2E tests.
|
||||
runs-on: ubuntu-18.04
|
||||
runs-on: ubuntu-20.04
|
||||
needs: [build]
|
||||
steps:
|
||||
- name: Create dirs.
|
||||
|
@ -33,28 +37,17 @@ jobs:
|
|||
mkdir -p code/woocommerce
|
||||
mkdir -p package/woocommerce
|
||||
mkdir -p tmp/woocommerce
|
||||
mkdir -p node_modules
|
||||
|
||||
- name: Checkout code.
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: package/woocommerce
|
||||
|
||||
- name: Install PNPM and install dependencies
|
||||
working-directory: package/woocommerce
|
||||
run: |
|
||||
npm install -g pnpm
|
||||
pnpm install
|
||||
|
||||
- name: Load docker images and start containers.
|
||||
working-directory: package/woocommerce/plugins/woocommerce
|
||||
run: pnpx wc-e2e docker:up
|
||||
|
||||
- name: Move current directory to code. We will install zip file in this dir later.
|
||||
run: mv ./package/woocommerce/plugins/woocommerce/* ./code/woocommerce
|
||||
|
||||
- name: Download WooCommerce ZIP.
|
||||
uses: actions/download-artifact@v2
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: woocommerce
|
||||
path: tmp
|
||||
|
@ -65,11 +58,23 @@ jobs:
|
|||
unzip woocommerce.zip -d woocommerce
|
||||
mv woocommerce/woocommerce/* ../package/woocommerce/plugins/woocommerce/
|
||||
|
||||
- name: Install dependencies again
|
||||
- name: Cache modules
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.pnpm-store
|
||||
key: ${{ runner.os }}-npm-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||
|
||||
- name: Install PNPM
|
||||
run: npm install -g pnpm
|
||||
|
||||
- name: Install dependencies
|
||||
working-directory: package/woocommerce
|
||||
run: |
|
||||
npm install -g pnpm
|
||||
pnpm install
|
||||
run: pnpm install
|
||||
|
||||
- name: Load docker images and start containers.
|
||||
working-directory: package/woocommerce/plugins/woocommerce
|
||||
run: pnpm exec wc-e2e docker:up
|
||||
|
||||
- name: Run tests command.
|
||||
working-directory: package/woocommerce/plugins/woocommerce
|
||||
|
@ -77,11 +82,20 @@ jobs:
|
|||
WC_E2E_SCREENSHOTS: 1
|
||||
E2E_SLACK_TOKEN: ${{ secrets.E2E_SLACK_TOKEN }}
|
||||
E2E_SLACK_CHANNEL: ${{ secrets.E2E_SLACK_CHANNEL }}
|
||||
run: pnpx wc-e2e test:e2e
|
||||
run: pnpm exec wc-e2e test:e2e
|
||||
|
||||
- name: Archive E2E test screenshots
|
||||
uses: actions/upload-artifact@v3
|
||||
if: always()
|
||||
with:
|
||||
name: E2E Screenshots
|
||||
path: package/woocommerce/plugins/woocommerce/tests/e2e/screenshots
|
||||
if-no-files-found: ignore
|
||||
retention-days: 5
|
||||
|
||||
api-tests-run:
|
||||
name: Runs API tests.
|
||||
runs-on: ubuntu-18.04
|
||||
runs-on: ubuntu-20.04
|
||||
needs: [build]
|
||||
steps:
|
||||
- name: Create dirs.
|
||||
|
@ -89,28 +103,17 @@ jobs:
|
|||
mkdir -p code/woocommerce
|
||||
mkdir -p package/woocommerce
|
||||
mkdir -p tmp/woocommerce
|
||||
mkdir -p node_modules
|
||||
|
||||
- name: Checkout code.
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: package/woocommerce
|
||||
|
||||
- name: Install PNPM and install dependencies
|
||||
working-directory: package/woocommerce
|
||||
run: |
|
||||
npm install -g pnpm
|
||||
pnpm install
|
||||
|
||||
- name: Load docker images and start containers.
|
||||
working-directory: package/woocommerce/plugins/woocommerce
|
||||
run: pnpx wc-e2e docker:up
|
||||
|
||||
- name: Move current directory to code. We will install zip file in this dir later.
|
||||
run: mv ./package/woocommerce/plugins/woocommerce/* ./code/woocommerce
|
||||
|
||||
- name: Download WooCommerce ZIP.
|
||||
uses: actions/download-artifact@v2
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: woocommerce
|
||||
path: tmp
|
||||
|
@ -121,11 +124,23 @@ jobs:
|
|||
unzip woocommerce.zip -d woocommerce
|
||||
mv woocommerce/woocommerce/* ../package/woocommerce/plugins/woocommerce/
|
||||
|
||||
- name: Install dependencies again
|
||||
- name: Cache modules
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.pnpm-store
|
||||
key: ${{ runner.os }}-npm-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||
|
||||
- name: Install PNPM
|
||||
run: npm install -g pnpm
|
||||
|
||||
- name: Install dependencies
|
||||
working-directory: package/woocommerce
|
||||
run: |
|
||||
npm install -g pnpm
|
||||
pnpm install
|
||||
run: pnpm install
|
||||
|
||||
- name: Load docker images and start containers.
|
||||
working-directory: package/woocommerce/plugins/woocommerce
|
||||
run: pnpm exec wc-e2e docker:up
|
||||
|
||||
- name: Run tests command.
|
||||
working-directory: package/woocommerce/plugins/woocommerce
|
||||
|
@ -133,4 +148,75 @@ jobs:
|
|||
BASE_URL: http://localhost:8084
|
||||
USER_KEY: admin
|
||||
USER_SECRET: password
|
||||
run: pnpx wc-api-tests test api
|
||||
run: pnpm exec wc-api-tests test api
|
||||
|
||||
- name: Upload API test report
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: api-test-report---pr-${{ github.event.number }}
|
||||
path: |
|
||||
package/woocommerce/packages/js/api-core-tests/allure-results
|
||||
package/woocommerce/packages/js/api-core-tests/allure-report
|
||||
retention-days: 7
|
||||
|
||||
k6-tests-run:
|
||||
name: Runs k6 Performance tests
|
||||
runs-on: ubuntu-20.04
|
||||
needs: [build]
|
||||
steps:
|
||||
- name: Create dirs.
|
||||
run: |
|
||||
mkdir -p code/woocommerce
|
||||
mkdir -p package/woocommerce
|
||||
mkdir -p tmp/woocommerce
|
||||
|
||||
- name: Checkout code.
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: package/woocommerce
|
||||
|
||||
- name: Move current directory to code. We will install zip file in this dir later.
|
||||
run: mv ./package/woocommerce/plugins/woocommerce/* ./code/woocommerce
|
||||
|
||||
- name: Download WooCommerce ZIP.
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: woocommerce
|
||||
path: tmp
|
||||
|
||||
- name: Extract and replace WooCommerce zip.
|
||||
working-directory: tmp
|
||||
run: |
|
||||
unzip woocommerce.zip -d woocommerce
|
||||
mv woocommerce/woocommerce/* ../package/woocommerce/plugins/woocommerce/
|
||||
|
||||
- name: Cache modules
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.pnpm-store
|
||||
key: ${{ runner.os }}-npm-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||
|
||||
- name: Install PNPM
|
||||
run: npm install -g pnpm
|
||||
|
||||
- name: Install dependencies
|
||||
working-directory: package/woocommerce
|
||||
run: pnpm install
|
||||
|
||||
- name: Workaround to use initialization file with prepopulated data.
|
||||
working-directory: package/woocommerce/plugins/woocommerce/tests/e2e/docker
|
||||
run: |
|
||||
cp init-sample-products.sh initialize.sh
|
||||
|
||||
- name: Load docker images and start containers.
|
||||
working-directory: package/woocommerce/plugins/woocommerce
|
||||
run: pnpm exec wc-e2e docker:up
|
||||
|
||||
- name: Install k6
|
||||
run: |
|
||||
curl https://github.com/grafana/k6/releases/download/v0.33.0/k6-v0.33.0-linux-amd64.tar.gz -L | tar xvz --strip-components 1
|
||||
|
||||
- name: Run k6 tests
|
||||
run: |
|
||||
./k6 run package/woocommerce/plugins/woocommerce/tests/performance/tests/gh-action-pr-requests.js
|
||||
|
|
|
@ -4,12 +4,14 @@ on:
|
|||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
working-directory: plugins/woocommerce
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
jobs:
|
||||
test:
|
||||
name: Code coverage (PHP 7.4, WP Latest)
|
||||
timeout-minutes: 15
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 20
|
||||
runs-on: ubuntu-20.04
|
||||
services:
|
||||
database:
|
||||
image: mysql:5.6
|
||||
|
@ -20,7 +22,7 @@ jobs:
|
|||
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=5
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 100
|
||||
|
||||
|
@ -37,22 +39,30 @@ jobs:
|
|||
php --version
|
||||
composer --version
|
||||
|
||||
- name: Get cached composer directories
|
||||
uses: actions/cache@v2
|
||||
- name: Get cached composer and pnpm directories
|
||||
uses: actions/cache@v3
|
||||
id: cache-deps
|
||||
with:
|
||||
path: |
|
||||
./packages
|
||||
./vendor
|
||||
key: ${{ runner.os }}-${{ hashFiles('./composer.lock') }}
|
||||
~/.pnpm-store
|
||||
plugins/woocommerce/packages
|
||||
plugins/woocommerce/**/vendor
|
||||
key: ${{ runner.os }}-npm-composer-${{ hashFiles('**/composer.lock', '**/pnpm-lock.yaml') }}
|
||||
|
||||
- name: Install PNPM and install dependencies
|
||||
run: |
|
||||
npm install -g pnpm
|
||||
pnpm install
|
||||
- name: Install PNPM
|
||||
run: npm install -g pnpm
|
||||
|
||||
- name: Setup and install composer
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Install Composer dependencies
|
||||
if: steps.cache-deps.outputs.cache-hit != 'true'
|
||||
run: pnpm nx composer-install woocommerce
|
||||
|
||||
- name: Build Admin feature config
|
||||
run: |
|
||||
pnpm nx build:feature-config woocommerce
|
||||
|
||||
- name: Init DB and WP
|
||||
run: pnpm nx install-unit-test-db woocommerce
|
||||
|
||||
|
|
|
@ -4,15 +4,17 @@ on:
|
|||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
working-directory: plugins/woocommerce
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
jobs:
|
||||
test:
|
||||
name: Code sniff (PHP 7.4, WP Latest)
|
||||
timeout-minutes: 15
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 100
|
||||
|
||||
|
@ -27,25 +29,31 @@ jobs:
|
|||
php --version
|
||||
composer --version
|
||||
|
||||
- name: Get cached composer directories
|
||||
uses: actions/cache@v2
|
||||
- name: Get cached composer and pnpm directories
|
||||
uses: actions/cache@v3
|
||||
id: cache-deps
|
||||
with:
|
||||
path: |
|
||||
./packages
|
||||
./vendor
|
||||
key: ${{ runner.os }}-${{ hashFiles('./composer.lock') }}
|
||||
~/.pnpm-store
|
||||
plugins/woocommerce/packages
|
||||
plugins/woocommerce/**/vendor
|
||||
key: ${{ runner.os }}-npm-composer-${{ hashFiles('**/composer.lock', '**/pnpm-lock.yaml') }}
|
||||
|
||||
- name: Install PNPM and install dependencies
|
||||
run: |
|
||||
npm install -g pnpm
|
||||
pnpm install
|
||||
- name: Install PNPM
|
||||
run: npm install -g pnpm
|
||||
|
||||
- name: Setup and install composer
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Install Composer dependencies
|
||||
if: steps.cache-deps.outputs.cache-hit != 'true'
|
||||
run: pnpm nx composer-install woocommerce
|
||||
|
||||
- name: Run code sniff
|
||||
continue-on-error: true
|
||||
working-directory: plugins/woocommerce
|
||||
run: ./tests/bin/phpcs.sh "${{ github.event.pull_request.base.sha }}" "${{ github.event.after }}"
|
||||
|
||||
- name: Show PHPCS results in PR
|
||||
working-directory: plugins/woocommerce
|
||||
run: cs2pr ./phpcs-report.xml
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
name: Run lint checks potentially affecting projects across the monorepo
|
||||
on: pull_request
|
||||
concurrency:
|
||||
group: changelogger-${{ github.event_name }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
jobs:
|
||||
changelogger_used:
|
||||
name: Changelogger use
|
||||
runs-on: ubuntu-20.04
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: '7.4'
|
||||
|
||||
- name: Check change files are touched for touched projects
|
||||
env:
|
||||
BASE: ${{ github.event.pull_request.base.sha }}
|
||||
HEAD: ${{ github.event.pull_request.head.sha }}
|
||||
run: php tools/monorepo/check-changelogger-use.php --debug "$BASE" "$HEAD"
|
|
@ -0,0 +1,47 @@
|
|||
name: Lint and tests for JS packages and woocommerce-admin/client
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'packages/js/**/**'
|
||||
- 'plugins/woocommerce-admin/client/**'
|
||||
- '!**.md'
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
lint-test-js:
|
||||
name: Lint and Test JS
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '16'
|
||||
|
||||
- name: Cache modules
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.pnpm-store
|
||||
key: ${{ runner.os }}-npm-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||
|
||||
- name: Install PNPM
|
||||
run: npm install -g pnpm
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Lint
|
||||
run: |
|
||||
pnpm nx lint woocommerce-admin
|
||||
pnpm nx lint:js-packages woocommerce-admin
|
||||
|
||||
- name: Test
|
||||
run: |
|
||||
pnpm nx build woocommerce-admin
|
||||
pnpm nx test woocommerce-admin
|
||||
pnpm nx test:packages woocommerce-admin
|
|
@ -0,0 +1,18 @@
|
|||
name: 'Label Pull Request Project'
|
||||
on:
|
||||
pull_request_target:
|
||||
types:
|
||||
- opened
|
||||
- synchronize
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
label_project:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/labeler@v3
|
||||
with:
|
||||
repo-token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
configuration-path: .github/project-pr-labeler.yml
|
|
@ -1,105 +1,125 @@
|
|||
name: Run smoke tests against pull request.
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- trunk
|
||||
types:
|
||||
- labeled
|
||||
pull_request:
|
||||
branches:
|
||||
- trunk
|
||||
types:
|
||||
- labeled
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
prcheck:
|
||||
name: Smoke test a pull request.
|
||||
if: "${{ contains(github.event.label.name, 'run: smoke tests') }}"
|
||||
runs-on: ubuntu-18.04
|
||||
steps:
|
||||
- name: Create dirs.
|
||||
run: |
|
||||
mkdir -p code/woocommerce
|
||||
mkdir -p package/woocommerce
|
||||
mkdir -p tmp/woocommerce
|
||||
mkdir -p node_modules
|
||||
prcheck:
|
||||
name: Smoke test a pull request.
|
||||
if: "${{ contains(github.event.label.name, 'run: smoke tests') }}"
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Create dirs.
|
||||
run: |
|
||||
mkdir -p code/woocommerce
|
||||
mkdir -p package/woocommerce
|
||||
mkdir -p tmp/woocommerce
|
||||
|
||||
- name: Checkout code.
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
path: package/woocommerce
|
||||
- name: Checkout code.
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: package/woocommerce
|
||||
|
||||
- name: Install prerequisites.
|
||||
working-directory: package/woocommerce/plugins/woocommerce
|
||||
id: installation
|
||||
run: |
|
||||
npm install -g pnpm
|
||||
pnpm install
|
||||
pnpm nx composer-install-no-dev woocommerce
|
||||
pnpm nx build-assets woocommerce
|
||||
pnpm install jest
|
||||
- name: Get cached composer and pnpm directories
|
||||
uses: actions/cache@v3
|
||||
id: cache-deps
|
||||
with:
|
||||
path: |
|
||||
~/.pnpm-store
|
||||
package/woocommerce/plugins/woocommerce/packages
|
||||
package/woocommerce/plugins/woocommerce/**/vendor
|
||||
key: ${{ runner.os }}-smoke-test-npm-composer-${{ hashFiles('**/composer.lock', '**/pnpm-lock.yaml') }}
|
||||
|
||||
- name: Run smoke test.
|
||||
working-directory: package/woocommerce/plugins/woocommerce
|
||||
if: always()
|
||||
env:
|
||||
SMOKE_TEST_URL: ${{ secrets.SMOKE_TEST_URL }}
|
||||
SMOKE_TEST_ADMIN_USER: ${{ secrets.SMOKE_TEST_ADMIN_USER }}
|
||||
SMOKE_TEST_ADMIN_PASSWORD: ${{ secrets.SMOKE_TEST_ADMIN_PASSWORD }}
|
||||
SMOKE_TEST_ADMIN_USER_EMAIL: ${{ secrets.SMOKE_TEST_ADMIN_USER_EMAIL }}
|
||||
SMOKE_TEST_CUSTOMER_USER: ${{ secrets.SMOKE_TEST_CUSTOMER_USER }}
|
||||
SMOKE_TEST_CUSTOMER_PASSWORD: ${{ secrets.SMOKE_TEST_CUSTOMER_PASSWORD }}
|
||||
WC_E2E_SCREENSHOTS: 1
|
||||
E2E_RETEST: 1
|
||||
E2E_SLACK_TOKEN: ${{ secrets.SMOKE_TEST_SLACK_TOKEN }}
|
||||
E2E_SLACK_CHANNEL: ${{ secrets.SMOKE_TEST_SLACK_CHANNEL }}
|
||||
UPDATE_WC: 1
|
||||
DEFAULT_TIMEOUT_OVERRIDE: 120000
|
||||
run: |
|
||||
pnpx wc-e2e test:e2e tests/e2e/specs/smoke-tests/update-woocommerce.js
|
||||
- name: Install PNPM
|
||||
run: npm install -g pnpm
|
||||
|
||||
- name: Post Smoke tests results comment on PR
|
||||
if: always()
|
||||
uses: actions/github-script@v5
|
||||
env:
|
||||
TITLE: 'Smoke Test Results'
|
||||
SMOKE_TEST_URL: ${{ secrets.SMOKE_TEST_URL }}
|
||||
with:
|
||||
github-token: ${{secrets.GITHUB_TOKEN}}
|
||||
script: |
|
||||
const script = require( './package/woocommerce/packages/js/e2e-environment/bin/post-results-to-github-pr.js' )
|
||||
await script({github, context})
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Run E2E tests.
|
||||
working-directory: package/woocommerce/plugins/woocommerce
|
||||
if: always()
|
||||
env:
|
||||
SMOKE_TEST_URL: ${{ secrets.SMOKE_TEST_URL }}
|
||||
SMOKE_TEST_ADMIN_USER: ${{ secrets.SMOKE_TEST_ADMIN_USER }}
|
||||
SMOKE_TEST_ADMIN_PASSWORD: ${{ secrets.SMOKE_TEST_ADMIN_PASSWORD }}
|
||||
SMOKE_TEST_ADMIN_USER_EMAIL: ${{ secrets.SMOKE_TEST_ADMIN_USER_EMAIL }}
|
||||
SMOKE_TEST_CUSTOMER_USER: ${{ secrets.SMOKE_TEST_CUSTOMER_USER }}
|
||||
SMOKE_TEST_CUSTOMER_PASSWORD: ${{ secrets.SMOKE_TEST_CUSTOMER_PASSWORD }}
|
||||
WC_E2E_SCREENSHOTS: 1
|
||||
E2E_RETEST: 1
|
||||
E2E_SLACK_TOKEN: ${{ secrets.SMOKE_TEST_SLACK_TOKEN }}
|
||||
E2E_SLACK_CHANNEL: ${{ secrets.SMOKE_TEST_SLACK_CHANNEL }}
|
||||
UPDATE_WC: 1
|
||||
DEFAULT_TIMEOUT_OVERRIDE: 120000
|
||||
run: |
|
||||
pnpx wc-e2e test:e2e
|
||||
- name: Install Composer dependencies
|
||||
if: steps.cache-deps.outputs.cache-hit != 'true'
|
||||
run: pnpm nx composer-install-no-dev woocommerce
|
||||
|
||||
- name: Post E2E tests results comment on PR
|
||||
if: always()
|
||||
uses: actions/github-script@v5
|
||||
env:
|
||||
TITLE: 'E2E Test Results'
|
||||
SMOKE_TEST_URL: ${{ secrets.SMOKE_TEST_URL }}
|
||||
with:
|
||||
github-token: ${{secrets.GITHUB_TOKEN}}
|
||||
script: |
|
||||
const script = require( './package/woocommerce/packages/js/e2e-environment/bin/post-results-to-github-pr.js' )
|
||||
await script({github, context})
|
||||
- name: Install prerequisites.
|
||||
working-directory: package/woocommerce/plugins/woocommerce
|
||||
id: installation
|
||||
run: |
|
||||
pnpm nx build-assets woocommerce
|
||||
pnpm install jest
|
||||
|
||||
- name: Remove label from pull request.
|
||||
if: |
|
||||
always()
|
||||
&& contains( github.event.pull_request.labels.*.name, format('run{0} smoke tests', ':'))
|
||||
uses: actions-ecosystem/action-remove-labels@v1
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
labels: 'run: smoke tests'
|
||||
- name: Run smoke test.
|
||||
working-directory: package/woocommerce/plugins/woocommerce
|
||||
if: always()
|
||||
env:
|
||||
SMOKE_TEST_URL: ${{ secrets.SMOKE_TEST_URL }}
|
||||
SMOKE_TEST_ADMIN_USER: ${{ secrets.SMOKE_TEST_ADMIN_USER }}
|
||||
SMOKE_TEST_ADMIN_PASSWORD: ${{ secrets.SMOKE_TEST_ADMIN_PASSWORD }}
|
||||
SMOKE_TEST_ADMIN_USER_EMAIL: ${{ secrets.SMOKE_TEST_ADMIN_USER_EMAIL }}
|
||||
SMOKE_TEST_CUSTOMER_USER: ${{ secrets.SMOKE_TEST_CUSTOMER_USER }}
|
||||
SMOKE_TEST_CUSTOMER_PASSWORD: ${{ secrets.SMOKE_TEST_CUSTOMER_PASSWORD }}
|
||||
WC_E2E_SCREENSHOTS: 1
|
||||
E2E_RETEST: 1
|
||||
E2E_SLACK_TOKEN: ${{ secrets.SMOKE_TEST_SLACK_TOKEN }}
|
||||
E2E_SLACK_CHANNEL: ${{ secrets.SMOKE_TEST_SLACK_CHANNEL }}
|
||||
UPDATE_WC: 1
|
||||
DEFAULT_TIMEOUT_OVERRIDE: 120000
|
||||
run: |
|
||||
pnpm exec wc-e2e test:e2e tests/e2e/specs/smoke-tests/update-woocommerce.js
|
||||
|
||||
- name: Post Smoke tests results comment on PR
|
||||
if: always()
|
||||
uses: actions/github-script@v5
|
||||
env:
|
||||
TITLE: 'Smoke Test Results'
|
||||
SMOKE_TEST_URL: ${{ secrets.SMOKE_TEST_URL }}
|
||||
with:
|
||||
github-token: ${{secrets.GITHUB_TOKEN}}
|
||||
script: |
|
||||
const script = require( './package/woocommerce/packages/js/e2e-environment/bin/post-results-to-github-pr.js' )
|
||||
await script({github, context})
|
||||
|
||||
- name: Run E2E tests.
|
||||
working-directory: package/woocommerce/plugins/woocommerce
|
||||
if: always()
|
||||
env:
|
||||
SMOKE_TEST_URL: ${{ secrets.SMOKE_TEST_URL }}
|
||||
SMOKE_TEST_ADMIN_USER: ${{ secrets.SMOKE_TEST_ADMIN_USER }}
|
||||
SMOKE_TEST_ADMIN_PASSWORD: ${{ secrets.SMOKE_TEST_ADMIN_PASSWORD }}
|
||||
SMOKE_TEST_ADMIN_USER_EMAIL: ${{ secrets.SMOKE_TEST_ADMIN_USER_EMAIL }}
|
||||
SMOKE_TEST_CUSTOMER_USER: ${{ secrets.SMOKE_TEST_CUSTOMER_USER }}
|
||||
SMOKE_TEST_CUSTOMER_PASSWORD: ${{ secrets.SMOKE_TEST_CUSTOMER_PASSWORD }}
|
||||
WC_E2E_SCREENSHOTS: 1
|
||||
E2E_RETEST: 1
|
||||
E2E_SLACK_TOKEN: ${{ secrets.SMOKE_TEST_SLACK_TOKEN }}
|
||||
E2E_SLACK_CHANNEL: ${{ secrets.SMOKE_TEST_SLACK_CHANNEL }}
|
||||
UPDATE_WC: 1
|
||||
DEFAULT_TIMEOUT_OVERRIDE: 120000
|
||||
run: |
|
||||
pnpm exec wc-e2e test:e2e
|
||||
|
||||
- name: Post E2E tests results comment on PR
|
||||
if: always()
|
||||
uses: actions/github-script@v5
|
||||
env:
|
||||
TITLE: 'E2E Test Results'
|
||||
SMOKE_TEST_URL: ${{ secrets.SMOKE_TEST_URL }}
|
||||
with:
|
||||
github-token: ${{secrets.GITHUB_TOKEN}}
|
||||
script: |
|
||||
const script = require( './package/woocommerce/packages/js/e2e-environment/bin/post-results-to-github-pr.js' )
|
||||
await script({github, context})
|
||||
|
||||
- name: Remove label from pull request.
|
||||
if: |
|
||||
always()
|
||||
&& contains( github.event.pull_request.labels.*.name, format('run{0} smoke tests', ':'))
|
||||
uses: actions-ecosystem/action-remove-labels@v1
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
labels: 'run: smoke tests'
|
||||
|
|
|
@ -4,24 +4,27 @@ on:
|
|||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
working-directory: plugins/woocommerce
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: PHP ${{ matrix.php }} WP ${{ matrix.wp }}
|
||||
timeout-minutes: 15
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 20
|
||||
runs-on: ubuntu-20.04
|
||||
continue-on-error: ${{ matrix.wp == 'nightly' }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
php: [ '7.0', '7.1', '7.2', '7.3', '7.4', '8.0' ]
|
||||
php: [ '7.2', '7.3', '7.4', '8.0' ]
|
||||
wp: [ "latest" ]
|
||||
include:
|
||||
- wp: nightly
|
||||
php: '7.4'
|
||||
- wp: '5.7'
|
||||
- wp: '5.8'
|
||||
php: 7.2
|
||||
- wp: '5.6'
|
||||
- wp: '5.7'
|
||||
php: 7.2
|
||||
services:
|
||||
database:
|
||||
|
@ -48,33 +51,45 @@ jobs:
|
|||
php --version
|
||||
composer --version
|
||||
|
||||
- name: Get cached composer directories
|
||||
uses: actions/cache@v2
|
||||
- name: Get cached composer and pnpm directories
|
||||
uses: actions/cache@v3
|
||||
id: cache-deps
|
||||
with:
|
||||
path: |
|
||||
./packages
|
||||
./vendor
|
||||
key: ${{ runner.os }}-${{ hashFiles('./composer.lock') }}
|
||||
~/.pnpm-store
|
||||
plugins/woocommerce/packages
|
||||
plugins/woocommerce/**/vendor
|
||||
key: ${{ runner.os }}-npm-composer-${{ hashFiles('**/composer.lock', '**/pnpm-lock.yaml') }}
|
||||
|
||||
- name: Install PNPM and install dependencies
|
||||
- name: Install PNPM
|
||||
run: npm install -g pnpm
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Install Composer dependencies
|
||||
if: steps.cache-deps.outputs.cache-hit != 'true'
|
||||
run: pnpm nx composer-install woocommerce
|
||||
|
||||
- name: Build Admin feature config
|
||||
run: |
|
||||
npm install -g pnpm
|
||||
pnpm install
|
||||
pnpm nx composer-install woocommerce
|
||||
pnpm nx build:feature-config woocommerce
|
||||
|
||||
- name: Add PHP8 Compatibility.
|
||||
run: |
|
||||
if [ "$(php -r "echo version_compare(PHP_VERSION,'8.0','>=');")" ]; then
|
||||
cd plugins/woocommerce
|
||||
curl -L https://github.com/woocommerce/phpunit/archive/add-compatibility-with-php8-to-phpunit-7.zip -o /tmp/phpunit-7.5-fork.zip
|
||||
unzip -d /tmp/phpunit-7.5-fork /tmp/phpunit-7.5-fork.zip
|
||||
composer bin phpunit config --unset platform
|
||||
composer bin phpunit config repositories.0 '{"type": "path", "url": "/tmp/phpunit-7.5-fork/phpunit-add-compatibility-with-php8-to-phpunit-7", "options": {"symlink": false}}'
|
||||
composer bin phpunit require --dev -W phpunit/phpunit:@dev --ignore-platform-reqs
|
||||
rm -rf ./vendor/phpunit/
|
||||
composer dump-autoload
|
||||
pnpm nx composer-dump-autoload woocommerce
|
||||
fi
|
||||
|
||||
- name: Init DB and WP
|
||||
working-directory: plugins/woocommerce
|
||||
run: ./tests/bin/install.sh woo_test root root 127.0.0.1 ${{ matrix.wp }}
|
||||
|
||||
- name: Run tests
|
||||
|
|
|
@ -7,7 +7,7 @@ jobs:
|
|||
process-pull-request-after-merge:
|
||||
name: "Process a pull request after it's merged"
|
||||
if: github.event.pull_request.merged == true
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: "Get the action scripts"
|
||||
run: |
|
||||
|
@ -30,12 +30,16 @@ jobs:
|
|||
with:
|
||||
php-version: '7.4'
|
||||
- name: "Run the script to assign a milestone"
|
||||
if: "!github.event.pull_request.milestone"
|
||||
if: |
|
||||
contains(github.event.pull_request.labels.*.name, 'plugin: woocommerce') &&
|
||||
!github.event.pull_request.milestone &&
|
||||
github.event.pull_request.base.ref == 'trunk'
|
||||
run: php assign-milestone-to-merged-pr.php
|
||||
env:
|
||||
PULL_REQUEST_ID: ${{ github.event.pull_request.node_id }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: "Run the script to post a comment with next steps hint"
|
||||
if: "contains(github.event.pull_request.labels.*.name, 'plugin: woocommerce')"
|
||||
run: php add-post-merge-comment.php
|
||||
env:
|
||||
PULL_REQUEST_ID: ${{ github.event.pull_request.node_id }}
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
name: "Enforce release code freeze"
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 16 * * 4' # Run at 1600 UTC on Thursdays.
|
||||
|
||||
jobs:
|
||||
maybe-create-next-milestone-and-release-branch:
|
||||
name: "Maybe create next milestone and release branch"
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: "Get the action script"
|
||||
run: |
|
||||
scripts="post-request-shared.php release-code-freeze.php"
|
||||
for script in $scripts
|
||||
do
|
||||
curl \
|
||||
--silent \
|
||||
--fail \
|
||||
--header 'Authorization: bearer ${{ secrets.GITHUB_TOKEN }}' \
|
||||
--header 'User-Agent: GitHub action to enforce release code freeze' \
|
||||
--header 'Accept: application/vnd.github.v3.raw' \
|
||||
--output $script \
|
||||
--location "$GITHUB_API_URL/repos/${{ github.repository }}/contents/.github/workflows/scripts/$script?ref=$GITHUB_REF"
|
||||
done
|
||||
env:
|
||||
GITHUB_API_URL: ${{ env.GITHUB_API_URL }}
|
||||
GITHUB_REF: ${{ env.GITHUB_REF }}
|
||||
- name: "Install PHP"
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: '7.4'
|
||||
- name: "Run the script to enforce the code freeze"
|
||||
run: php release-code-freeze.php
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
@ -57,8 +57,7 @@ echo "The pull request was merged by: $merger_user_name\n";
|
|||
|
||||
$comment_body = "Hi @$merger_user_name, thanks for merging this pull request. Please take a look at these follow-up tasks you may need to perform:
|
||||
|
||||
- [ ] Add the `status: needs changelog` label
|
||||
- [ ] Add the `status: needs testing instructions` label";
|
||||
- [ ] Add the `release: add testing instructions` label";
|
||||
|
||||
$add_comment_mutation = "
|
||||
addComment(input: {subjectId: \"$pr_id\", body: \"$comment_body\", clientMutationId: \"$github_token\"}) {
|
||||
|
|
|
@ -9,73 +9,7 @@
|
|||
|
||||
require_once __DIR__ . '/post-request-shared.php';
|
||||
|
||||
/*
|
||||
* Select the milestone to be added:
|
||||
*
|
||||
* 1. Get the first 10 milestones sorted by creation date descending.
|
||||
* (we'll never have more than 2 or 3 active milestones but let's get 10 to be sure).
|
||||
* 2. Discard those not open or whose title is not a proper version number ("X.Y.Z").
|
||||
* 3. Sort descending using version_compare.
|
||||
* 4. Get the oldest one that does not have a corresponding "release/X.Y" branch.
|
||||
*/
|
||||
|
||||
echo "Getting the list of milestones...\n";
|
||||
|
||||
$query = "
|
||||
repository(owner:\"$repo_owner\", name:\"$repo_name\") {
|
||||
milestones(first: 10, states: [OPEN], orderBy: {field: CREATED_AT, direction: DESC}) {
|
||||
nodes {
|
||||
id
|
||||
title
|
||||
state
|
||||
}
|
||||
}
|
||||
}
|
||||
";
|
||||
$json = do_graphql_api_request( $query );
|
||||
$milestones = $json['data']['repository']['milestones']['nodes'];
|
||||
$milestones = array_map(
|
||||
function( $x ) {
|
||||
return 1 === preg_match( '/^\d+\.\d+\.\d+$/D', $x['title'] ) ? $x : null;
|
||||
},
|
||||
$milestones
|
||||
);
|
||||
$milestones = array_filter( $milestones );
|
||||
usort(
|
||||
$milestones,
|
||||
function( $a, $b ) {
|
||||
return version_compare( $b['title'], $a['title'] );
|
||||
}
|
||||
);
|
||||
|
||||
echo 'Latest open milestone: ' . $milestones[0]['title'] . "\n";
|
||||
|
||||
$chosen_milestone = null;
|
||||
foreach ( $milestones as $milestone ) {
|
||||
$milestone_title_parts = explode( '.', $milestone['title'] );
|
||||
$milestone_release_branch = 'release/' . $milestone_title_parts[0] . '.' . $milestone_title_parts[1];
|
||||
|
||||
$query = "
|
||||
repository(owner:\"$repo_owner\", name:\"$repo_name\") {
|
||||
ref(qualifiedName: \"refs/heads/$milestone_release_branch\") {
|
||||
id
|
||||
}
|
||||
}
|
||||
";
|
||||
$result = do_graphql_api_request( $query );
|
||||
|
||||
if ( is_null( $result['data']['repository']['ref'] ) ) {
|
||||
$chosen_milestone = $milestone;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If all the milestones have a release branch, just take the newest one.
|
||||
if ( is_null( $chosen_milestone ) ) {
|
||||
echo "WARNING: No milestone without release branch found, the newest one will be assigned.\n";
|
||||
$chosen_milestone = $milestones[0];
|
||||
}
|
||||
$chosen_milestone = get_latest_milestone_from_api( true );
|
||||
|
||||
echo 'Milestone that will be assigned: ' . $chosen_milestone['title'] . "\n";
|
||||
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
/**
|
||||
* A script that fetches the asset id of a given release and sets it as the output for the step that calls it
|
||||
*/
|
||||
const https = require('https');
|
||||
|
||||
const options = {
|
||||
hostname: 'api.github.com',
|
||||
port: 443,
|
||||
path: `/repos/${process.env.REPO}/releases/${process.env.RELEASE_ID}/assets`,
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${ process.env.GITHUB_TOKEN }`,
|
||||
'User-Agent': 'WooCommerce Smoke Build'
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns {Promise}
|
||||
*/
|
||||
const fetchAssetId = () => {
|
||||
return new Promise( ( resolve, reject ) => {
|
||||
const request = https.get( options, ( response ) => {
|
||||
response.setEncoding('utf8');
|
||||
|
||||
let responseBody = '';
|
||||
|
||||
response.on( 'data', ( chunk ) => {
|
||||
responseBody += chunk;
|
||||
} );
|
||||
|
||||
response.on( 'end', () => {
|
||||
const assets = JSON.parse( responseBody );
|
||||
// use the most recently uploaded asset
|
||||
resolve( assets[ assets.length - 1 ].id );
|
||||
} );
|
||||
} );
|
||||
|
||||
request.on('error', ( error ) => {
|
||||
reject( error );
|
||||
} );
|
||||
|
||||
request.end();
|
||||
|
||||
} );
|
||||
}
|
||||
|
||||
module.exports = async ( { github, context, core } ) => {
|
||||
const id = await fetchAssetId();
|
||||
|
||||
// set asset_id as the output
|
||||
core.setOutput( 'asset_id', id );
|
||||
}
|
|
@ -19,9 +19,237 @@ $repo_name = $repo_parts[1];
|
|||
|
||||
$pr_id = getenv( 'PULL_REQUEST_ID' );
|
||||
$github_token = getenv( 'GITHUB_TOKEN' );
|
||||
$github_api_url = getenv( 'GITHUB_API_URL' );
|
||||
$graphql_api_url = getenv( 'GITHUB_GRAPHQL_URL' );
|
||||
|
||||
|
||||
/**
|
||||
* Function to get the latest milestone.
|
||||
*
|
||||
* @param bool $use_latest_when_null When true, the function returns the latest milestone regardless of release branch status.
|
||||
* @return string The title of the latest milestone.
|
||||
*/
|
||||
function get_latest_milestone_from_api( $use_latest_when_null = false ) {
|
||||
global $repo_owner, $repo_name;
|
||||
|
||||
echo 'Getting the list of milestones...' . PHP_EOL;
|
||||
|
||||
$query = "
|
||||
repository(owner:\"$repo_owner\", name:\"$repo_name\") {
|
||||
milestones(first: 10, states: [OPEN], orderBy: {field: CREATED_AT, direction: DESC}) {
|
||||
nodes {
|
||||
id
|
||||
title
|
||||
state
|
||||
}
|
||||
}
|
||||
}
|
||||
";
|
||||
$json = do_graphql_api_request( $query );
|
||||
$milestones = $json['data']['repository']['milestones']['nodes'];
|
||||
$milestones = array_map(
|
||||
function( $x ) {
|
||||
return 1 === preg_match( '/^\d+\.\d+\.\d+$/D', $x['title'] ) ? $x : null;
|
||||
},
|
||||
$milestones
|
||||
);
|
||||
$milestones = array_filter( $milestones );
|
||||
usort(
|
||||
$milestones,
|
||||
function( $a, $b ) {
|
||||
return version_compare( $b['title'], $a['title'] );
|
||||
}
|
||||
);
|
||||
|
||||
echo 'Latest open milestone: ' . $milestones[0]['title'] . PHP_EOL;
|
||||
|
||||
$chosen_milestone = null;
|
||||
foreach ( $milestones as $milestone ) {
|
||||
$milestone_title_parts = explode( '.', $milestone['title'] );
|
||||
$milestone_release_branch = 'release/' . $milestone_title_parts[0] . '.' . $milestone_title_parts[1];
|
||||
|
||||
$query = "
|
||||
repository(owner:\"$repo_owner\", name:\"$repo_name\") {
|
||||
ref(qualifiedName: \"refs/heads/$milestone_release_branch\") {
|
||||
id
|
||||
}
|
||||
}
|
||||
";
|
||||
$result = do_graphql_api_request( $query );
|
||||
|
||||
if ( is_null( $result['data']['repository']['ref'] ) ) {
|
||||
$chosen_milestone = $milestone;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If all the milestones have a release branch, just take the newest one.
|
||||
if ( $use_latest_when_null && is_null( $chosen_milestone ) ) {
|
||||
echo 'WARNING: No milestone without release branch found, the newest one will be assigned.' . PHP_EOL;
|
||||
$chosen_milestone = $milestones[0];
|
||||
}
|
||||
|
||||
return $chosen_milestone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to get the last major.minor version with a release from the API.
|
||||
*
|
||||
* @return string Returns the latest version with a release formatted as "major.minor".
|
||||
*/
|
||||
function get_latest_version_with_release() {
|
||||
global $repo_owner, $repo_name;
|
||||
|
||||
echo 'Getting the list of releases...' . PHP_EOL;
|
||||
|
||||
$query = "
|
||||
repository(owner:\"$repo_owner\", name:\"$repo_name\") {
|
||||
releases(first: 25, orderBy: { field: CREATED_AT, direction: DESC}) {
|
||||
nodes {
|
||||
tagName
|
||||
}
|
||||
}
|
||||
}
|
||||
";
|
||||
$json = do_graphql_api_request( $query );
|
||||
$releases = $json['data']['repository']['releases']['nodes'];
|
||||
$releases = array_map(
|
||||
function( $x ) {
|
||||
return 1 === preg_match( '/^\d+\.\d+\.\d+/D', $x['tagName'] ) ? $x : null;
|
||||
},
|
||||
$releases
|
||||
);
|
||||
$releases = array_filter( $releases );
|
||||
usort(
|
||||
$releases,
|
||||
function( $a, $b ) {
|
||||
return version_compare( $b['tagName'], $a['tagName'] );
|
||||
}
|
||||
);
|
||||
|
||||
$major_minor = preg_replace( '/(^\d+\.\d+).*?$/', '\1', $releases[0]['tagName'] );
|
||||
echo 'Most recent version with a release: ' . $major_minor . PHP_EOL;
|
||||
|
||||
return $major_minor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to retreive the sha1 reference for a given branch name.
|
||||
*
|
||||
* @param string $branch The name of the branch.
|
||||
* @return string Returns the name of the branch, or a falsey value on error.
|
||||
*/
|
||||
function get_ref_from_branch( $branch ) {
|
||||
global $repo_owner, $repo_name;
|
||||
$query = "
|
||||
repository(owner:\"$repo_owner\", name:\"$repo_name\") {
|
||||
ref(qualifiedName: \"refs/heads/{$branch}\") {
|
||||
target {
|
||||
... on Commit {
|
||||
history(first: 1) {
|
||||
edges{ node{ oid } }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
";
|
||||
$result = do_graphql_api_request( $query );
|
||||
|
||||
// Warnings suppressed here because traversing this level of arrays with isset / is_array checks would be messy.
|
||||
return @$result['data']['repository']['ref']['target']['history']['edges'][0]['node']['oid'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to create milestone using the GitHub REST API.
|
||||
*
|
||||
* @param string $title The title of the milestone to be created.
|
||||
* @return bool True on success, False otherwise.
|
||||
*/
|
||||
function create_github_milestone( $title ) {
|
||||
global $repo_owner, $repo_name;
|
||||
|
||||
$result = do_github_api_post_request( "/repos/{$repo_owner}/{$repo_name}/milestones", array(
|
||||
'title' => $title,
|
||||
) );
|
||||
|
||||
return is_array( $result ) && $result['title'] === $title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to create branch using the GitHub REST API.
|
||||
*
|
||||
* @param string $branch The branch to be created.
|
||||
* @param string $sha The sha1 reference for the branch.
|
||||
* @return bool True on success, False otherwise.
|
||||
*/
|
||||
function create_github_branch( $branch, $sha ) {
|
||||
global $repo_owner, $repo_name;
|
||||
|
||||
$ref = "refs/heads/{$branch}";
|
||||
$result = do_github_api_post_request( "/repos/{$repo_owner}/{$repo_name}/git/refs", array(
|
||||
'ref' => $ref,
|
||||
'sha' => $sha,
|
||||
) );
|
||||
|
||||
return is_array( $result ) && $result['ref'] === $ref;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to create branch using the GitHub REST API from an existing branch.
|
||||
*
|
||||
* @param string $source The branch from which to create.
|
||||
* @param string $target The branch to be created.
|
||||
* @return bool True on success, False otherwise.
|
||||
*/
|
||||
function create_github_branch_from_branch( $source, $target ) {
|
||||
$ref = get_ref_from_branch( $source );
|
||||
if ( ! $ref ) {
|
||||
return false;
|
||||
}
|
||||
return create_github_branch( $target, $ref );
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to do a GitHub API POST Request.
|
||||
*
|
||||
* @param array $request_url
|
||||
* @param array $body The body of the request to be json encoded.
|
||||
* @return mixed The json-decoded response if a response is received, 'false' (or whatever file_get_contents returns) otherwise.
|
||||
*/
|
||||
function do_github_api_post_request( $request_path, $body ) {
|
||||
global $github_token, $github_api_url, $github_api_response_code;
|
||||
|
||||
$context = stream_context_create(
|
||||
array(
|
||||
'http' => array(
|
||||
'method' => 'POST',
|
||||
'header' => array(
|
||||
'Accept: application/vnd.github.v3+json',
|
||||
'Content-Type: application/json',
|
||||
'User-Agent: GitHub Actions for creation of milestones',
|
||||
'Authorization: bearer ' . $github_token,
|
||||
),
|
||||
'content' => json_encode( $body ),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
$full_request_url = rtrim( $github_api_url, '/' ) . '/' . ltrim( $request_path, '/' );
|
||||
$result = @file_get_contents( $full_request_url, false, $context );
|
||||
|
||||
// Verify that the post request was sucessful.
|
||||
$status_line = $http_response_header[0];
|
||||
preg_match( "/^HTTPS?\/\d\.\d\s+(\d{3})\s+/i", $status_line, $matches );
|
||||
$github_api_response_code = $matches[1];
|
||||
if ( '2' !== substr( $github_api_response_code, 0, 1 ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return is_string( $result ) ? json_decode( $result, true ) : $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to query the GitHub GraphQL API.
|
||||
*
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
/**
|
||||
* Script to automatically enforce the release code freeze.
|
||||
*
|
||||
* @package WooCommerce/GithubActions
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/post-request-shared.php';
|
||||
|
||||
$now = time();
|
||||
if ( getenv( 'TIME_OVERRIDE' ) ) {
|
||||
$now = strtotime( getenv( 'TIME_OVERRIDE' ) );
|
||||
}
|
||||
|
||||
// Code freeze comes 26 days prior to release day.
|
||||
$release_time = strtotime( '+26 days', $now );
|
||||
$release_day_of_week = date( 'l', $release_time );
|
||||
$release_day_of_month = (int) date( 'j', $release_time );
|
||||
|
||||
// If 26 days from now isn't the second Tuesday, then it's not code freeze day.
|
||||
if ( 'Tuesday' !== $release_day_of_week || $release_day_of_month < 8 || $release_day_of_month > 14 ) {
|
||||
echo 'Info: Today is not the Thursday of the code freeze.' . PHP_EOL;
|
||||
return;
|
||||
}
|
||||
|
||||
$latest_version_with_release = get_latest_version_with_release();
|
||||
|
||||
if ( empty( $latest_version_with_release ) ) {
|
||||
echo '*** Error: Unable to get latest version with release' . PHP_EOL;
|
||||
return;
|
||||
}
|
||||
|
||||
// Because we go from 5.9 to 6.0, we can get the next major_minor by adding 0.1 and formatting appropriately.
|
||||
$latest_float = (float) $latest_version_with_release;
|
||||
$branch_major_minor = number_format( $latest_float + 0.1, 1 );
|
||||
$milestone_major_minor = number_format( $latest_float + 0.2, 1 );
|
||||
|
||||
// We use those values to get the release branch and next milestones that we need to create.
|
||||
$release_branch_to_create = "release/{$branch_major_minor}";
|
||||
$milestone_to_create = "{$milestone_major_minor}.0";
|
||||
|
||||
if ( getenv( 'DRY_RUN' ) ) {
|
||||
echo 'DRY RUN: Skipping actual creation of release branch and milestone...' . PHP_EOL;
|
||||
echo "Release Branch: {$release_branch_to_create}" . PHP_EOL;
|
||||
echo "Milestone: {$milestone_to_create}" . PHP_EOL;
|
||||
return;
|
||||
}
|
||||
|
||||
if ( create_github_milestone( $milestone_to_create ) ) {
|
||||
echo "Created milestone {$milestone_to_create}" . PHP_EOL;
|
||||
} else if ( '422' === $github_api_response_code ) {
|
||||
// The milestone already existed when GitHub returns a 422 status.
|
||||
echo "Notice: Unable to create {$milestone_to_create} milestone. Maybe it already exists? Skipping..." . PHP_EOL;
|
||||
} else {
|
||||
echo "*** Error: Unable to create {$milestone_to_create} milestone" . PHP_EOL;
|
||||
}
|
||||
|
||||
if ( create_github_branch_from_branch( 'trunk', $release_branch_to_create ) ) {
|
||||
echo "Created branch {$release_branch_to_create}" . PHP_EOL;
|
||||
} else if ( '422' === $github_api_response_code ) {
|
||||
// The release branch already existed when GitHub returns a 422 status.
|
||||
echo "Notice: Unable to create {$release_branch_to_create} branch. Maybe it already exists? Skipping..." . PHP_EOL;
|
||||
} else {
|
||||
echo "*** Error: Unable to create {$release_branch_to_create}" . PHP_EOL;
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
name: Check daily smoke test site status.
|
||||
on:
|
||||
schedule:
|
||||
- cron: '25 7 * * *'
|
||||
|
||||
jobs:
|
||||
ping_site:
|
||||
runs-on: ubuntu-20.04
|
||||
name: Check site and notify if not found
|
||||
steps:
|
||||
- name: Check site status
|
||||
id: sitecheck
|
||||
uses: srt32/uptime@958231f4d95c117f08eb0fc70907e80d0dfedf2b
|
||||
with:
|
||||
url-to-hit: "${{ secrets.SMOKE_TEST_URL }}ready/"
|
||||
expected-statuses: "200,301"
|
||||
- name: Send message to Slack API
|
||||
if: failure()
|
||||
uses: archive/github-actions-slack@deecc2edc496dc642d643de1d7cf3a47f51fb27a
|
||||
id: notify
|
||||
with:
|
||||
slack-bot-user-oauth-access-token: ${{ secrets.SMOKE_TEST_SLACK_TOKEN }}
|
||||
slack-channel: ${{ secrets.SMOKE_TEST_SLACK_CHANNEL }}
|
||||
slack-text: ':warning: <!subteam^${{ secrets.SMOKE_TEST_SLACK_GROUP }}> FYI the URL ${{ secrets.SMOKE_TEST_URL }}ready/ appears to be returning `404 not found` :x:'
|
|
@ -1,154 +1,153 @@
|
|||
name: Smoke test daily
|
||||
on:
|
||||
schedule:
|
||||
- cron: '25 3 * * *'
|
||||
schedule:
|
||||
- cron: '25 3 * * *'
|
||||
jobs:
|
||||
login-run:
|
||||
name: Daily smoke test on trunk.
|
||||
runs-on: ubuntu-18.04
|
||||
steps:
|
||||
login-run:
|
||||
name: Daily smoke test on trunk.
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Create dirs.
|
||||
run: |
|
||||
mkdir -p code/woocommerce
|
||||
mkdir -p package/woocommerce
|
||||
mkdir -p tmp/woocommerce
|
||||
mkdir -p node_modules
|
||||
|
||||
- name: Create dirs.
|
||||
run: |
|
||||
mkdir -p code/woocommerce
|
||||
mkdir -p package/woocommerce
|
||||
mkdir -p tmp/woocommerce
|
||||
mkdir -p node_modules
|
||||
- name: Checkout code.
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: package/woocommerce
|
||||
ref: trunk
|
||||
|
||||
- name: Checkout code.
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
path: package/woocommerce
|
||||
ref: trunk
|
||||
- name: Install prerequisites.
|
||||
working-directory: package/woocommerce/plugins/woocommerce
|
||||
run: |
|
||||
npm install -g pnpm
|
||||
pnpm install
|
||||
pnpm nx composer-install-no-dev woocommerce
|
||||
pnpm nx build-assets woocommerce
|
||||
pnpm install jest
|
||||
|
||||
- name: Install prerequisites.
|
||||
working-directory: package/woocommerce/plugins/woocommerce
|
||||
run: |
|
||||
npm install -g pnpm
|
||||
pnpm install
|
||||
pnpm nx composer-install-no-dev woocommerce
|
||||
pnpm nx build-assets woocommerce
|
||||
pnpm install jest
|
||||
- name: Run smoke test.
|
||||
working-directory: package/woocommerce/plugins/woocommerce
|
||||
env:
|
||||
SMOKE_TEST_URL: ${{ secrets.SMOKE_TEST_URL }}
|
||||
SMOKE_TEST_ADMIN_USER: ${{ secrets.SMOKE_TEST_ADMIN_USER }}
|
||||
SMOKE_TEST_ADMIN_PASSWORD: ${{ secrets.SMOKE_TEST_ADMIN_PASSWORD }}
|
||||
SMOKE_TEST_ADMIN_USER_EMAIL: ${{ secrets.SMOKE_TEST_ADMIN_USER_EMAIL }}
|
||||
SMOKE_TEST_CUSTOMER_USER: ${{ secrets.SMOKE_TEST_CUSTOMER_USER }}
|
||||
SMOKE_TEST_CUSTOMER_PASSWORD: ${{ secrets.SMOKE_TEST_CUSTOMER_PASSWORD }}
|
||||
WC_E2E_SCREENSHOTS: 1
|
||||
E2E_RETEST: 1
|
||||
E2E_SLACK_TOKEN: ${{ secrets.SMOKE_TEST_SLACK_TOKEN }}
|
||||
E2E_SLACK_CHANNEL: 'C01U0H617MY'
|
||||
UPDATE_WC: 1
|
||||
DEFAULT_TIMEOUT_OVERRIDE: 120000
|
||||
BASE_URL: ${{ secrets.SMOKE_TEST_URL }}
|
||||
USER_KEY: ${{ secrets.SMOKE_TEST_ADMIN_USER }}
|
||||
USER_SECRET: ${{ secrets.SMOKE_TEST_ADMIN_PASSWORD }}
|
||||
run: |
|
||||
pnpm exec wc-e2e test:e2e tests/e2e/specs/smoke-tests/update-woocommerce.js
|
||||
pnpm exec wc-e2e test:e2e
|
||||
pnpm exec wc-api-tests test api
|
||||
|
||||
- name: Run smoke test.
|
||||
working-directory: package/woocommerce/plugins/woocommerce
|
||||
env:
|
||||
SMOKE_TEST_URL: ${{ secrets.SMOKE_TEST_URL }}
|
||||
SMOKE_TEST_ADMIN_USER: ${{ secrets.SMOKE_TEST_ADMIN_USER }}
|
||||
SMOKE_TEST_ADMIN_PASSWORD: ${{ secrets.SMOKE_TEST_ADMIN_PASSWORD }}
|
||||
SMOKE_TEST_ADMIN_USER_EMAIL: ${{ secrets.SMOKE_TEST_ADMIN_USER_EMAIL }}
|
||||
SMOKE_TEST_CUSTOMER_USER: ${{ secrets.SMOKE_TEST_CUSTOMER_USER }}
|
||||
SMOKE_TEST_CUSTOMER_PASSWORD: ${{ secrets.SMOKE_TEST_CUSTOMER_PASSWORD }}
|
||||
WC_E2E_SCREENSHOTS: 1
|
||||
E2E_RETEST: 1
|
||||
E2E_SLACK_TOKEN: ${{ secrets.SMOKE_TEST_SLACK_TOKEN }}
|
||||
E2E_SLACK_CHANNEL: ${{ secrets.SMOKE_TEST_SLACK_CHANNEL }}
|
||||
UPDATE_WC: 1
|
||||
DEFAULT_TIMEOUT_OVERRIDE: 120000
|
||||
BASE_URL: ${{ secrets.SMOKE_TEST_URL }}
|
||||
USER_KEY: ${{ secrets.SMOKE_TEST_ADMIN_USER }}
|
||||
USER_SECRET: ${{ secrets.SMOKE_TEST_ADMIN_PASSWORD }}
|
||||
run: |
|
||||
pnpx wc-e2e test:e2e tests/e2e/specs/smoke-tests/update-woocommerce.js
|
||||
pnpx wc-e2e test:e2e
|
||||
pnpx wc-api-tests test api
|
||||
build:
|
||||
name: Build zip for PR
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
build:
|
||||
name: Build zip for PR
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
- name: Build
|
||||
id: build
|
||||
uses: woocommerce/action-build@trunk
|
||||
env:
|
||||
BUILD_ENV: e2e
|
||||
|
||||
- name: Build
|
||||
id: build
|
||||
uses: woocommerce/action-build@trunk
|
||||
env:
|
||||
BUILD_ENV: e2e
|
||||
- name: Upload PR zip
|
||||
uses: actions/upload-artifact@v3
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
name: woocommerce
|
||||
path: ${{ steps.build.outputs.zip_path }}
|
||||
retention-days: 7
|
||||
|
||||
- name: Upload PR zip
|
||||
uses: actions/upload-artifact@v2
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
name: woocommerce
|
||||
path: ${{ steps.build.outputs.zip_path }}
|
||||
retention-days: 7
|
||||
test-plugins:
|
||||
name: Smoke tests with ${{ matrix.plugin }} plugin installed
|
||||
runs-on: ubuntu-20.04
|
||||
needs: [build]
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- plugin: 'WooCommerce Payments'
|
||||
repo: 'automattic/woocommerce-payments'
|
||||
- plugin: 'WooCommerce PayPal Payments'
|
||||
repo: 'woocommerce/woocommerce-paypal-payments'
|
||||
- plugin: 'WooCommerce Shipping & Tax'
|
||||
repo: 'automattic/woocommerce-services'
|
||||
- plugin: 'WooCommerce Subscriptions'
|
||||
repo: WC_SUBSCRIPTIONS_REPO
|
||||
private: true
|
||||
- plugin: 'WordPress SEO' # Yoast SEO in the UI, but the slug is wordpress-seo
|
||||
repo: 'Yoast/wordpress-seo'
|
||||
- plugin: 'Contact Form 7'
|
||||
repo: 'takayukister/contact-form-7'
|
||||
steps:
|
||||
- name: Create dirs.
|
||||
run: |
|
||||
mkdir -p code/woocommerce
|
||||
mkdir -p package/woocommerce
|
||||
mkdir -p tmp/woocommerce
|
||||
mkdir -p node_modules
|
||||
|
||||
test-plugins:
|
||||
name: Smoke tests with ${{ matrix.plugin }} plugin installed
|
||||
runs-on: ubuntu-18.04
|
||||
needs: [build]
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- plugin: 'WooCommerce Payments'
|
||||
repo: 'automattic/woocommerce-payments'
|
||||
- plugin: 'WooCommerce PayPal Payments'
|
||||
repo: 'woocommerce/woocommerce-paypal-payments'
|
||||
- plugin: 'WooCommerce Shipping & Tax'
|
||||
repo: 'automattic/woocommerce-services'
|
||||
- plugin: 'WooCommerce Subscriptions'
|
||||
repo: WC_SUBSCRIPTIONS_REPO
|
||||
private: true
|
||||
- plugin: 'WordPress SEO' # Yoast SEO in the UI, but the slug is wordpress-seo
|
||||
repo: 'Yoast/wordpress-seo'
|
||||
- plugin: 'Contact Form 7'
|
||||
repo: 'takayukister/contact-form-7'
|
||||
steps:
|
||||
- name: Create dirs.
|
||||
run: |
|
||||
mkdir -p code/woocommerce
|
||||
mkdir -p package/woocommerce
|
||||
mkdir -p tmp/woocommerce
|
||||
mkdir -p node_modules
|
||||
- name: Checkout code.
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
path: package/woocommerce
|
||||
|
||||
- name: Checkout code.
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
path: package/woocommerce
|
||||
- name: Install PNPM and install dependencies
|
||||
working-directory: package/woocommerce
|
||||
run: |
|
||||
npm install -g pnpm
|
||||
pnpm install
|
||||
|
||||
- name: Install PNPM and install dependencies
|
||||
working-directory: package/woocommerce
|
||||
run: |
|
||||
npm install -g pnpm
|
||||
pnpm install
|
||||
- name: Load docker images and start containers.
|
||||
working-directory: package/woocommerce/plugins/woocommerce
|
||||
run: pnpm exec wc-e2e docker:up
|
||||
|
||||
- name: Load docker images and start containers.
|
||||
working-directory: package/woocommerce/plugins/woocommerce
|
||||
run: pnpx wc-e2e docker:up
|
||||
- name: Move current directory to code. We will install zip file in this dir later.
|
||||
run: mv ./package/woocommerce/plugins/woocommerce/* ./code/woocommerce
|
||||
|
||||
- name: Move current directory to code. We will install zip file in this dir later.
|
||||
run: mv ./package/woocommerce/plugins/woocommerce/* ./code/woocommerce
|
||||
- name: Download WooCommerce ZIP.
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: woocommerce
|
||||
path: tmp
|
||||
|
||||
- name: Download WooCommerce ZIP.
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: woocommerce
|
||||
path: tmp
|
||||
- name: Extract and replace WooCommerce zip.
|
||||
working-directory: tmp
|
||||
run: |
|
||||
unzip woocommerce.zip -d woocommerce
|
||||
mv woocommerce/woocommerce/* ../package/woocommerce/plugins/woocommerce/
|
||||
|
||||
- name: Extract and replace WooCommerce zip.
|
||||
working-directory: tmp
|
||||
run: |
|
||||
unzip woocommerce.zip -d woocommerce
|
||||
mv woocommerce/woocommerce/* ../package/woocommerce/plugins/woocommerce/
|
||||
- name: Install dependencies again
|
||||
working-directory: package/woocommerce
|
||||
run: |
|
||||
npm install -g pnpm
|
||||
pnpm install
|
||||
|
||||
- name: Install dependencies again
|
||||
working-directory: package/woocommerce
|
||||
run: |
|
||||
npm install -g pnpm
|
||||
pnpm install
|
||||
|
||||
- name: Run tests command.
|
||||
working-directory: package/woocommerce/plugins/woocommerce
|
||||
env:
|
||||
WC_E2E_SCREENSHOTS: 1
|
||||
E2E_SLACK_TOKEN: ${{ secrets.SMOKE_TEST_SLACK_TOKEN }}
|
||||
E2E_SLACK_CHANNEL: ${{ secrets.RELEASE_TEST_SLACK_CHANNEL }}
|
||||
PLUGIN_REPOSITORY: ${{ matrix.private && secrets[matrix.repo] || matrix.repo }}
|
||||
PLUGIN_NAME: ${{ matrix.plugin }}
|
||||
GITHUB_TOKEN: ${{ secrets.E2E_GH_TOKEN }}
|
||||
run: |
|
||||
pnpx wc-e2e test:e2e tests/e2e/specs/smoke-tests/upload-plugin.js
|
||||
pnpx wc-e2e test:e2e
|
||||
- name: Run tests command.
|
||||
working-directory: package/woocommerce/plugins/woocommerce
|
||||
env:
|
||||
WC_E2E_SCREENSHOTS: 1
|
||||
E2E_SLACK_TOKEN: ${{ secrets.SMOKE_TEST_SLACK_TOKEN }}
|
||||
E2E_SLACK_CHANNEL: ${{ secrets.RELEASE_TEST_SLACK_CHANNEL }}
|
||||
PLUGIN_REPOSITORY: ${{ matrix.private && secrets[matrix.repo] || matrix.repo }}
|
||||
PLUGIN_NAME: ${{ matrix.plugin }}
|
||||
GITHUB_TOKEN: ${{ secrets.E2E_GH_TOKEN }}
|
||||
run: |
|
||||
pnpm exec wc-e2e test:e2e tests/e2e/specs/smoke-tests/upload-plugin.js
|
||||
pnpm exec wc-e2e test:e2e
|
||||
|
|
|
@ -1,178 +1,197 @@
|
|||
name: Smoke test release
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
release_id:
|
||||
description: 'WooCommerce Release Id'
|
||||
required: true
|
||||
jobs:
|
||||
login-run:
|
||||
name: Daily smoke test on release.
|
||||
runs-on: ubuntu-18.04
|
||||
steps:
|
||||
login-run:
|
||||
name: Daily smoke test on release.
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Create dirs.
|
||||
run: |
|
||||
mkdir -p code/woocommerce
|
||||
mkdir -p package/woocommerce
|
||||
mkdir -p tmp/woocommerce
|
||||
mkdir -p node_modules
|
||||
|
||||
- name: Create dirs.
|
||||
run: |
|
||||
mkdir -p code/woocommerce
|
||||
mkdir -p package/woocommerce
|
||||
mkdir -p tmp/woocommerce
|
||||
mkdir -p node_modules
|
||||
- name: Checkout code.
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: package/woocommerce
|
||||
ref: trunk
|
||||
|
||||
- name: Checkout code.
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
path: package/woocommerce
|
||||
ref: trunk
|
||||
- name: Install prerequisites.
|
||||
working-directory: package/woocommerce/plugins/woocommerce
|
||||
run: |
|
||||
npm install -g pnpm
|
||||
pnpm install
|
||||
pnpm nx composer-install-no-dev woocommerce
|
||||
pnpm nx build-assets woocommerce
|
||||
pnpm install jest
|
||||
|
||||
- name: Install prerequisites.
|
||||
working-directory: package/woocommerce/plugins/woocommerce
|
||||
run: |
|
||||
npm install -g pnpm
|
||||
pnpm install
|
||||
pnpm nx composer-install-no-dev woocommerce
|
||||
pnpm nx build-assets woocommerce
|
||||
pnpm install jest
|
||||
- name: Run smoke test.
|
||||
working-directory: package/woocommerce/plugins/woocommerce
|
||||
env:
|
||||
SMOKE_TEST_URL: ${{ secrets.RELEASE_TEST_URL }}
|
||||
SMOKE_TEST_ADMIN_USER: ${{ secrets.RELEASE_TEST_ADMIN_USER }}
|
||||
SMOKE_TEST_ADMIN_PASSWORD: ${{ secrets.RELEASE_TEST_ADMIN_PASSWORD }}
|
||||
SMOKE_TEST_ADMIN_USER_EMAIL: ${{ secrets.RELEASE_TEST_ADMIN_USER_EMAIL }}
|
||||
SMOKE_TEST_CUSTOMER_USER: ${{ secrets.RELEASE_TEST_CUSTOMER_USER }}
|
||||
SMOKE_TEST_CUSTOMER_PASSWORD: ${{ secrets.RELEASE_TEST_CUSTOMER_PASSWORD }}
|
||||
WC_E2E_SCREENSHOTS: 1
|
||||
E2E_RETEST: 1
|
||||
E2E_SLACK_TOKEN: ${{ secrets.SMOKE_TEST_SLACK_TOKEN }}
|
||||
E2E_SLACK_CHANNEL: 'C02DS4NE72S'
|
||||
TEST_RELEASE: 1
|
||||
UPDATE_WC: 1
|
||||
DEFAULT_TIMEOUT_OVERRIDE: 120000
|
||||
BASE_URL: ${{ secrets.RELEASE_TEST_URL }}
|
||||
USER_KEY: ${{ secrets.RELEASE_TEST_ADMIN_USER }}
|
||||
USER_SECRET: ${{ secrets.RELEASE_TEST_ADMIN_PASSWORD }}
|
||||
run: |
|
||||
pnpm exec wc-e2e test:e2e tests/e2e/specs/smoke-tests/update-woocommerce.js
|
||||
pnpm exec wc-e2e test:e2e
|
||||
pnpm exec wc-api-tests test api
|
||||
test-wp-version:
|
||||
name: Smoke test on L-${{ matrix.wp }} WordPress version
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
matrix:
|
||||
wp: ['1', '2']
|
||||
steps:
|
||||
- name: Create dirs.
|
||||
run: |
|
||||
mkdir -p code/woocommerce
|
||||
mkdir -p package/woocommerce
|
||||
mkdir -p tmp/woocommerce
|
||||
mkdir -p node_modules
|
||||
|
||||
- name: Run smoke test.
|
||||
working-directory: package/woocommerce/plugins/woocommerce
|
||||
env:
|
||||
SMOKE_TEST_URL: ${{ secrets.RELEASE_TEST_URL }}
|
||||
SMOKE_TEST_ADMIN_USER: ${{ secrets.RELEASE_TEST_ADMIN_USER }}
|
||||
SMOKE_TEST_ADMIN_PASSWORD: ${{ secrets.RELEASE_TEST_ADMIN_PASSWORD }}
|
||||
SMOKE_TEST_ADMIN_USER_EMAIL: ${{ secrets.RELEASE_TEST_ADMIN_USER_EMAIL }}
|
||||
SMOKE_TEST_CUSTOMER_USER: ${{ secrets.RELEASE_TEST_CUSTOMER_USER }}
|
||||
SMOKE_TEST_CUSTOMER_PASSWORD: ${{ secrets.RELEASE_TEST_CUSTOMER_PASSWORD }}
|
||||
WC_E2E_SCREENSHOTS: 1
|
||||
E2E_RETEST: 1
|
||||
E2E_SLACK_TOKEN: ${{ secrets.SMOKE_TEST_SLACK_TOKEN }}
|
||||
E2E_SLACK_CHANNEL: ${{ secrets.RELEASE_TEST_SLACK_CHANNEL }}
|
||||
TEST_RELEASE: 1
|
||||
UPDATE_WC: 1
|
||||
DEFAULT_TIMEOUT_OVERRIDE: 120000
|
||||
BASE_URL: ${{ secrets.RELEASE_TEST_URL }}
|
||||
USER_KEY: ${{ secrets.RELEASE_TEST_ADMIN_USER }}
|
||||
USER_SECRET: ${{ secrets.RELEASE_TEST_ADMIN_PASSWORD }}
|
||||
run: |
|
||||
pnpx wc-e2e test:e2e tests/e2e/specs/smoke-tests/update-woocommerce.js
|
||||
pnpx wc-e2e test:e2e
|
||||
pnpx wc-api-tests test api
|
||||
test-wp-version:
|
||||
name: Smoke test on L-${{ matrix.wp }} WordPress version
|
||||
runs-on: ubuntu-18.04
|
||||
strategy:
|
||||
matrix:
|
||||
wp: [ '1', '2' ]
|
||||
steps:
|
||||
- name: Checkout code.
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: package/woocommerce
|
||||
- name: Fetch Asset ID
|
||||
id: fetch_asset_id
|
||||
uses: actions/github-script@v5
|
||||
env:
|
||||
RELEASE_ID: ${{ github.event.inputs.release_id }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
REPO: ${{ github.repository }}
|
||||
with:
|
||||
script: |
|
||||
const script = require( './package/woocommerce/.github/workflows/scripts/fetch-asset-id.js' )
|
||||
await script({github, context, core})
|
||||
|
||||
- name: Create dirs.
|
||||
run: |
|
||||
mkdir -p code/woocommerce
|
||||
mkdir -p package/woocommerce
|
||||
mkdir -p tmp/woocommerce
|
||||
mkdir -p node_modules
|
||||
- name: Install PNPM and install dependencies
|
||||
working-directory: package/woocommerce
|
||||
run: |
|
||||
npm install -g pnpm
|
||||
pnpm install
|
||||
|
||||
- name: Checkout code.
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
path: package/woocommerce
|
||||
- name: Load docker images and start containers.
|
||||
working-directory: package/woocommerce/plugins/woocommerce
|
||||
env:
|
||||
LATEST_WP_VERSION_MINUS: ${{ matrix.wp }}
|
||||
run: pnpm nx docker-up woocommerce
|
||||
|
||||
- name: Install PNPM and install dependencies
|
||||
working-directory: package/woocommerce
|
||||
run: |
|
||||
npm install -g pnpm
|
||||
pnpm install
|
||||
- name: Move current directory to code. We will install zip file in this dir later.
|
||||
run: mv ./package/woocommerce/plugins/woocommerce/* ./code/woocommerce
|
||||
|
||||
- name: Load docker images and start containers.
|
||||
working-directory: package/woocommerce/plugins/woocommerce
|
||||
env:
|
||||
LATEST_WP_VERSION_MINUS: ${{ matrix.wp }}
|
||||
run: pnpm nx docker-up woocommerce
|
||||
- name: Download WooCommerce release zip
|
||||
working-directory: tmp
|
||||
run: |
|
||||
curl https://api.github.com/repos/${{ github.repository }}/releases/assets/${{ steps.fetch_asset_id.outputs.asset_id }} -LJOH 'Accept: application/octet-stream'
|
||||
|
||||
- name: Move current directory to code. We will install zip file in this dir later.
|
||||
run: mv ./package/woocommerce/plugins/woocommerce/* ./code/woocommerce
|
||||
unzip woocommerce.zip -d woocommerce
|
||||
mv woocommerce/woocommerce/* ../package/woocommerce/plugins/woocommerce/
|
||||
|
||||
- name: Download WooCommerce release zip
|
||||
working-directory: tmp
|
||||
run: |
|
||||
ASSET_ID=$(jq ".release.assets[0].id" $GITHUB_EVENT_PATH)
|
||||
- name: Run tests command.
|
||||
working-directory: package/woocommerce/plugins/woocommerce
|
||||
env:
|
||||
WC_E2E_SCREENSHOTS: 1
|
||||
E2E_SLACK_TOKEN: ${{ secrets.SMOKE_TEST_SLACK_TOKEN }}
|
||||
E2E_SLACK_CHANNEL: ${{ secrets.RELEASE_TEST_SLACK_CHANNEL }}
|
||||
run: pnpm nx test-e2e woocommerce
|
||||
|
||||
curl https://api.github.com/repos/woocommerce/woocommerce/releases/assets/${ASSET_ID} -LJOH 'Accept: application/octet-stream'
|
||||
test-plugins:
|
||||
name: Smoke tests with ${{ matrix.plugin }} plugin installed
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- plugin: 'WooCommerce Payments'
|
||||
repo: 'automattic/woocommerce-payments'
|
||||
- plugin: 'WooCommerce PayPal Payments'
|
||||
repo: 'woocommerce/woocommerce-paypal-payments'
|
||||
- plugin: 'WooCommerce Shipping & Tax'
|
||||
repo: 'automattic/woocommerce-services'
|
||||
- plugin: 'WooCommerce Subscriptions'
|
||||
repo: WC_SUBSCRIPTIONS_REPO
|
||||
private: true
|
||||
- plugin: 'WordPress SEO' # Yoast SEO in the UI, but the slug is wordpress-seo
|
||||
repo: 'Yoast/wordpress-seo'
|
||||
- plugin: 'Contact Form 7'
|
||||
repo: 'takayukister/contact-form-7'
|
||||
steps:
|
||||
- name: Create dirs.
|
||||
run: |
|
||||
mkdir -p code/woocommerce
|
||||
mkdir -p package/woocommerce
|
||||
mkdir -p tmp/woocommerce
|
||||
mkdir -p node_modules
|
||||
|
||||
unzip woocommerce.zip -d woocommerce
|
||||
mv woocommerce/woocommerce/* ../package/woocommerce/plugins/woocommerce/
|
||||
- name: Checkout code.
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
path: package/woocommerce
|
||||
- name: Fetch Asset ID
|
||||
id: fetch_asset_id
|
||||
uses: actions/github-script@v5
|
||||
env:
|
||||
RELEASE_ID: ${{ github.event.inputs.release_id }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
REPO: ${{ github.repository }}
|
||||
with:
|
||||
script: |
|
||||
const script = require( './package/woocommerce/.github/workflows/scripts/fetch-asset-id.js' )
|
||||
await script({github, context, core})
|
||||
|
||||
- name: Run tests command.
|
||||
working-directory: package/woocommerce/plugins/woocommerce
|
||||
env:
|
||||
WC_E2E_SCREENSHOTS: 1
|
||||
E2E_SLACK_TOKEN: ${{ secrets.SMOKE_TEST_SLACK_TOKEN }}
|
||||
E2E_SLACK_CHANNEL: ${{ secrets.RELEASE_TEST_SLACK_CHANNEL }}
|
||||
run: pnpm nx test-e2e woocommerce
|
||||
- name: Install PNPM and install dependencies
|
||||
working-directory: package/woocommerce
|
||||
run: |
|
||||
npm install -g pnpm
|
||||
pnpm install
|
||||
|
||||
test-plugins:
|
||||
name: Smoke tests with ${{ matrix.plugin }} plugin installed
|
||||
runs-on: ubuntu-18.04
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- plugin: 'WooCommerce Payments'
|
||||
repo: 'automattic/woocommerce-payments'
|
||||
- plugin: 'WooCommerce PayPal Payments'
|
||||
repo: 'woocommerce/woocommerce-paypal-payments'
|
||||
- plugin: 'WooCommerce Shipping & Tax'
|
||||
repo: 'automattic/woocommerce-services'
|
||||
- plugin: 'WooCommerce Subscriptions'
|
||||
repo: WC_SUBSCRIPTIONS_REPO
|
||||
private: true
|
||||
- plugin: 'WordPress SEO' # Yoast SEO in the UI, but the slug is wordpress-seo
|
||||
repo: 'Yoast/wordpress-seo'
|
||||
- plugin: 'Contact Form 7'
|
||||
repo: 'takayukister/contact-form-7'
|
||||
steps:
|
||||
- name: Create dirs.
|
||||
run: |
|
||||
mkdir -p code/woocommerce
|
||||
mkdir -p package/woocommerce
|
||||
mkdir -p tmp/woocommerce
|
||||
mkdir -p node_modules
|
||||
- name: Load docker images and start containers.
|
||||
working-directory: package/woocommerce/plugins/woocommerce
|
||||
env:
|
||||
LATEST_WP_VERSION_MINUS: ${{ matrix.wp }}
|
||||
run: pnpm nx docker-up woocommerce
|
||||
|
||||
- name: Checkout code.
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
path: package/woocommerce
|
||||
- name: Move current directory to code. We will install zip file in this dir later.
|
||||
run: mv ./package/woocommerce/plugins/woocommerce/* ./code/woocommerce
|
||||
|
||||
- name: Install PNPM and install dependencies
|
||||
working-directory: package/woocommerce
|
||||
run: |
|
||||
npm install -g pnpm
|
||||
pnpm install
|
||||
- name: Download WooCommerce release zip
|
||||
working-directory: tmp
|
||||
run: |
|
||||
curl https://api.github.com/repos/${{ github.repository }}/releases/assets/${{ steps.fetch_asset_id.outputs.asset_id }} -LJOH 'Accept: application/octet-stream'
|
||||
|
||||
- name: Load docker images and start containers.
|
||||
working-directory: package/woocommerce/plugins/woocommerce
|
||||
env:
|
||||
LATEST_WP_VERSION_MINUS: ${{ matrix.wp }}
|
||||
run: pnpm nx docker-up woocommerce
|
||||
unzip woocommerce.zip -d woocommerce
|
||||
mv woocommerce/woocommerce/* ../package/woocommerce/plugins/woocommerce/
|
||||
|
||||
- name: Move current directory to code. We will install zip file in this dir later.
|
||||
run: mv ./package/woocommerce/plugins/woocommerce/* ./code/woocommerce
|
||||
|
||||
- name: Download WooCommerce release zip
|
||||
working-directory: tmp
|
||||
run: |
|
||||
ASSET_ID=$(jq ".release.assets[0].id" $GITHUB_EVENT_PATH)
|
||||
|
||||
curl https://api.github.com/repos/woocommerce/woocommerce/releases/assets/${ASSET_ID} -LJOH 'Accept: application/octet-stream'
|
||||
|
||||
unzip woocommerce.zip -d woocommerce
|
||||
mv woocommerce/woocommerce/* ../package/woocommerce/plugins/woocommerce/
|
||||
|
||||
- name: Run tests command.
|
||||
working-directory: package/woocommerce/plugins/woocommerce
|
||||
env:
|
||||
WC_E2E_SCREENSHOTS: 1
|
||||
E2E_SLACK_TOKEN: ${{ secrets.SMOKE_TEST_SLACK_TOKEN }}
|
||||
E2E_SLACK_CHANNEL: ${{ secrets.RELEASE_TEST_SLACK_CHANNEL }}
|
||||
PLUGIN_REPOSITORY: ${{ matrix.private && secrets[matrix.repo] || matrix.repo }}
|
||||
PLUGIN_NAME: ${{ matrix.plugin }}
|
||||
GITHUB_TOKEN: ${{ secrets.E2E_GH_TOKEN }}
|
||||
run: |
|
||||
pnpx wc-e2e test:e2e tests/e2e/specs/smoke-tests/upload-plugin.js
|
||||
pnpx wc-e2e test:e2e
|
||||
- name: Run tests command.
|
||||
working-directory: package/woocommerce/plugins/woocommerce
|
||||
env:
|
||||
WC_E2E_SCREENSHOTS: 1
|
||||
E2E_SLACK_TOKEN: ${{ secrets.SMOKE_TEST_SLACK_TOKEN }}
|
||||
E2E_SLACK_CHANNEL: ${{ secrets.RELEASE_TEST_SLACK_CHANNEL }}
|
||||
PLUGIN_REPOSITORY: ${{ matrix.private && secrets[matrix.repo] || matrix.repo }}
|
||||
PLUGIN_NAME: ${{ matrix.plugin }}
|
||||
GITHUB_TOKEN: ${{ secrets.E2E_GH_TOKEN }}
|
||||
run: |
|
||||
pnpm exec wc-e2e test:e2e tests/e2e/specs/smoke-tests/upload-plugin.js
|
||||
pnpm exec wc-e2e test:e2e
|
||||
|
|
|
@ -6,17 +6,19 @@ on:
|
|||
jobs:
|
||||
stale:
|
||||
if: |
|
||||
! contains(github.event.issue.labels.*.name, 'enhancement')
|
||||
runs-on: ubuntu-latest
|
||||
! contains(github.event.issue.labels.*.name, 'type: enhancement')
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/stale@v3
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
stale-issue-message: "As a part of this repository’s maintenance, this issue is being marked as stale due to inactivity. Please feel free to comment on it in case we missed something.\n\n###### After 7 days with no activity this issue will be automatically be closed."
|
||||
stale-issue-message: "As a part of this repository's maintenance, this issue is being marked as stale due to inactivity. Please feel free to comment on it in case we missed something.\n\n###### After 7 days with no activity this issue will be automatically be closed."
|
||||
close-issue-message: 'This issue was closed because it has been 14 days with no activity.'
|
||||
days-before-issue-stale: 7
|
||||
days-before-issue-close: 7
|
||||
days-before-pr-close: -1
|
||||
only-issue-labels: 'needs feedback'
|
||||
close-issue-label: "category: can't reproduce"
|
||||
stale-issue-label: 'status: stale'
|
||||
stale-pr-label: 'status: stale'
|
||||
only-issue-labels: 'needs: author feedback'
|
||||
close-issue-label: "status: can't reproduce"
|
||||
ascending: true
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
name: Add Triage Label
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: opened
|
||||
|
||||
jobs:
|
||||
add_label:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions-ecosystem/action-add-labels@v1
|
||||
if: github.event.issue.labels[0] == null
|
||||
with:
|
||||
labels: 'status: awaiting triage'
|
|
@ -5,8 +5,8 @@ on:
|
|||
- labeled
|
||||
jobs:
|
||||
add-dev-comment:
|
||||
if: "github.event.label.name == 'needs developer feedback'"
|
||||
runs-on: ubuntu-latest
|
||||
if: "github.event.label.name == 'needs: developer feedback'"
|
||||
runs-on: ubuntu-20.04
|
||||
permissions:
|
||||
issues: write
|
||||
steps:
|
||||
|
@ -25,8 +25,8 @@ jobs:
|
|||
Please note it may take a few days for them to get to this issue. Thank you for your patience.'
|
||||
})
|
||||
add-reproduction-comment:
|
||||
if: "github.event.label.name == 'status: needs reproduction'"
|
||||
runs-on: ubuntu-latest
|
||||
if: "github.event.label.name == 'status: reproduction'"
|
||||
runs-on: ubuntu-20.04
|
||||
permissions:
|
||||
issues: write
|
||||
steps:
|
||||
|
@ -45,7 +45,7 @@ jobs:
|
|||
})
|
||||
add-support-comment:
|
||||
if: "github.event.label.name == 'type: support request'"
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
permissions:
|
||||
issues: write
|
||||
steps:
|
||||
|
@ -84,8 +84,8 @@ jobs:
|
|||
state: 'closed'
|
||||
})
|
||||
add-votes-comment:
|
||||
if: "github.event.label.name == 'votes needed'"
|
||||
runs-on: ubuntu-latest
|
||||
if: "github.event.label.name == 'needs: votes'"
|
||||
runs-on: ubuntu-20.04
|
||||
permissions:
|
||||
issues: write
|
||||
steps:
|
||||
|
@ -98,14 +98,14 @@ jobs:
|
|||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: 'Thanks for the suggestion @${{ github.event.issue.user.login }},\n\n\
|
||||
While we appreciate you sharing your ideas with us, it doesn’t fit in with our current priorities for the project.\n\
|
||||
body: "Thanks for the suggestion @${{ github.event.issue.user.login }},\n\n\
|
||||
While we appreciate you sharing your ideas with us, it doesn't fit in with our current priorities for the project.\n\
|
||||
At some point, we may revisit our priorities and look through the list of suggestions like this one to see if it \
|
||||
warrants a second look.\n\n\
|
||||
In the meantime, we are going to close this issue with the `votes needed` label and evaluate over time if this \
|
||||
issue collects more feedback.\n\n\
|
||||
Don’t be alarmed if you don’t see any activity on this issue for a while. \
|
||||
We'll keep an eye on the popularity of this request.'
|
||||
Don't be alarmed if you don't see any activity on this issue for a while. \
|
||||
We'll keep an eye on the popularity of this request."
|
||||
})
|
||||
- name: Close votes needed issue
|
||||
uses: actions/github-script@v5
|
||||
|
@ -118,3 +118,49 @@ jobs:
|
|||
issue_number: context.issue.number,
|
||||
state: 'closed'
|
||||
})
|
||||
fill-template-comment:
|
||||
if: "github.event.label.name == 'needs: template'"
|
||||
runs-on: ubuntu-20.04
|
||||
permissions:
|
||||
issues: write
|
||||
steps:
|
||||
- name: Add reply to fill template
|
||||
uses: actions/github-script@v5
|
||||
with:
|
||||
github-token: ${{ secrets.WC_BOT_TRIAGE_TOKEN }}
|
||||
script: |
|
||||
github.rest.issues.createComment({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: "Hi @${{ github.event.issue.user.login }},\n\n\
|
||||
Thank you for submitting the issue. However, you didn't fill out the details of the bug report template that we ask for. Without these details, we can't fully evaluate this issue. Please provide us with the information requested so we could take a look further.\n\n\
|
||||
**Describe the bug**\n\n\
|
||||
A clear and concise description of what the bug is. Please be as descriptive as possible; issues lacking detail, or for any other reason than to report a bug, may be closed without action.\n\n\
|
||||
**To Reproduce**\n\n\
|
||||
Steps to reproduce the behavior:\n\n\
|
||||
1. Go to '...'\n\
|
||||
2. Click on '....'\n\
|
||||
3. Scroll down to '....'\n\
|
||||
4. See error\n\n\
|
||||
**Screenshots**\n\n\
|
||||
If applicable, add screenshots to help explain your problem.\n\n\
|
||||
**Expected behavior**\n\n\
|
||||
A clear and concise description of what you expected to happen.\n\n\
|
||||
**Isolating the problem (mark completed items with an [x]):**\n\n\
|
||||
- [ ] I have deactivated other plugins and confirmed this bug occurs when only WooCommerce plugin is active.\n\
|
||||
- [ ] This bug happens with a default WordPress theme active, or [Storefront](https://woocommerce.com/storefront/).\n\
|
||||
- [ ] I can reproduce this bug consistently using the steps above.\n\n\
|
||||
**WordPress Environment**\n\n\
|
||||
Copy and paste the system status report from **WooCommerce > System Status** in WordPress admin."
|
||||
})
|
||||
- name: remove-needs-template-label
|
||||
uses: actions-ecosystem/action-remove-labels@v1
|
||||
with:
|
||||
github-token: ${{ secrets.WC_BOT_TRIAGE_TOKEN }}
|
||||
labels: 'needs: template'
|
||||
- name: add-needs-author-feedback-label
|
||||
uses: actions-ecosystem/action-add-labels@v1
|
||||
with:
|
||||
github-token: ${{ secrets.WC_BOT_TRIAGE_TOKEN }}
|
||||
labels: 'needs: author feedback'
|
||||
|
|
|
@ -5,23 +5,24 @@ jobs:
|
|||
feedback:
|
||||
if: |
|
||||
github.actor != 'github-actions' &&
|
||||
github.actor == github.event.issue.user.login &&
|
||||
github.event.issue &&
|
||||
github.event.issue.state == 'open' &&
|
||||
contains(github.event.issue.labels.*.name, 'needs feedback')
|
||||
runs-on: ubuntu-latest
|
||||
contains(github.event.issue.labels.*.name, 'needs: author feedback')
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Add has feedback
|
||||
uses: actions-ecosystem/action-add-labels@v1
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
labels: 'has feedback'
|
||||
labels: 'needs: triage feedback'
|
||||
- name: remove needs feedback
|
||||
uses: actions-ecosystem/action-remove-labels@v1
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
labels: 'needs feedback'
|
||||
labels: 'needs: author feedback'
|
||||
- name: remove stale
|
||||
uses: actions-ecosystem/action-remove-labels@v1
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
labels: Stale
|
||||
labels: 'status: stale'
|
||||
|
|
|
@ -4,7 +4,7 @@ Thumbs.db
|
|||
|
||||
# IDE files
|
||||
.idea
|
||||
.vscode/
|
||||
.vscode/*
|
||||
project.xml
|
||||
project.properties
|
||||
.project
|
||||
|
@ -13,6 +13,9 @@ project.properties
|
|||
*.sublime-workspace
|
||||
.sublimelinterrc
|
||||
|
||||
# Excluded IDE Files for developer experience tooling within workspace
|
||||
!.vscode/tasks.json
|
||||
|
||||
# Grunt
|
||||
none
|
||||
|
||||
|
@ -40,6 +43,7 @@ npm-debug.log
|
|||
build/
|
||||
build-module/
|
||||
build-style/
|
||||
build-types/
|
||||
dist/
|
||||
|
||||
# Project files
|
||||
|
@ -73,3 +77,9 @@ nbproject/private/
|
|||
|
||||
# Test Results
|
||||
test-results.json
|
||||
|
||||
# Admin Feature config
|
||||
plugins/woocommerce/includes/react-admin/feature-config.php
|
||||
|
||||
# PHP lint
|
||||
phpcs-report.xml
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
pnpm install
|
||||
pnpm nx affected --target="composer-install" --base=ORIG_HEAD --head=HEAD
|
|
@ -0,0 +1,4 @@
|
|||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
pnpm exec lint-staged
|
|
@ -0,0 +1,4 @@
|
|||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
./bin/pre-push.sh
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"command": "pnpm tsc -b tsconfig.base.json",
|
||||
"type": "shell",
|
||||
"problemMatcher": [ "$tsc" ],
|
||||
"label": "Typescript compile",
|
||||
"detail": "Run tsc against tsconfig.base.json",
|
||||
"runOptions": {
|
||||
"runOn": "default"
|
||||
}
|
||||
},
|
||||
{
|
||||
"command": "pnpm tsc -b tsconfig.base.json --watch",
|
||||
"type": "shell",
|
||||
"problemMatcher": {
|
||||
"base": "$tsc-watch",
|
||||
"applyTo": "allDocuments"
|
||||
},
|
||||
"isBackground": true,
|
||||
"label": "Incremental Typescript compile",
|
||||
"detail": "Incremental background type checks",
|
||||
"runOptions": {
|
||||
"runOn": "folderOpen"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -45,6 +45,21 @@ You might also want to run `pnpm start` to watch your CSS and JS changes if you
|
|||
|
||||
You're now ready to develop!
|
||||
|
||||
### Typescript Checking
|
||||
|
||||
Typescript is progressively being implemented in this repository, and you might come across some files that are `.ts` or `.tsx`. By default, a VSCode environment will run type checking on such files that are currently open.
|
||||
|
||||
As of now, some parts of the codebase that were imported from the Woocommerce-Admin repository, into the `plugins/woocommerce-admin/client` directory, still fail Typescript checking. This has been scheduled on the team's backlog to be fixed.
|
||||
|
||||
In order to run type checking across the entire repository, you can run this command in your shell, from the root of this repository:
|
||||
|
||||
```sh
|
||||
pnpm tsc -b tsconfig.base.json
|
||||
```
|
||||
|
||||
For better developer experience, the folder `.vscode/tasks.json` has two VSCode tasks to run these commands automatically as well as to parse the output and highlight the errors in the `Problems` tab and in the file explorer pane. The first task runs it once, the second one runs it in the background upon saving of any modified files. This task is also automatically prompted by VSCode to be run upon opening the folder.
|
||||
|
||||
|
||||
## Using Xdebug
|
||||
|
||||
Please refer to [WP-ENV official README](https://github.com/WordPress/gutenberg/tree/master/packages/env#using-xdebug) section for setting up Xdebug.
|
||||
|
@ -102,13 +117,12 @@ You can get the current MySQL port from the output of `wp-env start` command.
|
|||
|
||||
1. Open your choice of MySQL tool.
|
||||
2. Use the following values to access the MySQL container.
|
||||
3. You can omit the username and password.
|
||||
|
||||
| Name | Value |
|
||||
| -------- | --------------------- |
|
||||
| Host | 127.0.0.1 |
|
||||
| Username | |
|
||||
| Password | |
|
||||
| Username | root |
|
||||
| Password | password |
|
||||
| Port | Port from the command |
|
||||
|
||||
## HOWTOs
|
||||
|
|
|
@ -18,6 +18,7 @@ If you are not a developer, please use the [WooCommerce plugin page](https://wor
|
|||
* [WooCommerce Developer Documentation](https://github.com/woocommerce/woocommerce/wiki)
|
||||
* [WooCommerce Code Reference](https://docs.woocommerce.com/wc-apidocs/)
|
||||
* [WooCommerce REST API Docs](https://woocommerce.github.io/woocommerce-rest-api-docs/)
|
||||
* [Setting up a development environment](https://github.com/woocommerce/woocommerce/wiki/How-to-set-up-WooCommerce-development-environment)
|
||||
|
||||
## Reporting Security Issues
|
||||
To disclose a security issue to our team, [please submit a report via HackerOne here](https://hackerone.com/automattic/).
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
#!/bin/sh
|
||||
|
||||
PROTECTED_BRANCH="trunk"
|
||||
CURRENT_BRANCH=$(git branch --show-current)
|
||||
if [ $PROTECTED_BRANCH = $CURRENT_BRANCH ]; then
|
||||
if [ "$TERM" = "dumb" ]; then
|
||||
>&2 echo "Sorry, you are unable to push to $PROTECTED_BRANCH using a GUI client! Please use git CLI."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
printf "%sYou're about to push to $PROTECTED_BRANCH, is that what you intended? [y/N]: %s" "$(tput setaf 3)" "$(tput sgr0)"
|
||||
read -r PROCEED < /dev/tty
|
||||
echo
|
||||
|
||||
if [ "$(echo "${PROCEED:-n}" | tr "[:upper:]" "[:lower:]")" = "y" ]; then
|
||||
echo "$(tput setaf 2)Brace yourself! Pushing to the $PROTECTED_BRANCH branch...$(tput sgr0)"
|
||||
echo
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "$(tput setaf 2)Push to $PROTECTED_BRANCH cancelled!$(tput sgr0)"
|
||||
echo
|
||||
exit 1
|
||||
fi
|
498
changelog.txt
498
changelog.txt
|
@ -1,5 +1,347 @@
|
|||
== Changelog ==
|
||||
|
||||
= 6.4.1 2022-04-15 =
|
||||
|
||||
**WooCommerce**
|
||||
|
||||
- Revert - incorrect position value for registering menu pages. ([#32623](https://github.com/woocommerce/woocommerce/pull/32623))
|
||||
|
||||
**WooCommerce Blocks - 7.2.2**
|
||||
|
||||
- Fix - page load problem due to incorrect URL to certain assets. ([#6260](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/6260))
|
||||
|
||||
= 6.4.0 2022-04-12 =
|
||||
|
||||
**WooCommerce**
|
||||
|
||||
- Add - Scaffolding for the custom orders table feature. ([#31692](https://github.com/woocommerce/woocommerce/pull/31692))
|
||||
- Add - Add DB table structure for custom order tables. ([#31811](https://github.com/woocommerce/woocommerce/pull/31811))
|
||||
- Add - Primary key for the product attributes lookup table. ([#32067](https://github.com/woocommerce/woocommerce/pull/32067))
|
||||
- Add - Tracks to the dashboard status widget and setup widget. ([#31857](https://github.com/woocommerce/woocommerce/pull/31857))
|
||||
- Add - Check around setup widget display when features are disabled. ([#31884](https://github.com/woocommerce/woocommerce/pull/31884))
|
||||
- Add - 'woocommerce_get_formatted_meta_data_include_all_meta_lines' filter hook. This can be used to control whether metadata lines are shown in the order meta box. ([#30948](https://github.com/woocommerce/woocommerce/pull/30948))
|
||||
- Enhancement - Introduce rate_limit_remaining column in the wc_rate_limits table. ([#32041](https://github.com/woocommerce/woocommerce/pull/32041))
|
||||
- Tweak - Update PayPal Standard JS used in the admin environment to avoid deprecated functionality. ([#32076](https://github.com/woocommerce/woocommerce/pull/32076))
|
||||
- Tweak - Change level of escaping used to render the CSV import error log. ([#32000](https://github.com/woocommerce/woocommerce/pull/32000))
|
||||
- Tweak - Make the payment_url field available via the REST API's orders endpoint. ([#31826](https://github.com/woocommerce/woocommerce/pull/31826))
|
||||
- Tweak - Rename WC_API_Exception code woocommerce_api_cannot_edit_product_catgory into woocommerce_api_cannot_edit_product_category ([#31785](https://github.com/woocommerce/woocommerce/pull/31785))
|
||||
- Tweak - Updated default email color to new Woo purple ([#30586](https://github.com/woocommerce/woocommerce/pull/30586))
|
||||
- Fix - Avoid depending on the presence of a theme header template to clear the cart after payment is made. ([#31877](https://github.com/woocommerce/woocommerce/pull/31877))
|
||||
- Fix - Payments tab tracking. ([#31844](https://github.com/woocommerce/woocommerce/pull/31844))
|
||||
- Fix - Remove unnecessary duplicate style in email-styles template. ([#31860](https://github.com/woocommerce/woocommerce/pull/31860))
|
||||
- Fix - incorrect position value for registering menu pages. ([#31779](https://github.com/woocommerce/woocommerce/pull/31779))
|
||||
- Fix - SZL currency symbol. Updated from 'L' to 'E'. ([#30602](https://github.com/woocommerce/woocommerce/pull/30602))
|
||||
- Fix - Removed execution of at least one hook ignoring the `woocommerce_load_webhooks_limit` filter value. ([#29002](https://github.com/woocommerce/woocommerce/pull/29002))
|
||||
- Dev - Added has_options() to REST API v3 product endpoint response. ([#32031](https://github.com/woocommerce/woocommerce/pull/32031))
|
||||
- Dev - Added woocommerce_admin_order_should_render_refunds hook to allow control over the refunds UI within the order editor. ([#31414](https://github.com/woocommerce/woocommerce/pull/31414))
|
||||
|
||||
**WooCommerce Admin - 3.3.0 & 3.3.1 & 3.3.2**
|
||||
|
||||
- Add - Add asynchronous plugin install and activation endpoints ([#8079](https://github.com/woocommerce/woocommerce-admin/pull/8079))
|
||||
- Performance - Avoid expensive get_notes() queries in CouponPageMoved admin_init actions by using new Notes::get_note_by_name() helper method. ([#8202](https://github.com/woocommerce/woocommerce-admin/pull/8202))
|
||||
- Enhancement - Add chart color filter for overriding default chart colors. ([#8258](https://github.com/woocommerce/woocommerce-admin/pull/8258))
|
||||
- Enhancement - Added Typescript type declarations to build for @woocommerce/components ([#8282](https://github.com/woocommerce/woocommerce-admin/pull/8282))
|
||||
- Enhancement - Increase color selection limit to ten and add additional colors. ([#8258](https://github.com/woocommerce/woocommerce-admin/pull/8258))
|
||||
- Enhancement - Made @woocommerce/components/Stepper a Typescript file ([#8286](https://github.com/woocommerce/woocommerce-admin/pull/8286))
|
||||
- Enhancement - Prompts a modal to save any unsaved changes when the users try to move to a different step ([#8278](https://github.com/woocommerce/woocommerce-admin/pull/8278))
|
||||
- Tweak - OBW: Override Country/Region label line-height style to avoid truncated descenders. ([#8186](https://github.com/woocommerce/woocommerce-admin/pull/8186))
|
||||
- Tweak - Show single success message for theme install and activation ([#8236](https://github.com/woocommerce/woocommerce-admin/pull/8236))
|
||||
- Tweak - Use WC_VERSION as cache buster for assets ([#8308](https://github.com/woocommerce/woocommerce-admin/pull/8308))
|
||||
- Update - Adjust time range and add an image for the Jetpack Backup note. ([#8293](https://github.com/woocommerce/woocommerce-admin/pull/8293))
|
||||
- Update - Implement MailChimp API request threshold for MailchimpScheduler. ([#8342](https://github.com/woocommerce/woocommerce-admin/pull/8342))
|
||||
- Update - Reintroduce CES on product add, product update, and order update. ([#8238](https://github.com/woocommerce/woocommerce-admin/pull/8238))
|
||||
- Update - Replace mysql image with mariadb ([#8220](https://github.com/woocommerce/woocommerce-admin/pull/8220))
|
||||
- Update - Update country support list for WooCommerce Payments Task. ([#8517](https://github.com/woocommerce/woocommerce-admin/pull/8517))
|
||||
- Fix - Fix handling of paid themes in purchase task. ([#8493](https://github.com/woocommerce/woocommerce-admin/pull/8493))
|
||||
- Fix - Make sure the paid extension task is also shown for themes. ([#8412](https://github.com/woocommerce/woocommerce-admin/pull/8412))
|
||||
- Fix - Reintroduce emphasis on inbox note action button. ([#8411](https://github.com/woocommerce/woocommerce-admin/pull/8411))
|
||||
- Fix - Remove class ExtendedPayments. ([#8461](https://github.com/woocommerce/woocommerce-admin/pull/8461))
|
||||
- Fix - Added random IDs to SVG checkmarks in stepper component ([#8222](https://github.com/woocommerce/woocommerce-admin/pull/8222))
|
||||
- Fix - Fix Google Listings plugin is always shown in free features despite already activated. ([#8330](https://github.com/woocommerce/woocommerce-admin/pull/8330))
|
||||
- Fix - Fix hidden notes in `admin/notes` endpoint when the user is not in the tasklist experiment. ([#8328](https://github.com/woocommerce/woocommerce-admin/pull/8328))
|
||||
- Fix - Fix missing product name in variation analytic page for the deleted products. ([#8255](https://github.com/woocommerce/woocommerce-admin/pull/8255))
|
||||
- Fix - Fix payments extensions displayed below the offline payments options. ([#8232](https://github.com/woocommerce/woocommerce-admin/pull/8232))
|
||||
- Fix - Fix setup wizard title and flash of content ([#8201](https://github.com/woocommerce/woocommerce-admin/pull/8201))
|
||||
- Fix - Fix too many pending run_remote_notifications actions. ([#8285](https://github.com/woocommerce/woocommerce-admin/pull/8285))
|
||||
- Fix - Fix view logic for Setup additional payment providers task. ([#8391](https://github.com/woocommerce/woocommerce-admin/pull/8391))
|
||||
- Fix - OBW: fix copy on Business Details when "WooCommerce Shipping" is not listed ([#8324](https://github.com/woocommerce/woocommerce-admin/pull/8324))
|
||||
- Fix - Only add product data on REST requests and task list ([#8235](https://github.com/woocommerce/woocommerce-admin/pull/8235))
|
||||
- Fix - Stop showing actioned inbox items ([#8394](https://github.com/woocommerce/woocommerce-admin/pull/8394))
|
||||
- Fix - WC Payments task is not visible after installing the plugin ([#8514](https://github.com/woocommerce/woocommerce-admin/pull/8514))
|
||||
- Fix - PHP warning when default param is missing in payments spec. ([#8519](https://github.com/woocommerce/woocommerce-admin/pull/8519))
|
||||
- Dev - Added a test for tracks event recording for PaymentGatewaySuggestions ([#8306](https://github.com/woocommerce/woocommerce-admin/pull/8306))
|
||||
- Dev - Add README to hook reference generation script ([#8004](https://github.com/woocommerce/woocommerce-admin/pull/8004))
|
||||
- Dev - Add reset WooCommerce functionality to E2E tests, so tests have a fresh state. ([#8219](https://github.com/woocommerce/woocommerce-admin/pull/8219))
|
||||
- Dev - Enabled optional typescript checking on ./client subfolder ([#8372](https://github.com/woocommerce/woocommerce-admin/pull/8372))
|
||||
- Dev - Fix formatting and add filter param for changelog types for the testing instructions script. ([#8256](https://github.com/woocommerce/woocommerce-admin/pull/8256))
|
||||
- Dev - Refactor MerchantEmailNotifications ([#8304](https://github.com/woocommerce/woocommerce-admin/pull/8304))
|
||||
- Dev - Remove preloaded countries from data endpoints and use data store instead. ([#8380](https://github.com/woocommerce/woocommerce-admin/pull/8380))
|
||||
- Dev - Remove unused pre loaded setting data displaying all the routes. ([#8379](https://github.com/woocommerce/woocommerce-admin/pull/8379))
|
||||
- Dev - Remove unused task styling classes ([#8234](https://github.com/woocommerce/woocommerce-admin/pull/8234))
|
||||
- Dev - Update dependencies to support react 17 and drop support for IE11. ([#8305](https://github.com/woocommerce/woocommerce-admin/pull/8305))
|
||||
- Dev - Update task list data structure to better handle new designs. ([#8332](https://github.com/woocommerce/woocommerce-admin/pull/8332))
|
||||
|
||||
**WooCommerce Blocks - 7.2.0 & 7.2.1**
|
||||
|
||||
- Enhancement - Add Global Styles support to the Product Price block. ([5950](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5950))
|
||||
- Enhancement - Add Global Styles support to the Add To Cart Button block. ([5816](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5816))
|
||||
- Enhancement - Store API - Introduced `wc/store/v1` namespace. ([5911](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5911))
|
||||
- Enhancement - Renamed WooCommerce block templates to more e-commerce related names. ([5935](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5935))
|
||||
- Enhancement - Featured Product block: Add the ability to reset to a previously set custom background image. ([5886](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5886))
|
||||
- Enhancement - Add a remove image button to the WooCommerce Feature Category block. ([5719](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5719))
|
||||
- Enhancement - Add support for the global style for the On-Sale Badge block. ([5565](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5565))
|
||||
- Enhancement - Add support for the global style for the Attribute Filter block. ([5557](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5557))
|
||||
- Enhancement - Category List block: Add support for global style. ([5516](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5516))
|
||||
- Fix - Fixed typo in `wooocommerce_store_api_validate_add_to_cart` and `wooocommerce_store_api_validate_cart_item` hook names. ([5926](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5926))
|
||||
- Fix - Fix loading WC core translations in locales where WC Blocks is not localized for some strings. ([5910](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5910))
|
||||
- Fix - Fixed an issue where clear customizations functionality was not working for WooCommerce templates. ([5746](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5746))
|
||||
- Fix - Fixed hover and focus states for button components. ([5712](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5712))
|
||||
- Fix - Add to Cart button on Products listing blocks will respect the "Redirect to the cart page after successful addition" setting. ([5708](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5708))
|
||||
- Fix - Fixes Twenty Twenty Two issues with sales price and added to cart "View Cart" call out styling in the "Products by Category" block. ([5684](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5684))
|
||||
- Fix - StoreAPI: Clear all wc notice types in the cart validation context [#5983](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5983)
|
||||
- Fix - Don't trigger class deprecations notices if headers are already sent [#6074](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/6074)
|
||||
- Various - Remove v1 string from Store Keys. ([5987](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5987))
|
||||
- Various - Introduce the `InvalidCartException` for handling cart validation. ([5904](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5904))
|
||||
- Various - Renamed Store API custom headers to remove `X-WC-Store-API` prefixes. [#5983](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5983)
|
||||
- Various - Normalised Store API error codes [#5992](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5992)
|
||||
- Various - Deprecated `woocommerce_blocks_checkout_order_processed` in favour of `woocommerce_store_api_checkout_order_processed`
|
||||
- Various - Deprecated `woocommerce_blocks_checkout_update_order_meta` in favour of `woocommerce_store_api_checkout_update_order_meta`
|
||||
- Various - Deprecated `woocommerce_blocks_checkout_update_order_from_request` in favour of `woocommerce_store_api_checkout_update_order_from_request`
|
||||
|
||||
= 6.3.1 2022-03-10 =
|
||||
|
||||
**WooCommerce**
|
||||
|
||||
* Security - Address an issue with the PayPal Standard Payment Gateway. See https://developer.woocommerce.com/2022/03/10/woocommerce-3-5-10-6-3-1-security-releases/. ([#32057](https://github.com/woocommerce/woocommerce/pull/32057))
|
||||
|
||||
= 6.3.0 2022-03-08 =
|
||||
|
||||
**WooCommerce**
|
||||
|
||||
* Add - Add states for Germany. ([#31825](https://github.com/woocommerce/woocommerce/pull/31825))
|
||||
* Add - Track WcPay settings in WC Tracker. ([#31663](https://github.com/woocommerce/woocommerce/pull/31663))
|
||||
* Add - Add filter woocommerce_set_cookie_enabled to allow disabling specific cookies.([#31317](https://github.com/woocommerce/woocommerce/pull/31317))
|
||||
* Tweak - Enhancement - Add indices to the product attributes lookup table. ([#31819](https://github.com/woocommerce/woocommerce/pull/31819))
|
||||
* Tweak - Adjust input styles for the Twenty Twenty One theme. ([#31734](https://github.com/woocommerce/woocommerce/pull/31734))
|
||||
* Tweak - Adjust input styles for the Twenty Twenty theme. ([#31698](https://github.com/woocommerce/woocommerce/pull/31698))
|
||||
* Tweak - 2022 theme store notice styling. ([#31683](https://github.com/woocommerce/woocommerce/pull/31683))
|
||||
* Tweak - Guatemalan postcode field is now visible by default but remains unrequired. ([#31303](https://github.com/woocommerce/woocommerce/pull/31303))
|
||||
* Tweak - Ensure the WC_CSV_Batch_Exporter::get_percent_complete() method returns an int. ([#31138](https://github.com/woocommerce/woocommerce/pull/31138))
|
||||
* Fix - Support custom Product Taxonomies in block template loader. ([#31610](https://github.com/woocommerce/woocommerce/pull/31610))
|
||||
* Fix - Support special chars in email subjects using wp_specialchars_decode. ([#31589](https://github.com/woocommerce/woocommerce/pull/31589))
|
||||
* Fix - Ensure that WooCommerce panel within the Customizer is showing a back button. ([#31508](https://github.com/woocommerce/woocommerce/pull/31508))
|
||||
* Fix - Avoids incorrectly setting the search argument under some conditions, when the Customers endpoint of the REST API is used. ([#31295](https://github.com/woocommerce/woocommerce/pull/31295))
|
||||
* Fix - Reverted #31593 that caused the returned line item price to be a string instead of a float. ([#31935](https://github.com/woocommerce/woocommerce/pull/31935))
|
||||
* Fix - Add prefix to easy identify guest sessions.
|
||||
* Dev - The cart session is now updated later on during the woocommerce_after_calculate_totals action (priority 1000, instead of priority 10 as previously). ([#31711](https://github.com/woocommerce/woocommerce/pull/31711))
|
||||
* Dev - Enable browser-suggested passwords on checkout signup. ([#31701](https://github.com/woocommerce/woocommerce/pull/31701))
|
||||
* Dev - Add method can_view_woocommerce_menu_item to check if the user can access the top-level WooCommerce menu item. ([#31689](https://github.com/woocommerce/woocommerce/pull/31689))
|
||||
* Dev - Wrap terms and conditions required asterisk symbol with <abbr> tag. ([#31673](https://github.com/woocommerce/woocommerce/pull/31673))
|
||||
* Dev - Allow to use use all get_image function parameters by woocommerce_get_product_thumbnail to customize image. ([#31605](https://github.com/woocommerce/woocommerce/pull/31605))
|
||||
* Dev - Format price decimal places correctly in the order API. ([#31593](https://github.com/woocommerce/woocommerce/pull/31593))
|
||||
* Dev - Update text for generating an account in admin menu to be more clear. ([#31590](https://github.com/woocommerce/woocommerce/pull/31590))
|
||||
* Dev - Adds the option to filter coupons by status when calling the GET /coupons endpoint. ([#31577](https://github.com/woocommerce/woocommerce/pull/31577))
|
||||
* Dev - Made the $loop position counter available via the 'woocommerce_variation_header' hook. ([#31565](https://github.com/woocommerce/woocommerce/pull/31565))
|
||||
* Dev - Change '__return_true' to true in the apply_filters() call for the woocommerce_product_recount_terms filter. ([#31506](https://github.com/woocommerce/woocommerce/pull/31506))
|
||||
* Dev - Add $key field as well to woocommerce_checkout_required_field_notice filter. ([#31435](https://github.com/woocommerce/woocommerce/pull/31435))
|
||||
* Dev - Add product meta data to published product tracks. ([#31355](https://github.com/woocommerce/woocommerce/pull/31355))
|
||||
* Dev - Allow auto-draft in API orders. ([#31290](https://github.com/woocommerce/woocommerce/pull/31290))
|
||||
* Dev - A $file param is now available via the woocommerce_[product_]csv_importer_check_import_file_path filter hooks. ([#31266](https://github.com/woocommerce/woocommerce/pull/31266))
|
||||
* Dev - Data migration to create and activate the product attributes lookup table. ([#31256](https://github.com/woocommerce/woocommerce/pull/31256))
|
||||
* Dev - A new filter hook woocommerce_cart_item_removed_because_modified_message($message, $product) which allows to update the notice message if a product is modified and page is loaded while product is in cart. ([#31193](https://github.com/woocommerce/woocommerce/pull/31193))
|
||||
* Security - Add prefix to identify guest sessions.
|
||||
|
||||
**WooCommerce Admin - 3.2.0 & 3.2.1**
|
||||
|
||||
* Fix - Adjusted task list logic to fix conflict between current and experimental task list. ([#8321](https://github.com/woocommerce/woocommerce-admin/pull/8321))
|
||||
* Fix - changed email validation in Store Details onboarding task to more closely match PHP backend validation. ([#8197](https://github.com/woocommerce/woocommerce-admin/pull/8197))
|
||||
* Fix - Disallow whitespace as the platform name input. ([#8090](https://github.com/woocommerce/woocommerce-admin/pull/8090))
|
||||
* Fix - Ensure setup-wizard redirection on homescreen is stable. ([#8114](https://github.com/woocommerce/woocommerce-admin/pull/8114))
|
||||
* Fix - Fix category report query returns invalid net sales. ([#8153](https://github.com/woocommerce/woocommerce-admin/pull/8153))
|
||||
* Fix - Fix clicking the error message opens the dropdown. ([#8094](https://github.com/woocommerce/woocommerce-admin/pull/8094))
|
||||
* Fix - Fix country/region selection not preserved in store details task. ([#8228](https://github.com/woocommerce/woocommerce-admin/pull/8228))
|
||||
* Fix - Fixed email address not being optional in OBW ([#8263](https://github.com/woocommerce/woocommerce-admin/pull/8263))
|
||||
* Fix - Fix get_automated_tax_supported_countries doesn't include UK. ([#8180](https://github.com/woocommerce/woocommerce-admin/pull/8180))
|
||||
* Fix - Fix incorrect date options when the "Default Date Range" is set from Analytics settings. ([#8189](https://github.com/woocommerce/woocommerce-admin/pull/8189))
|
||||
* Fix - Fix incorrectly displayed note created date. ([#8179](https://github.com/woocommerce/woocommerce-admin/pull/8179))
|
||||
* Fix - Fix incorrect screen reader text generated for data points on charts table. ([#8181](https://github.com/woocommerce/woocommerce-admin/pull/8181))
|
||||
* Fix - Fix incorrect total count of downloads on the analytics download report. ([#8182](https://github.com/woocommerce/woocommerce-admin/pull/8182))
|
||||
* Fix - Fix misaligned status column on order report. ([#8121](https://github.com/woocommerce/woocommerce-admin/pull/8121))
|
||||
* Fix - Fix shipping rate error message overlaps with the 'Proceed' button. ([#8165](https://github.com/woocommerce/woocommerce-admin/pull/8165))
|
||||
* Fix - Fix Shipping task sometimes skipping the set shipping costs step. ([#8260](https://github.com/woocommerce/woocommerce-admin/pull/8260))
|
||||
* Fix - Fix Uncaught TypeError count(NULL) for php8+ in Marketing.php. ([#8213](https://github.com/woocommerce/woocommerce-admin/pull/8213))
|
||||
* Fix - Fix undefined derived_currency value for the track 'wcadmin_storeprofiler_store_details_continue'. ([#8193](https://github.com/woocommerce/woocommerce-admin/pull/8193))
|
||||
* Fix - Fix variations table product filter query. ([#8120](https://github.com/woocommerce/woocommerce-admin/pull/8120))
|
||||
* Fix - Make sure free subscriptions does not show when cbd industry is selected. ([#8323](https://github.com/woocommerce/woocommerce-admin/pull/8323))
|
||||
* Fix - Make sure WooCommerce Payments tasklist_payment_setup is triggered again. ([#8146](https://github.com/woocommerce/woocommerce-admin/pull/8146))
|
||||
* Fix - Preserve HTML markup in server-side error messages received from sample product import request. ([#8173](https://github.com/woocommerce/woocommerce-admin/pull/8173))
|
||||
* Fix - Remove border between email input and newsletter checkbox in OBW store details. ([#8148](https://github.com/woocommerce/woocommerce-admin/pull/8148))
|
||||
* Fix - Reset "install_timestamp" if it's not numeric to avoid TypeError. ([#8100](https://github.com/woocommerce/woocommerce-admin/pull/8100))
|
||||
* Fix - Truncate the long site title with an ellipses on the second line. ([#8112](https://github.com/woocommerce/woocommerce-admin/pull/8112))
|
||||
* Fix - Fix backwards compatibility with SkyVerge payment gateway.([#8371](https://github.com/woocommerce/woocommerce-admin/pull/8371))
|
||||
* Add - Add additional store profiler track for the business details tab. ([#8265](https://github.com/woocommerce/woocommerce-admin/pull/8265))
|
||||
* Add - Add countries data store ([#8119](https://github.com/woocommerce/woocommerce-admin/pull/8119))
|
||||
* Add - Add extra tracking for plugin installation performance during onboarding. ([#8042](https://github.com/woocommerce/woocommerce-admin/pull/8042))
|
||||
* Add - Adding tooltip to describe the lack of refund deductions from revenue summaries. ([#8187](https://github.com/woocommerce/woocommerce-admin/pull/8187))
|
||||
* Add - Add localized validation to store address ([#8123](https://github.com/woocommerce/woocommerce-admin/pull/8123))
|
||||
* Add - Add Magento migration note ([#8145](https://github.com/woocommerce/woocommerce-admin/pull/8145))
|
||||
* Add - Add REST endpoint to retrieve address locales ([#8116](https://github.com/woocommerce/woocommerce-admin/pull/8116))
|
||||
* Add - Add Spain to Square country suggestion list. ([#8210](https://github.com/woocommerce/woocommerce-admin/pull/8210))
|
||||
* Add - Add wc_version property to the store profile onboarding tracks for view and complete steps. ([#8290](https://github.com/woocommerce/woocommerce-admin/pull/8290))
|
||||
* Add - Change the reviews empty state panels logic ([#8147](https://github.com/woocommerce/woocommerce-admin/pull/8147))
|
||||
* Update - Add custom error for store details email and allow continue ([#8110](https://github.com/woocommerce/woocommerce-admin/pull/8110))
|
||||
* Update - Adding "allow-plugins" property for composer configuration. ([#8139](https://github.com/woocommerce/woocommerce-admin/pull/8139))
|
||||
* Dev - Remove wc-admin-settings package and rename getSetting to getAdminSetting. ([#8057](https://github.com/woocommerce/woocommerce-admin/pull/8057))
|
||||
* Tweak - Fix WCPay in core texts and promo slug ([#8296](https://github.com/woocommerce/woocommerce-admin/pull/8296))
|
||||
* Tweak - Grow and center buttons in all WooCommerce ellipsis menu popover containers. ([#8168](https://github.com/woocommerce/woocommerce-admin/pull/8168))
|
||||
* Tweak - Hide store address fields in regions that specify hidden ([#8172](https://github.com/woocommerce/woocommerce-admin/pull/8172))
|
||||
* Tweak - Make activity panel badges margin consistent. ([#8152](https://github.com/woocommerce/woocommerce-admin/pull/8152))
|
||||
* Tweak - Padding tweak for marketing tools plugin list headings. ([#8171](https://github.com/woocommerce/woocommerce-admin/pull/8171))
|
||||
* Performance - Speed up customer syncing action. ([#8021](https://github.com/woocommerce/woocommerce-admin/pull/8021))
|
||||
* Enhancement - Enhance report chart i18n support. ([#8129](https://github.com/woocommerce/woocommerce-admin/pull/8129))
|
||||
* Enhancement - Make ExPlat request URL args filterable. Added woocommerce_explat_request_args filter. ([#8231](https://github.com/woocommerce/woocommerce-admin/pull/8231))
|
||||
* Enhancement - Show MailPoet in Installed marketing extensions. ([#8091](https://github.com/woocommerce/woocommerce-admin/pull/8091))
|
||||
* Enhancement - Update headercard to use filter to add ExPlat parameter ([#8233](https://github.com/woocommerce/woocommerce-admin/pull/8233))
|
||||
|
||||
**WooCommerce Blocks - 6.8.0 & 6.9.0**
|
||||
|
||||
* Add - Add support for the global style for the Price Filter block. ([#5559](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5559))
|
||||
* Add - Hold stock for 60mins if the order is pending payment. ([#5546](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5546))
|
||||
* Add - Allow users to reinsert the WooCommerce Legacy Template block in their block template if it is a WooCommerce block template. ([#5545](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5545))
|
||||
* Add - Add support for the global style for the Stock Indicator block. ([#5525](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5525))
|
||||
* Add - Add support for the global style for the Summary Product block. ([#5524](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5524))
|
||||
* Add - Add support for the global style for the Product Title block. ([#5515](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5515))
|
||||
* Add - Store API: Throw errors when attempting to pay with a non-available payment method. ([#5440](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5440))
|
||||
* Add - Add support for the wide and full alignment for the legacy template block. ([#5433](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5433))
|
||||
* Add - Store API and Cart block now support defining a quantity stepper and a minimum quantity. ([#5406](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5406))
|
||||
* Add - Added controls to product grid blocks for filtering by stock levels. ([#4943](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/4943))
|
||||
* Add - Add support for the global style for the Featured Category block. ([#5542](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5542))
|
||||
* Fix duplicated checkout error notices. ([#5476](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5476))
|
||||
* Fix - Use consistent HTML code for all rating sections, so that screen readers pronounce the rating correctly. ([#5552](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5552))
|
||||
* Fix - All Products block displays thumbnails. ([#5551](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5551))
|
||||
* Fix - Fixed a styling issue in the Checkout block when an order has multiple shipping packages. ([#5529](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5529))
|
||||
* Fix - Fixed a visual bug (#5152) with the points and rewards plugin. ([#5430](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5430))
|
||||
* Fix - Filter Products By Price block: Don't allow to insert negative values on inputs. ([#5123](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5123))
|
||||
* Fix - Enable Mini Cart template-parts only for experimental builds. ([#5606](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5606))
|
||||
* Fix - Show express payment button in full width if only one express payment method is available. ([#5601](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5601))
|
||||
* Fix - Wrapped cart item product contents in inner div. ([#5240](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5240))
|
||||
* Fix - Fix alignment issue with the "create account" section on the checkout block in the editor ([#5633](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5633))
|
||||
* Dev - Remove invalid `$wpdb->prepare()` statement in Featured Category Block. ([#5471](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5471))
|
||||
* Dev - Remove Stripe Payment Method Integration (which is now part of the Stripe Payment Method extension itself). ([#5449](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5449))
|
||||
* Dev - Update the block theme folders to latest Gutenberg convention (i.e. `templates` and `parts`). ([#5464](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5464))
|
||||
* Dev - Revert "Allow LegacyTemplate block to be reinserted, only on WooCommerce block templates.". ([#5643](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5643))
|
||||
|
||||
= 6.2.2 2022-03-10 =
|
||||
|
||||
**WooCommerce**
|
||||
|
||||
* Security - Address an issue with the PayPal Standard Payment Gateway. See https://developer.woocommerce.com/2022/03/10/woocommerce-3-5-10-6-3-1-security-releases/. ([#32057](https://github.com/woocommerce/woocommerce/pull/32057))
|
||||
|
||||
= 6.2.1 2022-02-22 =
|
||||
|
||||
**WooCommerce**
|
||||
|
||||
* Security - Fixed permission check for reviews in v1 & v2 REST API.
|
||||
* Security - Fixed Path Traversal in Importers.
|
||||
|
||||
= 6.2.0 2022-02-08 =
|
||||
|
||||
**WooCommerce**
|
||||
|
||||
* Add - Admin notice warning about the upcoming minimum PHP 7.2 version bump coming in WooCommerce 6.5. ([#31557](https://github.com/woocommerce/woocommerce/pull/31557))
|
||||
* Tweak - Removed images referred to from deprecated functions. ([#31395](https://github.com/woocommerce/woocommerce/pull/31395))
|
||||
* Tweak - Update store setup widget to use task list API. ([#31755](https://github.com/woocommerce/woocommerce/pull/31755))
|
||||
* Fix - Fixed styling of "pay for order" form for 2022 theme. ([#31682](https://github.com/woocommerce/woocommerce/pull/31682))
|
||||
* Fix - Search Blocks form for 2022 theme. ([#31687](https://github.com/woocommerce/woocommerce/pull/31687))
|
||||
* Fix - Checkout scroll to notices fallback scroll element. ([#30955](https://github.com/woocommerce/woocommerce/pull/30955))
|
||||
* Fix - Prevent PhotoSwipe tap from interacting with elements directly underneath. Props @Edsuns and @andi34. ([#31591](https://github.com/woocommerce/woocommerce/pull/31591))
|
||||
* Fix - Double notice about the upcoming change in the PHP version requirement. ([#31744](https://github.com/woocommerce/woocommerce/pull/31744))
|
||||
* Dev - Added logic to `do_variation_action` prematurely return on custom actions. ([#31088](https://github.com/woocommerce/woocommerce/pull/31088))
|
||||
* Dev - REST API - Adds `status` field to the GET `/coupons` endpoint. ([#31561](https://github.com/woocommerce/woocommerce/pull/31561))
|
||||
* Dev - Use `calc` function to prevent deprecated warnings when building SCSS.
|
||||
|
||||
**WooCommerce Admin - 3.1.0**
|
||||
|
||||
* Enhancement - Add SlotFill areas to header. ([#7805](https://github.com/woocommerce/woocommerce-admin/pull/7805))
|
||||
* Add - Add featured pill for MailPoet and Google Listings in marketing task. ([#8009](https://github.com/woocommerce/woocommerce-admin/pull/8009))
|
||||
* Add - Add inbox_action_click track when a note gets clicked. ([#8086](https://github.com/woocommerce/woocommerce-admin/pull/8086))
|
||||
* Add - Activate promo note after WC Pay is activated. ([#8104](https://github.com/woocommerce/woocommerce-admin/pull/8104))
|
||||
* Add - Add payment remind me later note. ([#8085](https://github.com/woocommerce/woocommerce-admin/pull/8085))
|
||||
* Add - Add WC Pay welcome page. ([#8083](https://github.com/woocommerce/woocommerce-admin/pull/8083))
|
||||
* Update - Allow content data note props to be passed from remote sources ([#8047](https://github.com/woocommerce/woocommerce-admin/pull/8047))
|
||||
* Update - Update @woocommerce/e2e-environment package to latest. ([#8000](https://github.com/woocommerce/woocommerce-admin/pull/8000))
|
||||
* Tweak - OBW Update WC Pay label on recommended extensions list ([#8038](https://github.com/woocommerce/woocommerce-admin/pull/8038))
|
||||
* Fix - Fix Onboarding flow where extensions might not be selected and installed. ([#7979](https://github.com/woocommerce/woocommerce-admin/pull/7979))
|
||||
* Fix - Fix pagination issue with Analytics Coupons page. ([#8001](https://github.com/woocommerce/woocommerce-admin/pull/8001))
|
||||
* Fix - Fix select-control component label/value alignment. ([#8045](https://github.com/woocommerce/woocommerce-admin/pull/8045))
|
||||
* Fix - Fix unexpected analytics report table filter results. ([#8072](https://github.com/woocommerce/woocommerce-admin/pull/8072))
|
||||
* Fix - Prevent coupon move notice for new installs. ([#7995](https://github.com/woocommerce/woocommerce-admin/pull/7995))
|
||||
* Fix - Remove calls to read_meta_data in the Note DataStore. ([#7988](https://github.com/woocommerce/woocommerce-admin/pull/7988))
|
||||
* Fix - Fix free extensions list isn't updated after store location or industry is changed. ([#8099](https://github.com/woocommerce/woocommerce-admin/pull/8099))
|
||||
* Fix - Fix misaligned "Rows per page" dropdown. ([#8113](https://github.com/woocommerce/woocommerce-admin/pull/8113))
|
||||
* Fix - Hide the extensions header when no available plugins in the category. ([#8089](https://github.com/woocommerce/woocommerce-admin/pull/8089))
|
||||
* Fix - Replace all docs.woocommerce.com links with woocommerce.com/document. ([#8105](https://github.com/woocommerce/woocommerce-admin/pull/8105))
|
||||
* Fix - Fixing marketing task not displaying on Atomic sites ([#8150](https://github.com/woocommerce/woocommerce-admin/pull/8150))
|
||||
* Fix - Fix setup wizard free features checkbox re-check itself. ([#8169](https://github.com/woocommerce/woocommerce-admin/pull/8169))
|
||||
* Dev - Add payment gateway suggestion docs and example extensions ([#7966](https://github.com/woocommerce/woocommerce-admin/pull/7966))
|
||||
* Dev - Remove low performing inbox notes. ([#8054](https://github.com/woocommerce/woocommerce-admin/pull/8054))
|
||||
* Dev - Remove navigation feedback note. ([#8055](https://github.com/woocommerce/woocommerce-admin/pull/8055))
|
||||
* Dev - Fix task ID class check and add tests around tracking ([#8185](https://github.com/woocommerce/woocommerce-admin/pull/8185))
|
||||
|
||||
**WooCommerce Blocks - 6.6.0 & 6.7.0 & 6.7.1 & 6.7.2 & 6.7.3**
|
||||
|
||||
* Enhancement - Added global styles (text color) to the Active Filters block. ([5465](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5465))
|
||||
* Enhancement - Prevent a 0 value shipping price being shown in the Checkout if no shipping methods are available. ([5444](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5444))
|
||||
* Fix - Convert token to string when setting the active payment method. ([5535](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5535))
|
||||
* Fix - Fixed an issue where the checkout address fields would be blank for logged in customers. ([5473](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5473))
|
||||
* Fix - Account for products without variations in the On Sale Products block. ([5470](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5470))
|
||||
* Fix - Update the template retrieving logic to allow for older Gutenberg convention and newer one (`block-templates`/`block-template-parts` vs. `templates`/`parts`). ([5455](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5455))
|
||||
* Fix - Ensure that the translation of the "Proceed to Checkout" button is working. ([5453](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5453))
|
||||
* Fix - Fix custom templates with fallback to archive being incorrectly attributed to the user in the editor instead of the parent theme. ([5447](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5447))
|
||||
* Fix - Remove text decorations from product filtering blocks items. ([5384](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5384))
|
||||
* Fix - "Added By" template column value is user friendly for modified WooCommerce block templates. ([5420](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5420))
|
||||
* Fix - Fixed a performance issue with the cart by preventing an extra network request on mount. ([5394](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5394))
|
||||
* Fix - Use the themes product archive block template for product category & product tag pages if the theme does not have more specific templates for those. ([5380](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5380))
|
||||
* Fix - Cart block: Switch to correct view if inner block is selected. ([5358](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5358))
|
||||
* Fix - Respect implicit quantity updates coming from server or directly from data stores. ([5352](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5352))
|
||||
* Fix - Fixed a case where payments could fail after validation errors when using saved cards. ([5350](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5350))
|
||||
* Fix - Add error handling for network errors during checkout. ([5341](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5341))
|
||||
* Fix - Fix cart and checkout margin problem by removing the full-width option. ([5315](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5315))
|
||||
* Fix - Enable Mini Cart template parts only for experimental builds. ([#5606](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5606))
|
||||
* Tweak - Sync draft orders whenever cart data changes. ([5379](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5379))
|
||||
* Tweak - Removed legacy handling for shipping_phone in Store API. ([5326](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5326))
|
||||
* Tweak - Site Editor template list: Fix wrong icon displayed on WooCommerce templates after they have been edited. ([5375](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5375))
|
||||
* Tweak - Fix validation error handling after using browser autofill. ([5373](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5373))
|
||||
* Tweak - Update loading skeleton animations. ([5362](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5362))
|
||||
* Tweak - Add error handling to `get_routes_from_namespace` method. ([5319](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5319))
|
||||
* Tweak - Update WooCommerce plugin slug for Block Templates. ([#5519](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5519))
|
||||
|
||||
= 6.1.2 2022-03-10 =
|
||||
|
||||
**WooCommerce**
|
||||
|
||||
* Security - Address an issue with the PayPal Standard Payment Gateway. See https://developer.woocommerce.com/2022/03/10/woocommerce-3-5-10-6-3-1-security-releases/. ([#32057](https://github.com/woocommerce/woocommerce/pull/32057))
|
||||
|
||||
= 6.1.1 2022-01-20 =
|
||||
|
||||
**WooCommerce**
|
||||
|
||||
* Enhancement - Add support for 2022 theme shop and product pages. ( [#31536](https://github.com/woocommerce/woocommerce/pull/31536) )
|
||||
* Enhancement - Add support for 2022 my account pages. ( [#31575](https://github.com/woocommerce/woocommerce/pull/31575) )
|
||||
* Enhancement - Add support for 2022 checkout page. ( [#31630](https://github.com/woocommerce/woocommerce/pull/31630) )
|
||||
* Fix - Use inline `onload` event instead of jQuery `load`. ( [#31623](https://github.com/woocommerce/woocommerce/pull/31623) )
|
||||
* Fix - Removes the revert warning about is_ajax. ( [#31672](https://github.com/woocommerce/woocommerce/pull/31672) )
|
||||
* Tweak - Better styling for checkout form for 2022 theme. ( [#31619](https://github.com/woocommerce/woocommerce/pull/31619) )
|
||||
* Tweak - Center product cards in the 2022 theme. ( [#31626](https://github.com/woocommerce/woocommerce/pull/31626) )
|
||||
* Tweak - Fix font sizes in single product tabs area in 2022 theme. ( [#31632](https://github.com/woocommerce/woocommerce/pull/31632) )
|
||||
* Tweak - Modify background color for `mark` elements in 2022 theme. ( [#31631](https://github.com/woocommerce/woocommerce/pull/31631) )
|
||||
* Tweak - Adjusts basis of overlay in 2022 theme checkout. ( [#31633](https://github.com/woocommerce/woocommerce/pull/31633) )
|
||||
* Tweak - Improve order details table on narrow viewports in 2022 theme. ( [#31634](https://github.com/woocommerce/woocommerce/pull/31634) )
|
||||
|
||||
**WooCommerce Blocks - 6.5.2**
|
||||
|
||||
* Fix - Update WooCommerce plugin slug for Block Templates. ( [#5519](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5519) )
|
||||
|
||||
= 6.1.0 2022-01-11 =
|
||||
|
||||
**WooCommerce**
|
||||
|
@ -98,6 +440,12 @@
|
|||
* Fix - Fix error when reverting WooCommerce templates. ( [#5342](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5342) )
|
||||
* Fix - Fix: WooCommerce block templates loading for WP 5.9 without Gutenberg plugin. ( [#5335](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5335) )
|
||||
|
||||
= 6.0.1 2022-03-10 =
|
||||
|
||||
**WooCommerce**
|
||||
|
||||
* Security - Address an issue with the PayPal Standard Payment Gateway. See https://developer.woocommerce.com/2022/03/10/woocommerce-3-5-10-6-3-1-security-releases/. ([#32057](https://github.com/woocommerce/woocommerce/pull/32057))
|
||||
|
||||
= 6.0.0 2021-12-14 =
|
||||
|
||||
**WooCommerce**
|
||||
|
@ -203,6 +551,12 @@
|
|||
* Fix - Store API – Ensure returned customer address state is valid. ( [#4844](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/4844) )
|
||||
* Fix - fatal error in certain WP 5.9 pre-release versions. ( [#5183](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/5183) )
|
||||
|
||||
= 5.9.1 2022-03-10 =
|
||||
|
||||
**WooCommerce**
|
||||
|
||||
* Security - Address an issue with the PayPal Standard Payment Gateway. See https://developer.woocommerce.com/2022/03/10/woocommerce-3-5-10-6-3-1-security-releases/. ([#32057](https://github.com/woocommerce/woocommerce/pull/32057))
|
||||
|
||||
= 5.9.0 2021-11-09 =
|
||||
|
||||
**WooCommerce**
|
||||
|
@ -260,6 +614,12 @@
|
|||
* Fix - Remove IntersectionObserver shim in favor of dropping IE11 support. #4808
|
||||
* Enhancement - Added global styles to All Reviews, Reviews by Category and Reviews by Product blocks. Now it's possible to change the text color and font size of those blocks. #4323
|
||||
|
||||
= 5.8.2 2022-03-10 =
|
||||
|
||||
**WooCommerce**
|
||||
|
||||
* Security - Address an issue with the PayPal Standard Payment Gateway. See https://developer.woocommerce.com/2022/03/10/woocommerce-3-5-10-6-3-1-security-releases/. ([#32057](https://github.com/woocommerce/woocommerce/pull/32057))
|
||||
|
||||
= 5.8.0 2021-10-12 =
|
||||
|
||||
**WooCommerce**
|
||||
|
@ -333,6 +693,12 @@
|
|||
* Fix - Improves compatibility with environments where NO_ZERO_DATE is enabled. #519
|
||||
* Fix - Adds safety checks to guard against errors when our database tables cannot be created. #645
|
||||
|
||||
= 5.7.2 2022-03-10 =
|
||||
|
||||
**WooCommerce**
|
||||
|
||||
* Security - Address an issue with the PayPal Standard Payment Gateway. See https://developer.woocommerce.com/2022/03/10/woocommerce-3-5-10-6-3-1-security-releases/. ([#32057](https://github.com/woocommerce/woocommerce/pull/32057))
|
||||
|
||||
= 5.7.1 2021-09-23 =
|
||||
|
||||
**WooCommerce**
|
||||
|
@ -440,6 +806,12 @@
|
|||
- Fix - Fix memory leak when previewing transform options for the All reviews block. #4428
|
||||
- Fix - Disable Cart, Checkout, All Products & filters blocks from the widgets screen. #4646
|
||||
|
||||
= 5.6.2 2022-03-10 =
|
||||
|
||||
**WooCommerce**
|
||||
|
||||
* Security - Address an issue with the PayPal Standard Payment Gateway. See https://developer.woocommerce.com/2022/03/10/woocommerce-3-5-10-6-3-1-security-releases/. ([#32057](https://github.com/woocommerce/woocommerce/pull/32057))
|
||||
|
||||
= 5.6.0 2021-08-17 =
|
||||
|
||||
**WooCommerce**
|
||||
|
@ -546,6 +918,12 @@
|
|||
- Tweak - Allow products to be added by SKU in the Hand-Picked Products block. #4366
|
||||
- Tweak - Add Slot in the Discounts section of the Checkout sidebar to allow third party extensions to render their own components there. #4310
|
||||
|
||||
= 5.5.4 2022-03-10 =
|
||||
|
||||
**WooCommerce**
|
||||
|
||||
* Security - Address an issue with the PayPal Standard Payment Gateway. See https://developer.woocommerce.com/2022/03/10/woocommerce-3-5-10-6-3-1-security-releases/. ([#32057](https://github.com/woocommerce/woocommerce/pull/32057))
|
||||
|
||||
= 5.5.2 2021-07-22 =
|
||||
|
||||
* Fix - Add a new option allowing product downloads to be served using redirects as a last resort. #30288
|
||||
|
@ -749,6 +1127,12 @@
|
|||
* Fix - Add extra safety/account for different versions of AS and different loading patterns. #714
|
||||
* Fix - Handle hidden columns (Tools → Scheduled Actions) | #600.
|
||||
|
||||
= 5.4.4 2022-03-10 =
|
||||
|
||||
**WooCommerce**
|
||||
|
||||
* Security - Address an issue with the PayPal Standard Payment Gateway. See https://developer.woocommerce.com/2022/03/10/woocommerce-3-5-10-6-3-1-security-releases/. ([#32057](https://github.com/woocommerce/woocommerce/pull/32057))
|
||||
|
||||
= 5.4.2 2021-07-14 =
|
||||
|
||||
**WooCommerce**
|
||||
|
@ -848,6 +1232,12 @@
|
|||
* Fix - Prevent parts of old addresses being displayed in the shipping calculator when changing countries. #4038
|
||||
* Fix - issue in which email and phone fields are cleared when using a separate billing address. #4162
|
||||
|
||||
= 5.3.3 2022-03-10 =
|
||||
|
||||
**WooCommerce**
|
||||
|
||||
* Security - Address an issue with the PayPal Standard Payment Gateway. See https://developer.woocommerce.com/2022/03/10/woocommerce-3-5-10-6-3-1-security-releases/. ([#32057](https://github.com/woocommerce/woocommerce/pull/32057))
|
||||
|
||||
= 5.3.1 2021-07-14 =
|
||||
|
||||
**WooCommerce**
|
||||
|
@ -985,6 +1375,12 @@
|
|||
* Tweak - Store profiler - Changed MailPoet's title and description #6886
|
||||
* Tweak - Update PayU logo #6829
|
||||
|
||||
= 5.2.5 2022-03-10 =
|
||||
|
||||
**WooCommerce**
|
||||
|
||||
* Security - Address an issue with the PayPal Standard Payment Gateway. See https://developer.woocommerce.com/2022/03/10/woocommerce-3-5-10-6-3-1-security-releases/. ([#32057](https://github.com/woocommerce/woocommerce/pull/32057))
|
||||
|
||||
= 5.2.3 2021-07-14 =
|
||||
|
||||
**WooCommerce**
|
||||
|
@ -1154,6 +1550,12 @@
|
|||
* Fix - Ensure sale badges have a uniform height in the Cart block. ([3897](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/3897))
|
||||
* Note - Internally, this release has modified how `AbstractBlock` (the base class for all of our blocks) functions, and how it loads assets. `AbstractBlock` is internal to this project and does not seem like something that would ever need to be extended by 3rd parties, but note if you are doing so for whatever reason, your implementation would need to be updated to match. ([3829](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/3829))
|
||||
|
||||
= 5.1.3 2022-03-10 =
|
||||
|
||||
**WooCommerce**
|
||||
|
||||
* Security - Address an issue with the PayPal Standard Payment Gateway. See https://developer.woocommerce.com/2022/03/10/woocommerce-3-5-10-6-3-1-security-releases/. ([#32057](https://github.com/woocommerce/woocommerce/pull/32057))
|
||||
|
||||
= 5.1.1 2021-07-14 =
|
||||
|
||||
**WooCommerce**
|
||||
|
@ -1268,6 +1670,12 @@
|
|||
* Dev - Added formatting classes to the Store API for extensions to consume.
|
||||
* Dev - Refactored and reordered Store API checkout processing to handle various edge cases and better support future extensibility. ([3454](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/3454))
|
||||
|
||||
= 5.0.3 2022-03-10 =
|
||||
|
||||
**WooCommerce**
|
||||
|
||||
* Security - Address an issue with the PayPal Standard Payment Gateway. See https://developer.woocommerce.com/2022/03/10/woocommerce-3-5-10-6-3-1-security-releases/. ([#32057](https://github.com/woocommerce/woocommerce/pull/32057))
|
||||
|
||||
= 5.0.1 2021-07-14 =
|
||||
|
||||
**WooCommerce**
|
||||
|
@ -1341,6 +1749,12 @@
|
|||
* Enhancement - Add an "unread" indicator to inbox messages. #6047
|
||||
* Add - Manage activity from home screen inbox message. #6072
|
||||
|
||||
= 4.9.5 2022-03-10 =
|
||||
|
||||
**WooCommerce**
|
||||
|
||||
* Security - Address an issue with the PayPal Standard Payment Gateway. See https://developer.woocommerce.com/2022/03/10/woocommerce-3-5-10-6-3-1-security-releases/. ([#32057](https://github.com/woocommerce/woocommerce/pull/32057))
|
||||
|
||||
= 4.9.3 2021-07-14 =
|
||||
|
||||
**WooCommerce**
|
||||
|
@ -1471,6 +1885,12 @@
|
|||
* Dev - Expose store/cart via ExtendRestApi to extensions. ([3445](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/3445))
|
||||
* Dev - Added formatting classes to the Store API for extensions to consume.
|
||||
|
||||
= 4.8.3 2022-03-10 =
|
||||
|
||||
**WooCommerce**
|
||||
|
||||
* Security - Address an issue with the PayPal Standard Payment Gateway. See https://developer.woocommerce.com/2022/03/10/woocommerce-3-5-10-6-3-1-security-releases/. ([#32057](https://github.com/woocommerce/woocommerce/pull/32057))
|
||||
|
||||
= 4.8.1 2021-07-14 =
|
||||
|
||||
**WooCommerce**
|
||||
|
@ -1590,6 +2010,12 @@
|
|||
* Fix - Twenty Twenty One Button and Placeholder Styling. #3443
|
||||
* Fix - checkbox and textarea styles in Twenty Twenty One when it has dark controls active. #3450
|
||||
|
||||
= 4.7.4 2022-03-10 =
|
||||
|
||||
**WooCommerce**
|
||||
|
||||
* Security - Address an issue with the PayPal Standard Payment Gateway. See https://developer.woocommerce.com/2022/03/10/woocommerce-3-5-10-6-3-1-security-releases/. ([#32057](https://github.com/woocommerce/woocommerce/pull/32057))
|
||||
|
||||
= 4.7.2 2021-07-14 =
|
||||
|
||||
**WooCommerce**
|
||||
|
@ -1658,6 +2084,12 @@
|
|||
* Tweak: Add BR and IN to list of stripe countries [#5377](https://github.com/woocommerce/woocommerce-admin/pull/5377)
|
||||
* Fix: Redirect instead of stalling on WCPay Inbox note action [#5413](https://github.com/woocommerce/woocommerce-admin/pull/5413)
|
||||
|
||||
= 4.6.5 2022-03-10 =
|
||||
|
||||
**WooCommerce**
|
||||
|
||||
* Security - Address an issue with the PayPal Standard Payment Gateway. See https://developer.woocommerce.com/2022/03/10/woocommerce-3-5-10-6-3-1-security-releases/. ([#32057](https://github.com/woocommerce/woocommerce/pull/32057))
|
||||
|
||||
= 4.6.3 2021-07-14 =
|
||||
|
||||
**WooCommerce**
|
||||
|
@ -1786,6 +2218,12 @@
|
|||
- Create DebouncedValidatedTextInput component. ([3108](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/3108))
|
||||
- Merge ProductPrice atomic block and component. ([3065](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/3065))
|
||||
|
||||
= 4.5.5 2022-03-10 =
|
||||
|
||||
**WooCommerce**
|
||||
|
||||
* Security - Address an issue with the PayPal Standard Payment Gateway. See https://developer.woocommerce.com/2022/03/10/woocommerce-3-5-10-6-3-1-security-releases/. ([#32057](https://github.com/woocommerce/woocommerce/pull/32057))
|
||||
|
||||
= 4.5.3 2021-07-14 =
|
||||
|
||||
**WooCommerce**
|
||||
|
@ -1840,6 +2278,12 @@
|
|||
* Dev - Task list - add a shortcut back to store setup. #4853
|
||||
* Dev - Update the colors of the illustrations in the welcome modal. #4945
|
||||
|
||||
= 4.4.4 2022-03-10 =
|
||||
|
||||
**WooCommerce**
|
||||
|
||||
* Security - Address an issue with the PayPal Standard Payment Gateway. See https://developer.woocommerce.com/2022/03/10/woocommerce-3-5-10-6-3-1-security-releases/. ([#32057](https://github.com/woocommerce/woocommerce/pull/32057))
|
||||
|
||||
= 4.4.2 2021-07-14 =
|
||||
|
||||
**WooCommerce**
|
||||
|
@ -1994,6 +2438,12 @@
|
|||
* Fix - 'Product Summary' in All Products block is not pulling in the short description of the product. #2913
|
||||
* Dev - Add query filter when searching for a table. #2886
|
||||
|
||||
= 4.3.6 2022-03-10 =
|
||||
|
||||
**WooCommerce**
|
||||
|
||||
* Security - Address an issue with the PayPal Standard Payment Gateway. See https://developer.woocommerce.com/2022/03/10/woocommerce-3-5-10-6-3-1-security-releases/. ([#32057](https://github.com/woocommerce/woocommerce/pull/32057))
|
||||
|
||||
= 4.3.4 2021-07-14 =
|
||||
|
||||
**WooCommerce**
|
||||
|
@ -2181,6 +2631,12 @@
|
|||
* Dev - Table creation validation for install routine #2287
|
||||
* Dev - Update the icons used in the blocks. #1644
|
||||
|
||||
= 4.2.5 2022-03-10 =
|
||||
|
||||
**WooCommerce**
|
||||
|
||||
* Security - Address an issue with the PayPal Standard Payment Gateway. See https://developer.woocommerce.com/2022/03/10/woocommerce-3-5-10-6-3-1-security-releases/. ([#32057](https://github.com/woocommerce/woocommerce/pull/32057))
|
||||
|
||||
= 4.2.3 2021-07-14 =
|
||||
|
||||
**WooCommerce**
|
||||
|
@ -2265,6 +2721,12 @@
|
|||
* Dev - Dynamic Currency with Context API #4027
|
||||
* Dev - Remove Duplicate array entry #4049
|
||||
|
||||
= 4.1.4 2022-03-10 =
|
||||
|
||||
**WooCommerce**
|
||||
|
||||
* Security - Address an issue with the PayPal Standard Payment Gateway. See https://developer.woocommerce.com/2022/03/10/woocommerce-3-5-10-6-3-1-security-releases/. ([#32057](https://github.com/woocommerce/woocommerce/pull/32057))
|
||||
|
||||
= 4.1.2 2021-07-14 =
|
||||
|
||||
**WooCommerce**
|
||||
|
@ -2330,6 +2792,12 @@
|
|||
* Dev - Adds usage data for the of cart & checkout blocks (currently in development in WooCommmerce Blocks plugin) to the WC Tracker snapshot. #26084
|
||||
* Dev - Implement some additional tracks for coupons, orders, and products. #26085
|
||||
|
||||
= 4.0.4 2022-03-10 =
|
||||
|
||||
**WooCommerce**
|
||||
|
||||
* Security - Address an issue with the PayPal Standard Payment Gateway. See https://developer.woocommerce.com/2022/03/10/woocommerce-3-5-10-6-3-1-security-releases/. ([#32057](https://github.com/woocommerce/woocommerce/pull/32057))
|
||||
|
||||
= 4.0.2 2021-07-14 =
|
||||
|
||||
**WooCommerce**
|
||||
|
@ -2454,6 +2922,12 @@
|
|||
* Dev - Applies woocommerce_maxmind_geolocation_database_path in MaxMind database migration. #25681
|
||||
* Dev - Support both .data() and .dataset for formdata in add to cart requests. #25726
|
||||
|
||||
= 3.9.5 2022-03-10 =
|
||||
|
||||
**WooCommerce**
|
||||
|
||||
* Security - Address an issue with the PayPal Standard Payment Gateway. See https://developer.woocommerce.com/2022/03/10/woocommerce-3-5-10-6-3-1-security-releases/. ([#32057](https://github.com/woocommerce/woocommerce/pull/32057))
|
||||
|
||||
= 3.9.4 2021-07-14 =
|
||||
|
||||
**WooCommerce**
|
||||
|
@ -2569,6 +3043,12 @@
|
|||
* Localization - Fixed translatable string comments for translators. #24928
|
||||
* Localization - Add postcode validation for Slovenia. #25174
|
||||
|
||||
= 3.8.3 2022-03-10 =
|
||||
|
||||
**WooCommerce**
|
||||
|
||||
* Security - Address an issue with the PayPal Standard Payment Gateway. See https://developer.woocommerce.com/2022/03/10/woocommerce-3-5-10-6-3-1-security-releases/. ([#32057](https://github.com/woocommerce/woocommerce/pull/32057))
|
||||
|
||||
= 3.8.2 2021-07-14 =
|
||||
|
||||
**WooCommerce**
|
||||
|
@ -2691,6 +3171,12 @@
|
|||
* Security - Add an exit after the redirect when checking author archive capabilities for customers.
|
||||
* Security - Ensure 404 pages with single product urls cannot be exploited using Open Redirect.
|
||||
|
||||
= 3.7.3 2022-03-10 =
|
||||
|
||||
**WooCommerce**
|
||||
|
||||
* Security - Address an issue with the PayPal Standard Payment Gateway. See https://developer.woocommerce.com/2022/03/10/woocommerce-3-5-10-6-3-1-security-releases/. ([#32057](https://github.com/woocommerce/woocommerce/pull/32057))
|
||||
|
||||
= 3.7.2 2021-07-14 =
|
||||
|
||||
**WooCommerce**
|
||||
|
@ -2803,6 +3289,12 @@
|
|||
* Localization - Add new currency for São Tomé, Príncipe dobra and Mauritanian ouguiya. #23950
|
||||
* Localization - Change Canada poscode label to `Postal code`. #23740
|
||||
|
||||
= 3.6.7 2022-03-10 =
|
||||
|
||||
**WooCommerce**
|
||||
|
||||
* Security - Address an issue with the PayPal Standard Payment Gateway. See https://developer.woocommerce.com/2022/03/10/woocommerce-3-5-10-6-3-1-security-releases/. ([#32057](https://github.com/woocommerce/woocommerce/pull/32057))
|
||||
|
||||
= 3.6.6 2021-07-14 =
|
||||
|
||||
**WooCommerce**
|
||||
|
@ -3132,6 +3624,12 @@
|
|||
* Localization - Update CA address format. #22692
|
||||
* Localization - Updated JP field order. #22774
|
||||
|
||||
= 3.5.10 2022-03-10 =
|
||||
|
||||
**WooCommerce**
|
||||
|
||||
* Security - Address an issue with the PayPal Standard Payment Gateway. See https://developer.woocommerce.com/2022/03/10/woocommerce-3-5-10-6-3-1-security-releases/. ([#32057](https://github.com/woocommerce/woocommerce/pull/32057))
|
||||
|
||||
= 3.5.9 2021-07-14 =
|
||||
|
||||
**WooCommerce**
|
||||
|
|
14
package.json
14
package.json
|
@ -14,22 +14,28 @@
|
|||
"url": "https://github.com/woocommerce/woocommerce/issues"
|
||||
},
|
||||
"scripts": {
|
||||
"preinstall": "npx only-allow pnpm"
|
||||
"preinstall": "npx only-allow pnpm",
|
||||
"postinstall": "pnpm git:update-hooks",
|
||||
"git:update-hooks": "rm -r .git/hooks && mkdir -p .git/hooks && husky install",
|
||||
"create-extension": "node ./tools/create-extension/index.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@automattic/nx-composer": "^0.1.0",
|
||||
"@nrwl/cli": "^13.3.4",
|
||||
"@nrwl/linter": "^13.3.4",
|
||||
"@nrwl/devkit": "^13.1.4",
|
||||
"@nrwl/linter": "^13.3.4",
|
||||
"@nrwl/tao": "13.3.4",
|
||||
"@nrwl/web": "^13.3.4",
|
||||
"@nrwl/workspace": "^13.3.4",
|
||||
"@types/node": "14.14.33",
|
||||
"@woocommerce/eslint-plugin": "^1.3.0",
|
||||
"@woocommerce/eslint-plugin": "workspace:*",
|
||||
"@wordpress/eslint-plugin": "^11.0.0",
|
||||
"@wordpress/prettier-config": "^1.1.1",
|
||||
"chalk": "^4.1.2",
|
||||
"glob": "^7.2.0",
|
||||
"husky": "^7.0.4",
|
||||
"jest": "^27.3.1",
|
||||
"lint-staged": "^12.3.7",
|
||||
"mkdirp": "^1.0.4",
|
||||
"node-stream-zip": "^1.15.0",
|
||||
"prettier": "npm:wp-prettier@^2.2.1-beta-1",
|
||||
|
@ -40,7 +46,9 @@
|
|||
"@babel/core": "7.12.9",
|
||||
"@wordpress/babel-plugin-import-jsx-pragma": "^3.1.0",
|
||||
"@wordpress/babel-preset-default": "^6.4.1",
|
||||
"fs-extra": "^10.0.1",
|
||||
"lodash": "^4.17.21",
|
||||
"promptly": "^3.2.0",
|
||||
"wp-textdomain": "1.0.1"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
# WooCommerce Packages
|
||||
|
||||
Currently we have a small set of public-facing packages that can be dowloaded from [npm](https://www.npmjs.com/org/woocommerce) and used in external applications.
|
||||
|
||||
- `@woocommerce/components`: A library of components that can be used to create pages in the WooCommerce dashboard and reports pages.
|
||||
- `@woocommerce/csv-export`: A set of functions to convert data into CSV values, and enable a browser download of the CSV data.
|
||||
- `@woocommerce/currency`: A class to display and work with currency values.
|
||||
- `@woocommerce/date`: A collection of utilities to display and work with date values.
|
||||
- `@woocommerce/navigation`: A collection of navigation-related functions for handling query parameter objects, serializing query parameters, updating query parameters, and triggering path changes.
|
||||
- `@woocommerce/tracks`: User event tracking utility functions for Automattic based projects.
|
||||
|
||||
## Working with existing packages
|
||||
|
||||
- You can make changes to packages files as normal, and running `pnpm start` will compile and watch both app files and packages.
|
||||
- :warning: Make sure any dependencies you add to a package are also added to that package's `package.json`, not just the woocommerce-admin package.json
|
||||
- :warning: Make sure you're not importing from any woocommerce-admin files outside of the package (you can import from other packages, just use the `import from @woocommerce/package` syntax).
|
||||
- Add your change to the CHANGELOG for that package under the next version number, creating one if necessary (we use semantic versioning for packages, [see these guidelines](https://github.com/WordPress/gutenberg/blob/master/CONTRIBUTING.md#maintaining-changelogs)).
|
||||
- Don't change the version in `package.json`.
|
||||
- Label your PR with the `Packages` label.
|
||||
- Once merged, you can wait for the next package release roundup, or you can publish a release now (see below, "Publishing packages").
|
||||
|
||||
---
|
||||
|
||||
## Creating a new package
|
||||
|
||||
Most of this is pulled [from the Gutenberg workflow](https://github.com/WordPress/gutenberg/blob/master/CONTRIBUTING.md#creating-new-package).
|
||||
|
||||
To create a new package, add a new folder to `/packages`, containing…
|
||||
|
||||
1. `package.json` based on the template:
|
||||
```json
|
||||
{
|
||||
"name": "@woocommerce/package-name",
|
||||
"version": "1.0.0-beta.0",
|
||||
"description": "Package description.",
|
||||
"author": "Automattic",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"keywords": [ "wordpress", "woocommerce" ],
|
||||
"homepage": "https://github.com/woocommerce/woocommerce/tree/main/packages/[_YOUR_PACKAGE_]/README.md",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/woocommerce/woocommerce.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/woocommerce/woocommerce/issues"
|
||||
},
|
||||
"main": "build/index.js",
|
||||
"module": "build-module/index.js",
|
||||
"react-native": "src/index",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
```
|
||||
2. `.npmrc` file which disables creating `package-lock.json` file for the package:
|
||||
```
|
||||
package-lock=false
|
||||
```
|
||||
3. `README.md` file containing at least:
|
||||
- Package name
|
||||
- Package description
|
||||
- Installation details
|
||||
- Usage example
|
||||
4. A `src` directory for the source of your module, which will be built by default using the `pnpm run build:packages` command. Note that you'll want an `index.js` file that exports the package contents, see other packages for examples.
|
||||
|
||||
5. Add the new package name to `packages/dependency-extraction-webpack-plugin/assets/packages.js` so that users of that plugin will also be able to use the new package without enqueuing it.
|
||||
|
||||
---
|
||||
|
||||
## Publishing packages
|
||||
|
||||
- Run `pnpm run publish-packages:check` to run pnpm publish with the `--dry-run` option
|
||||
- Create a PR with a CHANGELOG for each updated package (or try to add to the CHANGELOG with any PR editing `packages/`)
|
||||
- Run `pnpm run publish-packages:prod` to publish the package
|
||||
- _OR_ Run `pnpm run publish-packages:dev` to publish "next" releases (installed as `pnpm i @woocommerce/package@next`). Only use `:dev` if you have a reason to.
|
||||
- Both commands will run `build:packages` before the publishing task, just to catch any last updates.
|
||||
|
||||
### Publishing a single package
|
||||
|
||||
Sometimes, its helpful to release a singular package. This can be done directly through pnpm. Be sure versions and builds are correct.
|
||||
|
||||
- Bump the version in the package's package.json as well as its CHANGELOG file.
|
||||
- `pnpm install && pnpm run build:packages` to build packages.
|
||||
- `cd packages/<package-name>`
|
||||
- `pnpm publish`
|
|
@ -0,0 +1,4 @@
|
|||
module.exports = {
|
||||
extends: [ 'plugin:@woocommerce/eslint-plugin/recommended' ],
|
||||
root: true,
|
||||
};
|
|
@ -0,0 +1 @@
|
|||
package-lock=false
|
|
@ -0,0 +1,56 @@
|
|||
# Unreleased
|
||||
|
||||
- Add E2E tests to disabled welcome modal #32505
|
||||
|
||||
- Update test for payment task. #32467
|
||||
|
||||
- Increase timeout threshold for payment task. #32605
|
||||
|
||||
# 1.0.0
|
||||
|
||||
- Add returned type annotations and remove unused vars. #8020
|
||||
|
||||
- Add E2E tests for checking store currency if it matches the onboarded country. #7712
|
||||
|
||||
- Make unchecking free features more robust. #7761
|
||||
|
||||
- Fix typescript type error in admin-e2e-tests package #7765
|
||||
|
||||
- Add extension deactivation util function addition. #7804
|
||||
|
||||
- Add tests to Subscriptions inclusion. #7804
|
||||
|
||||
- Add missing dependencies. #8349
|
||||
|
||||
- Update all js packages with minor/patch version changes. #8392
|
||||
|
||||
- Add E2E test for checking onboarding tab clickable after going back. #8469
|
||||
## Breaking changes
|
||||
|
||||
- Update `@types/jest` to v27
|
||||
- Update the peer dependency constraint `@typescript-eslint/eslint-plugin` to ^5.
|
||||
- eslint-plugin: ban-types no longer reports object by default.
|
||||
|
||||
|
||||
# 0.1.2
|
||||
|
||||
- Add Customers to analytics pages tested #7573
|
||||
- Add `waitForTimeout` utility function #7572
|
||||
- Update analytics overview tests to allow re-running the tests.
|
||||
|
||||
# 0.1.1
|
||||
|
||||
- Allow packages to be built in isolation. #7286
|
||||
- Add scope to BACS slotfill #7405
|
||||
- Update e2e matcher for tasklist header #7406
|
||||
- Update homescreen, utils, payment task, payments setup. #7338
|
||||
- Refactor package style builds #7531
|
||||
- Updated onboarding tests to include email prefill and move client setup checkbox to business step.
|
||||
- Payment task update. #7577
|
||||
- Add test cases for the home screen tasklist and activity panels. #7509
|
||||
- Add wait for orders text on activity panel. #7550
|
||||
- Allow CBD to be optional in business details in E2E. #7675
|
||||
|
||||
# 0.1.0
|
||||
|
||||
- Released initial package
|
|
@ -0,0 +1,56 @@
|
|||
# Admin E2E Tests
|
||||
|
||||
An end-to-end test suite for WooCommerce setup, onboarding, home screen/task list, and analytics.
|
||||
|
||||
## Installation
|
||||
|
||||
Install the module
|
||||
|
||||
```bash
|
||||
pnpm install @woocommerce/admin-e2e-tests --save
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
Create a E2E test specification file under `/tests/e2e/specs/example.test.js`:
|
||||
|
||||
```js
|
||||
const { testAdminBasicSetup } = require( '@woocommerce/admin-e2e-tests' );
|
||||
|
||||
testAdminBasicSetup();
|
||||
```
|
||||
|
||||
See the [wooCommerce E2E Boilerplate](https://github.com/woocommerce/woocommerce-e2e-boilerplate) for instructions on setting up an E2E test environment.
|
||||
|
||||
### Configuration
|
||||
|
||||
Add the following entries to `tests/e2e/config/default.json`
|
||||
|
||||
```json
|
||||
"onboardingwizard": {
|
||||
"industry": "Test industry",
|
||||
"numberofproducts": "1 - 10",
|
||||
"sellingelsewhere": "No"
|
||||
},
|
||||
"settings": {
|
||||
"shipping": {
|
||||
"zonename": "United States",
|
||||
"zoneregions": "United States (US)",
|
||||
"shippingmethod": "Free shipping"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Available tests
|
||||
|
||||
The following test functions are included in the package:
|
||||
|
||||
| Function | Description |
|
||||
| --- | --- |
|
||||
| `testAdminBasicSetup` | Test that WooCommerce can be activated with pretty permalinks |
|
||||
| `testAdminOnboardingWizard` | Complete the onboarding wizard with US merchant |
|
||||
| `testAdminNonUSRecommendedFeatures` | Complete the onboarding wizard with non-US merchant |
|
||||
| `testSelectiveBundleWCPay` | Ensure onboarding wizard offers WC Payments in appropriate contexts |
|
||||
| `testAdminAnalyticsPages` | Test that the React App is functional on Analytics pages |
|
||||
| `testAdminCouponsPage` | Test that the Coupons is functional |
|
||||
| `testAdminPaymentSetupTask` | Test that payment methods can be configured |
|
|
@ -0,0 +1,65 @@
|
|||
{
|
||||
"name": "@woocommerce/admin-e2e-tests",
|
||||
"version": "1.0.0",
|
||||
"author": "Automattic",
|
||||
"description": "E2E tests for the new WooCommerce interface.",
|
||||
"homepage": "https://github.com/woocommerce/woocommerce/tree/trunk/packages/js/admin-e2e-tests/README.md",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/woocommerce/woocommerce.git"
|
||||
},
|
||||
"keywords": [
|
||||
"woocommerce",
|
||||
"e2e"
|
||||
],
|
||||
"license": "GPL-3.0+",
|
||||
"main": "build/index.js",
|
||||
"types": "build/index.d.ts",
|
||||
"files": [
|
||||
"/build/",
|
||||
"!*.ts.map",
|
||||
"!*.tsbuildinfo"
|
||||
],
|
||||
"sideEffects": false,
|
||||
"dependencies": {
|
||||
"@jest/globals": "^26.6.2",
|
||||
"@types/jest": "^27.4.1",
|
||||
"config": "^3.3.7"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@woocommerce/e2e-environment": "^0.2.3 || ^0.3.0",
|
||||
"@woocommerce/e2e-utils": "^0.2.0",
|
||||
"puppeteer": "^2.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.17.5",
|
||||
"@types/expect-puppeteer": "^4.4.7",
|
||||
"@types/puppeteer": "^5.4.5",
|
||||
"@typescript-eslint/eslint-plugin": "^5.14.0",
|
||||
"@woocommerce/api": "^0.2.0",
|
||||
"@wordpress/eslint-plugin": "^11.0.0",
|
||||
"eslint": "^8.12.0",
|
||||
"jest": "^27.5.1",
|
||||
"jest-cli": "^27.5.1",
|
||||
"jest-mock-extended": "^1.0.18",
|
||||
"rimraf": "^3.0.2",
|
||||
"ts-jest": "^27.1.3",
|
||||
"typescript": "^4.6.2"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"scripts": {
|
||||
"prepare": "pnpm run build",
|
||||
"build": "tsc --build",
|
||||
"start": "tsc --build --watch",
|
||||
"clean": "pnpm exec rimraf tsconfig.tsbuildinfo build build-*",
|
||||
"lint": "eslint src",
|
||||
"prepack": "pnpm run clean && pnpm run build"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.(t|j)s?(x)": [
|
||||
"eslint --fix"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
{
|
||||
"root": "packages/js/admin-e2e-tests",
|
||||
"sourceRoot": "packages/js/admin-e2e-tests/src",
|
||||
"projectType": "library",
|
||||
"targets": {
|
||||
"changelog": {
|
||||
"executor": "./tools/executors/changelogger:changelog",
|
||||
"options": {
|
||||
"action": "add",
|
||||
"cwd": "packages/js/admin-e2e-tests"
|
||||
}
|
||||
},
|
||||
"build": {
|
||||
"executor": "@nrwl/workspace:run-script",
|
||||
"options": {
|
||||
"script": "build"
|
||||
}
|
||||
},
|
||||
"build-watch": {
|
||||
"executor": "@nrwl/workspace:run-script",
|
||||
"options": {
|
||||
"script": "start"
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"executor": "@nrwl/workspace:run-script",
|
||||
"options": {
|
||||
"script": "test"
|
||||
}
|
||||
},
|
||||
"clean": {
|
||||
"executor": "@nrwl/workspace:run-script",
|
||||
"options": {
|
||||
"script": "clean"
|
||||
}
|
||||
},
|
||||
"prepare": {
|
||||
"executor": "@nrwl/workspace:run-script",
|
||||
"options": {
|
||||
"script": "prepare"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
export const TaskTitles = {
|
||||
storeDetails: 'Store details',
|
||||
addPayments: 'Set up payments',
|
||||
wooPayments:
|
||||
'Set up WooCommerce PaymentsBy setting up, you are agreeing to the Terms of Service2 minutes',
|
||||
addProducts: 'Add my products',
|
||||
taxSetup: 'Set up tax',
|
||||
setUpShippingCosts: 'Set up shipping',
|
||||
personalizeStore: 'Personalize my store',
|
||||
};
|
|
@ -0,0 +1,14 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { Page } from 'puppeteer';
|
||||
|
||||
export abstract class BaseElement {
|
||||
protected page: Page;
|
||||
protected selector: string;
|
||||
|
||||
constructor( page: Page, selector: string ) {
|
||||
this.page = page;
|
||||
this.selector = selector;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { getElementByText, getInputValue } from '../utils/actions';
|
||||
import { BaseElement } from './BaseElement';
|
||||
|
||||
export class DropdownField extends BaseElement {
|
||||
async select( value: string ): Promise< void > {
|
||||
const currentVal = await getInputValue( this.selector + ' input' );
|
||||
if ( currentVal !== value ) {
|
||||
await this.page.click(
|
||||
this.selector + ' .woocommerce-select-control__control'
|
||||
);
|
||||
const button = await getElementByText(
|
||||
'button',
|
||||
value,
|
||||
this.selector
|
||||
);
|
||||
await button?.click();
|
||||
await this.checkSelected( value );
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
async checkSelected( value: string ): Promise< void > {
|
||||
const currentVal = await getInputValue( this.selector + ' input' );
|
||||
expect( currentVal ).toBe( value );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { BaseElement } from './BaseElement';
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
const { clearAndFillInput } = require( '@woocommerce/e2e-utils' );
|
||||
/* eslint-enable @typescript-eslint/no-var-requires */
|
||||
|
||||
export class DropdownTypeaheadField extends BaseElement {
|
||||
async search( text: string ): Promise< void > {
|
||||
await clearAndFillInput( this.selector + '-0__control-input', text );
|
||||
}
|
||||
async select( selector: string ): Promise< void > {
|
||||
await this.page.click( this.selector + `__option-0-${ selector }` );
|
||||
}
|
||||
|
||||
async checkSelected( value: string ): Promise< void > {
|
||||
const selector = this.selector + '-0__control-input';
|
||||
await page.focus( selector );
|
||||
const field = await this.page.$( selector );
|
||||
const curValue = await field?.getProperty( 'value' );
|
||||
if ( curValue ) {
|
||||
const fieldValue = ( await curValue.jsonValue() ) as string;
|
||||
// Only compare alphanumeric characters
|
||||
expect( fieldValue?.replace( /\W/g, '' ) ).toBe(
|
||||
value.replace( /\W/g, '' )
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import type { ElementHandle } from 'puppeteer';
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { BaseElement } from './BaseElement';
|
||||
import { hasClass } from '../utils/actions';
|
||||
|
||||
export class FormToggle extends BaseElement {
|
||||
// Represents a FormToggle input. Use `selector` to represent the container its found in.
|
||||
async switchOn(): Promise< void > {
|
||||
const container = await this.getCheckboxContainer();
|
||||
if ( container && ! ( await hasClass( container, 'is-checked' ) ) ) {
|
||||
const input = await this.getCheckboxInput();
|
||||
|
||||
if ( ! input ) {
|
||||
throw new Error(
|
||||
`Could not find form toggle with selector ${ this.selector }`
|
||||
);
|
||||
}
|
||||
input.click();
|
||||
|
||||
// Wait for it to be checked.
|
||||
await this.page.waitForSelector(
|
||||
`${ this.selector } .components-form-toggle.is-checked`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async switchOff(): Promise< void > {
|
||||
const container = await this.getCheckboxContainer();
|
||||
if ( container && ( await hasClass( container, 'is-checked' ) ) ) {
|
||||
const input = await this.getCheckboxInput();
|
||||
|
||||
if ( ! input ) {
|
||||
throw new Error(
|
||||
`Could not find form toggle with selector ${ this.selector }`
|
||||
);
|
||||
}
|
||||
input.click();
|
||||
|
||||
// Wait for a not checked toggle to be present.
|
||||
await page.waitForFunction(
|
||||
( selector ) => {
|
||||
return document.querySelectorAll( selector ).length;
|
||||
},
|
||||
{},
|
||||
`${ this.selector } .components-form-toggle:not(.is-checked)`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async getCheckboxContainer(): Promise< ElementHandle< Element > | null > {
|
||||
return this.page.$( `${ this.selector } .components-form-toggle` );
|
||||
}
|
||||
|
||||
async getCheckboxInput(): Promise< ElementHandle< Element > | null > {
|
||||
return this.page.$(
|
||||
`${ this.selector } .components-form-toggle__input`
|
||||
);
|
||||
}
|
||||
|
||||
async isEnabled(): Promise< void > {
|
||||
await this.page.waitForSelector(
|
||||
`${ this.selector } .components-form-toggle.is-checked`
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { Page } from 'puppeteer';
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { getElementByText, waitForElementByText } from '../utils/actions';
|
||||
import { BaseElement } from './BaseElement';
|
||||
|
||||
export class HelpMenu extends BaseElement {
|
||||
protected helpMenuId = '#contextual-help-columns';
|
||||
|
||||
constructor( page: Page ) {
|
||||
super( page, '' );
|
||||
}
|
||||
|
||||
async openHelpMenu(): Promise< void > {
|
||||
const el = await getElementByText( 'button', 'Help' );
|
||||
await el?.click();
|
||||
}
|
||||
|
||||
async openSetupWizardTab(): Promise< void > {
|
||||
const el = await waitForElementByText( '*', 'Setup wizard' );
|
||||
await el?.click();
|
||||
}
|
||||
|
||||
async enableTaskList(): Promise< void > {
|
||||
await this.openSetupWizardTab();
|
||||
|
||||
const enableLink = await getElementByText(
|
||||
'*',
|
||||
'Enable',
|
||||
this.helpMenuId
|
||||
);
|
||||
await enableLink?.click();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { ElementHandle, Page } from 'puppeteer';
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { BaseElement } from './BaseElement';
|
||||
|
||||
export class OrdersActivityPanel extends BaseElement {
|
||||
constructor( page: Page ) {
|
||||
super( page, '.woocommerce-order-activity-card' );
|
||||
}
|
||||
|
||||
async getDisplayedOrders(): Promise< string[] > {
|
||||
await this.page.waitForSelector(
|
||||
'.woocommerce-order-activity-card h3'
|
||||
);
|
||||
const list = await this.page.$$(
|
||||
'.woocommerce-order-activity-card h3'
|
||||
);
|
||||
return Promise.all(
|
||||
list.map( async ( item: ElementHandle ) => {
|
||||
const textContent = await page.evaluate(
|
||||
( el ) => el.textContent,
|
||||
item
|
||||
);
|
||||
return textContent.trim();
|
||||
} )
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { httpClient } from './http-client';
|
||||
|
||||
const actionSchedulerEndpoint = '/woocommerce-reset/v1/cron/run';
|
||||
|
||||
export async function runActionScheduler() {
|
||||
const response = await httpClient.post( actionSchedulerEndpoint );
|
||||
if ( response.statusCode !== 404 ) {
|
||||
expect( response.statusCode ).toEqual( 200 );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { HTTPClientFactory } from '@woocommerce/api';
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
const config = require( 'config' );
|
||||
|
||||
// Prepare the HTTP client that will be consumed by the repository.
|
||||
// This is necessary so that it can make requests to the REST API.
|
||||
const admin = config.get( 'users.admin' );
|
||||
const url = config.get( 'url' );
|
||||
|
||||
export const httpClient = HTTPClientFactory.build( url )
|
||||
.withBasicAuth( admin.username, admin.password )
|
||||
.create();
|
|
@ -0,0 +1,4 @@
|
|||
export * from './orders';
|
||||
export * from './options';
|
||||
export * from './reset';
|
||||
export * from './action-scheduler';
|
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { httpClient } from './http-client';
|
||||
|
||||
const optionsEndpoint = '/wc-admin/options';
|
||||
|
||||
export async function updateOption(
|
||||
optionName: string,
|
||||
optionValue: string
|
||||
): Promise< void > {
|
||||
const response = await httpClient.post( optionsEndpoint, {
|
||||
[ optionName ]: optionValue,
|
||||
} );
|
||||
expect( response.statusCode ).toEqual( 200 );
|
||||
}
|
||||
|
||||
export async function unhideTaskList( id: string ): Promise< void > {
|
||||
const response = await httpClient.post(
|
||||
`/wc-admin/onboarding/tasks/${ id }/unhide`
|
||||
);
|
||||
expect( response.statusCode ).toEqual( 200 );
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { Order } from '@woocommerce/api';
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { httpClient } from './http-client';
|
||||
|
||||
const repository = Order.restRepository( httpClient );
|
||||
|
||||
export async function createOrder( status = 'completed' ): Promise< Order > {
|
||||
// The repository can now be used to create models.
|
||||
return await repository.create( {
|
||||
paymentMethod: 'cod',
|
||||
status,
|
||||
} );
|
||||
}
|
||||
|
||||
export async function removeAllOrders(): Promise< ( boolean | undefined )[] > {
|
||||
const products = await repository.list();
|
||||
return await Promise.all(
|
||||
products
|
||||
.map( ( pr ) => ( pr.id ? repository.delete( pr.id ) : undefined ) )
|
||||
.filter( ( pr ) => !! pr )
|
||||
);
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { httpClient } from './http-client';
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
const { utils } = require( '@woocommerce/e2e-utils' );
|
||||
|
||||
const wpPluginsEndpoint = '/wp/v2/plugins';
|
||||
|
||||
type Plugin = {
|
||||
author: string;
|
||||
name: string;
|
||||
plugin: string;
|
||||
plugin_uri: string;
|
||||
status: 'active' | 'inactive';
|
||||
version: string;
|
||||
description: {
|
||||
raw: string;
|
||||
rendered: string;
|
||||
};
|
||||
};
|
||||
|
||||
export async function getPlugins(): Promise< Plugin[] > {
|
||||
const response = await httpClient.get( wpPluginsEndpoint );
|
||||
expect( response.statusCode ).toEqual( 200 );
|
||||
return response.data;
|
||||
}
|
||||
|
||||
export async function deletePlugin( pluginName: string ) {
|
||||
const response = await httpClient.delete(
|
||||
wpPluginsEndpoint + '/' + pluginName
|
||||
);
|
||||
expect( response.statusCode ).toEqual( 200 );
|
||||
}
|
||||
|
||||
export async function deactivatePlugin( pluginName: string ) {
|
||||
const response = await httpClient.post(
|
||||
wpPluginsEndpoint + '/' + pluginName,
|
||||
{
|
||||
status: 'inactive',
|
||||
}
|
||||
);
|
||||
expect( response.statusCode ).toEqual( 200 );
|
||||
}
|
||||
|
||||
async function deactivateAndDeletePlugin( pluginName: string ) {
|
||||
await deactivatePlugin( pluginName );
|
||||
await deletePlugin( pluginName );
|
||||
}
|
||||
export async function deactivateAndDeleteAllPlugins( except: string[] = [] ) {
|
||||
let plugins = await getPlugins();
|
||||
const skippedPlugins = [];
|
||||
const promises = [];
|
||||
for ( const plugin of plugins ) {
|
||||
const splitPluginName = plugin.plugin.split( '/' );
|
||||
const slug = splitPluginName[ 1 ] || splitPluginName[ 0 ];
|
||||
const slugFromName = utils.getSlug(
|
||||
plugin.name.replace( ' &', '' )
|
||||
);
|
||||
if ( ! except.includes( slug ) && ! except.includes( slugFromName ) ) {
|
||||
promises.push( deactivateAndDeletePlugin( plugin.plugin ) );
|
||||
} else {
|
||||
skippedPlugins.push( slug );
|
||||
}
|
||||
}
|
||||
await Promise.all( promises );
|
||||
plugins = await getPlugins();
|
||||
expect( plugins.length ).toEqual( skippedPlugins.length );
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { httpClient } from './http-client';
|
||||
import { deactivateAndDeleteAllPlugins } from './plugins';
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
const { utils } = require( '@woocommerce/e2e-utils' );
|
||||
|
||||
const { PLUGIN_NAME } = process.env;
|
||||
|
||||
const resetEndpoint = '/woocommerce-reset/v1/state';
|
||||
|
||||
const pluginName = PLUGIN_NAME ? PLUGIN_NAME : 'WooCommerce';
|
||||
const pluginNameSlug = utils.getSlug( pluginName );
|
||||
|
||||
const skippedPlugins = [
|
||||
'woocommerce',
|
||||
'woocommerce-admin',
|
||||
'woocommerce-reset',
|
||||
'basic-auth',
|
||||
'wp-mail-logging',
|
||||
pluginNameSlug,
|
||||
];
|
||||
|
||||
export async function resetWooCommerceState() {
|
||||
const response = await httpClient.delete( resetEndpoint );
|
||||
expect( response.data.options ).toEqual( true );
|
||||
expect( response.data.transients ).toEqual( true );
|
||||
expect( response.data.notes ).toEqual( true );
|
||||
expect( response.statusCode ).toEqual( 200 );
|
||||
await deactivateAndDeleteAllPlugins( skippedPlugins );
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { Browser, Page } from 'puppeteer';
|
||||
|
||||
declare global {
|
||||
const page: Page;
|
||||
const browser: Browser;
|
||||
const browserName: string;
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
export * from './specs';
|
|
@ -0,0 +1,8 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { BasePage } from './BasePage';
|
||||
|
||||
export class AllOrdersView extends BasePage {
|
||||
url = 'wp-admin/edit.php?post_type=shop_order';
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { BasePage } from './BasePage';
|
||||
|
||||
export type AnalyticsSection =
|
||||
| 'overview'
|
||||
| 'products'
|
||||
| 'revenue'
|
||||
| 'orders'
|
||||
| 'variations'
|
||||
| 'categories'
|
||||
| 'coupons'
|
||||
| 'taxes'
|
||||
| 'downloads'
|
||||
| 'stock'
|
||||
| 'settings';
|
||||
|
||||
export class Analytics extends BasePage {
|
||||
// If you need to navigate to the base analytics page you can go to the overview
|
||||
url = 'wp-admin/admin.php?page=wc-admin&path=%2Fanalytics%2Foverview';
|
||||
|
||||
// If you need to go to a specific single page of the analytics use `navigateToSection`
|
||||
async navigateToSection( section: AnalyticsSection ): Promise< void > {
|
||||
await this.goto( this.url.replace( 'overview', section ) );
|
||||
}
|
||||
|
||||
async isDisplayed(): Promise< void > {
|
||||
// This is a smoke test that ensures the single page was rendered without crashing
|
||||
await this.page.waitForSelector( '#woocommerce-layout__primary' );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,154 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { ElementHandle } from 'puppeteer';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import {
|
||||
waitForElementByText,
|
||||
waitUntilElementStopsMoving,
|
||||
} from '../utils/actions';
|
||||
import { Analytics } from './Analytics';
|
||||
|
||||
type Section = {
|
||||
title: string;
|
||||
element: ElementHandle< Element >;
|
||||
};
|
||||
const isSection = ( item: Section | undefined ): item is Section => {
|
||||
return !! item;
|
||||
};
|
||||
|
||||
export class AnalyticsOverview extends Analytics {
|
||||
async navigate(): Promise< void > {
|
||||
await this.navigateToSection( 'overview' );
|
||||
}
|
||||
|
||||
async getSections(): Promise< Section[] > {
|
||||
const list = await this.page.$$(
|
||||
'.woocommerce-dashboard-section .woocommerce-section-header'
|
||||
);
|
||||
const sections = await Promise.all(
|
||||
list.map( async ( item ) => {
|
||||
const title = await item.evaluate( ( element ) => {
|
||||
const header = element.querySelector( 'h2' );
|
||||
return header?.textContent;
|
||||
} );
|
||||
if ( title ) {
|
||||
return {
|
||||
title,
|
||||
element: item,
|
||||
};
|
||||
}
|
||||
return undefined;
|
||||
} )
|
||||
);
|
||||
return sections.filter( isSection );
|
||||
}
|
||||
|
||||
async getSectionTitles(): Promise< string[] > {
|
||||
const sections = ( await this.getSections() ).map(
|
||||
( section ) => section.title
|
||||
);
|
||||
return sections;
|
||||
}
|
||||
|
||||
async openSectionEllipsis( sectionTitle: string ): Promise< void > {
|
||||
const section = ( await this.getSections() ).find(
|
||||
( thisSection ) => thisSection.title === sectionTitle
|
||||
);
|
||||
if ( section ) {
|
||||
const ellipsisMenu = await section.element.$(
|
||||
'.woocommerce-ellipsis-menu .woocommerce-ellipsis-menu__toggle'
|
||||
);
|
||||
await ellipsisMenu?.click();
|
||||
await this.page.waitForSelector(
|
||||
'.woocommerce-ellipsis-menu div[role=menu]'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async closeSectionEllipsis( sectionTitle: string ): Promise< void > {
|
||||
const section = ( await this.getSections() ).find(
|
||||
( thisSection ) => thisSection.title === sectionTitle
|
||||
);
|
||||
if ( section ) {
|
||||
const ellipsisMenu = await section.element.$(
|
||||
'.woocommerce-ellipsis-menu .woocommerce-ellipsis-menu__toggle'
|
||||
);
|
||||
await ellipsisMenu?.click();
|
||||
await page.waitForFunction(
|
||||
() =>
|
||||
! document.querySelector(
|
||||
'.woocommerce-ellipsis-menu div[role=menu]'
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async removeSection( sectionTitle: string ): Promise< void > {
|
||||
await this.openSectionEllipsis( sectionTitle );
|
||||
const item = await waitForElementByText( 'div', 'Remove section' );
|
||||
await item?.click();
|
||||
}
|
||||
|
||||
async addSection( sectionTitle: string ): Promise< void > {
|
||||
await this.page.waitForSelector( "button[title='Add more sections']" );
|
||||
await this.page.click( "button[title='Add more sections']" );
|
||||
const addSectionSelector = `button[title='Add ${ sectionTitle } section']`;
|
||||
await this.page.waitForSelector( addSectionSelector );
|
||||
await waitUntilElementStopsMoving( addSectionSelector );
|
||||
await this.page.click( addSectionSelector );
|
||||
}
|
||||
|
||||
async moveSectionDown( sectionTitle: string ): Promise< void > {
|
||||
await this.openSectionEllipsis( sectionTitle );
|
||||
const item = await waitForElementByText( 'div', 'Move down' );
|
||||
await item?.click();
|
||||
}
|
||||
|
||||
async moveSectionUp( sectionTitle: string ): Promise< void > {
|
||||
await this.openSectionEllipsis( sectionTitle );
|
||||
const item = await waitForElementByText( 'div', 'Move up' );
|
||||
await item?.click();
|
||||
}
|
||||
|
||||
async getEllipsisMenuItems(
|
||||
sectionTitle: string
|
||||
): Promise<
|
||||
{ title: string | null; element: ElementHandle< Element > }[]
|
||||
> {
|
||||
await this.openSectionEllipsis( sectionTitle );
|
||||
const list = await this.page.$$(
|
||||
'.woocommerce-ellipsis-menu div[role=menuitem]'
|
||||
);
|
||||
return Promise.all(
|
||||
list.map( async ( item ) => ( {
|
||||
title: await item.evaluate(
|
||||
( element ) => element?.textContent
|
||||
),
|
||||
element: item,
|
||||
} ) )
|
||||
);
|
||||
}
|
||||
|
||||
async getEllipsisMenuCheckboxItems(
|
||||
sectionTitle: string
|
||||
): Promise<
|
||||
{ title: string | null; element: ElementHandle< Element > }[]
|
||||
> {
|
||||
await this.openSectionEllipsis( sectionTitle );
|
||||
const list = await this.page.$$(
|
||||
'.woocommerce-ellipsis-menu div[role=menuitemcheckbox]'
|
||||
);
|
||||
return Promise.all(
|
||||
list.map( async ( item ) => ( {
|
||||
title: await item.evaluate(
|
||||
( element ) => element?.textContent
|
||||
),
|
||||
element: item,
|
||||
} ) )
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,162 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { ElementHandle, Page } from 'puppeteer';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { DropdownField } from '../elements/DropdownField';
|
||||
import { DropdownTypeaheadField } from '../elements/DropdownTypeaheadField';
|
||||
import { FormToggle } from '../elements/FormToggle';
|
||||
import { getElementByText, waitForTimeout } from '../utils/actions';
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
const config = require( 'config' );
|
||||
/* eslint-enable @typescript-eslint/no-var-requires */
|
||||
const baseUrl = config.get( 'url' );
|
||||
|
||||
// Represents a page that can be navigated to
|
||||
export abstract class BasePage {
|
||||
protected page: Page;
|
||||
protected url = '';
|
||||
protected baseUrl: string = baseUrl;
|
||||
|
||||
// cache of elements that have been setup, note that they are unique "per page/per selector"
|
||||
private dropDownElements: Record< string, DropdownField > = {};
|
||||
private dropDownTypeAheadElements: Record<
|
||||
string,
|
||||
DropdownTypeaheadField
|
||||
> = {};
|
||||
private formToggleElements: Record< string, FormToggle > = {};
|
||||
|
||||
constructor( page: Page ) {
|
||||
this.page = page;
|
||||
}
|
||||
|
||||
getDropdownField( selector: string ): DropdownField {
|
||||
if ( ! this.dropDownElements[ selector ] ) {
|
||||
this.dropDownElements[ selector ] = new DropdownField(
|
||||
page,
|
||||
selector
|
||||
);
|
||||
}
|
||||
|
||||
return this.dropDownElements[ selector ];
|
||||
}
|
||||
|
||||
getDropdownTypeahead( selector: string ): DropdownTypeaheadField {
|
||||
if ( ! this.dropDownTypeAheadElements[ selector ] ) {
|
||||
this.dropDownTypeAheadElements[
|
||||
selector
|
||||
] = new DropdownTypeaheadField( page, selector );
|
||||
}
|
||||
|
||||
return this.dropDownTypeAheadElements[ selector ];
|
||||
}
|
||||
|
||||
getFormToggle( selector: string ): FormToggle {
|
||||
if ( ! this.formToggleElements[ selector ] ) {
|
||||
this.formToggleElements[ selector ] = new FormToggle(
|
||||
page,
|
||||
selector
|
||||
);
|
||||
}
|
||||
|
||||
return this.formToggleElements[ selector ];
|
||||
}
|
||||
|
||||
async click( selector: string ): Promise< void > {
|
||||
await this.page.waitForSelector( selector );
|
||||
await this.page.click( selector );
|
||||
}
|
||||
|
||||
async clickButtonWithText( text: string ): Promise< void > {
|
||||
const el = await getElementByText( 'button', text );
|
||||
await el?.click();
|
||||
}
|
||||
|
||||
async clickElementWithText(
|
||||
element: string,
|
||||
text: string
|
||||
): Promise< void > {
|
||||
const el = await getElementByText( element, text );
|
||||
await el?.click();
|
||||
}
|
||||
|
||||
async setCheckboxWithText( text: string ): Promise< void > {
|
||||
let checkbox = await getElementByText( 'label', text );
|
||||
|
||||
if ( ! checkbox ) {
|
||||
checkbox = await getElementByText( 'span', text );
|
||||
}
|
||||
|
||||
if ( checkbox ) {
|
||||
const checkboxStatus = await (
|
||||
await checkbox.getProperty( 'checked' )
|
||||
).jsonValue();
|
||||
|
||||
if ( checkboxStatus !== true ) {
|
||||
await checkbox.click();
|
||||
}
|
||||
} else {
|
||||
throw new Error( `Could not find checkbox with text "${ text }"` );
|
||||
}
|
||||
}
|
||||
|
||||
async unsetAllCheckboxes( selector: string ): Promise< void > {
|
||||
const checkboxes = await page.$$( selector );
|
||||
// Uncheck all checkboxes, to avoid installing plugins
|
||||
for ( const checkbox of checkboxes ) {
|
||||
await this.toggleCheckbox( checkbox, false );
|
||||
await waitForTimeout( 200 );
|
||||
}
|
||||
}
|
||||
|
||||
async setAllCheckboxes( selector: string ): Promise< void > {
|
||||
const checkboxes = await page.$$( selector );
|
||||
// Uncheck all checkboxes, to avoid installing plugins
|
||||
for ( const checkbox of checkboxes ) {
|
||||
await this.toggleCheckbox( checkbox, true );
|
||||
await waitForTimeout( 200 );
|
||||
}
|
||||
}
|
||||
|
||||
// Set or unset a checkbox based on `checked` value passed.
|
||||
async toggleCheckbox(
|
||||
checkbox: ElementHandle< Element >,
|
||||
checked: boolean
|
||||
): Promise< void > {
|
||||
const checkboxStatus = await (
|
||||
await checkbox.getProperty( 'checked' )
|
||||
).jsonValue();
|
||||
|
||||
if ( checkboxStatus !== checked ) {
|
||||
await checkbox.click();
|
||||
}
|
||||
}
|
||||
|
||||
async navigate(): Promise< void > {
|
||||
if ( ! this.url ) {
|
||||
throw new Error( 'You must define a url for the page object' );
|
||||
}
|
||||
|
||||
await this.goto( this.url );
|
||||
}
|
||||
|
||||
protected async goto( url: string ): Promise< void > {
|
||||
const fullUrl = baseUrl + url;
|
||||
try {
|
||||
await this.page.goto( fullUrl, {
|
||||
waitUntil: 'networkidle0',
|
||||
timeout: 10000,
|
||||
} );
|
||||
} catch ( e ) {
|
||||
if ( e instanceof Error ) {
|
||||
throw new Error(
|
||||
`Could not navigate to url: ${ fullUrl } with error: ${ e.message }`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { BasePage } from './BasePage';
|
||||
|
||||
export class Coupons extends BasePage {
|
||||
url = 'wp-admin/edit.php?post_type=shop_coupon&legacy_coupon_menu=1';
|
||||
|
||||
async isDisplayed(): Promise< void > {
|
||||
// This is a smoke test that ensures the single page was rendered without crashing
|
||||
await this.page.waitForSelector( '#woocommerce-layout__primary' );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { Analytics } from './Analytics';
|
||||
|
||||
export class Customers extends Analytics {
|
||||
// The analytics pages are `analytics-{slug}`.
|
||||
url = 'wp-admin/admin.php?page=wc-admin&path=%2Fcustomers';
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { BasePage } from './BasePage';
|
||||
|
||||
export class Dashboard extends BasePage {
|
||||
url = 'wp-admin';
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { getElementByText } from '../utils/actions';
|
||||
import { BasePage } from './BasePage';
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
const { clearAndFillInput } = require( '@woocommerce/e2e-utils' );
|
||||
const config = require( 'config' );
|
||||
|
||||
export class Login extends BasePage {
|
||||
url = 'wp-login.php';
|
||||
|
||||
async login(): Promise< void > {
|
||||
await this.navigate();
|
||||
|
||||
await getElementByText( 'label', 'Username or Email Address' );
|
||||
await clearAndFillInput( '#user_login', ' ' );
|
||||
|
||||
await this.page.type(
|
||||
'#user_login',
|
||||
config.get( 'users.admin.username' )
|
||||
);
|
||||
await this.page.type(
|
||||
'#user_pass',
|
||||
config.get( 'users.admin.password' )
|
||||
);
|
||||
|
||||
await Promise.all( [
|
||||
this.page.click( 'input[type=submit]' ),
|
||||
this.page.waitForNavigation( {
|
||||
waitUntil: 'networkidle0',
|
||||
timeout: 10000,
|
||||
} ),
|
||||
] );
|
||||
}
|
||||
|
||||
async logout(): Promise< void > {
|
||||
// Log out link in admin bar is not visible so can't be clicked directly.
|
||||
const logoutLinks = await this.page.$$eval(
|
||||
'#wp-admin-bar-logout a',
|
||||
( am ) =>
|
||||
am
|
||||
.filter( ( e ) => ( e as HTMLLinkElement ).href )
|
||||
.map( ( e ) => ( e as HTMLLinkElement ).href )
|
||||
);
|
||||
|
||||
await page.goto( logoutLinks[ 0 ], {
|
||||
waitUntil: 'networkidle0',
|
||||
timeout: 10000,
|
||||
} );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { BasePage } from './BasePage';
|
||||
|
||||
export class NewCoupon extends BasePage {
|
||||
url = 'wp-admin/post-new.php?post_type=shop_coupon';
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { BasePage } from './BasePage';
|
||||
|
||||
export class NewOrder extends BasePage {
|
||||
url = 'wp-admin/post-new.php?post_type=shop_order';
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { BasePage } from './BasePage';
|
||||
|
||||
export class NewProduct extends BasePage {
|
||||
url = 'wp-admin/post-new.php?post_type=product';
|
||||
}
|
|
@ -0,0 +1,157 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { Page } from 'puppeteer';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { BusinessSection } from '../sections/onboarding/BusinessSection';
|
||||
import { IndustrySection } from '../sections/onboarding/IndustrySection';
|
||||
import { ProductTypeSection } from '../sections/onboarding/ProductTypesSection';
|
||||
import {
|
||||
StoreDetails,
|
||||
StoreDetailsSection,
|
||||
} from '../sections/onboarding/StoreDetailsSection';
|
||||
import { ThemeSection } from '../sections/onboarding/ThemeSection';
|
||||
import { BasePage } from './BasePage';
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
const { expect } = require( '@jest/globals' );
|
||||
const config = require( 'config' );
|
||||
|
||||
export class OnboardingWizard extends BasePage {
|
||||
url = 'wp-admin/admin.php?page=wc-admin&path=/setup-wizard';
|
||||
|
||||
storeDetails: StoreDetailsSection;
|
||||
industry: IndustrySection;
|
||||
productTypes: ProductTypeSection;
|
||||
business: BusinessSection;
|
||||
themes: ThemeSection;
|
||||
|
||||
constructor( page: Page ) {
|
||||
super( page );
|
||||
this.storeDetails = new StoreDetailsSection( page );
|
||||
this.industry = new IndustrySection( page );
|
||||
this.productTypes = new ProductTypeSection( page );
|
||||
this.business = new BusinessSection( page );
|
||||
this.themes = new ThemeSection( page );
|
||||
}
|
||||
|
||||
async skipStoreSetup(): Promise< void > {
|
||||
await this.clickButtonWithText( 'Skip setup store details' );
|
||||
await this.optionallySelectUsageTracking( false );
|
||||
}
|
||||
|
||||
async continue(): Promise< void > {
|
||||
await this.clickButtonWithText( 'Continue' );
|
||||
}
|
||||
|
||||
async optionallySelectUsageTracking( select = false ): Promise< void > {
|
||||
const usageTrackingHeader = await this.page.waitForSelector(
|
||||
'.components-modal__header-heading',
|
||||
{
|
||||
timeout: 5000,
|
||||
}
|
||||
);
|
||||
if ( ! usageTrackingHeader ) {
|
||||
return;
|
||||
}
|
||||
await expect( page ).toMatchElement(
|
||||
'.components-modal__header-heading',
|
||||
{
|
||||
text: 'Build a better WooCommerce',
|
||||
}
|
||||
);
|
||||
|
||||
// Query for primary buttons: "Continue" and "Yes, count me in"
|
||||
const primaryButtons = await this.page.$$( 'button.is-primary' );
|
||||
expect( primaryButtons ).toHaveLength( 2 );
|
||||
|
||||
if ( select ) {
|
||||
await this.clickButtonWithText( 'Yes, count me in' );
|
||||
} else {
|
||||
await this.clickButtonWithText( 'No thanks' );
|
||||
}
|
||||
|
||||
await this.page.waitForNavigation( {
|
||||
waitUntil: 'networkidle0',
|
||||
timeout: 4000,
|
||||
} );
|
||||
}
|
||||
|
||||
async goToOBWStep( step: string ): Promise< void > {
|
||||
await this.clickElementWithText( 'span', step );
|
||||
}
|
||||
|
||||
async walkThroughAndCompleteOnboardingWizard(
|
||||
options: {
|
||||
storeDetails?: StoreDetails;
|
||||
industries?: string[];
|
||||
products?: string[];
|
||||
businessDetails?: {
|
||||
productNumber: string;
|
||||
currentlySelling: string;
|
||||
};
|
||||
themeTitle?: string;
|
||||
} = {}
|
||||
): Promise< void > {
|
||||
await this.navigate();
|
||||
await this.storeDetails.completeStoreDetailsSection(
|
||||
options.storeDetails
|
||||
);
|
||||
|
||||
// Wait for "Continue" button to become active
|
||||
await this.continue();
|
||||
|
||||
// Wait for usage tracking pop-up window to appear
|
||||
await this.optionallySelectUsageTracking();
|
||||
// Query for the industries checkboxes
|
||||
await this.industry.isDisplayed();
|
||||
const industries = options.industries || [ 'Other' ];
|
||||
for ( const industry of industries ) {
|
||||
await this.industry.selectIndustry( industry );
|
||||
}
|
||||
await this.continue();
|
||||
await this.productTypes.isDisplayed( 7 );
|
||||
const products = options.products || [
|
||||
'Physical products',
|
||||
'Downloads',
|
||||
];
|
||||
for ( const product of products ) {
|
||||
await this.productTypes.selectProduct( product );
|
||||
}
|
||||
|
||||
await this.continue();
|
||||
await page.waitForNavigation( {
|
||||
waitUntil: 'networkidle0',
|
||||
} );
|
||||
await this.business.isDisplayed();
|
||||
|
||||
const businessDetails = options.businessDetails || {
|
||||
productNumber: config.get( 'onboardingwizard.numberofproducts' ),
|
||||
currentlySelling: config.get( 'onboardingwizard.sellingelsewhere' ),
|
||||
};
|
||||
await this.business.selectProductNumber(
|
||||
businessDetails.productNumber
|
||||
);
|
||||
await this.business.selectCurrentlySelling(
|
||||
businessDetails.currentlySelling
|
||||
);
|
||||
|
||||
await this.continue();
|
||||
await this.business.freeFeaturesIsDisplayed();
|
||||
await this.business.expandRecommendedBusinessFeatures();
|
||||
await this.business.uncheckAllRecommendedBusinessFeatures();
|
||||
|
||||
await this.continue();
|
||||
await this.themes.isDisplayed();
|
||||
|
||||
// This navigates to the home screen
|
||||
if ( options.themeTitle ) {
|
||||
await this.themes.continueWithTheme( options.themeTitle );
|
||||
} else {
|
||||
await this.themes.continueWithActiveTheme();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { waitForElementByText, getElementByText } from '../utils/actions';
|
||||
import { BasePage } from './BasePage';
|
||||
|
||||
type PaymentMethodWithSetupButton =
|
||||
| 'wcpay'
|
||||
| 'stripe'
|
||||
| 'paypal'
|
||||
| 'klarna_payments'
|
||||
| 'mollie'
|
||||
| 'bacs';
|
||||
|
||||
type PaymentMethod = PaymentMethodWithSetupButton | 'cod';
|
||||
|
||||
export class PaymentsSetup extends BasePage {
|
||||
url = 'wp-admin/admin.php?page=wc-admin&task=payments';
|
||||
|
||||
async isDisplayed(): Promise< void > {
|
||||
await waitForElementByText( 'h1', 'Set up payments' );
|
||||
}
|
||||
|
||||
async possiblyCloseHelpModal(): Promise< void > {
|
||||
try {
|
||||
await waitForElementByText( 'div', "We're here for help", {
|
||||
timeout: 2000,
|
||||
} );
|
||||
await this.clickButtonWithText( 'Got it' );
|
||||
} catch ( e ) {}
|
||||
}
|
||||
|
||||
async showOtherPaymentMethods(): Promise< void > {
|
||||
const selector = '.woocommerce-task-payments button.toggle-button';
|
||||
await this.page.waitForSelector( selector );
|
||||
const toggleButton = await this.page.$(
|
||||
`${ selector }[aria-expanded=false]`
|
||||
);
|
||||
await toggleButton?.click();
|
||||
await waitForElementByText( 'h2', 'Offline payment methods' );
|
||||
}
|
||||
|
||||
async goToPaymentMethodSetup(
|
||||
method: PaymentMethodWithSetupButton
|
||||
): Promise< void > {
|
||||
const selector = `.woocommerce-task-payment-${ method } button`;
|
||||
await this.page.waitForSelector( selector );
|
||||
const button = await this.page.$( selector );
|
||||
|
||||
if ( ! button ) {
|
||||
throw new Error(
|
||||
`Could not find button with selector: ${ selector }`
|
||||
);
|
||||
} else {
|
||||
await button.click();
|
||||
}
|
||||
}
|
||||
|
||||
async enableCashOnDelivery(): Promise< void > {
|
||||
await this.page.waitForSelector( '.woocommerce-task-payment-cod' );
|
||||
await this.clickButtonWithText( 'Enable' );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { BasePage } from './BasePage';
|
||||
|
||||
export class PermalinkSettings extends BasePage {
|
||||
url = 'wp-admin/options-permalink.php';
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { BasePage } from './BasePage';
|
||||
|
||||
export class Plugins extends BasePage {
|
||||
url = 'wp-admin/plugins.php';
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { waitForElementByText } from '../utils/actions';
|
||||
import { BasePage } from './BasePage';
|
||||
|
||||
export class ProductsSetup extends BasePage {
|
||||
url = 'wp-admin/admin.php?page=wc-admin&task=products';
|
||||
|
||||
async isDisplayed(): Promise< void > {
|
||||
await waitForElementByText( 'h1', 'Add my products' );
|
||||
}
|
||||
|
||||
async isStartWithATemplateDisplayed(
|
||||
templatesCount: number
|
||||
): Promise< void > {
|
||||
await waitForElementByText( 'h1', 'Start with a template' );
|
||||
const length = await this.page.$$eval(
|
||||
'.components-radio-control__input',
|
||||
( items ) => items.length
|
||||
);
|
||||
expect( length === templatesCount ).toBeTruthy();
|
||||
}
|
||||
|
||||
async clickStartWithTemplate(): Promise< void > {
|
||||
await this.clickElementWithText( '*', 'Start with a template' );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,145 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { ElementHandle } from 'puppeteer';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import {
|
||||
waitForElementByText,
|
||||
getElementByAttributeAndValue,
|
||||
waitForElementByTextWithoutThrow,
|
||||
getElementByText,
|
||||
waitForTimeout,
|
||||
} from '../utils/actions';
|
||||
import { BasePage } from './BasePage';
|
||||
|
||||
export class WcHomescreen extends BasePage {
|
||||
url = 'wp-admin/admin.php?page=wc-admin';
|
||||
|
||||
async isDisplayed(): Promise< void > {
|
||||
// Wait for Benefits section to appear
|
||||
await waitForElementByText( 'h1', 'Home' );
|
||||
}
|
||||
|
||||
async possiblyDismissWelcomeModal(): Promise< void > {
|
||||
const modal = await this.isWelcomeModalVisible();
|
||||
|
||||
if ( modal ) {
|
||||
await this.clickButtonWithText( 'Next' );
|
||||
await waitForTimeout( 1000 );
|
||||
await this.clickButtonWithText( 'Next' );
|
||||
await waitForTimeout( 1000 );
|
||||
await this.click( '.components-guide__finish-button' );
|
||||
await waitForTimeout( 500 );
|
||||
}
|
||||
}
|
||||
|
||||
async isWelcomeModalVisible(): Promise< boolean > {
|
||||
const modalText = 'Welcome to your WooCommerce store’s online HQ!';
|
||||
const modal = await waitForElementByTextWithoutThrow(
|
||||
'h2',
|
||||
modalText,
|
||||
10
|
||||
);
|
||||
return modal;
|
||||
}
|
||||
|
||||
async getTaskList(): Promise< Array< string | null > > {
|
||||
await page.waitForSelector(
|
||||
'.woocommerce-task-card .woocommerce-task-list__item-title'
|
||||
);
|
||||
await waitForElementByText( '*', 'Get ready to start selling' );
|
||||
const list = await this.page.$$eval(
|
||||
'.woocommerce-task-card .woocommerce-task-list__item-title',
|
||||
( items ) => items.map( ( item ) => item.textContent )
|
||||
);
|
||||
return list.map( ( item: string | null ) => {
|
||||
const match = item?.match( /(.+)[0-9] minute/ );
|
||||
if ( match && match.length > 1 ) {
|
||||
return match[ 1 ];
|
||||
}
|
||||
return item;
|
||||
} );
|
||||
}
|
||||
|
||||
async isTaskListDisplayed(): Promise< boolean > {
|
||||
return !! ( await waitForElementByTextWithoutThrow(
|
||||
'*',
|
||||
'Get ready to start selling'
|
||||
) );
|
||||
}
|
||||
|
||||
async clickOnTaskList( taskTitle: string ): Promise< void > {
|
||||
const item = await waitForElementByText( '*', taskTitle );
|
||||
|
||||
if ( ! item ) {
|
||||
throw new Error(
|
||||
`Could not find task list item with title: ${ taskTitle }`
|
||||
);
|
||||
} else {
|
||||
await item.click();
|
||||
await waitForElementByText( 'h1', taskTitle );
|
||||
}
|
||||
}
|
||||
|
||||
async hideTaskList(): Promise< void > {
|
||||
const taskListOptions = await getElementByAttributeAndValue(
|
||||
'button',
|
||||
'title',
|
||||
'Task List Options'
|
||||
);
|
||||
await taskListOptions?.click();
|
||||
await waitForElementByText( 'button', 'Hide this' );
|
||||
await waitForTimeout( 200 ); // Transition of popup.
|
||||
const hideThisButton = await getElementByText( 'button', 'Hide this' );
|
||||
await hideThisButton?.click();
|
||||
await waitForTimeout( 500 );
|
||||
}
|
||||
|
||||
async waitForNotesRequestToBeLoaded(): Promise< void > {
|
||||
await this.page.waitForResponse( ( response ) => {
|
||||
const url = encodeURIComponent( response.url() );
|
||||
return url.includes( '/wc-analytics/admin/notes' ) && response.ok();
|
||||
} );
|
||||
}
|
||||
|
||||
async isActivityPanelShown(): Promise< boolean > {
|
||||
return !! ( await this.page.$( '.woocommerce-activity-panel' ) );
|
||||
}
|
||||
|
||||
async getActivityPanels(): Promise<
|
||||
Array< { title: string; count?: number; element?: ElementHandle } >
|
||||
> {
|
||||
const panelContainer = await page.waitForSelector(
|
||||
'.woocommerce-activity-panel'
|
||||
);
|
||||
const list = await panelContainer.$$( 'h2' );
|
||||
return Promise.all(
|
||||
list.map( async ( item: ElementHandle ) => {
|
||||
const textContent = await page.evaluate(
|
||||
( el ) => el.textContent,
|
||||
item
|
||||
);
|
||||
const match = textContent?.match( /([a-zA-Z]+)([0-9]+)/ );
|
||||
if ( match && match.length > 2 ) {
|
||||
return {
|
||||
title: match[ 1 ],
|
||||
count: parseInt( match[ 2 ], 10 ),
|
||||
element: item,
|
||||
};
|
||||
}
|
||||
return { title: textContent };
|
||||
} )
|
||||
);
|
||||
}
|
||||
|
||||
async expandActivityPanel( title: string ): Promise< void > {
|
||||
const activityPanels = await this.getActivityPanels();
|
||||
const panel = activityPanels.find( ( p ) => p.title === title );
|
||||
if ( panel ) {
|
||||
await panel.element?.click();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { getAttribute, hasClass, waitForElementByText } from '../utils/actions';
|
||||
import { BasePage } from './BasePage';
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
const { setCheckbox } = require( '@woocommerce/e2e-utils' );
|
||||
/* eslint-enable @typescript-eslint/no-var-requires */
|
||||
|
||||
export class WcSettings extends BasePage {
|
||||
url = 'wp-admin/admin.php?page=wc-settings';
|
||||
|
||||
async navigate( tab = 'general', section = '' ): Promise< void > {
|
||||
let settingsUrl = this.url + `&tab=${ tab }`;
|
||||
|
||||
if ( section ) {
|
||||
settingsUrl += `§ion=${ section }`;
|
||||
}
|
||||
|
||||
await this.goto( settingsUrl );
|
||||
await waitForElementByText( 'a', 'General' );
|
||||
}
|
||||
|
||||
async enableTaxRates(): Promise< void > {
|
||||
await waitForElementByText( 'th', 'Enable taxes' );
|
||||
await setCheckbox( '#woocommerce_calc_taxes' );
|
||||
}
|
||||
|
||||
async getTaxRateValue(): Promise< unknown > {
|
||||
return await getAttribute( '#woocommerce_calc_taxes', 'checked' );
|
||||
}
|
||||
|
||||
async saveSettings(): Promise< void > {
|
||||
this.clickButtonWithText( 'Save changes' );
|
||||
await this.page.waitForNavigation( {
|
||||
waitUntil: 'networkidle0',
|
||||
} );
|
||||
await waitForElementByText(
|
||||
'strong',
|
||||
'Your settings have been saved.'
|
||||
);
|
||||
}
|
||||
|
||||
async paymentMethodIsEnabled( method = '' ): Promise< boolean > {
|
||||
await this.navigate( 'checkout' );
|
||||
await waitForElementByText( 'h2', 'Payment methods' );
|
||||
const className = await getAttribute(
|
||||
`tr[data-gateway_id=${ method }] .woocommerce-input-toggle`,
|
||||
'className'
|
||||
);
|
||||
return (
|
||||
( className as string ).indexOf(
|
||||
'woocommerce-input-toggle--disabled'
|
||||
) === -1
|
||||
);
|
||||
}
|
||||
|
||||
async cleanPaymentMethods(): Promise< void > {
|
||||
await this.navigate( 'checkout' );
|
||||
await waitForElementByText( 'h2', 'Payment methods' );
|
||||
const paymentMethods = await page.$$( 'span.woocommerce-input-toggle' );
|
||||
for ( const method of paymentMethods ) {
|
||||
if (
|
||||
method &&
|
||||
( await hasClass(
|
||||
method,
|
||||
'woocommerce-input-toggle--enabled'
|
||||
) )
|
||||
) {
|
||||
await method?.click();
|
||||
}
|
||||
}
|
||||
await this.saveSettings();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { waitForElementByText } from '../utils/actions';
|
||||
import { BasePage } from './BasePage';
|
||||
|
||||
export class WpSettings extends BasePage {
|
||||
url = 'wp-admin/options-permalink.php';
|
||||
|
||||
async openPermalinkSettings(): Promise< void > {
|
||||
await waitForElementByText( 'h1', 'Permalink Settings' );
|
||||
}
|
||||
|
||||
async saveSettings(): Promise< void > {
|
||||
await this.click( '#submit' );
|
||||
await this.page.waitForNavigation( {
|
||||
waitUntil: 'networkidle0',
|
||||
} );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { BasePage } from '../../pages/BasePage';
|
||||
import { waitForElementByText } from '../../utils/actions';
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
const {
|
||||
setCheckbox,
|
||||
unsetCheckbox,
|
||||
verifyCheckboxIsSet,
|
||||
verifyCheckboxIsUnset,
|
||||
} = require( '@woocommerce/e2e-utils' );
|
||||
/* eslint-enable @typescript-eslint/no-var-requires */
|
||||
|
||||
export class BusinessSection extends BasePage {
|
||||
async isDisplayed(): Promise< void > {
|
||||
await waitForElementByText( 'h2', 'Tell us about your business' );
|
||||
}
|
||||
|
||||
async freeFeaturesIsDisplayed(): Promise< void > {
|
||||
await waitForElementByText( 'h2', 'Included business features' );
|
||||
}
|
||||
|
||||
async selectProductNumber( productLabel: string ): Promise< void > {
|
||||
const howManyProductsDropdown = this.getDropdownField(
|
||||
'.woocommerce-profile-wizard__product-count'
|
||||
);
|
||||
|
||||
await howManyProductsDropdown.select( productLabel );
|
||||
}
|
||||
|
||||
async selectCurrentlySelling( currentlySelling: string ): Promise< void > {
|
||||
const sellingElsewhereDropdown = this.getDropdownField(
|
||||
'.woocommerce-profile-wizard__selling-venues'
|
||||
);
|
||||
|
||||
await sellingElsewhereDropdown.select( currentlySelling );
|
||||
}
|
||||
async selectEmployeesNumber( employeesNumber: string ) {
|
||||
const employeesNumberDropdown = this.getDropdownField(
|
||||
'.woocommerce-profile-wizard__number-employees'
|
||||
);
|
||||
|
||||
await employeesNumberDropdown.select( employeesNumber );
|
||||
}
|
||||
async selectRevenue( revenue: string ) {
|
||||
const revenueDropdown = this.getDropdownField(
|
||||
'.woocommerce-profile-wizard__revenue'
|
||||
);
|
||||
|
||||
await revenueDropdown.select( revenue );
|
||||
}
|
||||
async selectOtherPlatformName( otherPlatformName: string ) {
|
||||
const otherPlatformNameDropdown = this.getDropdownField(
|
||||
'.woocommerce-profile-wizard__other-platform'
|
||||
);
|
||||
|
||||
await otherPlatformNameDropdown.select( otherPlatformName );
|
||||
}
|
||||
|
||||
async selectInstallFreeBusinessFeatures(
|
||||
select: boolean
|
||||
): Promise< void > {
|
||||
if ( select ) {
|
||||
await setCheckbox( '#woocommerce-business-extensions__checkbox' );
|
||||
} else {
|
||||
await unsetCheckbox( '#woocommerce-business-extensions__checkbox' );
|
||||
}
|
||||
}
|
||||
|
||||
async expandRecommendedBusinessFeatures(): Promise< void > {
|
||||
const expandButtonSelector =
|
||||
'.woocommerce-admin__business-details__selective-extensions-bundle__expand';
|
||||
|
||||
await this.page.waitForSelector(
|
||||
expandButtonSelector + ':not([disabled])'
|
||||
);
|
||||
await this.click( expandButtonSelector );
|
||||
|
||||
// Confirm that expanding the list shows all the extensions available to install.
|
||||
await this.page.waitForFunction( () => {
|
||||
const inputsNum = document.querySelectorAll(
|
||||
'.components-checkbox-control__input'
|
||||
).length;
|
||||
return inputsNum > 1;
|
||||
} );
|
||||
}
|
||||
|
||||
async uncheckAllRecommendedBusinessFeatures(): Promise< void > {
|
||||
await this.unsetAllCheckboxes( '.components-checkbox-control__input' );
|
||||
}
|
||||
|
||||
// The old list displayed on the dropdown page
|
||||
async uncheckBusinessFeatures(): Promise< void > {
|
||||
await this.unsetAllCheckboxes(
|
||||
'.woocommerce-profile-wizard__benefit .components-form-toggle__input'
|
||||
);
|
||||
}
|
||||
|
||||
async selectSetupForClient(): Promise< void > {
|
||||
await setCheckbox( '.components-checkbox-control__input' );
|
||||
}
|
||||
|
||||
async checkClientSetupCheckbox( selected: boolean ): Promise< void > {
|
||||
if ( selected ) {
|
||||
await verifyCheckboxIsSet( '.components-checkbox-control__input' );
|
||||
} else {
|
||||
await verifyCheckboxIsUnset(
|
||||
'.components-checkbox-control__input'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { BasePage } from '../../pages/BasePage';
|
||||
import { waitForElementByText } from '../../utils/actions';
|
||||
|
||||
export class IndustrySection extends BasePage {
|
||||
async isDisplayed(
|
||||
industryCount?: number,
|
||||
industryCountMax?: number
|
||||
): Promise< void > {
|
||||
await waitForElementByText(
|
||||
'h2',
|
||||
'In which industry does the store operate?'
|
||||
);
|
||||
|
||||
if ( industryCount ) {
|
||||
const length = await this.page.$$eval(
|
||||
'.components-checkbox-control__input',
|
||||
( items ) => items.length
|
||||
);
|
||||
|
||||
if ( industryCountMax ) {
|
||||
expect(
|
||||
length >= industryCount && length <= industryCountMax
|
||||
).toBeTruthy();
|
||||
} else {
|
||||
expect( length === industryCount ).toBeTruthy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async uncheckIndustries(): Promise< void > {
|
||||
await this.unsetAllCheckboxes( '.components-checkbox-control__input' );
|
||||
}
|
||||
|
||||
async selectIndustry( industryLabel: string ): Promise< void > {
|
||||
await this.setCheckboxWithText( industryLabel );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { BasePage } from '../../pages/BasePage';
|
||||
import { waitForElementByText } from '../../utils/actions';
|
||||
|
||||
export class ProductTypeSection extends BasePage {
|
||||
async isDisplayed( productCount: number ): Promise< void > {
|
||||
await waitForElementByText(
|
||||
'h2',
|
||||
'What type of products will be listed?'
|
||||
);
|
||||
const length = await this.page.$$eval(
|
||||
'.components-checkbox-control__input',
|
||||
( items ) => items.length
|
||||
);
|
||||
expect( length === productCount ).toBeTruthy();
|
||||
}
|
||||
|
||||
async uncheckProducts(): Promise< void > {
|
||||
await this.unsetAllCheckboxes( '.components-checkbox-control__input' );
|
||||
}
|
||||
|
||||
async selectProduct( productLabel: string ): Promise< void > {
|
||||
await this.setCheckboxWithText( productLabel );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,124 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { DropdownTypeaheadField } from '../../elements/DropdownTypeaheadField';
|
||||
import { BasePage } from '../../pages/BasePage';
|
||||
import { waitForElementByText } from '../../utils/actions';
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
const {
|
||||
clearAndFillInput,
|
||||
verifyCheckboxIsSet,
|
||||
verifyCheckboxIsUnset,
|
||||
} = require( '@woocommerce/e2e-utils' );
|
||||
const config = require( 'config' );
|
||||
/* eslint-enable @typescript-eslint/no-var-requires */
|
||||
|
||||
export interface StoreDetails {
|
||||
addressLine1?: string;
|
||||
addressLine2?: string;
|
||||
countryRegionSubstring?: string;
|
||||
countryRegionSelector?: string;
|
||||
countryRegion?: string;
|
||||
city?: string;
|
||||
postcode?: string;
|
||||
storeEmail?: string;
|
||||
}
|
||||
|
||||
export class StoreDetailsSection extends BasePage {
|
||||
private get countryDropdown(): DropdownTypeaheadField {
|
||||
return this.getDropdownTypeahead( '#woocommerce-select-control' );
|
||||
}
|
||||
|
||||
async isDisplayed(): Promise< void > {
|
||||
await waitForElementByText( 'h2', 'Welcome to WooCommerce' );
|
||||
}
|
||||
|
||||
async completeStoreDetailsSection(
|
||||
storeDetails: StoreDetails = {}
|
||||
): Promise< void > {
|
||||
// const onboardingWizard = new OnboardingWizard( page );
|
||||
// Fill store's address - first line
|
||||
await this.fillAddress(
|
||||
storeDetails.addressLine1 ||
|
||||
config.get( 'addresses.admin.store.addressfirstline' )
|
||||
);
|
||||
|
||||
// Fill store's address - second line
|
||||
await this.fillAddressLineTwo(
|
||||
storeDetails.addressLine2 ||
|
||||
config.get( 'addresses.admin.store.addresssecondline' )
|
||||
);
|
||||
|
||||
// Type the requested country/region substring or 'cali' in the
|
||||
// country/region select, then select the requested country/region
|
||||
// substring or 'US:CA'.
|
||||
await this.selectCountry(
|
||||
storeDetails.countryRegionSubstring || 'cali',
|
||||
storeDetails.countryRegionSelector || 'US\\:CA'
|
||||
);
|
||||
|
||||
if ( storeDetails.countryRegion ) {
|
||||
await this.checkCountrySelected( storeDetails.countryRegion );
|
||||
}
|
||||
|
||||
// Fill the city where the store is located
|
||||
await this.fillCity(
|
||||
storeDetails.city || config.get( 'addresses.admin.store.city' )
|
||||
);
|
||||
|
||||
// Fill postcode of the store
|
||||
await this.fillPostalCode(
|
||||
storeDetails.postcode ||
|
||||
config.get( 'addresses.admin.store.postcode' )
|
||||
);
|
||||
|
||||
// Fill store's email address
|
||||
await this.fillEmailAddress(
|
||||
storeDetails.storeEmail ||
|
||||
config.get( 'addresses.admin.store.email' )
|
||||
);
|
||||
|
||||
// Verify that checkbox next to "Get tips, product updates and inspiration straight to your mailbox" is selected
|
||||
await this.checkMarketingCheckbox( true );
|
||||
}
|
||||
|
||||
async fillAddress( address: string ): Promise< void > {
|
||||
await clearAndFillInput( '#inspector-text-control-0', address );
|
||||
}
|
||||
|
||||
async fillAddressLineTwo( address: string ): Promise< void > {
|
||||
await clearAndFillInput( '#inspector-text-control-1', address );
|
||||
}
|
||||
|
||||
async selectCountry( search: string, selector: string ): Promise< void > {
|
||||
await this.countryDropdown.search( search );
|
||||
await this.countryDropdown.select( selector );
|
||||
}
|
||||
|
||||
async checkCountrySelected( country: string ): Promise< void > {
|
||||
await this.countryDropdown.checkSelected( country );
|
||||
}
|
||||
|
||||
async fillCity( city: string ): Promise< void > {
|
||||
await clearAndFillInput( '#inspector-text-control-2', city );
|
||||
}
|
||||
|
||||
async fillPostalCode( postalCode: string ): Promise< void > {
|
||||
await clearAndFillInput( '#inspector-text-control-3', postalCode );
|
||||
}
|
||||
|
||||
async fillEmailAddress( email: string ): Promise< void > {
|
||||
await clearAndFillInput( '#inspector-text-control-4', email );
|
||||
}
|
||||
|
||||
async checkMarketingCheckbox( selected: boolean ): Promise< void > {
|
||||
if ( selected ) {
|
||||
await verifyCheckboxIsSet( '.components-checkbox-control__input' );
|
||||
} else {
|
||||
await verifyCheckboxIsUnset(
|
||||
'.components-checkbox-control__input'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { BasePage } from '../../pages/BasePage';
|
||||
import { waitForElementByText } from '../../utils/actions';
|
||||
|
||||
export class ThemeSection extends BasePage {
|
||||
async isDisplayed(): Promise< void > {
|
||||
await waitForElementByText( 'h2', 'Choose a theme' );
|
||||
await waitForElementByText( 'button', 'All themes' );
|
||||
}
|
||||
|
||||
async continueWithActiveTheme(): Promise< void > {
|
||||
await this.clickButtonWithText( 'Continue with my active theme' );
|
||||
}
|
||||
|
||||
async continueWithTheme( themeTitle: string ): Promise< void > {
|
||||
const title = await waitForElementByText( 'h2', themeTitle );
|
||||
const chooseButton = await title?.evaluateHandle( ( element ) => {
|
||||
const card = element.closest( '.components-card' );
|
||||
return Array.from( card?.querySelectorAll( 'button' ) || [] ).find(
|
||||
( el ) => el.textContent === 'Choose'
|
||||
);
|
||||
} );
|
||||
if ( chooseButton ) {
|
||||
await chooseButton.asElement()?.click();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { BasePage } from '../../pages/BasePage';
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
const { clearAndFillInput } = require( '@woocommerce/e2e-utils' );
|
||||
/* eslint-enable @typescript-eslint/no-var-requires */
|
||||
|
||||
type AccountDetails = {
|
||||
accountName: string;
|
||||
accountNumber: string;
|
||||
bankName: string;
|
||||
sortCode: string;
|
||||
iban: string;
|
||||
swiftCode: string;
|
||||
};
|
||||
|
||||
export class BankAccountTransferSetup extends BasePage {
|
||||
url = 'wp-admin/admin.php?page=wc-admin&task=payments&method=bacs';
|
||||
|
||||
async saveAccountDetails( {
|
||||
accountName,
|
||||
accountNumber,
|
||||
bankName,
|
||||
sortCode,
|
||||
iban,
|
||||
swiftCode,
|
||||
}: AccountDetails ): Promise< void > {
|
||||
await clearAndFillInput( '[placeholder="Account name"]', accountName );
|
||||
await clearAndFillInput(
|
||||
'[placeholder="Account number"]',
|
||||
accountNumber
|
||||
);
|
||||
await clearAndFillInput( '[placeholder="Bank name"]', bankName );
|
||||
await clearAndFillInput( '[placeholder="Sort code"]', sortCode );
|
||||
await clearAndFillInput( '[placeholder="IBAN"]', iban );
|
||||
await clearAndFillInput( '[placeholder="BIC / Swift"]', swiftCode );
|
||||
|
||||
await this.clickButtonWithText( 'Save' );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { WcSettings } from '../../pages/WcSettings';
|
||||
import { WpSettings } from '../../pages/WpSettings';
|
||||
import { Login } from '../../pages/Login';
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
const {
|
||||
clearAndFillInput,
|
||||
verifyValueOfInputField,
|
||||
} = require( '@woocommerce/e2e-utils' );
|
||||
const {
|
||||
afterAll,
|
||||
beforeAll,
|
||||
describe,
|
||||
it,
|
||||
expect,
|
||||
} = require( '@jest/globals' );
|
||||
/* eslint-enable @typescript-eslint/no-var-requires */
|
||||
|
||||
const testAdminBasicSetup = () => {
|
||||
describe( 'Store owner can finish initial store setup', () => {
|
||||
const wcSettings = new WcSettings( page );
|
||||
const wpSettings = new WpSettings( page );
|
||||
const login = new Login( page );
|
||||
|
||||
beforeAll( async () => {
|
||||
await login.login();
|
||||
} );
|
||||
afterAll( async () => {
|
||||
await login.logout();
|
||||
} );
|
||||
|
||||
it( 'can enable tax rates and calculations', async () => {
|
||||
// Go to general settings page
|
||||
await wcSettings.navigate( 'general' );
|
||||
await wcSettings.enableTaxRates();
|
||||
await wcSettings.saveSettings();
|
||||
|
||||
// Verify that settings have been saved
|
||||
const taxRate = await wcSettings.getTaxRateValue();
|
||||
expect( taxRate ).toEqual( true );
|
||||
} );
|
||||
|
||||
it( 'can configure permalink settings', async () => {
|
||||
// Go to Permalink Settings page
|
||||
await wpSettings.navigate();
|
||||
await wpSettings.openPermalinkSettings();
|
||||
|
||||
// Select "Post name" option in common settings section
|
||||
await page.click( 'input[value="/%postname%/"]' );
|
||||
|
||||
// Select "Custom base" in product permalinks section
|
||||
await page.click( '#woocommerce_custom_selection' );
|
||||
|
||||
// Fill custom base slug to use
|
||||
await clearAndFillInput( '#woocommerce_permalink_structure', '' );
|
||||
await page.type( '#woocommerce_permalink_structure', '/product/' );
|
||||
|
||||
await wpSettings.saveSettings();
|
||||
|
||||
// Verify that settings have been saved
|
||||
await Promise.all( [
|
||||
expect( page ).toMatchElement(
|
||||
'#setting-error-settings_updated',
|
||||
{
|
||||
text: 'Permalink structure updated.',
|
||||
}
|
||||
),
|
||||
verifyValueOfInputField(
|
||||
'#permalink_structure',
|
||||
'/%postname%/'
|
||||
),
|
||||
verifyValueOfInputField(
|
||||
'#woocommerce_permalink_structure',
|
||||
'/product/'
|
||||
),
|
||||
] );
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
module.exports = { testAdminBasicSetup };
|
|
@ -0,0 +1,633 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { OnboardingWizard } from '../../pages/OnboardingWizard';
|
||||
import { WcHomescreen } from '../../pages/WcHomescreen';
|
||||
import { TaskTitles } from '../../constants/taskTitles';
|
||||
import { Login } from '../../pages/Login';
|
||||
import { WcSettings } from '../../pages/WcSettings';
|
||||
import { ProductsSetup } from '../../pages/ProductsSetup';
|
||||
import { resetWooCommerceState } from '../../fixtures/reset';
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
const {
|
||||
afterAll,
|
||||
beforeAll,
|
||||
describe,
|
||||
it,
|
||||
expect,
|
||||
} = require( '@jest/globals' );
|
||||
const config = require( 'config' );
|
||||
|
||||
const { verifyValueOfInputField } = require( '@woocommerce/e2e-utils' );
|
||||
/* eslint-enable @typescript-eslint/no-var-requires */
|
||||
|
||||
/**
|
||||
* This tests a default, happy path for the onboarding wizard.
|
||||
*/
|
||||
const testAdminOnboardingWizard = () => {
|
||||
describe( 'Store owner can complete onboarding wizard', () => {
|
||||
const profileWizard = new OnboardingWizard( page );
|
||||
const login = new Login( page );
|
||||
|
||||
beforeAll( async () => {
|
||||
await login.login();
|
||||
await resetWooCommerceState();
|
||||
} );
|
||||
afterAll( async () => {
|
||||
await login.logout();
|
||||
} );
|
||||
|
||||
it( 'can start the profile wizard', async () => {
|
||||
await profileWizard.navigate();
|
||||
} );
|
||||
|
||||
it( 'can complete the store details section', async () => {
|
||||
await profileWizard.storeDetails.isDisplayed();
|
||||
await profileWizard.storeDetails.completeStoreDetailsSection();
|
||||
// Wait for "Continue" button to become active
|
||||
await profileWizard.continue();
|
||||
|
||||
// Wait for usage tracking pop-up window to appear
|
||||
await profileWizard.optionallySelectUsageTracking();
|
||||
} );
|
||||
|
||||
it( 'can complete the industry section', async () => {
|
||||
// Query for the industries checkboxes
|
||||
await profileWizard.industry.isDisplayed( 7, 8 );
|
||||
|
||||
// Select just "fashion" and "health/beauty" to get the single checkbox business section when
|
||||
// filling out details for a US store.
|
||||
await profileWizard.industry.selectIndustry(
|
||||
'Fashion, apparel, and accessories'
|
||||
);
|
||||
await profileWizard.industry.selectIndustry( 'Health and beauty' );
|
||||
|
||||
await profileWizard.continue();
|
||||
} );
|
||||
|
||||
it( 'can click industry tab after going back', async () => {
|
||||
await profileWizard.navigate();
|
||||
await profileWizard.goToOBWStep( 'Store Details' );
|
||||
await profileWizard.storeDetails.isDisplayed();
|
||||
|
||||
await profileWizard.goToOBWStep( 'Industry' );
|
||||
await profileWizard.industry.isDisplayed();
|
||||
|
||||
await profileWizard.continue();
|
||||
} );
|
||||
|
||||
it( 'can complete the product types section', async () => {
|
||||
await profileWizard.productTypes.isDisplayed( 7 );
|
||||
|
||||
// Select Physical and Downloadable products
|
||||
await profileWizard.productTypes.selectProduct(
|
||||
'Physical products'
|
||||
);
|
||||
await profileWizard.productTypes.selectProduct( 'Downloads' );
|
||||
|
||||
await profileWizard.continue();
|
||||
} );
|
||||
|
||||
it( 'can complete the business section', async () => {
|
||||
await profileWizard.business.isDisplayed();
|
||||
await profileWizard.business.selectProductNumber(
|
||||
config.get( 'onboardingwizard.numberofproducts' )
|
||||
);
|
||||
await profileWizard.business.selectCurrentlySelling(
|
||||
config.get( 'onboardingwizard.sellingelsewhere' )
|
||||
);
|
||||
await profileWizard.business.checkClientSetupCheckbox( false );
|
||||
await profileWizard.continue();
|
||||
} );
|
||||
|
||||
it( 'can unselect all business features and continue', async () => {
|
||||
await profileWizard.business.freeFeaturesIsDisplayed();
|
||||
// Add WC Pay check
|
||||
await profileWizard.business.expandRecommendedBusinessFeatures();
|
||||
|
||||
expect( page ).toMatchElement( 'a', {
|
||||
text: 'WooCommerce Payments',
|
||||
} );
|
||||
|
||||
await profileWizard.business.uncheckAllRecommendedBusinessFeatures();
|
||||
await profileWizard.continue();
|
||||
} );
|
||||
|
||||
it( 'can complete the theme selection section', async () => {
|
||||
await profileWizard.themes.isDisplayed();
|
||||
await profileWizard.themes.continueWithActiveTheme();
|
||||
} );
|
||||
|
||||
it( 'can select the right currency on settings page related to the onboarding country', async () => {
|
||||
const settingsScreen = new WcSettings( page );
|
||||
await settingsScreen.navigate();
|
||||
verifyValueOfInputField( '#woocommerce_currency', 'USD' );
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
const testSelectiveBundleWCPay = () => {
|
||||
describe( 'A japanese store can complete the selective bundle install but does not include WCPay.', () => {
|
||||
const profileWizard = new OnboardingWizard( page );
|
||||
const login = new Login( page );
|
||||
|
||||
beforeAll( async () => {
|
||||
await login.login();
|
||||
await resetWooCommerceState();
|
||||
} );
|
||||
afterAll( async () => {
|
||||
await login.logout();
|
||||
} );
|
||||
|
||||
it( 'can start the profile wizard', async () => {
|
||||
await profileWizard.navigate();
|
||||
} );
|
||||
|
||||
it( 'can complete the store details section', async () => {
|
||||
await profileWizard.storeDetails.completeStoreDetailsSection( {
|
||||
countryRegionSubstring: 'japan',
|
||||
countryRegionSelector: 'JP\\:JP01',
|
||||
countryRegion: 'Japan — Hokkaido',
|
||||
} );
|
||||
|
||||
// Wait for "Continue" button to become active
|
||||
await profileWizard.continue();
|
||||
|
||||
// Wait for usage tracking pop-up window to appear
|
||||
await profileWizard.optionallySelectUsageTracking();
|
||||
} );
|
||||
|
||||
// JP:JP01
|
||||
it( 'can choose the "Other" industry', async () => {
|
||||
// Query for the industries checkboxes
|
||||
await profileWizard.industry.isDisplayed();
|
||||
await profileWizard.industry.selectIndustry( 'Other' );
|
||||
await profileWizard.continue();
|
||||
} );
|
||||
|
||||
it( 'can complete the product types section', async () => {
|
||||
await profileWizard.productTypes.isDisplayed( 7 );
|
||||
|
||||
// Select Physical and Downloadable products
|
||||
await profileWizard.productTypes.selectProduct(
|
||||
'Physical products'
|
||||
);
|
||||
await profileWizard.productTypes.selectProduct( 'Downloads' );
|
||||
|
||||
await profileWizard.continue();
|
||||
await page.waitForNavigation( { waitUntil: 'networkidle0' } );
|
||||
} );
|
||||
|
||||
it( 'can complete the business details tab', async () => {
|
||||
await profileWizard.business.isDisplayed();
|
||||
|
||||
await profileWizard.business.selectProductNumber(
|
||||
config.get( 'onboardingwizard.numberofproducts' )
|
||||
);
|
||||
await profileWizard.business.selectCurrentlySelling(
|
||||
config.get( 'onboardingwizard.sellingelsewhere' )
|
||||
);
|
||||
|
||||
await profileWizard.continue();
|
||||
} );
|
||||
|
||||
it( 'can choose not to install any extensions', async () => {
|
||||
await profileWizard.business.freeFeaturesIsDisplayed();
|
||||
// Add WC Pay check
|
||||
await profileWizard.business.expandRecommendedBusinessFeatures();
|
||||
|
||||
expect( page ).not.toMatchElement( 'a', {
|
||||
text: 'WooCommerce Payments',
|
||||
} );
|
||||
|
||||
await profileWizard.business.uncheckAllRecommendedBusinessFeatures();
|
||||
await profileWizard.continue();
|
||||
} );
|
||||
|
||||
it( 'can finish the rest of the wizard successfully', async () => {
|
||||
await profileWizard.themes.isDisplayed();
|
||||
|
||||
// This navigates to the home screen
|
||||
await profileWizard.themes.continueWithActiveTheme();
|
||||
} );
|
||||
|
||||
it( 'should display the choose payments task, and not the woocommerce payments task', async () => {
|
||||
const homescreen = new WcHomescreen( page );
|
||||
await homescreen.isDisplayed();
|
||||
await homescreen.possiblyDismissWelcomeModal();
|
||||
const tasks = await homescreen.getTaskList();
|
||||
expect( tasks ).toContain( TaskTitles.addPayments );
|
||||
expect( tasks ).not.toContain( TaskTitles.wooPayments );
|
||||
} );
|
||||
|
||||
it( 'can select the right currency on settings page related to the onboarding country', async () => {
|
||||
const settingsScreen = new WcSettings( page );
|
||||
await settingsScreen.navigate();
|
||||
verifyValueOfInputField( '#woocommerce_currency', 'JPY' );
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
const testDifferentStoreCurrenciesWCPay = () => {
|
||||
const testCountryCurrencyPairs = [
|
||||
{
|
||||
countryRegionSubstring: 'australia',
|
||||
countryRegionSelector: 'AU\\:QLD',
|
||||
countryRegion: 'Australia — Queensland',
|
||||
expectedCurrency: 'AUD',
|
||||
isWCPaySupported: true,
|
||||
},
|
||||
{
|
||||
countryRegionSubstring: 'canada',
|
||||
countryRegionSelector: 'CA\\:QC',
|
||||
countryRegion: 'Canada — Quebec',
|
||||
expectedCurrency: 'CAD',
|
||||
isWCPaySupported: true,
|
||||
},
|
||||
{
|
||||
countryRegionSubstring: 'china',
|
||||
countryRegionSelector: 'CN\\:CN2',
|
||||
countryRegion: 'China — Beijing',
|
||||
expectedCurrency: 'CNY',
|
||||
isWCPaySupported: false,
|
||||
},
|
||||
{
|
||||
countryRegionSubstring: 'spain',
|
||||
countryRegionSelector: 'ES\\:CO',
|
||||
countryRegion: 'Spain — Córdoba',
|
||||
expectedCurrency: 'EUR',
|
||||
isWCPaySupported: true,
|
||||
},
|
||||
{
|
||||
countryRegionSubstring: 'india',
|
||||
countryRegionSelector: 'IN\\:DL',
|
||||
countryRegion: 'India — Delhi',
|
||||
expectedCurrency: 'INR',
|
||||
isWCPaySupported: false,
|
||||
},
|
||||
{
|
||||
countryRegionSubstring: 'kingd',
|
||||
countryRegionSelector: 'GB',
|
||||
countryRegion: 'United Kingdom (UK)',
|
||||
expectedCurrency: 'GBP',
|
||||
isWCPaySupported: true,
|
||||
},
|
||||
];
|
||||
|
||||
testCountryCurrencyPairs.forEach( ( spec ) => {
|
||||
describe( 'A store can onboard with any country and have the correct currency selected after onboarding.', () => {
|
||||
const profileWizard = new OnboardingWizard( page );
|
||||
const login = new Login( page );
|
||||
|
||||
beforeAll( async () => {
|
||||
await login.login();
|
||||
await resetWooCommerceState();
|
||||
} );
|
||||
afterAll( async () => {
|
||||
await login.logout();
|
||||
} );
|
||||
|
||||
it( `can complete the profile wizard with selecting ${ spec.countryRegion } as the country`, async () => {
|
||||
await profileWizard.navigate();
|
||||
await profileWizard.storeDetails.completeStoreDetailsSection( {
|
||||
countryRegionSubstring: spec.countryRegionSubstring,
|
||||
countryRegionSelector: spec.countryRegionSelector,
|
||||
countryRegion: spec.countryRegion,
|
||||
} );
|
||||
|
||||
// Wait for "Continue" button to become active
|
||||
await profileWizard.continue();
|
||||
|
||||
// Wait for usage tracking pop-up window to appear
|
||||
await profileWizard.optionallySelectUsageTracking();
|
||||
// Query for the industries checkboxes
|
||||
await profileWizard.industry.isDisplayed();
|
||||
await profileWizard.industry.selectIndustry( 'Other' );
|
||||
await profileWizard.continue();
|
||||
await profileWizard.productTypes.isDisplayed( 7 );
|
||||
await profileWizard.productTypes.selectProduct(
|
||||
'Physical products'
|
||||
);
|
||||
await profileWizard.productTypes.selectProduct( 'Downloads' );
|
||||
|
||||
await profileWizard.continue();
|
||||
await page.waitForNavigation( {
|
||||
waitUntil: 'networkidle0',
|
||||
} );
|
||||
await profileWizard.business.isDisplayed();
|
||||
|
||||
await profileWizard.business.selectProductNumber(
|
||||
config.get( 'onboardingwizard.numberofproducts' )
|
||||
);
|
||||
await profileWizard.business.selectCurrentlySelling(
|
||||
config.get( 'onboardingwizard.sellingelsewhere' )
|
||||
);
|
||||
|
||||
await profileWizard.continue();
|
||||
await profileWizard.business.freeFeaturesIsDisplayed();
|
||||
// Add WC Pay check
|
||||
await profileWizard.business.expandRecommendedBusinessFeatures();
|
||||
|
||||
if ( spec.isWCPaySupported ) {
|
||||
expect( page ).toMatchElement( 'a', {
|
||||
text: 'WooCommerce Payments',
|
||||
} );
|
||||
} else {
|
||||
expect( page ).not.toMatchElement( 'a', {
|
||||
text: 'WooCommerce Payments',
|
||||
} );
|
||||
}
|
||||
|
||||
await profileWizard.business.uncheckAllRecommendedBusinessFeatures();
|
||||
await profileWizard.continue();
|
||||
await profileWizard.themes.isDisplayed();
|
||||
|
||||
// This navigates to the home screen
|
||||
await profileWizard.themes.continueWithActiveTheme();
|
||||
} );
|
||||
|
||||
it( `can select ${ spec.expectedCurrency } as the currency for ${ spec.countryRegion }`, async () => {
|
||||
const settingsScreen = new WcSettings( page );
|
||||
await settingsScreen.navigate();
|
||||
verifyValueOfInputField(
|
||||
'#woocommerce_currency',
|
||||
spec.expectedCurrency
|
||||
);
|
||||
} );
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
const testSubscriptionsInclusion = () => {
|
||||
describe( 'A non-US store will not see the Subscriptions inclusion', () => {
|
||||
const profileWizard = new OnboardingWizard( page );
|
||||
const login = new Login( page );
|
||||
|
||||
beforeAll( async () => {
|
||||
await login.login();
|
||||
await resetWooCommerceState();
|
||||
} );
|
||||
|
||||
it( 'can complete the store details section', async () => {
|
||||
await profileWizard.navigate();
|
||||
await profileWizard.storeDetails.completeStoreDetailsSection( {
|
||||
countryRegionSubstring: 'fran',
|
||||
countryRegionSelector: 'FR',
|
||||
countryRegion: 'France',
|
||||
} );
|
||||
|
||||
// Wait for "Continue" button to become active
|
||||
await profileWizard.continue();
|
||||
|
||||
// Wait for usage tracking pop-up window to appear
|
||||
await profileWizard.optionallySelectUsageTracking();
|
||||
} );
|
||||
|
||||
it( 'can complete the product types section, Subscriptions copy is not visible', async () => {
|
||||
// Query for the industries checkboxes
|
||||
await profileWizard.industry.isDisplayed();
|
||||
await profileWizard.industry.selectIndustry( 'Health and beauty' );
|
||||
await profileWizard.continue();
|
||||
await profileWizard.productTypes.isDisplayed( 7 );
|
||||
await profileWizard.productTypes.selectProduct( 'Subscriptions' );
|
||||
await expect( page ).not.toMatchElement( 'p', {
|
||||
text:
|
||||
'The following extensions will be added to your site for free: WooCommerce Payments. An account is required to use this feature.',
|
||||
} );
|
||||
|
||||
await profileWizard.continue();
|
||||
await page.waitForNavigation( { waitUntil: 'networkidle0' } );
|
||||
} );
|
||||
|
||||
it( 'can complete the business details tab', async () => {
|
||||
await profileWizard.business.isDisplayed();
|
||||
|
||||
await profileWizard.business.selectProductNumber(
|
||||
config.get( 'onboardingwizard.numberofproducts' )
|
||||
);
|
||||
await profileWizard.business.selectCurrentlySelling(
|
||||
config.get( 'onboardingwizard.sellingelsewhere' )
|
||||
);
|
||||
|
||||
await profileWizard.continue();
|
||||
} );
|
||||
|
||||
it( 'should display the WooCommerce Payments extension after it has been installed', async () => {
|
||||
await profileWizard.business.freeFeaturesIsDisplayed();
|
||||
await profileWizard.business.expandRecommendedBusinessFeatures();
|
||||
|
||||
expect( page ).toMatchElement( 'a', {
|
||||
text: 'WooCommerce Payments',
|
||||
} );
|
||||
} );
|
||||
|
||||
it( 'should display the task "Add Subscriptions to my store"', async () => {
|
||||
await profileWizard.navigate();
|
||||
await profileWizard.goToOBWStep( 'Store Details' );
|
||||
await profileWizard.skipStoreSetup();
|
||||
const homescreen = new WcHomescreen( page );
|
||||
await homescreen.isDisplayed();
|
||||
await homescreen.possiblyDismissWelcomeModal();
|
||||
const tasks = await homescreen.getTaskList();
|
||||
expect( tasks ).toContain( 'Add Subscriptions to my store' );
|
||||
} );
|
||||
|
||||
it( 'can select the Subscription option in the "Start with a template" modal', async () => {
|
||||
const productsSetup = new ProductsSetup( page );
|
||||
await productsSetup.navigate();
|
||||
await productsSetup.isDisplayed();
|
||||
await productsSetup.clickStartWithTemplate();
|
||||
await productsSetup.isStartWithATemplateDisplayed( 3 );
|
||||
} );
|
||||
} );
|
||||
describe( 'A US store will see the Subscriptions inclusion', () => {
|
||||
const profileWizard = new OnboardingWizard( page );
|
||||
const login = new Login( page );
|
||||
|
||||
beforeAll( async () => {
|
||||
await resetWooCommerceState();
|
||||
} );
|
||||
|
||||
it( 'can complete the store details section', async () => {
|
||||
await profileWizard.navigate();
|
||||
await profileWizard.storeDetails.completeStoreDetailsSection( {
|
||||
countryRegionSubstring: 'cali',
|
||||
countryRegionSelector: 'US\\:CA',
|
||||
countryRegion: 'United States (US) — California',
|
||||
} );
|
||||
|
||||
// Wait for "Continue" button to become active
|
||||
await profileWizard.continue();
|
||||
|
||||
// Wait for usage tracking pop-up window to appear
|
||||
await profileWizard.optionallySelectUsageTracking();
|
||||
} );
|
||||
|
||||
it( 'can complete the product types section, the Subscriptions copy now is visible', async () => {
|
||||
// Query for the industries checkboxes
|
||||
await profileWizard.industry.isDisplayed();
|
||||
await profileWizard.industry.selectIndustry( 'Health and beauty' );
|
||||
await profileWizard.continue();
|
||||
await profileWizard.productTypes.isDisplayed( 7 );
|
||||
await profileWizard.productTypes.selectProduct( 'Subscriptions' );
|
||||
await expect( page ).toMatchElement( 'p', {
|
||||
text:
|
||||
'The following extensions will be added to your site for free: WooCommerce Payments. An account is required to use this feature.',
|
||||
} );
|
||||
|
||||
await profileWizard.continue();
|
||||
await page.waitForNavigation( { waitUntil: 'networkidle0' } );
|
||||
} );
|
||||
|
||||
it( 'can complete the business details tab', async () => {
|
||||
await profileWizard.business.isDisplayed();
|
||||
|
||||
await profileWizard.business.selectProductNumber(
|
||||
config.get( 'onboardingwizard.numberofproducts' )
|
||||
);
|
||||
await profileWizard.business.selectCurrentlySelling(
|
||||
config.get( 'onboardingwizard.sellingelsewhere' )
|
||||
);
|
||||
|
||||
await profileWizard.continue();
|
||||
} );
|
||||
|
||||
it( 'cannot see the WooCommerce Payments extension after it has been installed', async () => {
|
||||
await profileWizard.business.freeFeaturesIsDisplayed();
|
||||
await profileWizard.business.expandRecommendedBusinessFeatures();
|
||||
|
||||
expect( page ).not.toMatchElement( 'a', {
|
||||
text: 'WooCommerce Payments',
|
||||
} );
|
||||
} );
|
||||
|
||||
it( 'should not display the task "Add Subscriptions to my store"', async () => {
|
||||
await profileWizard.navigate();
|
||||
await profileWizard.goToOBWStep( 'Store Details' );
|
||||
await profileWizard.skipStoreSetup();
|
||||
const homescreen = new WcHomescreen( page );
|
||||
await homescreen.isDisplayed();
|
||||
await homescreen.possiblyDismissWelcomeModal();
|
||||
const tasks = await homescreen.getTaskList();
|
||||
expect( tasks ).not.toContain( 'Add Subscriptions to my store' );
|
||||
} );
|
||||
|
||||
it( 'can select the Subscription option in the "Start with a template" modal', async () => {
|
||||
const productsSetup = new ProductsSetup( page );
|
||||
await productsSetup.navigate();
|
||||
await productsSetup.isDisplayed();
|
||||
await productsSetup.clickStartWithTemplate();
|
||||
await productsSetup.isStartWithATemplateDisplayed( 4 );
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
const testBusinessDetailsForm = () => {
|
||||
describe( 'A store that is selling elsewhere will see the "Number of employees” dropdown menu', () => {
|
||||
const profileWizard = new OnboardingWizard( page );
|
||||
const login = new Login( page );
|
||||
|
||||
beforeAll( async () => {
|
||||
await resetWooCommerceState();
|
||||
} );
|
||||
|
||||
afterAll( async () => {
|
||||
await login.logout();
|
||||
} );
|
||||
|
||||
it( 'can complete the store details and product types sections', async () => {
|
||||
await profileWizard.navigate();
|
||||
await profileWizard.storeDetails.isDisplayed();
|
||||
await profileWizard.storeDetails.completeStoreDetailsSection();
|
||||
|
||||
// Wait for "Continue" button to become active
|
||||
await profileWizard.continue();
|
||||
|
||||
// Wait for usage tracking pop-up window to appear
|
||||
await profileWizard.optionallySelectUsageTracking();
|
||||
|
||||
// Query for the industries checkboxes
|
||||
await profileWizard.industry.isDisplayed();
|
||||
await profileWizard.industry.selectIndustry(
|
||||
'Fashion, apparel, and accessories'
|
||||
);
|
||||
await profileWizard.continue();
|
||||
await profileWizard.productTypes.isDisplayed( 7 );
|
||||
// Select Physical
|
||||
await profileWizard.productTypes.selectProduct(
|
||||
'Physical products'
|
||||
);
|
||||
await profileWizard.productTypes.selectProduct( 'Downloads' );
|
||||
|
||||
await profileWizard.continue();
|
||||
await page.waitForNavigation( {
|
||||
waitUntil: 'networkidle0',
|
||||
} );
|
||||
} );
|
||||
|
||||
it( 'can complete the business details tab', async () => {
|
||||
await profileWizard.business.isDisplayed();
|
||||
|
||||
await profileWizard.business.selectProductNumber(
|
||||
config.get( 'onboardingwizard.numberofproducts' )
|
||||
);
|
||||
await profileWizard.business.selectCurrentlySelling(
|
||||
config.get( 'onboardingwizard.sellingOnAnotherPlatform' )
|
||||
);
|
||||
expect( page ).toMatchElement( 'label', {
|
||||
text: 'How many employees do you have?',
|
||||
} );
|
||||
await profileWizard.business.selectEmployeesNumber(
|
||||
config.get( 'onboardingwizard.number_employees' )
|
||||
);
|
||||
await profileWizard.business.selectRevenue(
|
||||
config.get( 'onboardingwizard.revenue' )
|
||||
);
|
||||
await profileWizard.business.selectOtherPlatformName(
|
||||
config.get( 'onboardingwizard.other_platform_name' )
|
||||
);
|
||||
|
||||
await profileWizard.continue();
|
||||
await profileWizard.business.expandRecommendedBusinessFeatures();
|
||||
await profileWizard.business.uncheckAllRecommendedBusinessFeatures();
|
||||
await profileWizard.continue();
|
||||
await profileWizard.themes.isDisplayed();
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
const testAdminHomescreen = () => {
|
||||
describe( 'Homescreen', () => {
|
||||
const profileWizard = new OnboardingWizard( page );
|
||||
const homeScreen = new WcHomescreen( page );
|
||||
const login = new Login( page );
|
||||
|
||||
beforeAll( async () => {
|
||||
await login.login();
|
||||
await resetWooCommerceState();
|
||||
await profileWizard.navigate();
|
||||
await profileWizard.skipStoreSetup();
|
||||
} );
|
||||
|
||||
afterAll( async () => {
|
||||
await login.logout();
|
||||
} );
|
||||
|
||||
it( 'should not show welcome modal', async () => {
|
||||
await homeScreen.isDisplayed();
|
||||
await expect( homeScreen.isWelcomeModalVisible() ).resolves.toBe(
|
||||
false
|
||||
);
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
testAdminOnboardingWizard,
|
||||
testSelectiveBundleWCPay,
|
||||
testDifferentStoreCurrenciesWCPay,
|
||||
testSubscriptionsInclusion,
|
||||
testBusinessDetailsForm,
|
||||
testAdminHomescreen,
|
||||
};
|
|
@ -0,0 +1,98 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { AnalyticsOverview } from '../../pages/AnalyticsOverview';
|
||||
import { Login } from '../../pages/Login';
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
const { afterAll, beforeAll, describe, it } = require( '@jest/globals' );
|
||||
|
||||
const testAdminAnalyticsOverview = () => {
|
||||
describe( 'Analytics pages', () => {
|
||||
const analyticsPage = new AnalyticsOverview( page );
|
||||
const login = new Login( page );
|
||||
const sectionTitles = [ 'Performance', 'Charts', 'Leaderboards' ];
|
||||
const titlesString = sectionTitles.join( ', ' );
|
||||
|
||||
beforeAll( async () => {
|
||||
await login.login();
|
||||
await analyticsPage.navigate();
|
||||
await analyticsPage.isDisplayed();
|
||||
// Restore original order to sections
|
||||
for ( let t = 0; t < sectionTitles.length; t++ ) {
|
||||
const visibleSections = await analyticsPage.getSectionTitles();
|
||||
if ( visibleSections.indexOf( sectionTitles[ t ] ) < 0 ) {
|
||||
await analyticsPage.addSection( sectionTitles[ t ] );
|
||||
}
|
||||
}
|
||||
} );
|
||||
afterAll( async () => {
|
||||
await login.logout();
|
||||
} );
|
||||
|
||||
it( `a user should see ${ sectionTitles.length } sections by default - ${ titlesString }`, async () => {
|
||||
const sections = await analyticsPage.getSectionTitles();
|
||||
for ( let t = 0; t < sectionTitles.length; t++ ) {
|
||||
expect( sections ).toContain( sectionTitles[ t ] );
|
||||
}
|
||||
} );
|
||||
|
||||
it( 'should allow a user to remove a section', async () => {
|
||||
await analyticsPage.removeSection( sectionTitles[ 0 ] );
|
||||
const sections = await analyticsPage.getSectionTitles();
|
||||
expect( sections ).not.toContain( sectionTitles[ 0 ] );
|
||||
} );
|
||||
|
||||
it( 'should allow a user to add a section back in', async () => {
|
||||
let sections = await analyticsPage.getSectionTitles();
|
||||
expect( sections ).not.toContain( sectionTitles[ 0 ] );
|
||||
await analyticsPage.addSection( sectionTitles[ 0 ] );
|
||||
|
||||
sections = await analyticsPage.getSectionTitles();
|
||||
expect( sections ).toContain( sectionTitles[ 0 ] );
|
||||
} );
|
||||
|
||||
describe( 'moving sections', () => {
|
||||
it( 'should not display move up for the top, or move down for the bottom section', async () => {
|
||||
const sections = await analyticsPage.getSections();
|
||||
for ( const section of sections ) {
|
||||
const index = sections.indexOf( section );
|
||||
const menuItems = (
|
||||
await analyticsPage.getEllipsisMenuItems(
|
||||
section.title
|
||||
)
|
||||
).map( ( item ) => item.title );
|
||||
if ( index === 0 ) {
|
||||
expect( menuItems ).toContain( 'Move down' );
|
||||
expect( menuItems ).not.toContain( 'Move up' );
|
||||
} else if ( index === sections.length - 1 ) {
|
||||
expect( menuItems ).not.toContain( 'Move down' );
|
||||
expect( menuItems ).toContain( 'Move up' );
|
||||
} else {
|
||||
expect( menuItems ).toContain( 'Move down' );
|
||||
expect( menuItems ).toContain( 'Move up' );
|
||||
}
|
||||
await analyticsPage.closeSectionEllipsis( section.title );
|
||||
}
|
||||
} );
|
||||
|
||||
it( 'should allow a user to move a section down', async () => {
|
||||
const sections = await analyticsPage.getSectionTitles();
|
||||
await analyticsPage.moveSectionDown( sections[ 0 ] );
|
||||
const newSections = await analyticsPage.getSectionTitles();
|
||||
expect( sections[ 0 ] ).toEqual( newSections[ 1 ] );
|
||||
expect( sections[ 1 ] ).toEqual( newSections[ 0 ] );
|
||||
} );
|
||||
|
||||
it( 'should allow a user to move a section up', async () => {
|
||||
const sections = await analyticsPage.getSectionTitles();
|
||||
await analyticsPage.moveSectionUp( sections[ 1 ] );
|
||||
const newSections = await analyticsPage.getSectionTitles();
|
||||
expect( sections[ 0 ] ).toEqual( newSections[ 1 ] );
|
||||
expect( sections[ 1 ] ).toEqual( newSections[ 0 ] );
|
||||
} );
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
module.exports = { testAdminAnalyticsOverview };
|
|
@ -0,0 +1,86 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { Analytics } from '../../pages/Analytics';
|
||||
import { Customers } from '../../pages/Customers';
|
||||
import { Login } from '../../pages/Login';
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
const { afterAll, beforeAll, describe, it } = require( '@jest/globals' );
|
||||
|
||||
const testAdminAnalyticsPages = () => {
|
||||
describe( 'Analytics pages', () => {
|
||||
const analyticsPage = new Analytics( page );
|
||||
const customersPage = new Customers( page );
|
||||
const login = new Login( page );
|
||||
|
||||
beforeAll( async () => {
|
||||
await login.login();
|
||||
} );
|
||||
afterAll( async () => {
|
||||
await login.logout();
|
||||
} );
|
||||
|
||||
it( 'A user can view the analytics overview without it crashing', async () => {
|
||||
await analyticsPage.navigate();
|
||||
await analyticsPage.isDisplayed();
|
||||
} );
|
||||
|
||||
it( 'A user can view the analytics for products without it crashing', async () => {
|
||||
await analyticsPage.navigateToSection( 'products' );
|
||||
await analyticsPage.isDisplayed();
|
||||
} );
|
||||
|
||||
it( 'A user can view the analytics for revenue without it crashing', async () => {
|
||||
await analyticsPage.navigateToSection( 'revenue' );
|
||||
await analyticsPage.isDisplayed();
|
||||
} );
|
||||
|
||||
it( 'A user can view the analytics for orders without it crashing', async () => {
|
||||
await analyticsPage.navigateToSection( 'orders' );
|
||||
await analyticsPage.isDisplayed();
|
||||
} );
|
||||
|
||||
it( 'A user can view the analytics for variations without it crashing', async () => {
|
||||
await analyticsPage.navigateToSection( 'variations' );
|
||||
await analyticsPage.isDisplayed();
|
||||
} );
|
||||
|
||||
it( 'A user can view the analytics for categories without it crashing', async () => {
|
||||
await analyticsPage.navigateToSection( 'categories' );
|
||||
await analyticsPage.isDisplayed();
|
||||
} );
|
||||
|
||||
it( 'A user can view the analytics for coupons without it crashing', async () => {
|
||||
await analyticsPage.navigateToSection( 'coupons' );
|
||||
await analyticsPage.isDisplayed();
|
||||
} );
|
||||
|
||||
it( 'A user can view the analytics for taxes without it crashing', async () => {
|
||||
await analyticsPage.navigateToSection( 'taxes' );
|
||||
await analyticsPage.isDisplayed();
|
||||
} );
|
||||
|
||||
it( 'A user can view the analytics for downloads without it crashing', async () => {
|
||||
await analyticsPage.navigateToSection( 'downloads' );
|
||||
await analyticsPage.isDisplayed();
|
||||
} );
|
||||
|
||||
it( 'A user can view the analytics for stock without it crashing', async () => {
|
||||
await analyticsPage.navigateToSection( 'stock' );
|
||||
await analyticsPage.isDisplayed();
|
||||
} );
|
||||
|
||||
it( 'A user can view the analytics for settings without it crashing', async () => {
|
||||
await analyticsPage.navigateToSection( 'settings' );
|
||||
await analyticsPage.isDisplayed();
|
||||
} );
|
||||
|
||||
it( 'A user can view the customers page without it crashing', async () => {
|
||||
await customersPage.navigate();
|
||||
await customersPage.isDisplayed();
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
module.exports = { testAdminAnalyticsPages };
|
|
@ -0,0 +1,135 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { createSimpleProduct, withRestApi } from '@woocommerce/e2e-utils';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { Login } from '../../pages/Login';
|
||||
import { OnboardingWizard } from '../../pages/OnboardingWizard';
|
||||
import { WcHomescreen } from '../../pages/WcHomescreen';
|
||||
import {
|
||||
createOrder,
|
||||
removeAllOrders,
|
||||
unhideTaskList,
|
||||
runActionScheduler,
|
||||
updateOption,
|
||||
resetWooCommerceState,
|
||||
} from '../../fixtures';
|
||||
import { OrdersActivityPanel } from '../../elements/OrdersActivityPanel';
|
||||
import { addReviewToProduct, waitForElementByText } from '../../utils/actions';
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
const { afterAll, beforeAll, describe, it } = require( '@jest/globals' );
|
||||
/* eslint-enable @typescript-eslint/no-var-requires */
|
||||
|
||||
const simpleProductName = 'Simple order';
|
||||
const testAdminHomescreenActivityPanel = () => {
|
||||
describe( 'Homescreen activity panel', () => {
|
||||
const profileWizard = new OnboardingWizard( page );
|
||||
const homeScreen = new WcHomescreen( page );
|
||||
const ordersPanel = new OrdersActivityPanel( page );
|
||||
const login = new Login( page );
|
||||
|
||||
beforeAll( async () => {
|
||||
await login.login();
|
||||
await resetWooCommerceState();
|
||||
await profileWizard.navigate();
|
||||
await profileWizard.skipStoreSetup();
|
||||
|
||||
await homeScreen.isDisplayed();
|
||||
await homeScreen.possiblyDismissWelcomeModal();
|
||||
} );
|
||||
|
||||
afterAll( async () => {
|
||||
await withRestApi.deleteAllProducts();
|
||||
await removeAllOrders();
|
||||
await unhideTaskList( 'setup' );
|
||||
await runActionScheduler();
|
||||
await updateOption( 'woocommerce_task_list_hidden', 'no' );
|
||||
await login.logout();
|
||||
} );
|
||||
|
||||
it( 'should not show activity panel while task list is displayed', async () => {
|
||||
await expect( homeScreen.isTaskListDisplayed() ).resolves.toBe(
|
||||
true
|
||||
);
|
||||
await expect( homeScreen.isActivityPanelShown() ).resolves.toBe(
|
||||
false
|
||||
);
|
||||
} );
|
||||
|
||||
it( 'should not show panels when there are no orders or products yet with task list hidden', async () => {
|
||||
await homeScreen.hideTaskList();
|
||||
await expect( homeScreen.isTaskListDisplayed() ).resolves.toBe(
|
||||
false
|
||||
);
|
||||
await expect( homeScreen.isActivityPanelShown() ).resolves.toBe(
|
||||
false
|
||||
);
|
||||
} );
|
||||
|
||||
it( 'should show Reviews panel when we have at-least one product', async () => {
|
||||
const productId = await createSimpleProduct(
|
||||
simpleProductName,
|
||||
'9.99'
|
||||
);
|
||||
await addReviewToProduct( productId, simpleProductName );
|
||||
await homeScreen.navigate();
|
||||
await homeScreen.isDisplayed();
|
||||
const activityPanels = await homeScreen.getActivityPanels();
|
||||
expect( activityPanels ).toHaveLength( 1 );
|
||||
expect( activityPanels ).toEqual(
|
||||
expect.arrayContaining( [
|
||||
expect.objectContaining( { title: 'Reviews' } ),
|
||||
] )
|
||||
);
|
||||
} );
|
||||
|
||||
it( 'should show Orders and Stock panels when at-least one order is added', async () => {
|
||||
await createOrder();
|
||||
await page.reload( {
|
||||
waitUntil: [ 'networkidle0', 'domcontentloaded' ],
|
||||
} );
|
||||
const activityPanels = await homeScreen.getActivityPanels();
|
||||
expect( activityPanels ).toHaveLength( 3 );
|
||||
expect( activityPanels ).toEqual(
|
||||
expect.arrayContaining( [
|
||||
expect.objectContaining( { title: 'Orders' } ),
|
||||
] )
|
||||
);
|
||||
expect( activityPanels ).toEqual(
|
||||
expect.arrayContaining( [
|
||||
expect.objectContaining( { title: 'Stock' } ),
|
||||
] )
|
||||
);
|
||||
} );
|
||||
|
||||
describe( 'Orders panel', () => {
|
||||
it( 'should show: "you have fullfilled all your orders" when expanding Orders panel if no actionable orders', async () => {
|
||||
await homeScreen.expandActivityPanel( 'Orders' );
|
||||
await waitForElementByText(
|
||||
'h4',
|
||||
'You’ve fulfilled all your orders'
|
||||
);
|
||||
await expect( page ).toMatchElement( 'h4', {
|
||||
text: 'You’ve fulfilled all your orders',
|
||||
} );
|
||||
} );
|
||||
|
||||
it( 'should show actionable Orders when expanding Orders panel', async () => {
|
||||
const order1 = await createOrder( 'processing' );
|
||||
const order2 = await createOrder( 'on-hold' );
|
||||
await homeScreen.navigate();
|
||||
await homeScreen.expandActivityPanel( 'Orders' );
|
||||
const orders = await ordersPanel.getDisplayedOrders();
|
||||
expect( orders ).toHaveLength( 2 );
|
||||
expect( orders ).toContain( `Order #${ order1.id }` );
|
||||
expect( orders ).toContain( `Order #${ order2.id }` );
|
||||
} );
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
module.exports = { testAdminHomescreenActivityPanel };
|
|
@ -0,0 +1,77 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { takeScreenshotFor } from '@woocommerce/e2e-environment';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { Login } from '../../pages/Login';
|
||||
import { OnboardingWizard } from '../../pages/OnboardingWizard';
|
||||
import { WcHomescreen } from '../../pages/WcHomescreen';
|
||||
import { TaskTitles } from '../../constants/taskTitles';
|
||||
import { HelpMenu } from '../../elements/HelpMenu';
|
||||
import { WcSettings } from '../../pages/WcSettings';
|
||||
import { resetWooCommerceState, unhideTaskList } from '../../fixtures';
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
const { afterAll, beforeAll, describe, it } = require( '@jest/globals' );
|
||||
/* eslint-enable @typescript-eslint/no-var-requires */
|
||||
|
||||
const testAdminHomescreenTasklist = () => {
|
||||
describe( 'Homescreen task list', () => {
|
||||
const profileWizard = new OnboardingWizard( page );
|
||||
const homeScreen = new WcHomescreen( page );
|
||||
const helpMenu = new HelpMenu( page );
|
||||
const settings = new WcSettings( page );
|
||||
const login = new Login( page );
|
||||
|
||||
beforeAll( async () => {
|
||||
await login.login();
|
||||
await resetWooCommerceState();
|
||||
|
||||
// This makes this test more isolated, by always navigating to the
|
||||
// profile wizard and skipping, this behaves the same as if the
|
||||
// profile wizard had not been run yet and the user is redirected
|
||||
// to it when trying to go to wc-admin.
|
||||
await profileWizard.navigate();
|
||||
await profileWizard.skipStoreSetup();
|
||||
|
||||
await homeScreen.isDisplayed();
|
||||
await homeScreen.possiblyDismissWelcomeModal();
|
||||
await takeScreenshotFor( 'WooCommerce Admin Home Screen' );
|
||||
} );
|
||||
|
||||
afterAll( async () => {
|
||||
await unhideTaskList( 'setup' );
|
||||
await login.logout();
|
||||
} );
|
||||
|
||||
it( 'should show 6 or more tasks on the home screen', async () => {
|
||||
const tasks = await homeScreen.getTaskList();
|
||||
expect( tasks.length ).toBeGreaterThanOrEqual( 6 );
|
||||
expect( tasks ).toContain( TaskTitles.storeDetails );
|
||||
expect( tasks ).toContain( TaskTitles.addProducts );
|
||||
expect( tasks ).toContain( TaskTitles.taxSetup );
|
||||
expect( tasks ).toContain( TaskTitles.personalizeStore );
|
||||
} );
|
||||
|
||||
it( 'should be able to hide the task list', async () => {
|
||||
await homeScreen.hideTaskList();
|
||||
expect( await homeScreen.isTaskListDisplayed() ).toBe( false );
|
||||
} );
|
||||
|
||||
it( 'should be able to show the task list again through the help menu', async () => {
|
||||
await settings.navigate();
|
||||
await helpMenu.openHelpMenu();
|
||||
await helpMenu.enableTaskList();
|
||||
// redirects to homescreen
|
||||
await homeScreen.isDisplayed();
|
||||
await expect( homeScreen.isTaskListDisplayed() ).resolves.toBe(
|
||||
true
|
||||
);
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
module.exports = { testAdminHomescreenTasklist };
|
|
@ -0,0 +1,9 @@
|
|||
export * from './activate-and-setup/basic-setup';
|
||||
export * from './activate-and-setup/complete-onboarding-wizard';
|
||||
export * from './analytics/analytics';
|
||||
export * from './analytics/analytics-overview';
|
||||
export * from './marketing/coupons';
|
||||
export * from './tasks/payment';
|
||||
export * from './tasks/purchase';
|
||||
export * from './homescreen/task-list';
|
||||
export * from './homescreen/activity-panel';
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { Coupons } from '../../pages/Coupons';
|
||||
import { Login } from '../../pages/Login';
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
const { afterAll, beforeAll, describe, it } = require( '@jest/globals' );
|
||||
/* eslint-enable @typescript-eslint/no-var-requires */
|
||||
|
||||
const testAdminCouponsPage = () => {
|
||||
describe( 'Coupons page', () => {
|
||||
const couponsPage = new Coupons( page );
|
||||
const login = new Login( page );
|
||||
|
||||
beforeAll( async () => {
|
||||
await login.login();
|
||||
} );
|
||||
afterAll( async () => {
|
||||
await login.logout();
|
||||
} );
|
||||
|
||||
it( 'A user can view the coupons overview without it crashing', async () => {
|
||||
await couponsPage.navigate();
|
||||
await couponsPage.isDisplayed();
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
module.exports = { testAdminCouponsPage };
|
|
@ -0,0 +1,90 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { takeScreenshotFor } from '@woocommerce/e2e-environment';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { Login } from '../../pages/Login';
|
||||
import { OnboardingWizard } from '../../pages/OnboardingWizard';
|
||||
import { PaymentsSetup } from '../../pages/PaymentsSetup';
|
||||
import { WcHomescreen } from '../../pages/WcHomescreen';
|
||||
import { BankAccountTransferSetup } from '../../sections/payment-setup/BankAccountTransferSetup';
|
||||
import { waitForTimeout } from '../../utils/actions';
|
||||
import { WcSettings } from '../../pages/WcSettings';
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
const { afterAll, beforeAll, describe, it } = require( '@jest/globals' );
|
||||
/* eslint-enable @typescript-eslint/no-var-requires */
|
||||
|
||||
const testAdminPaymentSetupTask = () => {
|
||||
describe( 'Payment setup task', () => {
|
||||
const profileWizard = new OnboardingWizard( page );
|
||||
const homeScreen = new WcHomescreen( page );
|
||||
const paymentsSetup = new PaymentsSetup( page );
|
||||
const bankTransferSetup = new BankAccountTransferSetup( page );
|
||||
const login = new Login( page );
|
||||
const settings = new WcSettings( page );
|
||||
|
||||
beforeAll( async () => {
|
||||
await login.login();
|
||||
|
||||
// This makes this test more isolated, by always navigating to the
|
||||
// profile wizard and skipping, this behaves the same as if the
|
||||
// profile wizard had not been run yet and the user is redirected
|
||||
// to it when trying to go to wc-admin.
|
||||
await profileWizard.navigate();
|
||||
await profileWizard.skipStoreSetup();
|
||||
|
||||
await homeScreen.isDisplayed();
|
||||
await takeScreenshotFor( 'Payment setup task home screen' );
|
||||
await homeScreen.possiblyDismissWelcomeModal();
|
||||
} );
|
||||
|
||||
afterAll( async () => {
|
||||
await login.logout();
|
||||
} );
|
||||
|
||||
it( 'Can visit the payment setup task from the homescreen if the setup wizard has been skipped', async () => {
|
||||
await homeScreen.clickOnTaskList( 'Set up payments' );
|
||||
await paymentsSetup.possiblyCloseHelpModal();
|
||||
await paymentsSetup.isDisplayed();
|
||||
} );
|
||||
|
||||
it( 'Saving valid bank account transfer details enables the payment method', async () => {
|
||||
await paymentsSetup.showOtherPaymentMethods();
|
||||
await paymentsSetup.goToPaymentMethodSetup( 'bacs' );
|
||||
await bankTransferSetup.saveAccountDetails( {
|
||||
accountNumber: '1234',
|
||||
accountName: 'Savings',
|
||||
bankName: 'TestBank',
|
||||
sortCode: '12',
|
||||
iban: '12 3456 7890',
|
||||
swiftCode: 'ABBA',
|
||||
} );
|
||||
await waitForTimeout( 1500 );
|
||||
expect( await settings.paymentMethodIsEnabled( 'bacs' ) ).toBe(
|
||||
true
|
||||
);
|
||||
} );
|
||||
|
||||
it( 'Enabling cash on delivery enables the payment method', async () => {
|
||||
await settings.cleanPaymentMethods();
|
||||
await homeScreen.navigate();
|
||||
await homeScreen.isDisplayed();
|
||||
await waitForTimeout( 1000 );
|
||||
await homeScreen.clickOnTaskList( 'Set up payments' );
|
||||
await paymentsSetup.possiblyCloseHelpModal();
|
||||
await paymentsSetup.isDisplayed();
|
||||
await paymentsSetup.showOtherPaymentMethods();
|
||||
await paymentsSetup.enableCashOnDelivery();
|
||||
await waitForTimeout( 1500 );
|
||||
expect( await settings.paymentMethodIsEnabled( 'cod' ) ).toBe(
|
||||
true
|
||||
);
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
module.exports = { testAdminPaymentSetupTask };
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue