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();
+	} );
 } );