diff --git a/bin/composer/wp/composer.lock b/bin/composer/wp/composer.lock index 0674d3f98fa..08806cfd5e5 100644 --- a/bin/composer/wp/composer.lock +++ b/bin/composer/wp/composer.lock @@ -254,16 +254,16 @@ }, { "name": "rmccue/requests", - "version": "v1.8.0", + "version": "v1.8.1", "source": { "type": "git", "url": "https://github.com/WordPress/Requests.git", - "reference": "afbe4790e4def03581c4a0963a1e8aa01f6030f1" + "reference": "82e6936366eac3af4d836c18b9d8c31028fe4cd5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/WordPress/Requests/zipball/afbe4790e4def03581c4a0963a1e8aa01f6030f1", - "reference": "afbe4790e4def03581c4a0963a1e8aa01f6030f1", + "url": "https://api.github.com/repos/WordPress/Requests/zipball/82e6936366eac3af4d836c18b9d8c31028fe4cd5", + "reference": "82e6936366eac3af4d836c18b9d8c31028fe4cd5", "shasum": "" }, "require": { @@ -306,11 +306,7 @@ "iri", "sockets" ], - "support": { - "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" + "time": "2021-06-04T09:56:25+00:00" }, { "name": "symfony/finder", @@ -612,5 +608,5 @@ "platform-overrides": { "php": "7.0" }, - "plugin-api-version": "2.0.0" + "plugin-api-version": "1.1.0" } diff --git a/composer.json b/composer.json index 276a8a09036..f1bb1a94606 100644 --- a/composer.json +++ b/composer.json @@ -21,8 +21,8 @@ "pelago/emogrifier": "3.1.0", "psr/container": "1.0.0", "woocommerce/action-scheduler": "3.2.0", - "woocommerce/woocommerce-admin": "2.3.1", - "woocommerce/woocommerce-blocks": "5.1.0" + "woocommerce/woocommerce-admin": "2.4.0-rc.2", + "woocommerce/woocommerce-blocks": "5.3.1" }, "require-dev": { "bamarni/composer-bin-plugin": "^1.4" diff --git a/composer.lock b/composer.lock index 15575a3419f..72facb2f192 100644 --- a/composer.lock +++ b/composer.lock @@ -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": "21b06e63b5f65deec4b635463a10402b", + "content-hash": "6427ca1d82e637782404faeb3b988ec3", "packages": [ { "name": "automattic/jetpack-autoloader", @@ -51,9 +51,6 @@ "GPL-2.0-or-later" ], "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" }, { @@ -85,9 +82,6 @@ "GPL-2.0-or-later" ], "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" }, { @@ -220,10 +214,6 @@ "zend", "zikula" ], - "support": { - "issues": "https://github.com/composer/installers/issues", - "source": "https://github.com/composer/installers/tree/v1.11.0" - }, "funding": [ { "url": "https://packagist.com", @@ -298,10 +288,6 @@ "geolocation", "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" }, { @@ -376,10 +362,6 @@ "email", "pre-processing" ], - "support": { - "issues": "https://github.com/MyIntervals/emogrifier/issues", - "source": "https://github.com/MyIntervals/emogrifier" - }, "time": "2019-12-26T19:37:31+00:00" }, { @@ -429,10 +411,6 @@ "container-interop", "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" }, { @@ -486,9 +464,6 @@ ], "description": "Symfony CssSelector Component", "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/css-selector/tree/master" - }, "time": "2017-05-01T15:01:29+00:00" }, { @@ -532,16 +507,16 @@ }, { "name": "woocommerce/woocommerce-admin", - "version": "2.3.1", + "version": "2.4.0-rc.2", "source": { "type": "git", "url": "https://github.com/woocommerce/woocommerce-admin.git", - "reference": "f28cf3f027e27a6679e4fa8173d8b6859ec84838" + "reference": "ed72985cd459831c555dff2ff5f75111b6e210c1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/woocommerce/woocommerce-admin/zipball/f28cf3f027e27a6679e4fa8173d8b6859ec84838", - "reference": "f28cf3f027e27a6679e4fa8173d8b6859ec84838", + "url": "https://api.github.com/repos/woocommerce/woocommerce-admin/zipball/ed72985cd459831c555dff2ff5f75111b6e210c1", + "reference": "ed72985cd459831c555dff2ff5f75111b6e210c1", "shasum": "" }, "require": { @@ -576,24 +551,20 @@ ], "description": "A modern, javascript-driven WooCommerce Admin experience.", "homepage": "https://github.com/woocommerce/woocommerce-admin", - "support": { - "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" + "time": "2021-06-18T05:58:25+00:00" }, { "name": "woocommerce/woocommerce-blocks", - "version": "v5.1.0", + "version": "v5.3.1", "source": { "type": "git", "url": "https://github.com/woocommerce/woocommerce-gutenberg-products-block.git", - "reference": "a4f168596f3832e161b26dec636b69293039ee51" + "reference": "28c7c4f9b5cace9098fb2246ff93abe110a26bca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/woocommerce/woocommerce-gutenberg-products-block/zipball/a4f168596f3832e161b26dec636b69293039ee51", - "reference": "a4f168596f3832e161b26dec636b69293039ee51", + "url": "https://api.github.com/repos/woocommerce/woocommerce-gutenberg-products-block/zipball/28c7c4f9b5cace9098fb2246ff93abe110a26bca", + "reference": "28c7c4f9b5cace9098fb2246ff93abe110a26bca", "shasum": "" }, "require": { @@ -627,11 +598,7 @@ "gutenberg", "woocommerce" ], - "support": { - "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" + "time": "2021-06-15T09:12:48+00:00" } ], "packages-dev": [ @@ -679,10 +646,6 @@ "isolation", "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" } ], @@ -698,5 +661,5 @@ "platform-overrides": { "php": "7.0" }, - "plugin-api-version": "2.0.0" + "plugin-api-version": "1.1.0" } diff --git a/includes/admin/importers/class-wc-product-csv-importer-controller.php b/includes/admin/importers/class-wc-product-csv-importer-controller.php index 0de82507fdc..b14ad20f453 100644 --- a/includes/admin/importers/class-wc-product-csv-importer-controller.php +++ b/includes/admin/importers/class-wc-product-csv-importer-controller.php @@ -566,6 +566,8 @@ class WC_Product_CSV_Importer_Controller { /* translators: %d: Attribute number */ __( 'Attribute %d default', 'woocommerce' ) => 'attributes:default', /* translators: %d: Download number */ + __( 'Download %d ID', 'woocommerce' ) => 'downloads:id', + /* translators: %d: Download number */ __( 'Download %d name', 'woocommerce' ) => 'downloads:name', /* translators: %d: Download number */ __( 'Download %d URL', 'woocommerce' ) => 'downloads:url', @@ -721,6 +723,7 @@ class WC_Product_CSV_Importer_Controller { 'downloads' => array( 'name' => __( 'Downloads', 'woocommerce' ), 'options' => array( + 'downloads:id' . $index => __( 'Download ID', 'woocommerce' ), 'downloads:name' . $index => __( 'Download name', 'woocommerce' ), 'downloads:url' . $index => __( 'Download URL', 'woocommerce' ), 'download_limit' => __( 'Download limit', 'woocommerce' ), diff --git a/includes/admin/importers/mappings/default.php b/includes/admin/importers/mappings/default.php index 4de9337d89c..0d9599da04c 100644 --- a/includes/admin/importers/mappings/default.php +++ b/includes/admin/importers/mappings/default.php @@ -102,6 +102,7 @@ function wc_importer_default_special_english_mappings( $mappings ) { 'Attribute %d visible' => 'attributes:visible', 'Attribute %d global' => 'attributes:taxonomy', 'Attribute %d default' => 'attributes:default', + 'Download %d ID' => 'downloads:id', 'Download %d name' => 'downloads:name', 'Download %d URL' => 'downloads:url', 'Meta: %s' => 'meta:', diff --git a/includes/admin/list-tables/class-wc-admin-list-table-orders.php b/includes/admin/list-tables/class-wc-admin-list-table-orders.php index 417f2819f1a..6c604088976 100644 --- a/includes/admin/list-tables/class-wc-admin-list-table-orders.php +++ b/includes/admin/list-tables/class-wc-admin-list-table-orders.php @@ -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_on-hold'] = __( 'Change status to on-hold', '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' ) ) ) { $actions['remove_personal_data'] = __( 'Remove personal data', 'woocommerce' ); diff --git a/includes/class-wc-install.php b/includes/class-wc-install.php index 9a78baacaa9..ea22c5231aa 100644 --- a/includes/class-wc-install.php +++ b/includes/class-wc-install.php @@ -310,6 +310,7 @@ class WC_Install { self::create_files(); self::maybe_create_pages(); self::maybe_set_activation_transients(); + self::set_paypal_standard_load_eligibility(); self::update_wc_version(); self::maybe_update_db_version(); @@ -1635,6 +1636,18 @@ CREATE TABLE {$wpdb->prefix}wc_reserved_stock ( 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(); diff --git a/includes/class-wc-payment-gateways.php b/includes/class-wc-payment-gateways.php index c6114ef68c7..04520322ee0 100644 --- a/includes/class-wc-payment-gateways.php +++ b/includes/class-wc-payment-gateways.php @@ -78,9 +78,12 @@ class WC_Payment_Gateways { 'WC_Gateway_BACS', 'WC_Gateway_Cheque', 'WC_Gateway_COD', - 'WC_Gateway_Paypal', ); + if ( $this->should_load_paypal_standard() ) { + $load_gateways[] = 'WC_Gateway_Paypal'; + } + // Filter. $load_gateways = apply_filters( 'woocommerce_payment_gateways', $load_gateways ); @@ -219,4 +222,15 @@ class WC_Payment_Gateways { 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(); + } } diff --git a/includes/export/class-wc-product-csv-exporter.php b/includes/export/class-wc-product-csv-exporter.php index a2380da9bee..0be4abb9c4f 100644 --- a/includes/export/class-wc-product-csv-exporter.php +++ b/includes/export/class-wc-product-csv-exporter.php @@ -601,10 +601,13 @@ class WC_Product_CSV_Exporter extends WC_CSV_Batch_Exporter { if ( $downloads ) { $i = 1; foreach ( $downloads as $download ) { + /* translators: %s: download number */ + $this->column_names[ 'downloads:id' . $i ] = sprintf( __( 'Download %d ID', 'woocommerce' ), $i ); /* translators: %s: download number */ $this->column_names[ 'downloads:name' . $i ] = sprintf( __( 'Download %d name', 'woocommerce' ), $i ); /* translators: %s: download number */ $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:url' . $i ] = $download->get_file(); $i++; diff --git a/includes/gateways/paypal/class-wc-gateway-paypal.php b/includes/gateways/paypal/class-wc-gateway-paypal.php index 68a8095ad22..e6390151214 100644 --- a/includes/gateways/paypal/class-wc-gateway-paypal.php +++ b/includes/gateways/paypal/class-wc-gateway-paypal.php @@ -473,4 +473,42 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway { 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 ); + } } diff --git a/includes/import/class-wc-product-csv-importer.php b/includes/import/class-wc-product-csv-importer.php index c9c11f44684..78d65f789bb 100644 --- a/includes/import/class-wc-product-csv-importer.php +++ b/includes/import/class-wc-product-csv-importer.php @@ -894,6 +894,12 @@ class WC_Product_CSV_Importer extends WC_Product_Importer { } 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' ) ) { if ( ! empty( $value ) ) { $downloads[ str_replace( 'downloads:name', '', $key ) ]['name'] = $value; @@ -935,8 +941,9 @@ class WC_Product_CSV_Importer extends WC_Product_Importer { } $data['downloads'][] = array( - 'name' => $file['name'] ? $file['name'] : wc_get_filename_from_url( $file['url'] ), - 'file' => $file['url'], + 'download_id' => isset( $file['id'] ) ? $file['id'] : null, + 'name' => $file['name'] ? $file['name'] : wc_get_filename_from_url( $file['url'] ), + 'file' => $file['url'], ); } } diff --git a/includes/interfaces/class-wc-abstract-order-data-store-interface.php b/includes/interfaces/class-wc-abstract-order-data-store-interface.php index c043c34e214..6e2ca1f224d 100644 --- a/includes/interfaces/class-wc-abstract-order-data-store-interface.php +++ b/includes/interfaces/class-wc-abstract-order-data-store-interface.php @@ -6,10 +6,6 @@ * @package WooCommerce\Interfaces */ -if ( ! defined( 'ABSPATH' ) ) { - exit; -} - /** * WC Order Data Store Interface * diff --git a/includes/interfaces/class-wc-coupon-data-store-interface.php b/includes/interfaces/class-wc-coupon-data-store-interface.php index 95256bcc00d..1cc0389ebce 100644 --- a/includes/interfaces/class-wc-coupon-data-store-interface.php +++ b/includes/interfaces/class-wc-coupon-data-store-interface.php @@ -6,10 +6,6 @@ * @package WooCommerce\Interfaces */ -if ( ! defined( 'ABSPATH' ) ) { - exit; -} - /** * WC Coupon Data Store Interface * diff --git a/includes/interfaces/class-wc-customer-data-store-interface.php b/includes/interfaces/class-wc-customer-data-store-interface.php index d2601898516..f3df3083fea 100644 --- a/includes/interfaces/class-wc-customer-data-store-interface.php +++ b/includes/interfaces/class-wc-customer-data-store-interface.php @@ -6,10 +6,6 @@ * @package WooCommerce\Interface */ -if ( ! defined( 'ABSPATH' ) ) { - exit; -} - /** * WC Customer Data Store Interface * diff --git a/includes/interfaces/class-wc-customer-download-data-store-interface.php b/includes/interfaces/class-wc-customer-download-data-store-interface.php index 4ef79c59395..81cde862794 100644 --- a/includes/interfaces/class-wc-customer-download-data-store-interface.php +++ b/includes/interfaces/class-wc-customer-download-data-store-interface.php @@ -6,10 +6,6 @@ * @package WooCommerce\Interface */ -if ( ! defined( 'ABSPATH' ) ) { - exit; -} - /** * WC Customer Download Data Store Interface. * diff --git a/includes/interfaces/class-wc-customer-download-log-data-store-interface.php b/includes/interfaces/class-wc-customer-download-log-data-store-interface.php index 32c5b168c4f..662f22ef069 100644 --- a/includes/interfaces/class-wc-customer-download-log-data-store-interface.php +++ b/includes/interfaces/class-wc-customer-download-log-data-store-interface.php @@ -6,10 +6,6 @@ * @package WooCommerce\Interface */ -if ( ! defined( 'ABSPATH' ) ) { - exit; -} - /** * WC Customer Download Log Data Store Interface. * diff --git a/includes/interfaces/class-wc-importer-interface.php b/includes/interfaces/class-wc-importer-interface.php index fa4317932b8..55f4cf64aca 100644 --- a/includes/interfaces/class-wc-importer-interface.php +++ b/includes/interfaces/class-wc-importer-interface.php @@ -6,10 +6,6 @@ * @version 3.1.0 */ -if ( ! defined( 'ABSPATH' ) ) { - exit; -} - /** * WC_Importer_Interface class. */ diff --git a/includes/interfaces/class-wc-log-handler-interface.php b/includes/interfaces/class-wc-log-handler-interface.php index d84e39720c8..f83828165e5 100644 --- a/includes/interfaces/class-wc-log-handler-interface.php +++ b/includes/interfaces/class-wc-log-handler-interface.php @@ -6,10 +6,6 @@ * @package WooCommerce\Interface */ -if ( ! defined( 'ABSPATH' ) ) { - exit; // Exit if accessed directly. -} - /** * WC Log Handler Interface * diff --git a/includes/interfaces/class-wc-logger-interface.php b/includes/interfaces/class-wc-logger-interface.php index 726b20cfe66..78b83df0ae6 100644 --- a/includes/interfaces/class-wc-logger-interface.php +++ b/includes/interfaces/class-wc-logger-interface.php @@ -6,10 +6,6 @@ * @package WooCommerce\Interface */ -if ( ! defined( 'ABSPATH' ) ) { - exit; // Exit if accessed directly. -} - /** * WC Logger Interface * diff --git a/includes/interfaces/class-wc-object-data-store-interface.php b/includes/interfaces/class-wc-object-data-store-interface.php index f6f276aaae6..397aeb965cd 100644 --- a/includes/interfaces/class-wc-object-data-store-interface.php +++ b/includes/interfaces/class-wc-object-data-store-interface.php @@ -6,10 +6,6 @@ * @package WooCommerce\Interface */ -if ( ! defined( 'ABSPATH' ) ) { - exit; -} - /** * WC Data Store Interface * diff --git a/includes/interfaces/class-wc-order-data-store-interface.php b/includes/interfaces/class-wc-order-data-store-interface.php index 6f00c8a3efe..18745176414 100644 --- a/includes/interfaces/class-wc-order-data-store-interface.php +++ b/includes/interfaces/class-wc-order-data-store-interface.php @@ -6,10 +6,6 @@ * @package WooCommerce\Interface */ -if ( ! defined( 'ABSPATH' ) ) { - exit; -} - /** * WC Order Data Store Interface * diff --git a/includes/interfaces/class-wc-order-item-data-store-interface.php b/includes/interfaces/class-wc-order-item-data-store-interface.php index 68ba29b4013..b23f42727bd 100644 --- a/includes/interfaces/class-wc-order-item-data-store-interface.php +++ b/includes/interfaces/class-wc-order-item-data-store-interface.php @@ -6,10 +6,6 @@ * @package WooCommerce\Interface */ -if ( ! defined( 'ABSPATH' ) ) { - exit; -} - /** * WC Order Item Data Store Interface * diff --git a/includes/interfaces/class-wc-order-item-product-data-store-interface.php b/includes/interfaces/class-wc-order-item-product-data-store-interface.php index f5cd402ea2f..654c408c364 100644 --- a/includes/interfaces/class-wc-order-item-product-data-store-interface.php +++ b/includes/interfaces/class-wc-order-item-product-data-store-interface.php @@ -6,10 +6,6 @@ * @package WooCommerce\Interface */ -if ( ! defined( 'ABSPATH' ) ) { - exit; -} - /** * WC Order Item Data Store Interface * diff --git a/includes/interfaces/class-wc-order-item-type-data-store-interface.php b/includes/interfaces/class-wc-order-item-type-data-store-interface.php index 006a4e6b0d4..23693faf29e 100644 --- a/includes/interfaces/class-wc-order-item-type-data-store-interface.php +++ b/includes/interfaces/class-wc-order-item-type-data-store-interface.php @@ -6,10 +6,6 @@ * @package WooCommerce\Interface */ -if ( ! defined( 'ABSPATH' ) ) { - exit; -} - /** * WC Order Item Data Store Interface * diff --git a/includes/interfaces/class-wc-order-refund-data-store-interface.php b/includes/interfaces/class-wc-order-refund-data-store-interface.php index b97864d06e3..1167e830943 100644 --- a/includes/interfaces/class-wc-order-refund-data-store-interface.php +++ b/includes/interfaces/class-wc-order-refund-data-store-interface.php @@ -6,10 +6,6 @@ * @package WooCommerce\Interface */ -if ( ! defined( 'ABSPATH' ) ) { - exit; -} - /** * WC Order Refund Data Store Interface * diff --git a/includes/interfaces/class-wc-payment-token-data-store-interface.php b/includes/interfaces/class-wc-payment-token-data-store-interface.php index fb2a581e741..9fb64a29806 100644 --- a/includes/interfaces/class-wc-payment-token-data-store-interface.php +++ b/includes/interfaces/class-wc-payment-token-data-store-interface.php @@ -6,10 +6,6 @@ * @package WooCommerce\Interface */ -if ( ! defined( 'ABSPATH' ) ) { - exit; -} - /** * WC Payment Token Data Store Interface * diff --git a/includes/interfaces/class-wc-product-data-store-interface.php b/includes/interfaces/class-wc-product-data-store-interface.php index 3e50cfedf14..4c1a68c94ec 100644 --- a/includes/interfaces/class-wc-product-data-store-interface.php +++ b/includes/interfaces/class-wc-product-data-store-interface.php @@ -6,10 +6,6 @@ * @package WooCommerce\Interface */ -if ( ! defined( 'ABSPATH' ) ) { - exit; -} - /** * WC Product Data Store Interface * diff --git a/includes/interfaces/class-wc-product-variable-data-store-interface.php b/includes/interfaces/class-wc-product-variable-data-store-interface.php index b22893dc3a6..03b72b48a3e 100644 --- a/includes/interfaces/class-wc-product-variable-data-store-interface.php +++ b/includes/interfaces/class-wc-product-variable-data-store-interface.php @@ -6,10 +6,6 @@ * @package WooCommerce\Interface */ -if ( ! defined( 'ABSPATH' ) ) { - exit; -} - /** * WC Product Variable Data Store Interface * diff --git a/includes/interfaces/class-wc-queue-interface.php b/includes/interfaces/class-wc-queue-interface.php index 5a960d383f7..3cfe06845ce 100644 --- a/includes/interfaces/class-wc-queue-interface.php +++ b/includes/interfaces/class-wc-queue-interface.php @@ -6,10 +6,6 @@ * @package WooCommerce\Interface */ -if ( ! defined( 'ABSPATH' ) ) { - exit; // Exit if accessed directly. -} - /** * WC Queue Interface * diff --git a/includes/interfaces/class-wc-shipping-zone-data-store-interface.php b/includes/interfaces/class-wc-shipping-zone-data-store-interface.php index 7009c5b7209..031e4048b3e 100644 --- a/includes/interfaces/class-wc-shipping-zone-data-store-interface.php +++ b/includes/interfaces/class-wc-shipping-zone-data-store-interface.php @@ -6,10 +6,6 @@ * @package WooCommerce\Interface */ -if ( ! defined( 'ABSPATH' ) ) { - exit; -} - /** * WC Shipping Zone Data Store Interface. * diff --git a/includes/interfaces/class-wc-webhooks-data-store-interface.php b/includes/interfaces/class-wc-webhooks-data-store-interface.php index f0e2e729843..0f59d011d20 100644 --- a/includes/interfaces/class-wc-webhooks-data-store-interface.php +++ b/includes/interfaces/class-wc-webhooks-data-store-interface.php @@ -6,10 +6,6 @@ * @package WooCommerce\Interface */ -if ( ! defined( 'ABSPATH' ) ) { - exit; -} - /** * WooCommerce Webhook data store interface. */ diff --git a/tests/e2e/core-tests/specs/shopper/front-end-checkout.test.js b/tests/e2e/core-tests/specs/shopper/front-end-checkout.test.js index 46bf8121eff..812d7385d25 100644 --- a/tests/e2e/core-tests/specs/shopper/front-end-checkout.test.js +++ b/tests/e2e/core-tests/specs/shopper/front-end-checkout.test.js @@ -69,14 +69,6 @@ const runCheckoutPageTest = () => { // Verify that settings have been saved 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(); }); @@ -93,7 +85,6 @@ const runCheckoutPageTest = () => { await shopper.goToCheckout(); 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: 'Cash on delivery'}); }); diff --git a/tests/e2e/core-tests/specs/shopper/front-end-single-product.test.js b/tests/e2e/core-tests/specs/shopper/front-end-single-product.test.js index 8d6fc05e9bd..d1473eb75a1 100644 --- a/tests/e2e/core-tests/specs/shopper/front-end-single-product.test.js +++ b/tests/e2e/core-tests/specs/shopper/front-end-single-product.test.js @@ -4,18 +4,37 @@ */ const { shopper, - merchant, createSimpleProduct, createVariableProduct, createGroupedProduct, uiUnblocked } = require( '@woocommerce/e2e-utils' ); -let simplePostIdValue; -let variablePostIdValue; -let groupedPostIdValue; const config = require( 'config' ); + +// Variables for simple product 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 = () => { describe('Single Product Page', () => { @@ -43,30 +62,34 @@ const runSingleProductPageTest = () => { }); }); - describe.skip('Variable Product Page', () => { + describe('Variable Product Page', () => { beforeAll(async () => { - await merchant.login(); - variablePostIdValue = await createVariableProduct(); - await merchant.logout(); + variableProductId = await createVariableProduct(); }); it('should be able to add variation products to the cart', async () => { // Add a product with one set of variations to cart - 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 shopper.goToProduct(variableProductId); + + for (const attr of defaultVariableProduct.attributes) { + const { name, options } = attr; + const selectElem = `#${name.toLowerCase()}`; + const value = options[0]; + + await expect(page).toSelect(selectElem, value); + } + await shopper.addToCart(); await expect(page).toMatchElement('.woocommerce-message', {text: 'has been added to your cart.'}); // Verify cart contents 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 () => { // Remove items from cart - await shopper.removeFromCart('Variable Product with Three Variations'); + await shopper.removeFromCart(defaultVariableProduct.name); await uiUnblocked(); await expect(page).toMatchElement('.cart-empty', {text: 'Your cart is currently empty.'}); }); @@ -74,9 +97,7 @@ const runSingleProductPageTest = () => { describe('Grouped Product Page', () => { beforeAll(async () => { - await merchant.login(); - groupedPostIdValue = await createGroupedProduct(); - await merchant.logout(); + groupedPostIdValue = await createGroupedProduct(groupedProduct); }); it('should be able to add grouped products to the cart', async () => { @@ -93,7 +114,7 @@ const runSingleProductPageTest = () => { await quantityFields[1].type('5'); await shopper.addToCart(); await expect(page).toMatchElement('.woocommerce-message', - {text: '“'+simpleProductName+' 1” and “'+simpleProductName+' 2” have been added to your cart.'}); + {text: '“'+simpleProductName+' 1” and “'+simpleProductName+' 2” have been added to your cart.'}); // Verify cart contents await shopper.goToCart(); diff --git a/tests/e2e/core-tests/specs/shopper/front-end-variable-product-updates.test.js b/tests/e2e/core-tests/specs/shopper/front-end-variable-product-updates.test.js index 2cce3fd22b1..8c0ac5a9c5f 100644 --- a/tests/e2e/core-tests/specs/shopper/front-end-variable-product-updates.test.js +++ b/tests/e2e/core-tests/specs/shopper/front-end-variable-product-updates.test.js @@ -4,73 +4,103 @@ */ const { shopper, - merchant, createVariableProduct, } = require( '@woocommerce/e2e-utils' ); +const config = require('config'); let variablePostIdValue; const cartDialogMessage = 'Please select some product options before adding this product to your cart.'; +const attributes = config.get( 'products.variable.attributes' ) const runVariableProductUpdateTest = () => { describe('Shopper > Update variable product',() => { beforeAll(async () => { - await merchant.login(); variablePostIdValue = await createVariableProduct(); - await merchant.logout(); }); it('shopper can change variable attributes to the same value', async () => { 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 () => { await shopper.goToProduct(variablePostIdValue); - await expect(page).toSelect('#attr-1', 'val1'); - await expect(page).toSelect('#attr-2', 'val2'); - await expect(page).toSelect('#attr-3', 'val1'); + await expect(page).toSelect( + `#${attributes[0].name.toLowerCase()}`, + 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-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--dimensions', { text: '10 × 20 × 15 cm' }); + }); it('shopper can change variable product attributes to variation with a different price', async () => { await shopper.goToProduct(variablePostIdValue); - await expect(page).toSelect('#attr-1', 'val1'); - await expect(page).toSelect('#attr-2', 'val1'); - await expect(page).toSelect('#attr-3', 'val2'); + await expect(page).toSelect( + `#${attributes[0].name.toLowerCase()}`, + 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' }); }); it('shopper can reset variations', async () => { await shopper.goToProduct(variablePostIdValue); - await expect(page).toSelect('#attr-1', 'val1'); - await expect(page).toSelect('#attr-2', 'val2'); - await expect(page).toSelect('#attr-3', 'val1'); + await expect(page).toSelect( + `#${attributes[0].name.toLowerCase()}`, + 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'); // Verify the reset by attempting to add the product to the cart const couponDialog = await expect(page).toDisplayDialog(async () => { - await expect(page).toClick('.single_add_to_cart_button'); - }); + await expect(page).toClick('.single_add_to_cart_button'); + }); expect(couponDialog.message()).toMatch(cartDialogMessage); - - // Accept the dialog - await couponDialog.accept(); }); }); - + }; module.exports = runVariableProductUpdateTest; diff --git a/tests/e2e/utils/CHANGELOG.md b/tests/e2e/utils/CHANGELOG.md index 8f5ba3ad79e..35a7d9abe01 100644 --- a/tests/e2e/utils/CHANGELOG.md +++ b/tests/e2e/utils/CHANGELOG.md @@ -1,5 +1,8 @@ # Unreleased +## Added + +- Factories for variable product, variation, and grouped product - Added new constant for WordPress update page `WP_ADMIN_WP_UPDATES` - Added new merchant flow for `openWordPressUpdatesPage()` - Added new merchant flows: diff --git a/tests/e2e/utils/src/components.js b/tests/e2e/utils/src/components.js index c5e3daf7f51..d77351d66c7 100644 --- a/tests/e2e/utils/src/components.js +++ b/tests/e2e/utils/src/components.js @@ -7,10 +7,8 @@ */ import { merchant, IS_RETEST_MODE } from './flows'; import { - clickTab, uiUnblocked, verifyCheckboxIsUnset, - selectOptionInSelect2, setCheckbox, unsetCheckbox, evalAndClick, @@ -24,6 +22,8 @@ const client = factories.api.withDefaultPermalinks; const config = require( 'config' ); const simpleProductName = config.get( 'products.simple.name' ); 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 @@ -135,6 +135,9 @@ const completeOnboardingWizard = async () => { // Business Details section + // Temporarily add delay to reduce test flakiness + await page.waitFor( 2000 ); + // Query for the s const selectControls = await page.$$( '.woocommerce-select-control' ); expect( selectControls ).toHaveLength( 2 ); @@ -220,172 +223,104 @@ const createSimpleProductWithCategory = async ( productName, productPrice, categ /** * 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 - page.removeAllListeners('dialog'); + // Create variation for all attributes + const createVariation = (aIdx) => { + const { name, options } = attributes[aIdx]; + const isLastAttribute = aIdx === attributes.length - 1; - // Go to "add product" page - await merchant.openNewProduct(); + // Add each attribute value to the buffer. + options.forEach((opt) => { + buffer.push({ + name: name, + option: opt + }); - // Make sure we're on the add product page - await expect( page.title() ).resolves.toMatch( 'Add new product' ); + if (isLastAttribute) { + // 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. + variations.push({ + attributes: [...buffer] + }); + } else { + // Otherwise, move to the next attribute first + // before proceeding to the next value in this attribute. + createVariation(aIdx + 1); + } - // Set product data - await expect( page ).toFill( '#title', 'Variable Product with Three Variations' ); - await expect( page ).toSelect( '#product-type', 'Variable product' ); + buffer.pop(); + }); + }; + createVariation(aIdx); - // Create attributes for variations - await clickTab( 'Attributes' ); - await expect( page ).toSelect( 'select[name="attribute_taxonomy"]', 'Custom product attribute' ); + // Set some properties of 1st variation + variations[0].regularPrice = '9.99'; + variations[0].virtual = true; - for ( let i = 0; i < 3; i++ ) { - await expect( page ).toClick( 'button.add_attribute', { text: 'Add' } ); - // Wait for attribute form to load - await uiUnblocked(); + // Set some properties of 2nd variation + variations[1].regularPrice = '11.99'; + variations[1].virtual = true; - 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 }]"]` ); + // Set some properties of 3rd variation + variations[2].regularPrice = '20'; + variations[2].weight = '200'; + 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 + }); } - await expect( page ).toClick( 'button', { text: 'Save attributes' } ); - - // Wait for attribute form to save (triggers 2 UI blocks) - await uiUnblocked(); - await page.waitFor( 1000 ); - await uiUnblocked(); - - // Create variations from attributes - await clickTab( 'Variations' ); - await page.waitForSelector( 'select.variation_actions:not([disabled])' ); - 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 () => { - // Using this technique since toClick() isn't working. - // See: https://github.com/GoogleChrome/puppeteer/issues/1805#issuecomment-464802876 - page.$eval( 'a.do_variation_action', elem => elem.click() ); - - } ); - - expect( firstDialog.message() ).toMatch( 'Are you sure you want to link all variations?' ); - - 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; + return id; }; /** * Create grouped product. + * + * @param groupedProduct Defaults to the grouped product object in `default.json` + * @returns ID of the grouped product */ -const createGroupedProduct = async () => { - // Create two products to be linked in a grouped product after - await factories.products.simple.create( { - name: simpleProductName + ' 1', - regularPrice: simpleProductPrice - } ); - await factories.products.simple.create( { - name: simpleProductName + ' 2', - regularPrice: simpleProductPrice - } ); +const createGroupedProduct = async (groupedProduct = defaultGroupedProduct) => { + const { name, groupedProducts } = groupedProduct; + const simpleProductIds = []; + let groupedProductRequest; - // Go to "add product" page - await merchant.openNewProduct(); + // Using the api, create simple products to be grouped + 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 - await expect( page.title() ).resolves.toMatch( 'Add new product' ); + // Using the api, create the grouped product + groupedProductRequest = { + name: name, + groupedProducts: simpleProductIds + }; + const { id } = await factories.products.grouped.create( + groupedProductRequest + ); - // Set product data and save the product - 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; -} + return id; +}; /** * Create a basic order with the provided order status. diff --git a/tests/e2e/utils/src/factories.js b/tests/e2e/utils/src/factories.js index 46f3b91f948..4ebc5e38041 100644 --- a/tests/e2e/utils/src/factories.js +++ b/tests/e2e/utils/src/factories.js @@ -1,6 +1,9 @@ import { HTTPClientFactory } from '@woocommerce/api'; const config = require( 'config' ); 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 adminUsername = config.get( 'users.admin.username' ); @@ -20,6 +23,9 @@ const factories = { }, products: { simple: simpleProductFactory( withDefaultPermalinks ), + variable: variableProductFactory( withDefaultPermalinks ), + variation: variationFactory( withDefaultPermalinks ), + grouped: groupedProductFactory( withDefaultPermalinks ) }, }; diff --git a/tests/e2e/utils/src/factories/grouped-product.js b/tests/e2e/utils/src/factories/grouped-product.js new file mode 100644 index 00000000000..cb2315f586c --- /dev/null +++ b/tests/e2e/utils/src/factories/grouped-product.js @@ -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 + }; + }); +} diff --git a/tests/e2e/utils/src/factories/variable-product.js b/tests/e2e/utils/src/factories/variable-product.js new file mode 100644 index 00000000000..5080dbc0422 --- /dev/null +++ b/tests/e2e/utils/src/factories/variable-product.js @@ -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 + }; + }); +} diff --git a/tests/e2e/utils/src/factories/variation.js b/tests/e2e/utils/src/factories/variation.js new file mode 100644 index 00000000000..4aed65ad353 --- /dev/null +++ b/tests/e2e/utils/src/factories/variation.js @@ -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; + }); +} diff --git a/tests/legacy/bootstrap.php b/tests/legacy/bootstrap.php index fd8bfb96dce..3b648590f14 100644 --- a/tests/legacy/bootstrap.php +++ b/tests/legacy/bootstrap.php @@ -58,6 +58,9 @@ class WC_Unit_Tests_Bootstrap { // load test function so tests_add_filter() is available. 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. tests_add_filter( 'muplugins_loaded', array( $this, 'load_wc' ) ); diff --git a/tests/legacy/unit-tests/importer/product.php b/tests/legacy/unit-tests/importer/product.php index e55fdd79351..a77cc9fb2e2 100644 --- a/tests/legacy/unit-tests/importer/product.php +++ b/tests/legacy/unit-tests/importer/product.php @@ -84,6 +84,7 @@ class WC_Tests_Product_CSV_Importer extends WC_Unit_Test_Case { 'Attribute 2 value(s)' => 'attributes:value2', 'Attribute 1 default' => 'attributes:default1', 'Attribute 2 default' => 'attributes:default2', + 'Download 1 ID' => 'downloads:id1', 'Download 1 name' => 'downloads:name1', 'Download 1 URL' => 'downloads:url1', ); @@ -238,6 +239,7 @@ class WC_Tests_Product_CSV_Importer extends WC_Unit_Test_Case { '', '', '', + '', ), array( 'simple, downloadable, virtual', @@ -283,6 +285,7 @@ class WC_Tests_Product_CSV_Importer extends WC_Unit_Test_Case { '180-Gram', '', '', + '4ff604c2-97bd-4869-938b-7798ba6648ab', 'Album flac', 'http://woo.dev/albums/album.flac', ), @@ -393,8 +396,9 @@ class WC_Tests_Product_CSV_Importer extends WC_Unit_Test_Case { ), 'downloads' => array( array( - 'name' => 'Album flac', - 'file' => 'http://woo.dev/albums/album.flac', + 'name' => 'Album flac', + 'file' => 'http://woo.dev/albums/album.flac', + 'download_id' => '4ff604c2-97bd-4869-938b-7798ba6648ab', ), ), 'menu_order' => 1, diff --git a/tests/legacy/unit-tests/importer/sample.csv b/tests/legacy/unit-tests/importer/sample.csv index 00b323feaf3..607fb8c9247 100644 --- a/tests/legacy/unit-tests/importer/sample.csv +++ b/tests/legacy/unit-tests/importer/sample.csv @@ -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 -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 -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,, -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,,,, -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,,,,,,,, +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, 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,,,,,,,,, +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,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,,,,,,,,,