From 72f75edf58781da02280f3792015cf57aa00639f Mon Sep 17 00:00:00 2001 From: Patrick Rauland Date: Wed, 13 Mar 2024 17:43:44 -0600 Subject: [PATCH] Adding accessible markup to sale price. (#44413) * Adding accessible markup to sale price. See #31099 This PR adds accessible markup to the sale price. A user who only uses screen reader software can now hear and understand the original price as well as the current price. This is important for accessibility. Full issue: https://github.com/woocommerce/woocommerce/issues/31099 * Improving sale price string formatting & localization #31099 This PR merges in feedback from the WooCommerce team. * Improving string translation & output. Giving RTL languages more customization with the price in the translatable string. * Formatting regular price & sale price at the top and then inserting into the HTML below. This prevents some sloppy logic where you might print out a blank del or ins tag. * Swapping esc_html & sprintf #31099 Reversed the esc_html() and sprintf(). This is intentional because if translations accidentally include some HTML, that could break things. Also, stripping HTML tags in $formatted_regular_price so that the end result in the screen-reader-text span is just plain text. * Adjusting white space #31099 Mostly removing white space for the lint checker * Adding translator comments #31099 Adding translator comments for lint * Add changelog * Fix some PHPCS violations * Fix unit tests * Adjust E2E test --------- Co-authored-by: Jorge Torres --- plugins/woocommerce/changelog/31099 | 4 ++++ .../includes/wc-formatting-functions.php | 23 ++++++++++++++++++- .../tests/merchant/product-edit.spec.js | 2 +- .../unit-tests/formatting/functions.php | 2 +- .../tests/legacy/unit-tests/product/data.php | 4 ++-- 5 files changed, 30 insertions(+), 5 deletions(-) create mode 100644 plugins/woocommerce/changelog/31099 diff --git a/plugins/woocommerce/changelog/31099 b/plugins/woocommerce/changelog/31099 new file mode 100644 index 00000000000..c7d42720bfe --- /dev/null +++ b/plugins/woocommerce/changelog/31099 @@ -0,0 +1,4 @@ +Significance: minor +Type: enhancement + +Improve accessibility of sale price markup. diff --git a/plugins/woocommerce/includes/wc-formatting-functions.php b/plugins/woocommerce/includes/wc-formatting-functions.php index 52084b31291..2549d909bfb 100644 --- a/plugins/woocommerce/includes/wc-formatting-functions.php +++ b/plugins/woocommerce/includes/wc-formatting-functions.php @@ -1290,7 +1290,28 @@ function wc_format_stock_quantity_for_display( $stock_quantity, $product ) { * @return string */ function wc_format_sale_price( $regular_price, $sale_price ) { - $price = ' ' . ( is_numeric( $sale_price ) ? wc_price( $sale_price ) : $sale_price ) . ''; + // Format the prices. + $formatted_regular_price = is_numeric( $regular_price ) ? wc_price( $regular_price ) : $regular_price; + $formatted_sale_price = is_numeric( $sale_price ) ? wc_price( $sale_price ) : $sale_price; + + // Strikethrough pricing. + $price = ' '; + + // For accessibility (a11y) we'll also display that information to screen readers. + $price .= ''; + // translators: %s is a product's regular price. + $price .= esc_html( sprintf( __( 'Original price was: %s.', 'woocommerce' ), wp_strip_all_tags( $formatted_regular_price ) ) ); + $price .= ''; + + // Add the sale price. + $price .= ''; + + // For accessibility (a11y) we'll also display that information to screen readers. + $price .= ''; + // translators: %s is a product's current (sale) price. + $price .= esc_html( sprintf( __( 'Current price is: %s.', 'woocommerce' ), wp_strip_all_tags( $formatted_sale_price ) ) ); + $price .= ''; + return apply_filters( 'woocommerce_format_sale_price', $price, $regular_price, $sale_price ); } diff --git a/plugins/woocommerce/tests/e2e-pw/tests/merchant/product-edit.spec.js b/plugins/woocommerce/tests/e2e-pw/tests/merchant/product-edit.spec.js index 9564a72222d..a9c8501b013 100644 --- a/plugins/woocommerce/tests/e2e-pw/tests/merchant/product-edit.spec.js +++ b/plugins/woocommerce/tests/e2e-pw/tests/merchant/product-edit.spec.js @@ -163,7 +163,7 @@ baseTest.describe( 'Products > Edit Product', () => { .soft( page.locator( 'p' ).locator( 'del' ) ) .toHaveText( `$${ expectedRegularPrice }` ); await expect - .soft( page.locator( 'p' ).getByRole( 'insertion' ) ) + .soft( page.locator( 'p' ).locator( 'ins' ) ) .toHaveText( `$${ expectedSalePrice }` ); await expect .soft( page.getByText( `${ expectedStockQty } in stock` ) ) diff --git a/plugins/woocommerce/tests/legacy/unit-tests/formatting/functions.php b/plugins/woocommerce/tests/legacy/unit-tests/formatting/functions.php index 5759750c101..a2f57041ffe 100644 --- a/plugins/woocommerce/tests/legacy/unit-tests/formatting/functions.php +++ b/plugins/woocommerce/tests/legacy/unit-tests/formatting/functions.php @@ -932,7 +932,7 @@ class WC_Tests_Formatting_Functions extends WC_Unit_Test_Case { * @since 3.3.0 */ public function test_wc_format_sale_price() { - $this->assertEquals( ' $5.00', wc_format_sale_price( '10', '5' ) ); + $this->assertEquals( ' Original price was: $10.00.Current price is: $5.00.', wc_format_sale_price( '10', '5' ) ); } /** diff --git a/plugins/woocommerce/tests/legacy/unit-tests/product/data.php b/plugins/woocommerce/tests/legacy/unit-tests/product/data.php index ae732e1a3f5..dab7f83d71f 100644 --- a/plugins/woocommerce/tests/legacy/unit-tests/product/data.php +++ b/plugins/woocommerce/tests/legacy/unit-tests/product/data.php @@ -262,11 +262,11 @@ class WC_Tests_Product_Data extends WC_Unit_Test_Case { $product = wc_get_product( $product1_id ); $this->assertEquals( $product1_id, $product->get_id() ); - $this->assertEquals( ' $7.00', $product->get_price_html() ); + $this->assertEquals( ' Original price was: $10.00.Current price is: $7.00.', $product->get_price_html() ); $product = wc_get_product( $product2_id ); $this->assertEquals( $product2_id, $product->get_id() ); - $this->assertEquals( ' $16.00', $product->get_price_html() ); + $this->assertEquals( ' Original price was: $20.00.Current price is: $16.00.', $product->get_price_html() ); $product = wc_get_product( $product3_id ); $this->assertEquals( $product3_id, $product->get_id() );