Merge branch 'trunk' into update/ai-product-endpoint-last-product-param

This commit is contained in:
Patricia Hillebrandt 2023-12-04 04:04:02 -03:00
commit 1f1ddd17d4
45 changed files with 615 additions and 310 deletions

View File

@ -0,0 +1,4 @@
Significance: patch
Type: tweak
[Product Block Editor]: minor Summary block enhancements

View File

@ -26,7 +26,7 @@ import { SummaryAttributes } from './types';
import { ALIGNMENT_CONTROLS } from './constants';
import { ProductEditorBlockEditProps } from '../../../types';
export function Edit( {
export function SummaryBlockEdit( {
attributes,
setAttributes,
context,
@ -36,7 +36,7 @@ export function Edit( {
style: { direction },
} );
const contentId = useInstanceId(
Edit,
SummaryBlockEdit,
'wp-block-woocommerce-product-summary-field__content'
);
const [ summary, setSummary ] = useEntityProp< string >(
@ -88,23 +88,30 @@ export function Edit( {
<BaseControl
id={ contentId.toString() }
label={ createInterpolateElement(
label || __( 'Summary', 'woocommerce' ),
{
optional: (
<span className="woocommerce-product-form__optional-input">
{ __( '(OPTIONAL)', 'woocommerce' ) }
</span>
),
}
) }
label={
typeof label === 'undefined'
? createInterpolateElement(
__( 'Summary', 'woocommerce' ),
{
optional: (
<span className="woocommerce-product-form__optional-input">
{ __(
'(OPTIONAL)',
'woocommerce'
) }
</span>
),
}
)
: label
}
help={
typeof helpText === 'string'
? helpText
: __(
typeof helpText === 'undefined'
? __(
"Summarize this product in 1-2 short sentences. We'll show it at the top of the page.",
'woocommerce'
)
: helpText
}
>
<div { ...blockProps }>

View File

@ -2,7 +2,7 @@
* Internal dependencies
*/
import blockConfiguration from './block.json';
import { Edit } from './edit';
import { SummaryBlockEdit } from './edit';
import { registerProductEditorBlockType } from '../../../utils';
const { name, ...metadata } = blockConfiguration;
@ -11,7 +11,7 @@ export { name, metadata };
export const settings = {
example: {},
edit: Edit,
edit: SummaryBlockEdit,
};
export function init() {

View File

@ -0,0 +1,4 @@
Significance: patch
Type: dev
Comment: Create closeWelcomeModal, goToPageEditor and goToPostEditor utils in PlayWright e2e tests

View File

@ -0,0 +1,4 @@
Significance: patch
Type: fix
Comment: Fixes a bug found in unreleased feature. No changelog needed.

View File

@ -0,0 +1,4 @@
Significance: patch
Type: fix
Comment: Fixes unreleased feature, no changelog required.

View File

@ -0,0 +1,4 @@
Significance: patch
Type: performance
Prevent second query used to determine real post count from running if paging isn't being used.

View File

@ -0,0 +1,4 @@
Significance: minor
Type: add
Add functionality and UI for downloading log files directly from WC Admin

View File

@ -0,0 +1,4 @@
Significance: patch
Type: fix
Fixed a vertical alignment issue in the variations selector

View File

@ -0,0 +1,4 @@
Significance: minor
Type: add
Display variation upsells from private variable products to users with required permissions.

View File

@ -0,0 +1,4 @@
Significance: minor
Type: update
Update product template for external products, hiding shipping and variation tabs.

View File

@ -4115,7 +4115,7 @@ table.wc_shipping {
.wc-backbone-modal-main article {
padding: 0 32px 32px 32px;
}
.wc-backbone-modal-main header{
@ -4124,7 +4124,7 @@ table.wc_shipping {
.wc-backbone-modal-main footer {
padding: 20px 32px 12px 32px;
}
.wc-backbone-modal-main .wc-backbone-modal-header h1 {
@ -4168,7 +4168,7 @@ table.wc_shipping {
display: none;
}
}
}
.wc-shipping-method-add-class-costs {
@ -4186,7 +4186,7 @@ table.wc_shipping {
height: 1px;
overflow: hidden;
position: absolute;
white-space: nowrap;
white-space: nowrap;
width: 1px;
&:checked + label {
@ -4237,7 +4237,7 @@ table.wc_shipping {
font-size: 24px;
}
}
.wc-shipping-zone-method-fields {
& > label {
@ -4258,7 +4258,7 @@ table.wc_shipping {
margin-bottom: 24px;
position: relative;
input,
input,
select {
margin: 6px 0;
padding: 12px;
@ -4362,7 +4362,7 @@ table {
.edit {
margin: 5px 0;
}
.edit > input,
.edit > select {
width: 100%;
@ -4390,7 +4390,7 @@ table {
}
}
.wc-shipping-class-hide-sibling-view + .view {
.wc-shipping-class-hide-sibling-view + .view {
display: none;
}
@ -4402,7 +4402,7 @@ table {
display: inline-block;
margin: 0 12px;
}
}
}
.wc-shipping-zone-heading-help-text {
max-width: 800px;

View File

@ -182,9 +182,18 @@
}
}
// Ensure variation label is vertically centered.
div.product form.cart table.variations td select {
min-width: 70%; // Fix for Safari.
}
div.product form.cart table.variations td,
div.product form.cart table.variations th {
// Ensure variation label is vertically centered.
line-height: 3.5rem;
vertical-align: middle;
}
.single_variation_wrap .woocommerce-variation {
margin-bottom: var(--wp--style--block-gap);
}
}

View File

@ -569,6 +569,9 @@
status : 'new'
}
});
} else {
shippingMethodView.model.trigger( 'change:methods' );
shippingMethodView.model.trigger( 'saved:methods' );
}
$( document.body ).trigger( 'init_tooltips' );
@ -629,17 +632,6 @@
}
} else if ( target === 'wc-modal-shipping-method-settings' ) {
event.data.view.possiblyHideFreeShippingRequirements( data );
const requiredFields = [ 'woocommerce_free_shipping_title', 'woocommerce_flat_rate_title', 'woocommerce_local_pickup_title' ];
const requiredFieldPresent = requiredFields.find( ( field ) => {
return data.hasOwnProperty( field ) && field;
} );
if ( requiredFieldPresent ) {
const shouldDisable = data[ requiredFieldPresent ].length === 0;
const saveButton = document.getElementById( 'btn-ok' );
saveButton.disabled = shouldDisable;
saveButton.classList.toggle( 'disabled', shouldDisable );
}
}
},
onCloseConfigureShippingMethod: function( event, target, post_data, addButtonCalled ) {

View File

@ -1603,7 +1603,7 @@ class WC_Product extends WC_Abstract_Legacy_Product {
if ( $this->get_parent_id() ) {
$parent_product = wc_get_product( $this->get_parent_id() );
if ( $parent_product && 'publish' !== $parent_product->get_status() ) {
if ( $parent_product && 'publish' !== $parent_product->get_status() && ! current_user_can( 'edit_post', $parent_product->get_id() ) ) {
$visible = false;
}
}

View File

@ -149,7 +149,7 @@ if ( ! defined( 'ABSPATH' ) ) {
</article>
<footer>
<div class="inner">
<button id="btn-ok" data-status='{{ data.status }}' disabled='{{ data.status === "new" ? "disabled" : "" }}' class="button button-primary button-large {{ data.status === 'new' ? 'disabled' : '' }}">
<button id="btn-ok" data-status='{{ data.status }}' class="button button-primary button-large">
<div class="wc-backbone-modal-action-{{ data.status === 'new' ? 'active' : 'inactive' }}"><?php esc_html_e( 'Create', 'woocommerce' ); ?></div>
<div class="wc-backbone-modal-action-{{ data.status === 'existing' ? 'active' : 'inactive' }}"><?php esc_html_e( 'Save', 'woocommerce' ); ?></div>
</button>

View File

@ -354,7 +354,7 @@ abstract class WC_REST_CRUD_Controller extends WC_REST_Posts_Controller {
$result = $query->query( $query_args );
$total_posts = $query->found_posts;
if ( $total_posts < 1 ) {
if ( $total_posts < 1 && isset( $query_args['paged'] ) && absint( $query_args['paged'] ) > 1 ) {
// Out-of-bounds, run the query again without LIMIT for total count.
unset( $query_args['paged'] );
$count_query = new WP_Query();

View File

@ -367,7 +367,7 @@ abstract class WC_REST_Posts_Controller extends WC_REST_Controller {
$page = (int) $query_args['paged'];
$total_posts = $posts_query->found_posts;
if ( $total_posts < 1 ) {
if ( $total_posts < 1 && $page > 1 ) {
// Out-of-bounds, run the query again without LIMIT for total count.
unset( $query_args['paged'] );
$count_query = new WP_Query();

View File

@ -15,7 +15,7 @@ $settings = array(
'title' => __( 'Name', 'woocommerce' ),
'type' => 'text',
'description' => __( 'Your customers will see the name of this shipping method during checkout.', 'woocommerce' ),
'default' => '',
'default' => __( 'Flat rate', 'woocommerce' ),
'placeholder' => __( 'e.g. Standard national', 'woocommerce' ),
'desc_tip' => true,
),

View File

@ -112,7 +112,7 @@ class WC_Shipping_Free_Shipping extends WC_Shipping_Method {
'title' => __( 'Name', 'woocommerce' ),
'type' => 'text',
'description' => __( 'Your customers will see the name of this shipping method during checkout.', 'woocommerce' ),
'default' => '',
'default' => $this->method_title,
'placeholder' => __( 'e.g. Free shipping', 'woocommerce' ),
'desc_tip' => true,
),

View File

@ -108,7 +108,7 @@ class WC_Shipping_Local_Pickup extends WC_Shipping_Method {
'title' => __( 'Name', 'woocommerce' ),
'type' => 'text',
'description' => __( 'Your customers will see the name of this shipping method during checkout.', 'woocommerce' ),
'default' => '',
'default' => __( 'Local pickup', 'woocommerce' ),
'placeholder' => __( 'e.g. Local pickup', 'woocommerce' ),
'desc_tip' => true,
),

View File

@ -93,7 +93,7 @@ class Controller extends GenericController implements ExportableInterface {
$result = $query->query( $query_args );
$total_posts = $query->found_posts;
if ( $total_posts < 1 ) {
if ( $total_posts < 1 && isset( $query_args['paged'] ) && absint( $query_args['paged'] ) > 1 ) {
// Out-of-bounds, run the query again without LIMIT for total count.
unset( $query_args['paged'] );
$count_query = new \WP_Query();

View File

@ -179,6 +179,15 @@ class File {
return fclose( $this->stream );
}
/**
* Get the full absolute path of the file.
*
* @return string
*/
public function get_path(): string {
return $this->path;
}
/**
* Get the name of the file, with extension, but without full path.
*

View File

@ -4,6 +4,7 @@ declare( strict_types = 1 );
namespace Automattic\WooCommerce\Internal\Admin\Logging\FileV2;
use Automattic\Jetpack\Constants;
use PclZip;
use WC_Cache_Helper;
use WP_Error;
@ -345,6 +346,68 @@ class FileController {
return $deleted;
}
/**
* Stream a single file to the browser without zipping it first.
*
* @param string $file_id A file ID (file basename without the hash).
*
* @return WP_Error|void Only returns something if there is an error.
*/
public function export_single_file( $file_id ) {
$file = $this->get_file_by_id( $file_id );
if ( is_wp_error( $file ) ) {
return $file;
}
$file_name = $file->get_file_id() . '.log';
$exporter = new FileExporter( $file->get_path(), $file_name );
return $exporter->emit_file();
}
/**
* Create a zip archive of log files and stream it to the browser.
*
* @param array $file_ids An array of file IDs (file basename without the hash).
*
* @return WP_Error|void Only returns something if there is an error.
*/
public function export_multiple_files( array $file_ids ) {
$files = $this->get_files_by_id( $file_ids );
if ( count( $files ) < 1 ) {
return new WP_Error(
'wc_logs_invalid_file',
__( 'Could not access the specified files.', 'woocommerce' )
);
}
$temp_dir = get_temp_dir();
if ( ! is_dir( $temp_dir ) || ! wp_is_writable( $temp_dir ) ) {
return new WP_Error(
'wc_logs_invalid_directory',
__( 'Could not write to the temp directory. Try downloading files one at a time instead.', 'woocommerce' )
);
}
require_once ABSPATH . 'wp-admin/includes/class-pclzip.php';
$path = trailingslashit( $temp_dir ) . 'woocommerce_logs_' . gmdate( 'Y-m-d_H-i-s' ) . '.zip';
$file_paths = array_map(
fn( $file ) => $file->get_path(),
$files
);
$archive = new PclZip( $path );
$archive->create( $file_paths, PCLZIP_OPT_REMOVE_ALL_PATH );
$exporter = new FileExporter( $path );
return $exporter->emit_file();
}
/**
* Search within a set of log files for a particular string.
*

View File

@ -0,0 +1,136 @@
<?php
declare( strict_types=1 );
namespace Automattic\WooCommerce\Internal\Admin\Logging\FileV2;
use WP_Error;
use WP_Filesystem_Direct;
/**
* FileExport class.
*/
class FileExporter {
/**
* The number of bytes per read while streaming the file.
*
* @const int
*/
private const CHUNK_SIZE = 4 * KB_IN_BYTES;
/**
* The absolute path of the file.
*
* @var string
*/
private $path;
/**
* A name of the file to send to the browser rather than the filename part of the path.
*
* @var string
*/
private $alternate_filename;
/**
* Class FileExporter.
*
* @param string $path The absolute path of the file.
* @param string $alternate_filename Optional. The name of the file to send to the browser rather than the filename
* part of the path.
*/
public function __construct( string $path, string $alternate_filename = '' ) {
global $wp_filesystem;
if ( ! $wp_filesystem instanceof WP_Filesystem_Direct ) {
WP_Filesystem();
}
$this->path = $path;
$this->alternate_filename = $alternate_filename;
}
/**
* Configure PHP and stream the file to the browser.
*
* @return WP_Error|void Only returns something if there is an error.
*/
public function emit_file() {
global $wp_filesystem;
if ( ! $wp_filesystem->is_file( $this->path ) || ! $wp_filesystem->is_readable( $this->path ) ) {
return new WP_Error(
'wc_logs_invalid_file',
__( 'Could not access file.', 'woocommerce' )
);
}
// These configuration tweaks are copied from WC_CSV_Exporter::send_headers().
// phpcs:disable WordPress.PHP.NoSilencedErrors.Discouraged
if ( function_exists( 'gc_enable' ) ) {
gc_enable(); // phpcs:ignore PHPCompatibility.FunctionUse.NewFunctions.gc_enableFound
}
if ( function_exists( 'apache_setenv' ) ) {
@apache_setenv( 'no-gzip', '1' ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.runtime_configuration_apache_setenv
}
@ini_set( 'zlib.output_compression', 'Off' ); // phpcs:ignore WordPress.PHP.IniSet.Risky
@ini_set( 'output_buffering', 'Off' ); // phpcs:ignore WordPress.PHP.IniSet.Risky
@ini_set( 'output_handler', '' ); // phpcs:ignore WordPress.PHP.IniSet.Risky
ignore_user_abort( true );
wc_set_time_limit();
wc_nocache_headers();
// phpcs:enable WordPress.PHP.NoSilencedErrors.Discouraged
$this->send_headers();
$this->send_contents();
die;
}
/**
* Send HTTP headers at the beginning of a file.
*
* Modeled on WC_CSV_Exporter::send_headers().
*
* @return void
*/
private function send_headers(): void {
header( 'Content-Type: text/plain; charset=utf-8' );
header( 'Content-Disposition: attachment; filename=' . $this->get_filename() );
header( 'Pragma: no-cache' );
header( 'Expires: 0' );
}
/**
* Send the contents of the file.
*
* @return void
*/
private function send_contents(): void {
// phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_read_fopen -- No suitable alternative.
$stream = fopen( $this->path, 'rb' );
while ( is_resource( $stream ) && ! feof( $stream ) ) {
// phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_read_fread -- No suitable alternative.
$chunk = fread( $stream, self::CHUNK_SIZE );
if ( is_string( $chunk ) ) {
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Outputting to file.
echo $chunk;
}
}
// phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_read_fclose -- No suitable alternative.
fclose( $stream );
}
/**
* Get the name of the file that will be sent to the browser.
*
* @return string
*/
private function get_filename(): string {
if ( $this->alternate_filename ) {
return $this->alternate_filename;
}
return basename( $this->path );
}
}

View File

@ -67,6 +67,7 @@ class FileListTable extends WP_List_Table {
*/
protected function get_bulk_actions(): array {
return array(
'export' => esc_html__( 'Download', 'woocommerce' ),
'delete' => esc_html__( 'Delete permanently', 'woocommerce' ),
);
}

View File

@ -196,22 +196,28 @@ class PageController {
$rotations = $this->file_controller->get_file_rotations( $file->get_file_id() );
$rotation_url_base = add_query_arg( 'view', 'single_file', $this->get_logs_tab_url() );
$delete_url = add_query_arg(
$download_url = add_query_arg(
array(
'action' => 'export',
'file_id' => array( $file->get_file_id() ),
),
wp_nonce_url( $this->get_logs_tab_url(), 'bulk-log-files' )
);
$delete_url = add_query_arg(
array(
'action' => 'delete',
'file_id' => array( $file->get_file_id() ),
),
wp_nonce_url( $this->get_logs_tab_url(), 'bulk-log-files' )
);
$stream = $file->get_stream();
$line_number = 1;
$delete_confirmation_js = sprintf(
"return window.confirm( '%s' )",
esc_js( __( 'Delete this log file permanently?', 'woocommerce' ) )
);
$stream = $file->get_stream();
$line_number = 1;
?>
<header id="logs-header" class="wc-logs-header">
<h2>
@ -255,6 +261,14 @@ class PageController {
</nav>
<?php endif; ?>
<div class="wc-logs-single-file-actions">
<?php
// Download button.
printf(
'<a href="%1$s" class="button button-secondary">%2$s</a>',
esc_url( $download_url ),
esc_html__( 'Download', 'woocommerce' )
);
?>
<?php
// Delete button.
printf(
@ -464,6 +478,17 @@ class PageController {
}
switch ( $action ) {
case 'export':
if ( 1 === count( $file_ids ) ) {
$export_error = $this->file_controller->export_single_file( reset( $file_ids ) );
} else {
$export_error = $this->file_controller->export_multiple_files( $file_ids );
}
if ( is_wp_error( $export_error ) ) {
wp_die( wp_kses_post( $export_error ) );
}
break;
case 'delete':
$deleted = $this->file_controller->delete_files( $file_ids );
$sendback = add_query_arg( 'deleted', $deleted, $sendback );

View File

@ -103,6 +103,18 @@ class SimpleProductTemplate extends AbstractProductFormTemplate implements Produ
),
)
);
$shipping_hide_conditions = array();
if ( Features::is_enabled( 'product-grouped' ) ) {
$shipping_hide_conditions[] = array(
'expression' => 'editedProduct.type === "grouped"',
);
}
if ( Features::is_enabled( 'product-external-affiliate' ) ) {
$shipping_hide_conditions[] = array(
'expression' => 'editedProduct.type === "external"',
);
}
$this->add_group(
array(
'id' => $this::GROUP_IDS['SHIPPING'],
@ -110,21 +122,22 @@ class SimpleProductTemplate extends AbstractProductFormTemplate implements Produ
'attributes' => array(
'title' => __( 'Shipping', 'woocommerce' ),
),
'hideConditions' => Features::is_enabled( 'product-grouped' ) ? array(
array(
'expression' => 'editedProduct.type === "grouped"',
),
) : null,
'hideConditions' => $shipping_hide_conditions,
)
);
if ( Features::is_enabled( 'product-variation-management' ) ) {
$this->add_group(
array(
'id' => $this::GROUP_IDS['VARIATIONS'],
'order' => 50,
'attributes' => array(
'id' => $this::GROUP_IDS['VARIATIONS'],
'order' => 50,
'attributes' => array(
'title' => __( 'Variations', 'woocommerce' ),
),
'hideConditions' => Features::is_enabled( 'product-external-affiliate' ) ? array(
array(
'expression' => 'editedProduct.type === "external"',
),
) : null,
)
);
}

View File

@ -1,36 +1,11 @@
const { test, expect } = require( '@playwright/test' );
const wcApi = require( '@woocommerce/woocommerce-rest-api' ).default;
const { goToPostEditor } = require( '../../utils/editor' );
// need to figure out whether tests are being run on a mac
const macOS = process.platform === 'darwin';
const cmdKeyCombo = macOS ? 'Meta+k' : 'Control+k';
const goToPostEditor = async ( { page } ) => {
await page.goto( 'wp-admin/post-new.php' );
const welcomeModalVisible =
await test.step( 'Check if the Welcome modal appeared', async () => {
return await page
.getByRole( 'heading', {
name: 'Welcome to the block editor',
} )
.isVisible();
} );
if ( welcomeModalVisible ) {
await test.step( 'Welcome modal appeared. Close it.', async () => {
await page
.getByRole( 'document' )
.getByRole( 'button', { name: 'Close' } )
.click();
} );
} else {
await test.step( 'Welcome modal did not appear.', async () => {
// do nothing.
} );
}
};
const clickOnCommandPaletteOption = async ( { page, optionName } ) => {
// Press `Ctrl` + `K` to open the command palette.
await page.keyboard.press( cmdKeyCombo );

View File

@ -1,5 +1,6 @@
const { test, expect, request } = require( '@playwright/test' );
const { admin } = require( '../../test-data/data' );
const { goToPageEditor } = require( '../../utils/editor' );
const pageTitle = `Page-${ new Date().getTime().toString() }`;
@ -32,17 +33,7 @@ test.describe( 'Can create a new page', () => {
} );
test( 'can create new page', async ( { page } ) => {
await page.goto( 'wp-admin/post-new.php?post_type=page' );
const welcomeModalVisible = await page
.getByRole( 'heading', {
name: 'Welcome to the block editor',
} )
.isVisible();
if ( welcomeModalVisible ) {
await page.getByRole( 'button', { name: 'Close' } ).click();
}
await goToPageEditor( { page } );
await page
.getByRole( 'textbox', { name: 'Add Title' } )

View File

@ -1,5 +1,6 @@
const { test, expect, request } = require( '@playwright/test' );
const { admin } = require( '../../test-data/data' );
const { goToPostEditor } = require( '../../utils/editor' );
const postTitle = `Post-${ new Date().getTime().toString() }`;
@ -33,31 +34,7 @@ test.describe( 'Can create a new post', () => {
} );
test( 'can create new post', async ( { page } ) => {
await page.goto( 'wp-admin/post-new.php' );
const welcomeModalVisible = await test.step(
'Check if the Welcome modal appeared',
async () => {
return await page
.getByRole( 'heading', {
name: 'Welcome to the block editor',
} )
.isVisible();
}
);
if ( welcomeModalVisible ) {
await test.step( 'Welcome modal appeared. Close it.', async () => {
await page
.getByRole( 'document' )
.getByRole( 'button', { name: 'Close' } )
.click();
} );
} else {
await test.step( 'Welcome modal did not appear.', async () => {
// do nothing.
} );
}
await goToPostEditor( { page } );
await page
.getByRole( 'textbox', { name: 'Add Title' } )

View File

@ -67,28 +67,36 @@ test.describe( 'WooCommerce Shipping Settings - Add new shipping zone', () => {
.getByPlaceholder( 'Zone name' )
.fill( shippingZoneNameLocalPickup );
const input = await page.getByPlaceholder( 'Start typing to filter zones' );
const input = await page.getByPlaceholder(
'Start typing to filter zones'
);
input.click();
input.type( 'British Columbia, Canada' );
await page
.getByText( 'British Columbia, Canada' ).last()
.click();
// Close dropdown
await page.keyboard.press('Escape');
await page.getByRole( 'link', { name: 'Limit to specific ZIP/postcodes' } ).click();
await page.getByPlaceholder( 'List 1 postcode per line' ).fill( maynePostal );
await page.getByRole( 'button', { name: 'Add shipping method' } ).click();
await page.getByText( 'Local pickup', { exact: true } ).click();
await page.getByRole('button', { name: 'Continue' } ).last().click();
await page.waitForLoadState( 'networkidle' );
await page.getByText( 'British Columbia, Canada' ).last().click();
// Close dropdown
await page.keyboard.press( 'Escape' );
await page
.getByPlaceholder( 'e.g. Local pickup' )
.fill( 'Local pickup' );
.getByRole( 'link', {
name: 'Limit to specific ZIP/postcodes',
} )
.click();
await page
.getByPlaceholder( 'List 1 postcode per line' )
.fill( maynePostal );
await page
.getByRole( 'button', { name: 'Add shipping method' } )
.click();
await page.getByText( 'Local pickup', { exact: true } ).click();
await page
.getByRole( 'button', { name: 'Continue' } )
.last()
.click();
await page.waitForLoadState( 'networkidle' );
await page.locator( '#btn-ok' ).click();
await page.waitForLoadState( 'networkidle' );
@ -130,28 +138,32 @@ test.describe( 'WooCommerce Shipping Settings - Add new shipping zone', () => {
'wp-admin/admin.php?page=wc-settings&tab=shipping&zone_id=new',
{ waitUntil: 'networkidle' }
);
await page.getByPlaceholder( 'Zone name' ).fill( shippingZoneNameFreeShip );
await page
.getByPlaceholder( 'Zone name' )
.fill( shippingZoneNameFreeShip );
const input = await page.getByPlaceholder( 'Start typing to filter zones' );
const input = await page.getByPlaceholder(
'Start typing to filter zones'
);
input.click();
input.type( 'British Columbia, Canada' );
await page
.getByText( 'British Columbia, Canada' ).last()
.click();
await page.getByText( 'British Columbia, Canada' ).last().click();
// Close dropdown
await page.keyboard.press('Escape');
await page.getByRole( 'button', { name: 'Add shipping method' } ).click();
await page.keyboard.press( 'Escape' );
await page
.getByRole( 'button', { name: 'Add shipping method' } )
.click();
await page.getByText( 'Free shipping', { exact: true } ).click();
await page.getByRole('button', { name: 'Continue' } ).last().click();
await page.waitForLoadState( 'networkidle' );
await page
.getByPlaceholder( 'e.g. Free shipping' )
.fill( 'Free shipping' );
.getByRole( 'button', { name: 'Continue' } )
.last()
.click();
await page.waitForLoadState( 'networkidle' );
await page.locator( '#btn-ok' ).click();
await page.waitForLoadState( 'networkidle' );
@ -190,27 +202,31 @@ test.describe( 'WooCommerce Shipping Settings - Add new shipping zone', () => {
'wp-admin/admin.php?page=wc-settings&tab=shipping&zone_id=new',
{ waitUntil: 'networkidle' }
);
await page.getByPlaceholder( 'Zone name' ).fill( shippingZoneNameFlatRate );
await page
.getByPlaceholder( 'Zone name' )
.fill( shippingZoneNameFlatRate );
const input = await page.getByPlaceholder( 'Start typing to filter zones' );
const input = await page.getByPlaceholder(
'Start typing to filter zones'
);
input.click();
input.type( 'Canada' );
await page
.getByText('Canada').last()
.click();
// Close dropdown
await page.keyboard.press('Escape');
await page.getByText( 'Canada' ).last().click();
await page.getByRole( 'button', { name: 'Add shipping method' } ).click();
// Close dropdown
await page.keyboard.press( 'Escape' );
await page
.getByRole( 'button', { name: 'Add shipping method' } )
.click();
await page.getByText( 'Flat rate', { exact: true } ).click();
await page.getByRole('button', { name: 'Continue' } ).last().click();
await page
.getByRole( 'button', { name: 'Continue' } )
.last()
.click();
await page.waitForLoadState( 'networkidle' );
await page
.getByPlaceholder( 'e.g. Standard national' )
.fill( 'Flat rate' );
await page.locator( '#btn-ok' ).click();
await page.waitForLoadState( 'networkidle' );
@ -220,7 +236,11 @@ test.describe( 'WooCommerce Shipping Settings - Add new shipping zone', () => {
.filter( { hasText: 'Flat rate' } )
).toBeVisible();
await page.locator( 'td:has-text("Flat rate") ~ td.wc-shipping-zone-actions a.wc-shipping-zone-action-edit' ).click();
await page
.locator(
'td:has-text("Flat rate") ~ td.wc-shipping-zone-actions a.wc-shipping-zone-action-edit'
)
.click();
await page.getByLabel( 'Cost', { exact: true } ).fill( '10' );
await page.getByRole( 'button', { name: 'Save' } ).last().click();
await page.waitForLoadState( 'networkidle' );
@ -257,16 +277,16 @@ test.describe( 'WooCommerce Shipping Settings - Add new shipping zone', () => {
);
await page.locator( '#zone_name' ).fill( shippingZoneNameUSRegion );
const input = await page.getByPlaceholder( 'Start typing to filter zones' );
const input = await page.getByPlaceholder(
'Start typing to filter zones'
);
input.click();
input.type( 'United States' );
await page
.getByText( 'United States' ).last()
.click();
// Close dropdown
await page.keyboard.press('Escape');
await page.getByText( 'United States' ).last().click();
// Close dropdown
await page.keyboard.press( 'Escape' );
await page.locator( '#submit' ).click();
await page.waitForFunction( () => {
@ -286,7 +306,11 @@ test.describe( 'WooCommerce Shipping Settings - Add new shipping zone', () => {
//delete created shipping zone region after confirmation it exists
await page.goto( 'wp-admin/admin.php?page=wc-settings&tab=shipping' );
await page.locator( 'td:has-text("USA Zone") ~ td.wc-shipping-zone-actions a.wc-shipping-zone-action-edit' ).click();
await page
.locator(
'td:has-text("USA Zone") ~ td.wc-shipping-zone-actions a.wc-shipping-zone-action-edit'
)
.click();
//delete
await page.getByRole( 'button', { name: 'Remove' } ).click();
@ -319,37 +343,41 @@ test.describe( 'WooCommerce Shipping Settings - Add new shipping zone', () => {
);
await page.locator( '#zone_name' ).fill( shippingZoneNameFlatRate );
const input = await page.getByPlaceholder( 'Start typing to filter zones' );
const input = await page.getByPlaceholder(
'Start typing to filter zones'
);
input.click();
input.type( 'Canada' );
await page
.getByText( 'Canada' ).last()
.click();
// Close dropdown
await page.keyboard.press('Escape');
await page.getByText( 'Canada' ).last().click();
// Close dropdown
await page.keyboard.press( 'Escape' );
await page.locator( 'text=Add shipping method' ).click();
await page.getByText( 'Flat rate', { exact: true } ).click();
await page.getByRole('button', { name: 'Continue' } ).last().click();
await page
.getByRole( 'button', { name: 'Continue' } )
.last()
.click();
await page.waitForLoadState( 'networkidle' );
await page
.getByPlaceholder( 'e.g. Standard national' )
.fill( 'Flat rate' );
await page.locator( '#btn-ok' ).click();
await page.waitForLoadState( 'networkidle' );
await expect(
page
.locator( '.wc-shipping-zone-method-title' )
.filter( { hasText: 'Flat rate' } )
).toBeVisible();
await page.locator( 'td:has-text("Flat rate") ~ td.wc-shipping-zone-actions a.wc-shipping-zone-action-edit' ).click();
await page
.locator(
'td:has-text("Flat rate") ~ td.wc-shipping-zone-actions a.wc-shipping-zone-action-edit'
)
.click();
await page.locator( '#woocommerce_flat_rate_cost' ).fill( '10' );
await page.locator( '#btn-ok' ).click();
await page.waitForLoadState( 'networkidle' );
@ -435,20 +463,13 @@ test.describe( 'Verifies shipping options from customer perspective', () => {
method_id: 'flat_rate',
settings: {
cost: '10.00',
title: 'Flat rate',
},
} );
await api.post( `shipping/zones/${ shippingFreeId }/methods`, {
method_id: 'free_shipping',
settings: {
title: 'Free shipping',
}
} );
await api.post( `shipping/zones/${ shippingLocalId }/methods`, {
method_id: 'local_pickup',
settings: {
title: 'Local pickup',
}
} );
} );

View File

@ -1,5 +1,6 @@
const { test, expect } = require( '@playwright/test' );
const { admin } = require( '../../test-data/data' );
const { closeWelcomeModal } = require( '../../utils/editor' );
const wcApi = require( '@woocommerce/woocommerce-rest-api' ).default;
const firstProductName = 'First Product';
@ -145,14 +146,7 @@ test.describe( 'Cart Block Calculate Shipping', () => {
await page.locator( 'input[name="pwd"]' ).fill( admin.password );
await page.locator( 'text=Log In' ).click();
// close welcome popup if prompted
try {
await page
.getByLabel( 'Close', { exact: true } )
.click( { timeout: 5000 } );
} catch ( error ) {
console.log( "Welcome modal wasn't present, skipping action." );
}
await closeWelcomeModal( { page } );
await page
.getByRole( 'textbox', { name: 'Add title' } )

View File

@ -1,6 +1,7 @@
const { test, expect } = require( '@playwright/test' );
const wcApi = require( '@woocommerce/woocommerce-rest-api' ).default;
const { admin } = require( '../../test-data/data' );
const { closeWelcomeModal } = require( '../../utils/editor' );
const productName = 'First Product Cart Block Taxing';
const productPrice = '100.00';
@ -106,14 +107,7 @@ test.describe( 'Shopper Cart Block Tax Display', () => {
await page.locator( 'input[name="pwd"]' ).fill( admin.password );
await page.locator( 'text=Log In' ).click();
// Close welcome popup if prompted
try {
await page
.getByLabel( 'Close', { exact: true } )
.click( { timeout: 5000 } );
} catch ( error ) {
console.log( "Welcome modal wasn't present, skipping action." );
}
await closeWelcomeModal( { page } );
await page
.getByRole( 'textbox', { name: 'Add title' } )

View File

@ -1,5 +1,6 @@
const { test, expect } = require( '@playwright/test' );
const { admin } = require( '../../test-data/data' );
const { closeWelcomeModal } = require( '../../utils/editor' );
const wcApi = require( '@woocommerce/woocommerce-rest-api' ).default;
const simpleProductName = 'A Simple Product';
@ -91,14 +92,7 @@ test.describe( 'Cart Block Applying Coupons', () => {
await page.locator( 'input[name="pwd"]' ).fill( admin.password );
await page.locator( 'text=Log In' ).click();
// Close welcome popup if prompted
try {
await page
.getByLabel( 'Close', { exact: true } )
.click( { timeout: 5000 } );
} catch ( error ) {
console.log( "Welcome modal wasn't present, skipping action." );
}
await closeWelcomeModal( { page } );
await page
.getByRole( 'textbox', { name: 'Add title' } )

View File

@ -1,5 +1,6 @@
const { test, expect } = require( '@playwright/test' );
const { admin } = require( '../../test-data/data' );
const { closeWelcomeModal } = require( '../../utils/editor' );
const wcApi = require( '@woocommerce/woocommerce-rest-api' ).default;
const simpleProductName = 'Single Simple Product';
@ -91,14 +92,7 @@ test.describe( 'Cart Block page', () => {
await page.locator( 'input[name="pwd"]' ).fill( admin.password );
await page.locator( 'text=Log In' ).click();
// Close welcome popup if prompted
try {
await page
.getByLabel( 'Close', { exact: true } )
.click( { timeout: 5000 } );
} catch ( error ) {
console.log( "Welcome modal wasn't present, skipping action." );
}
await closeWelcomeModal( { page } );
await page
.getByRole( 'textbox', { name: 'Add title' } )

View File

@ -78,22 +78,15 @@ test.describe( 'Cart Calculate Shipping', () => {
// set shipping zone methods
await api.post( `shipping/zones/${ shippingZoneDEId }/methods`, {
method_id: 'free_shipping',
settings: {
title: 'Free shipping',
},
} );
await api.post( `shipping/zones/${ shippingZoneFRId }/methods`, {
method_id: 'flat_rate',
settings: {
title: 'Flat rate',
cost: '5.00',
},
} );
await api.post( `shipping/zones/${ shippingZoneFRId }/methods`, {
method_id: 'local_pickup',
settings: {
title: 'Local pickup',
},
} );
// confirm that we allow shipping to any country
await api.put( 'settings/general/woocommerce_allowed_countries', {
@ -174,9 +167,9 @@ test.describe( 'Cart Calculate Shipping', () => {
await page.locator( 'text=Local pickup' ).click();
// Verify updated shipping costs
await expect( page.locator( '.order-total .amount' ).first() ).toContainText(
`$${ firstProductPrice }`
);
await expect(
page.locator( '.order-total .amount' ).first()
).toContainText( `$${ firstProductPrice }` );
} );
test( 'should show correct total cart price after updating quantity', async ( {

View File

@ -66,9 +66,6 @@ test.describe( 'Shopper Checkout Create Account', () => {
] );
await api.post( `shipping/zones/${ shippingZoneId }/methods`, {
method_id: 'free_shipping',
settings: {
title: 'Free shipping',
}
} );
await api.put( 'payment_gateways/cod', {
enabled: true,

View File

@ -62,9 +62,6 @@ test.describe( 'Shopper Checkout Login Account', () => {
] );
await api.post( `shipping/zones/${ shippingZoneId }/methods`, {
method_id: 'free_shipping',
settings: {
title: 'Free shipping',
}
} );
// create customer and save its id
await api
@ -175,6 +172,8 @@ test.describe( 'Shopper Checkout Login Account', () => {
// check my account page
await page.goto( '/my-account/' );
await expect( page.url() ).toContain( 'my-account/' );
await expect( page.getByRole( 'heading', { name: 'My account' } ) ).toBeVisible();
await expect(
page.getByRole( 'heading', { name: 'My account' } )
).toBeVisible();
} );
} );

View File

@ -67,9 +67,6 @@ test.describe( 'Checkout page', () => {
] );
await api.post( `shipping/zones/${ shippingZoneId }/methods`, {
method_id: 'free_shipping',
settings: {
title: 'Free shipping',
}
} );
} );
@ -117,7 +114,6 @@ test.describe( 'Checkout page', () => {
await api.put( 'payment_gateways/cod', {
enabled: true,
} );
} );
test( 'should display cart items in order review', async ( { page } ) => {
@ -132,7 +128,11 @@ test.describe( 'Checkout page', () => {
await expect( page.locator( 'strong.product-quantity' ) ).toContainText(
'1'
);
let totalPrice = await page.getByRole( 'row', { name: 'Total' } ).last().locator( 'td' ).textContent();
let totalPrice = await page
.getByRole( 'row', { name: 'Total' } )
.last()
.locator( 'td' )
.textContent();
console.log( `Total Price: ${ totalPrice }` );
totalPrice = Number( totalPrice.replace( /[^\d.-]/g, '' ) );
console.log( `Number: ${ totalPrice }` );
@ -154,7 +154,11 @@ test.describe( 'Checkout page', () => {
await expect( page.locator( 'strong.product-quantity' ) ).toContainText(
'2'
);
let totalPrice = await page.getByRole( 'row', { name: 'Total' } ).last().locator( 'td' ).textContent();
let totalPrice = await page
.getByRole( 'row', { name: 'Total' } )
.last()
.locator( 'td' )
.textContent();
console.log( `Total Price: ${ totalPrice }` );
totalPrice = Number( totalPrice.replace( /[^\d.-]/g, '' ) );
console.log( `Number: ${ totalPrice }` );
@ -178,7 +182,11 @@ test.describe( 'Checkout page', () => {
await expect( page.locator( 'strong.product-quantity' ) ).toContainText(
'3'
);
let totalPrice = await page.getByRole( 'row', { name: 'Total' } ).last().locator( 'td' ).textContent();
let totalPrice = await page
.getByRole( 'row', { name: 'Total' } )
.last()
.locator( 'td' )
.textContent();
console.log( `Total Price: ${ totalPrice }` );
totalPrice = Number( totalPrice.replace( /[^\d.-]/g, '' ) );
console.log( `Number: ${ totalPrice }` );
@ -200,24 +208,44 @@ test.describe( 'Checkout page', () => {
await expect( page.locator( '#billing_email' ) ).toBeEditable();
} );
test( 'warn when customer is missing required details', async ( { page } ) => {
await page.goto( `/shop/?add-to-cart=${ productId }`, { waitUntil: 'networkidle' } );
test( 'warn when customer is missing required details', async ( {
page,
} ) => {
await page.goto( `/shop/?add-to-cart=${ productId }`, {
waitUntil: 'networkidle',
} );
await page.goto( '/checkout/' );
// first try submitting the form with no fields complete
await page.getByRole('button', { name: 'Place order' }).click();
await expect( page.locator('form[name="checkout"]').getByRole('alert') ).toBeVisible();
await expect( page.getByText( 'Billing First name is a required field.' ) ).toBeVisible();
await expect( page.getByText( 'Billing Last name is a required field.' ) ).toBeVisible();
await expect( page.getByText( 'Billing Street address is a required field.' ) ).toBeVisible();
await expect( page.getByText( 'Billing Town / City is a required field.' ) ).toBeVisible();
await expect( page.getByText( 'Billing ZIP Code is a required field.' ) ).toBeVisible();
await expect( page.getByText( 'Billing Phone is a required field.' ) ).toBeVisible();
await expect( page.getByText( 'Billing Email address is a required field.' ) ).toBeVisible();
await page.getByRole( 'button', { name: 'Place order' } ).click();
await expect(
page.locator( 'form[name="checkout"]' ).getByRole( 'alert' )
).toBeVisible();
await expect(
page.getByText( 'Billing First name is a required field.' )
).toBeVisible();
await expect(
page.getByText( 'Billing Last name is a required field.' )
).toBeVisible();
await expect(
page.getByText( 'Billing Street address is a required field.' )
).toBeVisible();
await expect(
page.getByText( 'Billing Town / City is a required field.' )
).toBeVisible();
await expect(
page.getByText( 'Billing ZIP Code is a required field.' )
).toBeVisible();
await expect(
page.getByText( 'Billing Phone is a required field.' )
).toBeVisible();
await expect(
page.getByText( 'Billing Email address is a required field.' )
).toBeVisible();
// toggle ship to different address, fill out billing info and confirm error shown
await page.getByText('Ship to a different address?').click();
await page.getByText( 'Ship to a different address?' ).click();
await page.locator( '#billing_first_name' ).fill( 'Homer' );
await page.locator( '#billing_last_name' ).fill( 'Simpson' );
await page
@ -229,14 +257,24 @@ test.describe( 'Checkout page', () => {
await page.locator( '#billing_postcode' ).fill( '97403' );
await page.locator( '#billing_phone' ).fill( '555 555-5555' );
await page.locator( '#billing_email' ).fill( customer.email );
await page.getByRole('button', { name: 'Place order' }).click();
await page.getByRole( 'button', { name: 'Place order' } ).click();
await expect( page.locator( 'ul.woocommerce-error' ) ).toBeVisible();
await expect( page.getByText( 'Shipping First name is a required field.' ) ).toBeVisible();
await expect( page.getByText( 'Shipping Last name is a required field.' ) ).toBeVisible();
await expect( page.getByText( 'Shipping Street address is a required field.' ) ).toBeVisible();
await expect( page.getByText( 'Shipping Town / City is a required field.' ) ).toBeVisible();
await expect( page.getByText( 'Shipping ZIP Code is a required field.' ) ).toBeVisible();
await expect(
page.getByText( 'Shipping First name is a required field.' )
).toBeVisible();
await expect(
page.getByText( 'Shipping Last name is a required field.' )
).toBeVisible();
await expect(
page.getByText( 'Shipping Street address is a required field.' )
).toBeVisible();
await expect(
page.getByText( 'Shipping Town / City is a required field.' )
).toBeVisible();
await expect(
page.getByText( 'Shipping ZIP Code is a required field.' )
).toBeVisible();
} );
test( 'allows customer to fill shipping details', async ( { page } ) => {
@ -249,7 +287,11 @@ test.describe( 'Checkout page', () => {
await expect( page.locator( 'strong.product-quantity' ) ).toContainText(
'2'
);
let totalPrice = await page.getByRole( 'row', { name: 'Total' } ).last().locator( 'td' ).textContent();
let totalPrice = await page
.getByRole( 'row', { name: 'Total' } )
.last()
.locator( 'td' )
.textContent();
console.log( `Total Price: ${ totalPrice }` );
totalPrice = Number( totalPrice.replace( /[^\d.-]/g, '' ) );
console.log( `Number: ${ totalPrice }` );
@ -281,7 +323,11 @@ test.describe( 'Checkout page', () => {
await expect( page.locator( 'strong.product-quantity' ) ).toContainText(
'2'
);
let totalPrice = await page.getByRole( 'row', { name: 'Total' } ).last().locator( 'td' ).textContent();
let totalPrice = await page
.getByRole( 'row', { name: 'Total' } )
.last()
.locator( 'td' )
.textContent();
console.log( `Total Price: ${ totalPrice }` );
totalPrice = Number( totalPrice.replace( /[^\d.-]/g, '' ) );
console.log( `Number: ${ totalPrice }` );
@ -315,7 +361,6 @@ test.describe( 'Checkout page', () => {
.textContent();
guestOrderId = await orderReceivedText.split( /(\s+)/ )[ 6 ].toString();
// Let's simulate a new browser context (by dropping all cookies), and reload the page. This approximates a
// scenario where the server can no longer identify the shopper. However, so long as we are within the 10 minute
// grace period following initial order placement, the 'order received' page should still be rendered.
@ -327,19 +372,23 @@ test.describe( 'Checkout page', () => {
// Let's simulate a scenario where the 10 minute grace period has expired. This time, we expect the shopper to
// be presented with a request to verify their email address.
await setFilterValue( page, 'woocommerce_order_email_verification_grace_period', 0 );
await page.reload();
await expect( page.locator( 'form.woocommerce-verify-email p:nth-child(3)' ) ).toContainText(
/verify the email address associated with the order/
await setFilterValue(
page,
'woocommerce_order_email_verification_grace_period',
0
);
await page.reload();
await expect(
page.locator( 'form.woocommerce-verify-email p:nth-child(3)' )
).toContainText( /verify the email address associated with the order/ );
// Supplying an email address other than the actual order billing email address will take them back to the same
// page with an error message.
await page.fill( '#email', 'incorrect@email.address' );
await page.locator( 'form.woocommerce-verify-email button' ).click();
await expect( page.locator( 'form.woocommerce-verify-email p:nth-child(4)' ) ).toContainText(
/verify the email address associated with the order/
);
await expect(
page.locator( 'form.woocommerce-verify-email p:nth-child(4)' )
).toContainText( /verify the email address associated with the order/ );
await expect( page.locator( 'ul.woocommerce-error li' ) ).toContainText(
/We were unable to verify the email address you provided/
);
@ -362,7 +411,9 @@ test.describe( 'Checkout page', () => {
);
await expect(
page.getByRole( 'heading', { name: `Order #${ guestOrderId } details` } )
page.getByRole( 'heading', {
name: `Order #${ guestOrderId } details`,
} )
).toBeVisible();
await expect( page.locator( '.wc-order-item-name' ) ).toContainText(
simpleProductName
@ -381,8 +432,12 @@ test.describe( 'Checkout page', () => {
test( 'allows existing customer to place order', async ( { page } ) => {
await page.goto( 'my-account/' );
await page.locator( 'input[name="username"]' ).fill( customer.username );
await page.locator( 'input[name="password"]' ).fill( customer.password );
await page
.locator( 'input[name="username"]' )
.fill( customer.username );
await page
.locator( 'input[name="password"]' )
.fill( customer.password );
await page.locator( 'text=Log In' ).click();
await page.waitForLoadState( 'networkidle' );
for ( let i = 1; i < 3; i++ ) {
@ -394,7 +449,11 @@ test.describe( 'Checkout page', () => {
await expect( page.locator( 'strong.product-quantity' ) ).toContainText(
'2'
);
let totalPrice = await page.getByRole( 'row', { name: 'Total' } ).last().locator( 'td' ).textContent();
let totalPrice = await page
.getByRole( 'row', { name: 'Total' } )
.last()
.locator( 'td' )
.textContent();
console.log( `Total Price: ${ totalPrice }` );
totalPrice = Number( totalPrice.replace( /[^\d.-]/g, '' ) );
console.log( `Number: ${ totalPrice }` );

View File

@ -1,5 +1,6 @@
const { test, expect, request } = require( '@playwright/test' );
const { admin } = require( '../../test-data/data' );
const { closeWelcomeModal } = require( '../../utils/editor' );
const wcApi = require( '@woocommerce/woocommerce-rest-api' ).default;
const pageTitle = 'Mini Cart';
@ -143,14 +144,7 @@ test.describe( 'Mini Cart block page', () => {
await page.locator( 'input[name="pwd"]' ).fill( admin.password );
await page.locator( 'text=Log In' ).click();
// Close welcome popup if prompted
try {
await page
.getByLabel( 'Close', { exact: true } )
.click( { timeout: 5000 } );
} catch ( error ) {
console.log( "Welcome modal wasn't present, skipping action." );
}
await closeWelcomeModal( { page } );
await page
.getByRole( 'textbox', { name: 'Add title' } )

View File

@ -1,6 +1,7 @@
const { test, expect, request } = require( '@playwright/test' );
const { admin } = require( '../../test-data/data' );
const pageTitle = 'Product Showcase';
const { goToPageEditor } = require( '../../utils/editor' );
const wcApi = require( '@woocommerce/woocommerce-rest-api' ).default;
const singleProductPrice1 = '5.00';
@ -265,17 +266,7 @@ test.describe( 'Browse product tags and attributes from the product page', () =>
test( 'can see products showcase', async ( { page } ) => {
// create as a merchant a new page with Products block
await page.goto( 'wp-admin/post-new.php?post_type=page' );
const welcomeModalVisible = await page
.getByRole( 'heading', {
name: 'Welcome to the block editor',
} )
.isVisible();
if ( welcomeModalVisible ) {
await page.getByRole( 'button', { name: 'Close' } ).click();
}
await goToPageEditor( { page } );
await page
.getByRole( 'textbox', { name: 'Add Title' } )

View File

@ -0,0 +1,43 @@
const { test } = require( '@playwright/test' );
const closeWelcomeModal = async ( { page } ) => {
const welcomeModalVisible =
await test.step( 'Check if the Welcome modal appeared', async () => {
return await page
.getByRole( 'heading', {
name: 'Welcome to the block editor',
} )
.isVisible();
} );
if ( welcomeModalVisible ) {
await test.step( 'Welcome modal appeared. Close it.', async () => {
await page
.getByRole( 'document' )
.getByRole( 'button', { name: 'Close' } )
.click();
} );
} else {
await test.step( 'Welcome modal did not appear.', async () => {
// do nothing.
} );
}
};
const goToPageEditor = async ( { page } ) => {
await page.goto( 'wp-admin/post-new.php?post_type=page' );
await closeWelcomeModal( { page } );
};
const goToPostEditor = async ( { page } ) => {
await page.goto( 'wp-admin/post-new.php' );
await closeWelcomeModal( { page } );
};
module.exports = {
closeWelcomeModal,
goToPageEditor,
goToPostEditor,
};

View File

@ -680,7 +680,7 @@ class WC_Tests_API_Shipping_Zones_V2 extends WC_REST_Unit_Test_Case {
$data = $response->get_data();
$this->assertArrayHasKey( 'title', $data['settings'] );
$this->assertEquals( '', $data['settings']['title']['value'] );
$this->assertEquals( 'Flat rate', $data['settings']['title']['value'] );
$this->assertArrayHasKey( 'tax_status', $data['settings'] );
$this->assertEquals( 'taxable', $data['settings']['tax_status']['value'] );
$this->assertArrayHasKey( 'cost', $data['settings'] );
@ -691,8 +691,7 @@ class WC_Tests_API_Shipping_Zones_V2 extends WC_REST_Unit_Test_Case {
$request->set_body_params(
array(
'settings' => array(
'cost' => 5,
'title' => 'Flat rate',
'cost' => 5,
),
)
);

View File

@ -703,7 +703,7 @@ class WC_Tests_API_Shipping_Zones extends WC_REST_Unit_Test_Case {
$data = $response->get_data();
$this->assertArrayHasKey( 'title', $data['settings'] );
$this->assertEquals( '', $data['settings']['title']['value'] );
$this->assertEquals( 'Flat rate', $data['settings']['title']['value'] );
$this->assertArrayHasKey( 'tax_status', $data['settings'] );
$this->assertEquals( 'taxable', $data['settings']['tax_status']['value'] );
$this->assertArrayHasKey( 'cost', $data['settings'] );
@ -714,8 +714,7 @@ class WC_Tests_API_Shipping_Zones extends WC_REST_Unit_Test_Case {
$request->set_body_params(
array(
'settings' => array(
'cost' => 5,
'title' => 'Flat rate',
'cost' => 5,
),
)
);