Commit 3b385853330 for woocommerce

commit 3b38585333098025113f42d2e1ca46a54d78954e
Author: Brandon Kraft <public@brandonkraft.com>
Date:   Tue Aug 4 09:29:52 2026 -0600

    e2e-utils-playwright: harden getCanvas beyond trunk's iframe wait (#65326)

diff --git a/packages/js/e2e-utils-playwright/changelog/fix-get-canvas-iframe-wait b/packages/js/e2e-utils-playwright/changelog/fix-get-canvas-iframe-wait
new file mode 100644
index 00000000000..c6a76deb823
--- /dev/null
+++ b/packages/js/e2e-utils-playwright/changelog/fix-get-canvas-iframe-wait
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Harden `getCanvas` so the non-iframed editor path also waits for the canvas, hidden leftover iframes are ignored, and a missing canvas fails loudly instead of silently resolving to the wrong document.
diff --git a/packages/js/e2e-utils-playwright/src/editor.ts b/packages/js/e2e-utils-playwright/src/editor.ts
index d0593de65f9..13099b0760f 100644
--- a/packages/js/e2e-utils-playwright/src/editor.ts
+++ b/packages/js/e2e-utils-playwright/src/editor.ts
@@ -92,26 +92,35 @@ export const openEditorSettings = async ( {
 /**
  * Returns the editor canvas frame for Gutenberg interactions.
  *
- * The Gutenberg editor content can be contained within an iframe in some contexts.
- * This helper function returns the content frame of the editor canvas iframe if it exists,
- * or falls back to the main page if the iframe isn't present.
+ * The Gutenberg editor mounts either inside an `iframe[name="editor-canvas"]`
+ * (modern site/post editor) or directly on the outer page (non-iframed
+ * contexts, e.g. accessibility mode). Recent Gutenberg
+ * builds mount the iframe slightly after initial paint, so callers that resolve
+ * the canvas before the iframe attaches end up running locators against the
+ * outer page and timing out inside the editor.
+ *
+ * Resolves as soon as either surface becomes visible, using a union selector
+ * so neither path incurs a hardcoded probe timeout. If neither surface appears
+ * within Playwright's default timeout, the underlying `waitFor` throws and the
+ * test fails loudly rather than silently degrading to the wrong document.
  *
  * @param page - The Playwright page object
  * @return The editor canvas frame or the original page
  */
 export const getCanvas = async ( page: Page ): Promise< EditorCanvas > => {
-	const iframeLocator = page.locator( 'iframe[name="editor-canvas"]' );
-	await iframeLocator.waitFor( { state: 'attached' } ).catch( ( error ) => {
-		console.warn(
-			'The editor canvas iframe was not found. Falling back to the page context.',
-			error
-		);
-	} );
+	const canvasLocator = page
+		.locator(
+			'iframe[name="editor-canvas"]:visible, .wp-block-post-content:visible'
+		)
+		.first();

-	if ( ( await iframeLocator.count() ) > 0 ) {
-		return iframeLocator.contentFrame();
-	}
-	return page;
+	await canvasLocator.waitFor();
+
+	const isFramed = await canvasLocator.evaluate(
+		( node ) => node.tagName === 'IFRAME'
+	);
+
+	return isFramed ? canvasLocator.contentFrame() : page;
 };

 /**