Commit cb780991a4e for woocommerce
commit cb780991a4e00a5bc870940ca05435ce2ebc009b
Author: Francesco <frosso@users.noreply.github.com>
Date: Fri Aug 28 22:58:30 2026 +0200
fix: type of Store API item_data hidden flag (#68159)
diff --git a/plugins/woocommerce/changelog/fix-store-api-item-data-hidden-type b/plugins/woocommerce/changelog/fix-store-api-item-data-hidden-type
new file mode 100644
index 00000000000..bfe2e8e8268
--- /dev/null
+++ b/plugins/woocommerce/changelog/fix-store-api-item-data-hidden-type
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Correct the public TypeScript type for the Store API item_data `hidden` flag, which arrives as a string rather than a boolean.
diff --git a/plugins/woocommerce/client/blocks/assets/js/base/components/cart-checkout/product-details/test/index.js b/plugins/woocommerce/client/blocks/assets/js/base/components/cart-checkout/product-details/test/index.js
index 18a8a7745e1..26cfc9d16da 100644
--- a/plugins/woocommerce/client/blocks/assets/js/base/components/cart-checkout/product-details/test/index.js
+++ b/plugins/woocommerce/client/blocks/assets/js/base/components/cart-checkout/product-details/test/index.js
@@ -54,7 +54,7 @@ describe( 'ProductDetails', () => {
test( 'should not render hidden details', () => {
const details = [
- { name: 'Lorem', value: 'Ipsum', hidden: true },
+ { name: 'Lorem', value: 'Ipsum', hidden: '1' },
{ name: 'LOREM', value: 'Ipsum', display: 'IPSUM' },
{ name: 'LOREM 2', value: 'Ipsum2', display: 'IPSUM 2' },
];
@@ -83,10 +83,24 @@ describe( 'ProductDetails', () => {
expect( screen.getByText( 'IPSUM 2' ) ).toBeInTheDocument();
} );
+ // The Store API runs every item_data value through wp_kses_post(), which
+ // string-coerces, so an extension's boolean arrives as '1' or ''.
+ test( 'should treat the string hidden flags the Store API actually sends', () => {
+ const details = [
+ { name: 'Hidden', value: 'Ipsum', hidden: '1' },
+ { name: 'Visible', value: 'Ipsum2', hidden: '' },
+ ];
+
+ render( <ProductDetails details={ details } /> );
+
+ expect( screen.queryByText( 'Hidden:' ) ).not.toBeInTheDocument();
+ expect( screen.getByText( 'Visible:' ) ).toBeInTheDocument();
+ } );
+
test( 'should not render anything if all details are hidden', () => {
const details = [
- { name: 'Lorem', value: 'Ipsum', hidden: true },
- { name: 'LOREM', value: 'Ipsum', display: 'IPSUM', hidden: true },
+ { name: 'Lorem', value: 'Ipsum', hidden: '1' },
+ { name: 'LOREM', value: 'Ipsum', display: 'IPSUM', hidden: '1' },
];
const { container } = render( <ProductDetails details={ details } /> );
diff --git a/plugins/woocommerce/client/blocks/packages/public-api/types/type-defs/product-response.ts b/plugins/woocommerce/client/blocks/packages/public-api/types/type-defs/product-response.ts
index 55dbe6f2530..b6562c9d871 100644
--- a/plugins/woocommerce/client/blocks/packages/public-api/types/type-defs/product-response.ts
+++ b/plugins/woocommerce/client/blocks/packages/public-api/types/type-defs/product-response.ts
@@ -13,7 +13,13 @@ export interface ProductResponseItemPrices extends CurrencyResponse {
export interface ProductResponseItemBaseData {
value: string;
display?: string;
- hidden?: boolean;
+ /**
+ * Truthy marks the entry hidden. Always a string: the Store API runs every
+ * `item_data` value through `wp_kses_post()`, which string-coerces, so a
+ * boolean set by an extension arrives as `"1"` or `""`. Test it for
+ * truthiness — comparing against `true` or `1` can never match.
+ */
+ hidden?: string;
className?: string;
}