Skip to content

Commit

Permalink
- Add RTL hooks utility (#2998)
Browse files Browse the repository at this point in the history
- Cover useSignIn talon with tests using new utility

Co-authored-by: Devagouda <40405790+dpatil-magento@users.noreply.github.com>
  • Loading branch information
tjwiebell and dpatil-magento authored Feb 10, 2021
1 parent a192637 commit 8bcebed
Show file tree
Hide file tree
Showing 3 changed files with 226 additions and 0 deletions.
174 changes: 174 additions & 0 deletions packages/peregrine/lib/talons/SignIn/__tests__/useSignIn.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
import React from 'react';
import { MockedProvider } from '@apollo/client/testing';
import { renderHook, act } from '@testing-library/react-hooks';

import { useCartContext } from '../../../context/cart';
import { useUserContext } from '../../../context/user';
import defaultOperations from '../signIn.gql';
import { useSignIn } from '../useSignIn';

jest.mock('../../../Apollo/clearCartDataFromCache');
jest.mock('../../../Apollo/clearCustomerDataFromCache');
jest.mock('../../../hooks/useAwaitQuery');
jest.mock('../../../store/actions/cart', () => ({
retrieveCartId: jest.fn().mockReturnValue('new-cart-id')
}));

jest.mock('../../../context/cart', () => ({
useCartContext: jest.fn().mockReturnValue([
{ cartId: 'old-cart-id' },
{
createCart: jest.fn(),
removeCart: jest.fn(),
getCartDetails: jest.fn()
}
])
}));

jest.mock('../../../context/user', () => ({
useUserContext: jest.fn().mockReturnValue([
{
isGettingDetails: false,
getDetailsError: 'getDetails error from redux'
},
{ getUserDetails: jest.fn(), setToken: jest.fn() }
])
}));

const signInVariables = {
email: 'fry@planetexpress.com',
password: 'slurm is the best'
};
const authToken = 'auth-token-123';

const signInMock = {
request: {
query: defaultOperations.signInMutation,
variables: signInVariables
},
result: {
data: { generateCustomerToken: { token: authToken } }
}
};

const mergeCartsMock = {
request: {
query: defaultOperations.mergeCartsMutation,
variables: {
destinationCartId: 'new-cart-id',
sourceCartId: 'old-cart-id'
}
},
result: {
data: null
}
};

const initialProps = {
getCartDetailsQuery: 'getCartDetailsQuery',
setDefaultUsername: jest.fn(),
showCreateAccount: jest.fn(),
showForgotPassword: jest.fn()
};

const renderHookWithProviders = ({
renderHookOptions = { initialProps },
mocks = [signInMock, mergeCartsMock]
} = {}) => {
const wrapper = ({ children }) => (
<MockedProvider mocks={mocks} addTypename={false}>
{children}
</MockedProvider>
);

return renderHook(useSignIn, { wrapper, ...renderHookOptions });
};

test('returns correct shape', () => {
const { result } = renderHookWithProviders();

expect(result.current).toMatchInlineSnapshot(`
Object {
"errors": Map {
"getUserDetailsQuery" => "getDetails error from redux",
"signInMutation" => undefined,
},
"handleCreateAccount": [Function],
"handleForgotPassword": [Function],
"handleSubmit": [Function],
"isBusy": false,
"setFormApi": [Function],
}
`);
});

test('handleSubmit triggers waterfall of operations and actions', async () => {
const [, { getCartDetails }] = useCartContext();
const [, { getUserDetails, setToken }] = useUserContext();

const { result } = renderHookWithProviders();

await act(() => result.current.handleSubmit(signInVariables));

expect(result.current.isBusy).toBe(true);
expect(setToken).toHaveBeenCalledWith(authToken);
expect(getCartDetails).toHaveBeenCalled();
expect(getUserDetails).toHaveBeenCalled();
});

test('handleSubmit exception is logged and resets state', async () => {
const errorMessage = 'Oh no! Something went wrong :(';
const [, { getUserDetails, setToken }] = useUserContext();
setToken.mockRejectedValue(errorMessage);
jest.spyOn(console, 'error');

const { result } = renderHookWithProviders();

await act(() => result.current.handleSubmit(signInVariables));

expect(result.current.isBusy).toBe(false);
expect(getUserDetails).not.toHaveBeenCalled();
expect(console.error).toHaveBeenCalledWith(errorMessage);
});

test('handleForgotPassword triggers callbacks', () => {
const mockUsername = 'fry@planetexpress.com';
const mockApi = {
getValue: jest.fn().mockReturnValue(mockUsername)
};

const { result } = renderHookWithProviders();
act(() => result.current.setFormApi(mockApi));
act(() => result.current.handleForgotPassword());

expect(initialProps.setDefaultUsername).toHaveBeenCalledWith(mockUsername);
expect(initialProps.showForgotPassword).toHaveBeenCalled();
});

test('handleCreateAccount triggers callbacks', () => {
const mockUsername = 'fry@planetexpress.com';
const mockApi = {
getValue: jest.fn().mockReturnValue(mockUsername)
};

const { result } = renderHookWithProviders();
act(() => result.current.setFormApi(mockApi));
act(() => result.current.handleCreateAccount());

expect(initialProps.setDefaultUsername).toHaveBeenCalledWith(mockUsername);
expect(initialProps.showCreateAccount).toHaveBeenCalled();
});

test('mutation error is returned by talon', async () => {
const signInErrorMock = {
request: signInMock.request,
error: new Error('Uh oh! There was an error signing in :(')
};

const { result } = renderHookWithProviders({ mocks: [signInErrorMock] });
await act(() => result.current.handleSubmit(signInVariables));

expect(result.current.errors.get('signInMutation')).toMatchInlineSnapshot(
`[Error: Uh oh! There was an error signing in :(]`
);
});
1 change: 1 addition & 0 deletions packages/peregrine/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
},
"devDependencies": {
"@magento/eslint-config": "~1.5.0",
"@testing-library/react-hooks": "~5.0.3",
"intl": "~1.2.5",
"intl-locales-supported": "~1.8.12",
"react": "~17.0.1",
Expand Down
51 changes: 51 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2975,6 +2975,18 @@
dependencies:
defer-to-connect "^1.0.1"

"@testing-library/react-hooks@~5.0.3":
version "5.0.3"
resolved "https://registry.yarnpkg.com/@testing-library/react-hooks/-/react-hooks-5.0.3.tgz#dd0d2048817b013b266d35ca45e3ea48a19fd87e"
integrity sha512-UrnnRc5II7LMH14xsYNm/WRch/67cBafmrSQcyFh0v+UUmSf1uzfB7zn5jQXSettGwOSxJwdQUN7PgkT0w22Lg==
dependencies:
"@babel/runtime" "^7.12.5"
"@types/react" ">=16.9.0"
"@types/react-dom" ">=16.9.0"
"@types/react-test-renderer" ">=16.9.0"
filter-console "^0.1.1"
react-error-boundary "^3.1.0"

"@types/anymatch@*":
version "1.3.1"
resolved "https://registry.yarnpkg.com/@types/anymatch/-/anymatch-1.3.1.tgz#336badc1beecb9dacc38bea2cf32adf627a8421a"
Expand Down Expand Up @@ -3262,13 +3274,27 @@
"@types/react" "*"
"@types/reactcss" "*"

"@types/react-dom@>=16.9.0":
version "17.0.0"
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-17.0.0.tgz#b3b691eb956c4b3401777ee67b900cb28415d95a"
integrity sha512-lUqY7OlkF/RbNtD5nIq7ot8NquXrdFrjSOR6+w9a9RFQevGi1oZO1dcJbXMeONAPKtZ2UrZOEJ5UOCVsxbLk/g==
dependencies:
"@types/react" "*"

"@types/react-syntax-highlighter@11.0.4":
version "11.0.4"
resolved "https://registry.yarnpkg.com/@types/react-syntax-highlighter/-/react-syntax-highlighter-11.0.4.tgz#d86d17697db62f98046874f62fdb3e53a0bbc4cd"
integrity sha512-9GfTo3a0PHwQeTVoqs0g5bS28KkSY48pp5659wA+Dp4MqceDEa8EHBqrllJvvtyusszyJhViUEap0FDvlk/9Zg==
dependencies:
"@types/react" "*"

"@types/react-test-renderer@>=16.9.0":
version "17.0.0"
resolved "https://registry.yarnpkg.com/@types/react-test-renderer/-/react-test-renderer-17.0.0.tgz#9be47b375eeb906fced37049e67284a438d56620"
integrity sha512-nvw+F81OmyzpyIE1S0xWpLonLUZCMewslPuA8BtjSKc5XEbn8zEQBXS7KuOLHTNnSOEM2Pum50gHOoZ62tqTRg==
dependencies:
"@types/react" "*"

"@types/react@*":
version "16.9.17"
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.17.tgz#58f0cc0e9ec2425d1441dd7b623421a867aa253e"
Expand All @@ -3277,6 +3303,14 @@
"@types/prop-types" "*"
csstype "^2.2.0"

"@types/react@>=16.9.0":
version "17.0.1"
resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.1.tgz#eb1f1407dea8da3bc741879c1192aa703ab9975b"
integrity sha512-w8t9f53B2ei4jeOqf/gxtc2Sswnc3LBK5s0DyJcg5xd10tMHXts2N31cKjWfH9IC/JvEPa/YF1U4YeP1t4R6HQ==
dependencies:
"@types/prop-types" "*"
csstype "^3.0.2"

"@types/reactcss@*":
version "1.2.3"
resolved "https://registry.yarnpkg.com/@types/reactcss/-/reactcss-1.2.3.tgz#af28ae11bbb277978b99d04d1eedfd068ca71834"
Expand Down Expand Up @@ -6416,6 +6450,11 @@ csstype@^2.2.0, csstype@^2.5.7:
resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.8.tgz#0fb6fc2417ffd2816a418c9336da74d7f07db431"
integrity sha512-msVS9qTuMT5zwAGCVm4mxfrZ18BNc6Csd0oJAtiFMZ1FAx1CCvy2+5MDmYoix63LM/6NDbNtodCiGYGmFgO0dA==

csstype@^3.0.2:
version "3.0.6"
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.6.tgz#865d0b5833d7d8d40f4e5b8a6d76aea3de4725ef"
integrity sha512-+ZAmfyWMT7TiIlzdqJgjMb7S4f1beorDbWbsocyK4RaiqA5RTX3K14bnBWmmA9QEM0gRdsjyyrEmcyga8Zsxmw==

csv-parse@~4.4.6:
version "4.4.7"
resolved "https://registry.yarnpkg.com/csv-parse/-/csv-parse-4.4.7.tgz#069de0875b92780ca74a018c9880ab41cb3517a1"
Expand Down Expand Up @@ -8198,6 +8237,11 @@ fill-range@^7.0.1:
dependencies:
to-regex-range "^5.0.1"

filter-console@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/filter-console/-/filter-console-0.1.1.tgz#6242be28982bba7415bcc6db74a79f4a294fa67c"
integrity sha512-zrXoV1Uaz52DqPs+qEwNJWJFAWZpYJ47UNmpN9q4j+/EYsz85uV0DC9k8tRND5kYmoVzL0W+Y75q4Rg8sRJCdg==

finalhandler@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.0.tgz#ce0b6855b45853e791b2fcc680046d88253dd7f5"
Expand Down Expand Up @@ -14322,6 +14366,13 @@ react-draggable@^4.0.3:
classnames "^2.2.5"
prop-types "^15.6.0"

react-error-boundary@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/react-error-boundary/-/react-error-boundary-3.1.0.tgz#9487443df2f9ba1db90d8ab52351814907ea4af3"
integrity sha512-lmPrdi5SLRJR+AeJkqdkGlW/CRkAUvZnETahK58J4xb5wpbfDngasEGu+w0T1iXEhVrYBJZeW+c4V1hILCnMWQ==
dependencies:
"@babel/runtime" "^7.12.5"

react-error-overlay@^6.0.7:
version "6.0.8"
resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.8.tgz#474ed11d04fc6bda3af643447d85e9127ed6b5de"
Expand Down

0 comments on commit 8bcebed

Please sign in to comment.