Skip to content

Commit

Permalink
Add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
OKendigelyan committed Sep 11, 2024
1 parent fd93536 commit cfecc97
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,13 @@ import {
mockMnemonicAccount,
mockSocialAccount,
} from "@umami/core";
import { type UmamiStore, accountsActions, addTestAccounts, makeStore } from "@umami/state";
import {
type UmamiStore,
accountsActions,
addTestAccount,
addTestAccounts,
makeStore,
} from "@umami/state";

import { AccountSelectorModal } from "./AccountSelectorModal";
import { DeriveMnemonicAccountModal } from "./DeriveMnemonicAccountModal";
Expand Down Expand Up @@ -58,6 +64,87 @@ describe("<AccountSelectorModal />", () => {
}
);

describe("when clicking 'Remove account group' button", () => {
it.each([
["mnemonic", mockMnemonicAccount(0)],
["ledger", mockLedgerAccount(1)],
["social", mockSocialAccount(2)],
])(
"opens confirmation modal when clicking remove button for %s accounts",
async (_, account) => {
const user = userEvent.setup();
await renderInModal(<AccountSelectorModal />, store);
const accountLabel = getAccountGroupLabel(account);

const removeButton = screen.getByLabelText(`Remove ${accountLabel} accounts`);
await act(() => user.click(removeButton));

expect(screen.getByText("Remove All Accounts")).toBeInTheDocument();

await waitFor(() =>
expect(
screen.getByText(`Are you sure you want to remove all of your ${accountLabel}?`)
).toBeVisible()
);
}
);

it("removes mnemonic accounts when confirmed", async () => {
const user = userEvent.setup();
await renderInModal(<AccountSelectorModal />, store);
const account = mockMnemonicAccount(0);
const accountLabel = getAccountGroupLabel(account);
const removeButton = screen.getByLabelText(`Remove ${accountLabel} accounts`);
await act(() => user.click(removeButton));

const confirmButton = screen.getByText("Remove");
await act(() => user.click(confirmButton));

expect(store.getState().accounts.seedPhrases[account.seedFingerPrint]).toBe(undefined);
expect(store.getState().accounts.items.length).toBe(2);
});

it.each([
["ledger", mockLedgerAccount(1)],
["social", mockSocialAccount(2)],
])("removes %s accounts when confirmed", async (_, account) => {
const user = userEvent.setup();
await renderInModal(<AccountSelectorModal />, store);
const accountLabel = getAccountGroupLabel(account);
const accounts = store.getState().accounts.items;

const removeButton = screen.getByLabelText(`Remove ${accountLabel} accounts`);
await act(() => user.click(removeButton));

const confirmButton = screen.getByText("Remove");
await act(() => user.click(confirmButton));

expect(store.getState().accounts.items.length).toBe(accounts.length - 1);
});

it('shows "Remove & Off-board" message when removing last group of accounts', async () => {
store.dispatch(accountsActions.reset());
addTestAccount(store, mockSocialAccount(0));

const user = userEvent.setup();
const accountLabel = getAccountGroupLabel(mockSocialAccount(0));
await renderInModal(<AccountSelectorModal />, store);

const removeButton = screen.getByLabelText(`Remove ${accountLabel} accounts`);
await act(() => user.click(removeButton));

expect(screen.getByText("Remove & Off-board")).toBeInTheDocument();

await waitFor(() =>
expect(
screen.getByText(
"Removing all your accounts will off-board you from Umami. This will remove or reset all customized settings to their defaults. Personal data (including saved contacts, password and accounts) won't be affected."
)
).toBeVisible()
);
});
});

it("opens appropriate modal when clicking 'Add Account' button", async () => {
const user = userEvent.setup();
const { openWith } = dynamicModalContextMock;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,17 +41,17 @@ import { OnboardOptionsModal } from "../Onboarding/OnboardOptions";
import { useIsAccountVerified } from "../Onboarding/VerificationFlow";

export const AccountSelectorModal = () => {
const accounts = useImplicitAccounts();
const implicitAccounts = useImplicitAccounts();
const color = useColor();
const getBalance = useGetAccountBalance();
const isVerified = useIsAccountVerified();
const removeMnemonic = useRemoveMnemonic();
const removeNonMnemonic = useRemoveNonMnemonic();
const { openWith, onClose } = useDynamicModalContext();
const { openWith, goBack, onClose } = useDynamicModalContext();

const dispatch = useDispatch();

const groupedAccounts = groupBy(accounts, getAccountGroupLabel);
const groupedAccounts = groupBy(implicitAccounts, getAccountGroupLabel);

const handleDeriveAccount = (account?: ImplicitAccount) => {
if (!account) {
Expand All @@ -72,21 +72,21 @@ export const AccountSelectorModal = () => {
? "Removing all your accounts will off-board you from Umami. This will remove or reset all customized settings to their defaults. Personal data (including saved contacts, password and accounts) won't be affected."
: `Are you sure you want to remove all of your ${type}?`;

const onRemove = (accounts: Account[]) => {
const onRemove = (type: string, accounts: Account[]) => {
const account = accounts[0];
const isLast = accounts.length === accounts.length;
const isLast = accounts.length === implicitAccounts.length;

return openWith(
<ConfirmationModal
buttonLabel={buttonLabel(isLast)}
description={description(isLast, account.type)}
description={description(isLast, type)}
onSubmit={() => {
if (account.type === "mnemonic") {
removeMnemonic(account.seedFingerPrint);
} else if (account.type !== "multisig") {
removeNonMnemonic(account.type);
}
onClose();
goBack();
}}
title="Remove All Accounts"
/>
Expand Down Expand Up @@ -122,7 +122,7 @@ export const AccountSelectorModal = () => {
color={color("500")}
aria-label={`Remove ${type} accounts`}
icon={<TrashIcon />}
onClick={() => onRemove(accounts)}
onClick={() => onRemove(type, accounts)}
size="sm"
variant="ghost"
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,8 @@
import {
Button,
Flex,
Heading,
ModalContent,
ModalFooter,
ModalHeader,
Text,
} from "@chakra-ui/react";
import { useDynamicModalContext } from "@umami/components";
import { type LedgerAccount, type SecretKeyAccount, type SocialAccount } from "@umami/core";
import { useImplicitAccounts, useRemoveAccount } from "@umami/state";

import { AlertIcon } from "../../assets/icons";
import { useColor } from "../../styles/useColor";
import { ModalCloseButton } from "../CloseButton";
import { ConfirmationModal } from "../ConfirmationModal";

type RemoveAccountModalProps = {
account: SocialAccount | LedgerAccount | SecretKeyAccount;
Expand All @@ -22,7 +11,6 @@ type RemoveAccountModalProps = {
export const RemoveAccountModal = ({ account }: RemoveAccountModalProps) => {
const { goBack, onClose } = useDynamicModalContext();
const removeAccount = useRemoveAccount();
const color = useColor();

const isLastImplicitAccount = useImplicitAccounts().length === 1;

Expand Down Expand Up @@ -50,24 +38,11 @@ export const RemoveAccountModal = ({ account }: RemoveAccountModalProps) => {
}

return (
<ModalContent>
<ModalHeader>
<Flex alignItems="center" justifyContent="center" flexDirection="column">
<AlertIcon width="24px" color="red" />
<Heading marginTop="18px" marginBottom="12px" size="xl">
Remove Account
</Heading>
<Text maxWidth="340px" color={color("700")} fontWeight="400" size="md">
{description}
</Text>
</Flex>
<ModalCloseButton />
</ModalHeader>
<ModalFooter>
<Button width="full" onClick={handleRemoveAccount} variant="alert">
{buttonLabel}
</Button>
</ModalFooter>
</ModalContent>
<ConfirmationModal
buttonLabel={buttonLabel}
description={description}
onSubmit={handleRemoveAccount}
title="Remove Account"
/>
);
};
2 changes: 1 addition & 1 deletion apps/web/src/components/Menu/LogoutModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { ConfirmationModal } from "../ConfirmationModal";
export const LogoutModal = () => (
<ConfirmationModal
buttonLabel="Logout"
description="Are you sure you want to logout?"
description="Before logging out, make sure your mnemonic phrase is securely saved. Losing this phrase could result in permanent loss of access to your data."
onSubmit={() => logout(persistor)}
title="Logout"
/>
Expand Down

1 comment on commit cfecc97

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Title Lines Statements Branches Functions
apps/desktop Coverage: 83%
83.79% (1758/2098) 78.94% (825/1045) 78.45% (448/571)
apps/web Coverage: 83%
83.79% (1758/2098) 78.94% (825/1045) 78.45% (448/571)
packages/components Coverage: 97%
97.1% (134/138) 96.49% (55/57) 82.92% (34/41)
packages/core Coverage: 82%
82.89% (223/269) 73.18% (101/138) 81.35% (48/59)
packages/crypto Coverage: 100%
100% (28/28) 100% (3/3) 100% (5/5)
packages/data-polling Coverage: 98%
96.55% (140/145) 95.45% (21/22) 92.85% (39/42)
packages/multisig Coverage: 98%
98.4% (123/125) 89.47% (17/19) 100% (33/33)
packages/social-auth Coverage: 100%
100% (21/21) 100% (11/11) 100% (3/3)
packages/state Coverage: 84%
83.64% (772/923) 80.78% (164/203) 78.22% (291/372)
packages/tezos Coverage: 86%
85.57% (89/104) 89.47% (17/19) 82.75% (24/29)
packages/tzkt Coverage: 86%
84.05% (58/69) 81.25% (13/16) 76.92% (30/39)

Please sign in to comment.