Commit 0fdedbb913c for woocommerce
commit 0fdedbb913c6e82e1add6e271708b054b9512cac
Author: Faisal Ahammad <faisalahammad24@gmail.com>
Date: Tue Jul 14 16:15:57 2026 +0600
fix: show billing name for guest orders in Home Orders panel (#66279)
* fix: show billing name for guest orders in Home Orders panel
Fixes #59959
* fix(homescreen): sanitize guest + registered customer name in Orders panel
- Move angle-bracket sanitization into single sanitizeName() applied to
the resolved customerName, so registered customer.name is sanitized too
(previously only the guest billing fallback was).
- Use optional chaining (customer?.name) for name lookup.
- Rewrite comment to explain why brackets are stripped.
- Add Jest regression test for angle-bracket sanitization.
Addresses PR review feedback.
* fix(homescreen): correct sanitized-name assertion in guest order test
sanitizeName only strips angle brackets, slash stays. Test expected
'bscriptb Doe' but actual output is 'bscript/b Doe'.
Addresses CodeRabbit feedback on PR #66279.
diff --git a/plugins/woocommerce/changelog/59959-fix-guest-order-name-home-orders-panel b/plugins/woocommerce/changelog/59959-fix-guest-order-name-home-orders-panel
new file mode 100644
index 00000000000..8f86b3f2774
--- /dev/null
+++ b/plugins/woocommerce/changelog/59959-fix-guest-order-name-home-orders-panel
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Show the billing name for guest orders in the WooCommerce Home Orders activity panel instead of leaving the name blank.
diff --git a/plugins/woocommerce/client/admin/client/homescreen/activity-panel/orders/index.js b/plugins/woocommerce/client/admin/client/homescreen/activity-panel/orders/index.js
index e794dbf9912..b313d5ac499 100644
--- a/plugins/woocommerce/client/admin/client/homescreen/activity-panel/orders/index.js
+++ b/plugins/woocommerce/client/admin/client/homescreen/activity-panel/orders/index.js
@@ -74,9 +74,7 @@ function renderOrders( orders, customers, getFormattedOrderTotal ) {
return renderEmptyCard();
}
- const getCustomerString = ( customer ) => {
- const { name } = customer || {};
-
+ const getCustomerString = ( name ) => {
if ( ! name ) {
return '';
}
@@ -89,6 +87,7 @@ function renderOrders( orders, customers, getFormattedOrderTotal ) {
id: orderId,
number: orderNumber,
customer_id: customerId,
+ billing,
} = order;
const customer =
customers.find( ( c ) => c.user_id === customerId ) || {};
@@ -102,11 +101,21 @@ function renderOrders( orders, customers, getFormattedOrderTotal ) {
: getAdminLink( 'user-edit.php?user_id=' + customer.id );
}
+ // Guest orders have no customer record; fall back to the billing name.
+ // createInterpolateElement parses <word> as a token, so strip angle
+ // brackets from the name to keep it from being read as markup.
+ const sanitizeName = ( name ) =>
+ ( name || '' ).replace( /[<>]/g, '' ).trim();
+ const guestName = billing
+ ? `${ billing.first_name || '' } ${ billing.last_name || '' }`
+ : '';
+ const customerName = sanitizeName( customer?.name || guestName );
+
const formattedString = sprintf(
/* translators: 1: order number, 2: customer name */
__( '<orderLink>Order #%1$s</orderLink> %2$s', 'woocommerce' ),
orderNumber,
- getCustomerString( customer )
+ getCustomerString( customerName )
);
return (
@@ -218,6 +227,7 @@ function OrdersPanel( { unreadOrdersCount, orderStatuses } ) {
'status',
'total',
'customer',
+ 'billing',
'line_items',
'customer_id',
'date_created_gmt',
diff --git a/plugins/woocommerce/client/admin/client/homescreen/activity-panel/orders/test/index.js b/plugins/woocommerce/client/admin/client/homescreen/activity-panel/orders/test/index.js
index a779b5c21bc..7515eedb7c2 100644
--- a/plugins/woocommerce/client/admin/client/homescreen/activity-panel/orders/test/index.js
+++ b/plugins/woocommerce/client/admin/client/homescreen/activity-panel/orders/test/index.js
@@ -130,4 +130,97 @@ describe( 'OrdersPanel', () => {
);
expect( getByText( 'BTC123' ) ).toBeInTheDocument();
} );
+
+ it( 'should show the billing name for a guest order', () => {
+ useSelect.mockReturnValue( {
+ orders: [
+ {
+ total: 123,
+ id: 1,
+ number: 1,
+ customer_id: 0,
+ billing: {
+ first_name: 'Jane',
+ last_name: 'Doe',
+ },
+ },
+ ],
+ isError: false,
+ isRequesting: false,
+ } );
+
+ render( <OrdersPanel orderStatuses={ [] } unreadOrdersCount={ 1 } /> );
+ expect( screen.getByText( 'Jane Doe' ) ).toBeInTheDocument();
+ } );
+
+ it( 'should show no name for a guest order with a blank billing name', () => {
+ useSelect.mockReturnValue( {
+ orders: [
+ {
+ total: 123,
+ id: 1,
+ number: 1,
+ customer_id: 0,
+ billing: {
+ first_name: '',
+ last_name: '',
+ },
+ },
+ ],
+ isError: false,
+ isRequesting: false,
+ } );
+
+ render( <OrdersPanel orderStatuses={ [] } unreadOrdersCount={ 1 } /> );
+ expect( screen.getByText( 'Order #1' ) ).toBeInTheDocument();
+ } );
+
+ it( 'should prefer the registered customer name over the billing name', () => {
+ useSelect.mockReturnValue( {
+ orders: [
+ {
+ total: 123,
+ id: 1,
+ number: 1,
+ customer_id: 5,
+ billing: {
+ first_name: 'Jane',
+ last_name: 'Doe',
+ },
+ },
+ ],
+ customerItems: new Map( [
+ [ 5, { id: 5, user_id: 5, name: 'Registered Customer' } ],
+ ] ),
+ isError: false,
+ isRequesting: false,
+ } );
+
+ render( <OrdersPanel orderStatuses={ [] } unreadOrdersCount={ 1 } /> );
+ expect( screen.getByText( 'Registered Customer' ) ).toBeInTheDocument();
+ expect( screen.queryByText( 'Jane Doe' ) ).not.toBeInTheDocument();
+ } );
+
+ it( 'should strip angle brackets from a guest billing name', () => {
+ useSelect.mockReturnValue( {
+ orders: [
+ {
+ total: 123,
+ id: 1,
+ number: 1,
+ customer_id: 0,
+ billing: {
+ first_name: '<b>script</b>',
+ last_name: 'Doe',
+ },
+ },
+ ],
+ isError: false,
+ isRequesting: false,
+ } );
+
+ render( <OrdersPanel orderStatuses={ [] } unreadOrdersCount={ 1 } /> );
+ expect( screen.getByText( 'bscript/b Doe' ) ).toBeInTheDocument();
+ expect( screen.queryByText( /</ ) ).not.toBeInTheDocument();
+ } );
} );