Skip to content

Commit 0efd855

Browse files
committed
[WOOTAX-294] Guard against missing Store API extension data in store notices
On WooCommerce versions without StoreApi support the blocks integration still registers the script, but the Store API extension never adds the woocommerce-services key to the cart extensions data, and the notices effect crashed reading it.
1 parent 1cc94d6 commit 0efd855

2 files changed

Lines changed: 88 additions & 2 deletions

File tree

client/components/store/notices/store-notices.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,11 @@ export const StoreNotices = ( {
5050
return;
5151
}
5252

53-
// Get new notices from the API response.
54-
const newNotices = extensions[ 'woocommerce-services' ].notices;
53+
// Get new notices from the API response. The extension data is
54+
// missing on WooCommerce versions where the Store API extension
55+
// is not registered.
56+
const wcservicesData = extensions[ 'woocommerce-services' ];
57+
const newNotices = ( wcservicesData && wcservicesData.notices ) || [];
5558

5659
if ( 0 === newNotices.length ) {
5760
return;
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/** @format */
2+
3+
/**
4+
* External dependencies
5+
*/
6+
import React from 'react';
7+
import { mount } from 'enzyme';
8+
9+
describe( 'StoreNotices', () => {
10+
let createNotice;
11+
let removeNotices;
12+
let StoreNotices;
13+
14+
const usCart = { shippingAddress: { country: 'US', state: 'CA', postcode: '94105' } };
15+
16+
beforeEach( () => {
17+
jest.resetModules();
18+
19+
createNotice = jest.fn();
20+
removeNotices = jest.fn();
21+
22+
global.window.wp = {
23+
element: { useEffect: React.useEffect },
24+
data: {
25+
useDispatch: () => ( { createNotice, removeNotices } ),
26+
useSelect: () => [],
27+
},
28+
};
29+
30+
( { StoreNotices } = require( '../store-notices' ) );
31+
} );
32+
33+
afterEach( () => {
34+
delete global.window.wp;
35+
} );
36+
37+
it( 'creates notices from the extension data for US addresses', () => {
38+
const extensions = {
39+
'woocommerce-services': {
40+
notices: [ { type: 'error', message: 'ZIP could not be validated.' } ],
41+
},
42+
};
43+
44+
mount( <StoreNotices extensions={ extensions } cart={ usCart } /> );
45+
46+
expect( createNotice ).toHaveBeenCalledWith(
47+
'error',
48+
'ZIP could not be validated.',
49+
expect.objectContaining( { context: 'wc/cart' } )
50+
);
51+
} );
52+
53+
it( 'does not create notices for non-US addresses', () => {
54+
const extensions = {
55+
'woocommerce-services': {
56+
notices: [ { type: 'error', message: 'ZIP could not be validated.' } ],
57+
},
58+
};
59+
const caCart = { shippingAddress: { country: 'CA', state: 'ON', postcode: 'M5V 2T6' } };
60+
61+
mount( <StoreNotices extensions={ extensions } cart={ caCart } /> );
62+
63+
expect( createNotice ).not.toHaveBeenCalled();
64+
} );
65+
66+
it( 'renders without crashing when the extension data is missing', () => {
67+
// Old WooCommerce versions register the blocks integration but not the
68+
// Store API extension, so extensions has no woocommerce-services key.
69+
expect( () => {
70+
mount( <StoreNotices extensions={ {} } cart={ usCart } /> );
71+
} ).not.toThrow();
72+
73+
expect( createNotice ).not.toHaveBeenCalled();
74+
} );
75+
76+
it( 'renders without crashing when the notices key is missing', () => {
77+
expect( () => {
78+
mount( <StoreNotices extensions={ { 'woocommerce-services': {} } } cart={ usCart } /> );
79+
} ).not.toThrow();
80+
81+
expect( createNotice ).not.toHaveBeenCalled();
82+
} );
83+
} );

0 commit comments

Comments
 (0)