From f6476d7c4cf217c38bb46c63c18cc05641e88b51 Mon Sep 17 00:00:00 2001 From: Salvatore Di Salvo <119612231+sdisalvo-crd@users.noreply.github.com> Date: Fri, 17 Nov 2023 11:36:59 +0000 Subject: [PATCH] feat(ui): Standardise page layout PasscodeLogin (#258) * wip: PasscodeLogin layout * fix: alert --- src/ui/components/Alert/Alert.scss | 52 ++++++-- src/ui/components/PageFooter/PageFooter.tsx | 2 - .../components/PageFooter/PageFooter.types.ts | 1 - src/ui/pages/PasscodeLogin/PasscodeLogin.scss | 9 +- .../PasscodeLogin/PasscodeLogin.test.tsx | 120 +++++++++++++++++- src/ui/pages/PasscodeLogin/PasscodeLogin.tsx | 112 +++++++--------- src/ui/pages/SetPasscode/SetPasscode.tsx | 1 - tests/screen-objects/passcode.screen.ts | 63 ++++++--- 8 files changed, 257 insertions(+), 103 deletions(-) diff --git a/src/ui/components/Alert/Alert.scss b/src/ui/components/Alert/Alert.scss index 32c96e7d5..0b2489075 100644 --- a/src/ui/components/Alert/Alert.scss +++ b/src/ui/components/Alert/Alert.scss @@ -12,7 +12,18 @@ padding: 0 !important; h2 { - margin: 0; + margin: 0 auto 0.5rem; + font-size: 1.125rem; + font-style: normal; + font-weight: 500; + line-height: normal; + } + + @media screen and (min-height: 300px) and (max-height: 580px) { + h2 { + font-size: 0.9rem; + line-height: 1.2rem; + } } } } @@ -37,22 +48,37 @@ } } -.alert-button { - font-weight: 500 !important; - text-transform: none !important; - border: solid var(--ion-color-medium-grey) 2px !important; - border-radius: 20px !important; - margin: 0; - - &:first-child { - border: none !important; - background: var(--ion-color-primary-gradient) !important; - margin-bottom: 0.5rem; +button.alert-button { + &.sc-ion-alert-ios, + &.sc-ion-alert-md { + margin: 0; + font-size: 1rem; + font-style: normal; + font-weight: 500 !important; + line-height: 1.375rem; + text-transform: none !important; + border: solid var(--ion-color-medium-grey) 2px !important; + border-radius: 20px !important; + + &:first-child { + border: none !important; + background: var(--ion-color-primary-gradient) !important; + margin-bottom: 0.5rem; + } + } +} + +@media screen and (min-height: 300px) and (max-height: 580px) { + button.alert-button { + &.sc-ion-alert-ios, + &.sc-ion-alert-md { + font-size: 0.9rem; + height: 2.5rem; + } } } .custom-alert { - --min-width: calc(100vw - 40px) !important; &.md { .alert-sub-title { text-align: center; diff --git a/src/ui/components/PageFooter/PageFooter.tsx b/src/ui/components/PageFooter/PageFooter.tsx index f7a686054..a54631e1f 100644 --- a/src/ui/components/PageFooter/PageFooter.tsx +++ b/src/ui/components/PageFooter/PageFooter.tsx @@ -4,7 +4,6 @@ import "./PageFooter.scss"; const PageFooter = ({ pageId, - dataTestId, primaryButtonText, primaryButtonAction, primaryButtonDisabled, @@ -19,7 +18,6 @@ const PageFooter = ({ {primaryButtonText && primaryButtonAction && ( void; primaryButtonDisabled?: boolean; diff --git a/src/ui/pages/PasscodeLogin/PasscodeLogin.scss b/src/ui/pages/PasscodeLogin/PasscodeLogin.scss index f0d58e17a..13fbcdf42 100644 --- a/src/ui/pages/PasscodeLogin/PasscodeLogin.scss +++ b/src/ui/pages/PasscodeLogin/PasscodeLogin.scss @@ -1,5 +1,10 @@ .passcode-login { - .passcode-module { - padding-top: 2.5rem; + .responsive-page-content { + justify-content: space-evenly; + + .passcode-login-title, + .passcode-login-description { + text-align: center; + } } } diff --git a/src/ui/pages/PasscodeLogin/PasscodeLogin.test.tsx b/src/ui/pages/PasscodeLogin/PasscodeLogin.test.tsx index 7e6a8124f..b9d4b23e8 100644 --- a/src/ui/pages/PasscodeLogin/PasscodeLogin.test.tsx +++ b/src/ui/pages/PasscodeLogin/PasscodeLogin.test.tsx @@ -1,15 +1,95 @@ -import { MemoryRouter, Route } from "react-router-dom"; +import { MemoryRouter, Route, Router } from "react-router-dom"; import { fireEvent, render, waitFor } from "@testing-library/react"; import { Provider } from "react-redux"; +import configureStore from "redux-mock-store"; +import { createMemoryHistory } from "history"; import { PasscodeLogin } from "./PasscodeLogin"; import EN_TRANSLATIONS from "../../../locales/en/en.json"; import { SetPasscode } from "../SetPasscode"; import { store } from "../../../store"; - import { KeyStoreKeys, SecureStorage } from "../../../core/storage"; import { RoutePath } from "../../../routes"; +import { FIFTEEN_WORDS_BIT_LENGTH } from "../../../constants/appConstants"; + +interface StoreMocked { + stateCache: { + routes: RoutePath[]; + authentication: { + loggedIn: boolean; + time: number; + passcodeIsSet: boolean; + seedPhraseIsSet?: boolean; + }; + currentOperation: string; + }; + seedPhraseCache: { + seedPhrase160: string; + seedPhrase256: string; + selected: number; + }; + cryptoAccountsCache: { + cryptoAccounts: never[]; + }; +} + +const mockStore = configureStore(); +const dispatchMock = jest.fn(); +const history = createMemoryHistory(); +const storeMocked = (initialState: StoreMocked) => { + return { + ...mockStore(initialState), + dispatch: dispatchMock, + }; +}; describe("Passcode Login Page", () => { + beforeAll(() => { + history.push(RoutePath.PASSCODE_LOGIN); + }); + + const initialStateWithSeedPhrase = { + stateCache: { + routes: [RoutePath.PASSCODE_LOGIN], + authentication: { + loggedIn: false, + time: Date.now(), + passcodeIsSet: true, + seedPhraseIsSet: true, + }, + currentOperation: "", + }, + seedPhraseCache: { + seedPhrase160: + "example1 example2 example3 example4 example5 example6 example7 example8 example9 example10 example11 example12 example13 example14 example15", + seedPhrase256: "", + selected: FIFTEEN_WORDS_BIT_LENGTH, + }, + cryptoAccountsCache: { + cryptoAccounts: [], + }, + }; + + const initialStateWithoutSeedPhrase = { + stateCache: { + routes: [RoutePath.PASSCODE_LOGIN], + authentication: { + loggedIn: false, + time: Date.now(), + passcodeIsSet: true, + seedPhraseIsSet: false, + }, + currentOperation: "", + }, + seedPhraseCache: { + seedPhrase160: "", + seedPhrase256: "", + selected: FIFTEEN_WORDS_BIT_LENGTH, + }, + cryptoAccountsCache: { + cryptoAccounts: [], + }, + }; + test("Renders Passcode Login page with title and description", () => { const { getByText } = render( @@ -40,7 +120,7 @@ describe("Passcode Login Page", () => { test("If no seed phrase was stored and I click on I forgot my passcode, I can start over", async () => { const { getByText, findByText } = render( - + { ).toBeVisible(); }); + test("If a seed phrase was stored and I click on I forgot my passcode, I can start over", async () => { + const { getByText, findByText } = render( + + + + + + + ); + fireEvent.click(getByText(/1/)); + fireEvent.click(getByText(/2/)); + fireEvent.click(getByText(/3/)); + fireEvent.click(getByText(/4/)); + fireEvent.click(getByText(/5/)); + fireEvent.click(getByText(/6/)); + expect(await findByText(EN_TRANSLATIONS.passcodelogin.error)).toBeVisible(); + fireEvent.click(getByText(EN_TRANSLATIONS.passcodelogin.forgotten.button)); + expect( + await findByText(EN_TRANSLATIONS.passcodelogin.alert.text.verify) + ).toBeVisible(); + fireEvent.click( + getByText(EN_TRANSLATIONS.passcodelogin.alert.button.verify) + ); + expect( + await findByText(EN_TRANSLATIONS.setpasscode.enterpasscode.title) + ).toBeVisible(); + }); + test("verifies passcode and navigates to next route", async () => { const storedPass = "storedPass"; const secureStorageGetMock = jest diff --git a/src/ui/pages/PasscodeLogin/PasscodeLogin.tsx b/src/ui/pages/PasscodeLogin/PasscodeLogin.tsx index 5ba65d710..4731d562e 100644 --- a/src/ui/pages/PasscodeLogin/PasscodeLogin.tsx +++ b/src/ui/pages/PasscodeLogin/PasscodeLogin.tsx @@ -1,8 +1,6 @@ import { useEffect, useState } from "react"; -import { IonButton, IonCol, IonGrid, IonPage, IonRow } from "@ionic/react"; import { useHistory } from "react-router-dom"; import { i18n } from "../../../i18n"; -import { PageLayout } from "../../components/layout/PageLayout"; import { ErrorMessage, MESSAGE_MILLISECONDS, @@ -22,6 +20,9 @@ import { updateReduxState } from "../../../store/utils"; import "./PasscodeLogin.scss"; import { getBackRoute } from "../../../routes/backRoute"; import { RoutePath } from "../../../routes"; +import PageFooter from "../../components/PageFooter/PageFooter"; +import { ResponsivePageLayout } from "../../components/layout/ResponsivePageLayout"; +import { PageHeader } from "../../components/PageHeader"; const PasscodeLogin = () => { const history = useHistory(); @@ -129,67 +130,52 @@ const PasscodeLogin = () => { }; return ( - - - - - - {i18n.t("passcodelogin.title")} - - - - - {i18n.t("passcodelogin.description")} - - - - - } - passcode={passcode} - handlePinChange={handlePinChange} - handleRemove={handleRemove} - /> - - - - setIsOpen(true)} - > - {i18n.t("passcodelogin.forgotten.button")} - - - - - - - + } + > +

+ {i18n.t("passcodelogin.title")} +

+

+ {i18n.t("passcodelogin.description")} +

+ + } + passcode={passcode} + handlePinChange={handlePinChange} + handleRemove={handleRemove} + /> + setIsOpen(true)} + /> + +
); }; diff --git a/src/ui/pages/SetPasscode/SetPasscode.tsx b/src/ui/pages/SetPasscode/SetPasscode.tsx index e56a37a78..ca81b6a3c 100644 --- a/src/ui/pages/SetPasscode/SetPasscode.tsx +++ b/src/ui/pages/SetPasscode/SetPasscode.tsx @@ -127,7 +127,6 @@ const SetPasscode = () => { {originalPassCode !== "" ? ( handleClearState()} /> diff --git a/tests/screen-objects/passcode.screen.ts b/tests/screen-objects/passcode.screen.ts index 2014091c8..190b3ef69 100644 --- a/tests/screen-objects/passcode.screen.ts +++ b/tests/screen-objects/passcode.screen.ts @@ -1,23 +1,50 @@ -import { expect } from "expect-webdriverio" +import { expect } from "expect-webdriverio"; import { generateRandomNumbersArray } from "../helpers/generate.js"; import { log } from "../helpers/logger.js"; export class PasscodeScreen { - get backArrowIcon () { return $("[data-testid=\"back-button\"]")} - get digit0Button() { return $("[data-testid=\"passcode-button-0\"]")} - get digit1Button () { return $("[data-testid=\"passcode-button-1\"]")} - get digit2Button () { return $("[data-testid=\"passcode-button-2\"]")} - get digit3Button() { return $("[data-testid=\"passcode-button-3\"]")} - get digit4Button () { return $("[data-testid=\"passcode-button-4\"]")} - get digit5Button() { return $("[data-testid=\"passcode-button-5\"]")} - get digit6Button () { return $("[data-testid=\"passcode-button-6\"]")} - get digit7Button() { return $("[data-testid=\"passcode-button-7\"]")} - get digit8Button () { return $("[data-testid=\"passcode-button-8\"]")} - get digit9Button() { return $("[data-testid=\"passcode-button-9\"]")} - get forgotYourPasscodeButton () { return $("[data-testid=\"forgot-your-passcode-button\"]")} - get screenTitle() { return $("[data-testid=\"screen-title\"]")} - get screenDescriptionText() { return $("[data-testid=\"screen-description\"]")} - + get backArrowIcon() { + return $('[data-testid="back-button"]'); + } + get digit0Button() { + return $('[data-testid="passcode-button-0"]'); + } + get digit1Button() { + return $('[data-testid="passcode-button-1"]'); + } + get digit2Button() { + return $('[data-testid="passcode-button-2"]'); + } + get digit3Button() { + return $('[data-testid="passcode-button-3"]'); + } + get digit4Button() { + return $('[data-testid="passcode-button-4"]'); + } + get digit5Button() { + return $('[data-testid="passcode-button-5"]'); + } + get digit6Button() { + return $('[data-testid="passcode-button-6"]'); + } + get digit7Button() { + return $('[data-testid="passcode-button-7"]'); + } + get digit8Button() { + return $('[data-testid="passcode-button-8"]'); + } + get digit9Button() { + return $('[data-testid="passcode-button-9"]'); + } + get forgotYourPasscodeButton() { + return $('[data-testid="secondary-button-passcode-login"]'); + } + get screenTitle() { + return $('[data-testid="screen-title"]'); + } + get screenDescriptionText() { + return $('[data-testid="screen-description"]'); + } async screenLoads() { await expect(this.backArrowIcon).toBeDisplayed(); @@ -59,8 +86,8 @@ export class PasscodeScreen { async createAndEnterRandomPasscode() { const randomPasscode = generateRandomNumbersArray(); - log.info(`randomPasscode: ${randomPasscode}`) - await this.enterPasscode(randomPasscode) + log.info(`randomPasscode: ${randomPasscode}`); + await this.enterPasscode(randomPasscode); return randomPasscode; } }