Merge branch 'trunk' into flexcss
This commit is contained in:
commit
9ee2307b65
|
@ -7,11 +7,11 @@ There are many ways to contribute to the project!
|
|||
- [Translating strings into your language](https://github.com/woocommerce/woocommerce/wiki/Translating-WooCommerce).
|
||||
- Answering questions on the various WooCommerce communities like the [WP.org support forums](https://wordpress.org/support/plugin/woocommerce/).
|
||||
- Testing open [issues](https://github.com/woocommerce/woocommerce/issues) or [pull requests](https://github.com/woocommerce/woocommerce/pulls) and sharing your findings in a comment.
|
||||
- Testing WooCommerce beta versions and release candidates. Those are announced in the [WooCommerce development blog](https://woocommerce.wordpress.com/).
|
||||
- Testing WooCommerce beta versions and release candidates. Those are announced in the [WooCommerce development blog](https://developer.woocommerce.com/blog/).
|
||||
- Submitting fixes, improvements, and enhancements.
|
||||
- To disclose a security issue to our team, [please submit a report via HackerOne](https://hackerone.com/automattic/).
|
||||
|
||||
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/) 🎉
|
||||
If you wish to contribute code, please read the information in the sections below. Then [fork](https://docs.github.com/en/get-started/quickstart/fork-a-repo) WooCommerce, commit your changes, and [submit a pull request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-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%22type%3A+good+first+issue%22).
|
||||
|
||||
|
@ -31,7 +31,7 @@ If you have questions about the process to contribute code or want to discuss de
|
|||
|
||||
## Coding Guidelines and Development 🛠
|
||||
|
||||
- Ensure you stick to the [WordPress Coding Standards](https://make.wordpress.org/core/handbook/best-practices/coding-standards/php/)
|
||||
- Ensure you stick to the [WordPress Coding Standards](https://make.wordpress.org/core/handbook/best-practices/coding-standards/php/).
|
||||
- Run our build process described in the document on [how to set up WooCommerce development environment](https://github.com/woocommerce/woocommerce/wiki/How-to-set-up-WooCommerce-development-environment), it will install our pre-commit hook, code sniffs, dependencies, and more.
|
||||
- Whenever possible please fix pre-existing code standards errors in the files that you change. It is ok to skip that for larger files or complex fixes.
|
||||
- Ensure you use LF line endings in your code editor. Use [EditorConfig](http://editorconfig.org/) if your editor supports it so that indentation, line endings and other settings are auto configured.
|
||||
|
@ -39,16 +39,13 @@ If you have questions about the process to contribute code or want to discuss de
|
|||
- Ensure that your code supports the minimum supported versions of PHP and WordPress; this is shown at the top of the `readme.txt` file.
|
||||
- Push the changes to your fork and submit a pull request on the trunk branch of the WooCommerce repository.
|
||||
- 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.
|
||||
- Please create a change file for your changes by running `pnpm --filter=<project> changelog add`. For example, a change file for the WooCommerce Core project would be added by running `pnpm --filter=woocommerce changelog add`.
|
||||
- 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) Gutenberg blocks, note that it's developed in an external package.
|
||||
|
||||
- [Blocks](https://github.com/woocommerce/woocommerce-gutenberg-products-block)
|
||||
If you are contributing code to our (Javascript-driven) Gutenberg blocks, please note that they are developed in their [own repository](https://github.com/woocommerce/woocommerce-gutenberg-products-block) and have their [own issue tracker](https://github.com/woocommerce/woocommerce-gutenberg-products-block/issues).
|
||||
|
||||
## Feature Requests 🚀
|
||||
|
||||
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.
|
||||
The best place to submit feature requests is over on our [dedicated feature request page](https://woocommerce.com/feature-requests/woocommerce/). You can easily search and vote for existing requests, or create new requests if necessary.
|
||||
|
||||
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%3Aissue+sort%3Areactions-%2B1-desc+label%3A%22needs%3A+votes%22+).
|
||||
Alternatively, if you wish to propose a straightforward technical enhancement that is unlikely to require much discussion, you can [open a new issue](https://github.com/woocommerce/woocommerce/issues/new?assignees=&labels=type%3A+enhancement%2Cstatus%3A+awaiting+triage&template=2-enhancement.yml&title=%5BEnhancement%5D%3A+) right here on GitHub and, for any that may require more discussion, consider syncing with us during office hours or publishing a thread on [GitHub Discussions](https://github.com/woocommerce/woocommerce/discussions).
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
### All Submissions:
|
||||
### Submission Review Guidelines:
|
||||
|
||||
- [ ] Have you followed the [WooCommerce Contributing guideline](https://github.com/woocommerce/woocommerce/blob/trunk/.github/CONTRIBUTING.md)?
|
||||
- [ ] Does your code follow the [WordPress' coding standards](https://make.wordpress.org/core/handbook/best-practices/coding-standards/)?
|
||||
- [ ] Have you checked to ensure there aren't other open [Pull Requests](https://github.com/woocommerce/woocommerce/pulls) for the same update/change?
|
||||
|
||||
<!-- Mark completed items with an [x] -->
|
||||
- I have followed the [WooCommerce Contributing Guidelines](https://github.com/woocommerce/woocommerce/blob/trunk/.github/CONTRIBUTING.md) and the [WordPress Coding Standards](https://make.wordpress.org/core/handbook/best-practices/coding-standards/).
|
||||
- I have checked to ensure there aren't other open [Pull Requests](https://github.com/woocommerce/woocommerce/pulls) for the same update/change.
|
||||
- I have reviewed my code for [security best practices](https://developer.wordpress.org/apis/security/).
|
||||
- Following the above guidelines will result in quick merges and clear and detailed feedback when appropriate.
|
||||
|
||||
<!-- You can erase any parts of this template not applicable to your Pull Request. -->
|
||||
|
||||
|
@ -18,25 +17,12 @@ Closes # .
|
|||
|
||||
### How to test the changes in this Pull Request:
|
||||
|
||||
<!-- Please include detailed instructions on how these changes can be tested, make sure to review and follow the guide for writing high-quality testing instructions below. -->
|
||||
<!-- Include detailed instructions on how these changes can be tested. Review and follow the guide for how to write high-quality testing instructions. -->
|
||||
|
||||
- [ ] Have you followed the [Writing high-quality testing instructions guide](https://github.com/woocommerce/woocommerce/wiki/Writing-high-quality-testing-instructions)?
|
||||
Using the [WooCommerce Testing Instructions Guide](https://github.com/woocommerce/woocommerce/wiki/Writing-high-quality-testing-instructions), include your detailed testing instructions:
|
||||
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
|
||||
<!-- End testing instructions -->
|
||||
|
||||
### Other information:
|
||||
|
||||
- [ ] 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 created a changelog file for each project being changed, ie `pnpm --filter=<project> changelog add`?
|
||||
- [ ] Have you included testing instructions?
|
||||
|
||||
<!-- Mark completed items with an [x] -->
|
||||
|
||||
### 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.
|
||||
<!-- End testing instructions -->
|
|
@ -29,7 +29,7 @@ runs:
|
|||
- name: Setup PNPM
|
||||
uses: pnpm/action-setup@c3b53f6a16e57305370b4ae5a540c2077a1d50dd
|
||||
with:
|
||||
version: '^7.22.0'
|
||||
version: '7.29.1'
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
name: Run API tests
|
||||
description: Runs the WooCommerce Core API tests and generates Allure report.
|
||||
permissions: {}
|
||||
|
||||
inputs:
|
||||
report-name:
|
||||
description: Name of Allure report to be generated.
|
||||
required: true
|
||||
tests:
|
||||
description: Specific tests to run, separated by single whitespace. See https://playwright.dev/docs/test-cli
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Run API tests.
|
||||
id: run-api-tests
|
||||
working-directory: plugins/woocommerce
|
||||
shell: bash
|
||||
run: |
|
||||
pnpm exec playwright test \
|
||||
--config=tests/api-core-tests/playwright.config.js \
|
||||
${{ inputs.tests }}
|
||||
|
||||
- name: Generate Test report.
|
||||
if: success() || ( failure() && steps.run-api-tests.conclusion == 'failure' )
|
||||
working-directory: plugins/woocommerce
|
||||
shell: bash
|
||||
run: pnpm exec allure generate --clean ${{ env.ALLURE_RESULTS_DIR }} --output ${{ env.ALLURE_REPORT_DIR }}
|
||||
|
||||
- name: Archive test report
|
||||
if: success() || ( failure() && steps.run-api-tests.conclusion == 'failure' )
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ inputs.report-name }}
|
||||
path: |
|
||||
${{ env.ALLURE_RESULTS_DIR }}
|
||||
${{ env.ALLURE_REPORT_DIR }}
|
||||
retention-days: 20
|
|
@ -0,0 +1,49 @@
|
|||
name: Run E2E tests
|
||||
description: Runs the WooCommerce Core E2E tests and generates Allure report.
|
||||
permissions: {}
|
||||
|
||||
inputs:
|
||||
report-name:
|
||||
description: Name of Allure report to be generated.
|
||||
required: true
|
||||
tests:
|
||||
description: Specific tests to run, separated by single whitespace. See https://playwright.dev/docs/test-cli
|
||||
playwright-config:
|
||||
description: The Playwright configuration file to use.
|
||||
default: playwright.config.js
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Download and install Chromium browser.
|
||||
working-directory: plugins/woocommerce
|
||||
shell: bash
|
||||
run: pnpm exec playwright install chromium
|
||||
|
||||
- name: Run E2E tests.
|
||||
id: run-e2e-tests
|
||||
env:
|
||||
FORCE_COLOR: 1
|
||||
USE_WP_ENV: 1
|
||||
working-directory: plugins/woocommerce
|
||||
shell: bash
|
||||
run: |
|
||||
pnpm exec playwright test \
|
||||
--config=tests/e2e-pw/${{ inputs.playwright-config }} \
|
||||
${{ inputs.tests }}
|
||||
|
||||
- name: Generate Test report.
|
||||
if: success() || ( failure() && steps.run-e2e-tests.conclusion == 'failure' )
|
||||
working-directory: plugins/woocommerce
|
||||
shell: bash
|
||||
run: pnpm exec allure generate --clean ${{ env.ALLURE_RESULTS_DIR }} --output ${{ env.ALLURE_REPORT_DIR }}
|
||||
|
||||
- name: Archive test report
|
||||
if: success() || ( failure() && steps.run-e2e-tests.conclusion == 'failure' )
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ inputs.report-name }}
|
||||
path: |
|
||||
${{ env.ALLURE_RESULTS_DIR }}
|
||||
${{ env.ALLURE_REPORT_DIR }}
|
||||
retention-days: 20
|
|
@ -0,0 +1,17 @@
|
|||
name: Run k6 performance tests
|
||||
description: Runs the WooCommerce Core k6 performance tests.
|
||||
permissions: {}
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Install k6
|
||||
shell: bash
|
||||
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 performance tests
|
||||
id: run-k6-tests
|
||||
shell: bash
|
||||
run: |
|
||||
./k6 run plugins/woocommerce/tests/performance/tests/gh-action-pr-requests.js
|
|
@ -0,0 +1,29 @@
|
|||
name: Setup local test environment
|
||||
description: Set up a wp-env testing environment
|
||||
permissions: {}
|
||||
|
||||
inputs:
|
||||
test-type:
|
||||
required: true
|
||||
type: choice
|
||||
options:
|
||||
- e2e
|
||||
- api
|
||||
- k6
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Load docker images and start containers for E2E or API tests
|
||||
if: ( inputs.test-type == 'e2e' ) || ( inputs.test-type == 'api' )
|
||||
working-directory: plugins/woocommerce
|
||||
shell: bash
|
||||
run: pnpm run env:test
|
||||
|
||||
- name: Load docker images and start containers for k6 performance tests
|
||||
if: inputs.test-type == 'k6'
|
||||
working-directory: plugins/woocommerce
|
||||
shell: bash
|
||||
run: |
|
||||
pnpm env:dev --filter=woocommerce
|
||||
pnpm env:performance-init --filter=woocommerce
|
|
@ -0,0 +1,41 @@
|
|||
name: Send Slack alert on PR merge test failure
|
||||
description: Send a Slack alert when automated tests failed on trunk after PR merge.
|
||||
permissions: {}
|
||||
|
||||
inputs:
|
||||
slack-bot-token:
|
||||
required: true
|
||||
channel-id:
|
||||
required: true
|
||||
test-type:
|
||||
required: true
|
||||
type: choice
|
||||
options:
|
||||
- E2E
|
||||
- API
|
||||
- k6
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Compose Slack message
|
||||
id: compose-slack-message
|
||||
uses: actions/github-script@v6
|
||||
env:
|
||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
PR_TITLE: ${{ github.event.pull_request.title }}
|
||||
SHA: ${{ github.event.pull_request.merge_commit_sha }}
|
||||
TEST_TYPE: ${{ inputs.test-type }}
|
||||
with:
|
||||
script: |
|
||||
const script = require('./.github/actions/tests/slack-alert-on-pr-merge/scripts/compose-slack-message.js')
|
||||
const slackMessage = script()
|
||||
core.setOutput('slack-message', slackMessage)
|
||||
|
||||
- name: Send Slack alert
|
||||
uses: slackapi/slack-github-action@v1.23.0
|
||||
env:
|
||||
SLACK_BOT_TOKEN: ${{ inputs.slack-bot-token }}
|
||||
with:
|
||||
channel-id: ${{ inputs.channel-id }}
|
||||
payload: ${{ steps.compose-slack-message.outputs.slack-message }}
|
114
.github/actions/tests/slack-alert-on-pr-merge/scripts/compose-slack-message.js
vendored
Normal file
114
.github/actions/tests/slack-alert-on-pr-merge/scripts/compose-slack-message.js
vendored
Normal file
|
@ -0,0 +1,114 @@
|
|||
module.exports = () => {
|
||||
const {
|
||||
GITHUB_BASE_REF,
|
||||
GITHUB_RUN_ID,
|
||||
PR_NUMBER,
|
||||
PR_TITLE,
|
||||
SHA,
|
||||
TEST_TYPE,
|
||||
} = process.env;
|
||||
|
||||
// Slack message blocks
|
||||
const blocks = [];
|
||||
const dividerBlock = {
|
||||
type: 'divider',
|
||||
};
|
||||
const introBlock = {
|
||||
type: 'section',
|
||||
text: {
|
||||
type: 'mrkdwn',
|
||||
text: `${ TEST_TYPE } tests failed on \`${ GITHUB_BASE_REF }\` after merging PR <https://github.com/woocommerce/woocommerce/pull/${ PR_NUMBER }|#${ PR_NUMBER }>`,
|
||||
},
|
||||
};
|
||||
const prTitleBlock = {
|
||||
type: 'header',
|
||||
text: {
|
||||
type: 'plain_text',
|
||||
text: PR_TITLE,
|
||||
emoji: true,
|
||||
},
|
||||
};
|
||||
const prButtonBlock = {
|
||||
type: 'actions',
|
||||
elements: [
|
||||
{
|
||||
type: 'button',
|
||||
text: {
|
||||
type: 'plain_text',
|
||||
text: 'View pull request :pr-merged:',
|
||||
emoji: true,
|
||||
},
|
||||
value: 'view_pr',
|
||||
url: `https://github.com/woocommerce/woocommerce/pull/${ PR_NUMBER }`,
|
||||
action_id: 'view-pr',
|
||||
},
|
||||
],
|
||||
};
|
||||
const mergeCommitBlock = {
|
||||
type: 'actions',
|
||||
elements: [
|
||||
{
|
||||
type: 'button',
|
||||
text: {
|
||||
type: 'plain_text',
|
||||
text: `View merge commit ${ SHA.substring(
|
||||
0,
|
||||
7
|
||||
) } :alphabet-yellow-hash:`,
|
||||
emoji: true,
|
||||
},
|
||||
value: 'view_commit',
|
||||
url: `https://github.com/woocommerce/woocommerce/commit/${ SHA }`,
|
||||
action_id: 'view-commit',
|
||||
},
|
||||
],
|
||||
};
|
||||
const githubBlock = {
|
||||
type: 'actions',
|
||||
elements: [
|
||||
{
|
||||
type: 'button',
|
||||
text: {
|
||||
type: 'plain_text',
|
||||
text: 'View GitHub run log :github:',
|
||||
emoji: true,
|
||||
},
|
||||
value: 'view_github',
|
||||
url: `https://github.com/woocommerce/woocommerce/actions/runs/${ GITHUB_RUN_ID }`,
|
||||
action_id: 'view-github',
|
||||
},
|
||||
],
|
||||
};
|
||||
const reportBlock = {
|
||||
type: 'actions',
|
||||
elements: [
|
||||
{
|
||||
type: 'button',
|
||||
text: {
|
||||
type: 'plain_text',
|
||||
text: 'View test report :colorful-bar-chart:',
|
||||
emoji: true,
|
||||
},
|
||||
value: 'view_report',
|
||||
url: `https://woocommerce.github.io/woocommerce-test-reports/pr-merge/${ PR_NUMBER }/${ TEST_TYPE.toLowerCase() }`,
|
||||
action_id: 'view-report',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
// Assemble blocks
|
||||
blocks.push( dividerBlock );
|
||||
blocks.push( introBlock );
|
||||
blocks.push( prTitleBlock );
|
||||
blocks.push( prButtonBlock );
|
||||
blocks.push( mergeCommitBlock );
|
||||
blocks.push( githubBlock );
|
||||
|
||||
if ( [ 'e2e', 'api' ].includes( TEST_TYPE.toLowerCase() ) ) {
|
||||
blocks.push( reportBlock );
|
||||
}
|
||||
|
||||
blocks.push( dividerBlock );
|
||||
|
||||
return { blocks };
|
||||
};
|
|
@ -0,0 +1,37 @@
|
|||
name: Upload Allure files to bucket
|
||||
description: Upload Allure files to bucket.
|
||||
permissions: {}
|
||||
|
||||
inputs:
|
||||
artifact-name:
|
||||
description: Name of the artifact that contains the allure-report and/or allure-results folders.
|
||||
required: true
|
||||
aws-region:
|
||||
required: true
|
||||
aws-access-key-id:
|
||||
required: true
|
||||
aws-secret-access-key:
|
||||
required: true
|
||||
s3-bucket:
|
||||
required: true
|
||||
include-allure-results:
|
||||
dafault: false
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1-node16
|
||||
with:
|
||||
aws-region: ${{ inputs.aws-region }}
|
||||
aws-access-key-id: ${{ inputs.aws-access-key-id }}
|
||||
aws-secret-access-key: ${{ inputs.aws-secret-access-key }}
|
||||
|
||||
- name: Upload Allure artifact
|
||||
env:
|
||||
ARTIFACT_NAME: ${{ inputs.artifact-name }}
|
||||
S3_BUCKET: ${{ inputs.s3-bucket }}
|
||||
INCLUDE_ALLURE_RESULTS: ${{ inputs.include-allure-results }}
|
||||
shell: bash
|
||||
working-directory: .github/actions/tests/upload-allure-files-to-bucket/scripts
|
||||
run: bash upload-allure-artifact.sh
|
30
.github/actions/tests/upload-allure-files-to-bucket/scripts/upload-allure-artifact.sh
vendored
Normal file
30
.github/actions/tests/upload-allure-files-to-bucket/scripts/upload-allure-artifact.sh
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
s3_upload () {
|
||||
aws s3 cp "$1" "$2" \
|
||||
--recursive
|
||||
}
|
||||
|
||||
upload_allure_results () {
|
||||
if [[ $INCLUDE_ALLURE_RESULTS != "true" ]]; then
|
||||
return
|
||||
fi
|
||||
|
||||
SOURCE="$ALLURE_RESULTS_DIR"
|
||||
DESTINATION="$S3_BUCKET/artifacts/$GITHUB_RUN_ID/$ARTIFACT_NAME/allure-results"
|
||||
|
||||
s3_upload "$SOURCE" "$DESTINATION"
|
||||
}
|
||||
|
||||
upload_allure_report () {
|
||||
SOURCE="$ALLURE_REPORT_DIR"
|
||||
DESTINATION="$S3_BUCKET/artifacts/$GITHUB_RUN_ID/$ARTIFACT_NAME/allure-report"
|
||||
|
||||
s3_upload "$SOURCE" "$DESTINATION"
|
||||
}
|
||||
|
||||
upload_allure_results
|
||||
upload_allure_report
|
||||
|
||||
EXIT_CODE=$(echo $?)
|
||||
exit $EXIT_CODE
|
|
@ -65,3 +65,12 @@
|
|||
- plugins/woocommerce/src/Admin/**/*
|
||||
- plugins/woocommerce/src/Internal/Admin/**/*
|
||||
- plugins/woocommerce-admin/**/*
|
||||
|
||||
'focus: performance tests [team:Solaris]':
|
||||
- plugins/woocommerce/tests/performance/**/*
|
||||
|
||||
'focus: api tests [team:Solaris]':
|
||||
- plugins/woocommerce/tests/api-core-tests/**/*
|
||||
|
||||
'focus: e2e tests [team:Solaris]':
|
||||
- plugins/woocommerce/tests/e2e-pw/**/*
|
||||
|
|
|
@ -31,9 +31,9 @@ jobs:
|
|||
include:
|
||||
- wp: nightly
|
||||
php: '7.4'
|
||||
- wp: '5.9'
|
||||
- wp: '6.0'
|
||||
php: 7.4
|
||||
- wp: '5.8'
|
||||
- wp: '5.9'
|
||||
php: 7.4
|
||||
services:
|
||||
database:
|
||||
|
|
|
@ -173,7 +173,7 @@ jobs:
|
|||
return await script( { core } )
|
||||
|
||||
- name: Find PR comment by github-actions[bot]
|
||||
uses: peter-evans/find-comment@v2
|
||||
uses: peter-evans/find-comment@034abe94d3191f9c89d870519735beae326f2bdb
|
||||
id: find-comment
|
||||
with:
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
|
@ -181,7 +181,7 @@ jobs:
|
|||
body-includes: Test Results Summary
|
||||
|
||||
- name: Create or update PR comment
|
||||
uses: peter-evans/create-or-update-comment@v2
|
||||
uses: peter-evans/create-or-update-comment@67dcc547d311b736a8e6c5c236542148a47adc3d
|
||||
with:
|
||||
comment-id: ${{ steps.find-comment.outputs.comment-id }}
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
|
|
|
@ -219,7 +219,7 @@ jobs:
|
|||
return await script( { core } )
|
||||
|
||||
- name: Find PR comment by github-actions[bot]
|
||||
uses: peter-evans/find-comment@v2
|
||||
uses: peter-evans/find-comment@034abe94d3191f9c89d870519735beae326f2bdb
|
||||
id: find-comment
|
||||
with:
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
|
@ -227,7 +227,7 @@ jobs:
|
|||
body-includes: Test Results Summary
|
||||
|
||||
- name: Create or update PR comment
|
||||
uses: peter-evans/create-or-update-comment@v2
|
||||
uses: peter-evans/create-or-update-comment@67dcc547d311b736a8e6c5c236542148a47adc3d
|
||||
with:
|
||||
comment-id: ${{ steps.find-comment.outputs.comment-id }}
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
|
|
|
@ -20,7 +20,7 @@ jobs:
|
|||
uses: actions/checkout@v3
|
||||
- name: Install prerequisites
|
||||
run: |
|
||||
npm install -g pnpm
|
||||
npm install -g pnpm@7
|
||||
npm -g i @wordpress/env@5.1.0
|
||||
pnpm install --filter code-analyzer --filter cli-core
|
||||
- name: Run analyzer
|
||||
|
|
|
@ -15,12 +15,14 @@ permissions: {}
|
|||
jobs:
|
||||
test:
|
||||
if: ${{ github.event_name != 'pull_request' || github.event.pull_request.user.login != 'github-actions[bot]' }}
|
||||
name: PHP ${{ matrix.php }} WP ${{ matrix.wp }}
|
||||
name: PHP ${{ matrix.php }} WP ${{ matrix.wp }} ${{ matrix.hpos && 'HPOS' || '' }}
|
||||
timeout-minutes: 30
|
||||
runs-on: ubuntu-20.04
|
||||
permissions:
|
||||
contents: read
|
||||
continue-on-error: ${{ matrix.wp == 'nightly' }}
|
||||
env:
|
||||
HPOS: ${{ matrix.hpos }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
|
@ -33,6 +35,9 @@ jobs:
|
|||
php: 7.4
|
||||
- wp: '5.9'
|
||||
php: 7.4
|
||||
- wp: 'latest'
|
||||
php: '7.4'
|
||||
hpos: true
|
||||
services:
|
||||
database:
|
||||
image: mysql:5.6
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
name: Remind reviewers to also review the testing instructions.
|
||||
on:
|
||||
pull_request:
|
||||
types: [review_requested]
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
add-testing-instructions-review-comment:
|
||||
runs-on: ubuntu-20.04
|
||||
permissions:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Get the username of requested reviewers
|
||||
id: get_reviewer_username
|
||||
run: |
|
||||
# Retrieves the username of all reviewers and stores them in a comma-separated list
|
||||
reviewers=$(echo '${{ toJson(github.event.pull_request.requested_reviewers[*].login) }}' | jq -r 'map("@\(.)") | join(", ")')
|
||||
echo "REVIEWERS=$reviewers" >> $GITHUB_ENV
|
||||
|
||||
- name: Get the name of requested teams
|
||||
id: get_team_name
|
||||
run: |
|
||||
# Retrieves the name of all teams asked for review and stores them in a comma-separated list
|
||||
teams=$(echo '${{ toJson(github.event.pull_request.requested_teams[*].slug) }}' | jq -r 'map("@woocommerce/\(.)") | join(", ")')
|
||||
echo "TEAMS=$teams" >> $GITHUB_ENV
|
||||
|
||||
- name: Find the comment by github-actions[bot] asking for reviewing the testing instructions
|
||||
uses: peter-evans/find-comment@034abe94d3191f9c89d870519735beae326f2bdb
|
||||
id: find-comment
|
||||
with:
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
comment-author: 'github-actions[bot]'
|
||||
body-includes: please make sure to review the testing instructions
|
||||
|
||||
- name: Create or update PR comment asking for reviewers to review the testing instructions
|
||||
uses: peter-evans/create-or-update-comment@67dcc547d311b736a8e6c5c236542148a47adc3d
|
||||
with:
|
||||
comment-id: ${{ steps.find-comment.outputs.comment-id }}
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
body: |
|
||||
Hi ${{ env.REVIEWERS }}, ${{ env.TEAMS }}
|
||||
|
||||
Apart from reviewing the code changes, please make sure to review the testing instructions as well.
|
||||
|
||||
You can follow this guide to find out what good testing instructions should look like:
|
||||
https://github.com/woocommerce/woocommerce/wiki/Writing-high-quality-testing-instructions
|
||||
edit-mode: replace
|
|
@ -0,0 +1,168 @@
|
|||
name: Run tests against trunk after PR merge
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- closed
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
|
||||
cancel-in-progress: true
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
api:
|
||||
name: Run API tests
|
||||
runs-on: ubuntu-20.04
|
||||
if: (github.event.pull_request.merged == true) && (github.event.pull_request.base.ref == 'trunk')
|
||||
permissions:
|
||||
contents: read
|
||||
env:
|
||||
ALLURE_RESULTS_DIR: ${{ github.workspace }}/plugins/woocommerce/tests/api-core-tests/test-results/allure-results
|
||||
ALLURE_REPORT_DIR: ${{ github.workspace }}/plugins/woocommerce/tests/api-core-tests/test-results/allure-report
|
||||
ARTIFACT_NAME: api-pr-merge-${{ github.event.pull_request.number }}-run-${{ github.run_number }}
|
||||
steps:
|
||||
- name: Checkout merge commit on trunk
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.merge_commit_sha }}
|
||||
|
||||
- name: Setup WooCommerce Monorepo
|
||||
uses: ./.github/actions/setup-woocommerce-monorepo
|
||||
with:
|
||||
build-filters: woocommerce
|
||||
|
||||
- name: Setup local test environment
|
||||
uses: ./.github/actions/tests/setup-local-test-environment
|
||||
with:
|
||||
test-type: api
|
||||
|
||||
- name: Run API tests
|
||||
id: run-api-composite-action
|
||||
uses: ./.github/actions/tests/run-api-tests
|
||||
with:
|
||||
report-name: ${{ env.ARTIFACT_NAME }}
|
||||
|
||||
- name: Upload Allure files to bucket
|
||||
if: success() || ( failure() && steps.run-api-composite-action.conclusion == 'failure' )
|
||||
uses: ./.github/actions/tests/upload-allure-files-to-bucket
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.REPORTS_AWS_ACCESS_KEY_ID }}
|
||||
aws-region: ${{ secrets.REPORTS_AWS_REGION }}
|
||||
aws-secret-access-key: ${{ secrets.REPORTS_AWS_SECRET_ACCESS_KEY }}
|
||||
artifact-name: ${{ env.ARTIFACT_NAME }}
|
||||
s3-bucket: ${{ secrets.REPORTS_BUCKET }}
|
||||
|
||||
- name: Publish Allure report
|
||||
if: success() || ( failure() && steps.run-api-composite-action.conclusion == 'failure' )
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.REPORTS_TOKEN }}
|
||||
run: |
|
||||
gh workflow run publish-test-reports-trunk-merge.yml \
|
||||
-f run_id=${{ github.run_id }} \
|
||||
-f artifact=${{ env.ARTIFACT_NAME }} \
|
||||
-f pr_number=${{ github.event.pull_request.number }} \
|
||||
-f test_type="api" \
|
||||
--repo woocommerce/woocommerce-test-reports
|
||||
|
||||
- name: Send Slack alert on test failure
|
||||
if: failure() && steps.run-api-composite-action.conclusion == 'failure'
|
||||
uses: ./.github/actions/tests/slack-alert-on-pr-merge
|
||||
with:
|
||||
slack-bot-token: ${{ secrets.E2E_SLACK_TOKEN }}
|
||||
channel-id: ${{ secrets.E2E_TRUNK_SLACK_CHANNEL }}
|
||||
test-type: API
|
||||
|
||||
e2e:
|
||||
name: Run E2E tests
|
||||
needs: [api]
|
||||
runs-on: ubuntu-20.04
|
||||
permissions:
|
||||
contents: read
|
||||
env:
|
||||
ALLURE_RESULTS_DIR: ${{ github.workspace }}/plugins/woocommerce/tests/e2e-pw/test-results/allure-results
|
||||
ALLURE_REPORT_DIR: ${{ github.workspace }}/plugins/woocommerce/tests/e2e-pw/test-results/allure-report
|
||||
ARTIFACT_NAME: e2e-pr-merge-${{ github.event.pull_request.number }}-run-${{ github.run_number }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.merge_commit_sha }}
|
||||
|
||||
- name: Setup WooCommerce Monorepo
|
||||
uses: ./.github/actions/setup-woocommerce-monorepo
|
||||
with:
|
||||
build-filters: woocommerce
|
||||
|
||||
- name: Setup local test environment
|
||||
uses: ./.github/actions/tests/setup-local-test-environment
|
||||
with:
|
||||
test-type: e2e
|
||||
|
||||
- name: Run E2E tests
|
||||
id: run-e2e-composite-action
|
||||
timeout-minutes: 60
|
||||
uses: ./.github/actions/tests/run-e2e-tests
|
||||
env:
|
||||
E2E_MAX_FAILURES: 15
|
||||
with:
|
||||
report-name: ${{ env.ARTIFACT_NAME }}
|
||||
|
||||
- name: Upload Allure files to bucket
|
||||
if: success() || ( failure() && steps.run-e2e-composite-action.conclusion == 'failure' )
|
||||
uses: ./.github/actions/tests/upload-allure-files-to-bucket
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.REPORTS_AWS_ACCESS_KEY_ID }}
|
||||
aws-region: ${{ secrets.REPORTS_AWS_REGION }}
|
||||
aws-secret-access-key: ${{ secrets.REPORTS_AWS_SECRET_ACCESS_KEY }}
|
||||
artifact-name: ${{ env.ARTIFACT_NAME }}
|
||||
s3-bucket: ${{ secrets.REPORTS_BUCKET }}
|
||||
include-allure-results: false
|
||||
|
||||
- name: Publish Allure report
|
||||
if: success() || ( failure() && steps.run-e2e-composite-action.conclusion == 'failure' )
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.REPORTS_TOKEN }}
|
||||
run: |
|
||||
gh workflow run publish-test-reports-trunk-merge.yml \
|
||||
-f run_id=${{ github.run_id }} \
|
||||
-f artifact=${{ env.ARTIFACT_NAME }} \
|
||||
-f pr_number=${{ github.event.pull_request.number }} \
|
||||
-f test_type="e2e" \
|
||||
--repo woocommerce/woocommerce-test-reports
|
||||
|
||||
- name: Send Slack alert on test failure
|
||||
if: failure() && steps.run-e2e-composite-action.conclusion == 'failure'
|
||||
uses: ./.github/actions/tests/slack-alert-on-pr-merge
|
||||
with:
|
||||
slack-bot-token: ${{ secrets.E2E_SLACK_TOKEN }}
|
||||
channel-id: ${{ secrets.E2E_TRUNK_SLACK_CHANNEL }}
|
||||
test-type: E2E
|
||||
|
||||
k6:
|
||||
name: Run k6 Performance tests
|
||||
needs: [api]
|
||||
runs-on: ubuntu-20.04
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.merge_commit_sha }}
|
||||
|
||||
- name: Setup WooCommerce Monorepo
|
||||
uses: ./.github/actions/setup-woocommerce-monorepo
|
||||
|
||||
- name: Setup local test environment
|
||||
uses: ./.github/actions/tests/setup-local-test-environment
|
||||
with:
|
||||
test-type: k6
|
||||
|
||||
- name: Run k6 performance tests
|
||||
id: run-k6-composite-action
|
||||
uses: './.github/actions/tests/run-k6-tests'
|
||||
|
||||
- name: Send Slack alert on test failure
|
||||
if: failure() && steps.run-k6-composite-action.conclusion == 'failure'
|
||||
uses: ./.github/actions/tests/slack-alert-on-pr-merge
|
||||
with:
|
||||
slack-bot-token: ${{ secrets.E2E_SLACK_TOKEN }}
|
||||
channel-id: ${{ secrets.E2E_TRUNK_SLACK_CHANNEL }}
|
||||
test-type: k6
|
|
@ -12,9 +12,8 @@ concurrency:
|
|||
cancel-in-progress: true
|
||||
permissions: {}
|
||||
env:
|
||||
E2E_WP_LATEST_ARTIFACT: e2e-wp-latest--run-${{ github.run_number }}
|
||||
E2E_UPDATE_WC_ARTIFACT: e2e-update-wc--run-${{ github.run_number }}
|
||||
FORCE_COLOR: 1
|
||||
E2E_WP_LATEST_ARTIFACT: E2E test on release smoke test site with WP Latest (run ${{ github.run_number }})
|
||||
E2E_UPDATE_WC_ARTIFACT: WooCommerce version update test on release smoke test site (run ${{ github.run_number }})
|
||||
|
||||
jobs:
|
||||
get-tag:
|
||||
|
@ -80,12 +79,13 @@ jobs:
|
|||
install-filters: woocommerce
|
||||
build: false
|
||||
|
||||
- name: Download and install Chromium browser.
|
||||
working-directory: plugins/woocommerce
|
||||
run: pnpm exec playwright install chromium
|
||||
|
||||
- name: Run 'Update WooCommerce' test.
|
||||
working-directory: plugins/woocommerce
|
||||
- name: Run E2E tests
|
||||
id: run-e2e-composite-action
|
||||
timeout-minutes: 60
|
||||
uses: ./.github/actions/tests/run-e2e-tests
|
||||
with:
|
||||
report-name: ${{ env.E2E_UPDATE_WC_ARTIFACT }}
|
||||
tests: update-woocommerce.spec.js
|
||||
env:
|
||||
ADMIN_PASSWORD: ${{ secrets.RELEASE_TEST_ADMIN_PASSWORD }}
|
||||
ADMIN_USER: ${{ secrets.RELEASE_TEST_ADMIN_USER }}
|
||||
|
@ -95,36 +95,19 @@ jobs:
|
|||
DEFAULT_TIMEOUT_OVERRIDE: 120000
|
||||
GITHUB_TOKEN: ${{ secrets.E2E_GH_TOKEN }}
|
||||
UPDATE_WC: ${{ needs.get-tag.outputs.tag }}
|
||||
run: |
|
||||
pnpm exec playwright test \
|
||||
--config=tests/e2e-pw/playwright.config.js \
|
||||
update-woocommerce.spec.js
|
||||
|
||||
- name: Generate 'Update WooCommerce' test report.
|
||||
if: success() || failure()
|
||||
working-directory: plugins/woocommerce
|
||||
run: pnpm exec allure generate --clean ${{ env.ALLURE_RESULTS_DIR }} --output ${{ env.ALLURE_REPORT_DIR }}
|
||||
|
||||
- name: Configure AWS credentials
|
||||
if: success() || failure()
|
||||
uses: aws-actions/configure-aws-credentials@v1-node16
|
||||
- name: Upload Allure artifacts to bucket
|
||||
if: success() || ( failure() && steps.run-e2e-composite-action.conclusion == 'failure' )
|
||||
uses: ./.github/actions/tests/upload-allure-files-to-bucket
|
||||
with:
|
||||
aws-region: ${{ secrets.REPORTS_AWS_REGION }}
|
||||
aws-access-key-id: ${{ secrets.REPORTS_AWS_ACCESS_KEY_ID }}
|
||||
aws-region: ${{ secrets.REPORTS_AWS_REGION }}
|
||||
aws-secret-access-key: ${{ secrets.REPORTS_AWS_SECRET_ACCESS_KEY }}
|
||||
|
||||
- name: Upload Allure files to bucket
|
||||
if: success() || failure()
|
||||
run: |
|
||||
aws s3 sync ${{ env.ALLURE_RESULTS_DIR }} \
|
||||
${{ secrets.REPORTS_BUCKET }}/artifacts/${{ github.run_id }}/${{ env.E2E_WP_LATEST_ARTIFACT }}/allure-results \
|
||||
--quiet
|
||||
aws s3 sync ${{ env.ALLURE_REPORT_DIR }} \
|
||||
${{ secrets.REPORTS_BUCKET }}/artifacts/${{ github.run_id }}/${{ env.E2E_WP_LATEST_ARTIFACT }}/allure-report \
|
||||
--quiet
|
||||
artifact-name: ${{ env.E2E_WP_LATEST_ARTIFACT }}
|
||||
s3-bucket: ${{ secrets.REPORTS_BUCKET }}
|
||||
|
||||
- name: Publish E2E Allure report
|
||||
if: success() || failure()
|
||||
if: success() || ( failure() && steps.run-e2e-composite-action.conclusion == 'failure' )
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.REPORTS_TOKEN }}
|
||||
ENV_DESCRIPTION: wp-latest
|
||||
|
@ -139,17 +122,6 @@ jobs:
|
|||
-f test_type="e2e" \
|
||||
--repo woocommerce/woocommerce-test-reports
|
||||
|
||||
- name: Archive 'Update WooCommerce' test report
|
||||
if: success() || failure()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ env.E2E_UPDATE_WC_ARTIFACT }}
|
||||
path: |
|
||||
${{ env.ALLURE_RESULTS_DIR }}
|
||||
${{ env.ALLURE_REPORT_DIR }}
|
||||
if-no-files-found: ignore
|
||||
retention-days: 5
|
||||
|
||||
api-wp-latest:
|
||||
name: API on WP Latest
|
||||
runs-on: ubuntu-20.04
|
||||
|
@ -159,7 +131,7 @@ jobs:
|
|||
env:
|
||||
ALLURE_REPORT_DIR: ${{ github.workspace }}/plugins/woocommerce/tests/api-core-tests/api-test-report/allure-report
|
||||
ALLURE_RESULTS_DIR: ${{ github.workspace }}/plugins/woocommerce/tests/api-core-tests/api-test-report/allure-results
|
||||
API_WP_LATEST_ARTIFACT: api-wp-latest--run-${{ github.run_number }}
|
||||
API_WP_LATEST_ARTIFACT: API test on release smoke test site with WP Latest (run ${{ github.run_number }})
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
|
@ -169,41 +141,29 @@ jobs:
|
|||
install-filters: woocommerce
|
||||
build: false
|
||||
|
||||
- name: Run API tests.
|
||||
working-directory: plugins/woocommerce
|
||||
- name: Run API tests
|
||||
id: run-api-composite-action
|
||||
uses: ./.github/actions/tests/run-api-tests
|
||||
with:
|
||||
report-name: ${{ env.API_WP_LATEST_ARTIFACT }}
|
||||
tests: hello
|
||||
env:
|
||||
BASE_URL: ${{ secrets.RELEASE_TEST_URL }}
|
||||
USER_KEY: ${{ secrets.RELEASE_TEST_ADMIN_USER }}
|
||||
USER_SECRET: ${{ secrets.RELEASE_TEST_ADMIN_PASSWORD }}
|
||||
run: pnpm exec playwright test --config=tests/api-core-tests/playwright.config.js hello
|
||||
|
||||
- name: Generate API Test report.
|
||||
if: success() || failure()
|
||||
working-directory: plugins/woocommerce
|
||||
run: pnpm exec allure generate --clean ${{ env.ALLURE_RESULTS_DIR }} --output ${{ env.ALLURE_REPORT_DIR }}
|
||||
|
||||
- name: Configure AWS credentials
|
||||
if: success() || failure()
|
||||
uses: aws-actions/configure-aws-credentials@v1-node16
|
||||
- name: Upload Allure artifacts to bucket
|
||||
if: success() || ( failure() && steps.run-api-composite-action.conclusion == 'failure' )
|
||||
uses: ./.github/actions/tests/upload-allure-files-to-bucket
|
||||
with:
|
||||
aws-region: ${{ secrets.REPORTS_AWS_REGION }}
|
||||
aws-access-key-id: ${{ secrets.REPORTS_AWS_ACCESS_KEY_ID }}
|
||||
aws-region: ${{ secrets.REPORTS_AWS_REGION }}
|
||||
aws-secret-access-key: ${{ secrets.REPORTS_AWS_SECRET_ACCESS_KEY }}
|
||||
|
||||
- name: Upload Allure files to bucket
|
||||
if: success() || failure()
|
||||
run: |
|
||||
aws s3 cp ${{ env.ALLURE_RESULTS_DIR }} \
|
||||
${{ secrets.REPORTS_BUCKET }}/artifacts/${{ github.run_id }}/${{ env.API_WP_LATEST_ARTIFACT }}/allure-results \
|
||||
--recursive \
|
||||
--quiet
|
||||
aws s3 cp ${{ env.ALLURE_REPORT_DIR }} \
|
||||
${{ secrets.REPORTS_BUCKET }}/artifacts/${{ github.run_id }}/${{ env.API_WP_LATEST_ARTIFACT }}/allure-report \
|
||||
--recursive \
|
||||
--quiet
|
||||
artifact-name: ${{ env.API_WP_LATEST_ARTIFACT }}
|
||||
s3-bucket: ${{ secrets.REPORTS_BUCKET }}
|
||||
|
||||
- name: Publish API Allure report
|
||||
if: success() || failure()
|
||||
if: success() || ( failure() && steps.run-api-composite-action.conclusion == 'failure' )
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.REPORTS_TOKEN }}
|
||||
ENV_DESCRIPTION: wp-latest
|
||||
|
@ -218,17 +178,6 @@ jobs:
|
|||
-f test_type="api" \
|
||||
--repo woocommerce/woocommerce-test-reports
|
||||
|
||||
- name: Archive API test report
|
||||
if: success() || failure()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ env.API_WP_LATEST_ARTIFACT }}
|
||||
path: |
|
||||
${{ env.ALLURE_RESULTS_DIR }}
|
||||
${{ env.ALLURE_REPORT_DIR }}
|
||||
if-no-files-found: ignore
|
||||
retention-days: 5
|
||||
|
||||
e2e-wp-latest:
|
||||
name: E2E on WP Latest
|
||||
runs-on: ubuntu-20.04
|
||||
|
@ -247,11 +196,13 @@ jobs:
|
|||
install-filters: woocommerce
|
||||
build: false
|
||||
|
||||
- name: Download and install Chromium browser.
|
||||
working-directory: plugins/woocommerce
|
||||
run: pnpm exec playwright install chromium
|
||||
|
||||
- name: Run E2E tests
|
||||
id: run-e2e-composite-action
|
||||
timeout-minutes: 60
|
||||
uses: ./.github/actions/tests/run-e2e-tests
|
||||
with:
|
||||
report-name: e2e-wp-latest--partial--run-${{ github.run_number }}
|
||||
playwright-config: ignore-plugin-tests.playwright.config.js
|
||||
env:
|
||||
ADMIN_PASSWORD: ${{ secrets.RELEASE_TEST_ADMIN_PASSWORD }}
|
||||
ADMIN_USER: ${{ secrets.RELEASE_TEST_ADMIN_USER }}
|
||||
|
@ -262,9 +213,6 @@ jobs:
|
|||
DEFAULT_TIMEOUT_OVERRIDE: 120000
|
||||
E2E_MAX_FAILURES: 25
|
||||
RESET_SITE: true
|
||||
timeout-minutes: 60
|
||||
working-directory: plugins/woocommerce
|
||||
run: pnpm exec playwright test --config=tests/e2e-pw/ignore-plugin-tests.playwright.config.js
|
||||
|
||||
- name: Download 'e2e-update-wc' artifact
|
||||
if: success() || failure()
|
||||
|
@ -283,23 +231,26 @@ jobs:
|
|||
working-directory: plugins/woocommerce
|
||||
run: pnpm exec allure generate --clean ${{ env.ALLURE_RESULTS_DIR }} --output ${{ env.ALLURE_REPORT_DIR }}
|
||||
|
||||
- name: Configure AWS credentials
|
||||
- name: Archive E2E test report
|
||||
if: success() || failure()
|
||||
uses: aws-actions/configure-aws-credentials@v1-node16
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
aws-region: ${{ secrets.REPORTS_AWS_REGION }}
|
||||
aws-access-key-id: ${{ secrets.REPORTS_AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.REPORTS_AWS_SECRET_ACCESS_KEY }}
|
||||
name: ${{ env.E2E_WP_LATEST_ARTIFACT }}
|
||||
path: |
|
||||
${{ env.ALLURE_RESULTS_DIR }}
|
||||
${{ env.ALLURE_REPORT_DIR }}
|
||||
if-no-files-found: ignore
|
||||
retention-days: 5
|
||||
|
||||
- name: Upload report to bucket
|
||||
if: success() || failure()
|
||||
run: |
|
||||
aws s3 sync ${{ env.ALLURE_RESULTS_DIR }} \
|
||||
${{ secrets.REPORTS_BUCKET }}/artifacts/${{ github.run_id }}/${{ env.E2E_WP_LATEST_ARTIFACT }}/allure-results \
|
||||
--quiet
|
||||
aws s3 sync ${{ env.ALLURE_REPORT_DIR }} \
|
||||
${{ secrets.REPORTS_BUCKET }}/artifacts/${{ github.run_id }}/${{ env.E2E_WP_LATEST_ARTIFACT }}/allure-report \
|
||||
--quiet
|
||||
- name: Upload Allure artifacts to bucket
|
||||
if: success() || ( failure() && steps.run-e2e-composite-action.conclusion == 'failure' )
|
||||
uses: ./.github/actions/tests/upload-allure-files-to-bucket
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.REPORTS_AWS_ACCESS_KEY_ID }}
|
||||
aws-region: ${{ secrets.REPORTS_AWS_REGION }}
|
||||
aws-secret-access-key: ${{ secrets.REPORTS_AWS_SECRET_ACCESS_KEY }}
|
||||
artifact-name: ${{ env.E2E_WP_LATEST_ARTIFACT }}
|
||||
s3-bucket: ${{ secrets.REPORTS_BUCKET }}
|
||||
|
||||
- name: Publish E2E Allure report
|
||||
if: success() || failure()
|
||||
|
@ -317,17 +268,6 @@ jobs:
|
|||
-f test_type="e2e" \
|
||||
--repo woocommerce/woocommerce-test-reports
|
||||
|
||||
- name: Archive E2E test report
|
||||
if: success() || failure()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ env.E2E_WP_LATEST_ARTIFACT }}
|
||||
path: |
|
||||
${{ env.ALLURE_RESULTS_DIR }}
|
||||
${{ env.ALLURE_REPORT_DIR }}
|
||||
if-no-files-found: ignore
|
||||
retention-days: 5
|
||||
|
||||
get-wp-versions:
|
||||
name: Get WP L-1 & L-2 version numbers
|
||||
needs: [get-tag]
|
||||
|
@ -371,14 +311,15 @@ jobs:
|
|||
runs-on: ubuntu-20.04
|
||||
needs: [get-wp-versions]
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix: ${{ fromJSON(needs.get-wp-versions.outputs.matrix) }}
|
||||
env:
|
||||
API_ALLURE_REPORT_DIR: ${{ github.workspace }}/plugins/woocommerce/tests/e2e-pw/test-results/api/allure-report
|
||||
API_ALLURE_RESULTS_DIR: ${{ github.workspace }}/plugins/woocommerce/tests/e2e-pw/test-results/api/allure-results
|
||||
API_WP_LATEST_X_ARTIFACT: api-${{ matrix.version.env_description }}--run-${{ github.run_number }}
|
||||
API_WP_LATEST_X_ARTIFACT: API test on wp-env with WordPress ${{ matrix.version.number }} (run ${{ github.run_number }})
|
||||
E2E_ALLURE_REPORT_DIR: ${{ github.workspace }}/plugins/woocommerce/tests/e2e-pw/test-results/e2e/allure-report
|
||||
E2E_ALLURE_RESULTS_DIR: ${{ github.workspace }}/plugins/woocommerce/tests/e2e-pw/test-results/e2e/allure-results
|
||||
E2E_WP_LATEST_X_ARTIFACT: e2e-${{ matrix.version.env_description }}--run-${{ github.run_number }}
|
||||
E2E_WP_LATEST_X_ARTIFACT: E2E test on wp-env with WordPress ${{ matrix.version.number }} (run ${{ github.run_number }})
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
|
@ -414,38 +355,31 @@ jobs:
|
|||
pnpm exec wp-env run tests-cli "wp theme list"
|
||||
pnpm exec wp-env run tests-cli "wp user list"
|
||||
|
||||
- name: Run API tests.
|
||||
id: api
|
||||
working-directory: plugins/woocommerce
|
||||
- name: Run API tests
|
||||
id: run-api-composite-action
|
||||
uses: ./.github/actions/tests/run-api-tests
|
||||
with:
|
||||
report-name: ${{ env.API_WP_LATEST_X_ARTIFACT }}
|
||||
tests: hello
|
||||
env:
|
||||
ALLURE_RESULTS_DIR: ${{ env.API_ALLURE_RESULTS_DIR }}
|
||||
run: pnpm exec playwright test --config=tests/api-core-tests/playwright.config.js hello
|
||||
ALLURE_REPORT_DIR: ${{ env.API_ALLURE_REPORT_DIR }}
|
||||
|
||||
- name: Generate API Allure report.
|
||||
if: success() || failure()
|
||||
working-directory: plugins/woocommerce
|
||||
run: pnpm exec allure generate --clean ${{ env.API_ALLURE_RESULTS_DIR }} --output ${{ env.API_ALLURE_REPORT_DIR }}
|
||||
|
||||
- name: Configure AWS credentials
|
||||
if: success() || failure()
|
||||
uses: aws-actions/configure-aws-credentials@v1-node16
|
||||
- name: Upload Allure artifacts to bucket
|
||||
if: success() || ( failure() && steps.run-api-composite-action.conclusion == 'failure' )
|
||||
uses: ./.github/actions/tests/upload-allure-files-to-bucket
|
||||
env:
|
||||
ALLURE_RESULTS_DIR: ${{ env.API_ALLURE_RESULTS_DIR }}
|
||||
ALLURE_REPORT_DIR: ${{ env.API_ALLURE_REPORT_DIR }}
|
||||
with:
|
||||
aws-region: ${{ secrets.REPORTS_AWS_REGION }}
|
||||
aws-access-key-id: ${{ secrets.REPORTS_AWS_ACCESS_KEY_ID }}
|
||||
aws-region: ${{ secrets.REPORTS_AWS_REGION }}
|
||||
aws-secret-access-key: ${{ secrets.REPORTS_AWS_SECRET_ACCESS_KEY }}
|
||||
|
||||
- name: Upload API Allure artifacts to bucket
|
||||
if: success() || failure()
|
||||
run: |
|
||||
aws s3 sync ${{ env.API_ALLURE_RESULTS_DIR }} \
|
||||
${{ secrets.REPORTS_BUCKET }}/artifacts/${{ github.run_id }}/${{ env.API_WP_LATEST_X_ARTIFACT }}/allure-results \
|
||||
--quiet
|
||||
aws s3 sync ${{ env.API_ALLURE_REPORT_DIR }} \
|
||||
${{ secrets.REPORTS_BUCKET }}/artifacts/${{ github.run_id }}/${{ env.API_WP_LATEST_X_ARTIFACT }}/allure-report \
|
||||
--quiet
|
||||
artifact-name: ${{ env.API_WP_LATEST_X_ARTIFACT }}
|
||||
s3-bucket: ${{ secrets.REPORTS_BUCKET }}
|
||||
|
||||
- name: Publish API Allure report
|
||||
if: success() || failure()
|
||||
if: success() || ( failure() && steps.run-api-composite-action.conclusion == 'failure' )
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.REPORTS_TOKEN }}
|
||||
ENV_DESCRIPTION: ${{ matrix.version.env_description }}
|
||||
|
@ -460,65 +394,33 @@ jobs:
|
|||
-f test_type="api" \
|
||||
--repo woocommerce/woocommerce-test-reports
|
||||
|
||||
- name: Archive API Allure reports
|
||||
if: success() || failure()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ env.API_WP_LATEST_X_ARTIFACT }}
|
||||
path: |
|
||||
${{ env.API_ALLURE_RESULTS_DIR }}
|
||||
${{ env.API_ALLURE_REPORT_DIR }}
|
||||
if-no-files-found: ignore
|
||||
retention-days: 5
|
||||
|
||||
- name: Download and install Chromium browser.
|
||||
if: success() || failure()
|
||||
working-directory: plugins/woocommerce
|
||||
run: pnpm exec playwright install chromium
|
||||
|
||||
- name: Run E2E tests.
|
||||
if: |
|
||||
success() ||
|
||||
( failure() && steps.api.conclusion == 'success' )
|
||||
- name: Run E2E tests
|
||||
id: run-e2e-composite-action
|
||||
timeout-minutes: 60
|
||||
id: e2e
|
||||
uses: ./.github/actions/tests/run-e2e-tests
|
||||
env:
|
||||
USE_WP_ENV: 1
|
||||
E2E_MAX_FAILURES: 15
|
||||
FORCE_COLOR: 1
|
||||
ALLURE_RESULTS_DIR: ${{ env.E2E_ALLURE_RESULTS_DIR }}
|
||||
ALLURE_REPORT_DIR: ${{ env.E2E_ALLURE_REPORT_DIR }}
|
||||
DEFAULT_TIMEOUT_OVERRIDE: 120000
|
||||
working-directory: plugins/woocommerce
|
||||
run: pnpm exec playwright test --config=tests/e2e-pw/playwright.config.js
|
||||
|
||||
- name: Generate E2E Allure report.
|
||||
if: success() || failure()
|
||||
working-directory: plugins/woocommerce
|
||||
run: pnpm exec allure generate --clean ${{ env.E2E_ALLURE_RESULTS_DIR }} --output ${{ env.E2E_ALLURE_REPORT_DIR }}
|
||||
|
||||
- name: Upload E2E Allure artifacts to bucket
|
||||
if: success() || failure()
|
||||
run: |
|
||||
aws s3 sync ${{ env.E2E_ALLURE_RESULTS_DIR }} \
|
||||
${{ secrets.REPORTS_BUCKET }}/artifacts/${{ github.run_id }}/${{ env.E2E_WP_LATEST_X_ARTIFACT }}/allure-results \
|
||||
--quiet
|
||||
aws s3 sync ${{ env.E2E_ALLURE_REPORT_DIR }} \
|
||||
${{ secrets.REPORTS_BUCKET }}/artifacts/${{ github.run_id }}/${{ env.E2E_WP_LATEST_X_ARTIFACT }}/allure-report \
|
||||
--quiet
|
||||
|
||||
- name: Archive E2E Allure reports
|
||||
if: success() || failure()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ env.E2E_WP_LATEST_X_ARTIFACT }}
|
||||
path: |
|
||||
${{ env.E2E_ALLURE_RESULTS_DIR }}
|
||||
${{ env.E2E_ALLURE_REPORT_DIR }}
|
||||
if-no-files-found: ignore
|
||||
retention-days: 5
|
||||
report-name: ${{ env.E2E_WP_LATEST_X_ARTIFACT }}
|
||||
|
||||
- name: Upload Allure artifacts to bucket
|
||||
if: success() || ( failure() && steps.run-e2e-composite-action.conclusion == 'failure' )
|
||||
uses: ./.github/actions/tests/upload-allure-files-to-bucket
|
||||
env:
|
||||
ALLURE_RESULTS_DIR: ${{ env.E2E_ALLURE_RESULTS_DIR }}
|
||||
ALLURE_REPORT_DIR: ${{ env.E2E_ALLURE_REPORT_DIR }}
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.REPORTS_AWS_ACCESS_KEY_ID }}
|
||||
aws-region: ${{ secrets.REPORTS_AWS_REGION }}
|
||||
aws-secret-access-key: ${{ secrets.REPORTS_AWS_SECRET_ACCESS_KEY }}
|
||||
artifact-name: ${{ env.E2E_WP_LATEST_X_ARTIFACT }}
|
||||
s3-bucket: ${{ secrets.REPORTS_BUCKET }}
|
||||
|
||||
- name: Publish E2E Allure report
|
||||
if: success() || failure()
|
||||
if: success() || ( failure() && steps.run-e2e-composite-action.conclusion == 'failure' )
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.REPORTS_TOKEN }}
|
||||
ENV_DESCRIPTION: ${{ matrix.version.env_description }}
|
||||
|
@ -538,15 +440,16 @@ jobs:
|
|||
runs-on: ubuntu-20.04
|
||||
needs: [get-tag]
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
php_version: ['7.4', '8.1']
|
||||
env:
|
||||
API_ALLURE_REPORT_DIR: ${{ github.workspace }}/plugins/woocommerce/tests/api-core-tests/test-results/allure-report
|
||||
API_ALLURE_RESULTS_DIR: ${{ github.workspace }}/plugins/woocommerce/tests/api-core-tests/test-results/allure-results
|
||||
API_ARTIFACT: api-php-${{ matrix.php_version }}--run-${{ github.run_number }}
|
||||
API_ARTIFACT: API test on wp-env with PHP ${{ matrix.php_version }} (run ${{ github.run_number }})
|
||||
E2E_ALLURE_REPORT_DIR: ${{ github.workspace }}/plugins/woocommerce/tests/e2e-pw/test-results/allure-report
|
||||
E2E_ALLURE_RESULTS_DIR: ${{ github.workspace }}/plugins/woocommerce/tests/e2e-pw/test-results/allure-results
|
||||
E2E_ARTIFACT: e2e-php-${{ matrix.php_version }}--run-${{ github.run_number }}
|
||||
E2E_ARTIFACT: E2E test on wp-env with PHP ${{ matrix.php_version }} (run ${{ github.run_number }})
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
@ -574,38 +477,31 @@ jobs:
|
|||
- name: Replace `plugins/woocommerce` with unzipped woocommerce release build
|
||||
run: unzip -d plugins -o tmp/woocommerce.zip
|
||||
|
||||
- name: Run API tests.
|
||||
id: api
|
||||
working-directory: plugins/woocommerce
|
||||
- name: Run API tests
|
||||
id: run-api-composite-action
|
||||
uses: ./.github/actions/tests/run-api-tests
|
||||
with:
|
||||
report-name: ${{ env.API_ARTIFACT }}
|
||||
tests: hello
|
||||
env:
|
||||
ALLURE_RESULTS_DIR: ${{ env.API_ALLURE_RESULTS_DIR }}
|
||||
run: pnpm exec playwright test --config=tests/api-core-tests/playwright.config.js hello
|
||||
ALLURE_REPORT_DIR: ${{ env.API_ALLURE_REPORT_DIR }}
|
||||
|
||||
- name: Generate API Allure report.
|
||||
if: success() || failure()
|
||||
working-directory: plugins/woocommerce
|
||||
run: pnpm exec allure generate --clean ${{ env.API_ALLURE_RESULTS_DIR }} --output ${{ env.API_ALLURE_REPORT_DIR }}
|
||||
|
||||
- name: Configure AWS credentials
|
||||
if: success() || failure()
|
||||
uses: aws-actions/configure-aws-credentials@v1-node16
|
||||
- name: Upload Allure artifacts to bucket
|
||||
if: success() || ( failure() && steps.run-api-composite-action.conclusion == 'failure' )
|
||||
uses: ./.github/actions/tests/upload-allure-files-to-bucket
|
||||
env:
|
||||
ALLURE_RESULTS_DIR: ${{ env.API_ALLURE_RESULTS_DIR }}
|
||||
ALLURE_REPORT_DIR: ${{ env.API_ALLURE_REPORT_DIR }}
|
||||
with:
|
||||
aws-region: ${{ secrets.REPORTS_AWS_REGION }}
|
||||
aws-access-key-id: ${{ secrets.REPORTS_AWS_ACCESS_KEY_ID }}
|
||||
aws-region: ${{ secrets.REPORTS_AWS_REGION }}
|
||||
aws-secret-access-key: ${{ secrets.REPORTS_AWS_SECRET_ACCESS_KEY }}
|
||||
|
||||
- name: Upload API Allure artifacts to bucket
|
||||
if: success() || failure()
|
||||
run: |
|
||||
aws s3 sync ${{ env.API_ALLURE_RESULTS_DIR }} \
|
||||
${{ secrets.REPORTS_BUCKET }}/artifacts/${{ github.run_id }}/${{ env.API_ARTIFACT }}/allure-results \
|
||||
--quiet
|
||||
aws s3 sync ${{ env.API_ALLURE_REPORT_DIR }} \
|
||||
${{ secrets.REPORTS_BUCKET }}/artifacts/${{ github.run_id }}/${{ env.API_ARTIFACT }}/allure-report \
|
||||
--quiet
|
||||
artifact-name: ${{ env.API_ARTIFACT }}
|
||||
s3-bucket: ${{ secrets.REPORTS_BUCKET }}
|
||||
|
||||
- name: Publish API Allure report
|
||||
if: success() || failure()
|
||||
if: success() || ( failure() && steps.run-api-composite-action.conclusion == 'failure' )
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.REPORTS_TOKEN }}
|
||||
ENV_DESCRIPTION: php-${{ matrix.php_version }}
|
||||
|
@ -620,63 +516,33 @@ jobs:
|
|||
-f test_type="api" \
|
||||
--repo woocommerce/woocommerce-test-reports
|
||||
|
||||
- name: Archive API Allure reports
|
||||
if: success() || failure()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ env.API_ARTIFACT }}
|
||||
path: |
|
||||
${{ env.API_ALLURE_RESULTS_DIR }}
|
||||
${{ env.API_ALLURE_REPORT_DIR }}
|
||||
if-no-files-found: ignore
|
||||
retention-days: 5
|
||||
|
||||
- name: Download and install Chromium browser.
|
||||
working-directory: plugins/woocommerce
|
||||
run: pnpm exec playwright install chromium
|
||||
|
||||
- name: Run E2E tests.
|
||||
if: |
|
||||
success() ||
|
||||
( failure() && steps.api.conclusion == 'success' )
|
||||
- name: Run E2E tests
|
||||
id: run-e2e-composite-action
|
||||
timeout-minutes: 60
|
||||
uses: ./.github/actions/tests/run-e2e-tests
|
||||
env:
|
||||
USE_WP_ENV: 1
|
||||
E2E_MAX_FAILURES: 15
|
||||
FORCE_COLOR: 1
|
||||
ALLURE_RESULTS_DIR: ${{ env.E2E_ALLURE_RESULTS_DIR }}
|
||||
ALLURE_REPORT_DIR: ${{ env.E2E_ALLURE_REPORT_DIR }}
|
||||
DEFAULT_TIMEOUT_OVERRIDE: 120000
|
||||
working-directory: plugins/woocommerce
|
||||
run: pnpm exec playwright test --config=tests/e2e-pw/playwright.config.js
|
||||
|
||||
- name: Generate E2E Allure report.
|
||||
if: success() || failure()
|
||||
working-directory: plugins/woocommerce
|
||||
run: pnpm exec allure generate --clean ${{ env.E2E_ALLURE_RESULTS_DIR }} --output ${{ env.E2E_ALLURE_REPORT_DIR }}
|
||||
|
||||
- name: Upload E2E Allure artifacts to bucket
|
||||
if: success() || failure()
|
||||
run: |
|
||||
aws s3 sync ${{ env.E2E_ALLURE_RESULTS_DIR }} \
|
||||
${{ secrets.REPORTS_BUCKET }}/artifacts/${{ github.run_id }}/${{ env.E2E_ARTIFACT }}/allure-results \
|
||||
--quiet
|
||||
aws s3 sync ${{ env.E2E_ALLURE_REPORT_DIR }} \
|
||||
${{ secrets.REPORTS_BUCKET }}/artifacts/${{ github.run_id }}/${{ env.E2E_ARTIFACT }}/allure-report \
|
||||
--quiet
|
||||
|
||||
- name: Archive E2E Allure reports
|
||||
if: success() || failure()
|
||||
uses: actions/upload-artifact@v3
|
||||
E2E_MAX_FAILURES: 15
|
||||
with:
|
||||
name: ${{ env.E2E_ARTIFACT }}
|
||||
path: |
|
||||
${{ env.E2E_ALLURE_RESULTS_DIR }}
|
||||
${{ env.E2E_ALLURE_REPORT_DIR }}
|
||||
if-no-files-found: ignore
|
||||
retention-days: 5
|
||||
report-name: ${{ env.E2E_ARTIFACT }}
|
||||
|
||||
- name: Upload Allure artifacts to bucket
|
||||
if: success() || ( failure() && steps.run-e2e-composite-action.conclusion == 'failure' )
|
||||
uses: ./.github/actions/tests/upload-allure-files-to-bucket
|
||||
env:
|
||||
ALLURE_RESULTS_DIR: ${{ env.E2E_ALLURE_RESULTS_DIR }}
|
||||
ALLURE_REPORT_DIR: ${{ env.E2E_ALLURE_REPORT_DIR }}
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.REPORTS_AWS_ACCESS_KEY_ID }}
|
||||
aws-region: ${{ secrets.REPORTS_AWS_REGION }}
|
||||
aws-secret-access-key: ${{ secrets.REPORTS_AWS_SECRET_ACCESS_KEY }}
|
||||
artifact-name: ${{ env.E2E_ARTIFACT }}
|
||||
s3-bucket: ${{ secrets.REPORTS_BUCKET }}
|
||||
|
||||
- name: Publish E2E Allure report
|
||||
if: success() || failure()
|
||||
if: success() || ( failure() && steps.run-e2e-composite-action.conclusion == 'failure' )
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.REPORTS_TOKEN }}
|
||||
ENV_DESCRIPTION: php-${{ matrix.php_version }}
|
||||
|
@ -690,3 +556,103 @@ jobs:
|
|||
-f env_description="${{ env.ENV_DESCRIPTION }}" \
|
||||
-f test_type="e2e" \
|
||||
--repo woocommerce/woocommerce-test-reports
|
||||
|
||||
test-plugins:
|
||||
name: With ${{ matrix.plugin }}
|
||||
runs-on: ubuntu-20.04
|
||||
needs: [get-tag]
|
||||
env:
|
||||
ALLURE_RESULTS_DIR: ${{ github.workspace }}/plugins/woocommerce/tests/e2e-pw/allure-results
|
||||
ALLURE_REPORT_DIR: ${{ github.workspace }}/plugins/woocommerce/tests/e2e-pw/allure-report
|
||||
ARTIFACT_NAME: E2E test on wp-env with ${{ matrix.plugin }} installed (run ${{ github.run_number }})
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- plugin: 'WooCommerce Payments'
|
||||
repo: 'automattic/woocommerce-payments'
|
||||
env_description: 'woocommerce-payments'
|
||||
- plugin: 'WooCommerce PayPal Payments'
|
||||
repo: 'woocommerce/woocommerce-paypal-payments'
|
||||
env_description: 'woocommerce-paypal-payments'
|
||||
- plugin: 'WooCommerce Shipping & Tax'
|
||||
repo: 'automattic/woocommerce-services'
|
||||
env_description: 'woocommerce-shipping-&-tax'
|
||||
- plugin: 'WooCommerce Subscriptions'
|
||||
repo: WC_SUBSCRIPTIONS_REPO
|
||||
private: true
|
||||
env_description: 'woocommerce-subscriptions'
|
||||
- plugin: 'WordPress SEO' # Yoast SEO in the UI, but the slug is wordpress-seo
|
||||
repo: 'Yoast/wordpress-seo'
|
||||
env_description: 'wordpress-seo'
|
||||
- plugin: 'Contact Form 7'
|
||||
repo: 'takayukister/contact-form-7'
|
||||
env_description: 'contact-form-7'
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup WooCommerce Monorepo
|
||||
uses: ./.github/actions/setup-woocommerce-monorepo
|
||||
|
||||
- name: Launch WP Env
|
||||
working-directory: plugins/woocommerce
|
||||
run: pnpm run env:test
|
||||
|
||||
- name: Download release zip
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.E2E_GH_TOKEN }}
|
||||
run: gh release download ${{ needs.get-tag.outputs.tag }} --dir tmp
|
||||
|
||||
- name: Replace `plugins/woocommerce` with unzipped woocommerce release build
|
||||
run: unzip -d plugins -o tmp/woocommerce.zip
|
||||
|
||||
- name: Run 'Upload plugin' test
|
||||
id: run-upload-test
|
||||
timeout-minutes: 60
|
||||
uses: ./.github/actions/tests/run-e2e-tests
|
||||
with:
|
||||
report-name: ${{ env.ARTIFACT_NAME }}
|
||||
tests: upload-plugin.spec.js
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.E2E_GH_TOKEN }}
|
||||
PLUGIN_NAME: ${{ matrix.plugin }}
|
||||
PLUGIN_REPOSITORY: ${{ matrix.private && secrets[matrix.repo] || matrix.repo }}
|
||||
|
||||
- name: Run the rest of E2E tests
|
||||
id: run-e2e-composite-action
|
||||
timeout-minutes: 60
|
||||
uses: ./.github/actions/tests/run-e2e-tests
|
||||
with:
|
||||
playwright-config: ignore-plugin-tests.playwright.config.js
|
||||
report-name: ${{ env.ARTIFACT_NAME }}
|
||||
env:
|
||||
E2E_MAX_FAILURES: 15
|
||||
|
||||
- name: Upload Allure artifacts to bucket
|
||||
if: |
|
||||
success() ||
|
||||
( failure() &&
|
||||
( steps.run-upload-test.conclusion == 'failure' || steps.run-e2e-composite-action.conclusion == 'failure' ) )
|
||||
uses: ./.github/actions/tests/upload-allure-files-to-bucket
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.REPORTS_AWS_ACCESS_KEY_ID }}
|
||||
aws-region: ${{ secrets.REPORTS_AWS_REGION }}
|
||||
aws-secret-access-key: ${{ secrets.REPORTS_AWS_SECRET_ACCESS_KEY }}
|
||||
artifact-name: ${{ env.ARTIFACT_NAME }}
|
||||
s3-bucket: ${{ secrets.REPORTS_BUCKET }}
|
||||
|
||||
- name: Publish E2E Allure report
|
||||
if: success() || ( failure() && steps.run-e2e-composite-action.conclusion == 'failure' )
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.REPORTS_TOKEN }}
|
||||
run: |
|
||||
gh workflow run publish-test-reports-release.yml \
|
||||
-f created_at="${{ needs.get-tag.outputs.created }}" \
|
||||
-f run_id=${{ github.run_id }} \
|
||||
-f run_number=${{ github.run_number }} \
|
||||
-f release_tag=${{ needs.get-tag.outputs.tag }} \
|
||||
-f artifact="${{ env.ARTIFACT_NAME }}" \
|
||||
-f env_description="${{ matrix.env_description }}" \
|
||||
-f test_type="e2e" \
|
||||
--repo woocommerce/woocommerce-test-reports
|
||||
|
|
|
@ -1,56 +0,0 @@
|
|||
# Duplicate workflow that returns success for this check when there is no relevant file change. See https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/troubleshooting-required-status-checks#handling-skipped-but-required-checks
|
||||
|
||||
name: Status Check Bypass for Changelog Only Changes
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- '!**'
|
||||
- '**/changelog/**'
|
||||
|
||||
jobs:
|
||||
bypass-lint:
|
||||
runs-on: ubuntu-latest
|
||||
name: "Lint and Test JS"
|
||||
steps:
|
||||
- run: 'echo "No build required"'
|
||||
bypass-7-4-latest:
|
||||
runs-on: ubuntu-latest
|
||||
name: "PHP 7.4 WP latest"
|
||||
steps:
|
||||
- run: 'echo "No build required"'
|
||||
bypass-8-0-latest:
|
||||
runs-on: ubuntu-latest
|
||||
name: "PHP 8.0 WP latest"
|
||||
steps:
|
||||
- run: 'echo "No build required"'
|
||||
bypass-api-tests:
|
||||
runs-on: ubuntu-latest
|
||||
name: "Runs API tests."
|
||||
steps:
|
||||
- run: 'echo "No build required"'
|
||||
bypass-k6:
|
||||
runs-on: ubuntu-latest
|
||||
name: "Runs k6 Performance tests"
|
||||
steps:
|
||||
- run: 'echo "No build required"'
|
||||
bypass-sniff:
|
||||
runs-on: ubuntu-latest
|
||||
name: "Code sniff (PHP 7.4, WP Latest)"
|
||||
steps:
|
||||
- run: 'echo "No build required"'
|
||||
bypass-changelogger-use:
|
||||
runs-on: ubuntu-latest
|
||||
name: "Changelogger use"
|
||||
steps:
|
||||
- run: 'echo "No build required"'
|
||||
bypass-e2e:
|
||||
runs-on: ubuntu-latest
|
||||
name: "Runs E2E tests."
|
||||
steps:
|
||||
- run: 'echo "No build required"'
|
||||
bypass-pr-highlight:
|
||||
runs-on: ubuntu-latest
|
||||
name: "Check pull request changes to highlight"
|
||||
steps:
|
||||
- run: 'echo "No build required"'
|
||||
|
13
.syncpackrc
13
.syncpackrc
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"dev": true,
|
||||
"filter": "^(?:config|react|react-dom|eslint|typescript|@typescript-eslint|@types/react|@wordpress|@types/wordpress__components|postcss).*$",
|
||||
"filter": "^(?:config|react|react-dom|eslint|typescript|@typescript-eslint|@types/react|@wordpress|@types/wordpress__components|postcss|@types/node).*$",
|
||||
"indent": "\t",
|
||||
"overrides": true,
|
||||
"peer": true,
|
||||
|
@ -59,7 +59,7 @@
|
|||
"packages": [
|
||||
"**"
|
||||
],
|
||||
"pinVersion": "^4.8.3"
|
||||
"pinVersion": "^4.9.5"
|
||||
},
|
||||
{
|
||||
"dependencies": [
|
||||
|
@ -154,6 +154,15 @@
|
|||
"**"
|
||||
],
|
||||
"pinVersion": "^8.4.7"
|
||||
},
|
||||
{
|
||||
"dependencies": [
|
||||
"@types/node"
|
||||
],
|
||||
"packages": [
|
||||
"**"
|
||||
],
|
||||
"pinVersion": "^16.18.18"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
// Import the default config file and expose it in the project root.
|
||||
// Useful for editor integrations.
|
||||
module.exports = require( '@wordpress/prettier-config' );
|
|
@ -1,5 +1,78 @@
|
|||
== Changelog ==
|
||||
|
||||
= 7.5.1 2023-03-21 =
|
||||
|
||||
**WooCommerce**
|
||||
|
||||
* Fix - Fix no enforcing of min/max limits in quantity selector of variable products. [#36871](https://github.com/woocommerce/woocommerce/pull/36871)
|
||||
* Dev - Update column definitions with synonymous types to prevent dbDelta from trying to ALTER them on each install. [#37277](https://github.com/woocommerce/woocommerce/pull/37277)
|
||||
* Update - Update WooCommerce Blocks to 9.6.6. [#37298](https://github.com/woocommerce/woocommerce/pull/37298)
|
||||
|
||||
= 7.5.0 2023-03-14 =
|
||||
|
||||
**WooCommerce**
|
||||
|
||||
* Fix - Add HPOS support to the reserved stock query [#36535](https://github.com/woocommerce/woocommerce/pull/36535)
|
||||
* Fix - Comment: Fix inconsistencies on Analytics > Orders table when using date_paid or date_completed [#36876](https://github.com/woocommerce/woocommerce/pull/36876)
|
||||
* Fix - Define a public `api` property in the WooCommerce class to prevent a PHP deprecation warning [#36545](https://github.com/woocommerce/woocommerce/pull/36545)
|
||||
* Fix - Don't delete order from posts table when deleted from orders table if the later is authoritative and sync is off [#36617](https://github.com/woocommerce/woocommerce/pull/36617)
|
||||
* Fix - Eliminate data store internal meta keys duplicates [#36611](https://github.com/woocommerce/woocommerce/pull/36611)
|
||||
* Fix - Ensure changes made via the `woocommerce_order_list_table_prepare_items_query_args` are observed. [#36649](https://github.com/woocommerce/woocommerce/pull/36649)
|
||||
* Fix - Ensuring that we know if allowTracking is true before adding exit page. [#36656](https://github.com/woocommerce/woocommerce/pull/36656)
|
||||
* Fix - Fix Ampersand changed to & on product attribute export [#36525](https://github.com/woocommerce/woocommerce/pull/36525)
|
||||
* Fix - Fix decimal points for NOK currency [#36780](https://github.com/woocommerce/woocommerce/pull/36780)
|
||||
* Fix - Fix inconsitent product task icon colors [#36889](https://github.com/woocommerce/woocommerce/pull/36889)
|
||||
* Fix - Fix WordPress unit tests libraries being installed in a symlinked folder structure [#36641](https://github.com/woocommerce/woocommerce/pull/36641)
|
||||
* Fix - Make states optional for Hungary and Bulgaria. [#36701](https://github.com/woocommerce/woocommerce/pull/36701)
|
||||
* Fix - Screen ID matching switched to untranslated 'woocommerce' strings. [#36854](https://github.com/woocommerce/woocommerce/pull/36854)
|
||||
* Fix - Translate the labels for units of measure. [#36708](https://github.com/woocommerce/woocommerce/pull/36708)
|
||||
* Fix - Update `config@3.3.7` (from `3.3.3`). Fix `node_env_var_name is not defined` error. [#33828](https://github.com/woocommerce/woocommerce/pull/33828)
|
||||
* Add - Add 'add_tab' method in FormFactory to allow plugins to extend the WooCommerce admin product form [#36583](https://github.com/woocommerce/woocommerce/pull/36583)
|
||||
* Add - Add @woocommerce/product-editor dependency and change dependency of ProductSectionLayout component. [#36600](https://github.com/woocommerce/woocommerce/pull/36600)
|
||||
* Add - Add additional global attributes and local attributes information when saving product attributes [#36858](https://github.com/woocommerce/woocommerce/pull/36858)
|
||||
* Add - Add a new Channels card in multichannel marketing page. [#36541](https://github.com/woocommerce/woocommerce/pull/36541)
|
||||
* Add - Add an experimental slot for marketing overview extensibility [#36828](https://github.com/woocommerce/woocommerce/pull/36828)
|
||||
* Add - Add slot fill support for tabs for the new product management MVP. [#36551](https://github.com/woocommerce/woocommerce/pull/36551)
|
||||
* Add - Add survey after disabling new experience [#36544](https://github.com/woocommerce/woocommerce/pull/36544)
|
||||
* Add - Add unique sku option to error data when setting product sku [#36612](https://github.com/woocommerce/woocommerce/pull/36612)
|
||||
* Add - Add WC-specific criteria to the Site Health test for persistent object caches [#35202](https://github.com/woocommerce/woocommerce/pull/35202)
|
||||
* Add - Enable new experience when new user selects "Physical product". [#36406](https://github.com/woocommerce/woocommerce/pull/36406)
|
||||
* Update - Update WooCommerce Blocks to 9.6.5 [#37051](https://github.com/woocommerce/woocommerce/pull/37051)
|
||||
* Update - Update WooCommerce Blocks to 9.6.3 [#36992](https://github.com/woocommerce/woocommerce/pull/36992)
|
||||
* Update - Update WooCommerce Blocks to 9.6.2 [#36919](https://github.com/woocommerce/woocommerce/pull/36919)
|
||||
* Update - Add date_paid and date_completed date sorting options for Revenue and Order reports [#36492](https://github.com/woocommerce/woocommerce/pull/36492)
|
||||
* Update - Add default value for backorders [#36607](https://github.com/woocommerce/woocommerce/pull/36607)
|
||||
* Update - Add Skydropx, Envia, Sendcloud, Packlink to shipping task [#36873](https://github.com/woocommerce/woocommerce/pull/36873)
|
||||
* Update - Always show comments for product feedback form [#36484](https://github.com/woocommerce/woocommerce/pull/36484)
|
||||
* Update - Delete FlexSlider code for legacy browsers. [#36690](https://github.com/woocommerce/woocommerce/pull/36690)
|
||||
* Update - Disable the new product editor, pending design updates. [#36894](https://github.com/woocommerce/woocommerce/pull/36894)
|
||||
* Update - Have "Grow your store" appear first in marketing task by default [#36826](https://github.com/woocommerce/woocommerce/pull/36826)
|
||||
* Update - Migrating product editor pricing section to slot fills. [#36500](https://github.com/woocommerce/woocommerce/pull/36500)
|
||||
* Update - Refactor slot fills to ensure variant fills have distinct slots. [#36646](https://github.com/woocommerce/woocommerce/pull/36646)
|
||||
* Update - Removed I.D column from product import samples [#36857](https://github.com/woocommerce/woocommerce/pull/36857)
|
||||
* Update - Remove Meta from grow your store list [#36886](https://github.com/woocommerce/woocommerce/pull/36886)
|
||||
* Update - Remove opinionated styles from buttons in block themes so they inherit theme styles more accurately [#36651](https://github.com/woocommerce/woocommerce/pull/36651)
|
||||
* Update - Replace $.ajax() calls with browser-native window.fetch() calls. [#36275](https://github.com/woocommerce/woocommerce/pull/36275)
|
||||
* Update - Update payment gateway list ordering priority and remove Klarna from North America [#36550](https://github.com/woocommerce/woocommerce/pull/36550)
|
||||
* Update - Update Playwright version from 1.28.0 -> 1.30.0 [#36789](https://github.com/woocommerce/woocommerce/pull/36789)
|
||||
* Update - Updates to product editor fill to support new prop API. [#36592](https://github.com/woocommerce/woocommerce/pull/36592)
|
||||
* Update - Update WooCommerce Blocks 9.6.0 & 9.6.1 [#36852](https://github.com/woocommerce/woocommerce/pull/36852)
|
||||
* Dev - Add attribute creation form when there are no attributes [#36606](https://github.com/woocommerce/woocommerce/pull/36606)
|
||||
* Dev - Add a unit test for woocommerce_admin_experimental_onboarding_tasklists filter [#36827](https://github.com/woocommerce/woocommerce/pull/36827)
|
||||
* Dev - Code refactor on marketing components. [#36540](https://github.com/woocommerce/woocommerce/pull/36540)
|
||||
* Dev - Made e2e selectors more robust [#36499](https://github.com/woocommerce/woocommerce/pull/36499)
|
||||
* Dev - Remove attribute type logic from attribute component [#36563](https://github.com/woocommerce/woocommerce/pull/36563)
|
||||
* Dev - Update eslint to 8.32.0 across the monorepo. [#36700](https://github.com/woocommerce/woocommerce/pull/36700)
|
||||
* Dev - Update pnpm command to run e2e tests for consistency. Also update docs with new command. [#35287](https://github.com/woocommerce/woocommerce/pull/35287)
|
||||
* Tweak - Add IR and fields priorities to list of get_country_locale() method to follow conventional way of addressing in Iran. [#36491](https://github.com/woocommerce/woocommerce/pull/36491)
|
||||
* Tweak - Add missing deprecation notice for filter hook woocommerce_my_account_my_orders_columns. [#36356](https://github.com/woocommerce/woocommerce/pull/36356)
|
||||
* Tweak - Adjust default sizes for the quantity and coupon input fields within the cart page. [#29122](https://github.com/woocommerce/woocommerce/pull/29122)
|
||||
* Tweak - Do not display low/out-of-stock information in the dashboard status widget when stock management is disabled. [#36703](https://github.com/woocommerce/woocommerce/pull/36703)
|
||||
* Tweak - Remove free trial terms from Avalara tax task [#36888](https://github.com/woocommerce/woocommerce/pull/36888)
|
||||
* Tweak - Tweak product link description and display in the new product management experience [#36591](https://github.com/woocommerce/woocommerce/pull/36591)
|
||||
* Enhancement - Change the sass variable names to more predictable ones. [#28908](https://github.com/woocommerce/woocommerce/pull/28908)
|
||||
|
||||
|
||||
= 7.4.1 2023-03-01 =
|
||||
|
||||
**WooCommerce**
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
|
||||
Fix the incorrect workflow input for uploading Allure reports.
|
44
package.json
44
package.json
|
@ -3,6 +3,10 @@
|
|||
"title": "WooCommerce Monorepo",
|
||||
"description": "Monorepo for the WooCommerce ecosystem",
|
||||
"homepage": "https://woocommerce.com/",
|
||||
"engines": {
|
||||
"node": "^16.13.1",
|
||||
"pnpm": "^7.13.3"
|
||||
},
|
||||
"private": true,
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -25,41 +29,41 @@
|
|||
"sync-dependencies": "pnpm exec syncpack -- fix-mismatches"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/preset-env": "^7.16.11",
|
||||
"@babel/runtime": "^7.17.2",
|
||||
"@types/node": "14.14.33",
|
||||
"@babel/preset-env": "^7.20.2",
|
||||
"@babel/runtime": "^7.21.0",
|
||||
"@types/node": "^16.18.18",
|
||||
"@woocommerce/eslint-plugin": "workspace:*",
|
||||
"@wordpress/data": "wp-6.0",
|
||||
"@wordpress/eslint-plugin": "^11.1.0",
|
||||
"@wordpress/prettier-config": "^1.1.1",
|
||||
"babel-loader": "^8.2.3",
|
||||
"@wordpress/prettier-config": "^1.4.0",
|
||||
"babel-loader": "^8.3.0",
|
||||
"chalk": "^4.1.2",
|
||||
"copy-webpack-plugin": "^10.2.4",
|
||||
"core-js": "^3.21.1",
|
||||
"css-loader": "^6.7.0",
|
||||
"glob": "^7.2.0",
|
||||
"core-js": "^3.29.1",
|
||||
"css-loader": "^6.7.3",
|
||||
"glob": "^7.2.3",
|
||||
"husky": "^7.0.4",
|
||||
"jest": "^27.3.1",
|
||||
"lint-staged": "^12.3.7",
|
||||
"jest": "^27.5.1",
|
||||
"lint-staged": "^12.5.0",
|
||||
"mkdirp": "^1.0.4",
|
||||
"moment": "^2.29.1",
|
||||
"moment": "^2.29.4",
|
||||
"node-stream-zip": "^1.15.0",
|
||||
"postcss-loader": "^4.3.0",
|
||||
"prettier": "npm:wp-prettier@^2.2.1-beta-1",
|
||||
"regenerator-runtime": "^0.13.9",
|
||||
"prettier": "npm:wp-prettier@^2.6.2",
|
||||
"regenerator-runtime": "^0.13.11",
|
||||
"request": "^2.88.2",
|
||||
"sass": "^1.49.9",
|
||||
"sass-loader": "^10.2.1",
|
||||
"sass": "^1.59.3",
|
||||
"sass-loader": "^10.4.1",
|
||||
"syncpack": "^9.8.4",
|
||||
"turbo": "^1.7.0",
|
||||
"typescript": "^4.8.3",
|
||||
"turbo": "^1.8.5",
|
||||
"typescript": "^4.9.5",
|
||||
"url-loader": "^1.1.2",
|
||||
"webpack": "^5.70.0"
|
||||
"webpack": "^5.76.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/core": "7.12.9",
|
||||
"@wordpress/babel-plugin-import-jsx-pragma": "^3.1.0",
|
||||
"@wordpress/babel-preset-default": "^6.4.1",
|
||||
"@wordpress/babel-plugin-import-jsx-pragma": "^3.2.0",
|
||||
"@wordpress/babel-preset-default": "^6.17.0",
|
||||
"lodash": "^4.17.21",
|
||||
"wp-textdomain": "1.0.1"
|
||||
},
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
Comment: TypeScript build change
|
||||
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
Comment: Configuration change only
|
||||
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: update
|
||||
|
||||
Update showOtherPaymentMethods() to test latest payment task properly
|
|
@ -50,18 +50,18 @@
|
|||
"jest-mock-extended": "^1.0.18",
|
||||
"rimraf": "^3.0.2",
|
||||
"ts-jest": "^27.1.3",
|
||||
"typescript": "^4.8.3"
|
||||
"typescript": "^4.9.5"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"scripts": {
|
||||
"turbo:build": "tsc --build",
|
||||
"turbo:build": "tsc --project tsconfig.json",
|
||||
"prepare": "composer install",
|
||||
"changelog": "composer exec -- changelogger",
|
||||
"build": "pnpm -w exec turbo run turbo:build --filter=$npm_package_name",
|
||||
"lint": "eslint src",
|
||||
"start": "tsc --build --watch",
|
||||
"start": "tsc --project tsconfig.json --watch",
|
||||
"clean": "pnpm exec rimraf tsconfig.tsbuildinfo build build-*",
|
||||
"lint:fix": "eslint src --fix",
|
||||
"prepack": "pnpm run clean && pnpm run build"
|
||||
|
|
|
@ -31,12 +31,6 @@ export class PaymentsSetup extends BasePage {
|
|||
}
|
||||
|
||||
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' );
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
{
|
||||
"extends": "../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"rootDir": "src",
|
||||
"outDir": "build"
|
||||
"outDir": "build",
|
||||
"typeRoots": [
|
||||
"./typings",
|
||||
"./node_modules/@types"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Significance: minor
|
||||
Type: add
|
||||
|
||||
Adding support for modifying fill name to WooHeaderItem.
|
|
@ -0,0 +1,5 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
Comment: TypeScript build change
|
||||
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
Comment: Configuration change only
|
||||
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
|
||||
Update webpack config to use @woocommerce/internal-style-build's parser config
|
|
@ -34,9 +34,9 @@
|
|||
"clean": "pnpm exec rimraf tsconfig.tsbuildinfo build build-*",
|
||||
"build": "pnpm -w exec turbo run turbo:build --filter=$npm_package_name",
|
||||
"lint": "eslint src",
|
||||
"build:js": "tsc --build ./tsconfig.json ./tsconfig-cjs.json",
|
||||
"build:js": "tsc --project tsconfig.json && tsc --project tsconfig-cjs.json",
|
||||
"build:css": "webpack",
|
||||
"start": "concurrently \"tsc --build --watch\" \"webpack --watch\"",
|
||||
"start": "concurrently \"tsc --project tsconfig.json --watch\" \"tsc --project tsconfig-cjs.json --watch\" \"webpack --watch\"",
|
||||
"prepack": "pnpm run clean && pnpm run build",
|
||||
"lint:fix": "eslint src --fix"
|
||||
},
|
||||
|
@ -50,12 +50,13 @@
|
|||
"eslint": "^8.32.0",
|
||||
"jest": "^27.5.1",
|
||||
"jest-cli": "^27.5.1",
|
||||
"concurrently": "^7.0.0",
|
||||
"postcss-loader": "^4.3.0",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"sass-loader": "^10.2.1",
|
||||
"ts-jest": "^27.1.3",
|
||||
"typescript": "^4.8.3",
|
||||
"typescript": "^4.9.5",
|
||||
"webpack": "^5.70.0",
|
||||
"webpack-cli": "^3.3.12"
|
||||
},
|
||||
|
|
|
@ -11,6 +11,20 @@ import {
|
|||
|
||||
export const WC_HEADER_SLOT_NAME = 'woocommerce_header_item';
|
||||
|
||||
/**
|
||||
* Get the slot fill name for the generic header slot or a specific header if provided.
|
||||
*
|
||||
* @param name Name of the specific header.
|
||||
* @return string
|
||||
*/
|
||||
const getSlotFillName = ( name?: string ) => {
|
||||
if ( ! name || ! name.length ) {
|
||||
return WC_HEADER_SLOT_NAME;
|
||||
}
|
||||
|
||||
return `${ WC_HEADER_SLOT_NAME }/${ name }`;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a Fill for extensions to add items to the WooCommerce Admin header.
|
||||
*
|
||||
|
@ -26,17 +40,19 @@ export const WC_HEADER_SLOT_NAME = 'woocommerce_header_item';
|
|||
* scope: 'woocommerce-admin',
|
||||
* } );
|
||||
* @param {Object} param0
|
||||
* @param {Array} param0.name - Header name.
|
||||
* @param {Array} param0.children - Node children.
|
||||
* @param {Array} param0.order - Node order.
|
||||
*/
|
||||
export const WooHeaderItem: React.FC< {
|
||||
name?: string;
|
||||
children?: React.ReactNode;
|
||||
order?: number;
|
||||
} > & {
|
||||
Slot: React.FC< Slot.Props >;
|
||||
} = ( { children, order = 1 } ) => {
|
||||
Slot: React.FC< Slot.Props & { name?: string } >;
|
||||
} = ( { children, order = 1, name = '' } ) => {
|
||||
return (
|
||||
<Fill name={ WC_HEADER_SLOT_NAME }>
|
||||
<Fill name={ getSlotFillName( name ) }>
|
||||
{ ( fillProps: Fill.Props ) => {
|
||||
return createOrderedChildren( children, order, fillProps );
|
||||
} }
|
||||
|
@ -44,8 +60,8 @@ export const WooHeaderItem: React.FC< {
|
|||
);
|
||||
};
|
||||
|
||||
WooHeaderItem.Slot = ( { fillProps } ) => (
|
||||
<Slot name={ WC_HEADER_SLOT_NAME } fillProps={ fillProps }>
|
||||
WooHeaderItem.Slot = ( { fillProps, name = '' } ) => (
|
||||
<Slot name={ getSlotFillName( name ) } fillProps={ fillProps }>
|
||||
{ sortFillsByOrder }
|
||||
</Slot>
|
||||
);
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
{
|
||||
"extends": "../tsconfig-cjs",
|
||||
"compilerOptions": {
|
||||
"outDir": "build"
|
||||
"outDir": "build",
|
||||
"typeRoots": [
|
||||
"./typings",
|
||||
"./node_modules/@types"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,10 @@
|
|||
"outDir": "build-module",
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"declarationDir": "./build-types"
|
||||
"declarationDir": "./build-types",
|
||||
"typeRoots": [
|
||||
"./typings",
|
||||
"./node_modules/@types"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ module.exports = {
|
|||
path: __dirname,
|
||||
},
|
||||
module: {
|
||||
parser: webpackConfig.parser,
|
||||
rules: webpackConfig.rules,
|
||||
},
|
||||
plugins: webpackConfig.plugins,
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
Comment: TypeScript build change
|
||||
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
Comment: Configuration change only
|
||||
|
||||
|
|
@ -36,7 +36,7 @@
|
|||
"prepare": "composer install",
|
||||
"changelog": "composer exec -- changelogger",
|
||||
"clean": "rm -rf ./dist ./tsconfig.tsbuildinfo",
|
||||
"compile": "tsc -b",
|
||||
"compile": "tsc --project tsconfig.json",
|
||||
"prepack": "pnpm run build",
|
||||
"build": "pnpm -w exec turbo run turbo:build --filter=$npm_package_name",
|
||||
"lint": "eslint src",
|
||||
|
@ -50,7 +50,7 @@
|
|||
"devDependencies": {
|
||||
"@types/create-hmac": "1.1.0",
|
||||
"@types/jest": "^27.4.1",
|
||||
"@types/node": "13.13.5",
|
||||
"@types/node": "^16.18.18",
|
||||
"@typescript-eslint/eslint-plugin": "^5.54.0",
|
||||
"@typescript-eslint/parser": "^5.54.0",
|
||||
"@woocommerce/eslint-plugin": "workspace:*",
|
||||
|
@ -58,7 +58,7 @@
|
|||
"eslint": "^8.32.0",
|
||||
"jest": "^27",
|
||||
"ts-jest": "^27",
|
||||
"typescript": "^4.8.3"
|
||||
"typescript": "^4.9.5"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
|
|
|
@ -4,7 +4,11 @@
|
|||
"types": [ "node", "jest", "axios", "create-hmac" ],
|
||||
"rootDir": "src",
|
||||
"outDir": "dist",
|
||||
"target": "es5"
|
||||
"target": "es5",
|
||||
"typeRoots": [
|
||||
"./typings",
|
||||
"./node_modules/@types"
|
||||
]
|
||||
},
|
||||
"include": [ "src/" ]
|
||||
}
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Significance: minor
|
||||
Type: add
|
||||
|
||||
Adding simple DisplayState wrapper and modifying Collapsible component to allow rendering hidden content.
|
|
@ -0,0 +1,4 @@
|
|||
Significance: minor
|
||||
Type: add
|
||||
|
||||
Create SelectTree component that uses TreeControl
|
|
@ -0,0 +1,4 @@
|
|||
Significance: minor
|
||||
Type: fix
|
||||
|
||||
Prevent duplicate registration of core blocks in client
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
|
||||
Update TourKit README to correct primaryButton example and formatting.
|
|
@ -0,0 +1,5 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
Comment: TypeScript build change
|
||||
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
Comment: Configuration change only
|
||||
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
Comment: Configuration change only
|
||||
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
Significance: minor
|
||||
Type: update
|
||||
|
||||
Apply wccom experimental select control changes
|
|
@ -0,0 +1,5 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
Comment: Add unit tests
|
||||
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
|
||||
Update webpack config to use @woocommerce/internal-style-build's parser config
|
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
"rootDir": "./src",
|
||||
"preset": "../../internal-js-tests/jest.config.js"
|
||||
"preset": "../node_modules/@woocommerce/internal-js-tests/jest-preset.js"
|
||||
}
|
||||
|
|
|
@ -128,6 +128,7 @@
|
|||
"@types/wordpress__viewport": "^2.5.4",
|
||||
"@woocommerce/eslint-plugin": "workspace:*",
|
||||
"@woocommerce/internal-style-build": "workspace:*",
|
||||
"@woocommerce/internal-js-tests": "workspace:*",
|
||||
"@wordpress/browserslist-config": "wp-6.0",
|
||||
"@wordpress/scripts": "^12.6.1",
|
||||
"concurrently": "^7.0.0",
|
||||
|
@ -141,7 +142,7 @@
|
|||
"rimraf": "^3.0.2",
|
||||
"sass-loader": "^10.2.1",
|
||||
"ts-jest": "^27.1.3",
|
||||
"typescript": "^4.8.3",
|
||||
"typescript": "^4.9.5",
|
||||
"uuid": "^8.3.0",
|
||||
"webpack": "^5.70.0",
|
||||
"webpack-cli": "^3.3.12"
|
||||
|
@ -154,12 +155,12 @@
|
|||
"build": "pnpm -w exec turbo run turbo:build --filter=$npm_package_name",
|
||||
"test": "pnpm -w exec turbo run turbo:test --filter=$npm_package_name",
|
||||
"lint": "eslint src --ext=js,ts,tsx",
|
||||
"build:js": "tsc --build ./tsconfig.json ./tsconfig-cjs.json",
|
||||
"build:js": "tsc --project tsconfig.json && tsc --project tsconfig-cjs.json",
|
||||
"build:css": "webpack",
|
||||
"clean": "pnpm exec rimraf tsconfig.tsbuildinfo build build-*",
|
||||
"lint:fix": "eslint src --ext=js,ts,tsx --fix",
|
||||
"prepack": "pnpm run clean && pnpm run build",
|
||||
"start": "concurrently \"tsc --build ./tsconfig.json --watch\" \"webpack --watch\"",
|
||||
"start": "concurrently \"tsc --project tsconfig.json --watch\" \"tsc --project tsconfig-cjs.json --watch\" \"webpack --watch\"",
|
||||
"test:update-snapshots": "pnpm run test -- --updateSnapshot",
|
||||
"test-staged": "jest --bail --config ./jest.config.json --findRelatedTests"
|
||||
},
|
||||
|
|
|
@ -7,10 +7,12 @@ import { Icon, chevronDown, chevronUp } from '@wordpress/icons';
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { DisplayState } from '../display-state';
|
||||
|
||||
export type CollapsedProps = {
|
||||
initialCollapsed?: boolean;
|
||||
toggleText: string;
|
||||
persistRender?: boolean;
|
||||
children: React.ReactNode;
|
||||
} & React.HTMLAttributes< HTMLDivElement >;
|
||||
|
||||
|
@ -18,9 +20,19 @@ export const CollapsibleContent: React.FC< CollapsedProps > = ( {
|
|||
initialCollapsed = true,
|
||||
toggleText,
|
||||
children,
|
||||
persistRender = false,
|
||||
...props
|
||||
}: CollapsedProps ) => {
|
||||
const [ collapsed, setCollapsed ] = useState( initialCollapsed );
|
||||
|
||||
const getState = () => {
|
||||
if ( ! collapsed ) {
|
||||
return 'visible';
|
||||
}
|
||||
|
||||
return persistRender ? 'visually-hidden' : 'hidden';
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
aria-expanded={ collapsed ? 'false' : 'true' }
|
||||
|
@ -38,14 +50,14 @@ export const CollapsibleContent: React.FC< CollapsedProps > = ( {
|
|||
/>
|
||||
</div>
|
||||
</button>
|
||||
{ ! collapsed && (
|
||||
<DisplayState state={ getState() }>
|
||||
<div
|
||||
{ ...props }
|
||||
className="woocommerce-collapsible-content__content"
|
||||
>
|
||||
{ children }
|
||||
</div>
|
||||
) }
|
||||
</DisplayState>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { createElement, Fragment } from '@wordpress/element';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
|
||||
export type DisplayStateProps = {
|
||||
state?: 'visible' | 'visually-hidden' | 'hidden';
|
||||
children: React.ReactNode;
|
||||
} & React.HTMLAttributes< HTMLDivElement >;
|
||||
|
||||
export const DisplayState: React.FC< DisplayStateProps > = ( {
|
||||
state = 'visible',
|
||||
children,
|
||||
} ) => {
|
||||
if ( state === 'visible' ) {
|
||||
return <>{ children }</>;
|
||||
}
|
||||
|
||||
if ( state === 'visually-hidden' ) {
|
||||
return <div style={ { display: 'none' } }>{ children }</div>;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
|
@ -0,0 +1 @@
|
|||
export * from './display-state';
|
|
@ -44,3 +44,18 @@
|
|||
.woocommerce-experimental-select-control__suffix {
|
||||
align-self: stretch;
|
||||
}
|
||||
|
||||
.woocommerce-experimental-select-control__combox-box-toggle-button {
|
||||
all: unset;
|
||||
position: absolute;
|
||||
right: 6px;
|
||||
top: 50%;
|
||||
transform: translateY( -50% );
|
||||
> svg {
|
||||
margin-top: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.woocommerce-experimental-select-control:not( .is-focused ) .woocommerce-experimental-select-control__combox-box-toggle-button {
|
||||
pointer-events: none; // Prevents the icon from being clickable when the combobox is not focused, because otherwise we get a race condition when clicking on the icon, because focussing the combobox opens the menu, then sequentially the icon toggles it back closed
|
||||
}
|
||||
|
|
|
@ -1,26 +1,42 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { createElement, MouseEvent, useRef } from 'react';
|
||||
import { createElement, MouseEvent, useRef, forwardRef } from 'react';
|
||||
import classNames from 'classnames';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { Props } from './types';
|
||||
import { Icon, chevronDown } from '@wordpress/icons';
|
||||
|
||||
type ComboBoxProps = {
|
||||
children?: JSX.Element | JSX.Element[] | null;
|
||||
comboBoxProps: Props;
|
||||
inputProps: Props;
|
||||
comboBoxProps: JSX.IntrinsicElements[ 'div' ];
|
||||
inputProps: JSX.IntrinsicElements[ 'input' ];
|
||||
getToggleButtonProps?: () => Omit<
|
||||
JSX.IntrinsicElements[ 'button' ],
|
||||
'ref'
|
||||
>;
|
||||
suffix?: JSX.Element | null;
|
||||
showToggleButton?: boolean;
|
||||
};
|
||||
|
||||
const ToggleButton = forwardRef< HTMLButtonElement >( ( props, ref ) => {
|
||||
// using forwardRef here because getToggleButtonProps injects a ref prop
|
||||
return (
|
||||
<button
|
||||
className="woocommerce-experimental-select-control__combox-box-toggle-button"
|
||||
{ ...props }
|
||||
ref={ ref }
|
||||
>
|
||||
<Icon icon={ chevronDown } />
|
||||
</button>
|
||||
);
|
||||
} );
|
||||
|
||||
export const ComboBox = ( {
|
||||
children,
|
||||
comboBoxProps,
|
||||
getToggleButtonProps = () => ( {} ),
|
||||
inputProps,
|
||||
suffix,
|
||||
showToggleButton,
|
||||
}: ComboBoxProps ) => {
|
||||
const inputRef = useRef< HTMLInputElement | null >( null );
|
||||
|
||||
|
@ -60,12 +76,14 @@ export const ComboBox = ( {
|
|||
<input
|
||||
{ ...inputProps }
|
||||
ref={ ( node ) => {
|
||||
inputRef.current = node;
|
||||
(
|
||||
inputProps.ref as unknown as (
|
||||
node: HTMLInputElement | null
|
||||
) => void
|
||||
)( node );
|
||||
if ( typeof inputProps.ref === 'function' ) {
|
||||
inputRef.current = node;
|
||||
(
|
||||
inputProps.ref as unknown as (
|
||||
node: HTMLInputElement | null
|
||||
) => void
|
||||
)( node );
|
||||
}
|
||||
} }
|
||||
/>
|
||||
</div>
|
||||
|
@ -75,6 +93,9 @@ export const ComboBox = ( {
|
|||
{ suffix }
|
||||
</div>
|
||||
) }
|
||||
{ showToggleButton && (
|
||||
<ToggleButton { ...getToggleButtonProps() } />
|
||||
) }
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { createElement, ReactElement } from 'react';
|
||||
import { createElement, CSSProperties, ReactElement } from 'react';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
|
@ -14,6 +14,7 @@ export type MenuItemProps< ItemType > = {
|
|||
item: ItemType;
|
||||
children: ReactElement | string;
|
||||
getItemProps: getItemPropsType< ItemType >;
|
||||
activeStyle?: CSSProperties;
|
||||
};
|
||||
|
||||
export const MenuItem = < ItemType, >( {
|
||||
|
@ -21,11 +22,12 @@ export const MenuItem = < ItemType, >( {
|
|||
getItemProps,
|
||||
index,
|
||||
isActive,
|
||||
activeStyle = { backgroundColor: '#bde4ff' },
|
||||
item,
|
||||
}: MenuItemProps< ItemType > ) => {
|
||||
return (
|
||||
<li
|
||||
style={ isActive ? { backgroundColor: '#bde4ff' } : {} }
|
||||
style={ isActive ? activeStyle : {} }
|
||||
{ ...getItemProps( { item, index } ) }
|
||||
className="woocommerce-experimental-select-control__menu-item"
|
||||
>
|
||||
|
|
|
@ -22,6 +22,8 @@ type MenuProps = {
|
|||
getMenuProps: getMenuPropsType;
|
||||
isOpen: boolean;
|
||||
className?: string;
|
||||
position?: Popover.Position;
|
||||
scrollIntoViewOnOpen?: boolean;
|
||||
};
|
||||
|
||||
export const Menu = ( {
|
||||
|
@ -29,6 +31,8 @@ export const Menu = ( {
|
|||
getMenuProps,
|
||||
isOpen,
|
||||
className,
|
||||
position = 'bottom right',
|
||||
scrollIntoViewOnOpen = false,
|
||||
}: MenuProps ) => {
|
||||
const [ boundingRect, setBoundingRect ] = useState< DOMRect >();
|
||||
const selectControlMenuRef = useRef< HTMLDivElement >( null );
|
||||
|
@ -41,6 +45,13 @@ export const Menu = ( {
|
|||
}
|
||||
}, [ selectControlMenuRef.current ] );
|
||||
|
||||
// Scroll the selected item into view when the menu opens.
|
||||
useEffect( () => {
|
||||
if ( isOpen && scrollIntoViewOnOpen ) {
|
||||
selectControlMenuRef.current?.scrollIntoView();
|
||||
}
|
||||
}, [ isOpen, scrollIntoViewOnOpen ] );
|
||||
|
||||
/* eslint-disable jsx-a11y/no-noninteractive-element-interactions, jsx-a11y/click-events-have-key-events */
|
||||
/* Disabled because of the onmouseup on the ul element below. */
|
||||
return (
|
||||
|
@ -60,7 +71,7 @@ export const Menu = ( {
|
|||
'has-results': Children.count( children ) > 0,
|
||||
}
|
||||
) }
|
||||
position="bottom right"
|
||||
position={ position }
|
||||
animate={ false }
|
||||
>
|
||||
<ul
|
||||
|
|
|
@ -68,6 +68,7 @@ export type SelectControlProps< ItemType > = {
|
|||
disabled?: boolean;
|
||||
inputProps?: GetInputPropsOptions;
|
||||
suffix?: JSX.Element | null;
|
||||
showToggleButton?: boolean;
|
||||
/**
|
||||
* This is a feature already implemented in downshift@7.0.0 through the
|
||||
* reducer. In order for us to use it this prop is added temporarily until
|
||||
|
@ -123,6 +124,7 @@ function SelectControl< ItemType = DefaultItemType >( {
|
|||
disabled,
|
||||
inputProps = {},
|
||||
suffix = <SuffixIcon icon={ search } />,
|
||||
showToggleButton = false,
|
||||
__experimentalOpenMenuOnFocus = false,
|
||||
}: SelectControlProps< ItemType > ) {
|
||||
const [ isFocused, setIsFocused ] = useState( false );
|
||||
|
@ -154,12 +156,13 @@ function SelectControl< ItemType = DefaultItemType >( {
|
|||
}
|
||||
|
||||
setInputValue( getItemLabel( singleSelectedItem ) );
|
||||
}, [ singleSelectedItem ] );
|
||||
}, [ getItemLabel, multiple, singleSelectedItem ] );
|
||||
|
||||
const {
|
||||
isOpen,
|
||||
getLabelProps,
|
||||
getMenuProps,
|
||||
getToggleButtonProps,
|
||||
getInputProps,
|
||||
getComboboxProps,
|
||||
highlightedIndex,
|
||||
|
@ -256,6 +259,7 @@ function SelectControl< ItemType = DefaultItemType >( {
|
|||
{ /* eslint-enable jsx-a11y/label-has-for */ }
|
||||
<ComboBox
|
||||
comboBoxProps={ getComboboxProps() }
|
||||
getToggleButtonProps={ getToggleButtonProps }
|
||||
inputProps={ getInputProps( {
|
||||
...getDropdownProps( {
|
||||
preventKeyAction: isOpen,
|
||||
|
@ -274,6 +278,7 @@ function SelectControl< ItemType = DefaultItemType >( {
|
|||
...inputProps,
|
||||
} ) }
|
||||
suffix={ suffix }
|
||||
showToggleButton={ showToggleButton }
|
||||
>
|
||||
<>
|
||||
{ children( {
|
||||
|
|
|
@ -573,6 +573,24 @@ export const CustomSuffix: React.FC = () => {
|
|||
);
|
||||
};
|
||||
|
||||
export const ToggleButton: React.FC = () => {
|
||||
const [ selected, setSelected ] =
|
||||
useState< SelectedType< DefaultItemType > >();
|
||||
|
||||
return (
|
||||
<SelectControl
|
||||
items={ sampleItems }
|
||||
label="Has toggle button"
|
||||
selected={ selected }
|
||||
onSelect={ ( item ) => item && setSelected( item ) }
|
||||
onRemove={ () => setSelected( null ) }
|
||||
suffix={ null }
|
||||
showToggleButton={ true }
|
||||
__experimentalOpenMenuOnFocus={ true }
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default {
|
||||
title: 'WooCommerce Admin/experimental/SelectControl',
|
||||
component: SelectControl,
|
||||
|
|
|
@ -16,7 +16,8 @@ export type DefaultItemType = {
|
|||
export type SelectedType< ItemType > = ItemType | null;
|
||||
|
||||
export type Props = {
|
||||
[ key: string ]: string;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
[ key: string ]: any;
|
||||
};
|
||||
|
||||
export type getItemPropsType< ItemType > = (
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
export * from './select-tree';
|
|
@ -0,0 +1,15 @@
|
|||
.woocommerce-experimental-select-control__combo-box-wrapper {
|
||||
&:focus {
|
||||
box-shadow: 0 0 0 1px var( --wp-admin-theme-color );
|
||||
border-color: var( --wp-admin-theme-color );
|
||||
}
|
||||
}
|
||||
|
||||
.woocommerce-experimental-select-tree-control__dropdown {
|
||||
display: block;
|
||||
}
|
||||
|
||||
// That's the only way I could remove the padding from the @wordpress/components Dropdown.
|
||||
.woocommerce-experimental-select-tree-control__dropdown-content .components-popover__content {
|
||||
padding: 0;
|
||||
}
|
|
@ -0,0 +1,199 @@
|
|||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { createElement, useRef, useState } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { search } from '@wordpress/icons';
|
||||
import { Dropdown, Spinner } from '@wordpress/components';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { useLinkedTree } from '../experimental-tree-control/hooks/use-linked-tree';
|
||||
import { Tree } from '../experimental-tree-control/tree';
|
||||
import {
|
||||
Item,
|
||||
LinkedTree,
|
||||
TreeControlProps,
|
||||
} from '../experimental-tree-control/types';
|
||||
import { SelectedItems } from '../experimental-select-control/selected-items';
|
||||
import { ComboBox } from '../experimental-select-control/combo-box';
|
||||
import { SuffixIcon } from '../experimental-select-control/suffix-icon';
|
||||
|
||||
interface SelectTreeProps extends TreeControlProps {
|
||||
id: string;
|
||||
selected?: Item[];
|
||||
getSelectedItemProps?: any;
|
||||
treeRef?: React.ForwardedRef< HTMLOListElement >;
|
||||
suffix?: JSX.Element | null;
|
||||
isLoading?: boolean;
|
||||
label: string | JSX.Element;
|
||||
onInputChange?: ( value: string | undefined ) => void;
|
||||
}
|
||||
|
||||
export const SelectTree = function SelectTree( {
|
||||
items,
|
||||
getSelectedItemProps,
|
||||
treeRef: ref,
|
||||
suffix = <SuffixIcon icon={ search } />,
|
||||
placeholder,
|
||||
isLoading,
|
||||
onInputChange,
|
||||
shouldShowCreateButton,
|
||||
...props
|
||||
}: SelectTreeProps ) {
|
||||
const linkedTree = useLinkedTree( items );
|
||||
|
||||
const [ isFocused, setIsFocused ] = useState( false );
|
||||
|
||||
const comboBoxRef = useRef< HTMLDivElement >( null );
|
||||
|
||||
// getting the parent's parent div width to set the width of the dropdown
|
||||
const comboBoxWidth =
|
||||
comboBoxRef.current?.parentElement?.parentElement?.getBoundingClientRect()
|
||||
.width;
|
||||
|
||||
const shouldItemBeExpanded = ( item: LinkedTree ): boolean => {
|
||||
if ( ! props.createValue || ! item.children?.length ) return false;
|
||||
return item.children.some( ( child ) => {
|
||||
if (
|
||||
new RegExp( props.createValue || '', 'ig' ).test(
|
||||
child.data.label
|
||||
)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return shouldItemBeExpanded( child );
|
||||
} );
|
||||
};
|
||||
|
||||
return (
|
||||
<Dropdown
|
||||
className="woocommerce-experimental-select-tree-control__dropdown"
|
||||
contentClassName="woocommerce-experimental-select-tree-control__dropdown-content"
|
||||
focusOnMount={ false }
|
||||
renderContent={ ( { onClose } ) =>
|
||||
isLoading ? (
|
||||
<div
|
||||
style={ {
|
||||
width: comboBoxWidth,
|
||||
} }
|
||||
>
|
||||
<Spinner />
|
||||
</div>
|
||||
) : (
|
||||
<Tree
|
||||
{ ...props }
|
||||
id={ `${ props.id }-menu` }
|
||||
ref={ ref }
|
||||
items={ linkedTree }
|
||||
onTreeBlur={ onClose }
|
||||
shouldItemBeExpanded={ shouldItemBeExpanded }
|
||||
shouldShowCreateButton={ shouldShowCreateButton }
|
||||
style={ {
|
||||
width: comboBoxWidth,
|
||||
} }
|
||||
/>
|
||||
)
|
||||
}
|
||||
renderToggle={ ( { isOpen, onToggle, onClose } ) => (
|
||||
<div
|
||||
className={ classNames(
|
||||
'woocommerce-experimental-select-control',
|
||||
{
|
||||
'is-focused': isFocused,
|
||||
}
|
||||
) }
|
||||
>
|
||||
<label
|
||||
htmlFor={ `${ props.id }-input` }
|
||||
id={ `${ props.id }-label` }
|
||||
className="woocommerce-experimental-select-control__label"
|
||||
>
|
||||
{ props.label }
|
||||
</label>
|
||||
<ComboBox
|
||||
comboBoxProps={ {
|
||||
className:
|
||||
'woocommerce-experimental-select-control__combo-box-wrapper',
|
||||
ref: comboBoxRef,
|
||||
role: 'combobox',
|
||||
'aria-expanded': isOpen,
|
||||
'aria-haspopup': 'tree',
|
||||
'aria-labelledby': `${ props.id }-label`,
|
||||
'aria-owns': `${ props.id }-menu`,
|
||||
} }
|
||||
inputProps={ {
|
||||
className:
|
||||
'woocommerce-experimental-select-control__input',
|
||||
id: `${ props.id }-input`,
|
||||
'aria-autocomplete': 'list',
|
||||
'aria-controls': `${ props.id }-menu`,
|
||||
autoComplete: 'off',
|
||||
onFocus: () => {
|
||||
if ( ! isOpen ) {
|
||||
onToggle();
|
||||
}
|
||||
setIsFocused( true );
|
||||
},
|
||||
onBlur: ( event ) => {
|
||||
// if blurring to an element inside the dropdown, don't close it
|
||||
if (
|
||||
isOpen &&
|
||||
! document
|
||||
.querySelector(
|
||||
'.woocommerce-experimental-select-control ~ .components-popover'
|
||||
)
|
||||
?.contains( event.relatedTarget )
|
||||
) {
|
||||
onClose();
|
||||
}
|
||||
setIsFocused( false );
|
||||
},
|
||||
onKeyDown: ( event ) => {
|
||||
const baseQuery =
|
||||
'.woocommerce-experimental-select-tree-control__dropdown > .components-popover';
|
||||
if ( event.key === 'ArrowDown' ) {
|
||||
event.preventDefault();
|
||||
// focus on the first element from the Popover
|
||||
(
|
||||
document.querySelector(
|
||||
`${ baseQuery } input, ${ baseQuery } button`
|
||||
) as
|
||||
| HTMLInputElement
|
||||
| HTMLButtonElement
|
||||
)?.focus();
|
||||
}
|
||||
if ( event.key === 'Tab' ) {
|
||||
onClose();
|
||||
}
|
||||
},
|
||||
onChange: ( event ) =>
|
||||
onInputChange &&
|
||||
onInputChange( event.target.value ),
|
||||
placeholder,
|
||||
} }
|
||||
suffix={ suffix }
|
||||
>
|
||||
<SelectedItems
|
||||
items={ ( props.selected as Item[] ) || [] }
|
||||
getItemLabel={ ( item ) => item?.label || '' }
|
||||
getItemValue={ ( item ) => item?.value || '' }
|
||||
onRemove={ ( item ) => {
|
||||
if (
|
||||
! Array.isArray( item ) &&
|
||||
props.onRemove
|
||||
) {
|
||||
props.onRemove( item );
|
||||
onClose();
|
||||
}
|
||||
} }
|
||||
getSelectedItemProps={ () => ( {} ) }
|
||||
/>
|
||||
</ComboBox>
|
||||
</div>
|
||||
) }
|
||||
/>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,101 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
|
||||
import React, { createElement } from 'react';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { SelectTree } from '../select-tree';
|
||||
import { Item } from '../../experimental-tree-control/types';
|
||||
|
||||
const listItems: Item[] = [
|
||||
{ value: '1', label: 'Technology' },
|
||||
{ value: '1.1', label: 'Notebooks', parent: '1' },
|
||||
{ value: '1.2', label: 'Phones', parent: '1' },
|
||||
{ value: '1.2.1', label: 'iPhone', parent: '1.2' },
|
||||
{ value: '1.2.1.1', label: 'iPhone 14 Pro', parent: '1.2.1' },
|
||||
{ value: '1.2.1.2', label: 'iPhone 14 Pro Max', parent: '1.2.1' },
|
||||
{ value: '1.2.2', label: 'Samsung', parent: '1.2' },
|
||||
{ value: '1.2.2.1', label: 'Samsung Galaxy 22 Plus', parent: '1.2.2' },
|
||||
{ value: '1.2.2.2', label: 'Samsung Galaxy 22 Ultra', parent: '1.2.2' },
|
||||
{ value: '1.3', label: 'Wearables', parent: '1' },
|
||||
{ value: '2', label: 'Hardware' },
|
||||
{ value: '2.1', label: 'CPU', parent: '2' },
|
||||
{ value: '2.2', label: 'GPU', parent: '2' },
|
||||
{ value: '2.3', label: 'Memory RAM', parent: '2' },
|
||||
{ value: '3', label: 'Other' },
|
||||
];
|
||||
|
||||
const filterItems = ( items: Item[], searchValue ) => {
|
||||
const filteredItems = items.filter( ( e ) =>
|
||||
e.label.includes( searchValue )
|
||||
);
|
||||
const itemsToIterate = [ ...filteredItems ];
|
||||
while ( itemsToIterate.length > 0 ) {
|
||||
// The filter should include the parents of the filtered items
|
||||
const element = itemsToIterate.pop();
|
||||
if ( element ) {
|
||||
const parent = listItems.find(
|
||||
( item ) => item.value === element.parent
|
||||
);
|
||||
if ( parent && ! filteredItems.includes( parent ) ) {
|
||||
filteredItems.push( parent );
|
||||
itemsToIterate.push( parent );
|
||||
}
|
||||
}
|
||||
}
|
||||
return filteredItems;
|
||||
};
|
||||
|
||||
export const MultipleSelectTree: React.FC = () => {
|
||||
const [ value, setValue ] = React.useState( '' );
|
||||
const [ selected, setSelected ] = React.useState< Item[] >( [] );
|
||||
|
||||
const items = filterItems( listItems, value );
|
||||
|
||||
return (
|
||||
<SelectTree
|
||||
id="multiple-select-tree"
|
||||
label="Multiple Select Tree"
|
||||
multiple
|
||||
items={ items }
|
||||
selected={ selected }
|
||||
shouldNotRecursivelySelect
|
||||
shouldShowCreateButton={ ( typedValue ) =>
|
||||
! value ||
|
||||
listItems.findIndex( ( item ) => item.label === typedValue ) ===
|
||||
-1
|
||||
}
|
||||
createValue={ value }
|
||||
// eslint-disable-next-line no-alert
|
||||
onCreateNew={ () => alert( 'create new called' ) }
|
||||
onInputChange={ ( a ) => setValue( a || '' ) }
|
||||
onSelect={ ( selectedItems ) => {
|
||||
if ( Array.isArray( selectedItems ) ) {
|
||||
setSelected( [ ...selected, ...selectedItems ] );
|
||||
}
|
||||
} }
|
||||
onRemove={ ( removedItems ) => {
|
||||
const newValues = Array.isArray( removedItems )
|
||||
? selected.filter(
|
||||
( item ) =>
|
||||
! removedItems.some(
|
||||
( { value: removedValue } ) =>
|
||||
item.value === removedValue
|
||||
)
|
||||
)
|
||||
: selected.filter(
|
||||
( item ) => item.value !== removedItems.value
|
||||
);
|
||||
setSelected( newValues );
|
||||
} }
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default {
|
||||
title: 'WooCommerce Admin/experimental/SelectTreeControl',
|
||||
component: SelectTree,
|
||||
};
|
|
@ -0,0 +1,107 @@
|
|||
import { render } from '@testing-library/react';
|
||||
import React, { createElement } from '@wordpress/element';
|
||||
import { SelectTree } from '../select-tree';
|
||||
import { Item } from '../../experimental-tree-control';
|
||||
|
||||
const mockItems: Item[] = [
|
||||
{
|
||||
label: 'Item 1',
|
||||
value: 'item-1',
|
||||
},
|
||||
{
|
||||
label: 'Item 2',
|
||||
value: 'item-2',
|
||||
parent: 'item-1',
|
||||
},
|
||||
{
|
||||
label: 'Item 3',
|
||||
value: 'item-3',
|
||||
},
|
||||
];
|
||||
|
||||
const DEFAULT_PROPS = {
|
||||
id: 'select-tree',
|
||||
items: mockItems,
|
||||
label: 'Select Tree',
|
||||
placeholder: 'Type here',
|
||||
};
|
||||
|
||||
describe( 'SelectTree', () => {
|
||||
beforeEach( () => {
|
||||
jest.clearAllMocks();
|
||||
} );
|
||||
|
||||
it( 'should show the popover only when focused', () => {
|
||||
const { queryByPlaceholderText, queryByText } = render(
|
||||
<SelectTree { ...DEFAULT_PROPS } />
|
||||
);
|
||||
expect( queryByText( 'Item 1' ) ).not.toBeInTheDocument();
|
||||
queryByPlaceholderText( 'Type here' )?.focus();
|
||||
expect( queryByText( 'Item 1' ) ).toBeInTheDocument();
|
||||
} );
|
||||
|
||||
it( 'should show create button when callback is true ', () => {
|
||||
const { queryByText, queryByPlaceholderText } = render(
|
||||
<SelectTree
|
||||
{ ...DEFAULT_PROPS }
|
||||
shouldShowCreateButton={ () => true }
|
||||
/>
|
||||
);
|
||||
queryByPlaceholderText( 'Type here' )?.focus();
|
||||
expect( queryByText( 'Create new' ) ).toBeInTheDocument();
|
||||
} );
|
||||
it( 'should not show create button when callback is false or no callback', () => {
|
||||
const { queryByText, queryByPlaceholderText } = render(
|
||||
<SelectTree { ...DEFAULT_PROPS } />
|
||||
);
|
||||
queryByPlaceholderText( 'Type here' )?.focus();
|
||||
expect( queryByText( 'Create new' ) ).not.toBeInTheDocument();
|
||||
} );
|
||||
it( 'should show a root item when focused and child when expand button is clicked', () => {
|
||||
const { queryByText, queryByLabelText, queryByPlaceholderText } =
|
||||
render( <SelectTree { ...DEFAULT_PROPS } /> );
|
||||
queryByPlaceholderText( 'Type here' )?.focus();
|
||||
expect( queryByText( 'Item 1' ) ).toBeInTheDocument();
|
||||
|
||||
expect( queryByText( 'Item 2' ) ).not.toBeInTheDocument();
|
||||
queryByLabelText( 'Expand' )?.click();
|
||||
expect( queryByText( 'Item 2' ) ).toBeInTheDocument();
|
||||
} );
|
||||
|
||||
it( 'should show selected items', () => {
|
||||
const { queryAllByRole, queryByPlaceholderText } = render(
|
||||
<SelectTree { ...DEFAULT_PROPS } selected={ [ mockItems[ 0 ] ] } />
|
||||
);
|
||||
queryByPlaceholderText( 'Type here' )?.focus();
|
||||
expect( queryAllByRole( 'treeitem' )[ 0 ] ).toHaveAttribute(
|
||||
'aria-selected',
|
||||
'true'
|
||||
);
|
||||
} );
|
||||
|
||||
it( 'should show Create "<createValue>" button', () => {
|
||||
const { queryByPlaceholderText, queryByText } = render(
|
||||
<SelectTree
|
||||
{ ...DEFAULT_PROPS }
|
||||
createValue="new item"
|
||||
shouldShowCreateButton={ () => true }
|
||||
/>
|
||||
);
|
||||
queryByPlaceholderText( 'Type here' )?.focus();
|
||||
expect( queryByText( 'Create "new item"' ) ).toBeInTheDocument();
|
||||
} );
|
||||
it( 'should call onCreateNew when Create "<createValue>" button is clicked', () => {
|
||||
const mockFn = jest.fn();
|
||||
const { queryByPlaceholderText, queryByText } = render(
|
||||
<SelectTree
|
||||
{ ...DEFAULT_PROPS }
|
||||
createValue="new item"
|
||||
shouldShowCreateButton={ () => true }
|
||||
onCreateNew={ mockFn }
|
||||
/>
|
||||
);
|
||||
queryByPlaceholderText( 'Type here' )?.focus();
|
||||
queryByText( 'Create "new item"' )?.click();
|
||||
expect( mockFn ).toBeCalledTimes( 1 );
|
||||
} );
|
||||
} );
|
|
@ -17,7 +17,8 @@ export function useExpander( {
|
|||
useEffect( () => {
|
||||
if (
|
||||
item.children?.length &&
|
||||
typeof shouldItemBeExpanded === 'function'
|
||||
typeof shouldItemBeExpanded === 'function' &&
|
||||
! isExpanded
|
||||
) {
|
||||
setExpanded( shouldItemBeExpanded( item ) );
|
||||
}
|
||||
|
|
|
@ -110,12 +110,14 @@ export function useKeyboard( {
|
|||
onExpand,
|
||||
onCollapse,
|
||||
onToggleExpand,
|
||||
onLastItemLoop,
|
||||
}: {
|
||||
item: LinkedTree;
|
||||
isExpanded: boolean;
|
||||
onExpand(): void;
|
||||
onCollapse(): void;
|
||||
onToggleExpand(): void;
|
||||
onLastItemLoop?( event: React.KeyboardEvent< HTMLDivElement > ): void;
|
||||
} ) {
|
||||
function onKeyDown( event: React.KeyboardEvent< HTMLDivElement > ) {
|
||||
if ( event.code === 'ArrowRight' ) {
|
||||
|
@ -154,6 +156,9 @@ export function useKeyboard( {
|
|||
event.code
|
||||
);
|
||||
element?.focus();
|
||||
if ( event.code === 'ArrowDown' && ! element && onLastItemLoop ) {
|
||||
onLastItemLoop( event );
|
||||
}
|
||||
}
|
||||
|
||||
if ( event.code === 'Home' ) {
|
||||
|
@ -169,5 +174,5 @@ export function useKeyboard( {
|
|||
}
|
||||
}
|
||||
|
||||
return { onKeyDown };
|
||||
return { onKeyDown, onLastItemLoop };
|
||||
}
|
||||
|
|
|
@ -75,6 +75,7 @@ function hasSelectedSibblingChildren(
|
|||
export function useSelection( {
|
||||
item,
|
||||
multiple,
|
||||
shouldNotRecursivelySelect,
|
||||
selected,
|
||||
level,
|
||||
index,
|
||||
|
@ -89,6 +90,7 @@ export function useSelection( {
|
|||
| 'index'
|
||||
| 'onSelect'
|
||||
| 'onRemove'
|
||||
| 'shouldNotRecursivelySelect'
|
||||
> ) {
|
||||
const selectedItems = useMemo( () => {
|
||||
if ( level === 1 && index === 0 ) {
|
||||
|
@ -100,7 +102,11 @@ export function useSelection( {
|
|||
|
||||
const checkedStatus: CheckedStatus = useMemo( () => {
|
||||
if ( item.data.value in selectedItems ) {
|
||||
if ( multiple && isIndeterminate( selectedItems, item.children ) ) {
|
||||
if (
|
||||
multiple &&
|
||||
! shouldNotRecursivelySelect &&
|
||||
isIndeterminate( selectedItems, item.children )
|
||||
) {
|
||||
return 'indeterminate';
|
||||
}
|
||||
return 'checked';
|
||||
|
@ -113,7 +119,7 @@ export function useSelection( {
|
|||
|
||||
if ( multiple ) {
|
||||
value = [ item.data ];
|
||||
if ( item.children.length ) {
|
||||
if ( item.children.length && ! shouldNotRecursivelySelect ) {
|
||||
value.push( ...getDeepChildren( item ) );
|
||||
}
|
||||
} else if ( item.children?.length ) {
|
||||
|
@ -132,7 +138,7 @@ export function useSelection( {
|
|||
function onSelectChildren( value: Item | Item[] ) {
|
||||
if ( typeof onSelect !== 'function' ) return;
|
||||
|
||||
if ( multiple ) {
|
||||
if ( multiple && ! shouldNotRecursivelySelect ) {
|
||||
value = [ item.data, ...( value as Item[] ) ];
|
||||
}
|
||||
|
||||
|
@ -142,7 +148,11 @@ export function useSelection( {
|
|||
function onRemoveChildren( value: Item | Item[] ) {
|
||||
if ( typeof onRemove !== 'function' ) return;
|
||||
|
||||
if ( multiple && item.children?.length ) {
|
||||
if (
|
||||
multiple &&
|
||||
item.children?.length &&
|
||||
! shouldNotRecursivelySelect
|
||||
) {
|
||||
const hasSelectedSibbling = hasSelectedSibblingChildren(
|
||||
item.children,
|
||||
value as Item[],
|
||||
|
|
|
@ -17,6 +17,7 @@ export function useTreeItem( {
|
|||
item,
|
||||
level,
|
||||
multiple,
|
||||
shouldNotRecursivelySelect,
|
||||
selected,
|
||||
index,
|
||||
getLabel,
|
||||
|
@ -24,6 +25,11 @@ export function useTreeItem( {
|
|||
shouldItemBeHighlighted,
|
||||
onSelect,
|
||||
onRemove,
|
||||
isExpanded,
|
||||
onCreateNew,
|
||||
shouldShowCreateButton,
|
||||
onLastItemLoop,
|
||||
onTreeBlur,
|
||||
...props
|
||||
}: TreeItemProps ) {
|
||||
const nextLevel = level + 1;
|
||||
|
@ -41,6 +47,7 @@ export function useTreeItem( {
|
|||
index,
|
||||
onSelect,
|
||||
onRemove,
|
||||
shouldNotRecursivelySelect,
|
||||
} );
|
||||
|
||||
const highlighter = useHighlighter( {
|
||||
|
@ -56,6 +63,7 @@ export function useTreeItem( {
|
|||
|
||||
const { onKeyDown } = useKeyboard( {
|
||||
...expander,
|
||||
onLastItemLoop,
|
||||
item,
|
||||
} );
|
||||
|
||||
|
@ -96,6 +104,7 @@ export function useTreeItem( {
|
|||
getItemLabel: getLabel,
|
||||
shouldItemBeExpanded,
|
||||
shouldItemBeHighlighted,
|
||||
shouldNotRecursivelySelect,
|
||||
onSelect: selection.onSelectChildren,
|
||||
onRemove: selection.onRemoveChildren,
|
||||
},
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
import { TreeProps } from '../types';
|
||||
|
||||
export function useTree( {
|
||||
ref,
|
||||
items,
|
||||
level = 1,
|
||||
role = 'tree',
|
||||
|
@ -19,6 +18,11 @@ export function useTree( {
|
|||
shouldItemBeHighlighted,
|
||||
onSelect,
|
||||
onRemove,
|
||||
shouldNotRecursivelySelect,
|
||||
createValue,
|
||||
onTreeBlur,
|
||||
onCreateNew,
|
||||
shouldShowCreateButton,
|
||||
...props
|
||||
}: TreeProps ) {
|
||||
return {
|
||||
|
@ -35,6 +39,7 @@ export function useTree( {
|
|||
getLabel: getItemLabel,
|
||||
shouldItemBeExpanded,
|
||||
shouldItemBeHighlighted,
|
||||
shouldNotRecursivelySelect,
|
||||
onSelect,
|
||||
onRemove,
|
||||
},
|
||||
|
|
|
@ -12,4 +12,13 @@
|
|||
border: 1px solid $gray-400;
|
||||
border-radius: 2px;
|
||||
}
|
||||
&__button {
|
||||
width: 100%;
|
||||
&:hover,
|
||||
&:focus-within {
|
||||
outline: 1.5px solid var( --wp-admin-theme-color );
|
||||
outline-offset: -1.5px;
|
||||
background-color: $gray-100;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { Button, Icon } from '@wordpress/components';
|
||||
import { __, sprintf } from '@wordpress/i18n';
|
||||
import classNames from 'classnames';
|
||||
import { createElement, forwardRef } from 'react';
|
||||
import { createElement, forwardRef, Fragment, useRef } from 'react';
|
||||
import { plus } from '@wordpress/icons';
|
||||
import { useMergeRefs } from '@wordpress/compose';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
|
@ -13,31 +17,93 @@ import { TreeProps } from './types';
|
|||
|
||||
export const Tree = forwardRef( function ForwardedTree(
|
||||
props: TreeProps,
|
||||
ref: React.ForwardedRef< HTMLOListElement >
|
||||
forwardedRef: React.ForwardedRef< HTMLOListElement >
|
||||
) {
|
||||
const rootListRef = useRef< HTMLOListElement >( null );
|
||||
const ref = useMergeRefs( [ rootListRef, forwardedRef ] );
|
||||
|
||||
const { level, items, treeProps, treeItemProps } = useTree( {
|
||||
...props,
|
||||
ref,
|
||||
} );
|
||||
|
||||
if ( ! items.length ) return null;
|
||||
const isCreateButtonVisible =
|
||||
props.shouldShowCreateButton &&
|
||||
props.shouldShowCreateButton( props.createValue );
|
||||
|
||||
return (
|
||||
<ol
|
||||
{ ...treeProps }
|
||||
className={ classNames(
|
||||
treeProps.className,
|
||||
'experimental-woocommerce-tree',
|
||||
`experimental-woocommerce-tree--level-${ level }`
|
||||
<>
|
||||
<ol
|
||||
{ ...treeProps }
|
||||
className={ classNames(
|
||||
treeProps.className,
|
||||
'experimental-woocommerce-tree',
|
||||
`experimental-woocommerce-tree--level-${ level }`
|
||||
) }
|
||||
>
|
||||
{ items.map( ( child, index ) => (
|
||||
<TreeItem
|
||||
{ ...treeItemProps }
|
||||
isExpanded={ props.isExpanded }
|
||||
key={ child.data.value }
|
||||
item={ child }
|
||||
index={ index }
|
||||
// Button ref is not working, so need to use CSS directly
|
||||
onLastItemLoop={ () => {
|
||||
(
|
||||
rootListRef.current
|
||||
?.closest( 'ol[role="tree"]' )
|
||||
?.parentElement?.querySelector(
|
||||
'.experimental-woocommerce-tree__button'
|
||||
) as HTMLButtonElement
|
||||
)?.focus();
|
||||
} }
|
||||
/>
|
||||
) ) }
|
||||
</ol>
|
||||
{ isCreateButtonVisible && (
|
||||
<Button
|
||||
className="experimental-woocommerce-tree__button"
|
||||
onClick={ () => {
|
||||
if ( props.onCreateNew ) {
|
||||
props.onCreateNew();
|
||||
}
|
||||
if ( props.onTreeBlur ) {
|
||||
props.onTreeBlur();
|
||||
}
|
||||
} }
|
||||
// Component's event type definition is not working
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
onKeyDown={ ( event: any ) => {
|
||||
if (
|
||||
event.key === 'ArrowUp' ||
|
||||
event.key === 'ArrowDown'
|
||||
) {
|
||||
event.preventDefault();
|
||||
if ( event.key === 'ArrowUp' ) {
|
||||
const allHeadings =
|
||||
event.nativeEvent.srcElement.previousSibling.querySelectorAll(
|
||||
'.experimental-woocommerce-tree-item > .experimental-woocommerce-tree-item__heading'
|
||||
);
|
||||
|
||||
allHeadings[ allHeadings.length - 1 ]
|
||||
?.querySelector(
|
||||
'.experimental-woocommerce-tree-item__label'
|
||||
)
|
||||
?.focus();
|
||||
}
|
||||
}
|
||||
} }
|
||||
>
|
||||
<Icon icon={ plus } size={ 20 } />
|
||||
{ props.createValue
|
||||
? sprintf(
|
||||
__( 'Create "%s"', 'woocommerce' ),
|
||||
props.createValue
|
||||
)
|
||||
: __( 'Create new', 'woocommerce' ) }
|
||||
</Button>
|
||||
) }
|
||||
>
|
||||
{ items.map( ( child, index ) => (
|
||||
<TreeItem
|
||||
{ ...treeItemProps }
|
||||
key={ child.data.value }
|
||||
item={ child }
|
||||
index={ index }
|
||||
/>
|
||||
) ) }
|
||||
</ol>
|
||||
</>
|
||||
);
|
||||
} );
|
||||
|
|
|
@ -14,7 +14,7 @@ export type CheckedStatus = 'checked' | 'unchecked' | 'indeterminate';
|
|||
|
||||
type BaseTreeProps = {
|
||||
/**
|
||||
* It contians one item if `multiple` value is false or
|
||||
* It contains one item if `multiple` value is false or
|
||||
* a list of items if it is true.
|
||||
*/
|
||||
selected?: Item | Item[];
|
||||
|
@ -22,12 +22,30 @@ type BaseTreeProps = {
|
|||
* Whether the tree items are single or multiple selected.
|
||||
*/
|
||||
multiple?: boolean;
|
||||
/**
|
||||
* In `multiple` mode, when this flag is also set, selecting children does
|
||||
* not select their parents and selecting parents does not select their children.
|
||||
*/
|
||||
shouldNotRecursivelySelect?: boolean;
|
||||
/**
|
||||
* The value to be used for comparison to determine if 'create new' button should be shown.
|
||||
*/
|
||||
createValue?: string;
|
||||
/**
|
||||
* Called when the 'create new' button is clicked.
|
||||
*/
|
||||
onCreateNew?: () => void;
|
||||
/**
|
||||
* If passed, shows create button if return from callback is true
|
||||
*/
|
||||
shouldShowCreateButton?( value?: string ): boolean;
|
||||
isExpanded?: boolean;
|
||||
/**
|
||||
* When `multiple` is true and a child item is selected, all its
|
||||
* ancestors and its descendants are also selected. If it's false
|
||||
* only the clicked item is selected.
|
||||
*
|
||||
* @param value The selection
|
||||
* @param value The selection
|
||||
*/
|
||||
onSelect?( value: Item | Item[] ): void;
|
||||
/**
|
||||
|
@ -36,7 +54,7 @@ type BaseTreeProps = {
|
|||
* are also unselected. If it's false only the clicked item is
|
||||
* unselected.
|
||||
*
|
||||
* @param value The unselection
|
||||
* @param value The unselection
|
||||
*/
|
||||
onRemove?( value: Item | Item[] ): void;
|
||||
/**
|
||||
|
@ -48,12 +66,16 @@ type BaseTreeProps = {
|
|||
* shouldItemBeHighlighted={ isFirstChild }
|
||||
* />
|
||||
*
|
||||
* @param item The current linked tree item, useful to
|
||||
* traverse the entire linked tree from this item.
|
||||
* @param item The current linked tree item, useful to
|
||||
* traverse the entire linked tree from this item.
|
||||
*
|
||||
* @see {@link LinkedTree}
|
||||
*/
|
||||
shouldItemBeHighlighted?( item: LinkedTree ): boolean;
|
||||
/**
|
||||
* Called when the create button is clicked to help closing any related popover.
|
||||
*/
|
||||
onTreeBlur?(): void;
|
||||
};
|
||||
|
||||
export type TreeProps = BaseTreeProps &
|
||||
|
@ -66,7 +88,8 @@ export type TreeProps = BaseTreeProps &
|
|||
> & {
|
||||
level?: number;
|
||||
items: LinkedTree[];
|
||||
/** It gives a way to render a different Element as the
|
||||
/**
|
||||
* It gives a way to render a different Element as the
|
||||
* tree item label.
|
||||
*
|
||||
* @example
|
||||
|
@ -74,7 +97,7 @@ export type TreeProps = BaseTreeProps &
|
|||
* getItemLabel={ ( item ) => <span>${ item.data.label }</span> }
|
||||
* />
|
||||
*
|
||||
* @param item The current rendering tree item
|
||||
* @param item The current rendering tree item
|
||||
*
|
||||
* @see {@link LinkedTree}
|
||||
*/
|
||||
|
@ -107,8 +130,10 @@ export type TreeItemProps = BaseTreeProps &
|
|||
level: number;
|
||||
item: LinkedTree;
|
||||
index: number;
|
||||
isFocused?: boolean;
|
||||
getLabel?( item: LinkedTree ): JSX.Element;
|
||||
shouldItemBeExpanded?( item: LinkedTree ): boolean;
|
||||
onLastItemLoop?( event: React.KeyboardEvent< HTMLDivElement > ): void;
|
||||
};
|
||||
|
||||
export type TreeControlProps = Omit< TreeProps, 'items' | 'level' > & {
|
||||
|
|
|
@ -18,7 +18,7 @@ export type FormErrors< Values > = {
|
|||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export type FormContext< Values extends Record< string, any > > = {
|
||||
export type FormContextType< Values extends Record< string, any > > = {
|
||||
values: Values;
|
||||
errors: FormErrors< Values >;
|
||||
isDirty: boolean;
|
||||
|
@ -51,14 +51,16 @@ export type FormContext< Values extends Record< string, any > > = {
|
|||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export const FormContext = createContext< FormContext< any > >(
|
||||
export const FormContext: React.Context< FormContextType< any > > =
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
{} as FormContext< any >
|
||||
);
|
||||
createContext< FormContextType< any > >(
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
{} as FormContextType< any >
|
||||
);
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export function useFormContext< Values extends Record< string, any > >() {
|
||||
const formContext = useContext< FormContext< Values > >( FormContext );
|
||||
const formContext = useContext< FormContextType< Values > >( FormContext );
|
||||
|
||||
return formContext;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import { TextControl } from '@wordpress/components';
|
|||
* Internal dependencies
|
||||
*/
|
||||
import { Form, useFormContext } from '../';
|
||||
import type { FormContext } from '../';
|
||||
import type { FormContextType } from '../';
|
||||
import { DateTimePickerControl } from '../../date-time-picker-control';
|
||||
|
||||
const TestInputWithContext = () => {
|
||||
|
@ -44,7 +44,7 @@ describe( 'Form', () => {
|
|||
>
|
||||
{ ( {
|
||||
handleSubmit,
|
||||
}: FormContext< Record< string, string > > ) => {
|
||||
}: FormContextType< Record< string, string > > ) => {
|
||||
return <button onClick={ handleSubmit }>Submit</button>;
|
||||
} }
|
||||
</Form>
|
||||
|
@ -71,7 +71,7 @@ describe( 'Form', () => {
|
|||
onChange={ mockOnChange }
|
||||
validate={ () => ( {} ) }
|
||||
>
|
||||
{ ( { setValue }: FormContext< Record< string, string > > ) => {
|
||||
{ ( { setValue }: FormContextType< Record< string, string > > ) => {
|
||||
return (
|
||||
<button
|
||||
onClick={ () => {
|
||||
|
@ -103,7 +103,7 @@ describe( 'Form', () => {
|
|||
<Form onSubmit={ mockOnSubmit } validate={ () => ( {} ) }>
|
||||
{ ( {
|
||||
handleSubmit,
|
||||
}: FormContext< Record< string, string > > ) => {
|
||||
}: FormContextType< Record< string, string > > ) => {
|
||||
return <button onClick={ handleSubmit }>Submit</button>;
|
||||
} }
|
||||
</Form>
|
||||
|
@ -124,7 +124,7 @@ describe( 'Form', () => {
|
|||
|
||||
const { queryByText } = render(
|
||||
<Form onChange={ mockOnChange } validate={ () => ( {} ) }>
|
||||
{ ( { setValue }: FormContext< Record< string, string > > ) => {
|
||||
{ ( { setValue }: FormContextType< Record< string, string > > ) => {
|
||||
return (
|
||||
<button
|
||||
onClick={ () => {
|
||||
|
@ -156,7 +156,7 @@ describe( 'Form', () => {
|
|||
{ ( {
|
||||
setValue,
|
||||
getInputProps,
|
||||
}: FormContext< Record< string, string > > ) => {
|
||||
}: FormContextType< Record< string, string > > ) => {
|
||||
return (
|
||||
<TextControl
|
||||
label={ 'First Name' }
|
||||
|
@ -206,7 +206,7 @@ describe( 'Form', () => {
|
|||
{ ( {
|
||||
setValue,
|
||||
getInputProps,
|
||||
}: FormContext< Record< string, string > > ) => {
|
||||
}: FormContextType< Record< string, string > > ) => {
|
||||
return (
|
||||
<TextControl
|
||||
label={ 'First Name' }
|
||||
|
@ -243,7 +243,7 @@ describe( 'Form', () => {
|
|||
{ ( {
|
||||
setValue,
|
||||
getInputProps,
|
||||
}: FormContext< Record< string, string > > ) => {
|
||||
}: FormContextType< Record< string, string > > ) => {
|
||||
return (
|
||||
<TextControl
|
||||
label={ 'First Name' }
|
||||
|
@ -293,7 +293,7 @@ describe( 'Form', () => {
|
|||
{ ( {
|
||||
setValue,
|
||||
getInputProps,
|
||||
}: FormContext< Record< string, string > > ) => {
|
||||
}: FormContextType< Record< string, string > > ) => {
|
||||
return (
|
||||
<TextControl
|
||||
label={ 'First Name' }
|
||||
|
@ -329,7 +329,7 @@ describe( 'Form', () => {
|
|||
<Form onChanges={ mockOnChanges } validate={ () => ( {} ) }>
|
||||
{ ( {
|
||||
setValues,
|
||||
}: FormContext< Record< string, string > > ) => {
|
||||
}: FormContextType< Record< string, string > > ) => {
|
||||
return (
|
||||
<button
|
||||
onClick={ () => {
|
||||
|
@ -379,7 +379,7 @@ describe( 'Form', () => {
|
|||
<Form onChanges={ mockOnChanges } validate={ validate }>
|
||||
{ ( {
|
||||
setValues,
|
||||
}: FormContext< Record< string, string > > ) => {
|
||||
}: FormContextType< Record< string, string > > ) => {
|
||||
return (
|
||||
<button
|
||||
onClick={ () => {
|
||||
|
@ -428,7 +428,7 @@ describe( 'Form', () => {
|
|||
|
||||
const { container, queryByText } = render(
|
||||
<Form< TestData > onChange={ mockOnChange } validate={ validate }>
|
||||
{ ( { getInputProps, values }: FormContext< TestData > ) => {
|
||||
{ ( { getInputProps, values }: FormContextType< TestData > ) => {
|
||||
return (
|
||||
<DateTimePickerControl
|
||||
label={ 'Date' }
|
||||
|
|
|
@ -16,7 +16,7 @@ export { default as EmptyContent } from './empty-content';
|
|||
export { default as Flag } from './flag';
|
||||
export { Form, useFormContext } from './form';
|
||||
export { FormSection } from './form-section';
|
||||
export type { FormContext, FormRef, FormErrors } from './form';
|
||||
export type { FormContext, FormContextType, FormRef, FormErrors } from './form';
|
||||
export { default as FilterPicker } from './filter-picker';
|
||||
export { H, Section } from './section';
|
||||
export { ImageGallery, ImageGalleryItem } from './image-gallery';
|
||||
|
@ -95,7 +95,11 @@ export {
|
|||
SlotContextType,
|
||||
SlotContextHelpersType,
|
||||
} from './slot-context';
|
||||
export { TreeControl as __experimentalTreeControl } from './experimental-tree-control';
|
||||
export {
|
||||
TreeControl as __experimentalTreeControl,
|
||||
Item as TreeItemType,
|
||||
} from './experimental-tree-control';
|
||||
export { SelectTree as __experimentalSelectTreeControl } from './experimental-select-tree-control';
|
||||
export { default as TreeSelectControl } from './tree-select-control';
|
||||
|
||||
// Exports below can be removed once the @woocommerce/product-editor package is released.
|
||||
|
@ -103,3 +107,4 @@ export {
|
|||
ProductSectionLayout as __experimentalProductSectionLayout,
|
||||
ProductFieldSection as __experimentalProductFieldSection,
|
||||
} from './product-section-layout';
|
||||
export { DisplayState } from './display-state';
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { BlockInstance } from '@wordpress/blocks';
|
||||
import { BlockInstance, getBlockType } from '@wordpress/blocks';
|
||||
import {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore We need this to import the block modules for registration.
|
||||
|
@ -29,9 +29,10 @@ const ALLOWED_CORE_BLOCKS = [
|
|||
|
||||
const registerCoreBlocks = () => {
|
||||
const coreBlocks = __experimentalGetCoreBlocks();
|
||||
const blocks = coreBlocks.filter( ( block: BlockInstance ) =>
|
||||
ALLOWED_CORE_BLOCKS.includes( block.name )
|
||||
);
|
||||
const blocks = coreBlocks.filter( ( block: BlockInstance ) => {
|
||||
const isRegistered = !! getBlockType( block.name );
|
||||
return ! isRegistered && ALLOWED_CORE_BLOCKS.includes( block.name );
|
||||
} );
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore An argument is allowed to specify which blocks to register.
|
||||
|
|
|
@ -8,6 +8,6 @@ import { createContext } from '@wordpress/element';
|
|||
*
|
||||
* See https://medium.com/@Heydon/managing-heading-levels-in-design-systems-18be9a746fa3
|
||||
*/
|
||||
const Level = createContext( 2 );
|
||||
const Level: React.Context< number > = createContext( 2 );
|
||||
|
||||
export { Level };
|
||||
|
|
|
@ -43,7 +43,7 @@ export type SortableProps = {
|
|||
|
||||
const THROTTLE_TIME = 16;
|
||||
|
||||
export const SortableContext = createContext( {} );
|
||||
export const SortableContext: React.Context< object > = createContext( {} );
|
||||
|
||||
export const Sortable = ( {
|
||||
children,
|
||||
|
|
|
@ -56,5 +56,6 @@
|
|||
@import 'collapsible-content/style.scss';
|
||||
@import 'form/style.scss';
|
||||
@import 'experimental-tree-control/tree.scss';
|
||||
@import 'experimental-select-tree-control/select-tree.scss';
|
||||
@import 'product-section-layout/style.scss';
|
||||
@import 'tree-select-control/index.scss';
|
||||
|
|
|
@ -28,13 +28,15 @@ function Tour() {
|
|||
referenceElements: {
|
||||
desktop: '.render-step-near-me',
|
||||
},
|
||||
meta: {
|
||||
heading: 'Lorem ipsum dolor sit amet.',
|
||||
descriptions: {
|
||||
desktop: 'Lorem ipsum dolor sit amet.',
|
||||
},
|
||||
primaryButtonText: "Done"
|
||||
},
|
||||
meta: {
|
||||
heading: 'Lorem ipsum dolor sit amet.',
|
||||
descriptions: {
|
||||
desktop: 'Lorem ipsum dolor sit amet.',
|
||||
},
|
||||
primaryButton: {
|
||||
text: 'Done',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
closeHandler: () => setShowTour( false ),
|
||||
|
@ -57,8 +59,8 @@ function Tour() {
|
|||
|
||||
When a tour is rendered and focused, the following functionality exists:
|
||||
|
||||
- Close the tour on `ESC` key (in minimized view)
|
||||
- Go to previous/next step on `left/right` arrow keys (in step view)
|
||||
- Close the tour on `ESC` key (in minimized view)
|
||||
- Go to previous/next step on `left/right` arrow keys (in step view)
|
||||
|
||||
## Configuration
|
||||
|
||||
|
@ -66,51 +68,52 @@ The main API for configuring a tour is the config object. See example usage and
|
|||
|
||||
`config.steps`: An array of objects that define the content we wish to render on the page. Each step defined by:
|
||||
|
||||
- `referenceElements` (optional): A set of `desktop` & `mobile` selectors to render the step near.
|
||||
- `focusElement` (optional): A set of `desktop` & `mobile` & `iframe` selectors to automatically focus.
|
||||
- `meta`: Arbitrary object that encloses the content we want to render for each step.
|
||||
- `classNames` (optional): An array or CSV of CSS classes applied to a step.
|
||||
- `referenceElements` (optional): A set of `desktop` & `mobile` selectors to render the step near.
|
||||
- `focusElement` (optional): A set of `desktop` & `mobile` & `iframe` selectors to automatically focus.
|
||||
- `meta`: Arbitrary object that encloses the content we want to render for each step.
|
||||
- `classNames` (optional): An array or CSV of CSS classes applied to a step.
|
||||
|
||||
`config.closeHandler`: The callback responsible for closing the tour.
|
||||
|
||||
- `tourStep`: A React component that will be called to render each step. Receives the following properties:
|
||||
- `tourStep`: A React component that will be called to render each step. Receives the following properties:
|
||||
|
||||
- `steps`: The steps defined for the tour.
|
||||
- `currentStepIndex`
|
||||
- `onDismiss`: Handler that dismissed/closes the tour.
|
||||
- `onNext`: Handler that progresses the tour to the next step.
|
||||
- `onPrevious`: Handler that takes the tour to the previous step.
|
||||
- `onMinimize`: Handler that minimizes the tour (passes rendering to `tourMinimized`).
|
||||
- `setInitialFocusedElement`: A dispatcher that assigns an element to be initially focused when a step renders (see examples).
|
||||
- `onGoToStep`: Handler that progresses the tour to a given step index.
|
||||
- `steps`: The steps defined for the tour.
|
||||
- `currentStepIndex`
|
||||
- `onDismiss`: Handler that dismissed/closes the tour.
|
||||
- `onNext`: Handler that progresses the tour to the next step.
|
||||
- `onPrevious`: Handler that takes the tour to the previous step.
|
||||
- `onMinimize`: Handler that minimizes the tour (passes rendering to `tourMinimized`).
|
||||
- `setInitialFocusedElement`: A dispatcher that assigns an element to be initially focused when a step renders (see examples).
|
||||
- `onGoToStep`: Handler that progresses the tour to a given step index.
|
||||
|
||||
- `tourMinimized`: A React component that will be called to render a minimized view for the tour. Receives the following properties:
|
||||
- `steps`: The steps defined for the tour.
|
||||
- `currentStepIndex`
|
||||
- `onDismiss`: Handler that dismissed/closes the tour.
|
||||
- `onMaximize`: Handler that expands the tour (passes rendering to `tourStep`).
|
||||
- `tourMinimized`: A React component that will be called to render a minimized view for the tour. Receives the following properties:
|
||||
- `steps`: The steps defined for the tour.
|
||||
- `currentStepIndex`
|
||||
- `onDismiss`: Handler that dismissed/closes the tour.
|
||||
- `onMaximize`: Handler that expands the tour (passes rendering to `tourStep`).
|
||||
|
||||
`config.options` (optional):
|
||||
|
||||
- `classNames` (optional): An array or CSV of CSS classes to enclose the main tour frame with.
|
||||
- `classNames` (optional): An array or CSV of CSS classes to enclose the main tour frame with.
|
||||
|
||||
- `effects`: An object to enable/disable/combine various tour effects:
|
||||
- `effects`: An object to enable/disable/combine various tour effects:
|
||||
|
||||
- `spotlight`: Adds a semi-transparent overlay and highlights the reference element when provided with a transparent box over it. Expects an object with optional styles to override the default highlight/spotlight behavior when provided (default: spotlight wraps the entire reference element).
|
||||
- `interactivity`: An object that configures whether the user is allowed to interact with the referenced element during the tour
|
||||
- `styles`: CSS properties that configures the styles applied to the spotlight overlay
|
||||
- `arrowIndicator`: Adds an arrow tip pointing at the reference element when provided.
|
||||
- `overlay`: Includes the semi-transparent overlay for all the steps (also blocks interactions with the rest of the page)
|
||||
- `autoScroll`: The page scrolls up and down automatically such that the step target element is visible to the user.
|
||||
- `spotlight`: Adds a semi-transparent overlay and highlights the reference element when provided with a transparent box over it. Expects an object with optional styles to override the default highlight/spotlight behavior when provided (default: spotlight wraps the entire reference element).
|
||||
- `interactivity`: An object that configures whether the user is allowed to interact with the referenced element during the tour
|
||||
- `styles`: CSS properties that configures the styles applied to the spotlight overlay
|
||||
- `arrowIndicator`: Adds an arrow tip pointing at the reference element when provided.
|
||||
- `overlay`: Includes the semi-transparent overlay for all the steps (also blocks interactions with the rest of the page)
|
||||
- `autoScroll`: The page scrolls up and down automatically such that the step target element is visible to the user.
|
||||
|
||||
- `callbacks`: An object of callbacks to handle side effects from various interactions (see [types.ts](./src/types.ts)).
|
||||
- `callbacks`: An object of callbacks to handle side effects from various interactions (see [types.ts](./src/types.ts)).
|
||||
|
||||
- `popperModifiers`: The tour uses Popper to position steps near reference elements (and for other effects). An implementation can pass its own modifiers to tailor the functionality further e.g. more offset or padding from the reference element.
|
||||
- `tourRating` (optional - only in WPCOM Tour Kit variant):
|
||||
- `enabled`: Whether to show rating in last step.
|
||||
- `useTourRating`: (optional) A hook to provide the rating from an external source/state (see [types.ts](./src/types.ts)).
|
||||
- `onTourRate`: (optional) A callback to fire off when a rating is submitted.
|
||||
- `popperModifiers`: The tour uses Popper to position steps near reference elements (and for other effects). An implementation can pass its own modifiers to tailor the functionality further e.g. more offset or padding from the reference element.
|
||||
- `tourRating` (optional - only in WPCOM Tour Kit variant):
|
||||
|
||||
- `portalElementId`: A string that lets you customize under which DOM element the Tour will be appended.
|
||||
- `enabled`: Whether to show rating in last step.
|
||||
- `useTourRating`: (optional) A hook to provide the rating from an external source/state (see [types.ts](./src/types.ts)).
|
||||
- `onTourRate`: (optional) A callback to fire off when a rating is submitted.
|
||||
|
||||
- `portalElementId`: A string that lets you customize under which DOM element the Tour will be appended.
|
||||
|
||||
`placement` (Optional) : Describes the preferred placement of the popper. Possible values are left-start, left, left-end, top-start, top, top-end, right-start, right, right-end, bottom-start, bottom, and bottom-end.
|
||||
|
|
|
@ -15,19 +15,19 @@ import { BACKSPACE } from './constants';
|
|||
* The Control Component renders a search input and also the Tags.
|
||||
* It also triggers the setExpand for expanding the options tree on click.
|
||||
*
|
||||
* @param {Object} props Component props
|
||||
* @param {Array} props.tags Array of tags
|
||||
* @param {string} props.instanceId Id of the component
|
||||
* @param {string} props.placeholder Placeholder of the search input
|
||||
* @param {boolean} props.isExpanded True if the tree is expanded
|
||||
* @param {boolean} props.alwaysShowPlaceholder Will always show placeholder (default: false)
|
||||
* @param {boolean} props.disabled True if the component is disabled
|
||||
* @param {number} props.maxVisibleTags The maximum number of tags to show. Undefined, 0 or less than 0 evaluates to "Show All".
|
||||
* @param {string} props.value The current input value
|
||||
* @param {Function} props.onFocus On Focus Callback
|
||||
* @param {Function} props.onTagsChange Callback when the Tags change
|
||||
* @param {Function} props.onInputChange Callback when the Input value changes
|
||||
* @param {Function} [props.onControlClick] Callback when clicking on the control.
|
||||
* @param {Object} props Component props
|
||||
* @param {Array} props.tags Array of tags
|
||||
* @param {string} props.instanceId Id of the component
|
||||
* @param {string} props.placeholder Placeholder of the search input
|
||||
* @param {boolean} props.isExpanded True if the tree is expanded
|
||||
* @param {boolean} props.alwaysShowPlaceholder Will always show placeholder (default: false)
|
||||
* @param {boolean} props.disabled True if the component is disabled
|
||||
* @param {number} props.maxVisibleTags The maximum number of tags to show. Undefined, 0 or less than 0 evaluates to "Show All".
|
||||
* @param {string} props.value The current input value
|
||||
* @param {Function} props.onFocus On Focus Callback
|
||||
* @param {Function} props.onTagsChange Callback when the Tags change
|
||||
* @param {Function} props.onInputChange Callback when the Input value changes
|
||||
* @param {Function} [props.onControlClick] Callback when clicking on the control.
|
||||
* @return {JSX.Element} The rendered component
|
||||
*/
|
||||
const Control = forwardRef(
|
||||
|
|
|
@ -70,7 +70,7 @@ import { ARROW_DOWN, ARROW_UP, ENTER, ESCAPE, ROOT_VALUE } from './constants';
|
|||
* @param {number} [props.maxVisibleTags] The maximum number of tags to show. Undefined, 0 or less than 0 evaluates to "Show All".
|
||||
* @param {Function} [props.onChange] Callback when the selector changes
|
||||
* @param {(visible: boolean) => void} [props.onDropdownVisibilityChange] Callback when the visibility of the dropdown options is changed.
|
||||
* @param {Function} [props.onInputChange] Callback when the selector changes
|
||||
* @param {Function} [props.onInputChange] Callback when the selector changes
|
||||
* @return {JSX.Element} The component
|
||||
*/
|
||||
const TreeSelectControl = ( {
|
||||
|
|
|
@ -64,7 +64,7 @@ function createOrderedChildren< T = Fill.Props, S = Record< string, unknown > >(
|
|||
order: number,
|
||||
props: T,
|
||||
injectProps?: S
|
||||
) {
|
||||
): React.ReactElement {
|
||||
const { children: childrenToRender, props: propsToRender } =
|
||||
getChildrenAndProps( children, order, props, injectProps );
|
||||
return cloneElement( childrenToRender, propsToRender );
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
{
|
||||
"extends": "../tsconfig-cjs",
|
||||
"compilerOptions": {
|
||||
"outDir": "build"
|
||||
"outDir": "build",
|
||||
"typeRoots": [
|
||||
"./typings",
|
||||
"./node_modules/@types"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"declarationDir": "./build-types",
|
||||
"composite": true
|
||||
"typeRoots": [
|
||||
"./typings",
|
||||
"./node_modules/@types"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -12,6 +12,7 @@ module.exports = {
|
|||
path: __dirname,
|
||||
},
|
||||
module: {
|
||||
parser: webpackConfig.parser,
|
||||
rules: webpackConfig.rules,
|
||||
},
|
||||
plugins: webpackConfig.plugins,
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
Comment: TypeScript build change
|
||||
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
Comment: Configuration change only
|
||||
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
Comment: Configuration change only
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
"rootDir": "./src",
|
||||
"preset": "../../internal-js-tests/jest.config.js"
|
||||
"preset": "../node_modules/@woocommerce/internal-js-tests/jest-preset.js"
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
"types": "build-types",
|
||||
"react-native": "src/index",
|
||||
"dependencies": {
|
||||
"@types/node": "^16.18.18",
|
||||
"browser-filesaver": "^1.1.1",
|
||||
"moment": "^2.29.1"
|
||||
},
|
||||
|
@ -33,7 +34,7 @@
|
|||
"access": "public"
|
||||
},
|
||||
"scripts": {
|
||||
"turbo:build": "tsc --build ./tsconfig.json ./tsconfig-cjs.json",
|
||||
"turbo:build": "tsc --project tsconfig.json && tsc --project tsconfig-cjs.json",
|
||||
"turbo:test": "jest --config ./jest.config.json",
|
||||
"prepare": "composer install",
|
||||
"changelog": "composer exec -- changelogger",
|
||||
|
@ -41,7 +42,7 @@
|
|||
"build": "pnpm -w exec turbo run turbo:build --filter=$npm_package_name",
|
||||
"test": "pnpm -w exec turbo run turbo:test --filter=$npm_package_name",
|
||||
"lint": "eslint src",
|
||||
"start": "tsc --build --watch",
|
||||
"start": "concurrently \"tsc --project tsconfig.json --watch\" \"tsc --project tsconfig-cjs.json --watch\"",
|
||||
"prepack": "pnpm run clean && pnpm run build",
|
||||
"lint:fix": "eslint src --fix",
|
||||
"test-staged": "jest --bail --config ./jest.config.json --findRelatedTests"
|
||||
|
@ -50,12 +51,14 @@
|
|||
"@babel/core": "^7.17.5",
|
||||
"@types/jest": "^27.4.1",
|
||||
"@woocommerce/eslint-plugin": "workspace:*",
|
||||
"@woocommerce/internal-js-tests": "workspace:*",
|
||||
"eslint": "^8.32.0",
|
||||
"jest": "^27.5.1",
|
||||
"jest-cli": "^27.5.1",
|
||||
"concurrently": "^7.0.0",
|
||||
"rimraf": "^3.0.2",
|
||||
"ts-jest": "^27.1.3",
|
||||
"typescript": "^4.8.3"
|
||||
"typescript": "^4.9.5"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.(t|j)s?(x)": [
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
{
|
||||
"extends": "../tsconfig-cjs",
|
||||
"compilerOptions": {
|
||||
"outDir": "build"
|
||||
"outDir": "build",
|
||||
"typeRoots": [
|
||||
"./typings",
|
||||
"./node_modules/@types"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue