Skip to content

Commit a7b4631

Browse files
fix: attribute selection from PDPs with tokenized ECE (#10306)
Co-authored-by: Brett Shumaker <[email protected]>
1 parent 6d62c07 commit a7b4631

File tree

3 files changed

+235
-18
lines changed

3 files changed

+235
-18
lines changed

Diff for: changelog/fix-tokenized-ece-attribute-selection

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Significance: patch
2+
Type: fix
3+
4+
fix: attribute selection from PDPs with tokenized ECE
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
/* eslint-disable jsx-a11y/accessible-emoji */
2+
3+
/**
4+
* External dependencies
5+
*/
6+
import { applyFilters } from '@wordpress/hooks';
7+
import { render } from '@testing-library/react';
8+
9+
/**
10+
* Internal dependencies
11+
*/
12+
import '../wc-product-page';
13+
14+
describe( 'ECE product page compatibility', () => {
15+
it( 'returns the variation data', () => {
16+
render(
17+
<form className="variations_form">
18+
<table className="variations" role="presentation">
19+
<tbody>
20+
<tr>
21+
<th className="label">
22+
<label htmlFor="pa_color">Color</label>
23+
</th>
24+
<td className="value">
25+
<select
26+
id="pa_color"
27+
name="attribute_pa_color"
28+
data-attribute_name="attribute_pa_color"
29+
defaultValue="red"
30+
>
31+
<option value="">Choose an option</option>
32+
<option value="blue">Blue</option>
33+
<option value="green">Green</option>
34+
<option value="red">Red</option>
35+
</select>
36+
</td>
37+
</tr>
38+
<tr>
39+
<th className="label">
40+
<label htmlFor="logo">Logo</label>
41+
</th>
42+
<td className="value">
43+
<select
44+
id="logo"
45+
name="attribute_logo"
46+
data-attribute_name="attribute_logo"
47+
defaultValue="Yes"
48+
>
49+
<option value="">Choose an option</option>
50+
<option value="Yes">Yes</option>
51+
<option value="No">No</option>
52+
</select>
53+
</td>
54+
</tr>
55+
</tbody>
56+
</table>
57+
<div className="single_variation_wrap">
58+
<input type="hidden" name="product_id" value="10" />
59+
</div>
60+
</form>
61+
);
62+
const productData = applyFilters(
63+
'wcpay.express-checkout.cart-add-item',
64+
{
65+
variation: [],
66+
}
67+
);
68+
69+
expect( productData ).toStrictEqual( {
70+
id: 10,
71+
variation: [
72+
{
73+
attribute: 'Color',
74+
value: 'red',
75+
},
76+
{
77+
attribute: 'attribute_pa_color',
78+
value: 'red',
79+
},
80+
{
81+
attribute: 'Logo',
82+
value: 'Yes',
83+
},
84+
{
85+
attribute: 'attribute_logo',
86+
value: 'Yes',
87+
},
88+
],
89+
} );
90+
} );
91+
it( 'ensures compatibility with plugins modifying the DOM with additional markup', () => {
92+
// this markup is simulating the output of the "woo-variation-swatches" plugin.
93+
render(
94+
<form className="variations_form">
95+
<table className="variations">
96+
<tbody>
97+
<tr>
98+
<th className="label">
99+
<label htmlFor="size%f0%9f%98%86">
100+
Size😆
101+
<span className="cfvsw-selected-label">
102+
Medium
103+
</span>
104+
</label>
105+
</th>
106+
<td className="value woo-variation-items-wrapper">
107+
<select
108+
id="size%f0%9f%98%86"
109+
name="attribute_size%f0%9f%98%86"
110+
data-attribute_name="attribute_size%f0%9f%98%86"
111+
defaultValue="Medium"
112+
>
113+
<option value="">Choose an option</option>
114+
<option value="Small">Small</option>
115+
<option value="Medium">Medium</option>
116+
</select>
117+
</td>
118+
</tr>
119+
<tr>
120+
<th className="label">
121+
<label htmlFor="color-%e2%9c%8f%ef%b8%8f">
122+
Color ✏️
123+
</label>
124+
<span>: Blue</span>
125+
</th>
126+
<td className="value woo-variation-items-wrapper">
127+
<select
128+
id="color-%e2%9c%8f%ef%b8%8f"
129+
name="attribute_color-%e2%9c%8f%ef%b8%8f"
130+
data-attribute_name="attribute_color-%e2%9c%8f%ef%b8%8f"
131+
defaultValue="Green"
132+
>
133+
<option value="">Choose an option</option>
134+
<option value="Blue">Blue</option>
135+
<option value="Green">Green</option>
136+
</select>
137+
</td>
138+
</tr>
139+
<tr>
140+
<th className="label">
141+
<label htmlFor="autograph-choice-%e2%9c%8f%ef%b8%8f">
142+
Autograph choice ✏️
143+
</label>
144+
<span>: Yes 👍</span>
145+
</th>
146+
<td className="value woo-variation-items-wrapper">
147+
<select
148+
id="autograph-choice-%e2%9c%8f%ef%b8%8f"
149+
name="attribute_autograph-choice-%e2%9c%8f%ef%b8%8f"
150+
data-attribute_name="attribute_autograph-choice-%e2%9c%8f%ef%b8%8f"
151+
defaultValue="Yes 👍"
152+
>
153+
<option value="">Choose an option</option>
154+
<option value="Yes 👍">Yes 👍</option>
155+
<option value="No 👎">No 👎</option>
156+
</select>
157+
</td>
158+
</tr>
159+
</tbody>
160+
</table>
161+
<div className="single_variation_wrap">
162+
<input type="hidden" name="product_id" value="10" />
163+
</div>
164+
</form>
165+
);
166+
const productData = applyFilters(
167+
'wcpay.express-checkout.cart-add-item',
168+
{
169+
variation: [],
170+
}
171+
);
172+
173+
expect( productData ).toStrictEqual( {
174+
id: 10,
175+
variation: [
176+
{
177+
attribute: 'Size😆',
178+
value: 'Medium',
179+
},
180+
{
181+
attribute: 'attribute_size%f0%9f%98%86',
182+
value: 'Medium',
183+
},
184+
{
185+
attribute: 'Color ✏️',
186+
value: 'Green',
187+
},
188+
{
189+
attribute: 'attribute_color-%e2%9c%8f%ef%b8%8f',
190+
value: 'Green',
191+
},
192+
{
193+
attribute: 'Autograph choice ✏️',
194+
value: 'Yes 👍',
195+
},
196+
{
197+
attribute: 'attribute_autograph-choice-%e2%9c%8f%ef%b8%8f',
198+
value: 'Yes 👍',
199+
},
200+
],
201+
} );
202+
} );
203+
} );

Diff for: client/tokenized-express-checkout/compatibility/wc-product-page.js

+28-18
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,16 @@ addFilter(
3737
'wcpay.express-checkout.cart-add-item',
3838
'automattic/wcpay/express-checkout',
3939
( productData ) => {
40-
const $variationInformation = jQuery( '.single_variation_wrap' );
41-
if ( ! $variationInformation.length ) {
40+
const variationInformation = document.querySelector(
41+
'.single_variation_wrap'
42+
);
43+
if ( ! variationInformation ) {
4244
return productData;
4345
}
4446

45-
const productId = $variationInformation
46-
.find( 'input[name="product_id"]' )
47-
.val();
47+
const productId = variationInformation.querySelector(
48+
'input[name="product_id"]'
49+
).value;
4850
return {
4951
...productData,
5052
id: parseInt( productId, 10 ),
@@ -55,31 +57,39 @@ addFilter(
5557
'wcpay.express-checkout.cart-add-item',
5658
'automattic/wcpay/express-checkout',
5759
( productData ) => {
58-
const $variationsForm = jQuery( '.variations_form' );
59-
if ( ! $variationsForm.length ) {
60+
const variationsForm = document.querySelector( '.variations_form' );
61+
if ( ! variationsForm ) {
6062
return productData;
6163
}
6264

6365
const attributes = [];
64-
const $variationSelectElements = $variationsForm.find(
66+
const variationSelectElements = variationsForm.querySelectorAll(
6567
'.variations select'
6668
);
67-
$variationSelectElements.each( function () {
68-
const $select = jQuery( this );
69+
Array.from( variationSelectElements ).forEach( function ( select ) {
6970
const attributeName =
70-
$select.data( 'attribute_name' ) || $select.attr( 'name' );
71+
select.dataset.attribute_name || select.dataset.name;
7172

7273
attributes.push( {
7374
// The Store API accepts the variable attribute's label, rather than an internal identifier:
7475
// https://github.com/woocommerce/woocommerce-blocks/blob/trunk/src/StoreApi/docs/cart.md#add-item
7576
// It's an unfortunate hack that doesn't work when labels have special characters in them.
76-
attribute: document.querySelector(
77-
`label[for="${ attributeName.replace(
78-
'attribute_',
79-
''
80-
) }"]`
81-
).innerHTML,
82-
value: $select.val() || '',
77+
// fallback until https://github.com/woocommerce/woocommerce/pull/55317 has been consolidated in WC Core.
78+
attribute: Array.from(
79+
document.querySelector(
80+
`label[for="${ attributeName.replace(
81+
'attribute_',
82+
''
83+
) }"]`
84+
).childNodes
85+
)[ 0 ].textContent,
86+
value: select.value || '',
87+
} );
88+
89+
// proper logic for https://github.com/woocommerce/woocommerce/pull/55317 .
90+
attributes.push( {
91+
attribute: attributeName,
92+
value: select.value || '',
8393
} );
8494
} );
8595

0 commit comments

Comments
 (0)