Merge branch 'woocommerce:trunk' into autocomplete-signup

This commit is contained in:
dhjw 2022-01-25 19:43:26 -08:00 committed by GitHub
commit af347d3dc0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 515 additions and 226 deletions

View File

@ -3,7 +3,7 @@ on:
workflow_dispatch:
inputs:
ref:
description: 'By default the zip file is generated from the branch the workflow runs from, but you can specify an explicit reference to use instead here (e.g. refs/tags/tag_name). The resulting file will be available as an artifact on the workflow run.'
description: 'By default the zip file is generated from the branch the workflow runs from, but you can specify an explicit reference to use instead here (e.g. refs/tags/tag_name or refs/heads/release/x.x). The resulting file will be available as an artifact on the workflow run.'
required: false
default: ''
jobs:

120
.github/workflows/triage-replies.yml vendored Normal file
View File

@ -0,0 +1,120 @@
name: Add issue triage comments.
on:
issues:
types:
- labeled
jobs:
add-dev-comment:
if: "github.event.label.name == 'needs developer feedback'"
runs-on: ubuntu-latest
permissions:
issues: write
steps:
- name: Add developer feedback comment
uses: actions/github-script@v5
with:
github-token: ${{ secrets.WC_BOT_TRIAGE_TOKEN }}
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: 'Hi @${{ github.event.issue.user.login }},\n\n\
Thank you for opening the issue! It requires further feedback from the WooCommerce Core team.\n\n\
We are adding the `needs developer feedback` label to this issue so that the Core team could take a look.\n\n\
Please note it may take a few days for them to get to this issue. Thank you for your patience.'
})
add-reproduction-comment:
if: "github.event.label.name == 'status: needs reproduction'"
runs-on: ubuntu-latest
permissions:
issues: write
steps:
- name: Add needs reproduction comment
uses: actions/github-script@v5
with:
github-token: ${{ secrets.WC_BOT_TRIAGE_TOKEN }}
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: 'We are adding the `status: needs reproduction` label to this issue to try reproduce it on the \
current released version of WooCommerce.\n\n\
Thank you for your patience.'
})
add-support-comment:
if: "github.event.label.name == 'type: support request'"
runs-on: ubuntu-latest
permissions:
issues: write
steps:
- name: Add support request comment
uses: actions/github-script@v5
with:
github-token: ${{ secrets.WC_BOT_TRIAGE_TOKEN }}
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: 'Hi @${{ github.event.issue.user.login }},\n\n\
While our goal is to address all the issues reported in this repository, \
GitHub should be treated as a place to report confirmed bugs only.\n\n\
The type of issue you submitted looks like a support request which may or may not reveal a bug once proper \
troubleshooting is done. In order to confirm the bug, please follow one of the steps below:\n\n\
- Review [WooCommerce Self-Service Guide](https://docs.woocommerce.com/document/woocommerce-self-service-guide/) \
to see if the solutions listed there apply to your case;\n\
- If you are a paying customer of WooCommerce, contact WooCommerce support by \
[opening a ticket or starting a live chat](https://woocommerce.com/contact-us/);\n\
- Make a post on [WooCommerce community forum](https://wordpress.org/support/plugin/woocommerce/)\n\n\
If you confirm the bug, please provide us with clear steps to reproduce it.\n\n\
We are closing this issue for now as it seems to be a support request and not a bug. \
If we missed something, please leave a comment and we will take a second look.'
})
- name: Close support request issue
uses: actions/github-script@v5
with:
github-token: ${{ secrets.WC_BOT_TRIAGE_TOKEN }}
script: |
github.rest.issues.update({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
state: 'closed'
})
add-votes-comment:
if: "github.event.label.name == 'votes needed'"
runs-on: ubuntu-latest
permissions:
issues: write
steps:
- name: Add votes needed comment
uses: actions/github-script@v5
with:
github-token: ${{ secrets.WC_BOT_TRIAGE_TOKEN }}
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: 'Thanks for the suggestion @${{ github.event.issue.user.login }},\n\n\
While we appreciate you sharing your ideas with us, it doesnt fit in with our current priorities for the project.\n\
At some point, we may revisit our priorities and look through the list of suggestions like this one to see if it \
warrants a second look.\n\n\
In the meantime, we are going to close this issue with the `votes needed` label and evaluate over time if this \
issue collects more feedback.\n\n\
Dont be alarmed if you dont see any activity on this issue for a while. \
We'll keep an eye on the popularity of this request.'
})
- name: Close votes needed issue
uses: actions/github-script@v5
with:
github-token: ${{ secrets.WC_BOT_TRIAGE_TOKEN }}
script: |
github.rest.issues.update({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
state: 'closed'
})

View File

@ -5,7 +5,6 @@
## Added
- This package is now transpiled with Babel, which allows the usage of modern, yet compatible JS code.
- A `specs/data` folder to store page element data.
- Tests to verify that different top-level menu and their associated sub-menus load successfully.
- Test scaffolding via `npx wc-e2e install @woocommerce/e2e-core-tests`

View File

