Merge branch 'trunk' into add/install-all-pending-updates

This commit is contained in:
Greg 2021-06-18 11:31:42 -06:00 committed by GitHub
commit 74a9e1b0ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
43 changed files with 380 additions and 353 deletions

View File

@ -254,16 +254,16 @@
}, },
{ {
"name": "rmccue/requests", "name": "rmccue/requests",
"version": "v1.8.0", "version": "v1.8.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/WordPress/Requests.git", "url": "https://github.com/WordPress/Requests.git",
"reference": "afbe4790e4def03581c4a0963a1e8aa01f6030f1" "reference": "82e6936366eac3af4d836c18b9d8c31028fe4cd5"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/WordPress/Requests/zipball/afbe4790e4def03581c4a0963a1e8aa01f6030f1", "url": "https://api.github.com/repos/WordPress/Requests/zipball/82e6936366eac3af4d836c18b9d8c31028fe4cd5",
"reference": "afbe4790e4def03581c4a0963a1e8aa01f6030f1", "reference": "82e6936366eac3af4d836c18b9d8c31028fe4cd5",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -306,11 +306,7 @@
"iri", "iri",
"sockets" "sockets"
], ],
"support": { "time": "2021-06-04T09:56:25+00:00"
"issues": "https://github.com/WordPress/Requests/issues",
"source": "https://github.com/WordPress/Requests/tree/v1.8.0"
},
"time": "2021-04-27T11:05:25+00:00"
}, },
{ {
"name": "symfony/finder", "name": "symfony/finder",
@ -612,5 +608,5 @@
"platform-overrides": { "platform-overrides": {
"php": "7.0" "php": "7.0"
}, },
"plugin-api-version": "2.0.0" "plugin-api-version": "1.1.0"
} }

View File

@ -21,8 +21,8 @@
"pelago/emogrifier": "3.1.0", "pelago/emogrifier": "3.1.0",
"psr/container": "1.0.0", "psr/container": "1.0.0",
"woocommerce/action-scheduler": "3.2.0", "woocommerce/action-scheduler": "3.2.0",
"woocommerce/woocommerce-admin": "2.3.1", "woocommerce/woocommerce-admin": "2.4.0-rc.2",
"woocommerce/woocommerce-blocks": "5.1.0" "woocommerce/woocommerce-blocks": "5.3.1"
}, },
"require-dev": { "require-dev": {
"bamarni/composer-bin-plugin": "^1.4" "bamarni/composer-bin-plugin": "^1.4"

61
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "21b06e63b5f65deec4b635463a10402b", "content-hash": "6427ca1d82e637782404faeb3b988ec3",
"packages": [ "packages": [
{ {
"name": "automattic/jetpack-autoloader", "name": "automattic/jetpack-autoloader",
@ -51,9 +51,6 @@
"GPL-2.0-or-later" "GPL-2.0-or-later"
], ],
"description": "Creates a custom autoloader for a plugin or theme.", "description": "Creates a custom autoloader for a plugin or theme.",
"support": {
"source": "https://github.com/Automattic/jetpack-autoloader/tree/2.10.1"
},
"time": "2021-03-30T15:15:59+00:00" "time": "2021-03-30T15:15:59+00:00"
}, },
{ {
@ -85,9 +82,6 @@
"GPL-2.0-or-later" "GPL-2.0-or-later"
], ],
"description": "A wrapper for defining constants in a more testable way.", "description": "A wrapper for defining constants in a more testable way.",
"support": {
"source": "https://github.com/Automattic/jetpack-constants/tree/v1.5.1"
},
"time": "2020-10-28T19:00:31+00:00" "time": "2020-10-28T19:00:31+00:00"
}, },
{ {
@ -220,10 +214,6 @@
"zend", "zend",
"zikula" "zikula"
], ],
"support": {
"issues": "https://github.com/composer/installers/issues",
"source": "https://github.com/composer/installers/tree/v1.11.0"
},
"funding": [ "funding": [
{ {
"url": "https://packagist.com", "url": "https://packagist.com",
@ -298,10 +288,6 @@
"geolocation", "geolocation",
"maxmind" "maxmind"
], ],
"support": {
"issues": "https://github.com/maxmind/MaxMind-DB-Reader-php/issues",
"source": "https://github.com/maxmind/MaxMind-DB-Reader-php/tree/v1.6.0"
},
"time": "2019-12-19T22:59:03+00:00" "time": "2019-12-19T22:59:03+00:00"
}, },
{ {
@ -376,10 +362,6 @@
"email", "email",
"pre-processing" "pre-processing"
], ],
"support": {
"issues": "https://github.com/MyIntervals/emogrifier/issues",
"source": "https://github.com/MyIntervals/emogrifier"
},
"time": "2019-12-26T19:37:31+00:00" "time": "2019-12-26T19:37:31+00:00"
}, },
{ {
@ -429,10 +411,6 @@
"container-interop", "container-interop",
"psr" "psr"
], ],
"support": {
"issues": "https://github.com/php-fig/container/issues",
"source": "https://github.com/php-fig/container/tree/master"
},
"time": "2017-02-14T16:28:37+00:00" "time": "2017-02-14T16:28:37+00:00"
}, },
{ {
@ -486,9 +464,6 @@
], ],
"description": "Symfony CssSelector Component", "description": "Symfony CssSelector Component",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/css-selector/tree/master"
},
"time": "2017-05-01T15:01:29+00:00" "time": "2017-05-01T15:01:29+00:00"
}, },
{ {
@ -532,16 +507,16 @@
}, },
{ {
"name": "woocommerce/woocommerce-admin", "name": "woocommerce/woocommerce-admin",
"version": "2.3.1", "version": "2.4.0-rc.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/woocommerce/woocommerce-admin.git", "url": "https://github.com/woocommerce/woocommerce-admin.git",
"reference": "f28cf3f027e27a6679e4fa8173d8b6859ec84838" "reference": "ed72985cd459831c555dff2ff5f75111b6e210c1"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/woocommerce/woocommerce-admin/zipball/f28cf3f027e27a6679e4fa8173d8b6859ec84838", "url": "https://api.github.com/repos/woocommerce/woocommerce-admin/zipball/ed72985cd459831c555dff2ff5f75111b6e210c1",
"reference": "f28cf3f027e27a6679e4fa8173d8b6859ec84838", "reference": "ed72985cd459831c555dff2ff5f75111b6e210c1",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -576,24 +551,20 @@
], ],
"description": "A modern, javascript-driven WooCommerce Admin experience.", "description": "A modern, javascript-driven WooCommerce Admin experience.",
"homepage": "https://github.com/woocommerce/woocommerce-admin", "homepage": "https://github.com/woocommerce/woocommerce-admin",
"support": { "time": "2021-06-18T05:58:25+00:00"
"issues": "https://github.com/woocommerce/woocommerce-admin/issues",
"source": "https://github.com/woocommerce/woocommerce-admin/tree/v2.3.1"
},
"time": "2021-05-24T09:48:40+00:00"
}, },
{ {
"name": "woocommerce/woocommerce-blocks", "name": "woocommerce/woocommerce-blocks",
"version": "v5.1.0", "version": "v5.3.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/woocommerce/woocommerce-gutenberg-products-block.git", "url": "https://github.com/woocommerce/woocommerce-gutenberg-products-block.git",
"reference": "a4f168596f3832e161b26dec636b69293039ee51" "reference": "28c7c4f9b5cace9098fb2246ff93abe110a26bca"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/woocommerce/woocommerce-gutenberg-products-block/zipball/a4f168596f3832e161b26dec636b69293039ee51", "url": "https://api.github.com/repos/woocommerce/woocommerce-gutenberg-products-block/zipball/28c7c4f9b5cace9098fb2246ff93abe110a26bca",
"reference": "a4f168596f3832e161b26dec636b69293039ee51", "reference": "28c7c4f9b5cace9098fb2246ff93abe110a26bca",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -627,11 +598,7 @@
"gutenberg", "gutenberg",
"woocommerce" "woocommerce"
], ],
"support": { "time": "2021-06-15T09:12:48+00:00"
"issues": "https://github.com/woocommerce/woocommerce-gutenberg-products-block/issues",
"source": "https://github.com/woocommerce/woocommerce-gutenberg-products-block/tree/v5.1.0"
},
"time": "2021-05-10T15:01:42+00:00"
} }
], ],
"packages-dev": [ "packages-dev": [
@ -679,10 +646,6 @@
"isolation", "isolation",
"tool" "tool"
], ],
"support": {
"issues": "https://github.com/bamarni/composer-bin-plugin/issues",
"source": "https://github.com/bamarni/composer-bin-plugin/tree/master"
},
"time": "2020-05-03T08:27:20+00:00" "time": "2020-05-03T08:27:20+00:00"
} }
], ],
@ -698,5 +661,5 @@
"platform-overrides": { "platform-overrides": {
"php": "7.0" "php": "7.0"
}, },
"plugin-api-version": "2.0.0" "plugin-api-version": "1.1.0"
} }

