Product Gallery Block: Add Product Gallery template to allow users to edit full mode view (https://github.com/woocommerce/woocommerce-blocks/pull/10823)
* Product Gallery: add support for On Sale Badge Block * add align support * Add E2E tests * set margin via Block Styles * disable experimental flag * add next previous block * restore support file * fix TS error * fix layout * change product * change product * Product Gallert Block: Add zoom on hover * set to true by default * remove block is already registered error * remove unecessary await * Improve zoom logic Co-authored-by: Alexandre Lara <allexandrelara@gmail.com> * Product Gallery Full view mode: Add the logic to render the dedicated template * use template-part instead template * add E2E tests * update selectors * add feature flag product gallery template part * fix E2E tests * remove not necessary file --------- Co-authored-by: Alexandre Lara <allexandrelara@gmail.com>
This commit is contained in:
parent
0abe53d079
commit
11062e8600
|
@ -49,11 +49,15 @@
|
|||
},
|
||||
"fullScreenOnClick": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
"default": true
|
||||
},
|
||||
"nextPreviousButtonsPosition":{
|
||||
"type": "string",
|
||||
"default": "insideTheImage"
|
||||
},
|
||||
"mode": {
|
||||
"type": "string",
|
||||
"default": "standard"
|
||||
}
|
||||
},
|
||||
"viewScript": "wc-product-gallery-frontend"
|
||||
|
|
|
@ -9,6 +9,7 @@ import {
|
|||
} from '@wordpress/block-editor';
|
||||
import { BlockEditProps, InnerBlockTemplate } from '@wordpress/blocks';
|
||||
import { useEffect } from '@wordpress/element';
|
||||
import { useSelect } from '@wordpress/data';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
|
@ -86,6 +87,21 @@ const TEMPLATE: InnerBlockTemplate[] = [
|
|||
],
|
||||
];
|
||||
|
||||
const setMode = (
|
||||
currentTemplateId: string,
|
||||
templateType: string,
|
||||
setAttributes: ( attrs: Partial< ProductGalleryAttributes > ) => void
|
||||
) => {
|
||||
if (
|
||||
templateType === 'wp_template_part' &&
|
||||
currentTemplateId.includes( 'product-gallery' )
|
||||
) {
|
||||
setAttributes( {
|
||||
mode: 'full',
|
||||
} );
|
||||
}
|
||||
};
|
||||
|
||||
export const Edit = ( {
|
||||
clientId,
|
||||
attributes,
|
||||
|
@ -93,6 +109,18 @@ export const Edit = ( {
|
|||
}: BlockEditProps< ProductGalleryAttributes > ) => {
|
||||
const blockProps = useBlockProps();
|
||||
|
||||
const { currentTemplateId, templateType } = useSelect(
|
||||
( select ) => ( {
|
||||
currentTemplateId: select( 'core/edit-site' ).getEditedPostId(),
|
||||
templateType: select( 'core/edit-site' ).getEditedPostType(),
|
||||
} ),
|
||||
[]
|
||||
);
|
||||
|
||||
useEffect( () => {
|
||||
setMode( currentTemplateId, templateType, setAttributes );
|
||||
}, [ currentTemplateId, setAttributes, templateType ] );
|
||||
|
||||
useEffect( () => {
|
||||
setAttributes( {
|
||||
...attributes,
|
||||
|
|
|
@ -11,18 +11,22 @@ interface Context {
|
|||
woocommerce: {
|
||||
selectedImage: string;
|
||||
imageId: string;
|
||||
isDialogOpen: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
interface Selectors {
|
||||
woocommerce: {
|
||||
isSelected: ( store: unknown ) => boolean;
|
||||
isDialogOpen: ( store: unknown ) => boolean;
|
||||
};
|
||||
}
|
||||
|
||||
interface Actions {
|
||||
woocommerce: {
|
||||
handleClick: ( context: Context ) => void;
|
||||
thumbnails: {
|
||||
handleClick: ( context: Context ) => void;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -44,12 +48,18 @@ interactivityApiStore( {
|
|||
context?.woocommerce.imageId
|
||||
);
|
||||
},
|
||||
isDialogOpen: ( { context }: Store ) => {
|
||||
return context?.woocommerce.isDialogOpen;
|
||||
},
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
woocommerce: {
|
||||
handleClick: ( { context }: Store ) => {
|
||||
context.woocommerce.selectedImage = context.woocommerce.imageId;
|
||||
thumbnails: {
|
||||
handleClick: ( { context }: Store ) => {
|
||||
context.woocommerce.selectedImage =
|
||||
context.woocommerce.imageId;
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -11,6 +11,7 @@ import { Edit } from './edit';
|
|||
import { Save } from './save';
|
||||
import metadata from './block.json';
|
||||
import icon from './icon';
|
||||
import './style.scss';
|
||||
import './inner-blocks/product-gallery-large-image-next-previous';
|
||||
import './inner-blocks/product-gallery-pager';
|
||||
import './inner-blocks/product-gallery-thumbnails';
|
||||
|
|
|
@ -11,6 +11,7 @@ type Context = {
|
|||
transform: string;
|
||||
transition: string;
|
||||
};
|
||||
isDialogOpen: boolean;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -64,6 +65,9 @@ interactivityStore(
|
|||
context.woocommerce.styles.transform = `scale(1.0)`;
|
||||
context.woocommerce.styles[ 'transform-origin' ] = '';
|
||||
},
|
||||
handleClick: ( { context }: { context: Context } ) => {
|
||||
context.woocommerce.isDialogOpen = true;
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
.wp-block-woocommerce-product-gallery {
|
||||
dialog {
|
||||
position: fixed;
|
||||
width: 90vw;
|
||||
height: 90vh;
|
||||
top: 0;
|
||||
margin: $gap-largest;
|
||||
z-index: 9999;
|
||||
}
|
||||
}
|
|
@ -9,6 +9,7 @@ export interface ProductGalleryBlockAttributes {
|
|||
cropImages?: boolean;
|
||||
hoverZoom?: boolean;
|
||||
fullScreenOnClick?: boolean;
|
||||
mode: 'standard' | 'full';
|
||||
}
|
||||
|
||||
export interface ProductGalleryThumbnailsBlockAttributes {
|
||||
|
|
|
@ -34,7 +34,7 @@ The majority of our feature flagging is blocks, this is a list of them:
|
|||
|
||||
### Experimental flag
|
||||
|
||||
- Product Gallery ([PHP flag](https://github.com/woocommerce/woocommerce-blocks/blob/e3fe996251b270d45ecc73207ea4ad587c2dbc78/src/BlockTypesController.php#L232) | [webpack flag](https://github.com/woocommerce/woocommerce-blocks/blob/e3fe996251b270d45ecc73207ea4ad587c2dbc78/bin/webpack-entries.js#L50-L52C3)).
|
||||
- Product Gallery ([PHP flag](https://github.com/woocommerce/woocommerce-blocks/blob/e3fe996251b270d45ecc73207ea4ad587c2dbc78/src/BlockTypesController.php#L232) | [webpack flag](https://github.com/woocommerce/woocommerce-blocks/blob/e3fe996251b270d45ecc73207ea4ad587c2dbc78/bin/webpack-entries.js#L50-L52C3) | [BlockTemplatesController](https://github.com/woocommerce/woocommerce-blocks/blob/211960f753d093f2f819273e130b34f893a784cd/src/BlockTemplatesController.php/#L467-L469)).
|
||||
- Product Gallery Thumbnails ([PHP flag](https://github.com/woocommerce/woocommerce-blocks/blob/04af396b9aec5a915ad98188eded53e723a051d3/src/BlockTypesController.php#L234) | [webpack flag](https://github.com/woocommerce/woocommerce-blocks/blob/04af396b9aec5a915ad98188eded53e723a051d3/bin/webpack-entries.js#L57-L60)).
|
||||
- Product Average Rating ([PHP flag](https://github.com/woocommerce/woocommerce-blocks/blob/1111e2fb9d6f5074df96a444b99e2fc00e4eb8d1/src/BlockTypesController.php#L229) | [webpack flag](https://github.com/woocommerce/woocommerce-blocks/blob/1111e2fb9d6f5074df96a444b99e2fc00e4eb8d1/bin/webpack-entries.js#L68-L70))
|
||||
- Product Rating Stars ([PHP flag](https://github.com/woocommerce/woocommerce-blocks/blob/trunk/src/BlockTypesController.php#L230) | [webpack flag](https://github.com/woocommerce/woocommerce-blocks/blob/trunk/bin/webpack-entries.js#L68-L70))
|
||||
|
|
|
@ -21,27 +21,6 @@ use \WP_Post;
|
|||
*/
|
||||
class BlockTemplatesController {
|
||||
|
||||
/**
|
||||
* Holds the Package instance
|
||||
*
|
||||
* @var Package
|
||||
*/
|
||||
private $package;
|
||||
|
||||
/**
|
||||
* Holds the path for the directory where the block templates will be kept.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $templates_directory;
|
||||
|
||||
/**
|
||||
* Holds the path for the directory where the block template parts will be kept.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $template_parts_directory;
|
||||
|
||||
/**
|
||||
* Directory which contains all templates
|
||||
*
|
||||
|
@ -49,6 +28,13 @@ class BlockTemplatesController {
|
|||
*/
|
||||
const TEMPLATES_ROOT_DIR = 'templates';
|
||||
|
||||
/**
|
||||
* Package instance.
|
||||
*
|
||||
* @var Package
|
||||
*/
|
||||
private $package;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
|
@ -59,9 +45,6 @@ class BlockTemplatesController {
|
|||
|
||||
// This feature is gated for WooCommerce versions 6.0.0 and above.
|
||||
if ( defined( 'WC_VERSION' ) && version_compare( WC_VERSION, '6.0.0', '>=' ) ) {
|
||||
$root_path = plugin_dir_path( __DIR__ ) . self::TEMPLATES_ROOT_DIR . DIRECTORY_SEPARATOR;
|
||||
$this->templates_directory = $root_path . BlockTemplateUtils::DIRECTORY_NAMES['TEMPLATES'];
|
||||
$this->template_parts_directory = $root_path . BlockTemplateUtils::DIRECTORY_NAMES['TEMPLATE_PARTS'];
|
||||
$this->init();
|
||||
}
|
||||
}
|
||||
|
@ -321,7 +304,7 @@ class BlockTemplatesController {
|
|||
return $template;
|
||||
}
|
||||
|
||||
$directory = $this->get_templates_directory( $template_type );
|
||||
$directory = BlockTemplateUtils::get_templates_directory( $template_type );
|
||||
$template_file_path = $directory . '/' . $template_slug . '.html';
|
||||
$template_object = BlockTemplateUtils::create_new_block_template_object( $template_file_path, $template_type, $template_slug );
|
||||
$template_built = BlockTemplateUtils::build_template_result_from_file( $template_object, $template_type );
|
||||
|
@ -476,11 +459,14 @@ class BlockTemplatesController {
|
|||
* @return array Templates from the WooCommerce blocks plugin directory.
|
||||
*/
|
||||
public function get_block_templates_from_woocommerce( $slugs, $already_found_templates, $template_type = 'wp_template' ) {
|
||||
$directory = $this->get_templates_directory( $template_type );
|
||||
$directory = BlockTemplateUtils::get_templates_directory( $template_type );
|
||||
$template_files = BlockTemplateUtils::get_template_paths( $directory );
|
||||
$templates = array();
|
||||
|
||||
foreach ( $template_files as $template_file ) {
|
||||
if ( ! $this->package->is_experimental_build() && str_contains( $template_file, 'templates/parts/product-gallery.html' ) ) {
|
||||
break;
|
||||
}
|
||||
// Skip the template if it's blockified, and we should only use classic ones.
|
||||
if ( ! BlockTemplateUtils::should_use_blockified_product_grid_templates() && strpos( $template_file, 'blockified' ) !== false ) {
|
||||
continue;
|
||||
|
@ -559,25 +545,6 @@ class BlockTemplatesController {
|
|||
return BlockTemplateUtils::filter_block_templates_by_feature_flag( $templates );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the directory where templates of a specific template type can be found.
|
||||
*
|
||||
* @param string $template_type wp_template or wp_template_part.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function get_templates_directory( $template_type = 'wp_template' ) {
|
||||
if ( 'wp_template_part' === $template_type ) {
|
||||
return $this->template_parts_directory;
|
||||
}
|
||||
|
||||
if ( BlockTemplateUtils::should_use_blockified_product_grid_templates() ) {
|
||||
return $this->templates_directory . '/blockified';
|
||||
}
|
||||
|
||||
return $this->templates_directory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path of a template on the Blocks template folder.
|
||||
*
|
||||
|
@ -587,7 +554,7 @@ class BlockTemplatesController {
|
|||
* @return string
|
||||
*/
|
||||
public function get_template_path_from_woocommerce( $template_slug, $template_type = 'wp_template' ) {
|
||||
return $this->get_templates_directory( $template_type ) . '/' . $template_slug . '.html';
|
||||
return BlockTemplateUtils::get_templates_directory( $template_type ) . '/' . $template_slug . '.html';
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -602,7 +569,7 @@ class BlockTemplatesController {
|
|||
if ( ! $template_name ) {
|
||||
return false;
|
||||
}
|
||||
$directory = $this->get_templates_directory( $template_type ) . '/' . $template_name . '.html';
|
||||
$directory = BlockTemplateUtils::get_templates_directory( $template_type ) . '/' . $template_name . '.html';
|
||||
|
||||
return is_readable(
|
||||
$directory
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
namespace Automattic\WooCommerce\Blocks\BlockTypes;
|
||||
|
||||
use Automattic\WooCommerce\Blocks\Utils\ProductGalleryUtils;
|
||||
use Automattic\WooCommerce\Blocks\Utils\BlockTemplateUtils;
|
||||
|
||||
/**
|
||||
* ProductGallery class.
|
||||
|
@ -14,6 +14,45 @@ class ProductGallery extends AbstractBlock {
|
|||
*/
|
||||
protected $block_name = 'product-gallery';
|
||||
|
||||
/**
|
||||
* Return the dialog content.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function render_dialog() {
|
||||
$template_part = BlockTemplateUtils::get_template_part( 'product-gallery' );
|
||||
|
||||
$parsed_template = parse_blocks(
|
||||
$template_part
|
||||
);
|
||||
|
||||
$html = array_reduce(
|
||||
$parsed_template,
|
||||
function( $carry, $item ) {
|
||||
return $carry . render_block( $item );
|
||||
},
|
||||
''
|
||||
);
|
||||
|
||||
$gallery_dialog = '<dialog data-wc-bind--open="selectors.woocommerce.isDialogOpen">' . $html . '</dialog>';
|
||||
return $gallery_dialog;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This function remove the div wrapper.
|
||||
* The content has a <div> with the class wp-block-woocommerce-product-gallery>.
|
||||
* We don't need since that we add it in the render method.
|
||||
*
|
||||
* @param string $content Block content.
|
||||
* @return string Rendered block type output.
|
||||
*/
|
||||
private function remove_div_wrapper( $content ) {
|
||||
$parsed_string = preg_replace( '/<div class="wp-block-woocommerce-product-gallery">/', '', $content );
|
||||
$parsed_string = preg_replace( '/<\/div>$/', '', $parsed_string );
|
||||
return $parsed_string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Include and render the block.
|
||||
*
|
||||
|
@ -27,15 +66,18 @@ class ProductGallery extends AbstractBlock {
|
|||
global $product;
|
||||
$classname = $attributes['className'] ?? '';
|
||||
$wrapper_attributes = get_block_wrapper_attributes( array( 'class' => trim( sprintf( 'woocommerce %1$s', $classname ) ) ) );
|
||||
$gallery = ( true === $attributes['fullScreenOnClick'] && isset( $attributes['mode'] ) && 'full' !== $attributes['mode'] ) ? $this->render_dialog() : '';
|
||||
$html = sprintf(
|
||||
'<div data-wc-interactive %1$s>
|
||||
'<div %1$s>
|
||||
%2$s
|
||||
%3$s
|
||||
</div>',
|
||||
$wrapper_attributes,
|
||||
$content
|
||||
$this->remove_div_wrapper( $content ),
|
||||
$gallery
|
||||
);
|
||||
|
||||
$p = new \WP_HTML_Tag_Processor( $content );
|
||||
$p = new \WP_HTML_Tag_Processor( $html );
|
||||
|
||||
if ( $p->next_tag() ) {
|
||||
$p->set_attribute( 'data-wc-interactive', true );
|
||||
|
@ -45,6 +87,7 @@ class ProductGallery extends AbstractBlock {
|
|||
array(
|
||||
'woocommerce' => array(
|
||||
'selectedImage' => $product->get_image_id(),
|
||||
'isDialogOpen' => false,
|
||||
),
|
||||
)
|
||||
)
|
||||
|
|
|
@ -159,6 +159,7 @@ class ProductGalleryLargeImage extends AbstractBlock {
|
|||
return array(
|
||||
'data-wc-on--mousemove' => 'actions.woocommerce.handleMouseMove',
|
||||
'data-wc-on--mouseleave' => 'actions.woocommerce.handleMouseLeave',
|
||||
'data-wc-on--click' => 'actions.woocommerce.handleClick',
|
||||
'data-wc-context' => wp_json_encode( $context, JSON_NUMERIC_CHECK ),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ class ProductGalleryThumbnails extends AbstractBlock {
|
|||
if ( $processor->next_tag() ) {
|
||||
$processor->set_attribute(
|
||||
'data-wc-on--click',
|
||||
'actions.woocommerce.handleClick'
|
||||
'actions.woocommerce.thumbnails.handleClick'
|
||||
);
|
||||
|
||||
$html .= $processor->get_updated_html();
|
||||
|
|
|
@ -38,6 +38,8 @@ class BlockTemplateUtils {
|
|||
'TEMPLATE_PARTS' => 'parts',
|
||||
);
|
||||
|
||||
const TEMPLATES_ROOT_DIR = 'templates';
|
||||
|
||||
/**
|
||||
* WooCommerce plugin slug
|
||||
*
|
||||
|
@ -274,6 +276,29 @@ class BlockTemplateUtils {
|
|||
return $path_list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the directory where templates of a specific template type can be found.
|
||||
*
|
||||
* @param string $template_type wp_template or wp_template_part.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_templates_directory( $template_type = 'wp_template' ) {
|
||||
$root_path = dirname( __DIR__, 2 ) . '/' . self::TEMPLATES_ROOT_DIR . DIRECTORY_SEPARATOR;
|
||||
$templates_directory = $root_path . self::DIRECTORY_NAMES['TEMPLATES'];
|
||||
$template_parts_directory = $root_path . self::DIRECTORY_NAMES['TEMPLATE_PARTS'];
|
||||
|
||||
if ( 'wp_template_part' === $template_type ) {
|
||||
return $template_parts_directory;
|
||||
}
|
||||
|
||||
if ( self::should_use_blockified_product_grid_templates() ) {
|
||||
return $templates_directory . '/blockified';
|
||||
}
|
||||
|
||||
return $templates_directory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns template titles.
|
||||
*
|
||||
|
@ -735,4 +760,28 @@ class BlockTemplateUtils {
|
|||
$saved_woo_templates
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the template part by slug
|
||||
*
|
||||
* @param string $slug The template part slug.
|
||||
*
|
||||
* @return string The template part content.
|
||||
*/
|
||||
public static function get_template_part( $slug ) {
|
||||
$templates_from_db = self::get_block_templates_from_db( array( $slug ), 'wp_template_part' );
|
||||
if ( count( $templates_from_db ) > 0 ) {
|
||||
$template_slug_to_load = $templates_from_db[0]->theme;
|
||||
} else {
|
||||
$theme_has_template = self::theme_has_template_part( $slug );
|
||||
$template_slug_to_load = $theme_has_template ? get_stylesheet() : self::PLUGIN_SLUG;
|
||||
}
|
||||
$template_part = self::get_block_template( $template_slug_to_load . '//' . $slug, 'wp_template_part' );
|
||||
|
||||
if ( $template_part && ! empty( $template_part->content ) ) {
|
||||
return $template_part->content;
|
||||
}
|
||||
// phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
|
||||
return file_get_contents( self::get_templates_directory( 'wp_template_part' ) . DIRECTORY_SEPARATOR . $slug . '.html' );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
<!-- wp:woocommerce/product-gallery {"mode":"full"} -->
|
||||
<div class="wp-block-woocommerce-product-gallery"><!-- wp:group {"layout":{"type":"flex","flexWrap":"nowrap"}} -->
|
||||
<div class="wp-block-group"><!-- wp:woocommerce/product-gallery-thumbnails {"lock":{"move":true,"remove":true}} /-->
|
||||
|
||||
<!-- wp:woocommerce/product-gallery-large-image {"lock":{"move":true,"remove":true}} -->
|
||||
<div
|
||||
class="wp-block-woocommerce-product-gallery-large-image wc-block-product-gallery-large-image__inner-blocks">
|
||||
<!-- wp:woocommerce/product-sale-badge {"isDescendentOfSingleProductTemplate":true,"align":"right","style":{"spacing":{"margin":{"top":"4px","right":"4px","bottom":"4px","left":"4px"}}}} /-->
|
||||
|
||||
<!-- wp:woocommerce/product-gallery-large-image-next-previous {"layout":{"type":"flex","verticalAlignment":"bottom"}} -->
|
||||
<div class="wp-block-woocommerce-product-gallery-large-image-next-previous"></div>
|
||||
<!-- /wp:woocommerce/product-gallery-large-image-next-previous -->
|
||||
</div>
|
||||
<!-- /wp:woocommerce/product-gallery-large-image -->
|
||||
</div>
|
||||
<!-- /wp:group -->
|
||||
|
||||
<!-- wp:woocommerce/product-gallery-pager {"lock":{"move":true,"remove":true}} /-->
|
||||
</div>
|
||||
<!-- /wp:woocommerce/product-gallery -->
|
|
@ -1,12 +1,13 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { test, expect } from '@woocommerce/e2e-playwright-utils';
|
||||
import { test as base, expect } from '@woocommerce/e2e-playwright-utils';
|
||||
import { EditorUtils, FrontendUtils } from '@woocommerce/e2e-utils';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { ProductGalleryPage } from '../product-gallery/product-gallery.page';
|
||||
|
||||
const blockData = {
|
||||
name: 'woocommerce/product-sale-badge',
|
||||
|
@ -30,6 +31,18 @@ const blockData = {
|
|||
productPageNotOnSale: '/product/album/',
|
||||
};
|
||||
|
||||
const test = base.extend< { pageObject: ProductGalleryPage } >( {
|
||||
pageObject: async ( { page, editor, frontendUtils, editorUtils }, use ) => {
|
||||
const pageObject = new ProductGalleryPage( {
|
||||
page,
|
||||
editor,
|
||||
frontendUtils,
|
||||
editorUtils,
|
||||
} );
|
||||
await use( pageObject );
|
||||
},
|
||||
} );
|
||||
|
||||
const getBoundingClientRect = async ( {
|
||||
frontendUtils,
|
||||
editorUtils,
|
||||
|
@ -92,10 +105,15 @@ test.describe( `${ blockData.name }`, () => {
|
|||
frontendUtils,
|
||||
editor,
|
||||
page,
|
||||
pageObject,
|
||||
} ) => {
|
||||
await editor.openDocumentSettingsSidebar();
|
||||
await editor.insertBlock( {
|
||||
name: 'woocommerce/product-gallery',
|
||||
} );
|
||||
|
||||
await pageObject.toggleFullScreenOnClickSetting( false );
|
||||
|
||||
await Promise.all( [
|
||||
editor.saveSiteEditorEntities(),
|
||||
page.waitForResponse( ( response ) =>
|
||||
|
@ -116,10 +134,15 @@ test.describe( `${ blockData.name }`, () => {
|
|||
frontendUtils,
|
||||
editor,
|
||||
page,
|
||||
pageObject,
|
||||
} ) => {
|
||||
await editor.openDocumentSettingsSidebar();
|
||||
await editor.insertBlock( {
|
||||
name: 'woocommerce/product-gallery',
|
||||
} );
|
||||
|
||||
await pageObject.toggleFullScreenOnClickSetting( false );
|
||||
|
||||
await Promise.all( [
|
||||
editor.saveSiteEditorEntities(),
|
||||
page.waitForResponse( ( response ) =>
|
||||
|
@ -141,11 +164,15 @@ test.describe( `${ blockData.name }`, () => {
|
|||
editorUtils,
|
||||
editor,
|
||||
page,
|
||||
pageObject,
|
||||
} ) => {
|
||||
await editor.openDocumentSettingsSidebar();
|
||||
await editor.insertBlock( {
|
||||
name: 'woocommerce/product-gallery',
|
||||
} );
|
||||
|
||||
await pageObject.toggleFullScreenOnClickSetting( false );
|
||||
|
||||
const block = await editorUtils.getBlockByName( blockData.name );
|
||||
|
||||
await block.click();
|
||||
|
@ -189,11 +216,15 @@ test.describe( `${ blockData.name }`, () => {
|
|||
editorUtils,
|
||||
editor,
|
||||
page,
|
||||
pageObject,
|
||||
} ) => {
|
||||
await editor.openDocumentSettingsSidebar();
|
||||
await editor.insertBlock( {
|
||||
name: 'woocommerce/product-gallery',
|
||||
} );
|
||||
|
||||
await pageObject.toggleFullScreenOnClickSetting( false );
|
||||
|
||||
const block = await editorUtils.getBlockByName( blockData.name );
|
||||
|
||||
await block.click();
|
||||
|
@ -241,10 +272,13 @@ test.describe( `${ blockData.name }`, () => {
|
|||
editorUtils,
|
||||
editor,
|
||||
page,
|
||||
pageObject,
|
||||
} ) => {
|
||||
await editor.openDocumentSettingsSidebar();
|
||||
await editor.insertBlock( {
|
||||
name: 'woocommerce/product-gallery',
|
||||
} );
|
||||
await pageObject.toggleFullScreenOnClickSetting( false );
|
||||
|
||||
const editorBoundingClientRect = await getBoundingClientRect( {
|
||||
frontendUtils,
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { test, expect } from '@woocommerce/e2e-playwright-utils';
|
||||
import { EditorUtils, FrontendUtils } from '@woocommerce/e2e-utils';
|
||||
import { test as base, expect } from '@woocommerce/e2e-playwright-utils';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { addBlock } from './utils';
|
||||
import { ProductGalleryPage } from '../../product-gallery.page';
|
||||
|
||||
const blockData = {
|
||||
name: 'woocommerce/product-gallery-large-image-next-previous',
|
||||
|
@ -40,34 +40,52 @@ const blockData = {
|
|||
};
|
||||
|
||||
const getBoundingClientRect = async ( {
|
||||
frontendUtils,
|
||||
editorUtils,
|
||||
leftArrowSelector,
|
||||
rightArrowSelector,
|
||||
isFrontend,
|
||||
pageObject,
|
||||
}: {
|
||||
frontendUtils: FrontendUtils;
|
||||
editorUtils: EditorUtils;
|
||||
pageObject: ProductGalleryPage;
|
||||
leftArrowSelector: string;
|
||||
rightArrowSelector: string;
|
||||
isFrontend: boolean;
|
||||
} ) => {
|
||||
const page = isFrontend ? frontendUtils.page : editorUtils.editor.canvas;
|
||||
const page = isFrontend ? 'frontend' : 'editor';
|
||||
return {
|
||||
leftArrow: await page
|
||||
leftArrow: await (
|
||||
await pageObject.getNextPreviousButtonsBlock( {
|
||||
page,
|
||||
} )
|
||||
)
|
||||
.locator( leftArrowSelector )
|
||||
.evaluate( ( el ) => el.getBoundingClientRect() ),
|
||||
rightArrow: await page
|
||||
rightArrow: await (
|
||||
await pageObject.getNextPreviousButtonsBlock( {
|
||||
page,
|
||||
} )
|
||||
)
|
||||
.locator( rightArrowSelector )
|
||||
.evaluate( ( el ) => el.getBoundingClientRect() ),
|
||||
gallery: await (
|
||||
await ( isFrontend ? frontendUtils : editorUtils ).getBlockByName(
|
||||
'woocommerce/product-gallery-large-image'
|
||||
)
|
||||
await pageObject.getMainImageBlock( {
|
||||
page,
|
||||
} )
|
||||
).evaluate( ( el ) => el.getBoundingClientRect() ),
|
||||
};
|
||||
};
|
||||
|
||||
const test = base.extend< { pageObject: ProductGalleryPage } >( {
|
||||
pageObject: async ( { page, editor, frontendUtils, editorUtils }, use ) => {
|
||||
const pageObject = new ProductGalleryPage( {
|
||||
page,
|
||||
editor,
|
||||
frontendUtils,
|
||||
editorUtils,
|
||||
} );
|
||||
await use( pageObject );
|
||||
},
|
||||
} );
|
||||
|
||||
test.describe( `${ blockData.name }`, () => {
|
||||
test.beforeEach( async ( { requestUtils, admin, editorUtils } ) => {
|
||||
await requestUtils.deleteAllTemplates( 'wp_template' );
|
||||
|
@ -85,14 +103,16 @@ test.describe( `${ blockData.name }`, () => {
|
|||
} );
|
||||
|
||||
test( 'Renders Next/Previous Button block on the editor side', async ( {
|
||||
editorUtils,
|
||||
editor,
|
||||
pageObject,
|
||||
} ) => {
|
||||
await editor.insertBlock( {
|
||||
name: 'woocommerce/product-gallery',
|
||||
} );
|
||||
|
||||
const block = await editorUtils.getBlockByName( blockData.name );
|
||||
const block = await pageObject.getNextPreviousButtonsBlock( {
|
||||
page: 'editor',
|
||||
} );
|
||||
|
||||
await expect( block ).toBeVisible();
|
||||
} );
|
||||
|
@ -100,9 +120,9 @@ test.describe( `${ blockData.name }`, () => {
|
|||
test( 'Renders Next/Previous Button block on the frontend side', async ( {
|
||||
admin,
|
||||
editorUtils,
|
||||
frontendUtils,
|
||||
editor,
|
||||
page,
|
||||
pageObject,
|
||||
} ) => {
|
||||
await addBlock( admin, editor, editorUtils );
|
||||
|
||||
|
@ -117,7 +137,9 @@ test.describe( `${ blockData.name }`, () => {
|
|||
waitUntil: 'commit',
|
||||
} );
|
||||
|
||||
const block = await frontendUtils.getBlockByName( blockData.name );
|
||||
const block = await pageObject.getNextPreviousButtonsBlock( {
|
||||
page: 'frontend',
|
||||
} );
|
||||
|
||||
await expect( block ).toBeVisible();
|
||||
} );
|
||||
|
@ -127,13 +149,17 @@ test.describe( `${ blockData.name }`, () => {
|
|||
page,
|
||||
editor,
|
||||
editorUtils,
|
||||
pageObject,
|
||||
admin,
|
||||
} ) => {
|
||||
await addBlock( admin, editor, editorUtils );
|
||||
await (
|
||||
await editorUtils.getBlockByName( blockData.name )
|
||||
await pageObject.getNextPreviousButtonsBlock( {
|
||||
page: 'editor',
|
||||
} )
|
||||
).click();
|
||||
await editor.openDocumentSettingsSidebar();
|
||||
|
||||
await page
|
||||
.locator( blockData.selectors.editor.noArrowsOption )
|
||||
.click();
|
||||
|
@ -168,7 +194,7 @@ test.describe( `${ blockData.name }`, () => {
|
|||
page,
|
||||
editor,
|
||||
editorUtils,
|
||||
frontendUtils,
|
||||
pageObject,
|
||||
} ) => {
|
||||
// Currently we are adding the block under the related products block, but in the future we have to add replace the product gallery block with this block.
|
||||
const parentBlock = await editorUtils.getBlockByName(
|
||||
|
@ -188,7 +214,9 @@ test.describe( `${ blockData.name }`, () => {
|
|||
parentClientId
|
||||
);
|
||||
await (
|
||||
await editorUtils.getBlockByName( blockData.name )
|
||||
await pageObject.getNextPreviousButtonsBlock( {
|
||||
page: 'editor',
|
||||
} )
|
||||
).click();
|
||||
|
||||
await editor.openDocumentSettingsSidebar();
|
||||
|
@ -197,8 +225,7 @@ test.describe( `${ blockData.name }`, () => {
|
|||
.click();
|
||||
|
||||
const editorBoundingClientRect = await getBoundingClientRect( {
|
||||
frontendUtils,
|
||||
editorUtils,
|
||||
pageObject,
|
||||
leftArrowSelector:
|
||||
blockData.selectors.editor.leftArrow.outsideTheImage,
|
||||
rightArrowSelector:
|
||||
|
@ -226,8 +253,7 @@ test.describe( `${ blockData.name }`, () => {
|
|||
} );
|
||||
|
||||
const frontendBoundingClientRect = await getBoundingClientRect( {
|
||||
frontendUtils,
|
||||
editorUtils,
|
||||
pageObject,
|
||||
leftArrowSelector:
|
||||
blockData.selectors.editor.leftArrow.outsideTheImage,
|
||||
rightArrowSelector:
|
||||
|
@ -248,7 +274,7 @@ test.describe( `${ blockData.name }`, () => {
|
|||
page,
|
||||
editor,
|
||||
editorUtils,
|
||||
frontendUtils,
|
||||
pageObject,
|
||||
} ) => {
|
||||
// Currently we are adding the block under the related products block, but in the future we have to add replace the product gallery block with this block.
|
||||
const parentBlock = await editorUtils.getBlockByName(
|
||||
|
@ -268,7 +294,9 @@ test.describe( `${ blockData.name }`, () => {
|
|||
parentClientId
|
||||
);
|
||||
await (
|
||||
await editorUtils.getBlockByName( blockData.name )
|
||||
await pageObject.getNextPreviousButtonsBlock( {
|
||||
page: 'editor',
|
||||
} )
|
||||
).click();
|
||||
|
||||
await editor.openDocumentSettingsSidebar();
|
||||
|
@ -277,8 +305,7 @@ test.describe( `${ blockData.name }`, () => {
|
|||
.click();
|
||||
|
||||
const editorBoundingClientRect = await getBoundingClientRect( {
|
||||
frontendUtils,
|
||||
editorUtils,
|
||||
pageObject,
|
||||
leftArrowSelector:
|
||||
blockData.selectors.editor.leftArrow.insideTheImage,
|
||||
rightArrowSelector:
|
||||
|
@ -306,8 +333,7 @@ test.describe( `${ blockData.name }`, () => {
|
|||
} );
|
||||
|
||||
const frontendBoundingClientRect = await getBoundingClientRect( {
|
||||
frontendUtils,
|
||||
editorUtils,
|
||||
pageObject,
|
||||
leftArrowSelector:
|
||||
blockData.selectors.editor.leftArrow.insideTheImage,
|
||||
rightArrowSelector:
|
||||
|
@ -328,7 +354,7 @@ test.describe( `${ blockData.name }`, () => {
|
|||
page,
|
||||
editor,
|
||||
editorUtils,
|
||||
frontendUtils,
|
||||
pageObject,
|
||||
} ) => {
|
||||
// Currently we are adding the block under the related products block, but in the future we have to add replace the product gallery block with this block.
|
||||
const parentBlock = await editorUtils.getBlockByName(
|
||||
|
@ -348,12 +374,16 @@ test.describe( `${ blockData.name }`, () => {
|
|||
parentClientId
|
||||
);
|
||||
await (
|
||||
await editorUtils.getBlockByName( blockData.name )
|
||||
await pageObject.getNextPreviousButtonsBlock( {
|
||||
page: 'editor',
|
||||
} )
|
||||
).click();
|
||||
|
||||
await editorUtils.setLayoutOption( 'Align Top' );
|
||||
|
||||
const block = await editorUtils.getBlockByName( blockData.name );
|
||||
const block = await pageObject.getNextPreviousButtonsBlock( {
|
||||
page: 'editor',
|
||||
} );
|
||||
|
||||
await expect( block ).toHaveCSS( 'align-items', 'flex-start' );
|
||||
|
||||
|
@ -368,8 +398,10 @@ test.describe( `${ blockData.name }`, () => {
|
|||
waitUntil: 'commit',
|
||||
} );
|
||||
|
||||
const frontendBlock = await frontendUtils.getBlockByName(
|
||||
blockData.name
|
||||
const frontendBlock = await pageObject.getNextPreviousButtonsBlock(
|
||||
{
|
||||
page: 'frontend',
|
||||
}
|
||||
);
|
||||
|
||||
await expect( frontendBlock ).toHaveCSS(
|
||||
|
@ -382,7 +414,7 @@ test.describe( `${ blockData.name }`, () => {
|
|||
page,
|
||||
editor,
|
||||
editorUtils,
|
||||
frontendUtils,
|
||||
pageObject,
|
||||
} ) => {
|
||||
// Currently we are adding the block under the related products block, but in the future we have to add replace the product gallery block with this block.
|
||||
const parentBlock = await editorUtils.getBlockByName(
|
||||
|
@ -402,12 +434,16 @@ test.describe( `${ blockData.name }`, () => {
|
|||
parentClientId
|
||||
);
|
||||
await (
|
||||
await editorUtils.getBlockByName( blockData.name )
|
||||
await await pageObject.getNextPreviousButtonsBlock( {
|
||||
page: 'editor',
|
||||
} )
|
||||
).click();
|
||||
|
||||
await editorUtils.setLayoutOption( 'Align Middle' );
|
||||
|
||||
const block = await editorUtils.getBlockByName( blockData.name );
|
||||
const block = await pageObject.getNextPreviousButtonsBlock( {
|
||||
page: 'editor',
|
||||
} );
|
||||
|
||||
await expect( block ).toHaveCSS( 'align-items', 'center' );
|
||||
|
||||
|
@ -422,8 +458,10 @@ test.describe( `${ blockData.name }`, () => {
|
|||
waitUntil: 'commit',
|
||||
} );
|
||||
|
||||
const frontendBlock = await frontendUtils.getBlockByName(
|
||||
blockData.name
|
||||
const frontendBlock = await pageObject.getNextPreviousButtonsBlock(
|
||||
{
|
||||
page: 'frontend',
|
||||
}
|
||||
);
|
||||
|
||||
await expect( frontendBlock ).toHaveCSS( 'align-items', 'center' );
|
||||
|
@ -433,7 +471,7 @@ test.describe( `${ blockData.name }`, () => {
|
|||
page,
|
||||
editor,
|
||||
editorUtils,
|
||||
frontendUtils,
|
||||
pageObject,
|
||||
} ) => {
|
||||
// Currently we are adding the block under the related products block, but in the future we have to add replace the product gallery block with this block.
|
||||
const parentBlock = await editorUtils.getBlockByName(
|
||||
|
@ -453,10 +491,14 @@ test.describe( `${ blockData.name }`, () => {
|
|||
parentClientId
|
||||
);
|
||||
await (
|
||||
await editorUtils.getBlockByName( blockData.name )
|
||||
await pageObject.getNextPreviousButtonsBlock( {
|
||||
page: 'editor',
|
||||
} )
|
||||
).click();
|
||||
|
||||
const block = await editorUtils.getBlockByName( blockData.name );
|
||||
const block = await pageObject.getNextPreviousButtonsBlock( {
|
||||
page: 'editor',
|
||||
} );
|
||||
|
||||
await expect( block ).toHaveCSS( 'align-items', 'flex-end' );
|
||||
|
||||
|
@ -471,8 +513,10 @@ test.describe( `${ blockData.name }`, () => {
|
|||
waitUntil: 'commit',
|
||||
} );
|
||||
|
||||
const frontendBlock = await frontendUtils.getBlockByName(
|
||||
blockData.name
|
||||
const frontendBlock = await pageObject.getNextPreviousButtonsBlock(
|
||||
{
|
||||
page: 'frontend',
|
||||
}
|
||||
);
|
||||
|
||||
await expect( frontendBlock ).toHaveCSS(
|
||||
|
|
|
@ -19,10 +19,12 @@ const blockData = {
|
|||
};
|
||||
|
||||
const test = base.extend< { pageObject: ProductGalleryPage } >( {
|
||||
pageObject: async ( { page, editor }, use ) => {
|
||||
pageObject: async ( { page, editor, frontendUtils, editorUtils }, use ) => {
|
||||
const pageObject = new ProductGalleryPage( {
|
||||
page,
|
||||
editor,
|
||||
frontendUtils,
|
||||
editorUtils,
|
||||
} );
|
||||
await use( pageObject );
|
||||
},
|
||||
|
@ -48,12 +50,13 @@ test.describe( `${ blockData.name }`, () => {
|
|||
test( 'Renders Product Gallery Large Image block on the editor and frontend side', async ( {
|
||||
page,
|
||||
editorUtils,
|
||||
frontendUtils,
|
||||
pageObject,
|
||||
} ) => {
|
||||
await pageObject.addProductGalleryBlock( { cleanContent: true } );
|
||||
|
||||
const block = await editorUtils.getBlockByName( blockData.name );
|
||||
const block = await pageObject.getMainImageBlock( {
|
||||
page: 'editor',
|
||||
} );
|
||||
|
||||
await expect( block ).toBeVisible();
|
||||
|
||||
|
@ -63,9 +66,9 @@ test.describe( `${ blockData.name }`, () => {
|
|||
waitUntil: 'commit',
|
||||
} );
|
||||
|
||||
const blockFrontend = await frontendUtils.getBlockByName(
|
||||
blockData.name
|
||||
);
|
||||
const blockFrontend = await pageObject.getMainImageBlock( {
|
||||
page: 'frontend',
|
||||
} );
|
||||
|
||||
await expect( blockFrontend ).toBeVisible();
|
||||
} );
|
||||
|
@ -81,7 +84,6 @@ test.describe( `${ blockData.name }`, () => {
|
|||
test( 'should work on frontend when is enabled', async ( {
|
||||
pageObject,
|
||||
editorUtils,
|
||||
frontendUtils,
|
||||
page,
|
||||
} ) => {
|
||||
await pageObject.addProductGalleryBlock( { cleanContent: true } );
|
||||
|
@ -92,9 +94,9 @@ test.describe( `${ blockData.name }`, () => {
|
|||
waitUntil: 'commit',
|
||||
} );
|
||||
|
||||
const blockFrontend = await frontendUtils.getBlockByName(
|
||||
blockData.name
|
||||
);
|
||||
const blockFrontend = await pageObject.getMainImageBlock( {
|
||||
page: 'frontend',
|
||||
} );
|
||||
|
||||
// img[style] is the selector because the style attribute is Interactivity API.
|
||||
const imgElement = blockFrontend.locator(
|
||||
|
@ -116,7 +118,6 @@ test.describe( `${ blockData.name }`, () => {
|
|||
test( 'should not work on frontend when is disabled', async ( {
|
||||
pageObject,
|
||||
editorUtils,
|
||||
frontendUtils,
|
||||
page,
|
||||
} ) => {
|
||||
await pageObject.addProductGalleryBlock( { cleanContent: true } );
|
||||
|
@ -132,9 +133,9 @@ test.describe( `${ blockData.name }`, () => {
|
|||
waitUntil: 'commit',
|
||||
} );
|
||||
|
||||
const blockFrontend = await frontendUtils.getBlockByName(
|
||||
blockData.name
|
||||
);
|
||||
const blockFrontend = await pageObject.getMainImageBlock( {
|
||||
page: 'frontend',
|
||||
} );
|
||||
|
||||
// img[style] is the selector because the style attribute is added by Interactivity API. In this case, the style attribute should not be added.
|
||||
const imgElement = blockFrontend.locator(
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { test, expect } from '@woocommerce/e2e-playwright-utils';
|
||||
import { test as base, expect } from '@woocommerce/e2e-playwright-utils';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { addBlock } from './utils';
|
||||
import { ProductGalleryPage } from '../../product-gallery.page';
|
||||
|
||||
const blockData = {
|
||||
name: 'woocommerce/product-gallery-thumbnails',
|
||||
|
@ -25,6 +26,17 @@ const blockData = {
|
|||
productPage: '/product/v-neck-t-shirt/',
|
||||
};
|
||||
|
||||
const test = base.extend< { pageObject: ProductGalleryPage } >( {
|
||||
pageObject: async ( { page, editor, frontendUtils, editorUtils }, use ) => {
|
||||
const pageObject = new ProductGalleryPage( {
|
||||
page,
|
||||
editor,
|
||||
frontendUtils,
|
||||
editorUtils,
|
||||
} );
|
||||
await use( pageObject );
|
||||
},
|
||||
} );
|
||||
test.describe( `${ blockData.name }`, () => {
|
||||
test.beforeEach( async ( { requestUtils, admin, editorUtils } ) => {
|
||||
await requestUtils.deleteAllTemplates( 'wp_template' );
|
||||
|
@ -39,19 +51,18 @@ test.describe( `${ blockData.name }`, () => {
|
|||
test( 'Renders Product Gallery Thumbnails block on the editor and frontend side', async ( {
|
||||
page,
|
||||
editor,
|
||||
editorUtils,
|
||||
frontendUtils,
|
||||
pageObject,
|
||||
} ) => {
|
||||
await editor.insertBlock( {
|
||||
name: 'woocommerce/product-gallery',
|
||||
} );
|
||||
|
||||
const thumbnailsBlock = await editorUtils.getBlockByName(
|
||||
blockData.name
|
||||
);
|
||||
const largeImageBlock = await editorUtils.getBlockByName(
|
||||
'woocommerce/product-gallery-large-image'
|
||||
);
|
||||
const thumbnailsBlock = await pageObject.getThumbnailsBlock( {
|
||||
page: 'editor',
|
||||
} );
|
||||
const largeImageBlock = await pageObject.getMainImageBlock( {
|
||||
page: 'editor',
|
||||
} );
|
||||
|
||||
const thumbnailsBlockBoundingRect = await thumbnailsBlock.boundingBox();
|
||||
const largeImageBlockBoundingRect = await largeImageBlock.boundingBox();
|
||||
|
@ -76,13 +87,13 @@ test.describe( `${ blockData.name }`, () => {
|
|||
waitUntil: 'commit',
|
||||
} );
|
||||
|
||||
const thumbnailsBlockFrontend = await frontendUtils.getBlockByName(
|
||||
blockData.name
|
||||
);
|
||||
const thumbnailsBlockFrontend = await pageObject.getThumbnailsBlock( {
|
||||
page: 'frontend',
|
||||
} );
|
||||
|
||||
const largeImageBlockFrontend = await frontendUtils.getBlockByName(
|
||||
'woocommerce/product-gallery-large-image'
|
||||
);
|
||||
const largeImageBlockFrontend = await pageObject.getMainImageBlock( {
|
||||
page: 'frontend',
|
||||
} );
|
||||
|
||||
const thumbnailsBlockFrontendBoundingRect =
|
||||
await thumbnailsBlockFrontend.boundingBox();
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
*/
|
||||
import { test as base, expect } from '@woocommerce/e2e-playwright-utils';
|
||||
import { Locator, Page } from '@playwright/test';
|
||||
import { FrontendUtils } from '@woocommerce/e2e-utils';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
|
@ -21,23 +20,23 @@ const blockData = {
|
|||
};
|
||||
|
||||
const test = base.extend< { pageObject: ProductGalleryPage } >( {
|
||||
pageObject: async ( { page, editor }, use ) => {
|
||||
pageObject: async ( { page, editor, frontendUtils, editorUtils }, use ) => {
|
||||
const pageObject = new ProductGalleryPage( {
|
||||
page,
|
||||
editor,
|
||||
frontendUtils,
|
||||
editorUtils,
|
||||
} );
|
||||
await use( pageObject );
|
||||
},
|
||||
} );
|
||||
|
||||
export const getVisibleLargeImageId = async (
|
||||
frontendUtils: FrontendUtils
|
||||
mainImageBlockLocator: Locator
|
||||
) => {
|
||||
const mainImageBlock = await frontendUtils.getBlockByName(
|
||||
'woocommerce/product-gallery-large-image'
|
||||
);
|
||||
|
||||
const mainImage = mainImageBlock.locator( 'img:not([hidden])' ) as Locator;
|
||||
const mainImage = mainImageBlockLocator.locator(
|
||||
'img:not([hidden])'
|
||||
) as Locator;
|
||||
|
||||
const mainImageContext = ( await mainImage.getAttribute(
|
||||
'data-wc-context'
|
||||
|
@ -48,7 +47,7 @@ export const getVisibleLargeImageId = async (
|
|||
return mainImageParsedContext.woocommerce.imageId;
|
||||
};
|
||||
|
||||
export const waitForJavascriptFrontendFileIsLoaded = async ( page: Page ) => {
|
||||
const waitForJavascriptFrontendFileIsLoaded = async ( page: Page ) => {
|
||||
await page.waitForResponse(
|
||||
( response ) =>
|
||||
response.url().includes( 'product-gallery-frontend' ) &&
|
||||
|
@ -56,15 +55,11 @@ export const waitForJavascriptFrontendFileIsLoaded = async ( page: Page ) => {
|
|||
);
|
||||
};
|
||||
|
||||
export const getThumbnailImageIdByNth = async (
|
||||
const getThumbnailImageIdByNth = async (
|
||||
nth: number,
|
||||
frontendUtils: FrontendUtils
|
||||
thumbnailsLocator: Locator
|
||||
) => {
|
||||
const thumbnailsBlock = await frontendUtils.getBlockByName(
|
||||
'woocommerce/product-gallery-thumbnails'
|
||||
);
|
||||
|
||||
const image = thumbnailsBlock.locator( 'img' ).nth( nth );
|
||||
const image = thumbnailsLocator.locator( 'img' ).nth( nth );
|
||||
|
||||
const imageContext = ( await image.getAttribute(
|
||||
'data-wc-context'
|
||||
|
@ -91,75 +86,154 @@ test.describe( `${ blockData.name }`, () => {
|
|||
await requestUtils.deleteAllTemplates( 'wp_template_part' );
|
||||
} );
|
||||
|
||||
test( 'should have as first thumbnail, the same image that it is visible in the Large Image block', async ( {
|
||||
page,
|
||||
editorUtils,
|
||||
frontendUtils,
|
||||
pageObject,
|
||||
} ) => {
|
||||
await pageObject.addProductGalleryBlock( { cleanContent: true } );
|
||||
test.describe( 'with thumbnails', () => {
|
||||
test( 'should have as first thumbnail, the same image that it is visible in the Large Image block', async ( {
|
||||
page,
|
||||
editorUtils,
|
||||
pageObject,
|
||||
} ) => {
|
||||
await pageObject.addProductGalleryBlock( { cleanContent: true } );
|
||||
|
||||
await editorUtils.saveTemplate();
|
||||
await editorUtils.saveTemplate();
|
||||
|
||||
await page.goto( blockData.productPage, {
|
||||
waitUntil: 'commit',
|
||||
await page.goto( blockData.productPage, {
|
||||
waitUntil: 'commit',
|
||||
} );
|
||||
|
||||
const visibleLargeImageId = await getVisibleLargeImageId(
|
||||
await pageObject.getMainImageBlock( {
|
||||
page: 'frontend',
|
||||
} )
|
||||
);
|
||||
|
||||
const firstImageThumbnailId = await getThumbnailImageIdByNth(
|
||||
0,
|
||||
await pageObject.getThumbnailsBlock( {
|
||||
page: 'frontend',
|
||||
} )
|
||||
);
|
||||
|
||||
expect( visibleLargeImageId ).toBe( firstImageThumbnailId );
|
||||
} );
|
||||
|
||||
const visibleLargeImageId = await getVisibleLargeImageId(
|
||||
frontendUtils
|
||||
);
|
||||
// @todo: Fix this test. It's failing because the thumbnail images aren't generated correctly when the products are imported via .xml: https://github.com/woocommerce/woocommerce/issues/31646
|
||||
// eslint-disable-next-line playwright/no-skipped-test
|
||||
test.skip( 'should change the image when the user click on a thumbnail image', async ( {
|
||||
page,
|
||||
editorUtils,
|
||||
pageObject,
|
||||
} ) => {
|
||||
await pageObject.addProductGalleryBlock( { cleanContent: true } );
|
||||
|
||||
const firstImageThumbnailId = await getThumbnailImageIdByNth(
|
||||
0,
|
||||
frontendUtils
|
||||
);
|
||||
await editorUtils.saveTemplate();
|
||||
|
||||
expect( visibleLargeImageId ).toBe( firstImageThumbnailId );
|
||||
await Promise.all( [
|
||||
page.goto( blockData.productPage, {
|
||||
waitUntil: 'load',
|
||||
} ),
|
||||
waitForJavascriptFrontendFileIsLoaded( page ),
|
||||
] );
|
||||
|
||||
const visibleLargeImageId = await getVisibleLargeImageId(
|
||||
await pageObject.getMainImageBlock( {
|
||||
page: 'frontend',
|
||||
} )
|
||||
);
|
||||
|
||||
const secondImageThumbnailId = await getThumbnailImageIdByNth(
|
||||
1,
|
||||
await pageObject.getThumbnailsBlock( {
|
||||
page: 'frontend',
|
||||
} )
|
||||
);
|
||||
|
||||
expect( visibleLargeImageId ).not.toBe( secondImageThumbnailId );
|
||||
|
||||
await (
|
||||
await pageObject.getThumbnailsBlock( {
|
||||
page: 'frontend',
|
||||
} )
|
||||
)
|
||||
.locator( 'img' )
|
||||
.nth( 1 )
|
||||
.click();
|
||||
|
||||
const newVisibleLargeImageId = await getVisibleLargeImageId(
|
||||
await pageObject.getMainImageBlock( {
|
||||
page: 'frontend',
|
||||
} )
|
||||
);
|
||||
|
||||
expect( newVisibleLargeImageId ).toBe( secondImageThumbnailId );
|
||||
} );
|
||||
} );
|
||||
|
||||
// @todo: Fix this test. It's failing because the thumbnail images aren't generated correctly when the products are imported via .xml: https://github.com/woocommerce/woocommerce/issues/31646
|
||||
// eslint-disable-next-line playwright/no-skipped-test
|
||||
test.skip( 'should change the image when the user click on a thumbnail image', async ( {
|
||||
page,
|
||||
editorUtils,
|
||||
frontendUtils,
|
||||
pageObject,
|
||||
} ) => {
|
||||
await pageObject.addProductGalleryBlock( { cleanContent: true } );
|
||||
test.describe( 'full-screen when clicked option', () => {
|
||||
test( 'should be enabled by default', async ( {
|
||||
pageObject,
|
||||
editor,
|
||||
} ) => {
|
||||
await pageObject.addProductGalleryBlock( { cleanContent: true } );
|
||||
await editor.openDocumentSettingsSidebar();
|
||||
const fullScreenOption =
|
||||
await pageObject.getFullScreenOnClickSetting();
|
||||
|
||||
await editorUtils.saveTemplate();
|
||||
await expect( fullScreenOption ).toBeChecked();
|
||||
} );
|
||||
|
||||
await Promise.all( [
|
||||
page.goto( blockData.productPage, {
|
||||
waitUntil: 'load',
|
||||
} ),
|
||||
waitForJavascriptFrontendFileIsLoaded( page ),
|
||||
] );
|
||||
test( 'should open dialog on the frontend', async ( {
|
||||
pageObject,
|
||||
page,
|
||||
editorUtils,
|
||||
} ) => {
|
||||
await pageObject.addProductGalleryBlock( { cleanContent: true } );
|
||||
await editorUtils.saveTemplate();
|
||||
|
||||
const visibleLargeImageId = await getVisibleLargeImageId(
|
||||
frontendUtils
|
||||
);
|
||||
await Promise.all( [
|
||||
page.goto( blockData.productPage, {
|
||||
waitUntil: 'domcontentloaded',
|
||||
} ),
|
||||
waitForJavascriptFrontendFileIsLoaded( page ),
|
||||
] );
|
||||
|
||||
const secondImageThumbnailId = await getThumbnailImageIdByNth(
|
||||
1,
|
||||
frontendUtils
|
||||
);
|
||||
const mainImageBlock = await pageObject.getMainImageBlock( {
|
||||
page: 'frontend',
|
||||
} );
|
||||
|
||||
expect( visibleLargeImageId ).not.toBe( secondImageThumbnailId );
|
||||
await expect( page.locator( 'dialog' ) ).toBeHidden();
|
||||
|
||||
await (
|
||||
await frontendUtils.getBlockByName(
|
||||
'woocommerce/product-gallery-thumbnails'
|
||||
)
|
||||
)
|
||||
.locator( 'img' )
|
||||
.nth( 1 )
|
||||
.click();
|
||||
await mainImageBlock.click();
|
||||
|
||||
const newVisibleLargeImageId = await getVisibleLargeImageId(
|
||||
frontendUtils
|
||||
);
|
||||
await expect( page.locator( 'dialog' ) ).toBeVisible();
|
||||
} );
|
||||
|
||||
expect( newVisibleLargeImageId ).toBe( secondImageThumbnailId );
|
||||
test( 'should not open dialog when the setting is disable on the frontend', async ( {
|
||||
pageObject,
|
||||
page,
|
||||
editor,
|
||||
editorUtils,
|
||||
} ) => {
|
||||
await pageObject.addProductGalleryBlock( { cleanContent: true } );
|
||||
await editor.openDocumentSettingsSidebar();
|
||||
await pageObject.toggleFullScreenOnClickSetting( false );
|
||||
await editorUtils.saveTemplate();
|
||||
|
||||
await Promise.all( [
|
||||
page.goto( blockData.productPage, {
|
||||
waitUntil: 'domcontentloaded',
|
||||
} ),
|
||||
waitForJavascriptFrontendFileIsLoaded( page ),
|
||||
] );
|
||||
|
||||
await expect( page.locator( 'dialog' ) ).toBeHidden();
|
||||
|
||||
const mainImageBlock = await pageObject.getMainImageBlock( {
|
||||
page: 'frontend',
|
||||
} );
|
||||
|
||||
await mainImageBlock.click();
|
||||
|
||||
await expect( page.locator( 'dialog' ) ).toBeHidden();
|
||||
} );
|
||||
} );
|
||||
} );
|
||||
|
|
|
@ -2,21 +2,38 @@
|
|||
* External dependencies
|
||||
*/
|
||||
import { Page } from '@playwright/test';
|
||||
import { EditorUtils, FrontendUtils } from '@woocommerce/e2e-utils';
|
||||
import { Editor } from '@wordpress/e2e-test-utils-playwright';
|
||||
|
||||
const selectors = {
|
||||
editor: {
|
||||
zoomWhileHoveringSetting:
|
||||
"xpath=//label[contains(text(), 'Zoom while hovering')]/preceding-sibling::span/input",
|
||||
fullScreenOnClickSetting:
|
||||
"xpath=//label[contains(text(), 'Full-screen when clicked')]/preceding-sibling::span/input",
|
||||
},
|
||||
};
|
||||
|
||||
export class ProductGalleryPage {
|
||||
editor: Editor;
|
||||
page: Page;
|
||||
constructor( { editor, page }: { editor: Editor; page: Page } ) {
|
||||
frontendUtils: FrontendUtils;
|
||||
editorUtils: EditorUtils;
|
||||
constructor( {
|
||||
editor,
|
||||
page,
|
||||
frontendUtils,
|
||||
editorUtils,
|
||||
}: {
|
||||
editor: Editor;
|
||||
page: Page;
|
||||
frontendUtils: FrontendUtils;
|
||||
editorUtils: EditorUtils;
|
||||
} ) {
|
||||
this.editor = editor;
|
||||
this.page = page;
|
||||
this.frontendUtils = frontendUtils;
|
||||
this.editorUtils = editorUtils;
|
||||
}
|
||||
|
||||
async addProductGalleryBlock( { cleanContent = true } ) {
|
||||
|
@ -32,6 +49,24 @@ export class ProductGalleryPage {
|
|||
return this.page.locator( selectors.editor.zoomWhileHoveringSetting );
|
||||
}
|
||||
|
||||
getFullScreenOnClickSetting() {
|
||||
return this.page.locator( selectors.editor.fullScreenOnClickSetting );
|
||||
}
|
||||
|
||||
async toggleFullScreenOnClickSetting( enable: boolean ) {
|
||||
const button = this.page.locator(
|
||||
selectors.editor.fullScreenOnClickSetting
|
||||
);
|
||||
const isChecked = await button.isChecked();
|
||||
|
||||
// Toggle the checkbox if it's not in the desired state.
|
||||
if ( enable && ! isChecked ) {
|
||||
await button.click();
|
||||
} else if ( ! enable && isChecked ) {
|
||||
await button.click();
|
||||
}
|
||||
}
|
||||
|
||||
async toggleZoomWhileHoveringSetting( enable: boolean ) {
|
||||
const button = this.page.locator(
|
||||
selectors.editor.zoomWhileHoveringSetting
|
||||
|
@ -45,4 +80,57 @@ export class ProductGalleryPage {
|
|||
await button.click();
|
||||
}
|
||||
}
|
||||
|
||||
async getMainImageBlock( { page }: { page: 'frontend' | 'editor' } ) {
|
||||
const blockName = 'woocommerce/product-gallery-large-image';
|
||||
if ( page === 'frontend' ) {
|
||||
return (
|
||||
await this.frontendUtils.getBlockByName( blockName )
|
||||
).filter( {
|
||||
has: this.page.locator( ':visible' ),
|
||||
} );
|
||||
}
|
||||
return this.editorUtils.getBlockByName( blockName );
|
||||
}
|
||||
|
||||
async getThumbnailsBlock( { page }: { page: 'frontend' | 'editor' } ) {
|
||||
const blockName = 'woocommerce/product-gallery-thumbnails';
|
||||
if ( page === 'frontend' ) {
|
||||
return (
|
||||
await this.frontendUtils.getBlockByName( blockName )
|
||||
).filter( {
|
||||
has: this.page.locator( ':visible' ),
|
||||
} );
|
||||
}
|
||||
return this.editorUtils.getBlockByName( blockName );
|
||||
}
|
||||
|
||||
async getNextPreviousButtonsBlock( {
|
||||
page,
|
||||
}: {
|
||||
page: 'frontend' | 'editor';
|
||||
} ) {
|
||||
const blockName =
|
||||
'woocommerce/product-gallery-large-image-next-previous';
|
||||
if ( page === 'frontend' ) {
|
||||
return (
|
||||
await this.frontendUtils.getBlockByName( blockName )
|
||||
).filter( {
|
||||
has: this.page.locator( ':visible' ),
|
||||
} );
|
||||
}
|
||||
return this.editorUtils.getBlockByName( blockName );
|
||||
}
|
||||
|
||||
async getBlock( { page }: { page: 'frontend' | 'editor' } ) {
|
||||
const blockName = 'woocommerce/product-gallery';
|
||||
if ( page === 'frontend' ) {
|
||||
return (
|
||||
await this.frontendUtils.getBlockByName( blockName )
|
||||
).filter( {
|
||||
has: this.page.locator( ':visible' ),
|
||||
} );
|
||||
}
|
||||
return this.editorUtils.getBlockByName( blockName );
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue