Skip to content

Commit

Permalink
Bugfix/pwa 3377 after login issue on order success page (#4354)
Browse files Browse the repository at this point in the history
* Adding 'userOnOrderSuccess' flag to user context. The files add functionality to be  able to set and get the new flag value

* Updating Components to set Context and Adding Redirection Logics

* Updating tests to match with Component Changes

* Adding dependencies and fixing the lint issues in component and test-spec files

* Removing Unwanted Comments
  • Loading branch information
del15881 authored Dec 9, 2024
1 parent e7b42ad commit 1f39b61
Show file tree
Hide file tree
Showing 12 changed files with 240 additions and 9 deletions.
7 changes: 6 additions & 1 deletion packages/peregrine/lib/store/actions/user/actions.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { createActions } from 'redux-actions';

const prefix = 'USER';
const actionTypes = ['RESET', 'SET_TOKEN', 'CLEAR_TOKEN'];
const actionTypes = [
'RESET',
'SET_TOKEN',
'CLEAR_TOKEN',
'SET_USER_ON_ORDER_SUCCESS'
];

const actionMap = {
SIGN_IN: {
Expand Down
6 changes: 6 additions & 0 deletions packages/peregrine/lib/store/actions/user/asyncActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,9 @@ export const clearToken = () =>
// Remove from store
dispatch(actions.clearToken());
};

export const setUserOnOrderSuccess = successFlag =>
async function thunk(dispatch) {
// Dispatch the action to update the state
dispatch(actions.setUserOnOrderSuccess(successFlag));
};
9 changes: 8 additions & 1 deletion packages/peregrine/lib/store/reducers/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ const initialState = {
isResettingPassword: false,
isSignedIn: isSignedIn(),
resetPasswordError: null,
token: getToken()
token: getToken(),
userOnOrderSuccess: false // Add userOnOrderSuccess state
};

const reducerMap = {
Expand All @@ -48,6 +49,12 @@ const reducerMap = {
token: null
};
},
[actions.setUserOnOrderSuccess]: (state, { payload }) => {
return {
...state,
userOnOrderSuccess: payload // Update the state with the new flag value
};
},
[actions.getDetails.request]: state => {
return {
...state,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ import { useLazyQuery } from '@apollo/client';

import { useUserContext } from '../../../../context/user';

import { useDispatch } from 'react-redux'; // Import `connect` and `useDispatch` here

import { setUserOnOrderSuccess } from '../../../../store/actions/user/asyncActions'; // Import `setUserOnOrderSuccess`

jest.mock('../../../../context/user');
useUserContext.mockImplementation(() => {
return [
Expand All @@ -28,6 +32,21 @@ jest.mock('@apollo/client', () => {
};
});

// Mock `react-redux`'s `useDispatch` and `connect` functions

jest.mock('react-redux', () => ({
useDispatch: jest.fn(),
connect: jest.fn().mockReturnValue(Component => Component) // Mock `connect` as an identity function
}));

jest.mock('../../../../store/actions/user/asyncActions', () => ({
setUserOnOrderSuccess: jest.fn(value => ({
type: 'SET_USER_ON_ORDER_SUCCESS',

payload: value
})) // Mock `setUserOnOrderSuccess` to return an action object
}));

const Component = props => {
const talonProps = useOrderConfirmationPage(props);

Expand Down Expand Up @@ -131,6 +150,11 @@ describe('for guest', () => {
}
];
});

const mockDispatch = jest.fn(); // Mock dispatch for this test

useDispatch.mockReturnValue(mockDispatch);

const tree = createTestInstance(<Component {...DEFAULT_PROPS} />);

const { root } = tree;
Expand All @@ -143,6 +167,7 @@ describe('for guest', () => {
describe('for authenticated customers', () => {
it('returns the correct shape', () => {
const mockFetch = jest.fn();
const mockDispatch = jest.fn(); // Mock dispatch for this test

useLazyQuery.mockReturnValueOnce([
mockFetch,
Expand All @@ -153,8 +178,16 @@ describe('for authenticated customers', () => {
}
]);

useDispatch.mockReturnValue(mockDispatch);

const mockOrderNumber = '12345';

// Create a mock dispatch function

//const mockDispatch = jest.fn();

//useDispatch.mockReturnValue(mockDispatch); // Mock useDispatch to return the mock function

const tree = createTestInstance(
<Component orderNumber={mockOrderNumber} />
);
Expand All @@ -164,6 +197,10 @@ describe('for authenticated customers', () => {

expect(talonProps).toMatchSnapshot();

// Check if dispatch was called with the correct action

expect(mockDispatch).toHaveBeenCalledWith(setUserOnOrderSuccess(true));

expect(mockFetch).toHaveBeenCalledWith({
variables: { orderNumber: mockOrderNumber }
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { useGoogleReCaptcha } from '../../../hooks/useGoogleReCaptcha';

import DEFAULT_OPERATIONS from './createAccount.gql';
import { useEventingContext } from '../../../context/eventing';
import { useHistory } from 'react-router-dom';

/**
* Returns props necessary to render CreateAccount component. In particular this
Expand Down Expand Up @@ -95,6 +96,7 @@ export const useCreateAccount = props => {
formAction: 'createAccount'
});

const history = useHistory();
const handleSubmit = useCallback(
async formValues => {
setIsSubmitting(true);
Expand Down Expand Up @@ -158,6 +160,8 @@ export const useCreateAccount = props => {
if (onSubmit) {
onSubmit();
}

history.push('/account-information');
} catch (error) {
if (process.env.NODE_ENV !== 'production') {
console.error(error);
Expand All @@ -179,7 +183,8 @@ export const useCreateAccount = props => {
removeCart,
setToken,
signIn,
dispatch
dispatch,
history
]
);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { useEffect } from 'react';
import { useUserContext } from '../../../context/user';
import { setUserOnOrderSuccess } from '../../../store/actions/user/asyncActions';
import { useLazyQuery } from '@apollo/client';

import mergeOperations from '../../../util/shallowMerge';
import DEFAULT_OPERATIONS from './orderConfirmationPage.gql';
import { useDispatch } from 'react-redux';

export const flattenGuestCartData = data => {
if (!data) {
Expand Down Expand Up @@ -34,8 +36,13 @@ export const flattenCustomerOrderData = data => {
if (!data) {
return;
}

const { customer } = data;
const order = customer.orders.items[0];
const order = customer?.orders?.items?.[0];
if (!order || !order.shipping_address) {
// Return an empty response if no valid order or shipping address exists
return;
}
const { shipping_address: address } = order;

return {
Expand Down Expand Up @@ -65,6 +72,8 @@ export const useOrderConfirmationPage = props => {
const flatData =
flattenGuestCartData(props.data) || flattenCustomerOrderData(queryData);

const dispatch = useDispatch();

useEffect(() => {
if (props.orderNumber && !props.data) {
const orderNumber = props.orderNumber;
Expand All @@ -74,7 +83,19 @@ export const useOrderConfirmationPage = props => {
}
});
}
}, [props.orderNumber, props.data, fetchOrderConfirmationDetails]);

dispatch(setUserOnOrderSuccess(true));

return () => {
// Reset the flag when leaving the page
dispatch(setUserOnOrderSuccess(false));
};
}, [
props.orderNumber,
props.data,
fetchOrderConfirmationDetails,
dispatch
]);

return {
flatData,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,17 @@ import { retrieveCartId } from '../../../store/actions/cart';
import createTestInstance from '../../../util/createTestInstance';
import { useCreateAccount } from '../useCreateAccount';
import { useEventingContext } from '../../../context/eventing';
import { useHistory, useLocation } from 'react-router-dom'; // Added import for useHistory and useLocation

// Mocking useHistory and useLocation

jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'), // Keep the other functionality intact

useHistory: jest.fn(),

useLocation: jest.fn()
}));

jest.mock('@apollo/client', () => {
const apolloClient = jest.requireActual('@apollo/client');
Expand Down Expand Up @@ -186,6 +197,22 @@ beforeAll(() => {
});

useApolloClient.mockReturnValue(client);

// Mock useHistory and useLocation here if needed for specific tests

useHistory.mockReturnValue({
push: jest.fn() // You can mock any methods that useHistory would provide
});

useLocation.mockReturnValue({
pathname: '/mock-path',

search: '',

hash: '',

state: null
});
});

test('should return properly', () => {
Expand Down
23 changes: 21 additions & 2 deletions packages/peregrine/lib/talons/CreateAccount/useCreateAccount.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ import { useGoogleReCaptcha } from '../../hooks/useGoogleReCaptcha';

import DEFAULT_OPERATIONS from './createAccount.gql';
import { useEventingContext } from '../../context/eventing';
import { useHistory, useLocation } from 'react-router-dom';

/**
* Routes to redirect from if used to create an account.
*/
const REDIRECT_FOR_ROUTES = ['/checkout', '/order-confirmation'];

/**
* Returns props necessary to render CreateAccount component. In particular this
Expand Down Expand Up @@ -47,7 +53,7 @@ export const useCreateAccount = props => {
{ createCart, removeCart, getCartDetails }
] = useCartContext();
const [
{ isGettingDetails },
{ isGettingDetails, userOnOrderSuccess },
{ getUserDetails, setToken }
] = useUserContext();

Expand Down Expand Up @@ -112,6 +118,9 @@ export const useCreateAccount = props => {
};
}, [handleCancel]);

const history = useHistory();
const location = useLocation();

const handleSubmit = useCallback(
async formValues => {
setIsSubmitting(true);
Expand Down Expand Up @@ -188,6 +197,13 @@ export const useCreateAccount = props => {
if (onSubmit) {
onSubmit();
}

if (
userOnOrderSuccess &&
REDIRECT_FOR_ROUTES.includes(location.pathname)
) {
history.push('/account-information');
}
} catch (error) {
if (process.env.NODE_ENV !== 'production') {
console.error(error);
Expand All @@ -213,7 +229,10 @@ export const useCreateAccount = props => {
getCartDetails,
fetchCartDetails,
onSubmit,
dispatch
dispatch,
history,
location.pathname,
userOnOrderSuccess
]
);

Expand Down
24 changes: 24 additions & 0 deletions packages/peregrine/lib/talons/SignIn/__tests__/useSignIn.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,24 @@ jest.mock('@magento/peregrine/lib/context/eventing', () => ({
useEventingContext: jest.fn().mockReturnValue([{}, { dispatch: jest.fn() }])
}));

jest.mock('react-router-dom', () => ({
useHistory: jest.fn().mockReturnValue({
push: jest.fn(),

replace: jest.fn()
}),

useLocation: jest.fn().mockReturnValue({
pathname: '/checkout',

search: '',

hash: '',

state: null
})
}));

const Component = props => {
const talonProps = useSignIn(props);

Expand Down Expand Up @@ -277,6 +295,12 @@ test('mutation error is returned by talon', async () => {
expect(talonProps.errors).toMatchSnapshot();
});

test('useLocation and useHistory are used correctly', () => {
const { talonProps } = getTalonProps({ ...defaultProps });

expect(talonProps).toBeDefined(); // Placeholder assertion.
});

it('should call handleForgotPassword when Enter key is pressed', () => {
const { talonProps } = getTalonProps({
...defaultProps
Expand Down
Loading

0 comments on commit 1f39b61

Please sign in to comment.