From c02a8e60d1ede4f8456395b28690180f4505df63 Mon Sep 17 00:00:00 2001 From: internetti Date: Tue, 31 May 2022 17:45:33 +0200 Subject: [PATCH 1/2] apply design to login flow, show loading spinner on login button before enabled --- .../components/AuthWrapper/AuthWrapper.tsx | 5 +- .../AuthWrapper/useTokenResponse.ts | 15 +- .../LoginScreen/LoginScreen.component.tsx | 49 ++- .../screens/LoginScreen/LoginScreen.styles.ts | 4 - .../packages/core-auth/src/utils/helpers.ts | 15 +- .../design-system/src/assets/iconMap.ts | 1 + .../design-system/src/assets/icons/NRC.tsx | 28 ++ .../design-system/src/assets/icons/index.ts | 1 + .../src/components/Logo/Logo.tsx | 15 + .../design-system/src/components/index.ts | 1 + .../packages/design-system/src/themes/Logo.ts | 6 + .../design-system/src/themes/index.ts | 2 + pkg/server/login/templates/templates.go | 311 ++++++++++++------ 13 files changed, 328 insertions(+), 125 deletions(-) delete mode 100644 frontend/apps/core-app/src/screens/LoginScreen/LoginScreen.styles.ts create mode 100644 frontend/packages/design-system/src/assets/icons/NRC.tsx create mode 100644 frontend/packages/design-system/src/components/Logo/Logo.tsx create mode 100644 frontend/packages/design-system/src/themes/Logo.ts diff --git a/frontend/apps/core-app/src/components/AuthWrapper/AuthWrapper.tsx b/frontend/apps/core-app/src/components/AuthWrapper/AuthWrapper.tsx index 1cdcf723c..1f615839c 100644 --- a/frontend/apps/core-app/src/components/AuthWrapper/AuthWrapper.tsx +++ b/frontend/apps/core-app/src/components/AuthWrapper/AuthWrapper.tsx @@ -11,8 +11,9 @@ type Props = { export const AuthWrapper: React.FC = ({ onTokenChange, children }) => { const [loggedIn, setLoggedIn] = React.useState(false); + const [discoveryLoading, setDiscoveryLoading] = React.useState(true); - const [tokenResponse, login] = useTokenResponse(); + const [tokenResponse, login] = useTokenResponse(setDiscoveryLoading); React.useEffect(() => { if (tokenResponse) { @@ -29,7 +30,7 @@ export const AuthWrapper: React.FC = ({ onTokenChange, children }) => { }, [tokenResponse?.accessToken]); if (!loggedIn) { - return ; + return ; } return <>{children}; diff --git a/frontend/apps/core-app/src/components/AuthWrapper/useTokenResponse.ts b/frontend/apps/core-app/src/components/AuthWrapper/useTokenResponse.ts index a9fef7ce8..db1e6976d 100644 --- a/frontend/apps/core-app/src/components/AuthWrapper/useTokenResponse.ts +++ b/frontend/apps/core-app/src/components/AuthWrapper/useTokenResponse.ts @@ -2,6 +2,7 @@ import * as React from 'react'; import { Platform } from 'react-native'; import { CodeChallengeMethod, + DiscoveryDocument, exchangeCodeAsync, makeRedirectUri, ResponseType, @@ -10,6 +11,7 @@ import { useAutoDiscovery, } from 'expo-auth-session'; import Constants from 'expo-constants'; +import { useEffect } from 'react'; const getStoredTokenResponse = (): TokenResponse | undefined => { try { @@ -37,10 +39,9 @@ const storeTokenResponse = (tokenResponse: TokenResponse) => { } }; -export const useTokenResponse = (): [ - TokenResponse | undefined, - () => Promise, -] => { +export const useTokenResponse = ( + setDiscoveryLoading: React.Dispatch>, +): [TokenResponse | undefined, () => Promise] => { const [tokenResponse, setTokenResponse] = React.useState< TokenResponse | undefined >(getStoredTokenResponse()); @@ -58,6 +59,12 @@ export const useTokenResponse = (): [ const discovery = useAutoDiscovery(Constants.manifest?.extra?.issuer); const clientId = Constants.manifest?.extra?.client_id; + useEffect(() => { + if (discovery) { + setDiscoveryLoading(false); + } + }, [JSON.stringify(discovery)]); + const [request, response, promptAsync] = useAuthRequest( { clientId, diff --git a/frontend/apps/core-app/src/screens/LoginScreen/LoginScreen.component.tsx b/frontend/apps/core-app/src/screens/LoginScreen/LoginScreen.component.tsx index b7f79bf0f..c91499112 100644 --- a/frontend/apps/core-app/src/screens/LoginScreen/LoginScreen.component.tsx +++ b/frontend/apps/core-app/src/screens/LoginScreen/LoginScreen.component.tsx @@ -1,18 +1,49 @@ import * as React from 'react'; -import { Button } from 'native-base'; - -import * as Styles from './LoginScreen.styles'; +import { Box, Button, Text } from 'native-base'; +import { Logo } from 'core-design-system'; type Props = { onLogin: () => any; + isLoading: boolean; }; -export const LoginScreenComponent: React.FC = ({ onLogin }) => { +export const LoginScreenComponent: React.FC = ({ + onLogin, + isLoading, +}) => { return ( - - - + + + + + Login + + + Access to your personal account + + + + + + ); }; diff --git a/frontend/apps/core-app/src/screens/LoginScreen/LoginScreen.styles.ts b/frontend/apps/core-app/src/screens/LoginScreen/LoginScreen.styles.ts deleted file mode 100644 index e8a82c478..000000000 --- a/frontend/apps/core-app/src/screens/LoginScreen/LoginScreen.styles.ts +++ /dev/null @@ -1,4 +0,0 @@ -import styled from 'styled-components/native'; -import { Box } from 'native-base'; - -export const Container = styled(Box)``; diff --git a/frontend/packages/core-auth/src/utils/helpers.ts b/frontend/packages/core-auth/src/utils/helpers.ts index 9d486fb02..9ca55928a 100644 --- a/frontend/packages/core-auth/src/utils/helpers.ts +++ b/frontend/packages/core-auth/src/utils/helpers.ts @@ -1,9 +1,16 @@ -import { WebBrowserAuthSessionResult, WebBrowserResultType } from '../types/types'; +import { + WebBrowserAuthSessionResult, + WebBrowserResultType, +} from '../types/types'; import Browser from '../types/browser'; type Resolve = (value: WebBrowserAuthSessionResult) => void; -export const listener = (event: MessageEvent, browser: Browser, resolve: Resolve) => { +export const listener = ( + event: MessageEvent, + browser: Browser, + resolve: Resolve, +) => { const { data, isTrusted, origin } = event; if (!isTrusted) { @@ -22,7 +29,8 @@ export const listener = (event: MessageEvent, browser: Browser, resolve: Resolve }; export const handler = (resolve: Resolve, browser: Browser) => { - const localListener = (event: MessageEvent) => listener(event, browser, resolve); + const localListener = (event: MessageEvent) => + listener(event, browser, resolve); window.addEventListener('message', localListener, false); const interval = setInterval(() => { @@ -32,6 +40,7 @@ export const handler = (resolve: Resolve, browser: Browser) => { browser.dismissPopup(); } }, 10); + const popup = browser.getPopup(); if (popup != null) { browser.getListenerMap().set(popup, { listener: localListener, interval }); diff --git a/frontend/packages/design-system/src/assets/iconMap.ts b/frontend/packages/design-system/src/assets/iconMap.ts index 6ea109991..e6f10571f 100644 --- a/frontend/packages/design-system/src/assets/iconMap.ts +++ b/frontend/packages/design-system/src/assets/iconMap.ts @@ -30,6 +30,7 @@ export const iconMap = { minus: icons.Minus, more: icons.More, next: icons.Next, + nrc: icons.NRC, notification: icons.Notification, plus: icons.Plus, protection: icons.Protection, diff --git a/frontend/packages/design-system/src/assets/icons/NRC.tsx b/frontend/packages/design-system/src/assets/icons/NRC.tsx new file mode 100644 index 000000000..f07c85aa5 --- /dev/null +++ b/frontend/packages/design-system/src/assets/icons/NRC.tsx @@ -0,0 +1,28 @@ +import { G, Path, Rect, Svg } from 'react-native-svg'; +import React from 'react'; + +import { tokens } from '../../index'; + +export const NRC = () => ( + + + + + + +); diff --git a/frontend/packages/design-system/src/assets/icons/index.ts b/frontend/packages/design-system/src/assets/icons/index.ts index a967942e9..d0db3243b 100644 --- a/frontend/packages/design-system/src/assets/icons/index.ts +++ b/frontend/packages/design-system/src/assets/icons/index.ts @@ -27,6 +27,7 @@ export * from './Menu'; export * from './Minus'; export * from './More'; export * from './Next'; +export * from './NRC'; export * from './Notification'; export * from './Plus'; export * from './Protection'; diff --git a/frontend/packages/design-system/src/components/Logo/Logo.tsx b/frontend/packages/design-system/src/components/Logo/Logo.tsx new file mode 100644 index 000000000..f8d56035e --- /dev/null +++ b/frontend/packages/design-system/src/components/Logo/Logo.tsx @@ -0,0 +1,15 @@ +import React, { FC } from 'react'; +import { Icon as IconNB } from 'native-base'; + +import { iconMap } from '../../assets/iconMap'; +import { IconProps } from '../../types/icons'; + +export const Logo: FC> = (props) => { + const MappedIcon = iconMap.nrc; + + return ( + + {MappedIcon && } + + ); +}; diff --git a/frontend/packages/design-system/src/components/index.ts b/frontend/packages/design-system/src/components/index.ts index 05c6fef89..2caa00ffe 100644 --- a/frontend/packages/design-system/src/components/index.ts +++ b/frontend/packages/design-system/src/components/index.ts @@ -1,2 +1,3 @@ export { Icon } from './Icon/Icon'; +export { Logo } from './Logo/Logo'; export { Accordion } from './Accordion/Accordion'; diff --git a/frontend/packages/design-system/src/themes/Logo.ts b/frontend/packages/design-system/src/themes/Logo.ts new file mode 100644 index 000000000..89bf13f93 --- /dev/null +++ b/frontend/packages/design-system/src/themes/Logo.ts @@ -0,0 +1,6 @@ +export default { + baseStyle: { + fill: 'currentColor', + viewBox: '0 0 207 207', + }, +}; diff --git a/frontend/packages/design-system/src/themes/index.ts b/frontend/packages/design-system/src/themes/index.ts index ab3fc1ee4..5bca6f200 100644 --- a/frontend/packages/design-system/src/themes/index.ts +++ b/frontend/packages/design-system/src/themes/index.ts @@ -4,6 +4,7 @@ import tokens from '../tokens'; import Button from './Button'; import Icon from './Icon'; +import Logo from './Logo'; import Input from './Input'; import Text from './Text'; import FormControlErrorMessage from './FormControlErrorMessage'; @@ -30,6 +31,7 @@ export default extendTheme({ Input, Link, Text, + Logo, }, space: { nrc_1: tokens.spacing.spacing5, diff --git a/pkg/server/login/templates/templates.go b/pkg/server/login/templates/templates.go index 9ca3b07fb..ef497533d 100644 --- a/pkg/server/login/templates/templates.go +++ b/pkg/server/login/templates/templates.go @@ -1,7 +1,7 @@ package templates import ( - "html/template" + "html/template" ) const tplText = ` @@ -13,122 +13,227 @@ const tplText = ` -Hello, world! + + + +Login to NRC Core + {{end}} {{define "login_subject"}} - - {{template "header"}} - -
- -
-
-
-
-
-
Login
- -
-
- - -
- - - -
- - {{ if .Error }} -
{{.Error}}

- {{ end }} - -
-
-
-
-
-
- - - + + {{template "header"}} + +
+ +
+
+
+
+

Login

+ +

Access your personal account

+ +
+
+ + +
+ + + +
+ + {{ if .Error }} +
{{.Error}}

+ {{ end }} + +
+
+
+
+
+ + + {{end}} {{define "login_idp"}} - - {{template "header"}} - -
-
-
-
-
-
- -
{{.OrganizationName}}
- - {{ range $idp := .IdentityProviders}} -
-
-
-
-
-
- - - + + {{template "header"}} + +
+
+
+
+
+ +
{{.OrganizationName}}
+ + {{ range $idp := .IdentityProviders}} +
+
+
+
+
+ + + {{end}} {{define "challenge"}} - - {{template "header"}} - -
-
-
-
-
-
- -
Client {{.ClientName}} would like to access your information
- -
- - -
- - {{ if .Error }} -
{{.Error}}

- {{ end }} - -
-
-
-
-
-
- - - + + {{template "header"}} + +
+
+
+
+
+

Access Consent

+

NRC Core wants to access your account

+

Make sure you trust NRC Core

+

+ You may be sharing sensitive information with this site or app. + Learn about how NRC Core will handle your data by reviewing + it’s terms of service and pricacy policies. You can always see + or remove access in your account. +

+ + +
+
+ +
+
+ +
+
+ + {{ if .Error }} +
{{.Error}}

+ {{ end }} + +
+
+
+
+
+ + + {{end}} ` var Template *template.Template = nil func init() { - var err error - Template, err = template.New("").Parse(tplText) - if err != nil { - panic(err) - } + var err error + Template, err = template.New("").Parse(tplText) + if err != nil { + panic(err) + } } From bececc88ca6169ea3eda5a8fbfc9530b5f87f958 Mon Sep 17 00:00:00 2001 From: internetti Date: Wed, 1 Jun 2022 15:32:50 +0200 Subject: [PATCH 2/2] log out on click and fix tests --- .../{ => __tests__}/AuthWrapper.test.tsx | 31 +- .../{ => __tests__}/useTokenResponse.test.ts | 26 +- .../AuthWrapper/useTokenResponse.ts | 1 - .../src/components/NavHeader/logout.ts | 8 +- .../LoginScreen/LoginScreen.component.tsx | 2 +- .../__tests__/LoginScreen.component.test.tsx | 19 +- .../LoginScreen.component.test.tsx.snap | 335 ++++++++++++++---- 7 files changed, 313 insertions(+), 109 deletions(-) rename frontend/apps/core-app/src/components/AuthWrapper/{ => __tests__}/AuthWrapper.test.tsx (69%) rename frontend/apps/core-app/src/components/AuthWrapper/{ => __tests__}/useTokenResponse.test.ts (96%) diff --git a/frontend/apps/core-app/src/components/AuthWrapper/AuthWrapper.test.tsx b/frontend/apps/core-app/src/components/AuthWrapper/__tests__/AuthWrapper.test.tsx similarity index 69% rename from frontend/apps/core-app/src/components/AuthWrapper/AuthWrapper.test.tsx rename to frontend/apps/core-app/src/components/AuthWrapper/__tests__/AuthWrapper.test.tsx index f04f9a804..7bfe1c7e0 100644 --- a/frontend/apps/core-app/src/components/AuthWrapper/AuthWrapper.test.tsx +++ b/frontend/apps/core-app/src/components/AuthWrapper/__tests__/AuthWrapper.test.tsx @@ -1,11 +1,11 @@ import { Text } from 'react-native'; import { fireEvent } from '@testing-library/react-native'; import { TokenResponse } from 'expo-auth-session'; +import React, { useState } from 'react'; -import { render } from '../../testUtils/render'; - -import * as hooks from './useTokenResponse'; -import { AuthWrapper } from './AuthWrapper'; +import { render } from '../../../testUtils/render'; +import * as hooks from '../useTokenResponse'; +import { AuthWrapper } from '../AuthWrapper'; describe('Unauthenticated', () => { it('should render the login button', () => { @@ -16,35 +16,16 @@ describe('Unauthenticated', () => { .spyOn(hooks, 'useTokenResponse') .mockImplementationOnce(() => [undefined, loginSpy]); - const { getByText } = render( + const { getByTestId } = render( Success , ); - const button = getByText('Login'); + const button = getByTestId('login-button'); expect(button).toBeTruthy(); fireEvent.press(button); }); - - it('should call "login" when the button is clicked', () => { - const onTokenChangeMock = jest.fn(); - const loginSpy = jest.fn(); - - jest - .spyOn(hooks, 'useTokenResponse') - .mockImplementationOnce(() => [undefined, loginSpy]); - - const { getByText } = render( - - Success - , - ); - - const button = getByText('Login'); - fireEvent.press(button); - expect(loginSpy).toHaveBeenCalled(); - }); }); describe('Authenticated', () => { diff --git a/frontend/apps/core-app/src/components/AuthWrapper/useTokenResponse.test.ts b/frontend/apps/core-app/src/components/AuthWrapper/__tests__/useTokenResponse.test.ts similarity index 96% rename from frontend/apps/core-app/src/components/AuthWrapper/useTokenResponse.test.ts rename to frontend/apps/core-app/src/components/AuthWrapper/__tests__/useTokenResponse.test.ts index 3ee54ef00..9352bfb26 100644 --- a/frontend/apps/core-app/src/components/AuthWrapper/useTokenResponse.test.ts +++ b/frontend/apps/core-app/src/components/AuthWrapper/__tests__/useTokenResponse.test.ts @@ -2,7 +2,7 @@ import { renderHook } from '@testing-library/react-hooks'; import { waitFor } from '@testing-library/react-native'; import * as expoAuthSession from 'expo-auth-session'; -import { useTokenResponse } from './useTokenResponse'; +import { useTokenResponse } from '../useTokenResponse'; jest.useFakeTimers(); jest.spyOn(window, 'setInterval'); @@ -53,7 +53,7 @@ describe('Success', () => { .mockResolvedValue(fakeTokenResponse); exchangeCodeAsyncSpy.mockClear(); - const { waitForNextUpdate } = renderHook(() => useTokenResponse()); + const { waitForNextUpdate } = renderHook(() => useTokenResponse(jest.fn())); expect(useAutoDiscoverySpy).toHaveBeenCalledTimes(1); // issuer defined in core/frontend/app.json @@ -124,7 +124,7 @@ describe('Success', () => { .mockResolvedValue(fakeTokenResponse); exchangeCodeAsyncSpy.mockClear(); - const { result } = renderHook(() => useTokenResponse()); + const { result } = renderHook(() => useTokenResponse(jest.fn())); await waitFor(() => expect(result.current[0]).toEqual(fakeTokenResponse)); }); @@ -164,7 +164,9 @@ describe('Success', () => { .mockResolvedValue(fakeTokenResponse); exchangeCodeAsyncSpy.mockClear(); - const { result, waitForNextUpdate } = renderHook(() => useTokenResponse()); + const { result, waitForNextUpdate } = renderHook(() => + useTokenResponse(jest.fn()), + ); result.current[1](); expect(promptAsyncMock).toHaveBeenCalledTimes(1); @@ -222,7 +224,9 @@ describe('Success', () => { .mockResolvedValue(fakeTokenResponse); exchangeCodeAsyncSpy.mockClear(); - const { result, waitForNextUpdate } = renderHook(() => useTokenResponse()); + const { result, waitForNextUpdate } = renderHook(() => + useTokenResponse(jest.fn()), + ); expect(useAutoDiscoverySpy).toHaveBeenCalledTimes(1); // issuer defined in core/frontend/app.json @@ -318,7 +322,7 @@ describe('Failure', () => { .mockResolvedValue(fakeTokenResponse); exchangeCodeAsyncSpy.mockClear(); - const { result } = renderHook(() => useTokenResponse()); + const { result } = renderHook(() => useTokenResponse(jest.fn())); expect(useAutoDiscoverySpy).toHaveBeenCalledTimes(1); // issuer defined in core/frontend/app.json @@ -376,7 +380,7 @@ describe('Failure', () => { .mockResolvedValue(fakeTokenResponse); exchangeCodeAsyncSpy.mockClear(); - const { result } = renderHook(() => useTokenResponse()); + const { result } = renderHook(() => useTokenResponse(jest.fn())); expect(useAutoDiscoverySpy).toHaveBeenCalledTimes(1); // issuer defined in core/frontend/app.json @@ -400,7 +404,7 @@ describe('Failure', () => { expect(result.current[0]).toBe(undefined); }); - it('should not set the token respone if exchange codes fails', () => { + it('should not set the token response if exchange codes fails', () => { const fakeTokenResponse = new expoAuthSession.TokenResponse({ accessToken: 'fakeToken', }); @@ -438,7 +442,7 @@ describe('Failure', () => { }); exchangeCodeAsyncSpy.mockClear(); - const { result } = renderHook(() => useTokenResponse()); + const { result } = renderHook(() => useTokenResponse(jest.fn())); expect(useAutoDiscoverySpy).toHaveBeenCalledTimes(1); // issuer defined in core/frontend/app.json @@ -523,7 +527,9 @@ describe('Failure', () => { .mockResolvedValue(fakeTokenResponse); exchangeCodeAsyncSpy.mockClear(); - const { result, waitForNextUpdate } = renderHook(() => useTokenResponse()); + const { result, waitForNextUpdate } = renderHook(() => + useTokenResponse(jest.fn()), + ); expect(useAutoDiscoverySpy).toHaveBeenCalledTimes(1); // issuer defined in core/frontend/app.json diff --git a/frontend/apps/core-app/src/components/AuthWrapper/useTokenResponse.ts b/frontend/apps/core-app/src/components/AuthWrapper/useTokenResponse.ts index db1e6976d..d3c0c5807 100644 --- a/frontend/apps/core-app/src/components/AuthWrapper/useTokenResponse.ts +++ b/frontend/apps/core-app/src/components/AuthWrapper/useTokenResponse.ts @@ -2,7 +2,6 @@ import * as React from 'react'; import { Platform } from 'react-native'; import { CodeChallengeMethod, - DiscoveryDocument, exchangeCodeAsync, makeRedirectUri, ResponseType, diff --git a/frontend/apps/core-app/src/components/NavHeader/logout.ts b/frontend/apps/core-app/src/components/NavHeader/logout.ts index d372776ee..fc3c17306 100644 --- a/frontend/apps/core-app/src/components/NavHeader/logout.ts +++ b/frontend/apps/core-app/src/components/NavHeader/logout.ts @@ -3,6 +3,8 @@ import * as AuthSession from 'expo-auth-session'; import { openAuthSessionAsync } from 'expo-web-browser'; import Constants from 'expo-constants'; +import { formsClient } from '../../clients/formsClient'; + const authorizationEndpoint = `${Constants.manifest?.extra?.issuer}/oauth2/sessions/logout`; const redirectUri = AuthSession.makeRedirectUri({ useProxy: false }); @@ -12,10 +14,12 @@ export const logout = async () => { `${authorizationEndpoint}?post_logout_redirect=${redirectUri}`, 'redirectUrl', ); + } catch (err) { + console.error(err); + } finally { if (Platform.OS === 'web') { sessionStorage.removeItem('tokenResponse'); } - } catch (err) { - console.error(err); + formsClient.setToken(''); } }; diff --git a/frontend/apps/core-app/src/screens/LoginScreen/LoginScreen.component.tsx b/frontend/apps/core-app/src/screens/LoginScreen/LoginScreen.component.tsx index c91499112..46d000c13 100644 --- a/frontend/apps/core-app/src/screens/LoginScreen/LoginScreen.component.tsx +++ b/frontend/apps/core-app/src/screens/LoginScreen/LoginScreen.component.tsx @@ -22,7 +22,6 @@ export const LoginScreenComponent: React.FC = ({ maxWidth="700px" height="100%" bg="red" - shadow="1px 1px red" zIndex={1} > @@ -38,6 +37,7 @@ export const LoginScreenComponent: React.FC = ({ variant="major" w="440px" isLoading={isLoading} + testID="login-button" > Login diff --git a/frontend/apps/core-app/src/screens/LoginScreen/__tests__/LoginScreen.component.test.tsx b/frontend/apps/core-app/src/screens/LoginScreen/__tests__/LoginScreen.component.test.tsx index a5d4f994c..dda161b5d 100644 --- a/frontend/apps/core-app/src/screens/LoginScreen/__tests__/LoginScreen.component.test.tsx +++ b/frontend/apps/core-app/src/screens/LoginScreen/__tests__/LoginScreen.component.test.tsx @@ -5,13 +5,26 @@ import { LoginScreenComponent } from '../LoginScreen.component'; it('should match the snapshot', () => { const login = jest.fn(); - const { toJSON } = render(); + const { toJSON } = render( + , + ); expect(toJSON()).toMatchSnapshot(); }); it('should call login on click', () => { const login = jest.fn(); - const { getByText } = render(); - fireEvent.press(getByText('Login')); + const { getByTestId } = render( + , + ); + fireEvent.press(getByTestId('login-button')); expect(login).toHaveBeenCalled(); }); + +it('should not call login on click when loading', () => { + const login = jest.fn(); + const { getByTestId } = render( + , + ); + fireEvent.press(getByTestId('login-button')); + expect(login).not.toHaveBeenCalled(); +}); diff --git a/frontend/apps/core-app/src/screens/LoginScreen/__tests__/__snapshots__/LoginScreen.component.test.tsx.snap b/frontend/apps/core-app/src/screens/LoginScreen/__tests__/__snapshots__/LoginScreen.component.test.tsx.snap index dd35e5e0a..eff544f89 100644 --- a/frontend/apps/core-app/src/screens/LoginScreen/__tests__/__snapshots__/LoginScreen.component.test.tsx.snap +++ b/frontend/apps/core-app/src/screens/LoginScreen/__tests__/__snapshots__/LoginScreen.component.test.tsx.snap @@ -15,100 +15,301 @@ exports[`should match the snapshot 1`] = ` + + + + + + + + + + + + + + + + Login + + + Access to your personal account + - - Login - + + Login + + + `;