Skip to content

Commit e7a39de

Browse files
authored
Merge pull request #3902 from woocommerce/cleanup-fe-tests
Add JS Tests Workflow and Fix JS Unit tests
2 parents e5943e1 + 6e0c63b commit e7a39de

9 files changed

Lines changed: 130 additions & 74 deletions

File tree

.github/workflows/js-tests.yml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
name: JS Unit Tests
2+
3+
on:
4+
push:
5+
branches:
6+
- trunk
7+
- develop
8+
paths:
9+
- "**.js"
10+
- package.json
11+
- yarn.lock
12+
- .github/workflows/js-tests.yml
13+
pull_request:
14+
paths:
15+
- "**.js"
16+
- package.json
17+
- yarn.lock
18+
- .github/workflows/js-tests.yml
19+
20+
concurrency:
21+
group: ${{ github.workflow }}-${{ github.ref }}
22+
cancel-in-progress: true
23+
24+
jobs:
25+
UnitTests:
26+
name: JavaScript Unit Tests
27+
runs-on: ubuntu-latest
28+
env:
29+
FORCE_COLOR: 2
30+
steps:
31+
- name: Checkout repository
32+
uses: actions/checkout@v4
33+
34+
- name: Setup Node
35+
uses: actions/setup-node@v4
36+
with:
37+
node-version: 20
38+
39+
- name: Install dependencies
40+
run: yarn install --frozen-lockfile
41+
42+
- name: Run JavaScript unit tests
43+
run: npm run test:unit-js

README.md

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,13 @@ You may also need `$ ddev restart` to apply the config changes.
6969
#### Running tests and other tasks in the DDEV environment
7070

7171
Tests and code style:
72-
- `$ ddev npm run test`
73-
- `$ ddev npm run lint`
74-
- `$ ddev npm run fix-lint`
75-
- `$ ddev npm run lint-js`
76-
- `$ npm run ddev:unit-tests:coverage`
72+
- `$ yarn ddev:unit-tests`
73+
- `$ yarn ddev:unit-tests:coverage`
74+
- `$ yarn ddev:lint`
75+
- `$ yarn ddev:fix-lint`
76+
- `$ yarn ddev:lint-js`
77+
- `$ yarn test:unit-js`
78+
- `$ yarn test:unit-js:coverage`
7779

7880
See [package.json](/package.json) for other useful commands.
7981

@@ -101,7 +103,8 @@ Optionally, change the `PAYPAL_INTEGRATION_DATE` constant to `gmdate( 'Y-m-d' )`
101103

102104
#### Unit tests with Coverage
103105

104-
Run `npm run ddev:unit-tests:coverage`
106+
Run `yarn ddev:unit-tests:coverage`
107+
Run `yarn run test:unit-js:coverage`
105108

106109
This command generates a full test coverage report, available at the URL https://woocommerce-paypal-payments.ddev.site/coverage
107110

modules/ppcp-save-payment-methods/resources/js/add-payment-method.test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ jest.mock( '@ppcp-button/ErrorHandler', () => {
2828
} ) );
2929
} );
3030

