Commit 5fb2602b13b for woocommerce

commit 5fb2602b13b3688b808e19860d5987992cc64e45
Author: Luigi Teschio <gigitux@gmail.com>
Date:   Wed Sep 2 16:53:04 2026 +0200

    Speed up block template customization end-to-end tests (#67561)

    * Speed up template customization end-to-end tests

    * Add changelog entry for template test optimization

    * add comment

    * improve e2e test

    * remove .only

diff --git a/plugins/woocommerce/changelog/optimize-template-customization-e2e-rest b/plugins/woocommerce/changelog/optimize-template-customization-e2e-rest
new file mode 100644
index 00000000000..6f8b916efa2
--- /dev/null
+++ b/plugins/woocommerce/changelog/optimize-template-customization-e2e-rest
@@ -0,0 +1,4 @@
+Significance: patch
+Type: dev
+
+Speed up block template customization end-to-end tests using REST API setup and cleanup.
diff --git a/plugins/woocommerce/tests/e2e/tests/blocks/templates/template-customization.block_theme.spec.ts b/plugins/woocommerce/tests/e2e/tests/blocks/templates/template-customization.block_theme.spec.ts
index 24e1a414585..f7fa4b4771a 100644
--- a/plugins/woocommerce/tests/e2e/tests/blocks/templates/template-customization.block_theme.spec.ts
+++ b/plugins/woocommerce/tests/e2e/tests/blocks/templates/template-customization.block_theme.spec.ts
@@ -21,6 +21,11 @@ test.describe( 'Template customization', () => {
 			testData.templateType === 'wp_template'
 				? 'template'
 				: 'template part';
+		const templateOrigin =
+			testData.templateType === 'wp_template'
+				? BLOCK_THEME_SLUG
+				: 'woocommerce/woocommerce';
+		const templateId = `${ templateOrigin }//${ testData.templatePath }`;

 		test( `"${ testData.templateName }" template can be modified and reverted`, async ( {
 			admin,
@@ -41,12 +46,8 @@ test.describe( 'Template customization', () => {
 					templateName: testData.templateName,
 				} );
 			} else {
-				const templateSlug =
-					testData.templateType === 'wp_template'
-						? BLOCK_THEME_SLUG
-						: 'woocommerce/woocommerce';
 				await admin.visitSiteEditor( {
-					postId: `${ templateSlug }//${ testData.templatePath }`,
+					postId: templateId,
 					postType: testData.templateType,
 					canvas: 'edit',
 				} );
@@ -80,12 +81,10 @@ test.describe( 'Template customization', () => {
 			await expect( page.getByText( userText ).first() ).toBeVisible();

 			// Verify the edition can be reverted.
-			await admin.visitSiteEditor( {
-				postType: testData.templateType,
-			} );
-			await editor.revertTemplate( {
-				templateName: testData.templateName,
-			} );
+			await requestUtils.revertTemplate(
+				testData.templateType,
+				templateId
+			);
 			await testData.visitPage( {
 				admin,
 				editor,
@@ -97,37 +96,22 @@ test.describe( 'Template customization', () => {
 		} );

 		if ( testData.fallbackTemplate ) {
-			test( `"${ testData.templateName }" template defaults to the "${ testData.fallbackTemplate.templateName }" template`, async ( {
+			const fallbackTemplate = testData.fallbackTemplate;
+
+			test( `"${ testData.templateName }" template defaults to the "${ fallbackTemplate.templateName }" template`, async ( {
 				admin,
 				frontendUtils,
 				requestUtils,
 				editor,
 				page,
 			} ) => {
-				const templateSlug =
-					testData.templateType === 'wp_template'
-						? BLOCK_THEME_SLUG
-						: 'woocommerce/woocommerce';
-				// Edit fallback template and verify changes are visible.
-				await admin.visitSiteEditor( {
-					postId: `${ templateSlug }//${ testData.fallbackTemplate?.templatePath }`,
-					postType: testData.templateType,
-					canvas: 'edit',
-				} );
-
-				await editor.canvas
-					.locator( 'body' )
-					.waitFor( { timeout: 20000 } );
-
-				await editor.insertBlock( {
-					name: 'core/paragraph',
-					attributes: {
-						content: fallbackTemplateUserText,
-					},
-				} );
-				await editor.saveSiteEditorEntities( {
-					isOnlyCurrentEntityDirty: true,
-				} );
+				// Customize the fallback template and verify changes are visible.
+				const fallbackTemplateId = `${ templateOrigin }//${ fallbackTemplate.templatePath }`;
+				await requestUtils.updateTemplateContent(
+					testData.templateType,
+					fallbackTemplateId,
+					`<!-- wp:paragraph --><p>${ fallbackTemplateUserText }</p><!-- /wp:paragraph -->`
+				);
 				await testData.visitPage( {
 					admin,
 					editor,
@@ -140,13 +124,10 @@ test.describe( 'Template customization', () => {
 				).toBeVisible();

 				// Verify the edition can be reverted.
-				await admin.visitSiteEditor( {
-					postType: testData.templateType,
-				} );
-
-				await editor.revertTemplate( {
-					templateName: testData.fallbackTemplate?.templateName || '',
-				} );
+				await requestUtils.revertTemplate(
+					testData.templateType,
+					fallbackTemplateId
+				);

 				await testData.visitPage( {
 					admin,
@@ -206,7 +187,6 @@ test.describe( 'Template customization', () => {
 				postType: testData.templateType,
 				canvas: 'edit',
 			} );
-
 			await editor.canvas.locator( 'body' ).waitFor( { timeout: 20000 } );

 			await editor.insertBlock( {
@@ -217,6 +197,17 @@ test.describe( 'Template customization', () => {
 				isOnlyCurrentEntityDirty: true,
 			} );

+			// Verify only the customized theme template is returned for this slug.
+			// See: https://github.com/woocommerce/woocommerce/issues/42220
+			const templates = await requestUtils.getTemplates(
+				testData.templateType
+			);
+			expect(
+				templates.filter(
+					( template ) => template.slug === testData.templatePath
+				)
+			).toHaveLength( 1 );
+
 			// Verify the template is the one modified by the user based on the theme.
 			await testData.visitPage( {
 				admin,
@@ -231,17 +222,13 @@ test.describe( 'Template customization', () => {
 			).toBeHidden();

 			// Revert edition and verify the user-modified WC template is used.
-			// Note: we need to revert it from the admin (instead of calling
-			// `deleteAllTemplates()`). This way, we verify there are no
-			// duplicate templates with the same name.
+			// Revert the exact template rather than selecting it by its display
+			// name, which can be shared by templates from different origins.
 			// See: https://github.com/woocommerce/woocommerce/issues/42220
-			await admin.visitSiteEditor( {
-				postType: testData.templateType,
-			} );
-
-			await editor.revertTemplate( {
-				templateName: testData.templateName,
-			} );
+			await requestUtils.revertTemplate(
+				testData.templateType,
+				`${ BLOCK_THEME_WITH_TEMPLATES_SLUG }//${ testData.templatePath }`
+			);

 			await testData.visitPage( {
 				admin,
diff --git a/plugins/woocommerce/tests/e2e/tests/blocks/templates/template-customization.block_theme_with_templates.spec.ts b/plugins/woocommerce/tests/e2e/tests/blocks/templates/template-customization.block_theme_with_templates.spec.ts
index 5b0aeb2f147..cb679a9ee2f 100644
--- a/plugins/woocommerce/tests/e2e/tests/blocks/templates/template-customization.block_theme_with_templates.spec.ts
+++ b/plugins/woocommerce/tests/e2e/tests/blocks/templates/template-customization.block_theme_with_templates.spec.ts
@@ -27,6 +27,7 @@ test.describe( 'Template customization', () => {
 			testData.templateType === 'wp_template'
 				? 'template'
 				: 'template part';
+		const templateId = `${ BLOCK_THEME_WITH_TEMPLATES_SLUG }//${ testData.templatePath }`;

 		test.describe( `${ testData.templateName } template`, () => {
 			test( "theme template has priority over WooCommerce's and can be modified", async ( {
@@ -38,7 +39,7 @@ test.describe( 'Template customization', () => {
 			} ) => {
 				// Edit the theme template.
 				await admin.visitSiteEditor( {
-					postId: `${ BLOCK_THEME_WITH_TEMPLATES_SLUG }//${ testData.templatePath }`,
+					postId: templateId,
 					postType: testData.templateType,
 					canvas: 'edit',
 				} );
@@ -76,12 +77,10 @@ test.describe( 'Template customization', () => {
 				).toBeVisible();

 				// Revert edition and verify the template from the theme is used.
-				await admin.visitSiteEditor( {
-					postType: testData.templateType,
-				} );
-				await editor.revertTemplate( {
-					templateName: testData.templateName,
-				} );
+				await requestUtils.revertTemplate(
+					testData.templateType,
+					templateId
+				);

 				await testData.visitPage( {
 					admin,
@@ -102,34 +101,22 @@ test.describe( 'Template customization', () => {
 			} );

 			if ( testData.fallbackTemplate ) {
-				test( `theme template has priority over user-modified ${ testData.fallbackTemplate.templateName } template`, async ( {
+				const fallbackTemplate = testData.fallbackTemplate;
+
+				test( `theme template has priority over user-modified ${ fallbackTemplate.templateName } template`, async ( {
 					admin,
 					frontendUtils,
 					requestUtils,
 					editor,
 					page,
 				} ) => {
-					// Edit default template and verify changes are not visible,
-					// as the theme template has priority.
-					await admin.visitSiteEditor( {
-						postId: `${ BLOCK_THEME_WITH_TEMPLATES_SLUG }//${ testData.fallbackTemplate?.templatePath }`,
-						postType: testData.templateType,
-						canvas: 'edit',
-					} );
-
-					await editor.canvas
-						.locator( 'body' )
-						.waitFor( { timeout: 20000 } );
-
-					await editor.insertBlock( {
-						name: 'core/paragraph',
-						attributes: {
-							content: fallbackTemplateUserText,
-						},
-					} );
-					await editor.saveSiteEditorEntities( {
-						isOnlyCurrentEntityDirty: true,
-					} );
+					// Customize the fallback template and verify changes are not
+					// visible, as the theme template has priority.
+					await requestUtils.updateTemplateContent(
+						testData.templateType,
+						`${ BLOCK_THEME_WITH_TEMPLATES_SLUG }//${ fallbackTemplate.templatePath }`,
+						`<!-- wp:paragraph --><p>${ fallbackTemplateUserText }</p><!-- /wp:paragraph -->`
+					);
 					await testData.visitPage( {
 						admin,
 						editor,
diff --git a/plugins/woocommerce/tests/e2e/utils/blocks/request-utils/index.ts b/plugins/woocommerce/tests/e2e/utils/blocks/request-utils/index.ts
index b3b473eeb56..c8ba4a883aa 100644
--- a/plugins/woocommerce/tests/e2e/utils/blocks/request-utils/index.ts
+++ b/plugins/woocommerce/tests/e2e/utils/blocks/request-utils/index.ts
@@ -8,7 +8,9 @@ import { RequestUtils as CoreRequestUtils } from '@wordpress/e2e-test-utils-play
  */
 import { createPostFromFile, PostCompiler } from './posts';
 import {
+	updateTemplateContent,
 	getTemplates,
+	getTemplate,
 	revertTemplate,
 	createTemplateFromFile,
 	TemplateCompiler,
@@ -16,8 +18,13 @@ import {
 import { resetFeatureFlag, setFeatureFlag } from './feature-flag';

 export class RequestUtils extends CoreRequestUtils {
+	/** @borrows updateTemplateContent as this.updateTemplateContent */
+	updateTemplateContent: typeof updateTemplateContent =
+		updateTemplateContent.bind( this );
 	/** @borrows getTemplates as this.getTemplates */
 	getTemplates: typeof getTemplates = getTemplates.bind( this );
+	/** @borrows getTemplate as this.getTemplate */
+	getTemplate: typeof getTemplate = getTemplate.bind( this );
 	/** @borrows revertTemplate as this.revertTemplate */
 	revertTemplate: typeof revertTemplate = revertTemplate.bind( this );
 	/** @borrows createPostFromFile as this.createPostFromFile */
diff --git a/plugins/woocommerce/tests/e2e/utils/blocks/request-utils/templates.ts b/plugins/woocommerce/tests/e2e/utils/blocks/request-utils/templates.ts
index 691926a43d2..e7d61ba3df2 100644
--- a/plugins/woocommerce/tests/e2e/utils/blocks/request-utils/templates.ts
+++ b/plugins/woocommerce/tests/e2e/utils/blocks/request-utils/templates.ts
@@ -19,41 +19,103 @@ export type WPTemplateType = 'wp_template' | 'wp_template_part';
 export interface WPTemplate {
 	wp_id: number;
 	id: string;
+	slug: string;
 	type: WPTemplateType;
+	origin: 'plugin' | 'theme' | null;
+	content: {
+		raw: string;
+	};
 }

 export interface TemplateCompiler {
 	compile: ( data?: unknown ) => Promise< WPTemplate >;
 }

+function getTemplateRestPath(
+	templateType: WPTemplateType,
+	templateId?: string
+) {
+	const endpoint =
+		templateType === 'wp_template' ? 'templates' : 'template-parts';
+
+	return `/wp/v2/${ endpoint }${ templateId ? `/${ templateId }` : '' }`;
+}
+
 /**
  * Retrieves all available templates.
  */
-export async function getTemplates( this: RequestUtils ) {
+export async function getTemplates(
+	this: RequestUtils,
+	templateType: WPTemplateType = 'wp_template'
+) {
 	const templates = await this.rest< WPTemplate[] >( {
 		method: 'GET',
-		path: '/wp/v2/templates',
+		path: getTemplateRestPath( templateType ),
 	} );

 	return templates;
 }

 /**
- * Reverts a template to its original state.
+ * Retrieves a template or template part.
  */
-export async function revertTemplate( this: RequestUtils, slug: string ) {
-	const restPath = `/wp/v2/templates/${ slug }`;
-
-	const template = await this.rest( {
+export async function getTemplate(
+	this: RequestUtils,
+	templateType: WPTemplateType,
+	templateId: string
+) {
+	return await this.rest< WPTemplate >( {
 		method: 'GET',
-		path: restPath,
+		path: getTemplateRestPath( templateType, templateId ),
+	} );
+}
+
+/**
+ * Updates the content of a template or template part.
+ */
+export async function updateTemplateContent(
+	this: RequestUtils,
+	templateType: WPTemplateType,
+	templateId: string,
+	content: string
+) {
+	return await this.rest< WPTemplate >( {
+		method: 'POST',
+		path: getTemplateRestPath( templateType, templateId ),
+		data: {
+			id: templateId,
+			content,
+		},
 	} );
+}
+
+/**
+ * Reverts a template to its original state.
+ */
+export async function revertTemplate(
+	this: RequestUtils,
+	templateType: WPTemplateType,
+	templateId: string
+) {
+	const restPath = getTemplateRestPath( templateType, templateId );
+	const template = await this.getTemplate( templateType, templateId );
+
+	// User-created templates have no underlying theme or plugin template to
+	// restore, so remove the custom template instead of resetting its source.
+	if ( template.origin === null ) {
+		await this.rest( {
+			method: 'DELETE',
+			path: restPath,
+			params: { force: true },
+		} );
+		return;
+	}

 	await this.rest( {
 		method: 'POST',
 		path: restPath,
 		data: {
-			id: slug,
+			id: templateId,
 			content: template.content.raw,
 			source: 'theme',
 		},