View File

@ -566,6 +566,8 @@ class WC_Product_CSV_Importer_Controller {
/* translators: %d: Attribute number */ /* translators: %d: Attribute number */
__( 'Attribute %d default', 'woocommerce' ) => 'attributes:default', __( 'Attribute %d default', 'woocommerce' ) => 'attributes:default',
/* translators: %d: Download number */ /* translators: %d: Download number */
__( 'Download %d ID', 'woocommerce' ) => 'downloads:id',
/* translators: %d: Download number */
__( 'Download %d name', 'woocommerce' ) => 'downloads:name', __( 'Download %d name', 'woocommerce' ) => 'downloads:name',
/* translators: %d: Download number */ /* translators: %d: Download number */
__( 'Download %d URL', 'woocommerce' ) => 'downloads:url', __( 'Download %d URL', 'woocommerce' ) => 'downloads:url',
@ -721,6 +723,7 @@ class WC_Product_CSV_Importer_Controller {
'downloads' => array( 'downloads' => array(
'name' => __( 'Downloads', 'woocommerce' ), 'name' => __( 'Downloads', 'woocommerce' ),
'options' => array( 'options' => array(
'downloads:id' . $index => __( 'Download ID', 'woocommerce' ),
'downloads:name' . $index => __( 'Download name', 'woocommerce' ), 'downloads:name' . $index => __( 'Download name', 'woocommerce' ),
'downloads:url' . $index => __( 'Download URL', 'woocommerce' ), 'downloads:url' . $index => __( 'Download URL', 'woocommerce' ),
'download_limit' => __( 'Download limit', 'woocommerce' ), 'download_limit' => __( 'Download limit', 'woocommerce' ),

View File

@ -102,6 +102,7 @@ function wc_importer_default_special_english_mappings( $mappings ) {
'Attribute %d visible' => 'attributes:visible', 'Attribute %d visible' => 'attributes:visible',
'Attribute %d global' => 'attributes:taxonomy', 'Attribute %d global' => 'attributes:taxonomy',
'Attribute %d default' => 'attributes:default', 'Attribute %d default' => 'attributes:default',
'Download %d ID' => 'downloads:id',
'Download %d name' => 'downloads:name', 'Download %d name' => 'downloads:name',
'Download %d URL' => 'downloads:url', 'Download %d URL' => 'downloads:url',
'Meta: %s' => 'meta:', 'Meta: %s' => 'meta:',

View File

@ -145,6 +145,7 @@ class WC_Admin_List_Table_Orders extends WC_Admin_List_Table {
$actions['mark_processing'] = __( 'Change status to processing', 'woocommerce' ); $actions['mark_processing'] = __( 'Change status to processing', 'woocommerce' );
$actions['mark_on-hold'] = __( 'Change status to on-hold', 'woocommerce' ); $actions['mark_on-hold'] = __( 'Change status to on-hold', 'woocommerce' );
$actions['mark_completed'] = __( 'Change status to completed', 'woocommerce' ); $actions['mark_completed'] = __( 'Change status to completed', 'woocommerce' );
$actions['mark_cancelled'] = __( 'Change status to cancelled', 'woocommerce' );
if ( wc_string_to_bool( get_option( 'woocommerce_allow_bulk_remove_personal_data', 'no' ) ) ) { if ( wc_string_to_bool( get_option( 'woocommerce_allow_bulk_remove_personal_data', 'no' ) ) ) {
$actions['remove_personal_data'] = __( 'Remove personal data', 'woocommerce' ); $actions['remove_personal_data'] = __( 'Remove personal data', 'woocommerce' );

View File

@ -310,6 +310,7 @@ class WC_Install {
self::create_files(); self::create_files();
self::maybe_create_pages(); self::maybe_create_pages();
self::maybe_set_activation_transients(); self::maybe_set_activation_transients();
self::set_paypal_standard_load_eligibility();
self::update_wc_version(); self::update_wc_version();
self::maybe_update_db_version(); self::maybe_update_db_version();
@ -1635,6 +1636,18 @@ CREATE TABLE {$wpdb->prefix}wc_reserved_stock (
ob_end_clean(); ob_end_clean();
} }
} }
/**
* Sets whether PayPal Standard will be loaded on install.
*
* @since 5.5.0
*/
private static function set_paypal_standard_load_eligibility() {
// Initiating the payment gateways sets the flag.
if ( class_exists( 'WC_Gateway_Paypal' ) ) {
( new WC_Gateway_Paypal() )->should_load();
}
}
} }
WC_Install::init(); WC_Install::init();

View File

@ -78,9 +78,12 @@ class WC_Payment_Gateways {
'WC_Gateway_BACS', 'WC_Gateway_BACS',
'WC_Gateway_Cheque', 'WC_Gateway_Cheque',
'WC_Gateway_COD', 'WC_Gateway_COD',
'WC_Gateway_Paypal',
); );
if ( $this->should_load_paypal_standard() ) {
$load_gateways[] = 'WC_Gateway_Paypal';
}
// Filter. // Filter.
$load_gateways = apply_filters( 'woocommerce_payment_gateways', $load_gateways ); $load_gateways = apply_filters( 'woocommerce_payment_gateways', $load_gateways );
@ -219,4 +222,15 @@ class WC_Payment_Gateways {
update_option( 'woocommerce_gateway_order', $order ); update_option( 'woocommerce_gateway_order', $order );
} }
/**
* Determines if PayPal Standard should be loaded.
*
* @since 5.5.0
* @return bool Whether PayPal Standard should be loaded or not.
*/
protected function should_load_paypal_standard() {
$paypal = new WC_Gateway_Paypal();
return $paypal->should_load();
}
} }

View File

@ -601,10 +601,13 @@ class WC_Product_CSV_Exporter extends WC_CSV_Batch_Exporter {
if ( $downloads ) { if ( $downloads ) {
$i = 1; $i = 1;
foreach ( $downloads as $download ) { foreach ( $downloads as $download ) {
/* translators: %s: download number */
$this->column_names[ 'downloads:id' . $i ] = sprintf( __( 'Download %d ID', 'woocommerce' ), $i );
/* translators: %s: download number */ /* translators: %s: download number */
$this->column_names[ 'downloads:name' . $i ] = sprintf( __( 'Download %d name', 'woocommerce' ), $i ); $this->column_names[ 'downloads:name' . $i ] = sprintf( __( 'Download %d name', 'woocommerce' ), $i );
/* translators: %s: download number */ /* translators: %s: download number */
$this->column_names[ 'downloads:url' . $i ] = sprintf( __( 'Download %d URL', 'woocommerce' ), $i ); $this->column_names[ 'downloads:url' . $i ] = sprintf( __( 'Download %d URL', 'woocommerce' ), $i );
$row[ 'downloads:id' . $i ] = $download->get_id();
$row[ 'downloads:name' . $i ] = $download->get_name(); $row[ 'downloads:name' . $i ] = $download->get_name();
$row[ 'downloads:url' . $i ] = $download->get_file(); $row[ 'downloads:url' . $i ] = $download->get_file();
$i++; $i++;

View File

@ -473,4 +473,42 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
return $text; return $text;
} }
/**
* Determines whether PayPal Standard should be loaded or not.
*
* By default PayPal Standard isn't loaded on new installs or on existing sites which haven't set up the gateway.
*
* @since 5.5.0
*
* @return bool Whether PayPal Standard should be loaded.
*/
public function should_load() {
$option_key = '_should_load';
$should_load = $this->get_option( $option_key );
if ( '' === $should_load ) {
// New installs without PayPal Standard enabled don't load it.
if ( 'no' === $this->enabled && WC_Install::is_new_install() ) {
$should_load = false;
} else {
$should_load = true;
}
$this->update_option( $option_key, wc_bool_to_string( $should_load ) );
} else {
$should_load = wc_string_to_bool( $should_load );
}
/**
* Allow third-parties to filter whether PayPal Standard should be loaded or not.
*
* @since 5.5.0
*
* @param bool $should_load Whether PayPal Standard should be loaded.
* @param WC_Gateway_Paypal $this The WC_Gateway_Paypal instance.
*/
return apply_filters( 'woocommerce_should_load_paypal_standard', $should_load, $this );
}
} }

View File

@ -894,6 +894,12 @@ class WC_Product_CSV_Importer extends WC_Product_Importer {
} }
unset( $data[ $key ] ); unset( $data[ $key ] );
} elseif ( $this->starts_with( $key, 'downloads:id' ) ) {
if ( ! empty( $value ) ) {
$downloads[ str_replace( 'downloads:id', '', $key ) ]['id'] = $value;
}
unset( $data[ $key ] );
} elseif ( $this->starts_with( $key, 'downloads:name' ) ) { } elseif ( $this->starts_with( $key, 'downloads:name' ) ) {
if ( ! empty( $value ) ) { if ( ! empty( $value ) ) {
$downloads[ str_replace( 'downloads:name', '', $key ) ]['name'] = $value; $downloads[ str_replace( 'downloads:name', '', $key ) ]['name'] = $value;
@ -935,6 +941,7 @@ class WC_Product_CSV_Importer extends WC_Product_Importer {
} }
$data['downloads'][] = array( $data['downloads'][] = array(
'download_id' => isset( $file['id'] ) ? $file['id'] : null,
'name' => $file['name'] ? $file['name'] : wc_get_filename_from_url( $file['url'] ), 'name' => $file['name'] ? $file['name'] : wc_get_filename_from_url( $file['url'] ),
'file' => $file['url'], 'file' => $file['url'],
); );

View File

@ -6,10 +6,6 @@
* @package WooCommerce\Interfaces * @package WooCommerce\Interfaces
*/ */
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/** /**
* WC Order Data Store Interface * WC Order Data Store Interface
* *

View File

@ -6,10 +6,6 @@
* @package WooCommerce\Interfaces * @package WooCommerce\Interfaces
*/ */
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/** /**
* WC Coupon Data Store Interface * WC Coupon Data Store Interface
* *

View File

@ -6,10 +6,6 @@
* @package WooCommerce\Interface * @package WooCommerce\Interface
*/ */
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/** /**
* WC Customer Data Store Interface * WC Customer Data Store Interface
* *

View File

@ -6,10 +6,6 @@
* @package WooCommerce\Interface * @package WooCommerce\Interface
*/ */
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/** /**
* WC Customer Download Data Store Interface. * WC Customer Download Data Store Interface.
* *

View File

@ -6,10 +6,6 @@
* @package WooCommerce\Interface * @package WooCommerce\Interface
*/ */
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/** /**
* WC Customer Download Log Data Store Interface. * WC Customer Download Log Data Store Interface.
* *

View File

@ -6,10 +6,6 @@
* @version 3.1.0 * @version 3.1.0
*/ */
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/** /**
* WC_Importer_Interface class. * WC_Importer_Interface class.
*/ */

View File

@ -6,10 +6,6 @@
* @package WooCommerce\Interface * @package WooCommerce\Interface
*/ */
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
/** /**
* WC Log Handler Interface * WC Log Handler Interface
* *

View File

@ -6,10 +6,6 @@
* @package WooCommerce\Interface * @package WooCommerce\Interface
*/ */
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
/** /**
* WC Logger Interface * WC Logger Interface
* *

View File

@ -6,10 +6,6 @@
* @package WooCommerce\Interface * @package WooCommerce\Interface
*/ */
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/** /**
* WC Data Store Interface * WC Data Store Interface
* *

View File

@ -6,10 +6,6 @@
* @package WooCommerce\Interface * @package WooCommerce\Interface
*/ */
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/** /**
* WC Order Data Store Interface * WC Order Data Store Interface
* *

View File

@ -6,10 +6,6 @@
* @package WooCommerce\Interface * @package WooCommerce\Interface
*/ */
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/** /**
* WC Order Item Data Store Interface * WC Order Item Data Store Interface
* *

View File

@ -6,10 +6,6 @@
* @package WooCommerce\Interface * @package WooCommerce\Interface
*/ */
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/** /**
* WC Order Item Data Store Interface * WC Order Item Data Store Interface
* *

View File

@ -6,10 +6,6 @@
* @package WooCommerce\Interface * @package WooCommerce\Interface
*/ */
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/** /**
* WC Order Item Data Store Interface * WC Order Item Data Store Interface
* *

View File

@ -6,10 +6,6 @@
* @package WooCommerce\Interface * @package WooCommerce\Interface
*/ */
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/** /**
* WC Order Refund Data Store Interface * WC Order Refund Data Store Interface
* *

View File

@ -6,10 +6,6 @@
* @package WooCommerce\Interface * @package WooCommerce\Interface
*/ */
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/** /**
* WC Payment Token Data Store Interface * WC Payment Token Data Store Interface
* *

View File

@ -6,10 +6,6 @@
* @package WooCommerce\Interface * @package WooCommerce\Interface
*/ */
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/** /**
* WC Product Data Store Interface * WC Product Data Store Interface
* *

View File

@ -6,10 +6,6 @@
* @package WooCommerce\Interface * @package WooCommerce\Interface
*/ */
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/** /**
* WC Product Variable Data Store Interface * WC Product Variable Data Store Interface
* *

View File

@ -6,10 +6,6 @@
* @package WooCommerce\Interface * @package WooCommerce\Interface
*/ */
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
/** /**
* WC Queue Interface * WC Queue Interface
* *

View File

@ -6,10 +6,6 @@
* @package WooCommerce\Interface * @package WooCommerce\Interface
*/ */
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/** /**
* WC Shipping Zone Data Store Interface. * WC Shipping Zone Data Store Interface.
* *

View File

@ -6,10 +6,6 @@
* @package WooCommerce\Interface * @package WooCommerce\Interface
*/ */
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/** /**
* WooCommerce Webhook data store interface. * WooCommerce Webhook data store interface.
*/ */

View File

@ -69,14 +69,6 @@ const runCheckoutPageTest = () => {
// Verify that settings have been saved // Verify that settings have been saved
await verifyCheckboxIsSet('#woocommerce_cod_enabled'); await verifyCheckboxIsSet('#woocommerce_cod_enabled');
// Enable PayPal payment method
await merchant.openSettings('checkout', 'paypal');
await setCheckbox('#woocommerce_paypal_enabled');
await settingsPageSaveChanges();
// Verify that settings have been saved
await verifyCheckboxIsSet('#woocommerce_paypal_enabled');
await merchant.logout(); await merchant.logout();
}); });
@ -93,7 +85,6 @@ const runCheckoutPageTest = () => {
await shopper.goToCheckout(); await shopper.goToCheckout();
await shopper.productIsInCheckout(simpleProductName, `2`, twoProductPrice, twoProductPrice); await shopper.productIsInCheckout(simpleProductName, `2`, twoProductPrice, twoProductPrice);
await expect(page).toClick('.wc_payment_method label', {text: 'PayPal'});
await expect(page).toClick('.wc_payment_method label', {text: 'Direct bank transfer'}); await expect(page).toClick('.wc_payment_method label', {text: 'Direct bank transfer'});
await expect(page).toClick('.wc_payment_method label', {text: 'Cash on delivery'}); await expect(page).toClick('.wc_payment_method label', {text: 'Cash on delivery'});
}); });

View File

@ -4,18 +4,37 @@
*/ */
const { const {
shopper, shopper,
merchant,
createSimpleProduct, createSimpleProduct,
createVariableProduct, createVariableProduct,
createGroupedProduct, createGroupedProduct,
uiUnblocked uiUnblocked
} = require( '@woocommerce/e2e-utils' ); } = require( '@woocommerce/e2e-utils' );
let simplePostIdValue;
let variablePostIdValue;
let groupedPostIdValue;
const config = require( 'config' ); const config = require( 'config' );
// Variables for simple product
const simpleProductName = config.get( 'products.simple.name' ); const simpleProductName = config.get( 'products.simple.name' );
let simplePostIdValue;
// Variables for variable product
const defaultVariableProduct = config.get( 'products.variable' );
let variableProductId;
// Variables for grouped product
const simpleProductPrice = config.has('products.simple.price') ? config.get('products.simple.price') : '9.99';
const simple1 = {
name: simpleProductName + ' 1',
regularPrice: simpleProductPrice
};
const simple2 = {
name: simpleProductName + ' 2',
regularPrice: simpleProductPrice
};
const groupedProduct = {
name: 'Grouped Product',
groupedProducts: [simple1, simple2]
};
let groupedPostIdValue;
const runSingleProductPageTest = () => { const runSingleProductPageTest = () => {
describe('Single Product Page', () => { describe('Single Product Page', () => {
@ -43,30 +62,34 @@ const runSingleProductPageTest = () => {
}); });
}); });
describe.skip('Variable Product Page', () => { describe('Variable Product Page', () => {
beforeAll(async () => { beforeAll(async () => {
await merchant.login(); variableProductId = await createVariableProduct();
variablePostIdValue = await createVariableProduct();
await merchant.logout();
}); });
it('should be able to add variation products to the cart', async () => { it('should be able to add variation products to the cart', async () => {
// Add a product with one set of variations to cart // Add a product with one set of variations to cart
await shopper.goToProduct(variablePostIdValue); await shopper.goToProduct(variableProductId);
await expect(page).toSelect('#attr-1', 'val1');
await expect(page).toSelect('#attr-2', 'val1'); for (const attr of defaultVariableProduct.attributes) {
await expect(page).toSelect('#attr-3', 'val1'); const { name, options } = attr;
const selectElem = `#${name.toLowerCase()}`;
const value = options[0];
await expect(page).toSelect(selectElem, value);
}
await shopper.addToCart(); await shopper.addToCart();
await expect(page).toMatchElement('.woocommerce-message', {text: 'has been added to your cart.'}); await expect(page).toMatchElement('.woocommerce-message', {text: 'has been added to your cart.'});
// Verify cart contents // Verify cart contents
await shopper.goToCart(); await shopper.goToCart();
await shopper.productIsInCart('Variable Product with Three Variations'); await shopper.productIsInCart(defaultVariableProduct.name);
}); });
it('should be able to remove variation products from the cart', async () => { it('should be able to remove variation products from the cart', async () => {
// Remove items from cart // Remove items from cart
await shopper.removeFromCart('Variable Product with Three Variations'); await shopper.removeFromCart(defaultVariableProduct.name);
await uiUnblocked(); await uiUnblocked();
await expect(page).toMatchElement('.cart-empty', {text: 'Your cart is currently empty.'}); await expect(page).toMatchElement('.cart-empty', {text: 'Your cart is currently empty.'});
}); });
@ -74,9 +97,7 @@ const runSingleProductPageTest = () => {
describe('Grouped Product Page', () => { describe('Grouped Product Page', () => {
beforeAll(async () => { beforeAll(async () => {
await merchant.login(); groupedPostIdValue = await createGroupedProduct(groupedProduct);
groupedPostIdValue = await createGroupedProduct();
await merchant.logout();
}); });
it('should be able to add grouped products to the cart', async () => { it('should be able to add grouped products to the cart', async () => {

View File

@ -4,57 +4,90 @@
*/ */
const { const {
shopper, shopper,
merchant,
createVariableProduct, createVariableProduct,
} = require( '@woocommerce/e2e-utils' ); } = require( '@woocommerce/e2e-utils' );
const config = require('config');
let variablePostIdValue; let variablePostIdValue;
const cartDialogMessage = 'Please select some product options before adding this product to your cart.'; const cartDialogMessage = 'Please select some product options before adding this product to your cart.';
const attributes = config.get( 'products.variable.attributes' )
const runVariableProductUpdateTest = () => { const runVariableProductUpdateTest = () => {
describe('Shopper > Update variable product',() => { describe('Shopper > Update variable product',() => {
beforeAll(async () => { beforeAll(async () => {
await merchant.login();
variablePostIdValue = await createVariableProduct(); variablePostIdValue = await createVariableProduct();
await merchant.logout();
}); });
it('shopper can change variable attributes to the same value', async () => { it('shopper can change variable attributes to the same value', async () => {
await shopper.goToProduct(variablePostIdValue); await shopper.goToProduct(variablePostIdValue);
await expect(page).toSelect('#attr-1', 'val1');
await expect(page).toSelect('#attr-2', 'val1');
await expect(page).toSelect('#attr-3', 'val1');
await expect(page).toMatchElement('.woocommerce-variation-price', { text: '9.99' }); for (const a of attributes) {
const { name, options } = a;
const attrHTMLId = `#${name.toLowerCase()}`;
await expect(page).toSelect(attrHTMLId, options[0]);
}
await expect(page).toMatchElement('.woocommerce-variation-price', {
text: '9.99'
});
}); });
it('shopper can change attributes to combination with dimensions and weight', async () => { it('shopper can change attributes to combination with dimensions and weight', async () => {
await shopper.goToProduct(variablePostIdValue); await shopper.goToProduct(variablePostIdValue);
await expect(page).toSelect('#attr-1', 'val1'); await expect(page).toSelect(
await expect(page).toSelect('#attr-2', 'val2'); `#${attributes[0].name.toLowerCase()}`,
await expect(page).toSelect('#attr-3', 'val1'); attributes[0].options[0]
);
await expect(page).toSelect(
`#${attributes[1].name.toLowerCase()}`,
attributes[1].options[1]
);
await expect(page).toSelect(
`#${attributes[2].name.toLowerCase()}`,
attributes[2].options[0]
);
await expect(page).toMatchElement('.woocommerce-variation-price', { text: '20.00' }); await expect(page).toMatchElement('.woocommerce-variation-price', { text: '20.00' });
await expect(page).toMatchElement('.woocommerce-variation-availability', { text: 'Out of stock' }); await expect(page).toMatchElement('.woocommerce-variation-availability', { text: 'Out of stock' });
await expect(page).toMatchElement('.woocommerce-product-attributes-item--weight', { text: '200 kg' }); await expect(page).toMatchElement('.woocommerce-product-attributes-item--weight', { text: '200 kg' });
await expect(page).toMatchElement('.woocommerce-product-attributes-item--dimensions', { text: '10 × 20 × 15 cm' }); await expect(page).toMatchElement('.woocommerce-product-attributes-item--dimensions', { text: '10 × 20 × 15 cm' });
}); });
it('shopper can change variable product attributes to variation with a different price', async () => { it('shopper can change variable product attributes to variation with a different price', async () => {
await shopper.goToProduct(variablePostIdValue); await shopper.goToProduct(variablePostIdValue);
await expect(page).toSelect('#attr-1', 'val1'); await expect(page).toSelect(
await expect(page).toSelect('#attr-2', 'val1'); `#${attributes[0].name.toLowerCase()}`,
await expect(page).toSelect('#attr-3', 'val2'); attributes[0].options[0]
);
await expect(page).toSelect(
`#${attributes[1].name.toLowerCase()}`,
attributes[1].options[0]
);
await expect(page).toSelect(
`#${attributes[2].name.toLowerCase()}`,
attributes[2].options[1]
);
await expect(page).toMatchElement('.woocommerce-variation-price', { text: '11.99' }); await expect(page).toMatchElement('.woocommerce-variation-price', { text: '11.99' });
}); });
it('shopper can reset variations', async () => { it('shopper can reset variations', async () => {
await shopper.goToProduct(variablePostIdValue); await shopper.goToProduct(variablePostIdValue);
await expect(page).toSelect('#attr-1', 'val1'); await expect(page).toSelect(
await expect(page).toSelect('#attr-2', 'val2'); `#${attributes[0].name.toLowerCase()}`,
await expect(page).toSelect('#attr-3', 'val1'); attributes[0].options[0]
);
await expect(page).toSelect(
`#${attributes[1].name.toLowerCase()}`,
attributes[1].options[1]
);
await expect(page).toSelect(
`#${attributes[2].name.toLowerCase()}`,
attributes[2].options[0]
);
await expect(page).toClick('.reset_variations'); await expect(page).toClick('.reset_variations');
@ -64,9 +97,6 @@ const runVariableProductUpdateTest = () => {
}); });
expect(couponDialog.message()).toMatch(cartDialogMessage); expect(couponDialog.message()).toMatch(cartDialogMessage);
// Accept the dialog
await couponDialog.accept();
}); });
}); });

View File

@ -1,5 +1,8 @@
# Unreleased # Unreleased
## Added
- Factories for variable product, variation, and grouped product
- Added new constant for WordPress update page `WP_ADMIN_WP_UPDATES` - Added new constant for WordPress update page `WP_ADMIN_WP_UPDATES`
- Added new merchant flow for `openWordPressUpdatesPage()` - Added new merchant flow for `openWordPressUpdatesPage()`
- Added new merchant flows: - Added new merchant flows:

View File

@ -7,10 +7,8 @@
*/ */
import { merchant, IS_RETEST_MODE } from './flows'; import { merchant, IS_RETEST_MODE } from './flows';
import { import {
clickTab,
uiUnblocked, uiUnblocked,
verifyCheckboxIsUnset, verifyCheckboxIsUnset,
selectOptionInSelect2,
setCheckbox, setCheckbox,
unsetCheckbox, unsetCheckbox,
evalAndClick, evalAndClick,
@ -24,6 +22,8 @@ const client = factories.api.withDefaultPermalinks;
const config = require( 'config' ); const config = require( 'config' );
const simpleProductName = config.get( 'products.simple.name' ); const simpleProductName = config.get( 'products.simple.name' );
const simpleProductPrice = config.has('products.simple.price') ? config.get('products.simple.price') : '9.99'; const simpleProductPrice = config.has('products.simple.price') ? config.get('products.simple.price') : '9.99';
const defaultVariableProduct = config.get('products.variable');
const defaultGroupedProduct = config.get('products.grouped');
/** /**
* Verify and publish * Verify and publish
@ -135,6 +135,9 @@ const completeOnboardingWizard = async () => {
// Business Details section // Business Details section
// Temporarily add delay to reduce test flakiness
await page.waitFor( 2000 );
// Query for the <SelectControl>s // Query for the <SelectControl>s
const selectControls = await page.$$( '.woocommerce-select-control' ); const selectControls = await page.$$( '.woocommerce-select-control' );
expect( selectControls ).toHaveLength( 2 ); expect( selectControls ).toHaveLength( 2 );
@ -220,172 +223,104 @@ const createSimpleProductWithCategory = async ( productName, productPrice, categ
/** /**
* Create variable product. * Create variable product.
* Also, create variations for all attributes.
*
* @param varProduct Defaults to the variable product object in `default.json`
* @returns the ID of the created variable product
*/ */
const createVariableProduct = async () => { const createVariableProduct = async (varProduct = defaultVariableProduct) => {
const { attributes } = varProduct;
const { id } = await factories.products.variable.create(varProduct); // create the variable product
const variations = [];
const buffer = []; // accumulated attributes while looping
const aIdx = 0; // attributes[] index
// We need to remove any listeners on the `dialog` event otherwise we can't catch the dialogs below // Create variation for all attributes
page.removeAllListeners('dialog'); const createVariation = (aIdx) => {
const { name, options } = attributes[aIdx];
const isLastAttribute = aIdx === attributes.length - 1;
// Go to "add product" page // Add each attribute value to the buffer.
await merchant.openNewProduct(); options.forEach((opt) => {
buffer.push({
name: name,
option: opt
});
// Make sure we're on the add product page if (isLastAttribute) {
await expect( page.title() ).resolves.toMatch( 'Add new product' ); // If this is the last attribute, it means the variation is now complete.
// Save whatever's been accumulated in the buffer to the `variations[]` array.
// Set product data variations.push({
await expect( page ).toFill( '#title', 'Variable Product with Three Variations' ); attributes: [...buffer]
await expect( page ).toSelect( '#product-type', 'Variable product' ); });
} else {
// Create attributes for variations // Otherwise, move to the next attribute first
await clickTab( 'Attributes' ); // before proceeding to the next value in this attribute.
await expect( page ).toSelect( 'select[name="attribute_taxonomy"]', 'Custom product attribute' ); createVariation(aIdx + 1);
for ( let i = 0; i < 3; i++ ) {
await expect( page ).toClick( 'button.add_attribute', { text: 'Add' } );
// Wait for attribute form to load
await uiUnblocked();
await page.focus( `input[name="attribute_names[${ i }]"]` );
await expect( page ).toFill( `input[name="attribute_names[${ i }]"]`, 'attr #' + ( i + 1 ) );
await expect( page ).toFill( `textarea[name="attribute_values[${ i }]"]`, 'val1 | val2' );
await expect( page ).toClick( `input[name="attribute_variation[${ i }]"]` );
} }
await expect( page ).toClick( 'button', { text: 'Save attributes' } ); buffer.pop();
});
};
createVariation(aIdx);
// Wait for attribute form to save (triggers 2 UI blocks) // Set some properties of 1st variation
await uiUnblocked(); variations[0].regularPrice = '9.99';
await page.waitFor( 1000 ); variations[0].virtual = true;
await uiUnblocked();
// Create variations from attributes // Set some properties of 2nd variation
await clickTab( 'Variations' ); variations[1].regularPrice = '11.99';
await page.waitForSelector( 'select.variation_actions:not([disabled])' ); variations[1].virtual = true;
await page.focus( 'select.variation_actions' );
await expect( page ).toSelect( 'select.variation_actions', 'Create variations from all attributes' );
const firstDialog = await expect( page ).toDisplayDialog( async () => { // Set some properties of 3rd variation
// Using this technique since toClick() isn't working. variations[2].regularPrice = '20';
// See: https://github.com/GoogleChrome/puppeteer/issues/1805#issuecomment-464802876 variations[2].weight = '200';
page.$eval( 'a.do_variation_action', elem => elem.click() ); variations[2].dimensions = {
length: '10',
width: '20',
height: '15'
};
variations[2].manage_stock = true;
} ); // Use API to create each variation
for (const v of variations) {
await factories.products.variation.create({
productId: id,
variation: v
});
}
expect( firstDialog.message() ).toMatch( 'Are you sure you want to link all variations?' ); return id;
const secondDialog = await expect( page ).toDisplayDialog( async () => {
await firstDialog.accept();
} );
expect( secondDialog.message() ).toMatch( '8 variations added' );
await secondDialog.dismiss();
// Set some variation data
await uiUnblocked();
await uiUnblocked();
await page.waitForSelector( '.woocommerce_variation .handlediv' );
// Verify that variations were created
await Promise.all( [
expect( page ).toMatchElement( 'select[name="attribute_attr-1[0]"]', { text: 'val1' } ),
expect( page ).toMatchElement( 'select[name="attribute_attr-2[0]"]', { text: 'val1' } ),
expect( page ).toMatchElement( 'select[name="attribute_attr-3[0]"]', { text: 'val1' } ),
expect( page ).toMatchElement( 'select[name="attribute_attr-1[1]"]', { text: 'val1' } ),
expect( page ).toMatchElement( 'select[name="attribute_attr-2[1]"]', { text: 'val1' } ),
expect( page ).toMatchElement( 'select[name="attribute_attr-3[1]"]', { text: 'val2' } ),
expect( page ).toMatchElement( 'select[name="attribute_attr-1[2]"]', { text: 'val1' } ),
expect( page ).toMatchElement( 'select[name="attribute_attr-2[2]"]', { text: 'val2' } ),
expect( page ).toMatchElement( 'select[name="attribute_attr-3[2]"]', { text: 'val1' } ),
expect( page ).toMatchElement( 'select[name="attribute_attr-1[3]"]', { text: 'val1' } ),
expect( page ).toMatchElement( 'select[name="attribute_attr-2[3]"]', { text: 'val2' } ),
expect( page ).toMatchElement( 'select[name="attribute_attr-3[3]"]', { text: 'val2' } ),
expect( page ).toMatchElement( 'select[name="attribute_attr-1[4]"]', { text: 'val2' } ),
expect( page ).toMatchElement( 'select[name="attribute_attr-2[4]"]', { text: 'val1' } ),
expect( page ).toMatchElement( 'select[name="attribute_attr-3[4]"]', { text: 'val1' } ),
expect( page ).toMatchElement( 'select[name="attribute_attr-1[5]"]', { text: 'val2' } ),
expect( page ).toMatchElement( 'select[name="attribute_attr-2[5]"]', { text: 'val1' } ),
expect( page ).toMatchElement( 'select[name="attribute_attr-3[5]"]', { text: 'val2' } ),
expect( page ).toMatchElement( 'select[name="attribute_attr-1[6]"]', { text: 'val2' } ),
expect( page ).toMatchElement( 'select[name="attribute_attr-2[6]"]', { text: 'val2' } ),
expect( page ).toMatchElement( 'select[name="attribute_attr-3[6]"]', { text: 'val1' } ),
expect( page ).toMatchElement( 'select[name="attribute_attr-1[7]"]', { text: 'val2' } ),
expect( page ).toMatchElement( 'select[name="attribute_attr-2[7]"]', { text: 'val2' } ),
expect( page ).toMatchElement( 'select[name="attribute_attr-3[7]"]', { text: 'val2' } ),
] );
await expect( page ).toClick( '.woocommerce_variation:nth-of-type(2) .handlediv' );
await page.waitFor( 2000 );
await page.focus( 'input[name="variable_is_virtual[0]"]' );
await expect( page ).toClick( 'input[name="variable_is_virtual[0]"]' );
await expect( page ).toFill( 'input[name="variable_regular_price[0]"]', '9.99' );
await expect( page ).toClick( '.woocommerce_variation:nth-of-type(3) .handlediv' );
await page.waitFor( 2000 );
await page.focus( 'input[name="variable_is_virtual[1]"]' );
await expect( page ).toClick( 'input[name="variable_is_virtual[1]"]' );
await expect( page ).toFill( 'input[name="variable_regular_price[1]"]', '11.99' );
await expect( page ).toClick( '.woocommerce_variation:nth-of-type(4) .handlediv' );
await page.waitFor( 2000 );
await page.focus( 'input[name="variable_manage_stock[2]"]' );
await expect( page ).toClick( 'input[name="variable_manage_stock[2]"]' );
await expect( page ).toFill( 'input[name="variable_regular_price[2]"]', '20' );
await expect( page ).toFill( 'input[name="variable_weight[2]"]', '200' );
await expect( page ).toFill( 'input[name="variable_length[2]"]', '10' );
await expect( page ).toFill( 'input[name="variable_width[2]"]', '20' );
await expect( page ).toFill( 'input[name="variable_height[2]"]', '15' );
await page.focus( 'button.save-variation-changes' );
await expect( page ).toClick( 'button.save-variation-changes', { text: 'Save changes' } );
await verifyAndPublish( 'Product published.' );
const variablePostId = await page.$( '#post_ID' );
let variablePostIdValue = ( await ( await variablePostId.getProperty( 'value' ) ).jsonValue() );
return variablePostIdValue;
}; };
/** /**
* Create grouped product. * Create grouped product.
*
* @param groupedProduct Defaults to the grouped product object in `default.json`
* @returns ID of the grouped product
*/ */
const createGroupedProduct = async () => { const createGroupedProduct = async (groupedProduct = defaultGroupedProduct) => {
// Create two products to be linked in a grouped product after const { name, groupedProducts } = groupedProduct;
await factories.products.simple.create( { const simpleProductIds = [];
name: simpleProductName + ' 1', let groupedProductRequest;
regularPrice: simpleProductPrice
} );
await factories.products.simple.create( {
name: simpleProductName + ' 2',
regularPrice: simpleProductPrice
} );
// Go to "add product" page // Using the api, create simple products to be grouped
await merchant.openNewProduct(); for (const simpleProduct of groupedProducts) {
const { id } = await factories.products.simple.create(simpleProduct);
simpleProductIds.push(id);
}
// Make sure we're on the add product page // Using the api, create the grouped product
await expect( page.title() ).resolves.toMatch( 'Add new product' ); groupedProductRequest = {
name: name,
groupedProducts: simpleProductIds
};
const { id } = await factories.products.grouped.create(
groupedProductRequest
);
// Set product data and save the product return id;
await expect( page ).toFill( '#title', 'Grouped Product' ); };
await expect( page ).toSelect( '#product-type', 'Grouped product' );
await clickTab( 'Linked Products' );
await selectOptionInSelect2( simpleProductName + ' 1' );
await selectOptionInSelect2( simpleProductName + ' 2' );
await verifyAndPublish();
// Get product ID
const groupedPostId = await page.$( '#post_ID' );
let groupedPostIdValue = ( await ( await groupedPostId.getProperty( 'value' ) ).jsonValue() );
return groupedPostIdValue;
}
/** /**
* Create a basic order with the provided order status. * Create a basic order with the provided order status.

View File

@ -1,6 +1,9 @@
import { HTTPClientFactory } from '@woocommerce/api'; import { HTTPClientFactory } from '@woocommerce/api';
const config = require( 'config' ); const config = require( 'config' );
import { simpleProductFactory } from './factories/simple-product'; import { simpleProductFactory } from './factories/simple-product';
import { variableProductFactory } from './factories/variable-product';
import { variationFactory } from './factories/variation';
import { groupedProductFactory } from './factories/grouped-product';
const apiUrl = config.get( 'url' ); const apiUrl = config.get( 'url' );
const adminUsername = config.get( 'users.admin.username' ); const adminUsername = config.get( 'users.admin.username' );
@ -20,6 +23,9 @@ const factories = {
}, },
products: { products: {
simple: simpleProductFactory( withDefaultPermalinks ), simple: simpleProductFactory( withDefaultPermalinks ),
variable: variableProductFactory( withDefaultPermalinks ),
variation: variationFactory( withDefaultPermalinks ),
grouped: groupedProductFactory( withDefaultPermalinks )
}, },
}; };

View File

@ -0,0 +1,26 @@
import { GroupedProduct } from '@woocommerce/api';
import { Factory } from 'fishery';
/**
* Creates a new factory for creating variable products.
* This does not include creating product variations.
* Instead, use `variationFactory()` for that.
*
* @param {HTTPClient} httpClient The HTTP client we will give the repository.
* @return {AsyncFactory} The factory for creating models.
*/
export function groupedProductFactory(httpClient) {
const repository = GroupedProduct.restRepository(httpClient);
return Factory.define(({ params, onCreate }) => {
onCreate((model) => {
return repository.create(model);
});
return {
name: params.name,
type: 'grouped',
groupedProducts: params.groupedProducts
};
});
}

View File

@ -0,0 +1,27 @@
import { VariableProduct } from '@woocommerce/api';
import { Factory } from 'fishery';
/**
* Creates a new factory for creating variable products.
* This does not include creating product variations.
* Instead, use `variationFactory()` for that.
*
* @param {HTTPClient} httpClient The HTTP client we will give the repository.
* @return {AsyncFactory} The factory for creating models.
*/
export function variableProductFactory(httpClient) {
const repository = VariableProduct.restRepository(httpClient);
return Factory.define(({ params, onCreate }) => {
onCreate((model) => {
return repository.create(model);
});
return {
name: params.name,
type: 'variable',
defaultAttributes: params.defaultAttributes,
attributes: params.attributes
};
});
}

View File

@ -0,0 +1,22 @@
import { ProductVariation } from '@woocommerce/api';
import { Factory } from 'fishery';
/**
* Creates a new factory for creating a product variation.
*
* @param {HTTPClient} httpClient The HTTP client we will give the repository.
* @return {AsyncFactory} The factory for creating models.
*/
export function variationFactory(httpClient) {
const repository = ProductVariation.restRepository(httpClient);
return Factory.define(({ params, onCreate }) => {
const { productId, variation } = params;
onCreate((model) => {
return repository.create(productId, model);
});
return variation;
});
}

View File

@ -58,6 +58,9 @@ class WC_Unit_Tests_Bootstrap {
// load test function so tests_add_filter() is available. // load test function so tests_add_filter() is available.
require_once $this->wp_tests_dir . '/includes/functions.php'; require_once $this->wp_tests_dir . '/includes/functions.php';
// Always load PayPal Standard for unit tests.
tests_add_filter( 'woocommerce_should_load_paypal_standard', '__return_true' );
// load WC. // load WC.
tests_add_filter( 'muplugins_loaded', array( $this, 'load_wc' ) ); tests_add_filter( 'muplugins_loaded', array( $this, 'load_wc' ) );

View File

@ -84,6 +84,7 @@ class WC_Tests_Product_CSV_Importer extends WC_Unit_Test_Case {
'Attribute 2 value(s)' => 'attributes:value2', 'Attribute 2 value(s)' => 'attributes:value2',
'Attribute 1 default' => 'attributes:default1', 'Attribute 1 default' => 'attributes:default1',
'Attribute 2 default' => 'attributes:default2', 'Attribute 2 default' => 'attributes:default2',
'Download 1 ID' => 'downloads:id1',
'Download 1 name' => 'downloads:name1', 'Download 1 name' => 'downloads:name1',
'Download 1 URL' => 'downloads:url1', 'Download 1 URL' => 'downloads:url1',
); );
@ -238,6 +239,7 @@ class WC_Tests_Product_CSV_Importer extends WC_Unit_Test_Case {
'', '',
'', '',
'', '',
'',
), ),
array( array(
'simple, downloadable, virtual', 'simple, downloadable, virtual',
@ -283,6 +285,7 @@ class WC_Tests_Product_CSV_Importer extends WC_Unit_Test_Case {
'180-Gram', '180-Gram',
'', '',
'', '',
'4ff604c2-97bd-4869-938b-7798ba6648ab',
'Album flac', 'Album flac',
'http://woo.dev/albums/album.flac', 'http://woo.dev/albums/album.flac',
), ),
@ -395,6 +398,7 @@ class WC_Tests_Product_CSV_Importer extends WC_Unit_Test_Case {
array( array(
'name' => 'Album flac', 'name' => 'Album flac',
'file' => 'http://woo.dev/albums/album.flac', 'file' => 'http://woo.dev/albums/album.flac',
'download_id' => '4ff604c2-97bd-4869-938b-7798ba6648ab',
), ),
), ),
'menu_order' => 1, 'menu_order' => 1,

View File

@ -1,8 +1,8 @@
Type,SKU,Name,Published,Is featured?,Visibility in catalog,Short description,Description,Date sale price starts,Date sale price ends,Tax status,Tax class,In stock?,Stock,Backorders allowed?,Sold individually?,Weight (kg),Length (cm),Width (cm),Height (cm),Allow customer reviews?,Purchase note,Sale price,Regular price,Categories,Tags,Shipping class,Images,Download limit,Download expiry days,Parent,Upsells,Cross-sells,Grouped products,External URL,BUTTON TEXT,Position,Attribute 1 Name,Attribute 1 Value(s),Attribute 2 name,Attribute 2 value(s),Attribute 1 default,Attribute 2 default,Download 1 name,Download 1 URL Type,SKU,Name,Published,Is featured?,Visibility in catalog,Short description,Description,Date sale price starts,Date sale price ends,Tax status,Tax class,In stock?,Stock,Backorders allowed?,Sold individually?,Weight (kg),Length (cm),Width (cm),Height (cm),Allow customer reviews?,Purchase note,Sale price,Regular price,Categories,Tags,Shipping class,Images,Download limit,Download expiry days,Parent,Upsells,Cross-sells,Grouped products,External URL,BUTTON TEXT,Position,Attribute 1 Name,Attribute 1 Value(s),Attribute 2 name,Attribute 2 value(s),Attribute 1 default,Attribute 2 default,Download 1 ID,Download 1 name,Download 1 URL
simple,WOOLOGO,Woo Logo,1,,visible,"Lorem ipsum dolor sit amet, at exerci civibus appetere sit, iuvaret hendrerit mea no. Eam integre feugait liberavisse an.","Lorem ipsum dolor sit amet, at exerci civibus appetere sit, iuvaret hendrerit mea no. Eam integre feugait liberavisse an.",2017-01-01,2030-01-01 0:00:00,taxable,standard,1,5,notify,1,1,1,20,40,1,Lorem ipsum dolor sit amet.,18,20,"Clothing, Clothing > T-shirts",,,"http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/T_1_front.jpg, http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/T_1_back.jpg",,,,WOOALBUM,WOOALBUM,,,,0,Color,Red,,,,,, simple,WOOLOGO,Woo Logo,1,,visible,"Lorem ipsum dolor sit amet, at exerci civibus appetere sit, iuvaret hendrerit mea no. Eam integre feugait liberavisse an.","Lorem ipsum dolor sit amet, at exerci civibus appetere sit, iuvaret hendrerit mea no. Eam integre feugait liberavisse an.",2017-01-01,2030-01-01 0:00:00,taxable,standard,1,5,notify,1,1,1,20,40,1,Lorem ipsum dolor sit amet.,18,20,"Clothing, Clothing > T-shirts",,,"http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/T_1_front.jpg, http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/T_1_back.jpg",,,,WOOALBUM,WOOALBUM,,,,0,Color,Red,,,,,,,
"simple, downloadable, virtual",WOOALBUM,Woo Album #1,1,1,visible,"Lorem ipsum dolor sit amet, at exerci civibus appetere sit, iuvaret hendrerit mea no. Eam integre feugait liberavisse an.","Lorem ipsum dolor sit amet, at exerci civibus appetere sit, iuvaret hendrerit mea no. Eam integre feugait liberavisse an.",,,taxable,standard,1,,,,,,,,1,Lorem ipsum dolor sit amet.,,5,"Music > Albums, Music",Woo,,"http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/cd_1_angle.jpg, http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/cd_1_flat.jpg",10,90,,WOOLOGO,WOOLOGO,,,,1,Label,WooCommerce,Vinyl,180-Gram,,,Album flac,http://woo.dev/albums/album.flac "simple, downloadable, virtual",WOOALBUM,Woo Album #1,1,1,visible,"Lorem ipsum dolor sit amet, at exerci civibus appetere sit, iuvaret hendrerit mea no. Eam integre feugait liberavisse an.","Lorem ipsum dolor sit amet, at exerci civibus appetere sit, iuvaret hendrerit mea no. Eam integre feugait liberavisse an.",,,taxable,standard,1,,,,,,,,1,Lorem ipsum dolor sit amet.,,5,"Music > Albums, Music",Woo,,"http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/cd_1_angle.jpg, http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/cd_1_flat.jpg",10,90,,WOOLOGO,WOOLOGO,,,,1,Label,WooCommerce,Vinyl,180-Gram,,,4ff604c2-97bd-4869-938b-7798ba6648ab,Album flac,http://woo.dev/albums/album.flac
external,,WooCommerce Product CSV Suite,1,,visible,"Lorem ipsum dolor sit amet, at exerci civibus appetere sit, iuvaret hendrerit mea no. Eam integre feugait liberavisse an.","Lorem ipsum dolor sit amet, at exerci civibus appetere sit, iuvaret hendrerit mea no. Eam integre feugait liberavisse an.",,,taxable,standard,1,,,,,,,,0,Lorem ipsum dolor sit amet.,,199,Software,WooCommerce,,,,,,,,,https://woocommerce.com/products/product-csv-import-suite/,Buy on WooCommerce.com,2,,,,,,,, external,,WooCommerce Product CSV Suite,1,,visible,"Lorem ipsum dolor sit amet, at exerci civibus appetere sit, iuvaret hendrerit mea no. Eam integre feugait liberavisse an.","Lorem ipsum dolor sit amet, at exerci civibus appetere sit, iuvaret hendrerit mea no. Eam integre feugait liberavisse an.",,,taxable,standard,1,,,,,,,,0,Lorem ipsum dolor sit amet.,,199,Software,WooCommerce,,,,,,,,,https://woocommerce.com/products/product-csv-import-suite/,Buy on WooCommerce.com,2,,,,,,,,,
variable,WOOIDEA,Ship Your Idea,1,,visible,"Lorem ipsum dolor sit amet, at exerci civibus appetere sit, iuvaret hendrerit mea no. Eam integre feugait liberavisse an.","Lorem ipsum dolor sit amet, at exerci civibus appetere sit, iuvaret hendrerit mea no. Eam integre feugait liberavisse an.",,,,,,,,,,,,,1,Lorem ipsum dolor sit amet.,,,"Clothing, Clothing > T-shirts",,,"http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/T_4_front.jpg, http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/T_4_back.jpg, http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/T_3_front.jpg, http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/T_3_back.jpg",,,,,,,,,3,Color,"Black, Green",Size,"M, L",Green,L,, variable,WOOIDEA,Ship Your Idea,1,,visible,"Lorem ipsum dolor sit amet, at exerci civibus appetere sit, iuvaret hendrerit mea no. Eam integre feugait liberavisse an.","Lorem ipsum dolor sit amet, at exerci civibus appetere sit, iuvaret hendrerit mea no. Eam integre feugait liberavisse an.",,,,,,,,,,,,,1,Lorem ipsum dolor sit amet.,,,"Clothing, Clothing > T-shirts",,,"http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/T_4_front.jpg, http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/T_4_back.jpg, http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/T_3_front.jpg, http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/T_3_back.jpg",,,,,,,,,3,Color,"Black, Green",Size,"M, L",Green,L,,,
variation,,,1,,visible,,"Lorem ipsum dolor sit amet, at exerci civibus appetere sit, iuvaret hendrerit mea no. Eam integre feugait liberavisse an.",,,taxable,standard,1,6,0,,1,2,25,55,,,,20,,,,http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/T_4_front.jpg,,,WOOIDEA,,,,,,1,Color,Black,Size,M,,,, variation,,,1,,visible,,"Lorem ipsum dolor sit amet, at exerci civibus appetere sit, iuvaret hendrerit mea no. Eam integre feugait liberavisse an.",,,taxable,standard,1,6,0,,1,2,25,55,,,,20,,,,http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/T_4_front.jpg,,,WOOIDEA,,,,,,1,Color,Black,Size,M,,,,,
variation,,,1,,visible,,"Lorem ipsum dolor sit amet, at exerci civibus appetere sit, iuvaret hendrerit mea no. Eam integre feugait liberavisse an.",,,taxable,standard,1,10,1,,1,2,25,55,,,17.99,20,,,,http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/T_3_front.jpg,,,WOOIDEA,,,,,,2,Color,Green,Size,L,,,, variation,,,1,,visible,,"Lorem ipsum dolor sit amet, at exerci civibus appetere sit, iuvaret hendrerit mea no. Eam integre feugait liberavisse an.",,,taxable,standard,1,10,1,,1,2,25,55,,,17.99,20,,,,http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/T_3_front.jpg,,,WOOIDEA,,,,,,2,Color,Green,Size,L,,,,,
grouped,,Best Woo Products,1,1,visible,"Lorem ipsum dolor sit amet, at exerci civibus appetere sit, iuvaret hendrerit mea no. Eam integre feugait liberavisse an.","Lorem ipsum dolor sit amet, at exerci civibus appetere sit, iuvaret hendrerit mea no. Eam integre feugait liberavisse an.",,,,,1,,,,,,,,,,,,"Clothing, Clothing > T-shirts, Music > Albums, Music",,,"http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/T_1_front.jpg, http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/cd_1_angle.jpg",,,,,,"WOOLOGO, WOOALBUM",,,4,,,,,,,, grouped,,Best Woo Products,1,1,visible,"Lorem ipsum dolor sit amet, at exerci civibus appetere sit, iuvaret hendrerit mea no. Eam integre feugait liberavisse an.","Lorem ipsum dolor sit amet, at exerci civibus appetere sit, iuvaret hendrerit mea no. Eam integre feugait liberavisse an.",,,,,1,,,,,,,,,,,,"Clothing, Clothing > T-shirts, Music > Albums, Music",,,"http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/T_1_front.jpg, http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/cd_1_angle.jpg",,,,,,"WOOLOGO, WOOALBUM",,,4,,,,,,,,,

1 Type SKU Name Published Is featured? Visibility in catalog Short description Description Date sale price starts Date sale price ends Tax status Tax class In stock? Stock Backorders allowed? Sold individually? Weight (kg) Length (cm) Width (cm) Height (cm) Allow customer reviews? Purchase note Sale price Regular price Categories Tags Shipping class Images Download limit Download expiry days Parent Upsells Cross-sells Grouped products External URL BUTTON TEXT Position Attribute 1 Name Attribute 1 Value(s) Attribute 2 name Attribute 2 value(s) Attribute 1 default Attribute 2 default Download 1 ID Download 1 name Download 1 URL
2 simple WOOLOGO Woo Logo 1 visible Lorem ipsum dolor sit amet, at exerci civibus appetere sit, iuvaret hendrerit mea no. Eam integre feugait liberavisse an. Lorem ipsum dolor sit amet, at exerci civibus appetere sit, iuvaret hendrerit mea no. Eam integre feugait liberavisse an. 2017-01-01 2030-01-01 0:00:00 taxable standard 1 5 notify 1 1 1 20 40 1 Lorem ipsum dolor sit amet. 18 20 Clothing, Clothing > T-shirts http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/T_1_front.jpg, http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/T_1_back.jpg WOOALBUM WOOALBUM 0 Color Red
3 simple, downloadable, virtual WOOALBUM Woo Album #1 1 1 visible Lorem ipsum dolor sit amet, at exerci civibus appetere sit, iuvaret hendrerit mea no. Eam integre feugait liberavisse an. Lorem ipsum dolor sit amet, at exerci civibus appetere sit, iuvaret hendrerit mea no. Eam integre feugait liberavisse an. taxable standard 1 1 Lorem ipsum dolor sit amet. 5 Music > Albums, Music Woo http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/cd_1_angle.jpg, http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/cd_1_flat.jpg 10 90 WOOLOGO WOOLOGO 1 Label WooCommerce Vinyl 180-Gram 4ff604c2-97bd-4869-938b-7798ba6648ab Album flac http://woo.dev/albums/album.flac
4 external WooCommerce Product CSV Suite 1 visible Lorem ipsum dolor sit amet, at exerci civibus appetere sit, iuvaret hendrerit mea no. Eam integre feugait liberavisse an. Lorem ipsum dolor sit amet, at exerci civibus appetere sit, iuvaret hendrerit mea no. Eam integre feugait liberavisse an. taxable standard 1 0 Lorem ipsum dolor sit amet. 199 Software WooCommerce https://woocommerce.com/products/product-csv-import-suite/ Buy on WooCommerce.com 2
5 variable WOOIDEA Ship Your Idea 1 visible Lorem ipsum dolor sit amet, at exerci civibus appetere sit, iuvaret hendrerit mea no. Eam integre feugait liberavisse an. Lorem ipsum dolor sit amet, at exerci civibus appetere sit, iuvaret hendrerit mea no. Eam integre feugait liberavisse an. 1 Lorem ipsum dolor sit amet. Clothing, Clothing > T-shirts http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/T_4_front.jpg, http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/T_4_back.jpg, http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/T_3_front.jpg, http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/T_3_back.jpg 3 Color Black, Green Size M, L Green L
6 variation 1 visible Lorem ipsum dolor sit amet, at exerci civibus appetere sit, iuvaret hendrerit mea no. Eam integre feugait liberavisse an. taxable standard 1 6 0 1 2 25 55 20 http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/T_4_front.jpg WOOIDEA 1 Color Black Size M
7 variation 1 visible Lorem ipsum dolor sit amet, at exerci civibus appetere sit, iuvaret hendrerit mea no. Eam integre feugait liberavisse an. taxable standard 1 10 1 1 2 25 55 17.99 20 http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/T_3_front.jpg WOOIDEA 2 Color Green Size L
8 grouped Best Woo Products 1 1 visible Lorem ipsum dolor sit amet, at exerci civibus appetere sit, iuvaret hendrerit mea no. Eam integre feugait liberavisse an. Lorem ipsum dolor sit amet, at exerci civibus appetere sit, iuvaret hendrerit mea no. Eam integre feugait liberavisse an. 1 Clothing, Clothing > T-shirts, Music > Albums, Music http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/T_1_front.jpg, http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/cd_1_angle.jpg WOOLOGO, WOOALBUM 4