Commit 456580a9490 for woocommerce
commit 456580a94903d43ba9e7cfebe7579137cec1cf5c
Author: Luigi Teschio <gigitux@gmail.com>
Date: Thu May 21 13:52:18 2026 +0200
Fix variation table edit links (#65241)
* Fix variation table edit links
* Add changelog entry for variation edit link fix
diff --git a/packages/js/experimental-products-app/changelog/fix-variation-parent-edit-link b/packages/js/experimental-products-app/changelog/fix-variation-parent-edit-link
new file mode 100644
index 00000000000..910b36551bf
--- /dev/null
+++ b/packages/js/experimental-products-app/changelog/fix-variation-parent-edit-link
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Fix variation table edit links to open the parent product.
diff --git a/packages/js/experimental-products-app/src/dataviews-actions/actions.test.tsx b/packages/js/experimental-products-app/src/dataviews-actions/actions.test.tsx
index e23450ea725..1403ff3656e 100644
--- a/packages/js/experimental-products-app/src/dataviews-actions/actions.test.tsx
+++ b/packages/js/experimental-products-app/src/dataviews-actions/actions.test.tsx
@@ -343,6 +343,37 @@ describe( 'product list actions', () => {
} );
} );
+ it( 'opens the parent product editor when the Edit action is triggered for a variation', () => {
+ const { result } = renderHook( () => useProductActions() );
+ const editProductAction = result.current.find(
+ ( action ) => action.id === 'edit-product'
+ );
+
+ expect( editProductAction ).toBeDefined();
+
+ if ( ! editProductAction ) {
+ throw new Error( 'Edit action not found.' );
+ }
+
+ const originalLocation = window.location;
+ Object.defineProperty( window, 'location', {
+ writable: true,
+ value: { href: '' },
+ } );
+
+ getCallbackAction( editProductAction ).callback( [ blueVariation ], {
+ onActionPerformed,
+ } );
+
+ expect( window.location.href ).toBe( 'post.php?post=78&action=edit' );
+ expect( onActionPerformed ).toHaveBeenCalledWith( [ blueVariation ] );
+
+ Object.defineProperty( window, 'location', {
+ writable: true,
+ value: originalLocation,
+ } );
+ } );
+
it( 'duplicates products through the WooCommerce duplicate endpoint', async () => {
const duplicatedProduct = {
...product,
diff --git a/packages/js/experimental-products-app/src/dataviews-actions/actions.tsx b/packages/js/experimental-products-app/src/dataviews-actions/actions.tsx
index c301ceec29a..db160646783 100644
--- a/packages/js/experimental-products-app/src/dataviews-actions/actions.tsx
+++ b/packages/js/experimental-products-app/src/dataviews-actions/actions.tsx
@@ -24,7 +24,10 @@ import { useMemo } from '@wordpress/element';
*/
import type { ProductEntityRecord } from '../fields/types';
import { unlock } from '../lock-unlock';
-import { getProductListNavigationPath } from '../product-list/utils';
+import {
+ getProductEditPostId,
+ getProductListNavigationPath,
+} from '../product-list/utils';
const { useHistory, useLocation } = unlock( routerPrivateApis );
@@ -189,7 +192,7 @@ export const editAction = (): Action< ProductEntityRecord > => ( {
if ( product ) {
window.location.href = getAdminLink(
addQueryArgs( 'post.php', {
- post: product.id,
+ post: getProductEditPostId( product ),
action: 'edit',
} )
);
diff --git a/packages/js/experimental-products-app/src/product-list/index.tsx b/packages/js/experimental-products-app/src/product-list/index.tsx
index 1a060c51fb1..40c1df7c8ec 100644
--- a/packages/js/experimental-products-app/src/product-list/index.tsx
+++ b/packages/js/experimental-products-app/src/product-list/index.tsx
@@ -28,6 +28,7 @@ import {
import { productFields } from './fields';
import {
getItemId,
+ getProductEditPostId,
getProductListNavigationPath,
getProductListTab,
getProductsWithEmbeddedVariations,
@@ -318,7 +319,7 @@ export default function ProductList( {
{ ...props }
href={ getAdminLink(
addQueryArgs( 'post.php', {
- post: item.id,
+ post: getProductEditPostId( item ),
action: 'edit',
} )
) }
diff --git a/packages/js/experimental-products-app/src/product-list/utils.test.ts b/packages/js/experimental-products-app/src/product-list/utils.test.ts
index c9643ecc516..d0614da8d12 100644
--- a/packages/js/experimental-products-app/src/product-list/utils.test.ts
+++ b/packages/js/experimental-products-app/src/product-list/utils.test.ts
@@ -8,6 +8,7 @@ import type { View } from '@wordpress/dataviews';
*/
import type { ProductEntityRecord } from '../fields/types';
import {
+ getProductEditPostId,
hasActiveProductListSearchOrFilters,
getProductListNavigationPath,
getProductsWithEmbeddedVariations,
@@ -67,6 +68,20 @@ describe( 'product list utils', () => {
} );
} );
+ describe( 'getProductEditPostId', () => {
+ it( 'returns the product ID for parent products', () => {
+ expect( getProductEditPostId( createProduct( 1 ) ) ).toBe( 1 );
+ } );
+
+ it( 'returns the parent product ID for variations', () => {
+ expect( getProductEditPostId( createProduct( 2, 1 ) ) ).toBe( 1 );
+ } );
+
+ it( 'falls back to the variation ID when a parent ID is missing', () => {
+ expect( getProductEditPostId( createProduct( 2, 0 ) ) ).toBe( 2 );
+ } );
+ } );
+
describe( 'getProductsWithEmbeddedVariations', () => {
it( 'adds embedded variations after their parent product', () => {
const variation = createProduct( 2, 1 );
diff --git a/packages/js/experimental-products-app/src/product-list/utils.ts b/packages/js/experimental-products-app/src/product-list/utils.ts
index 189d0e38a8c..eabdcb3aee9 100644
--- a/packages/js/experimental-products-app/src/product-list/utils.ts
+++ b/packages/js/experimental-products-app/src/product-list/utils.ts
@@ -33,6 +33,10 @@ export function getItemId( item: ProductEntityRecord ) {
return item.id.toString();
}
+export function getProductEditPostId( item: ProductEntityRecord ) {
+ return item.parent_id && item.parent_id > 0 ? item.parent_id : item.id;
+}
+
export function getProductsWithEmbeddedVariations(
items: ProductEntityRecord[]
): ProductEntityRecord[] {