/**
* External dependencies
*/
import { act, render, screen, waitFor } from '@testing-library/react';
import { previewCart } from '@woocommerce/resource-previews';
import * as wpDataFunctions from '@wordpress/data';
import { CART_STORE_KEY, PAYMENT_STORE_KEY } from '@woocommerce/block-data';
import { default as fetchMock } from 'jest-fetch-mock';
import {
registerPaymentMethod,
__experimentalDeRegisterPaymentMethod,
} from '@woocommerce/blocks-registry';
import userEvent from '@testing-library/user-event';
import { dispatch } from '@wordpress/data';
/**
* Internal dependencies
*/
import PaymentMethods from '../payment-methods';
jest.mock( '../saved-payment-method-options', () => ( { onChange } ) => {
return (
<>
Saved payment method options
>
);
} );
jest.mock( '@woocommerce/blocks-components', () => {
const originalModule = jest.requireActual(
'@woocommerce/blocks-components'
);
return {
__esModule: true,
...originalModule,
RadioControlAccordion: ( { onChange } ) => (
<>
Payment method options
>
),
};
} );
const originalSelect = jest.requireActual( '@wordpress/data' ).select;
const selectMock = jest
.spyOn( wpDataFunctions, 'select' )
.mockImplementation( ( storeName ) => {
const originalStore = originalSelect( storeName );
if ( storeName === PAYMENT_STORE_KEY ) {
return {
...originalStore,
getState: () => {
const originalState = originalStore.getState();
return {
...originalState,
savedPaymentMethods: {},
availablePaymentMethods: {},
paymentMethodsInitialized: true,
};
},
};
}
return originalStore;
} );
const registerMockPaymentMethods = () => {
[ 'cod', 'credit-card' ].forEach( ( name ) => {
registerPaymentMethod( {
name,
label: name,
content:
A payment method
,
edit: A payment method
,
icons: null,
canMakePayment: () => true,
supports: {
showSavedCards: true,
showSaveOption: true,
features: [ 'products' ],
},
ariaLabel: name,
} );
} );
dispatch( PAYMENT_STORE_KEY ).__internalUpdateAvailablePaymentMethods();
};
const resetMockPaymentMethods = () => {
[ 'cod', 'credit-card' ].forEach( ( name ) => {
__experimentalDeRegisterPaymentMethod( name );
} );
};
describe( 'PaymentMethods', () => {
beforeEach( () => {
fetchMock.mockResponse( ( req ) => {
if ( req.url.match( /wc\/store\/v1\/cart/ ) ) {
return Promise.resolve( JSON.stringify( previewCart ) );
}
return Promise.resolve( '' );
} );
// need to clear the store resolution state between tests.
wpDataFunctions
.dispatch( CART_STORE_KEY )
.invalidateResolutionForStore();
wpDataFunctions.dispatch( CART_STORE_KEY ).receiveCart( {
...previewCart,
payment_methods: [ 'cod', 'credit-card' ],
} );
} );
afterEach( () => {
fetchMock.resetMocks();
} );
test( 'should show no payment methods component when there are no payment methods', async () => {
render( );
await waitFor( () => {
const noPaymentMethods = screen.queryAllByText(
/no payment methods available/
);
// We might get more than one match because the `speak()` function
// creates an extra `div` with the notice contents used for a11y.
expect( noPaymentMethods.length ).toBeGreaterThanOrEqual( 1 );
// Reset the mock back to how it was because we don't need it anymore after this test.
selectMock.mockRestore();
} );
} );
test( 'selecting new payment method', async () => {
const ShowActivePaymentMethod = () => {
const { activePaymentMethod, activeSavedToken } =
wpDataFunctions.useSelect( ( select ) => {
const store = select( PAYMENT_STORE_KEY );
return {
activePaymentMethod: store.getActivePaymentMethod(),
activeSavedToken: store.getActiveSavedToken(),
};
} );
return (
<>
{ 'Active Payment Method: ' + activePaymentMethod }
{ 'Active Saved Token: ' + activeSavedToken }
>
);
};
act( () => {
registerMockPaymentMethods();
} );
// Wait for the payment methods to finish loading before rendering.
await waitFor( () => {
expect(
wpDataFunctions
.select( PAYMENT_STORE_KEY )
.getActivePaymentMethod()
).toBe( 'cod' );
} );
render(
<>
>
);
await waitFor( () => {
const savedPaymentMethodOptions = screen.queryByText(
/Saved payment method options/
);
expect( savedPaymentMethodOptions ).not.toBeNull();
} );
await waitFor( () => {
const paymentMethodOptions = screen.queryByText(
/Payment method options/
);
expect( paymentMethodOptions ).not.toBeNull();
} );
await waitFor( () => {
const savedToken = screen.queryByText(
/Active Payment Method: credit-card/
);
expect( savedToken ).toBeNull();
} );
userEvent.click( screen.getByText( 'Select new payment' ) );
await waitFor( () => {
const activePaymentMethod = screen.queryByText(
/Active Payment Method: credit-card/
);
expect( activePaymentMethod ).not.toBeNull();
} );
act( () => resetMockPaymentMethods() );
} );
} );