31-
jest.mock( './Configuration', () => ( {
31+
jest.mock( './configuration', () => ( {
3232
buttonConfiguration: jest.fn( () => ( {
3333
createVaultSetupToken: jest.fn(),
3434
onApprove: jest.fn(),
@@ -59,7 +59,7 @@ import {
5959
import { getCurrentPaymentMethod } from '@ppcp-button/Helper/CheckoutMethodState';
6060
import { loadPayPalScript } from '@ppcp-button/Helper/PayPalScriptLoading';
6161
import ErrorHandler from '@ppcp-button/ErrorHandler';
62-
import { buttonConfiguration, cardFieldsConfiguration } from './Configuration';
62+
import { buttonConfiguration, cardFieldsConfiguration } from './configuration';
6363
import { renderFields } from '@ppcp-card-fields/Render';
6464
import {
6565
setVisible,
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { render, screen } from '@testing-library/react';
2+
import '@testing-library/jest-dom';
3+
import Notice from './Notice';
4+
5+
describe( 'Notice Component', () => {
6+
it('it renders with the default params', () => {
7+
render(<Notice>Test</Notice>);
8+
const element = screen.getByText('Test');
9+
10+
expect(element).toBeInTheDocument();
11+
expect(element.tagName).toBe('SPAN');
12+
expect(element).toHaveClass('ppcp--notice');
13+
expect(element).toHaveClass('type--info');
14+
});
15+
16+
it('it loads the type param in the class', () => {
17+
render(<Notice type="syde">Test</Notice>);
18+
const element = screen.getByText('Test');
19+
20+
expect(element).toBeInTheDocument();
21+
expect(element).toHaveClass('type--syde');
22+
expect(element).not.toHaveClass('type--info');
23+
});
24+
25+
it('it loads ustom classnames', () => {
26+
render(<Notice className="test">Test</Notice>);
27+
const element = screen.getByText('Test');
28+
29+
expect(element).toBeInTheDocument();
30+
expect(element).toHaveClass('test');
31+
});
32+
33+
});

modules/ppcp-settings/resources/js/Components/Screens/Settings/Components/Settings/Blocks/SavePaymentMethods.test.js

Lines changed: 8 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -119,17 +119,17 @@ describe( 'SavePaymentMethods', () => {
119119
).toBeInTheDocument();
120120
} );
121121

122-
it( 'does not render credit card toggle button when in ownBrandOnly mode', () => {
122+
it( 'Save Credit and Debit Cards is disabled when in ownBrandOnly mode', () => {
123123
render( <SavePaymentMethods ownBrandOnly={ true } /> );
124124

125125
expect(
126126
screen.queryByText( 'Save Credit and Debit Cards' )
127-
).not.toBeInTheDocument();
127+
).toBeInTheDocument();
128128
expect(
129129
screen.queryByRole( 'checkbox', {
130130
name: 'Save Credit and Debit Cards',
131131
} )
132-
).not.toBeInTheDocument();
132+
).toBeDisabled();
133133
} );
134134

135135
it( 'Does not render the component when ownBrandOnly is true and save_paypal_and_venmo feature is disabled', () => {
@@ -142,7 +142,7 @@ describe( 'SavePaymentMethods', () => {
142142
expect( container.firstChild ).toBeNull();
143143
} );
144144

145-
it( 'renders when ownBrandOnly is true and save_paypal_and_venmo feature is enabled', () => {
145+
it( 'renders when save_paypal_and_venmo feature is enabled and OwnBrand is true', () => {
146146
mockUseMerchantInfo.features.save_paypal_and_venmo.enabled = true;
147147

148148
render( <SavePaymentMethods ownBrandOnly={ true } /> );
@@ -152,13 +152,13 @@ describe( 'SavePaymentMethods', () => {
152152
).toBeInTheDocument();
153153
} );
154154

155-
it( 'renders when ownBrandOnly is false regardless of feature status', () => {
156-
mockUseMerchantInfo.features.save_paypal_and_venmo.enabled = false;
155+
it( 'renders when save_paypal_and_venmo feature is enabled and OwnBrand is false', () => {
156+
mockUseMerchantInfo.features.save_paypal_and_venmo.enabled = true;
157157

158-
render( <SavePaymentMethods ownBrandOnly={ false } /> );
158+
render( <SavePaymentMethods ownBrandOnly={ true } /> );
159159

160160
expect(
161-
screen.getByTestId( 'settings-block' )
161+
screen.getByTestId( 'settings-block' )
162162
).toBeInTheDocument();
163163
} );
164164
} );
@@ -176,29 +176,6 @@ describe( 'SavePaymentMethods', () => {
176176
expect( checkbox ).toBeChecked();
177177
} );
178178

179-
it( 'displays false value when feature is disabled', () => {
180-
mockUseSettings.savePaypalAndVenmo = true;
181-
mockUseMerchantInfo.features.save_paypal_and_venmo.enabled = false;
182-
183-
render( <SavePaymentMethods /> );
184-
185-
const checkbox = screen.getByRole( 'checkbox', {
186-
name: 'Save PayPal and Venmo',
187-
} );
188-
expect( checkbox ).not.toBeChecked();
189-
} );
190-
191-
it( 'is disabled when feature is not enabled', () => {
192-
mockUseMerchantInfo.features.save_paypal_and_venmo.enabled = false;
193-
194-
render( <SavePaymentMethods /> );
195-
196-
const checkbox = screen.getByRole( 'checkbox', {
197-
name: 'Save PayPal and Venmo',
198-
} );
199-
expect( checkbox ).toBeDisabled();
200-
} );
201-
202179
it( 'is enabled when feature is enabled', () => {
203180
mockUseMerchantInfo.features.save_paypal_and_venmo.enabled = true;
204181

@@ -282,24 +259,6 @@ describe( 'SavePaymentMethods', () => {
282259
} );
283260
} );
284261

285-
describe( 'Save Credit and Debit Cards rendering', () => {
286-
it( 'Renders when ownBrandOnly={false}', () => {
287-
render( <SavePaymentMethods ownBrandOnly={ false } /> );
288-
289-
expect(
290-
screen.getByText( 'Save Credit and Debit Cards' )
291-
).toBeInTheDocument();
292-
} );
293-
294-
it( 'Does not render when ownBrandOnly={true}', () => {
295-
render( <SavePaymentMethods ownBrandOnly={ true } /> );
296-
297-
expect(
298-
screen.queryByText( 'Save Credit and Debit Cards' )
299-
).not.toBeInTheDocument();
300-
} );
301-
} );
302-
303262
describe( 'Integration with hooks', () => {
304263
it( 'uses values from useSettings hook', () => {
305264
mockUseSettings.savePaypalAndVenmo = true;
@@ -317,16 +276,5 @@ describe( 'SavePaymentMethods', () => {
317276
expect( paypalCheckbox ).toBeChecked();
318277
expect( cardCheckbox ).toBeChecked();
319278
} );
320-
321-
it( 'uses features from useMerchantInfo hook', () => {
322-
mockUseMerchantInfo.features.save_paypal_and_venmo.enabled = false;
323-
324-
render( <SavePaymentMethods /> );
325-
326-
const checkbox = screen.getByRole( 'checkbox', {
327-
name: 'Save PayPal and Venmo',
328-
} );
329-
expect( checkbox ).toBeDisabled();
330-
} );
331279
} );
332280
} );

modules/ppcp-settings/resources/js/utils/formatPrice.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
const priceFormatInfo = {
22
USD: {
33
prefix: '$',
4-
suffix: 'USD',
4+
suffix: ' USD',
55
},
66
CAD: {
77
prefix: '$',
8-
suffix: 'CAD',
8+
suffix: ' CAD',
99
},
1010
AUD: {
1111
prefix: '$',
12-
suffix: 'AUD',
12+
suffix: ' AUD',
1313
},
1414
EUR: {
1515
prefix: '€',
@@ -30,5 +30,5 @@ export const formatPrice = ( value, currency ) => {
3030
return amount;
3131
}
3232

33-
return `${ currencyInfo.prefix }${ amount } ${ currencyInfo.suffix }`;
33+
return `${ currencyInfo.prefix }${ amount }${ currencyInfo.suffix }`;
3434
};
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { formatPrice } from './formatPrice';
2+
3+
describe( 'formatPrice', () => {
4+
5+
const cases = [
6+
[ 100, 'USD', '$100.00 USD' ],
7+
[ 100, 'CAD', '$100.00 CAD' ],
8+
[ 100, 'AUD', '$100.00 AUD' ],
9+
[ 100, 'EUR', '€100.00' ],
10+
[ 100, 'GBP', '£100.00' ],
11+
[ 100.999, 'GBP', '£101.00' ],
12+
[ 100.4, 'GBP', '£100.40' ],
13+
];
14+
15+
it.each(cases)('%d %s should be formatted as %s', (amount, currency, expectation) => {
16+
expect(formatPrice(amount, currency)).toBe(expectation);
17+
});
18+
19+
it( 'should handle when currency is not supported', () => {
20+
const spy = jest.spyOn( console, 'error').mockImplementation(() => {});
21+
expect( formatPrice( 100.00, 'XYZ' ) ).toBe( '100.00' );
22+
23+
expect(spy).toHaveBeenCalledWith( 'Unsupported currency: XYZ' );
24+
spy.mockRestore();
25+
} );
26+
27+
});

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,9 @@
8282
"watch-js": "npm run watch:modules",
8383
"lint-js": "wp-scripts lint-js",
8484
"test:unit-js": "wp-scripts test-unit-js --config ./tests/js/jest.config.json",
85-
"composer-update": "composer update && composer update --lock",
86-
"unit-tests": "vendor/bin/phpunit",
85+
"test:unit-js:coverage": "wp-scripts test-unit-js --config ./tests/js/jest.config.json --coverage",
86+
"ddev:composer-update": "ddev composer update && ddev composer update --lock",
87+
"ddev:unit-tests": "ddev exec phpunit",
8788
"ddev:unit-tests:coverage": "ddev xdebug on && ddev exec XDEBUG_MODE=coverage phpunit --coverage-html coverage/ --coverage-clover coverage/report.xml",
8889
"integration-tests": "(cp -n .env.integration.example .env.integration || true) && php tests/integration/PHPUnit/setup.php && vendor/bin/phpunit -c tests/integration/phpunit.xml.dist",
8990
"test": "npm run unit-tests && npm run integration-tests",

tests/js/jest.config.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
},
1313
"testPathIgnorePatterns": [
1414
"<rootDir>/tests/",
15+
"<rootDir>/.ddev/",
1516
"<rootDir>/node_modules/",
1617
"<rootDir>/vendor/"
1718
],

0 commit comments

Comments
 (0)