diff --git a/packages/peregrine/lib/context/user.js b/packages/peregrine/lib/context/user.js
index cde6de9a61..84ef97c0e2 100644
--- a/packages/peregrine/lib/context/user.js
+++ b/packages/peregrine/lib/context/user.js
@@ -42,4 +42,37 @@ export default connect(
mapDispatchToProps
)(UserContextProvider);
+/**
+ * @typedef {Object} UserState
+ *
+ * @property {CurrentUser} currentUser Current user details
+ * @property {Error} getDetailsError Get Details call related error
+ * @property {Boolean} isGettingDetails Boolean if true indicates that user details are being fetched. False otherwise.
+ * @property {Boolean} isResettingPassword Deprecated
+ * @property {Boolean} isSignedIn Boolean if true indicates that the user is signed in. False otherwise.
+ * @property {Error} resetPasswordError Deprecated
+ *
+ */
+
+/**
+ * @typedef {Object} CurrentUser
+ *
+ * @property {String} email Current user's email
+ * @property {String} firstname Current user's first name
+ * @property {String} lastname Current user's last name
+ */
+
+/**
+ * @typedef {Object} UserActions
+ *
+ * @property {Function} clearToken Callback to clear user token in browser persistence storage
+ * @property {Function} getUserDetails Callback to get user details
+ * @property {Function} resetPassword Deprecated
+ * @property {Function} setToken Callback to set user token in browser persistence storage
+ * @property {Function} signOut Callback to sign the user out
+ */
+
+/**
+ * @returns {[UserState, UserActions]}
+ */
export const useUserContext = () => useContext(UserContext);
diff --git a/packages/peregrine/lib/talons/AuthModal/useAuthModal.js b/packages/peregrine/lib/talons/AuthModal/useAuthModal.js
index 03a8734379..e0654a3be2 100644
--- a/packages/peregrine/lib/talons/AuthModal/useAuthModal.js
+++ b/packages/peregrine/lib/talons/AuthModal/useAuthModal.js
@@ -17,6 +17,10 @@ const UNAUTHED_ONLY = ['CREATE_ACCOUNT', 'FORGOT_PASSWORD', 'SIGN_IN'];
* @param {function} props.showForgotPassword - callback that shows forgot password view
* @param {function} props.showMainMenu - callback that shows main menu view
* @param {function} props.showMyAccount - callback that shows my account view
+ * @param {function} props.showSignIn - callback that shows signin view
+ * @param {DocumentNode} props.signOutMutation - mutation to call when signing out
+ * @param {string} props.view - string that represents the current view
+ *
* @return {{
* handleClose: function,
* handleCreateAccount: function,
@@ -35,6 +39,7 @@ export const useAuthModal = props => {
showForgotPassword,
showMainMenu,
showMyAccount,
+ showSignIn,
signOutMutation,
view
} = props;
@@ -67,6 +72,10 @@ export const useAuthModal = props => {
closeDrawer();
}, [closeDrawer, showMainMenu]);
+ const handleCancel = useCallback(() => {
+ showSignIn();
+ }, [showSignIn]);
+
const handleCreateAccount = useCallback(() => {
showMyAccount();
}, [showMyAccount]);
@@ -86,6 +95,7 @@ export const useAuthModal = props => {
}, [apolloClient, history, revokeToken, signOut]);
return {
+ handleCancel,
handleClose,
handleCreateAccount,
handleSignOut,
diff --git a/packages/peregrine/lib/talons/ForgotPassword/__tests__/__snapshots__/useForgotPassword.spec.js.snap b/packages/peregrine/lib/talons/ForgotPassword/__tests__/__snapshots__/useForgotPassword.spec.js.snap
new file mode 100644
index 0000000000..54a952d56c
--- /dev/null
+++ b/packages/peregrine/lib/talons/ForgotPassword/__tests__/__snapshots__/useForgotPassword.spec.js.snap
@@ -0,0 +1,14 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render properly 1`] = `
+Object {
+ "forgotPasswordEmail": null,
+ "formErrors": Array [
+ null,
+ ],
+ "handleCancel": [Function],
+ "handleFormSubmit": [Function],
+ "hasCompleted": false,
+ "isResettingPassword": false,
+}
+`;
diff --git a/packages/peregrine/lib/talons/ForgotPassword/__tests__/useForgotPassword.spec.js b/packages/peregrine/lib/talons/ForgotPassword/__tests__/useForgotPassword.spec.js
new file mode 100644
index 0000000000..27577a520e
--- /dev/null
+++ b/packages/peregrine/lib/talons/ForgotPassword/__tests__/useForgotPassword.spec.js
@@ -0,0 +1,118 @@
+import React from 'react';
+import { useMutation } from '@apollo/react-hooks';
+import { act } from 'react-test-renderer';
+
+import { createTestInstance } from '@magento/peregrine';
+
+import { useForgotPassword } from '../useForgotPassword';
+
+jest.mock('@apollo/react-hooks', () => ({
+ useMutation: jest.fn().mockReturnValue([
+ jest.fn().mockResolvedValue(true),
+ {
+ error: null,
+ loading: false
+ }
+ ])
+}));
+
+const Component = props => {
+ const talonProps = useForgotPassword(props);
+
+ return ;
+};
+
+const getTalonProps = props => {
+ const tree = createTestInstance();
+ const { root } = tree;
+ const { talonProps } = root.findByType('i').props;
+
+ const update = newProps => {
+ act(() => {
+ tree.update();
+ });
+
+ return root.findByType('i').props.talonProps;
+ };
+
+ return { talonProps, tree, update };
+};
+
+test('should render properly', () => {
+ const { talonProps } = getTalonProps({
+ mutations: {
+ requestPasswordResetEmailMutation:
+ 'requestPasswordResetEmailMutation'
+ },
+ onCancel: jest.fn()
+ });
+
+ expect(talonProps).toMatchSnapshot();
+});
+
+test('should call onCancel on handleCancel', () => {
+ const onCancel = jest.fn();
+ const { talonProps } = getTalonProps({
+ mutations: {
+ requestPasswordResetEmailMutation:
+ 'requestPasswordResetEmailMutation'
+ },
+ onCancel
+ });
+
+ talonProps.handleCancel();
+
+ expect(onCancel).toHaveBeenCalled();
+});
+
+test('handleFormSubmit should set hasCompleted to true', async () => {
+ const { talonProps, update } = getTalonProps({
+ mutations: {
+ requestPasswordResetEmailMutation:
+ 'requestPasswordResetEmailMutation'
+ },
+ onCancel: jest.fn()
+ });
+
+ await talonProps.handleFormSubmit({ email: 'gooseton@goosemail.com' });
+ const newTalonProps = update();
+
+ expect(newTalonProps.hasCompleted).toBeTruthy();
+});
+
+test('handleFormSubmit should set forgotPasswordEmail', async () => {
+ const { talonProps, update } = getTalonProps({
+ mutations: {
+ requestPasswordResetEmailMutation:
+ 'requestPasswordResetEmailMutation'
+ },
+ onCancel: jest.fn()
+ });
+
+ await talonProps.handleFormSubmit({ email: 'gooseton@goosemail.com' });
+ const newTalonProps = update();
+
+ expect(newTalonProps.forgotPasswordEmail).toBe('gooseton@goosemail.com');
+});
+
+test('handleFormSubmit should set hasCompleted to false if the mutation fails', async () => {
+ useMutation.mockReturnValueOnce([
+ jest.fn().mockRejectedValueOnce(false),
+ {
+ error: 'Mutation error',
+ loading: false
+ }
+ ]);
+ const { talonProps, update } = getTalonProps({
+ mutations: {
+ requestPasswordResetEmailMutation:
+ 'requestPasswordResetEmailMutation'
+ },
+ onCancel: jest.fn()
+ });
+
+ await talonProps.handleFormSubmit({ email: 'gooseton@goosemail.com' });
+ const newTalonProps = update();
+
+ expect(newTalonProps.hasCompleted).toBeFalsy();
+});
diff --git a/packages/peregrine/lib/talons/ForgotPassword/useForgotPassword.js b/packages/peregrine/lib/talons/ForgotPassword/useForgotPassword.js
index 1ba2d166ff..7a0fed1e8a 100644
--- a/packages/peregrine/lib/talons/ForgotPassword/useForgotPassword.js
+++ b/packages/peregrine/lib/talons/ForgotPassword/useForgotPassword.js
@@ -1,37 +1,81 @@
import { useCallback, useState } from 'react';
-import { useUserContext } from '@magento/peregrine/lib/context/user';
+import { useMutation } from '@apollo/react-hooks';
/**
* Returns props necessary to render a ForgotPassword form.
- * @param {function} props.onClose callback function to invoke when closing the form
+ *
+ * @function
+ *
+ * @param {Function} props.onCancel - callback function to call when user clicks the cancel button
+ * @param {RequestPasswordEmailMutations} props.mutations - GraphQL mutations for the forgot password form.
+ *
+ * @returns {ForgotPasswordProps}
+ *
+ * @example
Importing into your project
+ * import { useForgotPassword } from '@magento/peregrine/lib/talons/ForgotPassword/useForgotPassword.js';
*/
export const useForgotPassword = props => {
- const [{ isResettingPassword }, { resetPassword }] = useUserContext();
+ const { onCancel, mutations } = props;
- const { onClose } = props;
-
- const [inProgress, setInProgress] = useState(false);
+ const [hasCompleted, setCompleted] = useState(false);
const [forgotPasswordEmail, setForgotPasswordEmail] = useState(null);
+ const [
+ requestResetEmail,
+ { error: requestResetEmailError, loading: isResettingPassword }
+ ] = useMutation(mutations.requestPasswordResetEmailMutation);
+
const handleFormSubmit = useCallback(
async ({ email }) => {
- setInProgress(true);
- setForgotPasswordEmail(email);
- await resetPassword({ email });
+ try {
+ await requestResetEmail({ variables: { email } });
+ setForgotPasswordEmail(email);
+ setCompleted(true);
+ } catch (err) {
+ setCompleted(false);
+ }
},
- [resetPassword]
+ [requestResetEmail]
);
- const handleContinue = useCallback(() => {
- setInProgress(false);
- onClose();
- }, [onClose]);
+ const handleCancel = useCallback(() => {
+ onCancel();
+ }, [onCancel]);
return {
forgotPasswordEmail,
- handleContinue,
+ formErrors: [requestResetEmailError],
+ handleCancel,
handleFormSubmit,
- inProgress,
+ hasCompleted,
isResettingPassword
};
};
+
+/** JSDocs type definitions */
+
+/**
+ * GraphQL mutations for the forgot password form.
+ * This is a type used by the {@link useForgotPassword} talon.
+ *
+ * @typedef {Object} RequestPasswordEmailMutations
+ *
+ * @property {GraphQLAST} requestPasswordResetEmailMutation mutation for requesting password reset email
+ *
+ * @see [forgotPassword.gql.js]{@link https://github.com/magento/pwa-studio/blob/develop/packages/venia-ui/lib/components/ForgotPassword/forgotPassword.gql.js}
+ * for the query used in Venia
+ */
+
+/**
+ * Object type returned by the {@link useForgotPassword} talon.
+ * It provides props data to use when rendering the forgot password form component.
+ *
+ * @typedef {Object} ForgotPasswordProps
+ *
+ * @property {String} forgotPasswordEmail email address of the user whose password reset has been requested
+ * @property {Array} formErrors A list of form errors
+ * @property {Function} handleCancel Callback function to handle form cancellations
+ * @property {Function} handleFormSubmit Callback function to handle form submission
+ * @property {Boolean} hasCompleted True if password reset mutation has completed. False otherwise
+ * @property {Boolean} isResettingPassword True if password reset mutation is in progress. False otherwise
+ */
diff --git a/packages/peregrine/lib/talons/Header/__tests__/__snapshots__/useAccountMenu.spec.js.snap b/packages/peregrine/lib/talons/Header/__tests__/__snapshots__/useAccountMenu.spec.js.snap
index cb917f1f5d..4f939d3131 100644
--- a/packages/peregrine/lib/talons/Header/__tests__/__snapshots__/useAccountMenu.spec.js.snap
+++ b/packages/peregrine/lib/talons/Header/__tests__/__snapshots__/useAccountMenu.spec.js.snap
@@ -4,6 +4,7 @@ exports[`should return correct shape 1`] = `
Object {
"handleCreateAccount": [Function],
"handleForgotPassword": [Function],
+ "handleForgotPasswordCancel": [Function],
"handleSignOut": [Function],
"updateUsername": [Function],
"username": "",
diff --git a/packages/peregrine/lib/talons/Header/__tests__/__snapshots__/useAccountTrigger.spec.js.snap b/packages/peregrine/lib/talons/Header/__tests__/__snapshots__/useAccountTrigger.spec.js.snap
index fba9b22712..36af46c1f9 100644
--- a/packages/peregrine/lib/talons/Header/__tests__/__snapshots__/useAccountTrigger.spec.js.snap
+++ b/packages/peregrine/lib/talons/Header/__tests__/__snapshots__/useAccountTrigger.spec.js.snap
@@ -4,7 +4,7 @@ exports[`should return correct shape 1`] = `
Object {
"accountMenuIsOpen": false,
"accountMenuRef": "elementRef",
- "accountMenuTriggerRef": "triggerRef",
+ "accountMenuTriggerRef": [MockFunction],
"handleTriggerClick": [Function],
"setAccountMenuIsOpen": [MockFunction],
}
diff --git a/packages/peregrine/lib/talons/Header/__tests__/useAccountTrigger.spec.js b/packages/peregrine/lib/talons/Header/__tests__/useAccountTrigger.spec.js
index 463ee62227..636112b282 100644
--- a/packages/peregrine/lib/talons/Header/__tests__/useAccountTrigger.spec.js
+++ b/packages/peregrine/lib/talons/Header/__tests__/useAccountTrigger.spec.js
@@ -8,7 +8,7 @@ jest.mock('@magento/peregrine/lib/hooks/useDropdown', () => ({
elementRef: 'elementRef',
expanded: false,
setExpanded: jest.fn(),
- triggerRef: 'triggerRef'
+ triggerRef: jest.fn()
})
}));
diff --git a/packages/peregrine/lib/talons/Header/useAccountMenu.js b/packages/peregrine/lib/talons/Header/useAccountMenu.js
index 586b35f706..3390d66bb1 100644
--- a/packages/peregrine/lib/talons/Header/useAccountMenu.js
+++ b/packages/peregrine/lib/talons/Header/useAccountMenu.js
@@ -56,6 +56,10 @@ export const useAccountMenu = props => {
setView('FORGOT_PASSWORD');
}, []);
+ const handleForgotPasswordCancel = useCallback(() => {
+ setView('SIGNIN');
+ }, []);
+
const handleCreateAccount = useCallback(() => {
setView('CREATE_ACCOUNT');
}, []);
@@ -81,6 +85,7 @@ export const useAccountMenu = props => {
username,
handleSignOut,
handleForgotPassword,
+ handleForgotPasswordCancel,
handleCreateAccount,
updateUsername: setUsername
};
diff --git a/packages/peregrine/lib/talons/MyAccount/__tests__/__snapshots__/useResetPassword.spec.js.snap b/packages/peregrine/lib/talons/MyAccount/__tests__/__snapshots__/useResetPassword.spec.js.snap
new file mode 100644
index 0000000000..bedc51c274
--- /dev/null
+++ b/packages/peregrine/lib/talons/MyAccount/__tests__/__snapshots__/useResetPassword.spec.js.snap
@@ -0,0 +1,14 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render properly 1`] = `
+Object {
+ "email": "gooseton@adobe.com",
+ "formErrors": Array [
+ null,
+ ],
+ "handleSubmit": [Function],
+ "hasCompleted": false,
+ "loading": false,
+ "token": "eUokxamL1kiElLDjo6AQHYFO4XlK3",
+}
+`;
diff --git a/packages/peregrine/lib/talons/MyAccount/__tests__/useResetPassword.spec.js b/packages/peregrine/lib/talons/MyAccount/__tests__/useResetPassword.spec.js
new file mode 100644
index 0000000000..97e86a9dc1
--- /dev/null
+++ b/packages/peregrine/lib/talons/MyAccount/__tests__/useResetPassword.spec.js
@@ -0,0 +1,100 @@
+import React from 'react';
+import { useMutation } from '@apollo/react-hooks';
+import { act } from 'react-test-renderer';
+
+import createTestInstance from '@magento/peregrine/lib/util/createTestInstance';
+
+import { useResetPassword } from '../useResetPassword';
+
+jest.mock('@apollo/react-hooks', () => ({
+ useMutation: jest
+ .fn()
+ .mockReturnValue([jest.fn(), { error: null, loading: false }])
+}));
+jest.mock('react-router-dom', () => ({
+ useLocation: jest.fn().mockReturnValue({
+ search:
+ '?email=gooseton%40adobe.com&token=eUokxamL1kiElLDjo6AQHYFO4XlK3'
+ })
+}));
+
+const Component = props => {
+ const talonProps = useResetPassword(props);
+
+ return ;
+};
+
+const getTalonProps = props => {
+ const tree = createTestInstance();
+ const { root } = tree;
+ const { talonProps } = root.findByType('i').props;
+
+ const update = newProps => {
+ act(() => {
+ tree.update();
+ });
+
+ return root.findByType('i').props.talonProps;
+ };
+
+ return { talonProps, tree, update };
+};
+
+test('should render properly', () => {
+ const { talonProps } = getTalonProps({
+ mutations: {
+ resetPasswordMutation: 'resetPasswordMutation'
+ }
+ });
+
+ expect(talonProps).toMatchSnapshot();
+});
+
+test('should set hasCompleted to true if submission is successful', async () => {
+ const resetPassword = jest.fn().mockResolvedValueOnce({});
+ useMutation.mockReturnValueOnce([
+ resetPassword,
+ {
+ loading: false,
+ error: null
+ }
+ ]);
+ const { talonProps, update } = getTalonProps({
+ mutations: {
+ resetPasswordMutation: 'resetPasswordMutation'
+ }
+ });
+
+ await talonProps.handleSubmit({ newPassword: 'NEW_PASSWORD' });
+ const newTalonProps = update();
+
+ expect(newTalonProps.hasCompleted).toBeTruthy();
+ expect(resetPassword).toHaveBeenCalledWith({
+ variables: {
+ email: 'gooseton@adobe.com',
+ token: 'eUokxamL1kiElLDjo6AQHYFO4XlK3',
+ newPassword: 'NEW_PASSWORD'
+ }
+ });
+});
+
+test('should set hasCompleted to false if submission is not successful', async () => {
+ const resetPassword = jest.fn().mockRejectedValueOnce();
+ useMutation.mockReturnValueOnce([
+ resetPassword,
+ {
+ loading: false,
+ error: null
+ }
+ ]);
+ const { talonProps, update } = getTalonProps({
+ mutations: {
+ resetPasswordMutation: 'resetPasswordMutation'
+ }
+ });
+
+ await talonProps.handleSubmit({ newPassword: 'NEW_PASSWORD' });
+ const newTalonProps = update();
+
+ expect(newTalonProps.hasCompleted).toBeFalsy();
+});
diff --git a/packages/peregrine/lib/talons/MyAccount/useResetPassword.js b/packages/peregrine/lib/talons/MyAccount/useResetPassword.js
new file mode 100644
index 0000000000..1b092c8c4c
--- /dev/null
+++ b/packages/peregrine/lib/talons/MyAccount/useResetPassword.js
@@ -0,0 +1,84 @@
+import { useState, useMemo, useCallback } from 'react';
+import { useLocation } from 'react-router-dom';
+import { useMutation } from '@apollo/react-hooks';
+
+/**
+ * Returns props necessary to render a ResetPassword form.
+ *
+ * @param {function} props.mutations - mutation to call when the user submits the new password.
+ *
+ * @returns {ResetPasswordProps} - GraphQL mutations for the reset password form.
+ *
+ * @example Importing into your project
+ * import { useResetPassword } from '@magento/peregrine/lib/talons/MyAccount/useResetPassword.js';
+ */
+export const useResetPassword = props => {
+ const { mutations } = props;
+
+ const [hasCompleted, setHasCompleted] = useState(false);
+ const location = useLocation();
+ const [
+ resetPassword,
+ { error: resetPasswordErrors, loading }
+ ] = useMutation(mutations.resetPasswordMutation);
+
+ const searchParams = useMemo(() => new URLSearchParams(location.search), [
+ location
+ ]);
+ const email = searchParams.get('email');
+ const token = searchParams.get('token');
+
+ const handleSubmit = useCallback(
+ async ({ newPassword }) => {
+ try {
+ if (email && token && newPassword) {
+ await resetPassword({
+ variables: { email, token, newPassword }
+ });
+
+ setHasCompleted(true);
+ }
+ } catch (err) {
+ setHasCompleted(false);
+ }
+ },
+ [resetPassword, email, token]
+ );
+
+ return {
+ email,
+ formErrors: [resetPasswordErrors],
+ handleSubmit,
+ hasCompleted,
+ loading,
+ token
+ };
+};
+
+/** JSDocs type definitions */
+
+/**
+ * GraphQL mutations for the reset password form.
+ * This is a type used by the {@link useResetPassword} talon.
+ *
+ * @typedef {Object} ResetPasswordMutations
+ *
+ * @property {GraphQLAST} resetPasswordMutation mutation for resetting password
+ *
+ * @see [resetPassword.gql.js]{@link https://github.com/magento/pwa-studio/blob/develop/packages/venia-ui/lib/components/MyAccount/ResetPassword/resetPassword.gql.js}
+ * for the query used in Venia
+ */
+
+/**
+ * Object type returned by the {@link useResetPassword} talon.
+ * It provides props data to use when rendering the reset password form component.
+ *
+ * @typedef {Object} ResetPasswordProps
+ *
+ * @property {String} email email address of the user whose password is beeing reset
+ * @property {Array} formErrors A list of form errors
+ * @property {Function} handleSubmit Callback function to handle form submission
+ * @property {Boolean} hasCompleted True if password reset mutation has completed. False otherwise
+ * @property {Boolean} loading True if password reset mutation is in progress. False otherwise
+ * @property {String} token token needed for password reset, will be sent in the mutation
+ */
diff --git a/packages/peregrine/lib/talons/Password/__tests__/__snapshots__/usePassword.spec.js.snap b/packages/peregrine/lib/talons/Password/__tests__/__snapshots__/usePassword.spec.js.snap
new file mode 100644
index 0000000000..44076f15a8
--- /dev/null
+++ b/packages/peregrine/lib/talons/Password/__tests__/__snapshots__/usePassword.spec.js.snap
@@ -0,0 +1,8 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render properly 1`] = `
+Object {
+ "togglePasswordVisibility": [Function],
+ "visible": false,
+}
+`;
diff --git a/packages/peregrine/lib/talons/Password/__tests__/usePassword.spec.js b/packages/peregrine/lib/talons/Password/__tests__/usePassword.spec.js
new file mode 100644
index 0000000000..901e4f2dae
--- /dev/null
+++ b/packages/peregrine/lib/talons/Password/__tests__/usePassword.spec.js
@@ -0,0 +1,46 @@
+import React from 'react';
+import { act } from 'react-test-renderer';
+
+import createTestInstance from '@magento/peregrine/lib/util/createTestInstance';
+
+import { usePassword } from '../usePassword';
+
+const Component = props => {
+ const talonProps = usePassword(props);
+
+ return ;
+};
+
+const getTalonProps = props => {
+ const tree = createTestInstance();
+ const { root } = tree;
+ const { talonProps } = root.findByType('i').props;
+
+ const update = newProps => {
+ act(() => {
+ tree.update();
+ });
+
+ return root.findByType('i').props.talonProps;
+ };
+
+ return { talonProps, tree, update };
+};
+
+test('should render properly', () => {
+ const { talonProps } = getTalonProps();
+
+ expect(talonProps).toMatchSnapshot();
+});
+
+test('togglePasswordVisibility should toggle visible value', () => {
+ const { talonProps, update } = getTalonProps();
+
+ expect(talonProps.visible).toBeFalsy();
+
+ talonProps.togglePasswordVisibility();
+
+ const newTalonProps = update();
+
+ expect(newTalonProps.visible).toBeTruthy();
+});
diff --git a/packages/peregrine/lib/talons/Password/usePassword.js b/packages/peregrine/lib/talons/Password/usePassword.js
new file mode 100644
index 0000000000..edcc847f86
--- /dev/null
+++ b/packages/peregrine/lib/talons/Password/usePassword.js
@@ -0,0 +1,34 @@
+import { useState, useCallback } from 'react';
+
+/**
+ * Returns props necessary to render a Password component.
+ *
+ * @returns {PasswordProps}
+ *
+ * @example Importing into your project
+ * import { usePassword } from '@magento/peregrine/lib/talons/Password/usePassword.js';
+ */
+export const usePassword = () => {
+ const [visible, setVisbility] = useState(false);
+
+ const togglePasswordVisibility = useCallback(() => {
+ setVisbility(!visible);
+ }, [visible]);
+
+ return {
+ visible,
+ togglePasswordVisibility
+ };
+};
+
+/** JSDocs type definitions */
+
+/**
+ * Object type returned by the {@link usePassword} talon.
+ * It provides props data to use when rendering the password component.
+ *
+ * @typedef {Object} PasswordProps
+ *
+ * @property {Boolean} visible If true password should be visible. Hidden if false.
+ * @property {Function} togglePasswordVisibility Callback function to toggle password visibility
+ */
diff --git a/packages/venia-ui/lib/components/AccountMenu/__tests__/__snapshots__/accountMenu.spec.js.snap b/packages/venia-ui/lib/components/AccountMenu/__tests__/__snapshots__/accountMenu.spec.js.snap
index 0fca1396d3..e6cea2bea5 100644
--- a/packages/venia-ui/lib/components/AccountMenu/__tests__/__snapshots__/accountMenu.spec.js.snap
+++ b/packages/venia-ui/lib/components/AccountMenu/__tests__/__snapshots__/accountMenu.spec.js.snap
@@ -23,7 +23,7 @@ exports[`it renders SignIn component when the view is SIGNIN 1`] = `
`;
-exports[`it renders forgot password component when the view is CREATE_ACCOUNT 1`] = `
+exports[`it renders create account component when the view is CREATE_ACCOUNT 1`] = `