@ -9,8 +9,8 @@ const {
uiUnblocked,
evalAndClick,
clickUpdateOrder,
waitForSelector,
} = require( '@woocommerce/e2e-utils' );
const { waitForSelector } = require( '@woocommerce/e2e-environment' );
/**
* Evaluate and click a button selector then wait for a result selector.

View File

@ -1,43 +1,32 @@
# Unreleased
## Fixed
- Added the `resolveSingleE2EPath` method which builds a path to a specific E2E test
- It still supports the use of `plugins/woocommerce` and/or `tests/e2e` in file paths to avoid any breaking changes
## Fixed
- Added the ability to take screenshots from multiple test failures (when retried) in `utils/take-screenshot.js`.
## Added
- Added `post-results-to-github-pr.js` to post smoke test results to a GitHub PR.
- Added jest flags to generate a json test report
- Added more entries to `default.json`
- Print the full path to `test-results.json` when the tests ends to make it easier to find the test results file.
## Added
- Save `test-results.json` from test runs to the `tests/e2e` folder.
- Added `await` for every call to `shopper.logout`
- Updated `getLatestReleaseZipUrl()` to allow passing in an authorization token and simplified arguments to just the repository name
- Added `upload.ini` which increases the limits for uploading files (such as for plugins) in the Docker environment
- Test setup, scaffolding, and removal via `wc-e2e install` and `wc-e2e uninstall`
## Fixed
- Updated the browserViewport in `jest.setup.js` to match the `defaultViewport` dimensions defined in `jest-puppeteer.config.js`
## Added
- Added quotes around `WORDPRESS_TITLE` value in .env file to address issue with docker compose 2 "key cannot contain a space" error.
- Added `LATEST_WP_VERSION_MINUS` that allows setting a number to subtract from the current WordPress version for the WordPress Docker image.
- Support for PHP_VERSION, MARIADB_VERSION environment variables for built in container initialization
- `resolveLocalE2ePath` to resolve path to local E2E file
- `WC_E2E_FOLDER` for mapping plugin root to path within repo
- Added the `resolveSingleE2EPath` method which builds a path to a specific E2E test
- Added the ability to take screenshots from multiple test failures (when retried) in `utils/take-screenshot.js`.
## Changed
- Updated `getLatestReleaseZipUrl()` to allow passing in an authorization token and simplified arguments to just the repository name
## Fixed
- Updated the browserViewport in `jest.setup.js` to match the `defaultViewport` dimensions defined in `jest-puppeteer.config.js`
- Use consistent `defaultViewport` in both headless and non-headless context
- Add missing `config` dependency
# 0.2.3

View File

@ -114,6 +114,10 @@ await takeScreenshotFor( 'name of current step' );
Screenshots will be saved to `tests/e2e/screenshots`. This folder is cleared at the beginning of each test run.
#### Test results
The test results are saved in `json` format in `tests/e2e/test-results.json`.
### Override default test timeout
To override the default timeout for the tests, you can use the `DEFAULT_TIMEOUT_OVERRIDE` flag and pass in a maximum timeout in milliseconds. For example, you can pass it in when running the tests from the command line:

View File

@ -76,7 +76,7 @@ if ( program.args.length == 1 ) {
}
let jestCommand = 'jest';
let outputFile = resolveLocalE2ePath('/test-results.json');
let outputFile = 'test-results.json';
const jestArgs = [
'--maxWorkers=1',
'--rootDir=./',
@ -111,7 +111,11 @@ const jestProcess = spawnSync( jestCommand, jestArgs, {
env: envVars,
} );
console.log( 'Test result file path: ' + outputFile );
let results = resolvePackagePath( outputFile );
if ( fs.existsSync( results ) ) {
let localResults = resolveLocalE2ePath( outputFile );
fs.copyFileSync( results, localResults );
}
console.log( 'Jest exit code: ' + jestProcess.status );
// Pass Jest exit code to npm

View File

@ -29,6 +29,7 @@
"@wordpress/jest-preset-default": "^7.1.3",
"app-root-path": "^3.0.0",
"commander": "4.1.1",
"config": "3.3.3",
"jest": "^25.1.0",
"jest-circus": "25.1.0",
"jest-each": "25.5.0",

View File

@ -1,6 +1,6 @@
{
"require-dev": {
"woocommerce/woocommerce-sniffs": "^0.1.0"
"woocommerce/woocommerce-sniffs": "^0.1.2"
},
"config": {
"platform": {

View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "c50f65dd9f9a26d397f7bb30228d7a88",
"content-hash": "51112a9a1fd6cd39c29579a93a59cf9c",
"packages": [],
"packages-dev": [
{
@ -286,16 +286,16 @@
},
{
"name": "woocommerce/woocommerce-sniffs",
"version": "0.1.1",
"version": "0.1.2",
"source": {
"type": "git",
"url": "https://github.com/woocommerce/woocommerce-sniffs.git",
"reference": "eb604d751b61c42f31ff1aa24113c7c0de438553"
"reference": "5566270d280a300bc24bd0cb055a8b9325afdd6b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/woocommerce/woocommerce-sniffs/zipball/eb604d751b61c42f31ff1aa24113c7c0de438553",
"reference": "eb604d751b61c42f31ff1aa24113c7c0de438553",
"url": "https://api.github.com/repos/woocommerce/woocommerce-sniffs/zipball/5566270d280a300bc24bd0cb055a8b9325afdd6b",
"reference": "5566270d280a300bc24bd0cb055a8b9325afdd6b",
"shasum": ""
},
"require": {
@ -322,7 +322,11 @@
"woocommerce",
"wordpress"
],
"time": "2021-07-29T17:25:16+00:00"
"support": {
"issues": "https://github.com/woocommerce/woocommerce-sniffs/issues",
"source": "https://github.com/woocommerce/woocommerce-sniffs/tree/0.1.2"
},
"time": "2022-01-21T20:13:23+00:00"
},
{
"name": "wp-coding-standards/wpcs",
@ -381,5 +385,5 @@
"platform-overrides": {
"php": "7.0"
},
"plugin-api-version": "1.1.0"
"plugin-api-version": "2.2.0"
}

View File

@ -21,8 +21,8 @@
"pelago/emogrifier": "3.1.0",
"psr/container": "1.0.0",
"woocommerce/action-scheduler": "3.4.0",
"woocommerce/woocommerce-admin": "3.1.0-rc.1",
"woocommerce/woocommerce-blocks": "6.7.1"
"woocommerce/woocommerce-admin": "3.1.0",
"woocommerce/woocommerce-blocks": "6.7.3"
},
"require-dev": {
"bamarni/composer-bin-plugin": "^1.4",

View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "edd58bb30d9ec1e9ba74f499fb4a919b",
"content-hash": "d9b680722733ec1fae9414023f943830",
"packages": [
{
"name": "automattic/jetpack-autoloader",
@ -543,16 +543,16 @@
},
{
"name": "woocommerce/woocommerce-admin",
"version": "3.1.0-rc.1",
"version": "3.1.0",
"source": {
"type": "git",
"url": "https://github.com/woocommerce/woocommerce-admin.git",
"reference": "0c7a42f0c934f7f2e44c0534e2cec6fcb8362180"
"reference": "59dfff627d9b7b1d5396686e69b709a820f5e7e5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/woocommerce/woocommerce-admin/zipball/0c7a42f0c934f7f2e44c0534e2cec6fcb8362180",
"reference": "0c7a42f0c934f7f2e44c0534e2cec6fcb8362180",
"url": "https://api.github.com/repos/woocommerce/woocommerce-admin/zipball/59dfff627d9b7b1d5396686e69b709a820f5e7e5",
"reference": "59dfff627d9b7b1d5396686e69b709a820f5e7e5",
"shasum": ""
},
"require": {
@ -608,22 +608,22 @@
"homepage": "https://github.com/woocommerce/woocommerce-admin",
"support": {
"issues": "https://github.com/woocommerce/woocommerce-admin/issues",
"source": "https://github.com/woocommerce/woocommerce-admin/tree/v3.1.0-rc.1"
"source": "https://github.com/woocommerce/woocommerce-admin/tree/v3.1.0"
},
"time": "2022-01-13T02:42:30+00:00"
"time": "2022-01-25T02:36:40+00:00"
},
{
"name": "woocommerce/woocommerce-blocks",
"version": "v6.7.1",
"version": "v6.7.3",
"source": {
"type": "git",
"url": "https://github.com/woocommerce/woocommerce-gutenberg-products-block.git",
"reference": "d215803d7310046050bde26420c3082edcdbf866"
"reference": "742439da222272235190cbf14cc5ea0d4f178fa5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/woocommerce/woocommerce-gutenberg-products-block/zipball/d215803d7310046050bde26420c3082edcdbf866",
"reference": "d215803d7310046050bde26420c3082edcdbf866",
"url": "https://api.github.com/repos/woocommerce/woocommerce-gutenberg-products-block/zipball/742439da222272235190cbf14cc5ea0d4f178fa5",
"reference": "742439da222272235190cbf14cc5ea0d4f178fa5",
"shasum": ""
},
"require": {
@ -662,9 +662,9 @@
],
"support": {
"issues": "https://github.com/woocommerce/woocommerce-gutenberg-products-block/issues",
"source": "https://github.com/woocommerce/woocommerce-gutenberg-products-block/tree/v6.7.1"
"source": "https://github.com/woocommerce/woocommerce-gutenberg-products-block/tree/v6.7.3"
},
"time": "2022-01-07T16:15:03+00:00"
"time": "2022-01-24T10:38:10+00:00"
}
],
"packages-dev": [

View File

@ -545,7 +545,7 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
// If setting the status, ensure it's set to a valid status.
if ( true === $this->object_read ) {
// Only allow valid new status.
if ( ! in_array( 'wc-' . $new_status, $this->get_valid_statuses(), true ) && 'trash' !== $new_status ) {
if ( ! in_array( 'wc-' . $new_status, $this->get_valid_statuses(), true ) && 'trash' !== $new_status && 'auto-draft' !== $new_status ) {
$new_status = 'pending';
}

View File

@ -57,7 +57,7 @@ class WC_Admin_Menus {
$woocommerce_icon = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDI0IDEwMjQiPjxwYXRoIGZpbGw9IiNhMmFhYjIiIGQ9Ik02MTIuMTkyIDQyNi4zMzZjMC02Ljg5Ni0zLjEzNi01MS42LTI4LTUxLjYtMzcuMzYgMC00Ni43MDQgNzIuMjU2LTQ2LjcwNCA4Mi42MjQgMCAzLjQwOCAzLjE1MiA1OC40OTYgMjguMDMyIDU4LjQ5NiAzNC4xOTItLjAzMiA0Ni42NzItNzIuMjg4IDQ2LjY3Mi04OS41MnptMjAyLjE5MiAwYzAtNi44OTYtMy4xNTItNTEuNi0yOC4wMzItNTEuNi0zNy4yOCAwLTQ2LjYwOCA3Mi4yNTYtNDYuNjA4IDgyLjYyNCAwIDMuNDA4IDMuMDcyIDU4LjQ5NiAyNy45NTIgNTguNDk2IDM0LjE5Mi0uMDMyIDQ2LjY4OC03Mi4yODggNDYuNjg4LTg5LjUyek0xNDEuMjk2Ljc2OGMtNjguMjI0IDAtMTIzLjUwNCA1NS40ODgtMTIzLjUwNCAxMjMuOTJ2NjUwLjcyYzAgNjguNDMyIDU1LjI5NiAxMjMuOTIgMTIzLjUwNCAxMjMuOTJoMzM5LjgwOGwxMjMuNTA0IDEyMy45MzZWODk5LjMyOGgyNzguMDQ4YzY4LjIyNCAwIDEyMy41Mi01NS40NzIgMTIzLjUyLTEyMy45MnYtNjUwLjcyYzAtNjguNDMyLTU1LjI5Ni0xMjMuOTItMTIzLjUyLTEyMy45MmgtNzQxLjM2em01MjYuODY0IDQyMi4xNmMwIDU1LjA4OC0zMS4wODggMTU0Ljg4LTEwMi42NCAxNTQuODgtNi4yMDggMC0xOC40OTYtMy42MTYtMjUuNDI0LTYuMDE2LTMyLjUxMi0xMS4xNjgtNTAuMTkyLTQ5LjY5Ni01Mi4zNTItNjYuMjU2IDAgMC0zLjA3Mi0xNy43OTItMy4wNzItNDAuNzUyIDAtMjIuOTkyIDMuMDcyLTQ1LjMyOCAzLjA3Mi00NS4zMjggMTUuNTUyLTc1LjcyOCA0My41NTItMTA2LjczNiA5Ni40NDgtMTA2LjczNiA1OS4wNzItLjAzMiA4My45NjggNTguNTI4IDgzLjk2OCAxMTAuMjA4ek00ODYuNDk2IDMwMi40YzAgMy4zOTItNDMuNTUyIDE0MS4xNjgtNDMuNTUyIDIxMy40MjR2NzUuNzEyYy0yLjU5MiAxMi4wOC00LjE2IDI0LjE0NC0yMS44MjQgMjQuMTQ0LTQ2LjYwOCAwLTg4Ljg4LTE1MS40NzItOTIuMDE2LTE2MS44NC02LjIwOCA2Ljg5Ni02Mi4yNCAxNjEuODQtOTYuNDQ4IDE2MS44NC0yNC44NjQgMC00My41NTItMTEzLjY0OC00Ni42MDgtMTIzLjkzNkMxNzYuNzA0IDQzNi42NzIgMTYwIDMzNC4yMjQgMTYwIDMyNy4zMjhjMC0yMC42NzIgMS4xNTItMzguNzM2IDI2LjA0OC0zOC43MzYgNi4yMDggMCAyMS42IDYuMDY0IDIzLjcxMiAxNy4xNjggMTEuNjQ4IDYyLjAzMiAxNi42ODggMTIwLjUxMiAyOS4xNjggMTg1Ljk2OCAxLjg1NiAyLjkyOCAxLjUwNCA3LjAwOCA0LjU2IDEwLjQzMiAzLjE1Mi0xMC4yODggNjYuOTI4LTE2OC43ODQgOTQuOTYtMTY4Ljc4NCAyMi41NDQgMCAzMC40IDQ0LjU5MiAzMy41MzYgNjEuODI0IDYuMjA4IDIwLjY1NiAxMy4wODggNTUuMjE2IDIyLjQxNiA4Mi43NTIgMC0xMy43NzYgMTIuNDgtMjAzLjEyIDY1LjM5Mi0yMDMuMTIgMTguNTkyLjAzMiAyNi43MDQgNi45MjggMjYuNzA0IDI3LjU2OHpNODcwLjMyIDQyMi45MjhjMCA1NS4wODgtMzEuMDg4IDE1NC44OC0xMDIuNjQgMTU0Ljg4LTYuMTkyIDAtMTguNDQ4LTMuNjE2LTI1LjQyNC02LjAxNi0zMi40MzItMTEuMTY4LTUwLjE3Ni00OS42OTYtNTIuMjg4LTY2LjI1NiAwIDAtMy44ODgtMTcuOTItMy44ODgtNDAuODk2czMuODg4LTQ1LjE4NCAzLjg4OC00NS4xODRjMTUuNTUyLTc1LjcyOCA0My40ODgtMTA2LjczNiA5Ni4zODQtMTA2LjczNiA1OS4xMDQtLjAzMiA4My45NjggNTguNTI4IDgzLjk2OCAxMTAuMjA4eiIvPjwvc3ZnPg==';
if ( current_user_can( 'edit_others_shop_orders' ) ) {
if ( self::can_view_woocommerce_menu_item() ) {
$menu[] = array( '', 'read', 'separator-woocommerce', '', 'wp-menu-separator woocommerce' ); // WPCS: override ok.
}
@ -70,7 +70,7 @@ class WC_Admin_Menus {
* Add menu item.
*/
public function reports_menu() {
if ( current_user_can( 'edit_others_shop_orders' ) ) {
if ( self::can_view_woocommerce_menu_item() ) {
add_submenu_page( 'woocommerce', __( 'Reports', 'woocommerce' ), __( 'Reports', 'woocommerce' ), 'view_woocommerce_reports', 'wc-reports', array( $this, 'reports_page' ) );
} else {
add_menu_page( __( 'Sales reports', 'woocommerce' ), __( 'Sales reports', 'woocommerce' ), 'view_woocommerce_reports', 'wc-reports', array( $this, 'reports_page' ), 'dashicons-chart-bar', '55.6' );
@ -86,6 +86,13 @@ class WC_Admin_Menus {
add_action( 'load-' . $settings_page, array( $this, 'settings_page_init' ) );
}
/**
* Check if the user can access the top-level WooCommerce item.
*/
public static function can_view_woocommerce_menu_item() {
return current_user_can( 'edit_others_shop_orders' );
}
/**
* Loads gateways and shipping methods into memory for use within settings.
*/
@ -241,7 +248,7 @@ class WC_Admin_Menus {
* @return bool
*/
public function custom_menu_order( $enabled ) {
return $enabled || current_user_can( 'edit_others_shop_orders' );
return $enabled || self::can_view_woocommerce_menu_item();
}
/**

View File

@ -57,8 +57,9 @@ defined( 'ABSPATH' ) || exit;
* @since 3.6.0
*
* @param WP_Post $variation Post data.
* @param int $loop Position in the loop.
*/
do_action( 'woocommerce_variation_header', $variation );
do_action( 'woocommerce_variation_header', $variation, $loop );
?>
</h3>
<div class="woocommerce_variable_attributes wc-metabox-content" style="display: none;">

View File

@ -1056,7 +1056,6 @@ class WC_Countries {
'GT' => array(
'postcode' => array(
'required' => false,
'hidden' => true,
),
'state' => array(
'label' => __( 'Department', 'woocommerce' ),

View File

@ -169,6 +169,10 @@ class WC_Install {
'wc_update_600_migrate_rate_limit_options',
'wc_update_600_db_version',
),
'6.3.0' => array(
'wc_update_630_create_product_attributes_lookup_table',
'wc_update_630_db_version',
),
);
/**
@ -586,22 +590,22 @@ class WC_Install {
$pages = apply_filters(
'woocommerce_create_pages',
array(
'shop' => array(
'shop' => array(
'name' => _x( 'shop', 'Page slug', 'woocommerce' ),
'title' => _x( 'Shop', 'Page title', 'woocommerce' ),
'content' => '',
),
'cart' => array(
'cart' => array(
'name' => _x( 'cart', 'Page slug', 'woocommerce' ),
'title' => _x( 'Cart', 'Page title', 'woocommerce' ),
'content' => '<!-- wp:shortcode -->[' . apply_filters( 'woocommerce_cart_shortcode_tag', 'woocommerce_cart' ) . ']<!-- /wp:shortcode -->',
),
'checkout' => array(
'checkout' => array(
'name' => _x( 'checkout', 'Page slug', 'woocommerce' ),
'title' => _x( 'Checkout', 'Page title', 'woocommerce' ),
'content' => '<!-- wp:shortcode -->[' . apply_filters( 'woocommerce_checkout_shortcode_tag', 'woocommerce_checkout' ) . ']<!-- /wp:shortcode -->',
),
'myaccount' => array(
'myaccount' => array(
'name' => _x( 'my-account', 'Page slug', 'woocommerce' ),
'title' => _x( 'My account', 'Page title', 'woocommerce' ),
'content' => '<!-- wp:shortcode -->[' . apply_filters( 'woocommerce_my_account_shortcode_tag', 'woocommerce_my_account' ) . ']<!-- /wp:shortcode -->',

View File

@ -184,6 +184,6 @@ abstract class WC_CSV_Batch_Exporter extends WC_CSV_Exporter {
* @return int
*/
public function get_percent_complete() {
return $this->total_rows ? floor( ( $this->get_total_exported() / $this->total_rows ) * 100 ) : 100;
return $this->total_rows ? (int) floor( ( $this->get_total_exported() / $this->total_rows ) * 100 ) : 100;
}
}

View File

@ -924,7 +924,7 @@ class WC_REST_Orders_V2_Controller extends WC_REST_CRUD_Controller {
* @return array
*/
protected function get_order_statuses() {
$order_statuses = array();
$order_statuses = array( 'auto-draft' );
foreach ( array_keys( wc_get_order_statuses() ) as $status ) {
$order_statuses[] = str_replace( 'wc-', '', $status );

View File

@ -11,6 +11,8 @@
defined( 'ABSPATH' ) || exit;
use Automattic\WooCommerce\Internal\AssignDefaultCategory;
use Automattic\WooCommerce\Internal\ProductAttributesLookup\DataRegenerator;
use Automattic\WooCommerce\Internal\ProductAttributesLookup\LookupDataStore;
/**
* Update file paths for 2.0
@ -2306,7 +2308,7 @@ function wc_update_560_db_version() {
function wc_update_600_migrate_rate_limit_options() {
global $wpdb;
$rate_limits = $wpdb->get_results(
$rate_limits = $wpdb->get_results(
"
SELECT option_name, option_value
FROM $wpdb->options
@ -2335,3 +2337,28 @@ function wc_update_600_migrate_rate_limit_options() {
function wc_update_600_db_version() {
WC_Install::update_db_version( '6.0.0' );
}
/**
* Create the product attributes lookup table and initiate its filling,
* unless the table had been already created manually (via the tools page).
*
* @return false Always false, since the LookupDataStore class handles all the data filling process.
*/
function wc_update_630_create_product_attributes_lookup_table() {
$data_store = wc_get_container()->get( LookupDataStore::class );
if ( $data_store->check_lookup_table_exists() ) {
return false;
}
$data_regenerator = wc_get_container()->get( DataRegenerator::class );
$data_regenerator->initiate_regeneration();
return false;
}
/**
*
* Update DB version to 6.3.0.
*/
function wc_update_630_db_version() {
WC_Install::update_db_version( '6.3.0' );
}

View File

@ -185,7 +185,7 @@ $tt2-gray: #f7f7f7;
button[name='add-to-cart'],
input[name='submit'],
button.single_add_to_cart_button,
button[type='submit'] {
button[type='submit']:not(.wp-block-search__button) {
display: inline-block;
text-align: center;
word-break: break-word;
@ -294,10 +294,20 @@ $tt2-gray: #f7f7f7;
border-radius: 1rem;
border-style: solid;
line-height: 1.5rem;
padding: 0 0.5rem 0 0.5rem;
padding: 0;
font-size: 0.6rem;
background: var( --wp--preset--color--white );;
background: var( --wp--preset--color--white );
border-color: var( --wp--preset--color--white );
height: 1.5rem;
width: 1.5rem;
overflow: hidden;
&::before {
content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" focusable="false" viewBox="0 0 24 24" width="24" height="24"><path d="M13.5 6C10.5 6 8 8.5 8 11.5c0 1.1.3 2.1.9 3l-3.4 3 1 1.1 3.4-2.9c1 .9 2.2 1.4 3.6 1.4 3 0 5.5-2.5 5.5-5.5C19 8.5 16.5 6 13.5 6zm0 9.5c-2.2 0-4-1.8-4-4s1.8-4 4-4 4 1.8 4 4-1.8 4-4 4z" /></svg>');
display: block;
transform: rotateY(180deg);
margin-left: 1.55rem;
}
}
figure.woocommerce-product-gallery__wrapper {
@ -747,6 +757,12 @@ $tt2-gray: #f7f7f7;
color: var(--wp--preset--color--black);
}
}
&.woocommerce-orders-table__cell-order-actions {
a.button {
display: block;
}
}
}
}
}
@ -884,7 +900,8 @@ $tt2-gray: #f7f7f7;
}
}
.woocommerce-checkout {
.woocommerce-checkout,
&.woocommerce-order-pay {
display: table;
h3 {
@ -923,11 +940,13 @@ $tt2-gray: #f7f7f7;
.woocommerce-billing-fields__field-wrapper,
.woocommerce-checkout-review-order-table,
.woocommerce-checkout-payment {
.woocommerce-checkout-payment,
#payment {
margin-top: 4rem;
}
.woocommerce-checkout-review-order-table {
.woocommerce-checkout-review-order-table,
#order_review .shop_table {
border-collapse: collapse;
width: 100%;
@ -1204,3 +1223,44 @@ $tt2-gray: #f7f7f7;
}
}
}
.wp-block-search {
.wp-block-search__label {
font-weight: normal;
}
.wp-block-search__input {
padding: .9rem 1.1rem;
border: 1px solid var(--wp--preset--color--black);
}
.wp-block-search__button {
padding: 1rem 1.2rem;
}
}
.wc-block-product-search {
form {
.wc-block-product-search__fields {
display: flex;
flex: auto;
flex-wrap: nowrap;
max-width: 100%;
.wc-block-product-search__field {
padding: .9rem 1.1rem;
flex-grow: 1;
border: 1px solid var(--wp--preset--color--black);
font-size: inherit;
font-family: inherit;
}
.wc-block-product-search__button {
display: flex;
background-color: var( --wp--preset--color--primary );
color: #fff;
border: 1px solid var(--wp--preset--color--black);
padding: 1rem 1.2rem;
margin: 0 0 0 .7rem;
}
}
}
}

View File

@ -548,7 +548,7 @@ dl.variation,
margin-right: 0.5rem;
}
input {
input[type="number"] {
width: 5em;
}
}

View File

@ -21,7 +21,9 @@ defined( 'ABSPATH' ) || exit;
* the data store classes) whenever a product is created/updated.
*
* Additionally, after the regeneration is completed a 'woocommerce_attribute_lookup_enabled' option
* with a value of 'no' will have been created.
* with a value of 'yes' will have been created, thus effectively enabling the table usage
* (with an exception: if the regeneration was manually aborted via deleting the
* 'woocommerce_attribute_lookup_regeneration_in_progress' option) the option will be set to 'no'.
*
* This class also adds two entries to the Status - Tools menu: one for manually regenerating the table contents,
* and another one for enabling or disabling the actual lookup table usage.
@ -84,16 +86,11 @@ class DataRegenerator {
* deletes the lookup table and related options if they exist,
* then it creates the table and runs the first step of the regeneration process.
*
* This is the method that should be used as a callback for a data regeneration in wc-update-functions, e.g.:
*
* function wc_update_XX_regenerate_product_attributes_lookup_table() {
* wc_get_container()->get(DataRegenerator::class)->initiate_regeneration();
* return false;
* }
*
* (Note how we are returning "false" since the class handles the step scheduling by itself).
* This method is intended ONLY to be used as a callback for a db update in wc-update-functions,
* regeneration triggered from the tools page will use initiate_regeneration_from_tools_page instead.
*/
public function initiate_regeneration() {
$this->data_store->unset_regeneration_aborted_flag();
$this->enable_or_disable_lookup_table_usage( false );
$this->delete_all_attributes_lookup_data();
@ -101,23 +98,19 @@ class DataRegenerator {
if ( $products_exist ) {
$this->enqueue_regeneration_step_run();
} else {
$this->finalize_regeneration();
$this->finalize_regeneration( true );
}
}
/**
* Delete all the existing data related to the lookup table, including the table itself.
*
* Shortcut to run this method in case the debug tools UI isn't available or for quick debugging:
*
* wp eval "wc_get_container()->get(Automattic\WooCommerce\Internal\ProductAttributesLookup\DataRegenerator::class)->delete_all_attributes_lookup_data();"
*/
public function delete_all_attributes_lookup_data() {
private function delete_all_attributes_lookup_data() {
global $wpdb;
delete_option( 'woocommerce_attribute_lookup_enabled' );
delete_option( 'woocommerce_attribute_lookup_last_product_id_to_process' );
delete_option( 'woocommerce_attribute_lookup_last_products_page_processed' );
delete_option( 'woocommerce_attribute_lookup_processed_count' );
$this->data_store->unset_regeneration_in_progress_flag();
// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
@ -167,7 +160,7 @@ CREATE TABLE ' . $this->lookup_table_name . '(
$this->data_store->set_regeneration_in_progress_flag();
update_option( 'woocommerce_attribute_lookup_last_product_id_to_process', current( $last_existing_product_id ) );
update_option( 'woocommerce_attribute_lookup_last_products_page_processed', 0 );
update_option( 'woocommerce_attribute_lookup_processed_count', 0 );
return true;
}
@ -178,6 +171,10 @@ CREATE TABLE ' . $this->lookup_table_name . '(
*/
private function run_regeneration_step_callback() {
if ( ! $this->data_store->regeneration_is_in_progress() ) {
// No regeneration in progress at this point means that the regeneration process
// was manually aborted via deleting the 'woocommerce_attribute_lookup_regeneration_in_progress' option.
$this->data_store->set_regeneration_aborted_flag();
$this->finalize_regeneration( false );
return;
}
@ -185,7 +182,7 @@ CREATE TABLE ' . $this->lookup_table_name . '(
if ( $result ) {
$this->enqueue_regeneration_step_run();
} else {
$this->finalize_regeneration();
$this->finalize_regeneration( true );
}
}
@ -209,14 +206,21 @@ CREATE TABLE ' . $this->lookup_table_name . '(
* @return bool True if more steps need to be run, false otherwise.
*/
private function do_regeneration_step() {
$last_products_page_processed = get_option( 'woocommerce_attribute_lookup_last_products_page_processed' );
$current_products_page = (int) $last_products_page_processed + 1;
/**
* Filter to alter the count of products that will be processed in each step of the product attributes lookup table regeneration process.
*
* @since 6.3
* @param int $count Default processing step size.
*/
$products_per_generation_step = apply_filters( 'woocommerce_attribute_lookup_regeneration_step_size', self::PRODUCTS_PER_GENERATION_STEP );
$products_already_processed = get_option( 'woocommerce_attribute_lookup_processed_count', 0 );
$product_ids = WC()->call_function(
'wc_get_products',
array(
'limit' => self::PRODUCTS_PER_GENERATION_STEP,
'page' => $current_products_page,
'limit' => $products_per_generation_step,
'offset' => $products_already_processed,
'orderby' => array(
'ID' => 'ASC',
),
@ -232,7 +236,8 @@ CREATE TABLE ' . $this->lookup_table_name . '(
$this->data_store->create_data_for_product( $id );
}
update_option( 'woocommerce_attribute_lookup_last_products_page_processed', $current_products_page );
$products_already_processed += count( $product_ids );
update_option( 'woocommerce_attribute_lookup_processed_count', $products_already_processed );
$last_product_id_to_process = get_option( 'woocommerce_attribute_lookup_last_product_id_to_process' );
return end( $product_ids ) < $last_product_id_to_process;
@ -240,11 +245,14 @@ CREATE TABLE ' . $this->lookup_table_name . '(
/**
* Cleanup/final option setup after the regeneration has been completed.
*
* @param bool $enable_usage Whether the table usage should be enabled or not.
*
*/
private function finalize_regeneration() {
private function finalize_regeneration( bool $enable_usage ) {
delete_option( 'woocommerce_attribute_lookup_last_product_id_to_process' );
delete_option( 'woocommerce_attribute_lookup_last_products_page_processed' );
update_option( 'woocommerce_attribute_lookup_enabled', 'no' );
delete_option( 'woocommerce_attribute_lookup_processed_count' );
update_option( 'woocommerce_attribute_lookup_enabled', $enable_usage ? 'yes' : 'no' );
$this->data_store->unset_regeneration_in_progress_flag();
}
@ -255,76 +263,44 @@ CREATE TABLE ' . $this->lookup_table_name . '(
* @return array The tools array with the entry added.
*/
private function add_initiate_regeneration_entry_to_tools_array( array $tools_array ) {
$lookup_table_exists = $this->data_store->check_lookup_table_exists();
$generation_is_in_progress = $this->data_store->regeneration_is_in_progress();
// Regenerate table.
if ( $lookup_table_exists ) {
$generate_item_name = __( 'Regenerate the product attributes lookup table', 'woocommerce' );
$generate_item_desc = __( 'This tool will regenerate the product attributes lookup table data from existing product(s) data. This process may take a while.', 'woocommerce' );
$generate_item_return = __( 'Product attributes lookup table data is regenerating', 'woocommerce' );
$generate_item_button = __( 'Regenerate', 'woocommerce' );
} else {
$generate_item_name = __( 'Create and fill product attributes lookup table', 'woocommerce' );
$generate_item_desc = __( 'This tool will create the product attributes lookup table data and fill it with existing products data. This process may take a while.', 'woocommerce' );
$generate_item_return = __( 'Product attributes lookup table is being filled', 'woocommerce' );
$generate_item_button = __( 'Create', 'woocommerce' );
if ( ! $this->data_store->check_lookup_table_exists() ) {
return $tools_array;
}
$entry = array(
'name' => $generate_item_name,
'desc' => $generate_item_desc,
'requires_refresh' => true,
'callback' => function() use ( $generate_item_return ) {
$this->initiate_regeneration_from_tools_page();
return $generate_item_return;
},
);
$generation_is_in_progress = $this->data_store->regeneration_is_in_progress();
if ( $lookup_table_exists ) {
$entry['selector'] = array(
$entry = array(
'name' => __( 'Regenerate the product attributes lookup table', 'woocommerce' ),
'desc' => __( 'This tool will regenerate the product attributes lookup table data from existing product(s) data. This process may take a while.', 'woocommerce' ),
'requires_refresh' => true,
'callback' => function() {
$this->initiate_regeneration_from_tools_page();
return __( 'Product attributes lookup table data is regenerating', 'woocommerce' );
},
'selector' => array(
'description' => __( 'Select a product to regenerate the data for, or leave empty for a full table regeneration:', 'woocommerce' ),
'class' => 'wc-product-search',
'search_action' => 'woocommerce_json_search_products',
'name' => 'regenerate_product_attribute_lookup_data_product_id',
'placeholder' => esc_attr__( 'Search for a product&hellip;', 'woocommerce' ),
);
}
),
);
if ( $generation_is_in_progress ) {
$entry['button'] = sprintf(
/* translators: %d: How many products have been processed so far. */
__( 'Filling in progress (%d)', 'woocommerce' ),
get_option( 'woocommerce_attribute_lookup_last_products_page_processed', 0 ) * self::PRODUCTS_PER_GENERATION_STEP
get_option( 'woocommerce_attribute_lookup_processed_count', 0 )
);
$entry['disabled'] = true;
} else {
$entry['button'] = $generate_item_button;
$entry['button'] = __( 'Regenerate', 'woocommerce' );
}
$tools_array['regenerate_product_attributes_lookup_table'] = $entry;
if ( $lookup_table_exists ) {
// Delete the table.
$tools_array['delete_product_attributes_lookup_table'] = array(
'name' => __( 'Delete the product attributes lookup table', 'woocommerce' ),
'desc' => sprintf(
'<strong class="red">%1$s</strong> %2$s',
__( 'Note:', 'woocommerce' ),
__( 'This will delete the product attributes lookup table. You can create it again with the "Create and fill product attributes lookup table" tool.', 'woocommerce' )
),
'button' => __( 'Delete', 'woocommerce' ),
'requires_refresh' => true,
'callback' => function () {
$this->delete_all_attributes_lookup_data();
return __( 'Product attributes lookup table has been deleted.', 'woocommerce' );
},
);
}
return $tools_array;
}

View File

@ -226,17 +226,15 @@ class Filterer {
if ( ! empty( $attributes_to_filter_by ) ) {
$and_term_ids = array();
$or_term_ids = array();
foreach ( $attributes_to_filter_by as $taxonomy => $data ) {
if ( 'and' !== $data['query_type'] ) {
continue;
}
$all_terms = get_terms( $taxonomy, array( 'hide_empty' => false ) );
$term_ids_by_slug = wp_list_pluck( $all_terms, 'term_id', 'slug' );
$term_ids_to_filter_by = array_values( array_intersect_key( $term_ids_by_slug, array_flip( $data['terms'] ) ) );
if ( 'and' === $data['query_type'] ) {
$and_term_ids = array_merge( $and_term_ids, $term_ids_to_filter_by );
} else {
$or_term_ids = array_merge( $or_term_ids, $term_ids_to_filter_by );
}
$and_term_ids = array_merge( $and_term_ids, $term_ids_to_filter_by );
}
if ( ! empty( $and_term_ids ) ) {
@ -261,17 +259,6 @@ class Filterer {
AND term_id in {$term_ids_list}
) temp )";
}
if ( ! empty( $or_term_ids ) ) {
$term_ids_list = '(' . join( ',', $or_term_ids ) . ')';
$query['where'] .= "
AND product_or_parent_id IN ( SELECT product_or_parent_id FROM (
SELECT product_or_parent_id FROM {$this->lookup_table_name}
WHERE term_id in {$term_ids_list}
{$in_stock_clause}
) temp )";
}
} else {
$query['where'] .= $in_stock_clause;
}

View File

@ -36,7 +36,7 @@ class LookupDataStore {
public function __construct() {
global $wpdb;
$this->lookup_table_name = $wpdb->prefix . 'wc_product_attributes_lookup';
$this->lookup_table_name = $wpdb->prefix . 'wc_product_attributes_lookup';
$this->init_hooks();
}
@ -84,9 +84,18 @@ class LookupDataStore {
$settings[] = $title_item;
if ( ! $regeneration_is_in_progress ) {
$regeneration_aborted_warning =
$this->regeneration_was_aborted() ?
sprintf(
"<p><strong style='color: #E00000'>%s</strong></p><p>%s</p>",
__( 'WARNING: The product attributes lookup table regeneration process was aborted.', 'woocommerce' ),
__( 'This means that the table is probably in an inconsistent state. It\'s recommended to run a new regeneration process (Status - Tools - Regenerate the product attributes lookup table) before enabling the table usage.', 'woocommerce' )
) : null;
$settings[] = array(
'title' => __( 'Enable table usage', 'woocommerce' ),
'desc' => __( 'Use the product attributes lookup table for catalog filtering.', 'woocommerce' ),
'desc_tip' => $regeneration_aborted_warning,
'id' => 'woocommerce_attribute_lookup_enabled',
'default' => 'no',
'type' => 'checkbox',
@ -648,4 +657,28 @@ class LookupDataStore {
public function unset_regeneration_in_progress_flag() {
delete_option( 'woocommerce_attribute_lookup_regeneration_in_progress' );
}
/**
* Set a flag indicating that the last lookup table regeneration process started was aborted.
*/
public function set_regeneration_aborted_flag() {
update_option( 'woocommerce_attribute_lookup_regeneration_aborted', 'yes' );
}
/**
* Remove the flag indicating that the last lookup table regeneration process started was aborted.
*/
public function unset_regeneration_aborted_flag() {
delete_option( 'woocommerce_attribute_lookup_regeneration_aborted' );
}
/**
* Tells if the last lookup table regeneration process started was aborted
* (via deleting the 'woocommerce_attribute_lookup_regeneration_in_progress' option).
*
* @return bool True if the last lookup table regeneration process was aborted.
*/
public function regeneration_was_aborted(): bool {
return 'yes' === get_option( 'woocommerce_attribute_lookup_regeneration_aborted' );
}
}

View File

@ -0,0 +1,53 @@
import { sleep, check, group } from "k6";
import http from "k6/http";
import { Trend } from "k6/metrics";
import { randomIntBetween } from "https://jslib.k6.io/k6-utils/1.1.0/index.js";
import {
base_url,
think_time_min,
think_time_max,
product_search_term,
} from "../../config.js";
import {
htmlRequestHeader,
commonRequestHeaders,
commonGetRequestHeaders,
commonNonStandardHeaders,
} from "../../headers.js";
// Custom metrics to add to standard results output.
let postTypeOrderSearchTrend = new Trend("wc_get_post_type_order_search");
export function ordersSearch() {
let response;
group("Orders Search", function () {
var requestHeaders = Object.assign({},
htmlRequestHeader,
commonRequestHeaders,
commonGetRequestHeaders,
commonNonStandardHeaders
);
response = http.get(
`${base_url}/wp-admin/edit.php?s=${product_search_term}&` +
`post_status=all&post_type=shop_order&action=-1&m=0&_customer_user&` +
`paged=1&action2=-1`,
{
headers: requestHeaders,
}
);
postTypeOrderSearchTrend.add(response.timings.duration);
check(response, {
"is status 200": (r) => r.status === 200,
"body contains: 'Search results' subtitle": (response) =>
response.body.includes("Search results for:"),
});
});
sleep(randomIntBetween(`${think_time_min}`, `${think_time_max}`));
}
export default function () {
ordersSearch();
}

View File

@ -13,6 +13,7 @@ import { products } from '../requests/merchant/products.js';
import { addProduct } from '../requests/merchant/add-product.js';
import { orders } from '../requests/merchant/orders.js';
import { ordersHeartbeat } from '../requests/merchant/orders-heartbeat.js';
import { ordersSearch } from '../requests/merchant/orders-search.js';
import { homeWCAdmin } from '../requests/merchant/home-wc-admin.js';
import { myAccountMerchantLogin } from '../requests/merchant/my-account-merchant.js';
import { categoryPage } from '../requests/shopper/category-page.js';
@ -107,6 +108,7 @@ export function merchantAllFlows() {
myAccountMerchantLogin();
homeWCAdmin();
orders();
ordersSearch();
products();
addProduct();
}

View File

@ -13,6 +13,7 @@ import { products } from '../requests/merchant/products.js';
import { addProduct } from '../requests/merchant/add-product.js';
import { orders } from '../requests/merchant/orders.js';
import { ordersHeartbeat } from '../requests/merchant/orders-heartbeat.js';
import { ordersSearch } from '../requests/merchant/orders-search.js';
import { homeWCAdmin } from '../requests/merchant/home-wc-admin.js';
import { myAccountMerchantLogin } from '../requests/merchant/my-account-merchant.js';
import { categoryPage } from '../requests/shopper/category-page.js';
@ -97,6 +98,7 @@ export function merchantAllFlows() {
myAccountMerchantLogin();
homeWCAdmin();
orders();
ordersSearch();
products();
addProduct();
}

View File

@ -2,6 +2,7 @@ import { wpLogin } from '../requests/merchant/wp-login.js';
import { products } from '../requests/merchant/products.js';
import { addProduct } from '../requests/merchant/add-product.js';
import { orders } from '../requests/merchant/orders.js';
import { ordersSearch } from '../requests/merchant/orders-search.js';
import { homeWCAdmin } from '../requests/merchant/home-wc-admin.js';
import { myAccountMerchantLogin } from '../requests/merchant/my-account-merchant.js';
@ -22,6 +23,7 @@ export function allMerchantFlow() {
wpLogin();
homeWCAdmin();
orders();
ordersSearch();
products();
addProduct();
}

View File

@ -7,6 +7,8 @@
// phpcs:ignore Squiz.Commenting.FileComment.Missing
use Automattic\WooCommerce\Internal\ProductAttributesLookup\LookupDataStore;
require_once __DIR__ . '/class-wc-settings-unit-test-case.php';
/**
@ -28,6 +30,11 @@ class WC_Settings_Products_Test extends WC_Settings_Unit_Test_Case {
'downloadable',
);
// TODO: Once the lookup table is created in a migration, remove the check and just include 'advanced' in $expected.
if ( wc_get_container()->get( LookupDataStore::class )->check_lookup_table_exists() ) {
array_push( $expected, 'advanced' );
}
$this->assertEquals( $expected, $section_names );
}
@ -134,12 +141,12 @@ class WC_Settings_Products_Test extends WC_Settings_Unit_Test_Case {
$settings_ids_and_types = $this->get_ids_and_types( $settings );
$expected = array(
'digital_download_options' => array( 'title', 'sectionend' ),
'woocommerce_file_download_method' => 'select',
'woocommerce_downloads_redirect_fallback_allowed' => 'checkbox',
'woocommerce_downloads_require_login' => 'checkbox',
'digital_download_options' => array( 'title', 'sectionend' ),
'woocommerce_file_download_method' => 'select',
'woocommerce_downloads_redirect_fallback_allowed' => 'checkbox',
'woocommerce_downloads_require_login' => 'checkbox',
'woocommerce_downloads_grant_access_after_payment' => 'checkbox',
'woocommerce_downloads_add_hash_to_filename' => 'checkbox',
'woocommerce_downloads_add_hash_to_filename' => 'checkbox',
);
$this->assertEquals( $expected, $settings_ids_and_types );

View File

@ -121,7 +121,7 @@ class DataRegeneratorTest extends \WC_Unit_Test_Case {
$this->sut->initiate_regeneration();
$this->assertEquals( 100, get_option( 'woocommerce_attribute_lookup_last_product_id_to_process' ) );
$this->assertEquals( 0, get_option( 'woocommerce_attribute_lookup_last_products_page_processed' ) );
$this->assertEquals( 0, get_option( 'woocommerce_attribute_lookup_processed_count' ) );
$this->assertFalse( get_option( 'woocommerce_attribute_lookup_enabled' ) );
$expected_enqueued = array(
@ -156,8 +156,8 @@ class DataRegeneratorTest extends \WC_Unit_Test_Case {
$this->sut->initiate_regeneration();
$this->assertFalse( get_option( 'woocommerce_attribute_lookup_last_product_id_to_process' ) );
$this->assertFalse( get_option( 'woocommerce_attribute_lookup_last_products_page_processed' ) );
$this->assertEquals( 'no', get_option( 'woocommerce_attribute_lookup_enabled' ) );
$this->assertFalse( get_option( 'woocommerce_attribute_lookup_processed_count' ) );
$this->assertEquals( 'yes', get_option( 'woocommerce_attribute_lookup_enabled' ) );
$this->assertEmpty( $this->queue->get_methods_called() );
}
@ -165,15 +165,15 @@ class DataRegeneratorTest extends \WC_Unit_Test_Case {
* @testdox `initiate_regeneration` processes one chunk of products IDs and enqueues next step if there are more products available.
*/
public function test_initiate_regeneration_correctly_processes_ids_and_enqueues_next_step() {
$requested_products_pages = array();
$requested_products_offsets = array();
$this->register_legacy_proxy_function_mocks(
array(
'wc_get_products' => function( $args ) use ( &$requested_products_pages ) {
'wc_get_products' => function( $args ) use ( &$requested_products_offsets ) {
if ( 'DESC' === current( $args['orderby'] ) ) {
return array( 100 );
} else {
$requested_products_pages[] = $args['page'];
$requested_products_offsets[] = $args['offset'];
return array( 1, 2, 3 );
}
},
@ -186,13 +186,13 @@ class DataRegeneratorTest extends \WC_Unit_Test_Case {
$this->sut->initiate_regeneration();
$this->queue->clear_methods_called();
update_option( 'woocommerce_attribute_lookup_last_products_page_processed', 7 );
update_option( 'woocommerce_attribute_lookup_processed_count', 7 );
do_action( 'woocommerce_run_product_attribute_lookup_regeneration_callback' );
$this->assertEquals( array( 1, 2, 3 ), $this->lookup_data_store->passed_products );
$this->assertEquals( array( 8 ), $requested_products_pages );
$this->assertEquals( 8, get_option( 'woocommerce_attribute_lookup_last_products_page_processed' ) );
$this->assertEquals( array( 7 ), $requested_products_offsets );
$this->assertEquals( 7 + count( $this->lookup_data_store->passed_products ), get_option( 'woocommerce_attribute_lookup_processed_count' ) );
$expected_enqueued = array(
'method' => 'schedule_single',
@ -205,6 +205,50 @@ class DataRegeneratorTest extends \WC_Unit_Test_Case {
$this->assertEquals( sort( $expected_enqueued ), sort( $actual_enqueued ) );
}
/**
* @testDox Products are processed in groups of whatever the 'woocommerce_attribute_lookup_regeneration_step_size' filter returns, defaulting to PRODUCTS_PER_GENERATION_STEP
*
* @testWith [true]
* [false]
*
* @param bool $set_filter Whether to use the filter to change the processing group size or not.
*/
public function test_regeneration_uses_the_woocommerce_attribute_lookup_regeneration_step_size_filter( bool $set_filter ) {
$requested_step_sizes = array();
if ( $set_filter ) {
\add_filter(
'woocommerce_attribute_lookup_regeneration_step_size',
function( $default_filter_size ) {
return 100;
}
);
}
$this->register_legacy_proxy_function_mocks(
array(
'wc_get_products' => function( $args ) use ( &$requested_step_sizes ) {
if ( 'DESC' === current( $args['orderby'] ) ) {
return array( 100 );
} else {
$requested_step_sizes[] = $args['limit'];
return array( 1, 2, 3 );
}
},
)
);
$this->sut->initiate_regeneration();
$this->queue->clear_methods_called();
do_action( 'woocommerce_run_product_attribute_lookup_regeneration_callback' );
remove_all_filters( ' woocommerce_attribute_lookup_regeneration_step_size' );
$expected_limit_value = $set_filter ? 100 : DataRegenerator::PRODUCTS_PER_GENERATION_STEP;
$this->assertEquals( array( $expected_limit_value ), $requested_step_sizes );
}
/**
* @testdox `initiate_regeneration` finishes regeneration when the max product id is reached or no more products are returned.
*
@ -215,15 +259,12 @@ class DataRegeneratorTest extends \WC_Unit_Test_Case {
* @param array $product_ids The products ids that wc_get_products will return.
*/
public function test_initiate_regeneration_finishes_when_no_more_products_available( $product_ids ) {
$requested_products_pages = array();
$this->register_legacy_proxy_function_mocks(
array(
'wc_get_products' => function( $args ) use ( &$requested_products_pages, $product_ids ) {
'wc_get_products' => function( $args ) use ( &$requested_products_offsets, $product_ids ) {
if ( 'DESC' === current( $args['orderby'] ) ) {
return array( 100 );
} else {
$requested_products_pages[] = $args['page'];
return $product_ids;
}
},
@ -237,8 +278,8 @@ class DataRegeneratorTest extends \WC_Unit_Test_Case {
$this->assertEquals( $product_ids, $this->lookup_data_store->passed_products );
$this->assertFalse( get_option( 'woocommerce_attribute_lookup_last_product_id_to_process' ) );
$this->assertFalse( get_option( 'woocommerce_attribute_lookup_last_products_page_processed' ) );
$this->assertEquals( 'no', get_option( 'woocommerce_attribute_lookup_enabled' ) );
$this->assertFalse( get_option( 'woocommerce_attribute_lookup_processed_count' ) );
$this->assertEquals( 'yes', get_option( 'woocommerce_attribute_lookup_enabled' ) );
$this->assertEmpty( $this->queue->get_methods_called() );
}
}

View File

@ -545,16 +545,7 @@ class FiltererTest extends \WC_Unit_Test_Case {
$this->assertEmpty( $filtered_product_ids );
}
/*
* If a variable product defines an attribute value that isn't used by any variation:
* When using the lookup table: that value is not included in the count.
* When not using the lookup table: the value is included in the count since it is part of the parent product.
*/
if ( $using_lookup_table && 'or' === $filter_type && array( 'Green' ) === $attributes ) {
$expected_to_be_included_in_count = false;
} else {
$expected_to_be_included_in_count = 'or' === $filter_type || $expected_to_be_visible;
}
$expected_to_be_included_in_count = 'or' === $filter_type || $expected_to_be_visible;
$this->assert_counters( 'Color', $expected_to_be_included_in_count ? array( 'Blue', 'Red' ) : array(), $filter_type );
}
@ -822,16 +813,7 @@ class FiltererTest extends \WC_Unit_Test_Case {
$this->assertEmpty( $filtered_product_ids );
}
/*
* If a variable product defines an attribute value that isn't used by any variation:
* When using the lookup table: that value is not included in the count.
* When not using the lookup table: the value is included in the count since it is part of the parent product.
*/
if ( $using_lookup_table && 'or' === $filter_type && array( 'Elastic' ) === $attributes ) {
$expected_to_be_included_in_count = false;
} else {
$expected_to_be_included_in_count = 'or' === $filter_type || $expected_to_be_visible;
}
$expected_to_be_included_in_count = 'or' === $filter_type || $expected_to_be_visible;
$this->assert_counters( 'Features', $expected_to_be_included_in_count ? array( 'Washable', 'Ironable' ) : array(), $filter_type );
}
@ -1075,16 +1057,7 @@ class FiltererTest extends \WC_Unit_Test_Case {
$this->assertEmpty( $filtered_product_ids );
}
/*
* If a variable product defines an attribute value that isn't used by any variation:
* When using the lookup table: that value is not included in the count.
* When not using the lookup table: the value is included in the count since it is part of the parent product.
*/
if ( $using_lookup_table && 'or' === $filter_type && array( 'Green' ) === $attributes ) {
$expected_counted_attributes = array();
} else {
$expected_counted_attributes = 'or' === $filter_type || $expected_to_be_visible ? array( 'Blue', 'Red' ) : array();
}
$expected_counted_attributes = 'or' === $filter_type || $expected_to_be_visible ? array( 'Blue', 'Red' ) : array();
$this->assert_counters( 'Color', $expected_counted_attributes, $filter_type );
}
@ -1208,16 +1181,7 @@ class FiltererTest extends \WC_Unit_Test_Case {
$this->assertEmpty( $filtered_product_ids );
}
/*
* If a variable product defines an attribute value that isn't used by any variation:
* When using the lookup table: that value is not included in the count.
* When not using the lookup table: the value is included in the count since it is part of the parent product.
*/
if ( $using_lookup_table && 'or' === $filter_type && array( 'White' ) === $attributes ) {
$expected_to_be_included_in_count = false;
} else {
$expected_to_be_included_in_count = 'or' === $filter_type || $expected_to_be_visible;
}
$expected_to_be_included_in_count = 'or' === $filter_type || $expected_to_be_visible;
$this->assert_counters( 'Color', $expected_to_be_included_in_count ? array( 'Blue', 'Red', 'Green' ) : array(), $filter_type );
}
@ -1356,9 +1320,12 @@ class FiltererTest extends \WC_Unit_Test_Case {
wp_set_object_terms( $product_simple_1->get_id(), $terms, 'product_visibility' );
wp_set_object_terms( $product_variable_1['id'], $terms, 'product_visibility' );
$filtered_product_ids = $this->do_product_request( array() );
$actual_filtered_product_ids = $this->do_product_request( array() );
$expected_filtered_product_ids = array( $product_simple_2->get_id(), $product_variable_2['id'] );
sort( $actual_filtered_product_ids );
sort( $expected_filtered_product_ids );
$this->assertEquals( array( $product_simple_2->get_id(), $product_variable_2['id'] ), $filtered_product_ids );
$this->assertEquals( $expected_filtered_product_ids, $actual_filtered_product_ids );
$this->assert_counters( 'Color', $expected_colors_included_in_counters );
$this->assert_counters( 'Features', array( 'Ironable' ) );

View File

@ -9,7 +9,6 @@ use Automattic\WooCommerce\Internal\ProductAttributesLookup\DataRegenerator;
use Automattic\WooCommerce\Internal\ProductAttributesLookup\LookupDataStore;
use Automattic\WooCommerce\Testing\Tools\FakeQueue;
use Automattic\WooCommerce\Utilities\ArrayUtil;
use Automattic\WooCommerce\Testing\Tools\CodeHacking\Hacks\FunctionsMockerHack;
/**
* Tests for the LookupDataStore class.
@ -36,7 +35,6 @@ class LookupDataStoreTest extends \WC_Unit_Test_Case {
*/
public static function tearDownAfterClass() {
parent::tearDownAfterClass();
wc_get_container()->get( DataRegenerator::class )->delete_all_attributes_lookup_data();
}
/**

View File

@ -155,6 +155,7 @@ importers:
'@wordpress/jest-preset-default': ^7.1.3
app-root-path: ^3.0.0
commander: 4.1.1
config: 3.3.3
eslint: ^8.1.0
jest: ^25.1.0
jest-circus: 25.1.0
@ -175,6 +176,7 @@ importers:
'@wordpress/jest-preset-default': 7.1.3_@babel+core@7.12.9+jest@25.5.4
app-root-path: 3.0.0
commander: 4.1.1
config: 3.3.3
jest: 25.5.4
jest-circus: 25.1.0
jest-each: 25.5.0