diff --git a/packages/template-retail-react-app/app/hooks/use-auth-modal.js b/packages/template-retail-react-app/app/hooks/use-auth-modal.js
index b2946cdcd3..4d09cf4946 100644
--- a/packages/template-retail-react-app/app/hooks/use-auth-modal.js
+++ b/packages/template-retail-react-app/app/hooks/use-auth-modal.js
@@ -45,10 +45,10 @@ import {usePasswordReset} from '@salesforce/retail-react-app/app/hooks/use-passw
import {isServer} from '@salesforce/retail-react-app/app/utils/utils'
import {getConfig} from '@salesforce/pwa-kit-runtime/utils/ssr-config'
-const LOGIN_VIEW = 'login'
-const REGISTER_VIEW = 'register'
-const PASSWORD_VIEW = 'password'
-const EMAIL_VIEW = 'email'
+export const LOGIN_VIEW = 'login'
+export const REGISTER_VIEW = 'register'
+export const PASSWORD_VIEW = 'password'
+export const EMAIL_VIEW = 'email'
const LOGIN_ERROR = defineMessage({
defaultMessage: "Something's not right with your email or password. Try again.",
@@ -57,6 +57,7 @@ const LOGIN_ERROR = defineMessage({
export const AuthModal = ({
initialView = LOGIN_VIEW,
+ initialEmail = '',
onLoginSuccess = noop,
onRegistrationSuccess = noop,
isOpen,
@@ -85,7 +86,7 @@ export const AuthModal = ({
const register = useAuthHelper(AuthHelpers.Register)
const [loginType, setLoginType] = useState(LOGIN_TYPES.PASSWORD)
- const [passwordlessLoginEmail, setPasswordlessLoginEmail] = useState('')
+ const [passwordlessLoginEmail, setPasswordlessLoginEmail] = useState(initialEmail)
const {getPasswordResetToken} = usePasswordReset()
const authorizePasswordlessLogin = useAuthHelper(AuthHelpers.AuthorizePasswordless)
@@ -216,6 +217,10 @@ export const AuthModal = ({
form.reset()
}, [currentView])
+ useEffect(() => {
+ setPasswordlessLoginEmail(initialEmail)
+ }, [initialEmail])
+
useEffect(() => {
// Lets determine if the user has either logged in, or registed.
const loggingIn = currentView === LOGIN_VIEW
@@ -327,6 +332,7 @@ export const AuthModal = ({
AuthModal.propTypes = {
initialView: PropTypes.oneOf([LOGIN_VIEW, REGISTER_VIEW, PASSWORD_VIEW, EMAIL_VIEW]),
+ initialEmail: PropTypes.string,
isOpen: PropTypes.bool.isRequired,
onOpen: PropTypes.func.isRequired,
onClose: PropTypes.func.isRequired,
diff --git a/packages/template-retail-react-app/app/pages/checkout/partials/contact-info.jsx b/packages/template-retail-react-app/app/pages/checkout/partials/contact-info.jsx
index 2576696ae9..749542293c 100644
--- a/packages/template-retail-react-app/app/pages/checkout/partials/contact-info.jsx
+++ b/packages/template-retail-react-app/app/pages/checkout/partials/contact-info.jsx
@@ -32,20 +32,32 @@ import {
} from '@salesforce/retail-react-app/app/components/toggle-card'
import Field from '@salesforce/retail-react-app/app/components/field'
import LoginState from '@salesforce/retail-react-app/app/pages/checkout/partials/login-state'
-import {AuthModal, useAuthModal} from '@salesforce/retail-react-app/app/hooks/use-auth-modal'
+import {
+ AuthModal,
+ EMAIL_VIEW,
+ PASSWORD_VIEW,
+ useAuthModal
+} from '@salesforce/retail-react-app/app/hooks/use-auth-modal'
import useNavigation from '@salesforce/retail-react-app/app/hooks/use-navigation'
import {useCurrentCustomer} from '@salesforce/retail-react-app/app/hooks/use-current-customer'
import {useCurrentBasket} from '@salesforce/retail-react-app/app/hooks/use-current-basket'
import {AuthHelpers, useAuthHelper, useShopperBasketsMutation} from '@salesforce/commerce-sdk-react'
+import {
+ API_ERROR_MESSAGE,
+ FEATURE_UNAVAILABLE_ERROR_MESSAGE,
+ CREATE_ACCOUNT_FIRST_ERROR_MESSAGE,
+ PASSWORDLESS_ERROR_MESSAGES,
+ USER_NOT_FOUND_ERROR
+} from '@salesforce/retail-react-app/app/constants'
const ContactInfo = ({isSocialEnabled = false, isPasswordlessEnabled = false, idps = []}) => {
const {formatMessage} = useIntl()
- const authModal = useAuthModal('password')
const navigate = useNavigation()
const {data: customer} = useCurrentCustomer()
const {data: basket} = useCurrentBasket()
const login = useAuthHelper(AuthHelpers.LoginRegisteredUserB2C)
const logout = useAuthHelper(AuthHelpers.Logout)
+ const authorizePasswordlessLogin = useAuthHelper(AuthHelpers.AuthorizePasswordless)
const updateCustomerForBasket = useShopperBasketsMutation('updateCustomerForBasket')
const mergeBasket = useShopperBasketsMutation('mergeBasket')
@@ -62,8 +74,32 @@ const ContactInfo = ({isSocialEnabled = false, isPasswordlessEnabled = false, id
const [showPasswordField, setShowPasswordField] = useState(false)
const [signOutConfirmDialogIsOpen, setSignOutConfirmDialogIsOpen] = useState(false)
+ const [authModalView, setAuthModalView] = useState(PASSWORD_VIEW)
+ const authModal = useAuthModal(authModalView)
+ const [isPasswordlessLoginClicked, setIsPasswordlessLoginClicked] = useState(false)
+
+ const handlePasswordlessLogin = async (email) => {
+ try {
+ await authorizePasswordlessLogin.mutateAsync({userid: email})
+ setAuthModalView(EMAIL_VIEW)
+ authModal.onOpen()
+ } catch (error) {
+ const message = USER_NOT_FOUND_ERROR.test(error.message)
+ ? formatMessage(CREATE_ACCOUNT_FIRST_ERROR_MESSAGE)
+ : PASSWORDLESS_ERROR_MESSAGES.some((msg) => msg.test(error.message))
+ ? formatMessage(FEATURE_UNAVAILABLE_ERROR_MESSAGE)
+ : formatMessage(API_ERROR_MESSAGE)
+ setError(message)
+ }
+ }
+
const submitForm = async (data) => {
setError(null)
+ if (isPasswordlessLoginClicked) {
+ handlePasswordlessLogin(data.email)
+ setIsPasswordlessLoginClicked(false)
+ return
+ }
try {
if (!data.password) {
await updateCustomerForBasket.mutateAsync({
@@ -108,6 +144,7 @@ const ContactInfo = ({isSocialEnabled = false, isPasswordlessEnabled = false, id
}
const onForgotPasswordClick = () => {
+ setAuthModalView(PASSWORD_VIEW)
authModal.onOpen()
}
@@ -117,6 +154,10 @@ const ContactInfo = ({isSocialEnabled = false, isPasswordlessEnabled = false, id
}
}, [showPasswordField])
+ const onPasswordlessLoginClick = async () => {
+ setIsPasswordlessLoginClicked(true)
+ }
+
return (
-
+
{basket?.customerInfo?.email || customer?.email}
diff --git a/packages/template-retail-react-app/app/pages/checkout/partials/contact-info.test.js b/packages/template-retail-react-app/app/pages/checkout/partials/contact-info.test.js
index d5ce0a696d..aac8c5933d 100644
--- a/packages/template-retail-react-app/app/pages/checkout/partials/contact-info.test.js
+++ b/packages/template-retail-react-app/app/pages/checkout/partials/contact-info.test.js
@@ -5,9 +5,30 @@
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/
import React from 'react'
-import {screen, within} from '@testing-library/react'
+import {screen, waitFor, within} from '@testing-library/react'
import ContactInfo from '@salesforce/retail-react-app/app/pages/checkout/partials/contact-info'
import {renderWithProviders} from '@salesforce/retail-react-app/app/utils/test-utils'
+import {rest} from 'msw'
+import {scapiBasketWithItem} from '@salesforce/retail-react-app/app/mocks/mock-data'
+import {AuthHelpers} from '@salesforce/commerce-sdk-react'
+
+const invalidEmail = 'invalidEmail'
+const validEmail = 'test@salesforce.com'
+const password = 'abc123'
+const mockAuthHelperFunctions = {
+ [AuthHelpers.LoginRegisteredUserB2C]: {mutateAsync: jest.fn()},
+ [AuthHelpers.AuthorizePasswordless]: {mutateAsync: jest.fn()}
+}
+
+jest.mock('@salesforce/commerce-sdk-react', () => {
+ const originalModule = jest.requireActual('@salesforce/commerce-sdk-react')
+ return {
+ ...originalModule,
+ useAuthHelper: jest
+ .fn()
+ .mockImplementation((helperType) => mockAuthHelperFunctions[helperType])
+ }
+})
jest.mock('../util/checkout-context', () => {
return {
@@ -20,36 +41,203 @@ jest.mock('../util/checkout-context', () => {
login: null,
STEPS: {CONTACT_INFO: 0},
goToStep: null,
- goToNextStep: null
+ goToNextStep: jest.fn()
})
}
})
-test('renders component', async () => {
- const {user} = renderWithProviders(
-
- )
+afterEach(() => {
+ jest.resetModules()
+})
+
+describe('passwordless and social disabled', () => {
+ test('renders component', async () => {
+ const {user} = renderWithProviders(
+
+ )
+
+ // switch to login
+ const trigger = screen.getByText(/Already have an account\? Log in/i)
+ await user.click(trigger)
- // switch to login
- const trigger = screen.getByText(/Already have an account\? Log in/i)
- await user.click(trigger)
+ // open forgot password modal
+ const withinCard = within(screen.getByTestId('sf-toggle-card-step-0'))
+ const openModal = withinCard.getByText(/Forgot password\?/i)
+ await user.click(openModal)
- // open forgot password modal
- const withinCard = within(screen.getByTestId('sf-toggle-card-step-0'))
- const openModal = withinCard.getByText(/Forgot password\?/i)
- await user.click(openModal)
+ // check that forgot password modal is open
+ const withinForm = within(screen.getByTestId('sf-auth-modal-form'))
+ expect(withinForm.getByText(/Reset Password/i)).toBeInTheDocument()
+ })
- // check that forgot password modal is open
- const withinForm = within(screen.getByTestId('sf-auth-modal-form'))
- expect(withinForm.getByText(/Reset Password/i)).toBeInTheDocument()
+ test('does not allow login if email or password is missing', async () => {
+ const {user} = renderWithProviders()
+
+ // switch to login
+ const trigger = screen.getByText(/Already have an account\? Log in/i)
+ await user.click(trigger)
+
+ // attempt to login
+ const loginButton = screen.getByText('Log In')
+ await user.click(loginButton)
+ expect(screen.getByText('Please enter your email address.')).toBeInTheDocument()
+ expect(screen.getByText('Please enter your password.')).toBeInTheDocument()
+ })
+
+ test('allows login', async () => {
+ const {user} = renderWithProviders()
+
+ // switch to login
+ const trigger = screen.getByText(/Already have an account\? Log in/i)
+ await user.click(trigger)
+
+ // enter email address and password
+ await user.type(screen.getByLabelText('Email'), validEmail)
+ await user.type(screen.getByLabelText('Password'), password)
+
+ const loginButton = screen.getByText('Log In')
+ await user.click(loginButton)
+ expect(
+ mockAuthHelperFunctions[AuthHelpers.LoginRegisteredUserB2C].mutateAsync
+ ).toHaveBeenCalledWith({username: validEmail, password: password})
+ })
})
-test('Shows passwordless login button if enabled', async () => {
- renderWithProviders()
- expect(screen.getByText('Secure Link')).toBeInTheDocument()
+describe('passwordless enabled', () => {
+ let currentBasket = JSON.parse(JSON.stringify(scapiBasketWithItem))
+ beforeEach(() => {
+ global.server.use(
+ rest.put('*/baskets/:basketId/customer', (req, res, ctx) => {
+ currentBasket.customerInfo.email = validEmail
+ return res(ctx.json(currentBasket))
+ })
+ )
+ })
+
+ test('renders component', async () => {
+ const {getByRole} = renderWithProviders()
+ expect(getByRole('button', {name: 'Checkout as Guest'})).toBeInTheDocument()
+ expect(getByRole('button', {name: 'Secure Link'})).toBeInTheDocument()
+ expect(getByRole('button', {name: 'Password'})).toBeInTheDocument()
+ })
+
+ test('does not allow login if email is missing', async () => {
+ const {user} = renderWithProviders()
+
+ // Click passwordless login button
+ const passwordlessLoginButton = screen.getByText('Secure Link')
+ await user.click(passwordlessLoginButton)
+ expect(screen.getByText('Please enter your email address.')).toBeInTheDocument()
+
+ // Click password login button
+ const passwordLoginButton = screen.getByText('Password')
+ await user.click(passwordLoginButton)
+ expect(screen.getByText('Please enter your email address.')).toBeInTheDocument()
+ })
+
+ test('does not allow passwordless login if email is invalid', async () => {
+ const {user} = renderWithProviders()
+
+ // enter an invalid email address
+ await user.type(screen.getByLabelText('Email'), invalidEmail)
+
+ const passwordlessLoginButton = screen.getByText('Secure Link')
+ await user.click(passwordlessLoginButton)
+ expect(screen.queryByTestId('sf-form-resend-passwordless-email')).not.toBeInTheDocument()
+ })
+
+ test('allows passwordless login', async () => {
+ const {user} = renderWithProviders()
+
+ // enter a valid email address
+ await user.type(screen.getByLabelText('Email'), validEmail)
+
+ // initiate passwordless login
+ const passwordlessLoginButton = screen.getByText('Secure Link')
+ // Click the button twice as the isPasswordlessLoginClicked state doesn't change after the first click
+ await user.click(passwordlessLoginButton)
+ await user.click(passwordlessLoginButton)
+ expect(
+ mockAuthHelperFunctions[AuthHelpers.AuthorizePasswordless].mutateAsync
+ ).toHaveBeenCalledWith({userid: validEmail})
+
+ // check that check email modal is open
+ await waitFor(() => {
+ const withinForm = within(screen.getByTestId('sf-form-resend-passwordless-email'))
+ expect(withinForm.getByText(/Check Your Email/i)).toBeInTheDocument()
+ expect(withinForm.getByText(validEmail)).toBeInTheDocument()
+ })
+
+ // resend the email
+ user.click(screen.getByText(/Resend Link/i))
+ expect(
+ mockAuthHelperFunctions[AuthHelpers.AuthorizePasswordless].mutateAsync
+ ).toHaveBeenCalledWith({userid: validEmail})
+ })
+
+ test('allows login using password', async () => {
+ const {user} = renderWithProviders()
+
+ // enter a valid email address
+ await user.type(screen.getByLabelText('Email'), validEmail)
+
+ // initiate login using password
+ const passwordButton = screen.getByText('Password')
+ await user.click(passwordButton)
+
+ // enter a password
+ await user.type(screen.getByLabelText('Password'), password)
+
+ const loginButton = screen.getByText('Log In')
+ await user.click(loginButton)
+ expect(
+ mockAuthHelperFunctions[AuthHelpers.LoginRegisteredUserB2C].mutateAsync
+ ).toHaveBeenCalledWith({username: validEmail, password: password})
+ })
+
+ test.each([
+ [
+ 'User not found',
+ 'This feature is not currently available. You must create an account to access this feature.'
+ ],
+ [
+ "callback_uri doesn't match the registered callbacks",
+ 'This feature is not currently available.'
+ ],
+ [
+ 'PasswordLess Permissions Error for clientId:aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa',
+ 'This feature is not currently available.'
+ ],
+ ['client secret is not provided', 'This feature is not currently available.'],
+ ['unexpected error message', 'Something went wrong. Try again!']
+ ])(
+ 'maps API error "%s" to the displayed error message"%s"',
+ async (apiErrorMessage, expectedMessage) => {
+ mockAuthHelperFunctions[
+ AuthHelpers.AuthorizePasswordless
+ ].mutateAsync.mockImplementation(() => {
+ throw new Error(apiErrorMessage)
+ })
+ const {user} = renderWithProviders()
+ await user.type(screen.getByLabelText('Email'), validEmail)
+ const passwordlessLoginButton = screen.getByText('Secure Link')
+ // Click the button twice as the isPasswordlessLoginClicked state doesn't change after the first click
+ await user.click(passwordlessLoginButton)
+ await user.click(passwordlessLoginButton)
+ await waitFor(() => {
+ expect(screen.getByText(expectedMessage)).toBeInTheDocument()
+ })
+ }
+ )
})
-test('Shows Google login button if configured', async () => {
- renderWithProviders()
- expect(screen.getByText('Google')).toBeInTheDocument()
+describe('social login enabled', () => {
+ test('renders component', async () => {
+ const {getByRole} = renderWithProviders(
+
+ )
+ expect(getByRole('button', {name: 'Checkout as Guest'})).toBeInTheDocument()
+ expect(getByRole('button', {name: 'Password'})).toBeInTheDocument()
+ expect(getByRole('button', {name: /Google/i})).toBeInTheDocument()
+ })
})
diff --git a/packages/template-retail-react-app/app/pages/checkout/partials/login-state.jsx b/packages/template-retail-react-app/app/pages/checkout/partials/login-state.jsx
index e5fe705b56..e4fb5d88fd 100644
--- a/packages/template-retail-react-app/app/pages/checkout/partials/login-state.jsx
+++ b/packages/template-retail-react-app/app/pages/checkout/partials/login-state.jsx
@@ -12,6 +12,7 @@ import SocialLogin from '@salesforce/retail-react-app/app/components/social-logi
const LoginState = ({
form,
+ handlePasswordlessLoginClick,
isSocialEnabled,
isPasswordlessEnabled,
idps,
@@ -38,7 +39,7 @@ const LoginState = ({
borderColor="gray.500"
type="submit"
onClick={() => {
- form.clearErrors('global')
+ handlePasswordlessLoginClick()
}}
isLoading={form.formState.isSubmitting}
>
@@ -78,8 +79,8 @@ const LoginState = ({
}}
>
)
@@ -104,6 +105,7 @@ const LoginState = ({
LoginState.propTypes = {
form: PropTypes.object,
+ handlePasswordlessLoginClick: PropTypes.func,
isSocialEnabled: PropTypes.bool,
isPasswordlessEnabled: PropTypes.bool,
idps: PropTypes.arrayOf(PropTypes.string),
diff --git a/packages/template-retail-react-app/app/pages/checkout/partials/login-state.test.js b/packages/template-retail-react-app/app/pages/checkout/partials/login-state.test.js
new file mode 100644
index 0000000000..266908bbd7
--- /dev/null
+++ b/packages/template-retail-react-app/app/pages/checkout/partials/login-state.test.js
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2025, Salesforce, Inc.
+ * All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
+ */
+import React from 'react'
+import LoginState from '@salesforce/retail-react-app/../../app/pages/checkout/partials/login-state'
+import {renderWithProviders} from '@salesforce/retail-react-app/app/utils/test-utils'
+import {useForm} from 'react-hook-form'
+
+const mockTogglePasswordField = jest.fn()
+const idps = ['apple', 'google']
+
+const WrapperComponent = ({...props}) => {
+ const form = useForm()
+ return
+}
+
+describe('LoginState', () => {
+ test('shows login button when showPasswordField is false', async () => {
+ const {getByRole, user} = renderWithProviders()
+ const trigger = getByRole('button', {name: /Already have an account\? Log in/i})
+ await user.click(trigger)
+ expect(mockTogglePasswordField).toHaveBeenCalled()
+ })
+
+ test('shows checkout as guest button when showPasswordField is true', async () => {
+ const {getByRole, user} = renderWithProviders()
+ const trigger = getByRole('button', {name: /Checkout as Guest/i})
+ await user.click(trigger)
+ expect(mockTogglePasswordField).toHaveBeenCalled()
+ })
+
+ test('shows passwordless login button if enabled', async () => {
+ const {getByRole, getByText, user} = renderWithProviders(
+
+ )
+ expect(getByText('Or Login With')).toBeInTheDocument()
+ expect(getByRole('button', {name: 'Secure Link'})).toBeInTheDocument()
+ const trigger = getByRole('button', {name: 'Password'})
+ await user.click(trigger)
+ expect(mockTogglePasswordField).toHaveBeenCalled()
+ expect(getByRole('button', {name: 'Back to Sign In Options'})).toBeInTheDocument()
+ })
+
+ test('does not show passwordless login button if disabled', () => {
+ const {queryByRole, queryByText} = renderWithProviders(
+
+ )
+ expect(queryByText('Or Login With')).not.toBeInTheDocument()
+ expect(queryByRole('button', {name: 'Secure Link'})).not.toBeInTheDocument()
+ })
+
+ test('shows social login buttons if enabled', async () => {
+ const {getByRole, getByText, user} = renderWithProviders(
+
+ )
+ expect(getByText('Or Login With')).toBeInTheDocument()
+ expect(getByRole('button', {name: /Google/i})).toBeInTheDocument()
+ expect(getByRole('button', {name: /Apple/i})).toBeInTheDocument()
+ const trigger = getByRole('button', {name: 'Password'})
+ await user.click(trigger)
+ expect(mockTogglePasswordField).toHaveBeenCalled()
+ expect(getByRole('button', {name: 'Back to Sign In Options'})).toBeInTheDocument()
+ })
+
+ test('does not show social login buttons if disabled', () => {
+ const {queryByRole, queryByText} = renderWithProviders(
+
+ )
+ expect(queryByText('Or Login With')).not.toBeInTheDocument()
+ expect(queryByRole('button', {name: /Google/i})).not.toBeInTheDocument()
+ expect(queryByRole('button', {name: /Apple/i})).not.toBeInTheDocument()
+ })
+})
diff --git a/packages/template-retail-react-app/app/ssr.js b/packages/template-retail-react-app/app/ssr.js
index f17efe80e6..80ce88673a 100644
--- a/packages/template-retail-react-app/app/ssr.js
+++ b/packages/template-retail-react-app/app/ssr.js
@@ -75,7 +75,7 @@ const passwordlessLoginCallback =
config.app.login?.passwordless?.callbackURI || '/passwordless-login-callback'
// Reusable function to handle sending a magic link email.
-// By default, this imp[lmenetation uses Marketing Cloud.
+// By default, this implementation uses Marketing Cloud.
async function sendMagicLinkEmail(req, res, landingPath, emailTemplate) {
// Extract the base URL from the request
const base = req.protocol + '://' + req.get('host')
diff --git a/packages/template-retail-react-app/app/static/translations/compiled/en-GB.json b/packages/template-retail-react-app/app/static/translations/compiled/en-GB.json
index 28cbebae38..0142425eab 100644
--- a/packages/template-retail-react-app/app/static/translations/compiled/en-GB.json
+++ b/packages/template-retail-react-app/app/static/translations/compiled/en-GB.json
@@ -1055,6 +1055,12 @@
"value": "Already have an account? Log in"
}
],
+ "contact_info.button.back_to_sign_in_options": [
+ {
+ "type": 0,
+ "value": "Back to Sign In Options"
+ }
+ ],
"contact_info.button.checkout_as_guest": [
{
"type": 0,
diff --git a/packages/template-retail-react-app/app/static/translations/compiled/en-US.json b/packages/template-retail-react-app/app/static/translations/compiled/en-US.json
index 28cbebae38..0142425eab 100644
--- a/packages/template-retail-react-app/app/static/translations/compiled/en-US.json
+++ b/packages/template-retail-react-app/app/static/translations/compiled/en-US.json
@@ -1055,6 +1055,12 @@
"value": "Already have an account? Log in"
}
],
+ "contact_info.button.back_to_sign_in_options": [
+ {
+ "type": 0,
+ "value": "Back to Sign In Options"
+ }
+ ],
"contact_info.button.checkout_as_guest": [
{
"type": 0,
diff --git a/packages/template-retail-react-app/app/static/translations/compiled/en-XA.json b/packages/template-retail-react-app/app/static/translations/compiled/en-XA.json
index 75158e93dd..1a3e194232 100644
--- a/packages/template-retail-react-app/app/static/translations/compiled/en-XA.json
+++ b/packages/template-retail-react-app/app/static/translations/compiled/en-XA.json
@@ -2167,6 +2167,20 @@
"value": "]"
}
],
+ "contact_info.button.back_to_sign_in_options": [
+ {
+ "type": 0,
+ "value": "["
+ },
+ {
+ "type": 0,
+ "value": "Ɓȧȧƈķ ŧǿǿ Şīɠƞ Īƞ Ǿƥŧīǿǿƞş"
+ },
+ {
+ "type": 0,
+ "value": "]"
+ }
+ ],
"contact_info.button.checkout_as_guest": [
{
"type": 0,
diff --git a/packages/template-retail-react-app/translations/en-GB.json b/packages/template-retail-react-app/translations/en-GB.json
index 5a2ff3096c..0cdb95ae46 100644
--- a/packages/template-retail-react-app/translations/en-GB.json
+++ b/packages/template-retail-react-app/translations/en-GB.json
@@ -418,6 +418,9 @@
"contact_info.button.already_have_account": {
"defaultMessage": "Already have an account? Log in"
},
+ "contact_info.button.back_to_sign_in_options": {
+ "defaultMessage": "Back to Sign In Options"
+ },
"contact_info.button.checkout_as_guest": {
"defaultMessage": "Checkout as Guest"
},
diff --git a/packages/template-retail-react-app/translations/en-US.json b/packages/template-retail-react-app/translations/en-US.json
index 5a2ff3096c..0cdb95ae46 100644
--- a/packages/template-retail-react-app/translations/en-US.json
+++ b/packages/template-retail-react-app/translations/en-US.json
@@ -418,6 +418,9 @@
"contact_info.button.already_have_account": {
"defaultMessage": "Already have an account? Log in"
},
+ "contact_info.button.back_to_sign_in_options": {
+ "defaultMessage": "Back to Sign In Options"
+ },
"contact_info.button.checkout_as_guest": {
"defaultMessage": "Checkout as Guest"
},