Commit 6c3a76da3b2 for woocommerce
commit 6c3a76da3b218b124ca016c3960e391a4323262c
Author: Vlad Olaru <vlad.olaru@automattic.com>
Date: Mon Sep 14 11:34:52 2026 +0300
[tests] Trim block email rendering-source E2E tests from three to one (#68632)
test(email): Trim block email rendering-source titles
order-emails-block-editor.spec.ts ran three browser titles over one
decision: which post a sent block email renders from. Two of them
sent a real mail only to observe a rule the renderer applies before
any mail exists — that an email with no saved post falls back to the
file template, and that an unpublished draft does not leak into a
sent email.
Both rules already have PHPUnit owners on trunk, in
BlockEmailRendererTest and IntegrationTest, and neither test is
changed here. Delete those two titles.
Keep the one title that is a journey rather than a rule: a merchant
customizes an email, saves it, and the mail that goes out carries
their copy. It now performs the draft setup the deleted title used
to do, so it still walks the lazy-draft path on editor open.
That makes it independent, and the file changes with it: the serial
mode goes, since nothing orders anything any more; the hooks clear
the email-to-post mapping option so a stale one cannot mislead the
editor; and the post-save wait now watches for the write to the
draft's own REST route instead of re-querying the collection by
slug.
Consolidates the mega-branch slice:
- Slice 075: test(email): Move block email rendering below E2E
Refs TESTOPS-288
Refs #68046
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
diff --git a/plugins/woocommerce/changelog/testops-288-block-email-rendering-source b/plugins/woocommerce/changelog/testops-288-block-email-rendering-source
new file mode 100644
index 00000000000..c0d3b73b7ba
--- /dev/null
+++ b/plugins/woocommerce/changelog/testops-288-block-email-rendering-source
@@ -0,0 +1,4 @@
+Significance: patch
+Type: dev
+Comment: Trim block email rendering-source coverage to one browser journey; two rules move to their PHPUnit owners.
+
diff --git a/plugins/woocommerce/tests/e2e/tests/email/order-emails-block-editor.spec.ts b/plugins/woocommerce/tests/e2e/tests/email/order-emails-block-editor.spec.ts
index 06daf70cbef..e84062e7380 100644
--- a/plugins/woocommerce/tests/e2e/tests/email/order-emails-block-editor.spec.ts
+++ b/plugins/woocommerce/tests/e2e/tests/email/order-emails-block-editor.spec.ts
@@ -15,14 +15,13 @@ import {
import { ADMIN_STATE_PATH } from '../../playwright.config';
import { expect, test as baseTest } from '../../fixtures/fixtures';
import { admin } from '../../test-data/data';
-import { setOption } from '../../utils/options';
+import { deleteOption, setOption } from '../../utils/options';
import { accessTheEmailEditor, expectEmail } from '../../utils/email';
/**
- * End-to-end coverage for file-first block email rendering (WOOPLUG-6171):
- * with the block email editor enabled, a transactional email renders from its
- * file template until the merchant edits AND saves it — a draft scratchpad
- * (even one carrying unsaved edits) never affects what customers receive.
+ * End-to-end coverage for the installed block-email customization seam: a
+ * merchant opens the file-backed editor, edits its scratchpad, saves it, and
+ * receives the published customization in a transactional email.
*
* Uses the customer "Processing order" email; delivery is asserted through the
* WP Mail Logging inbox like the classic `order-emails.spec.ts`.
@@ -31,17 +30,14 @@ import { accessTheEmailEditor, expectEmail } from '../../utils/email';
const EMAIL_LISTING_TITLE = 'Order confirmation';
const EMAIL_TYPE = 'customer_processing_order';
const SUBJECT_REGEX = /Your .+ order has been received!/;
-// Footer text unique to the `wooemailtemplate` block template — proves the
-// email was rendered through the block pipeline, not the classic one.
-const BLOCK_TEMPLATE_FOOTER = 'All Rights Reserved';
const DRAFT_MARKER = 'WOOPLUG6171_DRAFT_ONLY_MARKER';
+const EMAIL_POST_MAPPING_OPTION =
+ 'woocommerce_email_templates_customer_processing_order_post_id';
const test = baseTest.extend( {
storageState: ADMIN_STATE_PATH,
} );
-test.describe.configure( { mode: 'serial' } );
-
const createAdminApiClient = ( baseURL: string ) =>
createClient( baseURL, {
type: 'basic',
@@ -75,6 +71,10 @@ test.beforeAll( async ( { baseURL } ) => {
);
// Start from a clean slate in case another spec left a post behind.
await deleteEmailTypePosts( baseURL );
+ // A mapping can outlive its email post and later point at an unrelated post
+ // after an environment restore reuses the numeric ID. Remove this email
+ // type's mapping so the real Edit action creates a fresh `woo_email` draft.
+ await deleteOption( request, baseURL, EMAIL_POST_MAPPING_OPTION );
} );
test.afterAll( async ( { baseURL } ) => {
@@ -87,6 +87,7 @@ test.afterAll( async ( { baseURL } ) => {
// Delete posts while the feature is still enabled so the
// `before_delete_post` hook also clears the email type → post mapping.
await deleteEmailTypePosts( baseURL );
+ await deleteOption( request, baseURL, EMAIL_POST_MAPPING_OPTION );
await setOption(
request,
baseURL,
@@ -124,26 +125,12 @@ const triggerOrderEmailAndOpenLog = async ( page, restApi ) => {
return modalContent.locator( 'iframe' ).contentFrame();
};
-test( 'uncustomized email is sent from the file template', async ( {
- page,
- restApi,
-} ) => {
- const emailBody = await triggerOrderEmailAndOpenLog( page, restApi );
-
- await expect( emailBody.locator( 'body' ) ).toContainText(
- 'is now being processed'
- );
- await expect( emailBody.locator( 'body' ) ).toContainText(
- BLOCK_TEMPLATE_FOOTER
- );
-} );
-
-test( 'draft edits do not affect sent emails until saved', async ( {
+test( 'saved email is sent from the customized post', async ( {
page,
restApi,
} ) => {
- // Opening the editor lazily creates the draft scratchpad with the file
- // template content.
+ // Opening the editor creates this email type's draft scratchpad from the
+ // canonical file template.
await accessTheEmailEditor( page, EMAIL_LISTING_TITLE );
await expect(
page
@@ -152,8 +139,6 @@ test( 'draft edits do not affect sent emails until saved', async ( {
.getByText( 'Thank you for your order' )
).toBeVisible();
- // Write an edit into the draft via REST — a deterministic stand-in for
- // the editor's remote autosave (which fires on a 60s interval).
const drafts = await restApi.get( `${ WP_API_PATH }/woo_email`, {
status: 'draft',
context: 'edit',
@@ -163,25 +148,12 @@ test( 'draft edits do not affect sent emails until saved', async ( {
( post.slug as string ).startsWith( EMAIL_TYPE )
);
expect( draft ).toBeTruthy();
+ expect( Number.isSafeInteger( draft.id ) && draft.id > 0 ).toBe( true );
await restApi.post( `${ WP_API_PATH }/woo_email/${ draft.id }`, {
content: `${ draft.content.raw }\n<!-- wp:paragraph --><p>${ DRAFT_MARKER }</p><!-- /wp:paragraph -->`,
} );
- const emailBody = await triggerOrderEmailAndOpenLog( page, restApi );
-
- await expect( emailBody.locator( 'body' ) ).toContainText(
- BLOCK_TEMPLATE_FOOTER
- );
- await expect( emailBody.locator( 'body' ) ).not.toContainText(
- DRAFT_MARKER
- );
-} );
-
-test( 'saved email is sent from the customized post', async ( {
- page,
- restApi,
-} ) => {
- // The editor reuses the edited draft (edits must survive reopening).
+ // The real listing must reopen that same edited scratchpad before Save.
await accessTheEmailEditor( page, EMAIL_LISTING_TITLE );
await expect(
page
@@ -191,22 +163,23 @@ test( 'saved email is sent from the customized post', async ( {
).toBeVisible();
// Save publishes the draft in the background, making it the rendering
- // source.
+ // source. Observe the exact post write and then poll the same draft ID.
+ const saveResponse = page.waitForResponse( ( response ) => {
+ const url = new URL( response.url() );
+ return (
+ url.pathname.endsWith( `/wp/v2/woo_email/${ draft.id }` ) &&
+ [ 'POST', 'PUT' ].includes( response.request().method() ) &&
+ response.ok()
+ );
+ } );
await page.getByRole( 'button', { name: 'Save', exact: true } ).click();
+ await saveResponse;
- const drafts = await restApi.get( `${ WP_API_PATH }/woo_email`, {
- status: 'publish,draft',
- per_page: 100,
- } );
- const post = drafts.data.find( ( item ) =>
- ( item.slug as string ).startsWith( EMAIL_TYPE )
- );
- expect( post ).toBeTruthy();
await expect
.poll(
async () => {
const response = await restApi.get(
- `${ WP_API_PATH }/woo_email/${ post.id }`,
+ `${ WP_API_PATH }/woo_email/${ draft.id }`,
{ context: 'edit' }
);
return response.data.status;