From 41b7fc9893da7062441af5b350ab4239d720be1f Mon Sep 17 00:00:00 2001 From: Micaela Estabillo <100321200+micaelae@users.noreply.github.com> Date: Wed, 12 Feb 2025 14:54:34 -0800 Subject: [PATCH 01/24] chore: show multichain network icons (#30276) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## **Description** This adds the multichain network icon mapping to the `getImageForChainId` function so network icons can be displayed for non-EVM assets [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/30276?quickstart=1) ## **Related issues** Fixes:N/A ## **Manual testing steps** 1. EVM network asset pickers should not be affected 2. Changes in multichain networks will only be visible after Swaps/Bridge supports them (separate PR) ## **Screenshots/Recordings** ### **Before** ### **After** ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --- .../asset-picker-modal/Asset.tsx | 8 ++----- .../asset-picker-modal/AssetList.tsx | 8 ++----- .../asset-picker-modal-network.tsx | 8 ++----- .../asset-picker-modal/asset-picker-modal.tsx | 15 ++++--------- .../asset-picker/asset-picker.tsx | 10 ++++----- ui/pages/bridge/quotes/bridge-quote-card.tsx | 22 ++++++------------- .../transaction-details.tsx | 10 +++------ ui/selectors/multichain.ts | 9 ++++---- 8 files changed, 29 insertions(+), 61 deletions(-) diff --git a/ui/components/multichain/asset-picker-amount/asset-picker-modal/Asset.tsx b/ui/components/multichain/asset-picker-amount/asset-picker-modal/Asset.tsx index e247409f848e..bf29d5669333 100644 --- a/ui/components/multichain/asset-picker-amount/asset-picker-modal/Asset.tsx +++ b/ui/components/multichain/asset-picker-amount/asset-picker-modal/Asset.tsx @@ -11,8 +11,8 @@ import { TokenListItem } from '../../token-list-item'; import { isEqualCaseInsensitive } from '../../../../../shared/modules/string-utils'; import { formatAmount } from '../../../../pages/confirmations/components/simulation-details/formatAmount'; import { getIntlLocale } from '../../../../ducks/locale/locale'; -import { CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP } from '../../../../../shared/constants/network'; import { formatCurrency } from '../../../../helpers/utils/confirm-tx.util'; +import { getImageForChainId } from '../../../../selectors/multichain'; import { AssetWithDisplayData, ERC20Asset, NativeAsset } from './types'; type AssetProps = AssetWithDisplayData & { @@ -78,11 +78,7 @@ export default function Asset({ primary={isTokenChainIdInWallet ? primaryAmountToUse : undefined} title={title} tooltipText={tooltipText} - tokenChainImage={ - CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP[ - chainId as keyof typeof CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP - ] - } + tokenChainImage={getImageForChainId(chainId)} isPrimaryTokenSymbolHidden {...assetItemProps} /> diff --git a/ui/components/multichain/asset-picker-amount/asset-picker-modal/AssetList.tsx b/ui/components/multichain/asset-picker-amount/asset-picker-modal/AssetList.tsx index afbaae178f2c..5cafc73018cd 100644 --- a/ui/components/multichain/asset-picker-amount/asset-picker-modal/AssetList.tsx +++ b/ui/components/multichain/asset-picker-amount/asset-picker-modal/AssetList.tsx @@ -27,7 +27,7 @@ import { import { TokenListItem } from '../..'; import LoadingScreen from '../../../ui/loading-screen'; import { useI18nContext } from '../../../../hooks/useI18nContext'; -import { CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP } from '../../../../../shared/constants/network'; +import { getImageForChainId } from '../../../../selectors/multichain'; import AssetComponent from './Asset'; import { AssetWithDisplayData, ERC20Asset, NFT, NativeAsset } from './types'; @@ -157,11 +157,7 @@ export default function AssetList({ secondary={secondaryCurrencyValue} tokenImage={token.image} isPrimaryTokenSymbolHidden - tokenChainImage={ - CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP[ - token.chainId as keyof typeof CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP - ] - } + tokenChainImage={getImageForChainId(token.chainId)} {...assetItemProps} /> ) : ( diff --git a/ui/components/multichain/asset-picker-amount/asset-picker-modal/asset-picker-modal-network.tsx b/ui/components/multichain/asset-picker-amount/asset-picker-modal/asset-picker-modal-network.tsx index a682c85a2cd9..c87af818700f 100644 --- a/ui/components/multichain/asset-picker-amount/asset-picker-modal/asset-picker-modal-network.tsx +++ b/ui/components/multichain/asset-picker-amount/asset-picker-modal/asset-picker-modal-network.tsx @@ -26,7 +26,6 @@ import { Text, AvatarNetworkSize, } from '../../../component-library'; -import { CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP } from '../../../../../shared/constants/network'; ///: BEGIN:ONLY_INCLUDE_IF(build-main,build-beta,build-flask) import { useI18nContext } from '../../../../hooks/useI18nContext'; ///: END:ONLY_INCLUDE_IF @@ -36,6 +35,7 @@ import { getCurrentCurrency } from '../../../../ducks/metamask/metamask'; import { formatCurrency } from '../../../../helpers/utils/confirm-tx.util'; import { useMultichainBalances } from '../../../../hooks/useMultichainBalances'; import { NETWORK_TO_SHORT_NETWORK_NAME_MAP } from '../../../../../shared/constants/bridge'; +import { getImageForChainId } from '../../../../selectors/multichain'; /** * AssetPickerModalNetwork component displays a modal for selecting a network in the asset picker. @@ -244,11 +244,7 @@ export const AssetPickerModalNetwork = ({ onNetworkChange(networkConfig); onBack(); }} - iconSrc={ - CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP[ - chainId as keyof typeof CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP - ] - } + iconSrc={getImageForChainId(chainId)} iconSize={AvatarNetworkSize.Sm} focus={false} disabled={shouldDisableNetwork?.(networkConfig)} diff --git a/ui/components/multichain/asset-picker-amount/asset-picker-modal/asset-picker-modal.tsx b/ui/components/multichain/asset-picker-amount/asset-picker-modal/asset-picker-modal.tsx index b9c212da8ea0..9da156bc4a0d 100644 --- a/ui/components/multichain/asset-picker-amount/asset-picker-modal/asset-picker-modal.tsx +++ b/ui/components/multichain/asset-picker-amount/asset-picker-modal/asset-picker-modal.tsx @@ -53,15 +53,13 @@ import { useTokenTracker } from '../../../../hooks/useTokenTracker'; import { getRenderableTokenData } from '../../../../hooks/useTokensToSearch'; import { getSwapsBlockedTokens } from '../../../../ducks/send'; import { isEqualCaseInsensitive } from '../../../../../shared/modules/string-utils'; -import { - CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP, - NETWORK_TO_NAME_MAP, -} from '../../../../../shared/constants/network'; +import { NETWORK_TO_NAME_MAP } from '../../../../../shared/constants/network'; import { useMultichainBalances } from '../../../../hooks/useMultichainBalances'; import { AvatarType } from '../../avatar-group/avatar-group.types'; import { NETWORK_TO_SHORT_NETWORK_NAME_MAP } from '../../../../../shared/constants/bridge'; import { useAsyncResult } from '../../../../hooks/useAsyncResult'; import { fetchTopAssetsList } from '../../../../pages/swaps/swaps.util'; +import { getImageForChainId } from '../../../../selectors/multichain'; import { ERC20Asset, NativeAsset, @@ -412,11 +410,6 @@ export function AssetPickerModal({ selectedNetwork, ]); - const getNetworkImageUrl = (networkChainId: string) => - CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP[ - networkChainId as keyof typeof CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP - ]; - const getNetworkPickerLabel = () => { if (!isMultiselectEnabled) { return ( @@ -477,7 +470,7 @@ export function AssetPickerModal({ label={getNetworkPickerLabel()} src={ selectedNetwork?.chainId - ? getNetworkImageUrl(selectedNetwork.chainId) + ? getImageForChainId(selectedNetwork.chainId) : undefined } avatarGroupProps={ @@ -485,7 +478,7 @@ export function AssetPickerModal({ ? { limit: 2, members: selectedChainIds.map((c) => ({ - avatarValue: getNetworkImageUrl(c), + avatarValue: getImageForChainId(c) ?? '', symbol: NETWORK_TO_SHORT_NETWORK_NAME_MAP[ c as keyof typeof NETWORK_TO_SHORT_NETWORK_NAME_MAP diff --git a/ui/components/multichain/asset-picker-amount/asset-picker/asset-picker.tsx b/ui/components/multichain/asset-picker-amount/asset-picker/asset-picker.tsx index a7592bbd79ce..e8da53856811 100644 --- a/ui/components/multichain/asset-picker-amount/asset-picker/asset-picker.tsx +++ b/ui/components/multichain/asset-picker-amount/asset-picker/asset-picker.tsx @@ -43,11 +43,11 @@ import { import { TabName } from '../asset-picker-modal/asset-picker-modal-tabs'; import { AssetPickerModalNetwork } from '../asset-picker-modal/asset-picker-modal-network'; import { - CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP, GOERLI_DISPLAY_NAME, SEPOLIA_DISPLAY_NAME, } from '../../../../../shared/constants/network'; import { useMultichainBalances } from '../../../../hooks/useMultichainBalances'; +import { getImageForChainId } from '../../../../selectors/multichain'; const ELLIPSIFY_LENGTH = 13; // 6 (start) + 4 (end) + 3 (...) @@ -163,11 +163,9 @@ export function AssetPicker({ return undefined; }; - const networkImageSrc = - selectedNetwork?.chainId && - CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP[ - selectedNetwork.chainId as keyof typeof CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP - ]; + const networkImageSrc = selectedNetwork?.chainId + ? getImageForChainId(selectedNetwork.chainId) + : undefined; const handleButtonClick = () => { if (networkProps && !networkProps.network) { diff --git a/ui/pages/bridge/quotes/bridge-quote-card.tsx b/ui/pages/bridge/quotes/bridge-quote-card.tsx index 0baa8de2ab2e..303e158ea91b 100644 --- a/ui/pages/bridge/quotes/bridge-quote-card.tsx +++ b/ui/pages/bridge/quotes/bridge-quote-card.tsx @@ -45,10 +45,10 @@ import { BRIDGE_MM_FEE_RATE, NETWORK_TO_SHORT_NETWORK_NAME_MAP, } from '../../../../shared/constants/bridge'; -import { CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP } from '../../../../shared/constants/network'; import { decimalToPrefixedHex } from '../../../../shared/modules/conversion.utils'; import { TERMS_OF_USE_LINK } from '../../../../shared/constants/terms'; import { getIntlLocale } from '../../../ducks/locale/locale'; +import { getImageForChainId } from '../../../selectors/multichain'; import { BridgeQuotesModal } from './bridge-quotes-modal'; export const BridgeQuoteCard = () => { @@ -130,13 +130,9 @@ export const BridgeQuoteCard = () => { @@ -152,13 +148,9 @@ export const BridgeQuoteCard = () => { diff --git a/ui/pages/bridge/transaction-details/transaction-details.tsx b/ui/pages/bridge/transaction-details/transaction-details.tsx index 3e2a8900717d..cea276dbad1e 100644 --- a/ui/pages/bridge/transaction-details/transaction-details.tsx +++ b/ui/pages/bridge/transaction-details/transaction-details.tsx @@ -47,7 +47,6 @@ import { import { formatDate } from '../../../helpers/utils/util'; import { ConfirmInfoRowDivider as Divider } from '../../../components/app/confirm/info/row'; import { useI18nContext } from '../../../hooks/useI18nContext'; -import { CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP } from '../../../../shared/constants/network'; import { selectedAddressTxListSelector } from '../../../selectors'; import { MetaMetricsContextProp, @@ -63,6 +62,7 @@ import { NETWORK_TO_SHORT_NETWORK_NAME_MAP, AllowedBridgeChainIds, } from '../../../../shared/constants/bridge'; +import { getImageForChainId } from '../../../selectors/multichain'; import TransactionDetailRow from './transaction-detail-row'; import BridgeExplorerLinks from './bridge-explorer-links'; import BridgeStepList from './bridge-step-list'; @@ -202,15 +202,11 @@ const CrossChainSwapTxDetails = () => { : StatusTypes.PENDING; const srcChainIconUrl = srcNetwork - ? CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP[ - srcNetwork.chainId as keyof typeof CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP - ] + ? getImageForChainId(srcNetwork.chainId) : undefined; const destChainIconUrl = destNetwork - ? CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP[ - destNetwork.chainId as keyof typeof CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP - ] + ? getImageForChainId(destNetwork.chainId) : undefined; const srcNetworkName = diff --git a/ui/selectors/multichain.ts b/ui/selectors/multichain.ts index a21c2d84015c..acaeb5d7a050 100644 --- a/ui/selectors/multichain.ts +++ b/ui/selectors/multichain.ts @@ -15,6 +15,7 @@ import { MULTICHAIN_PROVIDER_CONFIGS, MultichainNetworks, MULTICHAIN_ACCOUNT_TYPE_TO_MAINNET, + MULTICHAIN_TOKEN_IMAGE_MAP, } from '../../shared/constants/multichain/networks'; import { getCompletedOnboarding, @@ -433,10 +434,10 @@ function getNonEvmCachedBalance( } export function getImageForChainId(chainId: string) { - const evmChainIdKey = - chainId as keyof typeof CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP; - - return CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP[evmChainIdKey]; + return { + ...CHAIN_ID_TO_NETWORK_IMAGE_URL_MAP, + ...MULTICHAIN_TOKEN_IMAGE_MAP, + }[chainId]; } // This selector is not compatible with `useMultichainSelector` since it uses the selected From d98ac206ee049bbd7603354272aea1efec787133 Mon Sep 17 00:00:00 2001 From: George Marshall Date: Wed, 12 Feb 2025 15:00:14 -0800 Subject: [PATCH 02/24] chore: adding storybook story for unconnected account alert component (#30239) ## **Description** This PR adds a Storybook story for the `UnconnectedAccountAlert` component, improving coverage and making it easier to view and develop in isolation. [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/30239?quickstart=1) ## **Related issues** Fixes: N/A ## **Manual testing steps** 1. Go to the latest storybook build in this PR 2. Navigate to `Components/App/Alerts/UnconnectedAccountAlert` in the sidebar 3. Verify the `UnconnectedAccountAlert` component renders correctly in the Default story ## **Screenshots/Recordings** ### **Before** N/A - New component story ### **After** https://github.com/user-attachments/assets/aeca8e3a-41b5-4628-b529-2dc130dcb6a4 ## **Pre-merge author checklist** - [x] I've followed MetaMask Contributor Docs and MetaMask Extension Coding Standards - [x] I've completed the PR template to the best of my ability - [x] I've included tests through Storybook stories - [x] I've documented my code through component documentation and stories - [x] I've applied the right labels on the PR ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed) - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots --- .../unconnected-account-alert.stories.tsx | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 ui/components/app/alerts/unconnected-account-alert/unconnected-account-alert.stories.tsx diff --git a/ui/components/app/alerts/unconnected-account-alert/unconnected-account-alert.stories.tsx b/ui/components/app/alerts/unconnected-account-alert/unconnected-account-alert.stories.tsx new file mode 100644 index 000000000000..a98ef148d241 --- /dev/null +++ b/ui/components/app/alerts/unconnected-account-alert/unconnected-account-alert.stories.tsx @@ -0,0 +1,54 @@ +import React from 'react'; +import { Provider } from 'react-redux'; +import { configureStore } from '@reduxjs/toolkit'; +import type { Meta, StoryObj } from '@storybook/react'; +import testData from '../../../../../.storybook/test-data'; +import UnconnectedAccountAlert from './unconnected-account-alert'; + +const mockState = { + ...testData, + metamask: { + ...testData.metamask, + unconnectedAccount: { + state: 'IDLE', + }, + }, + activeTab: { + id: 113, + title: 'E2E Test Dapp', + origin: 'https://metamask.github.io', + protocol: 'https:', + url: 'https://metamask.github.io/test-dapp/', + }, +}; + +const store = configureStore({ + reducer: (state = mockState) => state, + preloadedState: mockState, +}); + +const meta = { + title: 'Components/App/Alerts/UnconnectedAccountAlert', + component: UnconnectedAccountAlert, + decorators: [ + (Story) => ( + + + + ), + ], + parameters: { + docs: { + description: { + component: 'Alert shown when the selected account is not connected to the current dapp', + }, + }, + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const DefaultStory: Story = { + name: 'Default', +}; From f38a93f24ebb20ad4f489ad714953e57936c1c9f Mon Sep 17 00:00:00 2001 From: David Murdoch <187813+davidmurdoch@users.noreply.github.com> Date: Wed, 12 Feb 2025 18:13:12 -0500 Subject: [PATCH 03/24] refactor: remove circular dependencies in `ui/components/component-library/*` (#30267) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR solves an issue with circular dependencies. It does not change the behavior of the application. It only rearranges functions/files to avoid circular references. This PR changes some imports to `import type { ... }` imports, which don't count for circular dependencies, and changes other from referencing it's own parent `index.ts` file to just referencing the main file with the component it needs directly. --- development/circular-deps.jsonc | 168 ------------------ .../avatar-account/avatar-account.test.tsx | 6 +- .../avatar-base/avatar-base.stories.tsx | 4 +- .../avatar-favicon/avatar-favicon.stories.tsx | 3 +- .../avatar-favicon/avatar-favicon.test.tsx | 4 +- .../avatar-icon/avatar-icon.stories.tsx | 6 +- .../avatar-icon/avatar-icon.test.tsx | 5 +- .../avatar-network/avatar-network.stories.tsx | 2 +- .../avatar-network/avatar-network.test.tsx | 4 +- .../avatar-token/avatar-token.stories.tsx | 17 +- .../avatar-token/avatar-token.test.tsx | 3 +- .../badge-wrapper/badge-wrapper.stories.tsx | 19 +- .../badge-wrapper/badge-wrapper.tsx | 3 +- .../badge-wrapper/badge-wrapper.types.ts | 7 +- .../component-library/banner-alert/README.mdx | 2 +- .../banner-alert/banner-alert.stories.tsx | 8 +- .../banner-alert/banner-alert.test.tsx | 4 +- .../banner-alert/banner-alert.tsx | 5 +- .../component-library/banner-base/README.mdx | 2 +- .../banner-base/banner-base.stories.tsx | 11 +- .../banner-base/banner-base.test.tsx | 2 +- .../banner-base/banner-base.tsx | 15 +- .../component-library/banner-tip/README.mdx | 2 +- .../banner-tip/banner-tip.stories.tsx | 15 +- .../banner-tip/banner-tip.test.tsx | 4 +- .../banner-tip/banner-tip.tsx | 5 +- .../component-library/box/box.stories.tsx | 2 +- .../component-library/box/box.test.tsx | 3 +- .../button-base/button-base.stories.tsx | 4 +- .../button-base/button-base.test.tsx | 2 +- .../button-base/button-base.tsx | 3 +- .../button-icon/button-icon.stories.tsx | 2 +- .../button-icon/button-icon.test.tsx | 2 +- .../button-icon/button-icon.tsx | 5 +- .../button-link/button-link.stories.tsx | 6 +- .../button-link/button-link.test.tsx | 5 +- .../button-link/button-link.tsx | 4 +- .../button-primary/button-primary.stories.tsx | 5 +- .../button-primary/button-primary.test.tsx | 5 +- .../button-secondary.stories.tsx | 6 +- .../button-secondary.test.tsx | 5 +- .../button/button.stories.tsx | 6 +- .../component-library/button/button.test.tsx | 4 +- .../checkbox/checkbox.stories.tsx | 4 +- .../checkbox/checkbox.test.tsx | 4 +- .../component-library/checkbox/checkbox.tsx | 8 +- .../container/container.stories.tsx | 2 +- .../container/container.test.tsx | 2 +- .../component-library/container/container.tsx | 2 +- .../form-text-field.stories.tsx | 23 +-- .../form-text-field/form-text-field.test.tsx | 3 +- .../form-text-field/form-text-field.tsx | 15 +- .../header-base/header-base.stories.tsx | 14 +- .../header-base/header-base.test.tsx | 2 +- .../header-base/header-base.tsx | 2 +- .../component-library/help-text/README.mdx | 2 +- .../help-text/help-text.stories.tsx | 4 +- .../help-text/help-text.test.tsx | 5 +- .../component-library/help-text/help-text.tsx | 7 +- .../component-library/icon/icon.stories.tsx | 19 +- .../component-library/input/input.stories.tsx | 4 +- .../component-library/label/README.mdx | 2 +- .../component-library/label/label.stories.tsx | 4 +- .../component-library/label/label.test.tsx | 3 +- .../modal-body/modal-body.stories.tsx | 2 +- .../modal-body/modal-body.tsx | 2 +- .../deprecated/modal-content.tsx | 6 +- .../modal-content/modal-content.stories.tsx | 17 +- .../modal-content/modal-content.test.tsx | 2 +- .../modal-content/modal-content.tsx | 6 +- .../modal-footer/modal-footer.stories.tsx | 4 +- .../modal-footer/modal-footer.tsx | 13 +- .../modal-header/deprecated/modal-header.tsx | 7 +- .../modal-header/modal-header.stories.tsx | 5 +- .../modal-header/modal-header.test.tsx | 2 +- .../modal-header/modal-header.tsx | 7 +- .../component-library/modal/modal.stories.tsx | 25 ++- .../picker-network/picker-network.stories.tsx | 2 +- .../picker-network/picker-network.test.tsx | 2 +- .../picker-network/picker-network.tsx | 14 +- .../popover-header/popover-header.stories.tsx | 4 +- .../popover-header/popover-header.test.tsx | 2 +- .../popover-header/popover-header.tsx | 7 +- .../popover/popover.stories.tsx | 8 +- .../component-library/popover/popover.tsx | 2 +- .../select-button/select-button.stories.tsx | 18 +- .../select-button/select-button.test.tsx | 6 +- .../select-button/select-button.tsx | 6 +- .../select-option/select-option.tsx | 2 +- .../select-wrapper/select-wrapper.stories.tsx | 4 +- .../select-wrapper/select-wrapper.test.tsx | 5 +- .../select-wrapper/select-wrapper.tsx | 4 +- .../sensitive-text/sensitive-text.stories.tsx | 10 +- .../skeleton/skeleton.stories.tsx | 4 +- .../component-library/skeleton/skeleton.tsx | 2 +- .../tag-url/tag-url.stories.tsx | 2 +- .../component-library/tag-url/tag-url.tsx | 16 +- ui/components/component-library/tag/tag.tsx | 5 +- .../text-field-search/README.mdx | 2 +- .../text-field-search/text-field-search.tsx | 14 +- .../text-field/text-field.stories.tsx | 24 +-- .../text-field/text-field.tsx | 6 +- .../component-library/text/text.stories.tsx | 2 +- ui/components/component-library/text/text.tsx | 3 +- .../textarea/textarea.stories.tsx | 2 +- .../component-library/textarea/textarea.tsx | 3 +- .../multichain/avatar-group/avatar-group.tsx | 32 ++-- .../avatar-group/avatar-group.types.tsx | 2 +- 108 files changed, 320 insertions(+), 519 deletions(-) diff --git a/development/circular-deps.jsonc b/development/circular-deps.jsonc index a2f7618b4531..18589944546e 100644 --- a/development/circular-deps.jsonc +++ b/development/circular-deps.jsonc @@ -35,174 +35,6 @@ "ui/components/app/name/name-details/name-details.tsx", "ui/components/app/name/name.tsx" ], - [ - "ui/components/component-library/avatar-account/avatar-account.tsx", - "ui/components/component-library/avatar-account/index.ts", - "ui/components/component-library/avatar-base/avatar-base.tsx", - "ui/components/component-library/avatar-base/index.ts", - "ui/components/component-library/index.ts", - "ui/components/component-library/text/index.ts", - "ui/components/component-library/text/text.tsx" - ], - [ - "ui/components/component-library/badge-wrapper/badge-wrapper.tsx", - "ui/components/component-library/badge-wrapper/index.ts", - "ui/components/component-library/index.ts" - ], - [ - "ui/components/component-library/banner-alert/banner-alert.tsx", - "ui/components/component-library/banner-alert/index.ts", - "ui/components/component-library/banner-base/banner-base.tsx", - "ui/components/component-library/banner-base/index.ts", - "ui/components/component-library/index.ts" - ], - [ - "ui/components/component-library/banner-alert/banner-alert.tsx", - "ui/components/component-library/banner-alert/index.ts", - "ui/components/component-library/index.ts" - ], - [ - "ui/components/component-library/banner-tip/banner-tip.tsx", - "ui/components/component-library/banner-tip/index.ts", - "ui/components/component-library/index.ts" - ], - [ - "ui/components/component-library/button-base/button-base.tsx", - "ui/components/component-library/button-base/index.ts", - "ui/components/component-library/index.ts" - ], - [ - "ui/components/component-library/button-icon/button-icon.tsx", - "ui/components/component-library/button-icon/index.ts", - "ui/components/component-library/index.ts" - ], - [ - "ui/components/component-library/button-link/button-link.tsx", - "ui/components/component-library/button-link/index.ts", - "ui/components/component-library/index.ts" - ], - [ - "ui/components/component-library/checkbox/checkbox.tsx", - "ui/components/component-library/checkbox/index.ts", - "ui/components/component-library/index.ts" - ], - [ - "ui/components/component-library/container/container.tsx", - "ui/components/component-library/container/index.ts", - "ui/components/component-library/index.ts" - ], - [ - "ui/components/component-library/form-text-field/form-text-field.tsx", - "ui/components/component-library/form-text-field/index.ts", - "ui/components/component-library/index.ts" - ], - [ - "ui/components/component-library/header-base/header-base.tsx", - "ui/components/component-library/header-base/index.ts", - "ui/components/component-library/index.ts" - ], - [ - "ui/components/component-library/help-text/help-text.tsx", - "ui/components/component-library/help-text/index.ts" - ], - [ - "ui/components/component-library/index.ts", - "ui/components/component-library/modal-body/index.ts", - "ui/components/component-library/modal-body/modal-body.tsx" - ], - [ - "ui/components/component-library/index.ts", - "ui/components/component-library/modal-content/index.ts", - "ui/components/component-library/modal-content/modal-content.tsx" - ], - [ - "ui/components/component-library/index.ts", - "ui/components/component-library/modal-footer/index.ts", - "ui/components/component-library/modal-footer/modal-footer.tsx" - ], - [ - "ui/components/component-library/index.ts", - "ui/components/component-library/modal-header/index.ts", - "ui/components/component-library/modal-header/modal-header.tsx" - ], - [ - "ui/components/component-library/index.ts", - "ui/components/component-library/picker-network/index.ts", - "ui/components/component-library/picker-network/picker-network.tsx" - ], - [ - "ui/components/component-library/index.ts", - "ui/components/component-library/picker-network/index.ts", - "ui/components/component-library/picker-network/picker-network.tsx", - "ui/components/component-library/picker-network/picker-network.types.ts", - "ui/components/multichain/avatar-group/avatar-group.types.tsx" - ], - [ - "ui/components/component-library/index.ts", - "ui/components/component-library/picker-network/index.ts", - "ui/components/component-library/picker-network/picker-network.tsx", - "ui/components/multichain/avatar-group/avatar-group.tsx", - "ui/components/multichain/avatar-group/index.ts" - ], - [ - "ui/components/component-library/index.ts", - "ui/components/component-library/popover-header/index.ts", - "ui/components/component-library/popover-header/popover-header.tsx" - ], - [ - "ui/components/component-library/index.ts", - "ui/components/component-library/popover/index.ts", - "ui/components/component-library/popover/popover.tsx" - ], - [ - "ui/components/component-library/index.ts", - "ui/components/component-library/select-button/index.ts", - "ui/components/component-library/select-button/select-button.tsx" - ], - [ - "ui/components/component-library/index.ts", - "ui/components/component-library/select-button/index.ts", - "ui/components/component-library/select-button/select-button.tsx", - "ui/components/component-library/select-wrapper/index.ts", - "ui/components/component-library/select-wrapper/select-wrapper.tsx" - ], - [ - "ui/components/component-library/index.ts", - "ui/components/component-library/select-option/index.ts", - "ui/components/component-library/select-option/select-option.tsx" - ], - [ - "ui/components/component-library/index.ts", - "ui/components/component-library/tag-url/index.ts", - "ui/components/component-library/tag-url/tag-url.tsx" - ], - [ - "ui/components/component-library/index.ts", - "ui/components/component-library/tag/index.ts", - "ui/components/component-library/tag/tag.tsx" - ], - [ - "ui/components/component-library/index.ts", - "ui/components/component-library/text-field-search/index.ts", - "ui/components/component-library/text-field-search/text-field-search.tsx" - ], - [ - "ui/components/component-library/index.ts", - "ui/components/component-library/text-field/index.ts", - "ui/components/component-library/text-field/text-field.tsx" - ], - [ - "ui/components/component-library/modal-header/deprecated/index.ts", - "ui/components/component-library/modal-header/deprecated/modal-header.tsx" - ], - [ - "ui/components/component-library/modal-header/index.ts", - "ui/components/component-library/modal-header/modal-header.tsx" - ], - [ - "ui/components/component-library/popover-header/index.ts", - "ui/components/component-library/popover-header/popover-header.tsx" - ], [ "ui/components/multichain/pages/send/components/account-picker.tsx", "ui/components/multichain/pages/send/components/index.ts" diff --git a/ui/components/component-library/avatar-account/avatar-account.test.tsx b/ui/components/component-library/avatar-account/avatar-account.test.tsx index 9279c1af93a0..e104c5db8682 100644 --- a/ui/components/component-library/avatar-account/avatar-account.test.tsx +++ b/ui/components/component-library/avatar-account/avatar-account.test.tsx @@ -1,8 +1,12 @@ /* eslint-disable jest/require-top-level-describe */ import { render } from '@testing-library/react'; import React from 'react'; -import { AvatarAccount, AvatarAccountSize, AvatarAccountVariant } from '.'; import 'jest-canvas-mock'; +import { AvatarAccount } from './avatar-account'; +import { + AvatarAccountSize, + AvatarAccountVariant, +} from './avatar-account.types'; describe('AvatarAccount', () => { it('should render correctly', () => { diff --git a/ui/components/component-library/avatar-base/avatar-base.stories.tsx b/ui/components/component-library/avatar-base/avatar-base.stories.tsx index a890f418a213..64ecc8b6b836 100644 --- a/ui/components/component-library/avatar-base/avatar-base.stories.tsx +++ b/ui/components/component-library/avatar-base/avatar-base.stories.tsx @@ -9,9 +9,11 @@ import { IconColor, } from '../../../helpers/constants/design-system'; -import { AvatarBase, Icon, IconName, Box } from '..'; import { AvatarBaseSize } from './avatar-base.types'; import README from './README.mdx'; +import { AvatarBase } from './avatar-base'; +import { Box } from '../box'; +import { Icon, IconName } from '../icon'; const marginSizeKnobOptions = [ 0, diff --git a/ui/components/component-library/avatar-favicon/avatar-favicon.stories.tsx b/ui/components/component-library/avatar-favicon/avatar-favicon.stories.tsx index 18b0248e3499..8b07e15cd459 100644 --- a/ui/components/component-library/avatar-favicon/avatar-favicon.stories.tsx +++ b/ui/components/component-library/avatar-favicon/avatar-favicon.stories.tsx @@ -9,7 +9,8 @@ import { import { Box } from '../box'; import README from './README.mdx'; -import { AvatarFavicon, AvatarFaviconSize } from '.'; +import { AvatarFavicon } from './avatar-favicon'; +import { AvatarFaviconSize } from './avatar-favicon.types'; export default { title: 'Components/ComponentLibrary/AvatarFavicon', diff --git a/ui/components/component-library/avatar-favicon/avatar-favicon.test.tsx b/ui/components/component-library/avatar-favicon/avatar-favicon.test.tsx index aa69e04127e5..cf679c88a665 100644 --- a/ui/components/component-library/avatar-favicon/avatar-favicon.test.tsx +++ b/ui/components/component-library/avatar-favicon/avatar-favicon.test.tsx @@ -2,9 +2,9 @@ import { render, screen } from '@testing-library/react'; import React from 'react'; -import { IconName } from '..'; +import { IconName } from '../icon'; import { AvatarFaviconSize } from './avatar-favicon.types'; -import { AvatarFavicon } from '.'; +import { AvatarFavicon } from './avatar-favicon'; describe('AvatarFavicon', () => { const args = { diff --git a/ui/components/component-library/avatar-icon/avatar-icon.stories.tsx b/ui/components/component-library/avatar-icon/avatar-icon.stories.tsx index bcd97d8ccee8..8537ebb58e08 100644 --- a/ui/components/component-library/avatar-icon/avatar-icon.stories.tsx +++ b/ui/components/component-library/avatar-icon/avatar-icon.stories.tsx @@ -10,10 +10,10 @@ import { import { Box } from '../box'; -import { IconName } from '..'; - import README from './README.mdx'; -import { AvatarIcon, AvatarIconSize } from '.'; +import { AvatarIcon } from './avatar-icon'; +import { IconName } from '../icon'; +import { AvatarIconSize } from './avatar-icon.types'; export default { title: 'Components/ComponentLibrary/AvatarIcon', diff --git a/ui/components/component-library/avatar-icon/avatar-icon.test.tsx b/ui/components/component-library/avatar-icon/avatar-icon.test.tsx index 17ce35fe0dea..51f63ec3428e 100644 --- a/ui/components/component-library/avatar-icon/avatar-icon.test.tsx +++ b/ui/components/component-library/avatar-icon/avatar-icon.test.tsx @@ -2,12 +2,13 @@ import { render } from '@testing-library/react'; import React from 'react'; -import { IconName } from '..'; import { BackgroundColor, IconColor, } from '../../../helpers/constants/design-system'; -import { AvatarIcon, AvatarIconSize } from '.'; +import { IconName } from '../icon'; +import { AvatarIcon } from './avatar-icon'; +import { AvatarIconSize } from './avatar-icon.types'; describe('AvatarIcon', () => { it('should render correctly', () => { diff --git a/ui/components/component-library/avatar-network/avatar-network.stories.tsx b/ui/components/component-library/avatar-network/avatar-network.stories.tsx index 390ddc3e87cc..c878d322584b 100644 --- a/ui/components/component-library/avatar-network/avatar-network.stories.tsx +++ b/ui/components/component-library/avatar-network/avatar-network.stories.tsx @@ -7,11 +7,11 @@ import { BorderColor, AlignItems, } from '../../../helpers/constants/design-system'; -import { Box } from '..'; import { AvatarNetworkSize } from './avatar-network.types'; import README from './README.mdx'; import { AvatarNetwork } from './avatar-network'; +import { Box } from '../box'; export default { title: 'Components/ComponentLibrary/AvatarNetwork', diff --git a/ui/components/component-library/avatar-network/avatar-network.test.tsx b/ui/components/component-library/avatar-network/avatar-network.test.tsx index ce7e5574cf45..81819ad49276 100644 --- a/ui/components/component-library/avatar-network/avatar-network.test.tsx +++ b/ui/components/component-library/avatar-network/avatar-network.test.tsx @@ -7,8 +7,8 @@ import { BorderColor, TextColor, } from '../../../helpers/constants/design-system'; - -import { AvatarNetwork, AvatarNetworkSize } from '.'; +import { AvatarNetwork } from './avatar-network'; +import { AvatarNetworkSize } from './avatar-network.types'; describe('AvatarNetwork', () => { const args = { diff --git a/ui/components/component-library/avatar-token/avatar-token.stories.tsx b/ui/components/component-library/avatar-token/avatar-token.stories.tsx index dc7af5b453b3..0101dd74bb65 100644 --- a/ui/components/component-library/avatar-token/avatar-token.stories.tsx +++ b/ui/components/component-library/avatar-token/avatar-token.stories.tsx @@ -7,17 +7,14 @@ import { BackgroundColor, BorderColor, } from '../../../helpers/constants/design-system'; -import { - AvatarNetwork, - AvatarNetworkSize, - BadgeWrapper, - Box, - ButtonLink, - ButtonLinkSize, - Text, -} from '..'; import README from './README.mdx'; -import { AvatarToken, AvatarTokenSize } from '.'; +import { AvatarToken } from './avatar-token'; +import { Box } from '../box'; +import { AvatarTokenSize } from './avatar-token.types'; +import { ButtonLink, ButtonLinkSize } from '../button-link'; +import { BadgeWrapper } from '../badge-wrapper'; +import { AvatarNetwork, AvatarNetworkSize } from '../avatar-network'; +import { Text } from '../text'; export default { title: 'Components/ComponentLibrary/AvatarToken', diff --git a/ui/components/component-library/avatar-token/avatar-token.test.tsx b/ui/components/component-library/avatar-token/avatar-token.test.tsx index 90a714505fb3..d3a6674661b3 100644 --- a/ui/components/component-library/avatar-token/avatar-token.test.tsx +++ b/ui/components/component-library/avatar-token/avatar-token.test.tsx @@ -6,7 +6,8 @@ import { BorderColor, TextColor, } from '../../../helpers/constants/design-system'; -import { AvatarToken, AvatarTokenSize } from '.'; +import { AvatarToken } from './avatar-token'; +import { AvatarTokenSize } from './avatar-token.types'; describe('AvatarToken', () => { const args = { diff --git a/ui/components/component-library/badge-wrapper/badge-wrapper.stories.tsx b/ui/components/component-library/badge-wrapper/badge-wrapper.stories.tsx index 1be4c474f4d1..712261c713d6 100644 --- a/ui/components/component-library/badge-wrapper/badge-wrapper.stories.tsx +++ b/ui/components/component-library/badge-wrapper/badge-wrapper.stories.tsx @@ -11,18 +11,6 @@ import { IconColor, } from '../../../helpers/constants/design-system'; -import Box from '../../ui/box/box'; - -import { - AvatarAccount, - AvatarNetwork, - AvatarNetworkSize, - AvatarToken, - Icon, - IconName, - IconSize, - Tag, -} from '..'; import { BadgeWrapperAnchorElementShape, BadgeWrapperPosition, @@ -31,6 +19,13 @@ import { import README from './README.mdx'; import { BadgeWrapper } from './badge-wrapper'; +import { AvatarNetwork, AvatarNetworkSize } from '../avatar-network'; +import { AvatarAccount } from '../avatar-account'; +import { AvatarToken } from '../avatar-token'; + +import Box from '../../ui/box/box'; +import { Icon, IconName, IconSize } from '../icon'; +import { Tag } from '../tag'; export default { title: 'Components/ComponentLibrary/BadgeWrapper', diff --git a/ui/components/component-library/badge-wrapper/badge-wrapper.tsx b/ui/components/component-library/badge-wrapper/badge-wrapper.tsx index 5d046c6150bd..36026228724a 100644 --- a/ui/components/component-library/badge-wrapper/badge-wrapper.tsx +++ b/ui/components/component-library/badge-wrapper/badge-wrapper.tsx @@ -2,9 +2,8 @@ import React from 'react'; import classnames from 'classnames'; import { Display } from '../../../helpers/constants/design-system'; -import { Box } from '..'; -import type { BoxProps, PolymorphicRef } from '..'; +import { Box, type BoxProps, type PolymorphicRef } from '../box'; import { BadgeWrapperPosition, BadgeWrapperAnchorElementShape, diff --git a/ui/components/component-library/badge-wrapper/badge-wrapper.types.ts b/ui/components/component-library/badge-wrapper/badge-wrapper.types.ts index 4dd9a515106e..eac3e87f000e 100644 --- a/ui/components/component-library/badge-wrapper/badge-wrapper.types.ts +++ b/ui/components/component-library/badge-wrapper/badge-wrapper.types.ts @@ -1,10 +1,9 @@ import React from 'react'; - import type { - StyleUtilityProps, - PolymorphicComponentPropWithRef, BoxProps, -} from '..'; + PolymorphicComponentPropWithRef, + StyleUtilityProps, +} from '../box'; export enum BadgeWrapperPosition { topRight = 'top-right', diff --git a/ui/components/component-library/banner-alert/README.mdx b/ui/components/component-library/banner-alert/README.mdx index 45151a6e31be..81eb19a2ad07 100644 --- a/ui/components/component-library/banner-alert/README.mdx +++ b/ui/components/component-library/banner-alert/README.mdx @@ -1,6 +1,6 @@ import { Story, Canvas, ArgsTable } from '@storybook/addon-docs'; import { BannerAlert } from './banner-alert'; -import { BannerBase } from '..'; +import { BannerBase } from '../banner-base'; # BannerAlert diff --git a/ui/components/component-library/banner-alert/banner-alert.stories.tsx b/ui/components/component-library/banner-alert/banner-alert.stories.tsx index 0502ad5e2a9a..c0ad19ff73b8 100644 --- a/ui/components/component-library/banner-alert/banner-alert.stories.tsx +++ b/ui/components/component-library/banner-alert/banner-alert.stories.tsx @@ -5,11 +5,15 @@ import { Display, FlexDirection, } from '../../../helpers/constants/design-system'; -import { ButtonLink, ButtonPrimary, IconName, Box, ButtonLinkSize } from '..'; import README from './README.mdx'; -import { BannerAlert, BannerAlertSeverity } from '.'; +import { BannerAlert } from './banner-alert'; +import { BannerAlertSeverity } from './banner-alert.types'; +import { Box } from '../box'; +import { ButtonLink, ButtonLinkSize } from '../button-link'; +import { IconName } from '../icon'; +import { ButtonPrimary } from '../button-primary'; export default { title: 'Components/ComponentLibrary/BannerAlert', diff --git a/ui/components/component-library/banner-alert/banner-alert.test.tsx b/ui/components/component-library/banner-alert/banner-alert.test.tsx index b1b51fdb7fdc..3147a035825d 100644 --- a/ui/components/component-library/banner-alert/banner-alert.test.tsx +++ b/ui/components/component-library/banner-alert/banner-alert.test.tsx @@ -3,8 +3,8 @@ import { render } from '@testing-library/react'; import React from 'react'; import { renderWithUserEvent } from '../../../../test/lib/render-helpers'; - -import { BannerAlert, BannerAlertSeverity } from '.'; +import { BannerAlert } from './banner-alert'; +import { BannerAlertSeverity } from './banner-alert.types'; describe('BannerAlert', () => { it('should render BannerAlert element correctly', () => { diff --git a/ui/components/component-library/banner-alert/banner-alert.tsx b/ui/components/component-library/banner-alert/banner-alert.tsx index a79551959b1b..9e71caf7bd76 100644 --- a/ui/components/component-library/banner-alert/banner-alert.tsx +++ b/ui/components/component-library/banner-alert/banner-alert.tsx @@ -1,14 +1,13 @@ import React from 'react'; import classnames from 'classnames'; -import { BannerBase, Icon, IconName, IconSize } from '..'; - import { BackgroundColor, IconColor, } from '../../../helpers/constants/design-system'; import { PolymorphicRef } from '../box'; -import { BannerBaseProps } from '../banner-base'; +import { BannerBase, BannerBaseProps } from '../banner-base'; +import { Icon, IconName, IconSize } from '../icon'; import { BannerAlertComponent, BannerAlertProps, diff --git a/ui/components/component-library/banner-base/README.mdx b/ui/components/component-library/banner-base/README.mdx index e4ebea851072..bf01a7cd315f 100644 --- a/ui/components/component-library/banner-base/README.mdx +++ b/ui/components/component-library/banner-base/README.mdx @@ -1,5 +1,5 @@ import { Story, Canvas, ArgsTable } from '@storybook/addon-docs'; -import { BannerBase } from './banner-base'; +import { BannerBase } from '../banner-base'; ### This is a base component. It should not be used in your feature code directly but as a "base" for other UI components diff --git a/ui/components/component-library/banner-base/banner-base.stories.tsx b/ui/components/component-library/banner-base/banner-base.stories.tsx index f5df17ca395d..1a51d1d23171 100644 --- a/ui/components/component-library/banner-base/banner-base.stories.tsx +++ b/ui/components/component-library/banner-base/banner-base.stories.tsx @@ -1,16 +1,11 @@ import React from 'react'; import { Meta, StoryFn } from '@storybook/react'; import { useState } from '@storybook/addons'; -import { - ButtonLink, - ButtonLinkSize, - ButtonPrimary, - Icon, - IconName, - IconSize, -} from '..'; import { BannerBase } from './banner-base'; import README from './README.mdx'; +import { Icon, IconName, IconSize } from '../icon'; +import { ButtonLink, ButtonLinkSize } from '../button-link'; +import { ButtonPrimary } from '../button-primary'; export default { title: 'Components/ComponentLibrary/BannerBase', diff --git a/ui/components/component-library/banner-base/banner-base.test.tsx b/ui/components/component-library/banner-base/banner-base.test.tsx index 09eaf3943c30..6019c652f43b 100644 --- a/ui/components/component-library/banner-base/banner-base.test.tsx +++ b/ui/components/component-library/banner-base/banner-base.test.tsx @@ -4,7 +4,7 @@ import React from 'react'; import { renderWithUserEvent } from '../../../../test/lib/render-helpers'; -import { Icon, IconName } from '..'; +import { Icon, IconName } from '../icon'; import { BannerBase } from './banner-base'; describe('BannerBase', () => { diff --git a/ui/components/component-library/banner-base/banner-base.tsx b/ui/components/component-library/banner-base/banner-base.tsx index 1dc0369b3025..12e4b7c717b7 100644 --- a/ui/components/component-library/banner-base/banner-base.tsx +++ b/ui/components/component-library/banner-base/banner-base.tsx @@ -10,16 +10,11 @@ import { TextVariant, } from '../../../helpers/constants/design-system'; -import { - ButtonLink, - IconName, - ButtonIcon, - Text, - Box, - ButtonLinkSize, - ButtonIconSize, -} from '..'; -import { BoxProps, PolymorphicRef } from '../box'; +import { Text } from '../text'; +import { Box, BoxProps, PolymorphicRef } from '../box'; +import { ButtonLink, ButtonLinkSize } from '../button-link'; +import { ButtonIcon, ButtonIconSize } from '../button-icon'; +import { IconName } from '../icon'; import { BannerBaseComponent, BannerBaseProps } from './banner-base.types'; export const BannerBase: BannerBaseComponent = React.forwardRef( diff --git a/ui/components/component-library/banner-tip/README.mdx b/ui/components/component-library/banner-tip/README.mdx index 49b567384c14..6c9955333833 100644 --- a/ui/components/component-library/banner-tip/README.mdx +++ b/ui/components/component-library/banner-tip/README.mdx @@ -1,6 +1,6 @@ import { Story, Canvas, ArgsTable } from '@storybook/addon-docs'; import { BannerTip } from './banner-tip'; -import { BannerBase } from '..'; +import { BannerBase } from '../banner-base'; # BannerTip diff --git a/ui/components/component-library/banner-tip/banner-tip.stories.tsx b/ui/components/component-library/banner-tip/banner-tip.stories.tsx index 0af4306b79b1..1ff949d941ce 100644 --- a/ui/components/component-library/banner-tip/banner-tip.stories.tsx +++ b/ui/components/component-library/banner-tip/banner-tip.stories.tsx @@ -4,16 +4,13 @@ import { Display, FlexDirection, } from '../../../helpers/constants/design-system'; -import { - ButtonLink, - ButtonLinkSize, - ButtonPrimary, - Box, - Icon, - IconName, -} from '..'; import README from './README.mdx'; -import { BannerTip, BannerTipLogoType } from '.'; +import { BannerTip } from './banner-tip'; +import { BannerTipLogoType } from './banner-tip.types'; +import { Box } from '../box'; +import { ButtonLink, ButtonLinkSize } from '../button-link'; +import { Icon, IconName } from '../icon'; +import { ButtonPrimary } from '../button-primary'; export default { title: 'Components/ComponentLibrary/BannerTip', diff --git a/ui/components/component-library/banner-tip/banner-tip.test.tsx b/ui/components/component-library/banner-tip/banner-tip.test.tsx index af7915cb72c1..6b9c0ce16b88 100644 --- a/ui/components/component-library/banner-tip/banner-tip.test.tsx +++ b/ui/components/component-library/banner-tip/banner-tip.test.tsx @@ -3,8 +3,8 @@ import { render } from '@testing-library/react'; import React from 'react'; import { renderWithUserEvent } from '../../../../test/lib/render-helpers'; - -import { BannerTip, BannerTipLogoType } from '.'; +import { BannerTip } from './banner-tip'; +import { BannerTipLogoType } from './banner-tip.types'; describe('BannerTip', () => { it('should render BannerTip element correctly', () => { diff --git a/ui/components/component-library/banner-tip/banner-tip.tsx b/ui/components/component-library/banner-tip/banner-tip.tsx index e7d67e60c345..9f2d789b6a19 100644 --- a/ui/components/component-library/banner-tip/banner-tip.tsx +++ b/ui/components/component-library/banner-tip/banner-tip.tsx @@ -5,9 +5,8 @@ import { BorderColor, Display, } from '../../../helpers/constants/design-system'; -import { BannerBase, Box } from '..'; -import { BoxProps, PolymorphicRef } from '../box'; -import { BannerBaseProps } from '../banner-base'; +import { Box, BoxProps, PolymorphicRef } from '../box'; +import { BannerBase, BannerBaseProps } from '../banner-base'; import { BannerTipComponent, BannerTipLogoType, diff --git a/ui/components/component-library/box/box.stories.tsx b/ui/components/component-library/box/box.stories.tsx index 8da07a5daada..522f190f78fd 100644 --- a/ui/components/component-library/box/box.stories.tsx +++ b/ui/components/component-library/box/box.stories.tsx @@ -16,7 +16,7 @@ import { FlexWrap, } from '../../../helpers/constants/design-system'; -import { Text } from '..'; +import { Text } from '../text'; import { Box } from './box'; diff --git a/ui/components/component-library/box/box.test.tsx b/ui/components/component-library/box/box.test.tsx index 7aa9125979df..39c58ee77fab 100644 --- a/ui/components/component-library/box/box.test.tsx +++ b/ui/components/component-library/box/box.test.tsx @@ -14,8 +14,7 @@ import { BackgroundColor, TextColor, } from '../../../helpers/constants/design-system'; - -import { Box } from '.'; +import { Box } from './box'; describe('Box', () => { it('should render the Box without crashing', () => { diff --git a/ui/components/component-library/button-base/button-base.stories.tsx b/ui/components/component-library/button-base/button-base.stories.tsx index 948ad6ea4890..871ba6290bd7 100644 --- a/ui/components/component-library/button-base/button-base.stories.tsx +++ b/ui/components/component-library/button-base/button-base.stories.tsx @@ -7,10 +7,12 @@ import { FlexDirection, TextColor, } from '../../../helpers/constants/design-system'; -import { Box, TextDirection, IconName } from '..'; import { ButtonBaseSize } from './button-base.types'; import { ButtonBase } from './button-base'; import README from './README.mdx'; +import { IconName } from '../icon'; +import { Box } from '../box'; +import { TextDirection } from '../text'; const marginSizeControlOptions = [ undefined, diff --git a/ui/components/component-library/button-base/button-base.test.tsx b/ui/components/component-library/button-base/button-base.test.tsx index 4708c0c1c5b0..d2eac4e40d5c 100644 --- a/ui/components/component-library/button-base/button-base.test.tsx +++ b/ui/components/component-library/button-base/button-base.test.tsx @@ -1,7 +1,7 @@ /* eslint-disable jest/require-top-level-describe */ import { render } from '@testing-library/react'; import React from 'react'; -import { IconName } from '..'; +import { IconName } from '../icon'; import { ButtonBaseSize } from './button-base.types'; import { ButtonBase } from './button-base'; diff --git a/ui/components/component-library/button-base/button-base.tsx b/ui/components/component-library/button-base/button-base.tsx index 2542c014e74d..7227722af9e3 100644 --- a/ui/components/component-library/button-base/button-base.tsx +++ b/ui/components/component-library/button-base/button-base.tsx @@ -1,6 +1,6 @@ import React from 'react'; import classnames from 'classnames'; -import { IconName, Icon, IconSize, Text } from '..'; +import { Text } from '../text'; import { AlignItems, Display, @@ -13,6 +13,7 @@ import { } from '../../../helpers/constants/design-system'; import type { PolymorphicRef } from '../box'; import type { TextProps } from '../text'; +import { Icon, IconName, IconSize } from '../icon'; import { ButtonBaseProps, ButtonBaseSize, diff --git a/ui/components/component-library/button-icon/button-icon.stories.tsx b/ui/components/component-library/button-icon/button-icon.stories.tsx index 271c944f4856..365861555617 100644 --- a/ui/components/component-library/button-icon/button-icon.stories.tsx +++ b/ui/components/component-library/button-icon/button-icon.stories.tsx @@ -1,10 +1,10 @@ import React from 'react'; import { StoryFn, Meta } from '@storybook/react'; import { IconColor } from '../../../helpers/constants/design-system'; -import { IconName } from '..'; import { ButtonIconSize } from './button-icon.types'; import { ButtonIcon } from './button-icon'; import README from './README.mdx'; +import { IconName } from '../icon'; export default { title: 'Components/ComponentLibrary/ButtonIcon', diff --git a/ui/components/component-library/button-icon/button-icon.test.tsx b/ui/components/component-library/button-icon/button-icon.test.tsx index bf48c0d95e69..f60b2cb8aef0 100644 --- a/ui/components/component-library/button-icon/button-icon.test.tsx +++ b/ui/components/component-library/button-icon/button-icon.test.tsx @@ -2,7 +2,7 @@ import { render } from '@testing-library/react'; import React from 'react'; import { IconColor } from '../../../helpers/constants/design-system'; -import { IconName } from '..'; +import { IconName } from '../icon'; import { ButtonIconSize } from './button-icon.types'; import { ButtonIcon } from './button-icon'; diff --git a/ui/components/component-library/button-icon/button-icon.tsx b/ui/components/component-library/button-icon/button-icon.tsx index e118b9ac3de1..46fc08c4620c 100644 --- a/ui/components/component-library/button-icon/button-icon.tsx +++ b/ui/components/component-library/button-icon/button-icon.tsx @@ -10,9 +10,8 @@ import { JustifyContent, } from '../../../helpers/constants/design-system'; -import { Box, Icon } from '..'; -import { IconSize } from '../icon'; -import { BoxProps, PolymorphicRef } from '../box'; +import { Box, BoxProps, PolymorphicRef } from '../box'; +import { Icon, IconSize } from '../icon'; import { ButtonIconSize, ButtonIconProps, diff --git a/ui/components/component-library/button-link/button-link.stories.tsx b/ui/components/component-library/button-link/button-link.stories.tsx index 087843decd74..aba1659e7d8f 100644 --- a/ui/components/component-library/button-link/button-link.stories.tsx +++ b/ui/components/component-library/button-link/button-link.stories.tsx @@ -8,9 +8,11 @@ import { TextVariant, TextColor, } from '../../../helpers/constants/design-system'; -import { Box, Text } from '..'; +import { Box } from '../box'; +import { Text } from '../text'; import README from './README.mdx'; -import { ButtonLink, ButtonLinkSize } from '.'; +import { ButtonLink } from './button-link'; +import { ButtonLinkSize } from './button-link.types'; export default { title: 'Components/ComponentLibrary/ButtonLink', diff --git a/ui/components/component-library/button-link/button-link.test.tsx b/ui/components/component-library/button-link/button-link.test.tsx index 424b2aa9973f..89a06eaa42f8 100644 --- a/ui/components/component-library/button-link/button-link.test.tsx +++ b/ui/components/component-library/button-link/button-link.test.tsx @@ -1,8 +1,9 @@ /* eslint-disable jest/require-top-level-describe */ import { render } from '@testing-library/react'; import React from 'react'; -import { IconName } from '..'; -import { ButtonLink, ButtonLinkSize } from '.'; +import { IconName } from '../icon'; +import { ButtonLink } from './button-link'; +import { ButtonLinkSize } from './button-link.types'; describe('ButtonLink', () => { it('should render button element correctly', () => { diff --git a/ui/components/component-library/button-link/button-link.tsx b/ui/components/component-library/button-link/button-link.tsx index 958c1a0ee7ac..2ce9c3776c2e 100644 --- a/ui/components/component-library/button-link/button-link.tsx +++ b/ui/components/component-library/button-link/button-link.tsx @@ -1,12 +1,12 @@ import React from 'react'; import classnames from 'classnames'; -import { ButtonBase, IconSize } from '..'; import { BackgroundColor, Color, } from '../../../helpers/constants/design-system'; import type { PolymorphicRef } from '../box'; -import type { ButtonBaseProps } from '../button-base'; +import { ButtonBase, type ButtonBaseProps } from '../button-base'; +import { IconSize } from '../icon'; import type { ButtonLinkProps } from './button-link.types'; import { ButtonLinkSize, ButtonLinkComponent } from './button-link.types'; diff --git a/ui/components/component-library/button-primary/button-primary.stories.tsx b/ui/components/component-library/button-primary/button-primary.stories.tsx index b6ecb83bebdc..74e25887ac08 100644 --- a/ui/components/component-library/button-primary/button-primary.stories.tsx +++ b/ui/components/component-library/button-primary/button-primary.stories.tsx @@ -1,9 +1,10 @@ import React from 'react'; import { StoryFn, Meta } from '@storybook/react'; import { AlignItems, Display } from '../../../helpers/constants/design-system'; -import { Box } from '..'; import README from './README.mdx'; -import { ButtonPrimary, ButtonPrimarySize } from '.'; +import { ButtonPrimary } from './button-primary'; +import { ButtonPrimarySize } from './button-primary.types'; +import { Box } from '../box'; export default { title: 'Components/ComponentLibrary/ButtonPrimary', diff --git a/ui/components/component-library/button-primary/button-primary.test.tsx b/ui/components/component-library/button-primary/button-primary.test.tsx index 95a51f79bb13..6b812807c5dc 100644 --- a/ui/components/component-library/button-primary/button-primary.test.tsx +++ b/ui/components/component-library/button-primary/button-primary.test.tsx @@ -1,8 +1,9 @@ /* eslint-disable jest/require-top-level-describe */ import { render } from '@testing-library/react'; import React from 'react'; -import { IconName } from '..'; -import { ButtonPrimary, ButtonPrimarySize } from '.'; +import { IconName } from '../icon'; +import { ButtonPrimary } from './button-primary'; +import { ButtonPrimarySize } from './button-primary.types'; describe('ButtonPrimary', () => { it('should render button element correctly', () => { diff --git a/ui/components/component-library/button-secondary/button-secondary.stories.tsx b/ui/components/component-library/button-secondary/button-secondary.stories.tsx index a7883213f999..6cb1bbbbe73a 100644 --- a/ui/components/component-library/button-secondary/button-secondary.stories.tsx +++ b/ui/components/component-library/button-secondary/button-secondary.stories.tsx @@ -1,9 +1,11 @@ import React from 'react'; import { StoryFn, Meta } from '@storybook/react'; import { AlignItems, Display } from '../../../helpers/constants/design-system'; -import { IconName, Box } from '..'; import README from './README.mdx'; -import { ButtonSecondary, ButtonSecondarySize } from '.'; +import { ButtonSecondary } from './button-secondary'; +import { IconName } from '../icon'; +import { ButtonSecondarySize } from './button-secondary.types'; +import { Box } from '../box'; const marginSizeControlOptions = [ undefined, diff --git a/ui/components/component-library/button-secondary/button-secondary.test.tsx b/ui/components/component-library/button-secondary/button-secondary.test.tsx index f8730d34af6c..c8ce5a265e40 100644 --- a/ui/components/component-library/button-secondary/button-secondary.test.tsx +++ b/ui/components/component-library/button-secondary/button-secondary.test.tsx @@ -1,8 +1,9 @@ /* eslint-disable jest/require-top-level-describe */ import { render } from '@testing-library/react'; import React from 'react'; -import { IconName } from '..'; -import { ButtonSecondary, ButtonSecondarySize } from '.'; +import { IconName } from '../icon'; +import { ButtonSecondary } from './button-secondary'; +import { ButtonSecondarySize } from './button-secondary.types'; describe('ButtonSecondary', () => { it('should render button element correctly', () => { diff --git a/ui/components/component-library/button/button.stories.tsx b/ui/components/component-library/button/button.stories.tsx index 421ee3a97dd7..0ee62b2d95f1 100644 --- a/ui/components/component-library/button/button.stories.tsx +++ b/ui/components/component-library/button/button.stories.tsx @@ -6,10 +6,12 @@ import { FlexDirection, TextVariant, } from '../../../helpers/constants/design-system'; -import { Box, IconName } from '..'; import { Text } from '../text'; import README from './README.mdx'; -import { Button, ButtonSize, ButtonVariant } from '.'; +import { Button } from './button'; +import { IconName } from '../icon'; +import { ButtonSize, ButtonVariant } from './button.types'; +import { Box } from '../box'; export default { title: 'Components/ComponentLibrary/Button', diff --git a/ui/components/component-library/button/button.test.tsx b/ui/components/component-library/button/button.test.tsx index 099158310f8f..b66511a97e60 100644 --- a/ui/components/component-library/button/button.test.tsx +++ b/ui/components/component-library/button/button.test.tsx @@ -1,9 +1,9 @@ /* eslint-disable jest/require-top-level-describe */ import { render } from '@testing-library/react'; import React from 'react'; -import { IconName } from '..'; +import { IconName } from '../icon'; import { Button } from './button'; -import { ButtonSize, ButtonVariant } from '.'; +import { ButtonSize, ButtonVariant } from './button.types'; describe('Button', () => { it('should render button element correctly', () => { diff --git a/ui/components/component-library/checkbox/checkbox.stories.tsx b/ui/components/component-library/checkbox/checkbox.stories.tsx index 6ee20f4f286c..c344d6195f28 100644 --- a/ui/components/component-library/checkbox/checkbox.stories.tsx +++ b/ui/components/component-library/checkbox/checkbox.stories.tsx @@ -2,7 +2,6 @@ import { StoryFn, Meta } from '@storybook/react'; import { useArgs } from '@storybook/client-api'; import React from 'react'; -import { Box } from '..'; import { BorderColor, Display, @@ -10,7 +9,8 @@ import { } from '../../../helpers/constants/design-system'; import README from './README.mdx'; -import { Checkbox } from '.'; +import { Checkbox } from './checkbox'; +import { Box } from '../box'; export default { title: 'Components/ComponentLibrary/Checkbox', diff --git a/ui/components/component-library/checkbox/checkbox.test.tsx b/ui/components/component-library/checkbox/checkbox.test.tsx index da9d62d756b2..a9fd1b6df888 100644 --- a/ui/components/component-library/checkbox/checkbox.test.tsx +++ b/ui/components/component-library/checkbox/checkbox.test.tsx @@ -1,8 +1,8 @@ import * as React from 'react'; import { render, fireEvent } from '@testing-library/react'; import { BorderColor } from '../../../helpers/constants/design-system'; -import { IconName } from '..'; -import { Checkbox } from '.'; +import { IconName } from '../icon'; +import { Checkbox } from './checkbox'; describe('Checkbox', () => { it('should render the Checkbox without crashing', () => { diff --git a/ui/components/component-library/checkbox/checkbox.tsx b/ui/components/component-library/checkbox/checkbox.tsx index ff6435e5d0b3..c5739d20562b 100644 --- a/ui/components/component-library/checkbox/checkbox.tsx +++ b/ui/components/component-library/checkbox/checkbox.tsx @@ -10,10 +10,10 @@ import { AlignItems, } from '../../../helpers/constants/design-system'; -import type { PolymorphicRef, TextProps } from '..'; -import { Box, Icon, IconName, Text } from '..'; - -import { CheckboxProps, CheckboxComponent } from './checkbox.types'; +import { type PolymorphicRef, Box } from '../box'; +import { Text, type TextProps } from '../text'; +import { Icon, IconName } from '../icon'; +import type { CheckboxProps, CheckboxComponent } from './checkbox.types'; export const Checkbox: CheckboxComponent = React.forwardRef( ( diff --git a/ui/components/component-library/container/container.stories.tsx b/ui/components/component-library/container/container.stories.tsx index d6dc61512a14..75ac73409e62 100644 --- a/ui/components/component-library/container/container.stories.tsx +++ b/ui/components/component-library/container/container.stories.tsx @@ -9,7 +9,7 @@ import { import README from './README.mdx'; import { ContainerMaxWidth } from './container.types'; -import { Container } from '.'; +import { Container } from './container'; export default { title: 'Components/ComponentLibrary/Container', diff --git a/ui/components/component-library/container/container.test.tsx b/ui/components/component-library/container/container.test.tsx index 8cac49dec5c2..96ad42379bd7 100644 --- a/ui/components/component-library/container/container.test.tsx +++ b/ui/components/component-library/container/container.test.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { render } from '@testing-library/react'; import { ContainerMaxWidth } from './container.types'; -import { Container } from '.'; +import { Container } from './container'; describe('Container', () => { it('should render the Container without crashing', () => { diff --git a/ui/components/component-library/container/container.tsx b/ui/components/component-library/container/container.tsx index 17ea5eef23c9..40d131020327 100644 --- a/ui/components/component-library/container/container.tsx +++ b/ui/components/component-library/container/container.tsx @@ -1,7 +1,7 @@ import React from 'react'; import classnames from 'classnames'; import type { PolymorphicRef, BoxProps } from '../box'; -import { Box } from '..'; +import { Box } from '../box'; import { ContainerProps, ContainerComponent } from './container.types'; diff --git a/ui/components/component-library/form-text-field/form-text-field.stories.tsx b/ui/components/component-library/form-text-field/form-text-field.stories.tsx index 746d8acc5b01..a423f9c3e688 100644 --- a/ui/components/component-library/form-text-field/form-text-field.stories.tsx +++ b/ui/components/component-library/form-text-field/form-text-field.stories.tsx @@ -11,23 +11,18 @@ import { IconColor, } from '../../../helpers/constants/design-system'; -import { - Box, - ButtonLink, - ButtonPrimary, - ButtonSecondary, - HelpText, - Label, - Text, - TextFieldType, - Icon, - IconName, - IconSize, -} from '..'; - import { FormTextField } from './form-text-field'; import README from './README.mdx'; +import { Text } from '../text'; +import { Box } from '../box'; +import { ButtonSecondary } from '../button-secondary'; +import { ButtonPrimary } from '../button-primary'; +import { Icon, IconName, IconSize } from '../icon'; +import { Label } from '../label'; +import { ButtonLink } from '../button-link'; +import { HelpText } from '../help-text'; +import { TextFieldType } from '../text-field'; export default { title: 'Components/ComponentLibrary/FormTextField', diff --git a/ui/components/component-library/form-text-field/form-text-field.test.tsx b/ui/components/component-library/form-text-field/form-text-field.test.tsx index 63b0e1c06f2e..30caab71567d 100644 --- a/ui/components/component-library/form-text-field/form-text-field.test.tsx +++ b/ui/components/component-library/form-text-field/form-text-field.test.tsx @@ -5,7 +5,8 @@ import React from 'react'; import { fireEvent, render } from '@testing-library/react'; import { renderWithUserEvent } from '../../../../test/lib/render-helpers'; -import { FormTextField, FormTextFieldSize } from '.'; +import { FormTextField } from './form-text-field'; +import { FormTextFieldSize } from './form-text-field.types'; describe('FormTextField', () => { it('should render correctly', () => { diff --git a/ui/components/component-library/form-text-field/form-text-field.tsx b/ui/components/component-library/form-text-field/form-text-field.tsx index 9ee7b534a179..829505e27f7e 100644 --- a/ui/components/component-library/form-text-field/form-text-field.tsx +++ b/ui/components/component-library/form-text-field/form-text-field.tsx @@ -4,17 +4,12 @@ import { Display, FlexDirection, } from '../../../helpers/constants/design-system'; -import { - Box, - TextField, - HelpText, - HelpTextSeverity, - Label, - TextFieldSize, -} from '..'; -import { PolymorphicRef } from '../box'; +import { Box, PolymorphicRef } from '../box'; import type { BoxProps } from '../box'; -import { TextFieldProps } from '../text-field/text-field.types'; +import { TextFieldProps, TextFieldSize } from '../text-field/text-field.types'; +import { Label } from '../label'; +import { TextField } from '../text-field'; +import { HelpText, HelpTextSeverity } from '../help-text'; import { FormTextFieldSize, FormTextFieldProps, diff --git a/ui/components/component-library/header-base/header-base.stories.tsx b/ui/components/component-library/header-base/header-base.stories.tsx index 409a576f2df5..2edcd96d4c78 100644 --- a/ui/components/component-library/header-base/header-base.stories.tsx +++ b/ui/components/component-library/header-base/header-base.stories.tsx @@ -1,14 +1,6 @@ import React from 'react'; import { StoryFn, Meta } from '@storybook/react'; -import { - IconName, - Button, - ButtonSize, - ButtonIcon, - ButtonIconSize, - Text, - Box, -} from '..'; +import { Text } from '../text'; import { AlignItems, @@ -18,6 +10,10 @@ import { } from '../../../helpers/constants/design-system'; import { HeaderBase } from './header-base'; import README from './README.mdx'; +import { ButtonIcon, ButtonIconSize } from '../button-icon'; +import { IconName } from '../icon'; +import { Box } from '../box'; +import { Button, ButtonSize } from '../button'; export default { title: 'Components/ComponentLibrary/HeaderBase', diff --git a/ui/components/component-library/header-base/header-base.test.tsx b/ui/components/component-library/header-base/header-base.test.tsx index 00171ab95c11..61b6483bdbd5 100644 --- a/ui/components/component-library/header-base/header-base.test.tsx +++ b/ui/components/component-library/header-base/header-base.test.tsx @@ -1,7 +1,7 @@ /* eslint-disable jest/require-top-level-describe */ import { render } from '@testing-library/react'; import React from 'react'; -import { Icon, IconName } from '..'; +import { Icon, IconName } from '../icon'; import { HeaderBase } from './header-base'; describe('HeaderBase', () => { diff --git a/ui/components/component-library/header-base/header-base.tsx b/ui/components/component-library/header-base/header-base.tsx index d5b00ab362aa..669c21410971 100644 --- a/ui/components/component-library/header-base/header-base.tsx +++ b/ui/components/component-library/header-base/header-base.tsx @@ -4,7 +4,7 @@ import { Display, JustifyContent, } from '../../../helpers/constants/design-system'; -import { Box } from '..'; +import { Box } from '../box'; import type { PolymorphicRef, BoxProps } from '../box'; diff --git a/ui/components/component-library/help-text/README.mdx b/ui/components/component-library/help-text/README.mdx index 1e8c4e2d6a2a..3e6f0cb86bee 100644 --- a/ui/components/component-library/help-text/README.mdx +++ b/ui/components/component-library/help-text/README.mdx @@ -1,6 +1,6 @@ import { Story, Canvas, ArgsTable } from '@storybook/addon-docs'; -import { Text } from '..'; +import { Text } from '../text'; import { HelpText } from './help-text'; diff --git a/ui/components/component-library/help-text/help-text.stories.tsx b/ui/components/component-library/help-text/help-text.stories.tsx index da14d225a4d1..df49051b7de9 100644 --- a/ui/components/component-library/help-text/help-text.stories.tsx +++ b/ui/components/component-library/help-text/help-text.stories.tsx @@ -7,12 +7,12 @@ import { TextColor, } from '../../../helpers/constants/design-system'; -import { Box, Icon, IconName, IconSize } from '..'; - import { HelpText } from './help-text'; import { HelpTextSeverity } from './help-text.types'; import README from './README.mdx'; +import { Box } from '../box'; +import { Icon, IconName, IconSize } from '../icon'; export default { title: 'Components/ComponentLibrary/HelpText', diff --git a/ui/components/component-library/help-text/help-text.test.tsx b/ui/components/component-library/help-text/help-text.test.tsx index 29cd2e46a463..39a6084b2032 100644 --- a/ui/components/component-library/help-text/help-text.test.tsx +++ b/ui/components/component-library/help-text/help-text.test.tsx @@ -2,8 +2,9 @@ import { render } from '@testing-library/react'; import React from 'react'; import { TextColor } from '../../../helpers/constants/design-system'; -import { Icon, IconName } from '..'; -import { HelpText, HelpTextSeverity } from '.'; +import { Icon, IconName } from '../icon'; +import { HelpText } from './help-text'; +import { HelpTextSeverity } from './help-text.types'; describe('HelpText', () => { it('should render with text inside the HelpText', () => { diff --git a/ui/components/component-library/help-text/help-text.tsx b/ui/components/component-library/help-text/help-text.tsx index 4be242562b26..c181680e7acd 100644 --- a/ui/components/component-library/help-text/help-text.tsx +++ b/ui/components/component-library/help-text/help-text.tsx @@ -7,8 +7,11 @@ import { import { Text } from '../text'; import type { PolymorphicRef } from '../box'; import type { TextProps } from '../text'; -import type { HelpTextProps, HelpTextComponent } from './help-text.types'; -import { HelpTextSeverity } from '.'; +import { + type HelpTextProps, + type HelpTextComponent, + HelpTextSeverity, +} from './help-text.types'; export const HelpText: HelpTextComponent = forwardRef( ( diff --git a/ui/components/component-library/icon/icon.stories.tsx b/ui/components/component-library/icon/icon.stories.tsx index 023b8a1dbf96..48fe9c66bd9e 100644 --- a/ui/components/component-library/icon/icon.stories.tsx +++ b/ui/components/component-library/icon/icon.stories.tsx @@ -17,22 +17,17 @@ import { BorderRadius, } from '../../../helpers/constants/design-system'; -import { - ButtonIcon, - ButtonLink, - ButtonLinkSize, - Label, - Text, - TextField, - TextFieldSize, - TextFieldSearch, - ButtonIconSize, - Box, -} from '..'; +import { Text } from '../text'; import { Icon } from './icon'; import { IconName, IconSize } from './icon.types'; import README from './README.mdx'; +import { Box } from '../box'; +import { Label } from '../label'; +import { TextFieldSearch } from '../text-field-search'; +import { TextField, TextFieldSize } from '../text-field'; +import { ButtonIcon, ButtonIconSize } from '../button-icon'; +import { ButtonLink, ButtonLinkSize } from '../button-link'; export default { title: 'Components/ComponentLibrary/Icon', diff --git a/ui/components/component-library/input/input.stories.tsx b/ui/components/component-library/input/input.stories.tsx index ab4476f3aec0..370a140a96f7 100644 --- a/ui/components/component-library/input/input.stories.tsx +++ b/ui/components/component-library/input/input.stories.tsx @@ -8,12 +8,12 @@ import { TextVariant, } from '../../../helpers/constants/design-system'; -import { Button, Box, ButtonVariant } from '..'; - import { InputType } from './input.types'; import { Input } from './input'; import README from './README.mdx'; +import { Box } from '../box'; +import { Button, ButtonVariant } from '../button'; const marginSizeControlOptions = [ undefined, diff --git a/ui/components/component-library/label/README.mdx b/ui/components/component-library/label/README.mdx index ef32640eed48..6962ef2c5dfe 100644 --- a/ui/components/component-library/label/README.mdx +++ b/ui/components/component-library/label/README.mdx @@ -1,6 +1,6 @@ import { Story, Canvas, ArgsTable } from '@storybook/addon-docs'; -import { Text } from '..'; +import { Text } from '../text'; import { Label } from './label'; diff --git a/ui/components/component-library/label/label.stories.tsx b/ui/components/component-library/label/label.stories.tsx index 2a5b157b7197..e1408ba8e4ef 100644 --- a/ui/components/component-library/label/label.stories.tsx +++ b/ui/components/component-library/label/label.stories.tsx @@ -7,10 +7,12 @@ import { IconColor, } from '../../../helpers/constants/design-system'; -import { Box, Icon, IconName, IconSize, TextField } from '..'; import { Label } from './label'; import README from './README.mdx'; +import { Icon, IconName, IconSize } from '../icon'; +import { Box } from '../box'; +import { TextField } from '../text-field'; export default { title: 'Components/ComponentLibrary/Label', diff --git a/ui/components/component-library/label/label.test.tsx b/ui/components/component-library/label/label.test.tsx index b2f3a4e222bd..fc5e7db52a0b 100644 --- a/ui/components/component-library/label/label.test.tsx +++ b/ui/components/component-library/label/label.test.tsx @@ -1,8 +1,9 @@ /* eslint-disable jest/require-top-level-describe */ import { fireEvent, render } from '@testing-library/react'; import React from 'react'; -import { Icon, IconName, TextField } from '..'; +import { Icon, IconName } from '../icon'; +import { TextField } from '../text-field'; import { Label } from './label'; describe('label', () => { diff --git a/ui/components/component-library/modal-body/modal-body.stories.tsx b/ui/components/component-library/modal-body/modal-body.stories.tsx index c958d0860fd4..4bf80240edb1 100644 --- a/ui/components/component-library/modal-body/modal-body.stories.tsx +++ b/ui/components/component-library/modal-body/modal-body.stories.tsx @@ -5,7 +5,7 @@ import { Display, FlexDirection, } from '../../../helpers/constants/design-system'; -import { Text } from '..'; +import { Text } from '../text'; import README from './README.mdx'; import { ModalBody } from './modal-body'; diff --git a/ui/components/component-library/modal-body/modal-body.tsx b/ui/components/component-library/modal-body/modal-body.tsx index c658b6cb7d6a..e45832adb74e 100644 --- a/ui/components/component-library/modal-body/modal-body.tsx +++ b/ui/components/component-library/modal-body/modal-body.tsx @@ -1,7 +1,7 @@ import React from 'react'; import classnames from 'classnames'; -import { Box } from '..'; +import { Box } from '../box'; import type { PolymorphicRef, BoxProps } from '../box'; import { ModalBodyProps, ModalBodyComponent } from './modal-body.types'; diff --git a/ui/components/component-library/modal-content/deprecated/modal-content.tsx b/ui/components/component-library/modal-content/deprecated/modal-content.tsx index dda7dc7d681e..a3e39128011e 100644 --- a/ui/components/component-library/modal-content/deprecated/modal-content.tsx +++ b/ui/components/component-library/modal-content/deprecated/modal-content.tsx @@ -10,15 +10,15 @@ import { AlignItems, } from '../../../../helpers/constants/design-system'; -import { Box, ModalFocus, useModalContext } from '../..'; - -import { BoxProps } from '../../box'; +import { Box, BoxProps } from '../../box'; import type { PolymorphicRef } from '../../box'; import { ModalContentProps, ModalContentSize, ModalContentComponent, } from '../modal-content.types'; +import { useModalContext } from '../../modal/modal.context'; +import { ModalFocus } from '../../modal-focus'; /** * @deprecated This version of `ModalContent` is deprecated. Please use the version from the component-library in ui/components/component-library/modal-content/modal-content.tsx diff --git a/ui/components/component-library/modal-content/modal-content.stories.tsx b/ui/components/component-library/modal-content/modal-content.stories.tsx index 90eab15c3aae..4dfb10455e86 100644 --- a/ui/components/component-library/modal-content/modal-content.stories.tsx +++ b/ui/components/component-library/modal-content/modal-content.stories.tsx @@ -3,21 +3,18 @@ import { StoryFn, Meta } from '@storybook/react'; import { Display, FlexWrap } from '../../../helpers/constants/design-system'; -import { - Box, - ButtonVariant, - Button, - Text, - Modal, - ModalHeader, - ModalBody, - ModalFooter, -} from '..'; +import { Text } from '../text'; import { ModalContent } from './modal-content'; import { ModalContentSize } from './modal-content.types'; import README from './README.mdx'; +import { Button, ButtonVariant } from '../button'; +import { Modal } from '../modal'; +import { ModalHeader } from '../modal-header'; +import { ModalBody } from '../modal-body'; +import { ModalFooter } from '../modal-footer'; +import { Box } from '../box'; export default { title: 'Components/ComponentLibrary/ModalContent', diff --git a/ui/components/component-library/modal-content/modal-content.test.tsx b/ui/components/component-library/modal-content/modal-content.test.tsx index 99cadb63a81f..7197d7ae7cac 100644 --- a/ui/components/component-library/modal-content/modal-content.test.tsx +++ b/ui/components/component-library/modal-content/modal-content.test.tsx @@ -1,7 +1,7 @@ /* eslint-disable jest/require-top-level-describe */ import { render, fireEvent } from '@testing-library/react'; import React from 'react'; -import { Modal } from '..'; +import { Modal } from '../modal'; import { ModalContent } from './modal-content'; import { ModalContentSize } from './modal-content.types'; diff --git a/ui/components/component-library/modal-content/modal-content.tsx b/ui/components/component-library/modal-content/modal-content.tsx index 39f25b084cf8..dc59ea7aa2f9 100644 --- a/ui/components/component-library/modal-content/modal-content.tsx +++ b/ui/components/component-library/modal-content/modal-content.tsx @@ -11,10 +11,10 @@ import { FlexDirection, } from '../../../helpers/constants/design-system'; -import { Box, ModalFocus, useModalContext } from '..'; - -import { BoxProps } from '../box'; +import { Box, BoxProps } from '../box'; import type { PolymorphicRef } from '../box'; +import { useModalContext } from '../modal/modal.context'; +import { ModalFocus } from '../modal-focus'; import { ModalContentProps, ModalContentSize, diff --git a/ui/components/component-library/modal-footer/modal-footer.stories.tsx b/ui/components/component-library/modal-footer/modal-footer.stories.tsx index 4b7f43189658..b2aefc730b6f 100644 --- a/ui/components/component-library/modal-footer/modal-footer.stories.tsx +++ b/ui/components/component-library/modal-footer/modal-footer.stories.tsx @@ -1,7 +1,6 @@ import React from 'react'; import type { Meta, StoryObj } from '@storybook/react'; -import { Box, Container, Checkbox, ContainerMaxWidth } from '..'; import { BackgroundColor, Display, @@ -10,6 +9,9 @@ import { import { ModalFooter } from './modal-footer'; import README from './README.mdx'; +import { Box } from '../box'; +import { Container, ContainerMaxWidth } from '../container'; +import { Checkbox } from '../checkbox'; const meta: Meta = { title: 'Components/ComponentLibrary/ModalFooter', diff --git a/ui/components/component-library/modal-footer/modal-footer.tsx b/ui/components/component-library/modal-footer/modal-footer.tsx index 053d69878f72..64e830e5e2c4 100644 --- a/ui/components/component-library/modal-footer/modal-footer.tsx +++ b/ui/components/component-library/modal-footer/modal-footer.tsx @@ -6,16 +6,9 @@ import { Display, FlexWrap, } from '../../../helpers/constants/design-system'; -import type { PolymorphicRef, BoxProps } from '../box'; -import type { ButtonProps } from '../button'; -import { - Box, - Button, - ButtonSize, - ButtonVariant, - Container, - ContainerMaxWidth, -} from '..'; +import { type PolymorphicRef, type BoxProps, Box } from '../box'; +import { Button, ButtonSize, ButtonVariant, type ButtonProps } from '../button'; +import { Container, ContainerMaxWidth } from '../container'; import { ModalFooterProps, ModalFooterComponent } from './modal-footer.types'; export const ModalFooter: ModalFooterComponent = React.forwardRef( diff --git a/ui/components/component-library/modal-header/deprecated/modal-header.tsx b/ui/components/component-library/modal-header/deprecated/modal-header.tsx index 612cac792c43..c91c498c45e4 100644 --- a/ui/components/component-library/modal-header/deprecated/modal-header.tsx +++ b/ui/components/component-library/modal-header/deprecated/modal-header.tsx @@ -1,12 +1,15 @@ import React from 'react'; import classnames from 'classnames'; -import { HeaderBase, Text, ButtonIcon, ButtonIconSize, IconName } from '../..'; +import { Text } from '../../text'; import { TextVariant, TextAlign, } from '../../../../helpers/constants/design-system'; import { useI18nContext } from '../../../../hooks/useI18nContext'; -import { ModalHeaderProps } from '.'; +import { ModalHeaderProps } from '../modal-header.types'; +import { HeaderBase } from '../../header-base'; +import { ButtonIcon, ButtonIconSize } from '../../button-icon'; +import { IconName } from '../../icon'; /** * @deprecated This version of `ModalHeader` is deprecated. Please use the version from the component-library in ui/components/component-library/modal-header/modal-header.tsx diff --git a/ui/components/component-library/modal-header/modal-header.stories.tsx b/ui/components/component-library/modal-header/modal-header.stories.tsx index 676cf7d09172..b8b165947b8e 100644 --- a/ui/components/component-library/modal-header/modal-header.stories.tsx +++ b/ui/components/component-library/modal-header/modal-header.stories.tsx @@ -10,10 +10,11 @@ import { JustifyContent, } from '../../../helpers/constants/design-system'; -import { AvatarAccount, ButtonSize, Button, Text } from '..'; - import { ModalHeader } from './modal-header'; +import { Text } from '../text'; import README from './README.mdx'; +import { AvatarAccount } from '../avatar-account'; +import { Button, ButtonSize } from '../button'; export default { title: 'Components/ComponentLibrary/ModalHeader', diff --git a/ui/components/component-library/modal-header/modal-header.test.tsx b/ui/components/component-library/modal-header/modal-header.test.tsx index a6fb8bfd08a2..c2e276cecb2d 100644 --- a/ui/components/component-library/modal-header/modal-header.test.tsx +++ b/ui/components/component-library/modal-header/modal-header.test.tsx @@ -1,7 +1,7 @@ /* eslint-disable jest/require-top-level-describe */ import { render, fireEvent } from '@testing-library/react'; import React from 'react'; -import { IconName } from '..'; +import { IconName } from '../icon'; import { ModalHeader } from './modal-header'; describe('ModalHeader', () => { diff --git a/ui/components/component-library/modal-header/modal-header.tsx b/ui/components/component-library/modal-header/modal-header.tsx index 0e3bbbdefcdc..506969c739cc 100644 --- a/ui/components/component-library/modal-header/modal-header.tsx +++ b/ui/components/component-library/modal-header/modal-header.tsx @@ -1,13 +1,16 @@ import React from 'react'; import classnames from 'classnames'; -import { HeaderBase, Text, ButtonIcon, ButtonIconSize, IconName } from '..'; +import { Text } from '../text'; import { TextVariant, TextAlign, BlockSize, } from '../../../helpers/constants/design-system'; import { useI18nContext } from '../../../hooks/useI18nContext'; -import { ModalHeaderProps } from '.'; +import { ButtonIcon, ButtonIconSize } from '../button-icon'; +import { IconName } from '../icon'; +import { HeaderBase } from '../header-base'; +import { ModalHeaderProps } from './modal-header.types'; export const ModalHeader: React.FC = ({ children, diff --git a/ui/components/component-library/modal/modal.stories.tsx b/ui/components/component-library/modal/modal.stories.tsx index 5e33799393c5..a7592e08d3ae 100644 --- a/ui/components/component-library/modal/modal.stories.tsx +++ b/ui/components/component-library/modal/modal.stories.tsx @@ -4,23 +4,20 @@ import { StoryFn, Meta } from '@storybook/react'; import { BlockSize, Display } from '../../../helpers/constants/design-system'; -import { - ModalOverlay, - ModalContent, - ModalHeader, - ModalBody, - ModalFooter, - Text, - Button, - ButtonLink, - ButtonLinkSize, - TextFieldSearch, - IconName, - Box, -} from '..'; +import { Text } from '../text'; import { Modal } from './modal'; import README from './README.mdx'; +import { ButtonLink, ButtonLinkSize } from '../button-link'; +import { Box } from '../box'; +import { Button } from '../button'; +import { IconName } from '../icon'; +import { ModalOverlay } from '../modal-overlay'; +import { ModalContent } from '../modal-content'; +import { ModalHeader } from '../modal-header'; +import { ModalBody } from '../modal-body'; +import { ModalFooter } from '../modal-footer'; +import { TextFieldSearch } from '../text-field-search'; export default { title: 'Components/ComponentLibrary/Modal', diff --git a/ui/components/component-library/picker-network/picker-network.stories.tsx b/ui/components/component-library/picker-network/picker-network.stories.tsx index ea35b98f397c..5809f26946ec 100644 --- a/ui/components/component-library/picker-network/picker-network.stories.tsx +++ b/ui/components/component-library/picker-network/picker-network.stories.tsx @@ -6,7 +6,7 @@ import { BlockSize, } from '../../../helpers/constants/design-system'; -import { Box } from '..'; +import { Box } from '../box'; import README from './README.mdx'; import { PickerNetwork } from './picker-network'; import { diff --git a/ui/components/component-library/picker-network/picker-network.test.tsx b/ui/components/component-library/picker-network/picker-network.test.tsx index d05e4a52caf9..f96fd1708cde 100644 --- a/ui/components/component-library/picker-network/picker-network.test.tsx +++ b/ui/components/component-library/picker-network/picker-network.test.tsx @@ -1,7 +1,7 @@ import { render, screen } from '@testing-library/react'; import React from 'react'; -import { IconName } from '..'; +import { IconName } from '../icon'; import { renderWithProvider } from '../../../../test/lib/render-helpers'; import configureStore from '../../../store/store'; import { AvatarType } from '../../multichain/avatar-group/avatar-group.types'; diff --git a/ui/components/component-library/picker-network/picker-network.tsx b/ui/components/component-library/picker-network/picker-network.tsx index f92ad174beed..29f6a1c8c57c 100644 --- a/ui/components/component-library/picker-network/picker-network.tsx +++ b/ui/components/component-library/picker-network/picker-network.tsx @@ -8,17 +8,11 @@ import { BackgroundColor, Display, } from '../../../helpers/constants/design-system'; -import { - AvatarNetwork, - AvatarNetworkSize, - Box, - IconName, - Icon, - IconSize, - Text, -} from '..'; -import { BoxProps, PolymorphicRef } from '../box'; +import { Text } from '../text'; +import { Box, BoxProps, PolymorphicRef } from '../box'; import { AvatarGroup } from '../../multichain/avatar-group'; +import { AvatarNetwork, AvatarNetworkSize } from '../avatar-network'; +import { Icon, IconName, IconSize } from '../icon'; import { PickerNetworkComponent, PickerNetworkProps, diff --git a/ui/components/component-library/popover-header/popover-header.stories.tsx b/ui/components/component-library/popover-header/popover-header.stories.tsx index 9cdeaf10a1bf..eefb79be09bf 100644 --- a/ui/components/component-library/popover-header/popover-header.stories.tsx +++ b/ui/components/component-library/popover-header/popover-header.stories.tsx @@ -10,10 +10,12 @@ import { JustifyContent, } from '../../../helpers/constants/design-system'; -import { AvatarAccount, ButtonSize, Button, Text } from '..'; +import { Text } from '../text'; import { PopoverHeader } from './popover-header'; import README from './README.mdx'; +import { AvatarAccount } from '../avatar-account'; +import { Button, ButtonSize } from '../button'; export default { title: 'Components/ComponentLibrary/PopoverHeader', diff --git a/ui/components/component-library/popover-header/popover-header.test.tsx b/ui/components/component-library/popover-header/popover-header.test.tsx index 6b027543fd8e..7572efa27449 100644 --- a/ui/components/component-library/popover-header/popover-header.test.tsx +++ b/ui/components/component-library/popover-header/popover-header.test.tsx @@ -1,7 +1,7 @@ /* eslint-disable jest/require-top-level-describe */ import { render, fireEvent } from '@testing-library/react'; import React from 'react'; -import { IconName } from '..'; +import { IconName } from '../icon'; import { PopoverHeader } from './popover-header'; describe('PopoverHeader', () => { diff --git a/ui/components/component-library/popover-header/popover-header.tsx b/ui/components/component-library/popover-header/popover-header.tsx index 1bd004bef583..89ed53a60040 100644 --- a/ui/components/component-library/popover-header/popover-header.tsx +++ b/ui/components/component-library/popover-header/popover-header.tsx @@ -1,6 +1,6 @@ import React from 'react'; import classnames from 'classnames'; -import { HeaderBase, ButtonIcon, ButtonIconSize, IconName, Text } from '..'; +import { Text } from '../text'; import { IconColor, TextVariant, @@ -8,7 +8,10 @@ import { TextColor, } from '../../../helpers/constants/design-system'; import { useI18nContext } from '../../../hooks/useI18nContext'; -import { PopoverHeaderProps } from '.'; +import { HeaderBase } from '../header-base'; +import { ButtonIcon, ButtonIconSize } from '../button-icon'; +import { IconName } from '../icon'; +import type { PopoverHeaderProps } from './popover-header.types'; export const PopoverHeader: React.FC = ({ children, diff --git a/ui/components/component-library/popover/popover.stories.tsx b/ui/components/component-library/popover/popover.stories.tsx index caaf343ecf8e..58a35e9afc6c 100644 --- a/ui/components/component-library/popover/popover.stories.tsx +++ b/ui/components/component-library/popover/popover.stories.tsx @@ -1,6 +1,6 @@ import React, { useState, useEffect } from 'react'; import { StoryFn, Meta } from '@storybook/react'; -import { Box, Icon, IconName, IconSize, PopoverHeader, Text } from '..'; +import { Text } from '../text'; import { AlignItems, BackgroundColor, @@ -13,7 +13,11 @@ import { } from '../../../helpers/constants/design-system'; import README from './README.mdx'; -import { Popover, PopoverPosition, PopoverRole } from '.'; +import { Popover } from './popover'; +import { PopoverPosition, PopoverRole } from './popover.types'; +import { Box } from '../box'; +import { PopoverHeader } from '../popover-header'; +import { Icon, IconName, IconSize } from '../icon'; export default { title: 'Components/ComponentLibrary/Popover', diff --git a/ui/components/component-library/popover/popover.tsx b/ui/components/component-library/popover/popover.tsx index 253bacef4855..eeee65274fe7 100644 --- a/ui/components/component-library/popover/popover.tsx +++ b/ui/components/component-library/popover/popover.tsx @@ -11,7 +11,7 @@ import { JustifyContent, } from '../../../helpers/constants/design-system'; -import { Box } from '..'; +import { Box } from '../box'; import type { BoxProps, PolymorphicRef } from '../box'; import { diff --git a/ui/components/component-library/select-button/select-button.stories.tsx b/ui/components/component-library/select-button/select-button.stories.tsx index 5cb74487c90a..b434a8686a82 100644 --- a/ui/components/component-library/select-button/select-button.stories.tsx +++ b/ui/components/component-library/select-button/select-button.stories.tsx @@ -1,15 +1,6 @@ import { StoryFn, Meta } from '@storybook/react'; import React from 'react'; -import { - AvatarBase, - AvatarBaseSize, - AvatarAccount, - AvatarAccountSize, - Box, - SelectWrapper, - SelectOption, - Text, -} from '..'; +import { Text } from '../text'; import { Display, TextColor, @@ -18,7 +9,12 @@ import { import README from './README.mdx'; import { SelectButtonSize } from './select-button.types'; -import { SelectButton } from '.'; +import { SelectButton } from './select-button'; +import { AvatarBase, AvatarBaseSize } from '../avatar-base'; +import { SelectWrapper } from '../select-wrapper'; +import { Box } from '../box'; +import { AvatarAccount, AvatarAccountSize } from '../avatar-account'; +import { SelectOption } from '../select-option'; export default { title: 'Components/ComponentLibrary/SelectButton', diff --git a/ui/components/component-library/select-button/select-button.test.tsx b/ui/components/component-library/select-button/select-button.test.tsx index 599a7e9390e7..28c14ffbdb60 100644 --- a/ui/components/component-library/select-button/select-button.test.tsx +++ b/ui/components/component-library/select-button/select-button.test.tsx @@ -1,7 +1,9 @@ import React from 'react'; import { render, fireEvent } from '@testing-library/react'; -import { AvatarAccount, AvatarAccountSize, SelectWrapper } from '..'; -import { SelectButton, SelectButtonSize } from '.'; +import { AvatarAccount, AvatarAccountSize } from '../avatar-account'; +import { SelectWrapper } from '../select-wrapper'; +import { SelectButton } from './select-button'; +import { SelectButtonSize } from './select-button.types'; describe('SelectButton', () => { it('renders without crashing', () => { diff --git a/ui/components/component-library/select-button/select-button.tsx b/ui/components/component-library/select-button/select-button.tsx index a4c6dac5a568..5546694f87f2 100644 --- a/ui/components/component-library/select-button/select-button.tsx +++ b/ui/components/component-library/select-button/select-button.tsx @@ -1,8 +1,8 @@ import React, { useContext } from 'react'; import classnames from 'classnames'; import { SelectContext } from '../select-wrapper'; -import type { PolymorphicRef } from '../box'; -import { Box, Icon, IconName, IconSize, Label, Text } from '..'; +import { Box, type PolymorphicRef } from '../box'; +import { Text } from '../text'; import type { TextProps } from '../text'; import { AlignItems, @@ -16,6 +16,8 @@ import { TextColor, TextVariant, } from '../../../helpers/constants/design-system'; +import { Label } from '../label'; +import { Icon, IconName, IconSize } from '../icon'; import { SelectButtonProps, SelectButtonComponent, diff --git a/ui/components/component-library/select-option/select-option.tsx b/ui/components/component-library/select-option/select-option.tsx index 3df4e741f996..a1ebeba44b5f 100644 --- a/ui/components/component-library/select-option/select-option.tsx +++ b/ui/components/component-library/select-option/select-option.tsx @@ -1,7 +1,7 @@ import React, { useContext } from 'react'; import classnames from 'classnames'; import type { PolymorphicRef, BoxProps } from '../box'; -import { Box } from '..'; +import { Box } from '../box'; import { SelectContext } from '../select-wrapper'; import { Display } from '../../../helpers/constants/design-system'; import { diff --git a/ui/components/component-library/select-wrapper/select-wrapper.stories.tsx b/ui/components/component-library/select-wrapper/select-wrapper.stories.tsx index af07e7f1249a..6e836d00a7f1 100644 --- a/ui/components/component-library/select-wrapper/select-wrapper.stories.tsx +++ b/ui/components/component-library/select-wrapper/select-wrapper.stories.tsx @@ -7,8 +7,8 @@ import { Button } from '../button'; import { Text } from '../text'; import { BackgroundColor } from '../../../helpers/constants/design-system'; import README from './README.mdx'; - -import { SelectWrapper, useSelectContext } from '.'; +import { SelectWrapper } from './select-wrapper'; +import { useSelectContext } from './select-wrapper.context'; export default { title: 'Components/ComponentLibrary/SelectWrapper', diff --git a/ui/components/component-library/select-wrapper/select-wrapper.test.tsx b/ui/components/component-library/select-wrapper/select-wrapper.test.tsx index a90566206e6f..f97f0fb8cf13 100644 --- a/ui/components/component-library/select-wrapper/select-wrapper.test.tsx +++ b/ui/components/component-library/select-wrapper/select-wrapper.test.tsx @@ -1,9 +1,10 @@ import * as React from 'react'; import { render, fireEvent, act } from '@testing-library/react'; -import { Button, type ButtonProps } from '..'; +import { Button, type ButtonProps } from '../button'; import { SelectButton } from '../select-button'; import { SelectOption } from '../select-option'; -import { SelectWrapper, useSelectContext } from '.'; +import { SelectWrapper } from './select-wrapper'; +import { useSelectContext } from './select-wrapper.context'; describe('SelectWrapper', () => { it('should render the SelectWrapper without crashing', () => { diff --git a/ui/components/component-library/select-wrapper/select-wrapper.tsx b/ui/components/component-library/select-wrapper/select-wrapper.tsx index 054cdd032c69..43211c438866 100644 --- a/ui/components/component-library/select-wrapper/select-wrapper.tsx +++ b/ui/components/component-library/select-wrapper/select-wrapper.tsx @@ -1,7 +1,7 @@ import React, { useState, useRef } from 'react'; import classnames from 'classnames'; -import type { PolymorphicRef, BoxProps } from '../box'; -import { Box, Popover, PopoverPosition } from '..'; +import { Box, type PolymorphicRef, BoxProps } from '../box'; +import { Popover, PopoverPosition } from '../popover'; import { SelectWrapperComponent, SelectWrapperProps, diff --git a/ui/components/component-library/sensitive-text/sensitive-text.stories.tsx b/ui/components/component-library/sensitive-text/sensitive-text.stories.tsx index 142def9118b5..4f1e1a2936c3 100644 --- a/ui/components/component-library/sensitive-text/sensitive-text.stories.tsx +++ b/ui/components/component-library/sensitive-text/sensitive-text.stories.tsx @@ -1,6 +1,6 @@ import type { Meta, StoryObj } from '@storybook/react'; import React from 'react'; -import { SensitiveText } from '.'; +import { SensitiveText } from './sensitive-text'; import { SensitiveTextLength } from './sensitive-text.types'; import README from './README.mdx'; import { Box } from '../box'; @@ -34,18 +34,14 @@ export const Children: Story = { args: { children: 'Sensitive information', }, - render: (args) => ( - - ), + render: (args) => , }; export const IsHidden: Story = { args: { isHidden: true, }, - render: (args) => ( - - ), + render: (args) => , }; export const Length: Story = { diff --git a/ui/components/component-library/skeleton/skeleton.stories.tsx b/ui/components/component-library/skeleton/skeleton.stories.tsx index 874c675e725b..2f7e0a38cda9 100644 --- a/ui/components/component-library/skeleton/skeleton.stories.tsx +++ b/ui/components/component-library/skeleton/skeleton.stories.tsx @@ -9,9 +9,11 @@ import { TextVariant, AlignItems, } from '../../../helpers/constants/design-system'; -import { Box, Button, ButtonVariant, Text } from '..'; +import { Text } from '../text'; import README from './README.mdx'; import { Skeleton } from './skeleton'; +import { Box } from '../box'; +import { Button, ButtonVariant } from '../button'; const meta: Meta = { title: 'Components/ComponentLibrary/Skeleton', diff --git a/ui/components/component-library/skeleton/skeleton.tsx b/ui/components/component-library/skeleton/skeleton.tsx index 760083a0c4ca..9c82945858ac 100644 --- a/ui/components/component-library/skeleton/skeleton.tsx +++ b/ui/components/component-library/skeleton/skeleton.tsx @@ -5,7 +5,7 @@ import { BackgroundColor, BorderRadius, } from '../../../helpers/constants/design-system'; -import { Box } from '..'; +import { Box } from '../box'; import type { PolymorphicRef, BoxProps } from '../box'; import { SkeletonProps, SkeletonComponent } from './skeleton.types'; diff --git a/ui/components/component-library/tag-url/tag-url.stories.tsx b/ui/components/component-library/tag-url/tag-url.stories.tsx index aa81632818c0..a33698a24bcc 100644 --- a/ui/components/component-library/tag-url/tag-url.stories.tsx +++ b/ui/components/component-library/tag-url/tag-url.stories.tsx @@ -4,7 +4,7 @@ import { Display, FlexDirection, } from '../../../helpers/constants/design-system'; -import { Box } from '..'; +import { Box } from '../box'; import README from './README.mdx'; import { TagUrl } from './tag-url'; diff --git a/ui/components/component-library/tag-url/tag-url.tsx b/ui/components/component-library/tag-url/tag-url.tsx index 15e3d3dbcef6..89555a3f461f 100644 --- a/ui/components/component-library/tag-url/tag-url.tsx +++ b/ui/components/component-library/tag-url/tag-url.tsx @@ -9,17 +9,11 @@ import { IconColor, TextVariant, } from '../../../helpers/constants/design-system'; -import { - AvatarFavicon, - ButtonLink, - Box, - IconName, - Icon, - IconSize, - Text, - ButtonLinkSize, -} from '..'; -import { BoxProps, PolymorphicRef } from '../box'; +import { Text } from '../text'; +import { Box, BoxProps, PolymorphicRef } from '../box'; +import { ButtonLink, ButtonLinkSize } from '../button-link'; +import { AvatarFavicon } from '../avatar-favicon'; +import { Icon, IconName, IconSize } from '../icon'; import { TagUrlComponent, TagUrlProps } from './tag-url.types'; export const TagUrl: TagUrlComponent = React.forwardRef( diff --git a/ui/components/component-library/tag/tag.tsx b/ui/components/component-library/tag/tag.tsx index 14548f969438..e2ffd73d7df9 100644 --- a/ui/components/component-library/tag/tag.tsx +++ b/ui/components/component-library/tag/tag.tsx @@ -1,7 +1,7 @@ import React from 'react'; import classnames from 'classnames'; -import { Box, Icon, IconSize, Text } from '..'; -import type { BoxProps, PolymorphicRef } from '../box'; +import { Text } from '../text'; +import { Box, type BoxProps, type PolymorphicRef } from '../box'; import { AlignItems, @@ -12,6 +12,7 @@ import { TextVariant, } from '../../../helpers/constants/design-system'; +import { Icon, IconSize } from '../icon'; import { TagComponent, TagProps } from './tag.types'; export const Tag: TagComponent = React.forwardRef( diff --git a/ui/components/component-library/text-field-search/README.mdx b/ui/components/component-library/text-field-search/README.mdx index 24bd69e036a3..6d8e0c9154cc 100644 --- a/ui/components/component-library/text-field-search/README.mdx +++ b/ui/components/component-library/text-field-search/README.mdx @@ -1,6 +1,6 @@ import { Story, Canvas, ArgsTable } from '@storybook/addon-docs'; -import { TextField } from '..'; +import { TextField } from '../text-field'; import { TextFieldSearch } from './text-field-search'; diff --git a/ui/components/component-library/text-field-search/text-field-search.tsx b/ui/components/component-library/text-field-search/text-field-search.tsx index 736f30a55859..a63b989164a0 100644 --- a/ui/components/component-library/text-field-search/text-field-search.tsx +++ b/ui/components/component-library/text-field-search/text-field-search.tsx @@ -1,17 +1,11 @@ import React from 'react'; import classnames from 'classnames'; -import { - ButtonIcon, - ButtonIconSize, - Icon, - IconName, - IconSize, - TextField, - TextFieldType, -} from '..'; import { useI18nContext } from '../../../hooks/useI18nContext'; -import { TextFieldProps } from '../text-field/text-field.types'; +import { TextFieldProps, TextFieldType } from '../text-field/text-field.types'; import { PolymorphicRef } from '../box'; +import { TextField } from '../text-field'; +import { ButtonIcon, ButtonIconSize } from '../button-icon'; +import { Icon, IconName, IconSize } from '../icon'; import { TextFieldSearchProps, TextFieldSearchComponent, diff --git a/ui/components/component-library/text-field/text-field.stories.tsx b/ui/components/component-library/text-field/text-field.stories.tsx index 4de3e956fb61..fafa90f3ecb0 100644 --- a/ui/components/component-library/text-field/text-field.stories.tsx +++ b/ui/components/component-library/text-field/text-field.stories.tsx @@ -12,28 +12,20 @@ import { TextColor, Size, } from '../../../helpers/constants/design-system'; +import { AvatarToken, AvatarTokenSize } from '../avatar-token'; -import { - AvatarAccount, - AvatarAccountSize, - AvatarToken, - Button, - ButtonIcon, - Box, - Text, - IconName, - Icon, - IconSize, - AvatarTokenSize, - Input, -} from '..'; +import { Text } from '../text'; -import { PolymorphicRef } from '../box'; -import { InputProps, InputComponent } from '../input'; +import { Box, PolymorphicRef } from '../box'; +import { InputProps, InputComponent, Input } from '../input'; import { TextFieldSize, TextFieldType } from './text-field.types'; import { TextField } from './text-field'; +import { ButtonIcon } from '../button-icon'; import README from './README.mdx'; +import { Icon, IconName, IconSize } from '../icon'; +import { AvatarAccount, AvatarAccountSize } from '../avatar-account'; +import { Button } from '../button'; export default { title: 'Components/ComponentLibrary/TextField', diff --git a/ui/components/component-library/text-field/text-field.tsx b/ui/components/component-library/text-field/text-field.tsx index 6b8a0f1fe53e..0ab0f95cf43a 100644 --- a/ui/components/component-library/text-field/text-field.tsx +++ b/ui/components/component-library/text-field/text-field.tsx @@ -8,10 +8,8 @@ import { BackgroundColor, } from '../../../helpers/constants/design-system'; -import { Box, Input } from '..'; - -import { BoxProps, PolymorphicRef } from '../box'; -import { InputProps } from '../input'; +import { Box, BoxProps, PolymorphicRef } from '../box'; +import { Input, InputProps } from '../input'; import { TextFieldComponent, TextFieldProps, diff --git a/ui/components/component-library/text/text.stories.tsx b/ui/components/component-library/text/text.stories.tsx index ecdc6e2f1b53..fcb8b26e475f 100644 --- a/ui/components/component-library/text/text.stories.tsx +++ b/ui/components/component-library/text/text.stories.tsx @@ -16,7 +16,7 @@ import { Color, } from '../../../helpers/constants/design-system'; -import { Box } from '..'; +import { Box } from '../box'; import README from './README.mdx'; import { Text } from './text'; diff --git a/ui/components/component-library/text/text.tsx b/ui/components/component-library/text/text.tsx index 02d5d4c89121..3b370347622a 100644 --- a/ui/components/component-library/text/text.tsx +++ b/ui/components/component-library/text/text.tsx @@ -6,8 +6,7 @@ import { TextColor, } from '../../../helpers/constants/design-system'; -import { Box } from '..'; - +import { Box } from '../box'; import type { PolymorphicRef, BoxProps } from '../box'; import { TextProps, TextComponent } from './text.types'; diff --git a/ui/components/component-library/textarea/textarea.stories.tsx b/ui/components/component-library/textarea/textarea.stories.tsx index e059fc7b5a0a..b7d78db9af0d 100644 --- a/ui/components/component-library/textarea/textarea.stories.tsx +++ b/ui/components/component-library/textarea/textarea.stories.tsx @@ -6,7 +6,7 @@ import { FlexDirection, Display, } from '../../../helpers/constants/design-system'; -import { Box } from '..'; +import { Box } from '../box'; import { TextareaResize } from './textarea.types'; import { Textarea } from './textarea'; diff --git a/ui/components/component-library/textarea/textarea.tsx b/ui/components/component-library/textarea/textarea.tsx index dca3a8025f0d..44e9cf938507 100644 --- a/ui/components/component-library/textarea/textarea.tsx +++ b/ui/components/component-library/textarea/textarea.tsx @@ -7,8 +7,7 @@ import { BorderColor, } from '../../../helpers/constants/design-system'; -import { Text } from '..'; -import { TextProps } from '../text'; +import { Text, TextProps } from '../text'; import { PolymorphicRef } from '../box'; import { diff --git a/ui/components/multichain/avatar-group/avatar-group.tsx b/ui/components/multichain/avatar-group/avatar-group.tsx index 39af437980d9..98457ac7bb10 100644 --- a/ui/components/multichain/avatar-group/avatar-group.tsx +++ b/ui/components/multichain/avatar-group/avatar-group.tsx @@ -2,19 +2,7 @@ import * as React from 'react'; import classnames from 'classnames'; import { useSelector } from 'react-redux'; import { getUseBlockie } from '../../../selectors'; -import { - Text, - Box, - AvatarToken, - AvatarTokenSize, - AvatarAccount, - AvatarAccountSize, - AvatarAccountVariant, - AvatarNetwork, - AvatarNetworkSize, - AvatarBase, - AvatarBaseSize, -} from '../../component-library'; +import { Text } from '../../component-library/text'; import { AlignItems, BackgroundColor, @@ -24,6 +12,24 @@ import { TextColor, TextVariant, } from '../../../helpers/constants/design-system'; +import { + AvatarTokenSize, + AvatarToken, +} from '../../component-library/avatar-token'; +import { Box } from '../../component-library/box'; +import { + AvatarAccount, + AvatarAccountSize, + AvatarAccountVariant, +} from '../../component-library/avatar-account'; +import { + AvatarNetwork, + AvatarNetworkSize, +} from '../../component-library/avatar-network'; +import { + AvatarBase, + AvatarBaseSize, +} from '../../component-library/avatar-base'; import { AvatarGroupProps, AvatarType } from './avatar-group.types'; export const AvatarGroup: React.FC = ({ diff --git a/ui/components/multichain/avatar-group/avatar-group.types.tsx b/ui/components/multichain/avatar-group/avatar-group.types.tsx index b5c52b1ed9f5..0c859d8b0a77 100644 --- a/ui/components/multichain/avatar-group/avatar-group.types.tsx +++ b/ui/components/multichain/avatar-group/avatar-group.types.tsx @@ -1,5 +1,5 @@ import { BorderColor } from '../../../helpers/constants/design-system'; -import { AvatarTokenSize } from '../../component-library'; +import { AvatarTokenSize } from '../../component-library/avatar-token/avatar-token.types'; import type { StyleUtilityProps } from '../../component-library/box'; export type AvatarGroupProps = StyleUtilityProps & { From 28f8d74131362db68c9b17c0dc33a064c05d398b Mon Sep 17 00:00:00 2001 From: George Marshall Date: Wed, 12 Feb 2025 16:30:05 -0800 Subject: [PATCH 04/24] chore: adding storybook story for asset picker modal network component (#30235) ## **Description** This PR adds a Storybook story for the `AssetPickerModalNetwork` component, improving coverage and making it easier to view and develop in isolation. [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/30235?quickstart=1) ## **Related issues** Fixes: N/A ## **Manual testing steps** 1. Go to the [storybook build of this PR](https://diuv6g5fj9pvx.cloudfront.net/metamask-extension/13250743903/storybook-build/index.html?path=/story/components-multichain-assetpickermodalnetwork--default) 2. Navigate to `Components/Multichain/AssetPickerModalNetwork` in the Storybook sidebar 3. Test the Default story: - Click "Open Network Modal" button - Verify network list displays correctly - Test modal close functionality 4. Test WithSelectedNetwork story: - Verify Ethereum network is pre-selected 5. Test WithMultiSelect story: - Verify multiple networks can be selected - Confirm Mainnet and Optimism are pre-selected - Check console logs when submitting selections 6. Test WithCustomHeader story: - Verify custom header "Select Source Network" is displayed ## **Screenshots/Recordings** ### **Before** N/A - New component stories ### **After** https://github.com/user-attachments/assets/390203dc-179a-43c1-8d4e-e0fa3c5b1afa ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md) - [x] I've completed the PR template to the best of my ability - [x] I've included tests (Storybook stories serve as interactive tests) - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format - [x] I've applied the right labels on the PR ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed) - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots --- .../asset-picker-modal-network.stories.tsx | 121 ++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 ui/components/multichain/asset-picker-amount/asset-picker-modal/asset-picker-modal-network.stories.tsx diff --git a/ui/components/multichain/asset-picker-amount/asset-picker-modal/asset-picker-modal-network.stories.tsx b/ui/components/multichain/asset-picker-amount/asset-picker-modal/asset-picker-modal-network.stories.tsx new file mode 100644 index 000000000000..489649727826 --- /dev/null +++ b/ui/components/multichain/asset-picker-amount/asset-picker-modal/asset-picker-modal-network.stories.tsx @@ -0,0 +1,121 @@ +import React, { useState } from 'react'; +import { Provider } from 'react-redux'; +import { RpcEndpointType, NetworkConfiguration } from '@metamask/network-controller'; +import { CHAIN_IDS } from '@metamask/transaction-controller'; +import configureStore from '../../../../store/store'; +import mockState from '../../../../../test/data/mock-state.json'; +import { AssetPickerModalNetwork } from './asset-picker-modal-network'; +import { Meta, StoryFn } from '@storybook/react'; +import { Button } from '../../../component-library'; + +const networks: NetworkConfiguration[] = [ + { + chainId: CHAIN_IDS.MAINNET, + nativeCurrency: 'ETH', + defaultBlockExplorerUrlIndex: 0, + blockExplorerUrls: ['https://explorerurl'], + defaultRpcEndpointIndex: 0, + rpcEndpoints: [ + { + networkClientId: 'test1', + url: 'https://rpcurl', + type: RpcEndpointType.Custom as const, + }, + ], + name: 'Ethereum', + }, + { + chainId: CHAIN_IDS.OPTIMISM, + nativeCurrency: 'ETH', + defaultBlockExplorerUrlIndex: 0, + blockExplorerUrls: ['https://explorerurl'], + defaultRpcEndpointIndex: 0, + rpcEndpoints: [ + { + networkClientId: 'test2', + url: 'https://rpcurl', + type: RpcEndpointType.Custom as const, + }, + ], + name: 'OP Mainnet', + }, + { + chainId: CHAIN_IDS.BSC, + nativeCurrency: 'BNB', + defaultBlockExplorerUrlIndex: 0, + blockExplorerUrls: ['https://explorerurl'], + defaultRpcEndpointIndex: 0, + rpcEndpoints: [ + { + networkClientId: 'test3', + url: 'https://rpcurl', + type: RpcEndpointType.Custom as const, + }, + ], + name: 'BNB Smart Chain', + }, +]; + +function store() { + return configureStore(mockState); +} + +const AssetPickerModalNetworkWithButton: StoryFn = (args) => { + const [isOpen, setIsOpen] = useState(false); + + return ( + + + setIsOpen(false)} + /> + + ); +}; + +const meta: Meta = { + title: 'Components/Multichain/AssetPickerModalNetwork', + component: AssetPickerModalNetwork, + render: AssetPickerModalNetworkWithButton, + args: { + onNetworkChange: () => {}, + onBack: () => {}, + }, +}; + +export default meta; +const Story = { + args: {} as Partial>, +}; +type StoryType = typeof Story & { args: Partial> }; + +export const Default: StoryType = { + args: { + networks, + }, +}; + +export const WithSelectedNetwork: StoryType = { + args: { + networks, + network: networks[0], + }, +}; + +export const WithMultiSelect: StoryType = { + args: { + networks, + isMultiselectEnabled: true, + selectedChainIds: [CHAIN_IDS.MAINNET, CHAIN_IDS.OPTIMISM], + onMultiselectSubmit: (chainIds) => console.log('Selected chains:', chainIds), + }, +}; + +export const WithCustomHeader: StoryType = { + args: { + networks, + header: 'Select Source Network', + }, +}; From baf9b082817d68ff924662ac0efb0b7d032908d1 Mon Sep 17 00:00:00 2001 From: Harika <153644847+hjetpoluru@users.noreply.github.com> Date: Wed, 12 Feb 2025 21:02:37 -0500 Subject: [PATCH 05/24] test: snap-bip-32 test scenario migration to pom (#30175) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## **Description** PR to migrate snap-bip32 test scenario to POM PR to migrate snap-bip44 test scenario to POM [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/30175?quickstart=1) ## **Related issues** Fixes: https://github.com/MetaMask/metamask-extension/issues/29894 https://github.com/MetaMask/metamask-extension/issues/30179 ## **Manual testing steps** yarn build:test:flask yarn test:e2e:single test/e2e/snaps/test-snap-bip-32.spec.ts --browser=chrome --leave-running yarn test:e2e:single test/e2e/snaps/test-snap-bip-44.spec.ts --browser=chrome --leave-running ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --- .../pages/dialog/snap-install-warning.ts | 44 +++++ .../page-objects/pages/dialog/snap-install.ts | 54 ++++++ test/e2e/page-objects/pages/test-snaps.ts | 127 ++++++++++++++ test/e2e/snaps/test-snap-bip-32.spec.js | 157 ------------------ test/e2e/snaps/test-snap-bip-32.spec.ts | 124 ++++++++++++++ test/e2e/snaps/test-snap-bip-44.spec.js | 116 ------------- test/e2e/snaps/test-snap-bip-44.spec.ts | 80 +++++++++ 7 files changed, 429 insertions(+), 273 deletions(-) create mode 100644 test/e2e/page-objects/pages/dialog/snap-install-warning.ts create mode 100644 test/e2e/page-objects/pages/dialog/snap-install.ts delete mode 100644 test/e2e/snaps/test-snap-bip-32.spec.js create mode 100644 test/e2e/snaps/test-snap-bip-32.spec.ts delete mode 100644 test/e2e/snaps/test-snap-bip-44.spec.js create mode 100644 test/e2e/snaps/test-snap-bip-44.spec.ts diff --git a/test/e2e/page-objects/pages/dialog/snap-install-warning.ts b/test/e2e/page-objects/pages/dialog/snap-install-warning.ts new file mode 100644 index 000000000000..da2937e20eb9 --- /dev/null +++ b/test/e2e/page-objects/pages/dialog/snap-install-warning.ts @@ -0,0 +1,44 @@ +import { Driver } from '../../../webdriver/driver'; + +class SnapInstallWarning { + private driver: Driver; + + private readonly checkBoxPermission = '.mm-checkbox__input'; + + private readonly buttonConfirm = + '[data-testid="snap-install-warning-modal-confirm"]'; + + private readonly permissionConnect = '.permissions-connect'; + + constructor(driver: Driver) { + this.driver = driver; + } + + async check_pageIsLoaded(): Promise { + try { + await this.driver.waitForMultipleSelectors([ + this.checkBoxPermission, + this.permissionConnect, + ]); + } catch (e) { + console.log( + 'Timeout while waiting for snap install warning dialog to be loaded', + e, + ); + throw e; + } + console.log('Snap install warning dialog is loaded'); + } + + async clickCheckboxPermission() { + console.log('Click checkbox permission'); + await this.driver.clickElement(this.checkBoxPermission); + } + + async clickConfirmButton() { + console.log('Click confirm button'); + await this.driver.clickElement(this.buttonConfirm); + } +} + +export default SnapInstallWarning; diff --git a/test/e2e/page-objects/pages/dialog/snap-install.ts b/test/e2e/page-objects/pages/dialog/snap-install.ts new file mode 100644 index 000000000000..65b09ef73385 --- /dev/null +++ b/test/e2e/page-objects/pages/dialog/snap-install.ts @@ -0,0 +1,54 @@ +import { Driver } from '../../../webdriver/driver'; + +class SnapInstall { + private driver: Driver; + + private readonly nextPageButton = + '[data-testid="page-container-footer-next"]'; + + private readonly pageFooter = '.page-container__footer'; + + private readonly permissionConnect = '.permissions-connect'; + + private readonly scrollSnapInstall = '[data-testid="snap-install-scroll"]'; + + private readonly approveButton = '[data-testid="confirmation-submit-button"]'; + + constructor(driver: Driver) { + this.driver = driver; + } + + async check_pageIsLoaded(): Promise { + try { + await this.driver.waitForMultipleSelectors([ + this.pageFooter, + this.permissionConnect, + ]); + } catch (e) { + console.log( + 'Timeout while waiting for Snap install dialog to be loaded', + e, + ); + throw e; + } + console.log('Snap install dialog is loaded'); + } + + async clickNextButton() { + console.log('Click Confirm/Ok button'); + await this.driver.clickElement(this.nextPageButton); + } + + async clickConfirmButton() { + console.log('Scroll and click confirm button'); + await this.driver.clickElementSafe(this.scrollSnapInstall); + await this.driver.clickElement(this.nextPageButton); + } + + async clickApproveButton() { + console.log('Click approve button'); + await this.driver.clickElement(this.approveButton); + } +} + +export default SnapInstall; diff --git a/test/e2e/page-objects/pages/test-snaps.ts b/test/e2e/page-objects/pages/test-snaps.ts index bf149e58277a..c53d56570915 100644 --- a/test/e2e/page-objects/pages/test-snaps.ts +++ b/test/e2e/page-objects/pages/test-snaps.ts @@ -32,6 +32,48 @@ export class TestSnaps { private readonly connectHomePage = '#connecthomepage'; + private readonly connectBip32 = '#connectbip32'; + + private readonly connectBip44 = '#connectbip44'; + + private readonly reconnectButton = { + css: '#connectbip32', + text: 'Reconnect to BIP-32 Snap', + }; + + private readonly reconnectBip44Button = { + css: '#connectbip44', + text: 'Reconnect to BIP-44 Snap', + }; + + private readonly getPublicKeyButton = { + css: '#bip32GetPublic', + text: 'Get Public Key', + }; + + private readonly getCompressedKeyButton = { + css: '#bip32GetCompressedPublic', + text: 'Get Compressed Public Key', + }; + + private readonly publicKeyBip44Button = '#sendBip44Test'; + + private readonly inputMessageEd25519 = '#bip32Message-ed25519'; + + private readonly inputMessageEd25519Bip32 = '#bip32Message-ed25519Bip32'; + + private readonly inputMessageSecp256k1 = '#bip32Message-secp256k1'; + + private readonly buttonMessageSecp256k1 = '#sendBip32-secp256k1'; + + private readonly buttonSignEd25519Message = '#sendBip32-ed25519'; + + private readonly inputMessageBip44 = '#bip44Message'; + + private readonly buttonSignBip44Message = '#signBip44Message'; + + private readonly buttonSignEd25519Bip32Message = '#sendBip32-ed25519Bip32'; + constructor(driver: Driver) { this.driver = driver; } @@ -53,6 +95,44 @@ export class TestSnaps { await this.driver.clickElement(this.dialogsSnapConfirmationButton); } + async clickConnectBip32() { + console.log('Wait, scroll and click connect button'); + await this.driver.scrollToElement( + this.driver.findClickableElement(this.connectBip32), + ); + await this.driver.delay(largeDelayMs); + await this.driver.waitForSelector(this.connectBip32); + await this.driver.clickElement(this.connectBip32); + } + + async clickConnectBip44() { + console.log('Wait, scroll and click connect button'); + await this.driver.scrollToElement( + this.driver.findClickableElement(this.connectBip44), + ); + await this.driver.delay(largeDelayMs); + await this.driver.waitForSelector(this.connectBip44); + await this.driver.clickElement(this.connectBip44); + } + + async clickGetPublicKeyButton() { + console.log('Wait and click get public key button'); + await this.driver.waitForSelector(this.getPublicKeyButton); + await this.driver.clickElement(this.getPublicKeyButton); + } + + async clickPublicKeyBip44Button() { + console.log('Wait and click get public key button'); + await this.driver.waitForSelector(this.publicKeyBip44Button); + await this.driver.clickElement(this.publicKeyBip44Button); + } + + async clickGetCompressedPublicKeyButton() { + console.log('Wait and click get compressed public key button'); + await this.driver.waitForSelector(this.getCompressedKeyButton); + await this.driver.clickElement(this.getCompressedKeyButton); + } + async completeSnapInstallConfirmation() { await this.driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog); @@ -85,4 +165,51 @@ export class TestSnaps { await this.driver.waitForSelector(this.connectHomePage); await this.driver.clickElement(this.connectHomePage); } + + async fillMessageSecp256k1(message: string) { + console.log('Wait and fill message in secp256k1'); + await this.driver.fill(this.inputMessageSecp256k1, message); + await this.driver.clickElement(this.buttonMessageSecp256k1); + } + + async fillMessageEd25519(message: string) { + console.log('Wait and fill message in ed25519'); + await this.driver.waitForSelector(this.inputMessageEd25519); + await this.driver.fill(this.inputMessageEd25519, message); + await this.driver.clickElement(this.buttonSignEd25519Message); + } + + async fillMessageEd25519Bip32(message: string) { + console.log('Wait and fill message in ed25519 bip32'); + await this.driver.waitForSelector(this.inputMessageEd25519Bip32); + await this.driver.fill(this.inputMessageEd25519Bip32, message); + await this.driver.clickElement(this.buttonSignEd25519Bip32Message); + } + + async fillBip44MessageAndSign(message: string) { + console.log('Wait and enter bip44 message '); + await this.driver.pasteIntoField(this.inputMessageBip44, message); + const buttonSignBip44 = await this.driver.findElement( + this.buttonSignBip44Message, + ); + await this.driver.scrollToElement(buttonSignBip44); + await this.driver.waitForSelector(this.buttonSignBip44Message); + await this.driver.clickElement(this.buttonSignBip44Message); + } + + async scrollToSendEd25519() { + console.log('Scroll to send ed25519'); + const sendEd25519 = await this.driver.findElement(this.inputMessageEd25519); + await this.driver.scrollToElement(sendEd25519); + } + + async waitForReconnectButton() { + console.log('Wait for reconnect button'); + await this.driver.waitForSelector(this.reconnectButton); + } + + async waitForReconnectBip44Button() { + console.log('Wait for reconnect button'); + await this.driver.waitForSelector(this.reconnectBip44Button); + } } diff --git a/test/e2e/snaps/test-snap-bip-32.spec.js b/test/e2e/snaps/test-snap-bip-32.spec.js deleted file mode 100644 index f6f01b8c2ee2..000000000000 --- a/test/e2e/snaps/test-snap-bip-32.spec.js +++ /dev/null @@ -1,157 +0,0 @@ -const { withFixtures, unlockWallet, WINDOW_TITLES } = require('../helpers'); -const FixtureBuilder = require('../fixture-builder'); -const { TEST_SNAPS_WEBSITE_URL } = require('./enums'); - -describe('Test Snap bip-32', function () { - it('tests various functions of bip-32', async function () { - await withFixtures( - { - fixtures: new FixtureBuilder().build(), - title: this.test.fullTitle(), - }, - async ({ driver }) => { - await unlockWallet(driver); - - // navigate to test snaps page and connect - await driver.driver.get(TEST_SNAPS_WEBSITE_URL); - - // wait for page to load - await driver.waitForSelector({ - text: 'Installed Snaps', - tag: 'h2', - }); - - // find and scroll to the bip32 snap - const snapButton1 = await driver.findElement('#connectbip32'); - await driver.scrollToElement(snapButton1); - - // added delay for firefox (deflake) - await driver.delayFirefox(3000); - - // wait for and click connect to bip-32 - await driver.waitForSelector('#connectbip32'); - await driver.clickElement('#connectbip32'); - - // switch to metamask extension and click connect - await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog); - await driver.waitForSelector({ - text: 'Connect', - tag: 'button', - }); - await driver.clickElement({ - text: 'Connect', - tag: 'button', - }); - - // wait for confirm to appear - await driver.waitForSelector({ text: 'Confirm' }); - - // click and dismiss possible scroll element - await driver.clickElementSafe('[data-testid="snap-install-scroll"]'); - - // click confirm - await driver.clickElement({ - text: 'Confirm', - tag: 'button', - }); - - // wait for permissions popover, click checkboxes and confirm - await driver.waitForSelector('.mm-checkbox__input'); - await driver.clickElement('.mm-checkbox__input'); - await driver.waitForSelector( - '[data-testid="snap-install-warning-modal-confirm"]', - ); - await driver.clickElement( - '[data-testid="snap-install-warning-modal-confirm"]', - ); - - // wait for and click OK and wait for window to close - await driver.waitForSelector({ text: 'OK' }); - await driver.clickElementAndWaitForWindowToClose({ - text: 'OK', - tag: 'button', - }); - - // switch back to test-snaps window - await driver.switchToWindowWithTitle(WINDOW_TITLES.TestSnaps); - - // wait for npm installation success - await driver.waitForSelector({ - css: '#connectbip32', - text: 'Reconnect to BIP-32 Snap', - }); - - // scroll to and click get public key - await driver.waitForSelector({ text: 'Get Public Key' }); - await driver.clickElement('#bip32GetPublic'); - - // check for proper public key response using waitForSelector - await driver.waitForSelector({ - css: '#bip32PublicKeyResult', - text: '"0x043e98d696ae15caef75fa8dd204a7c5c08d1272b2218ba3c20feeb4c691eec366606ece56791c361a2320e7fad8bcbb130f66d51c591fc39767ab2856e93f8dfb', - }); - - // scroll to and click get compressed public key - await driver.waitForSelector({ text: 'Get Compressed Public Key' }); - await driver.clickElement('#bip32GetCompressedPublic'); - - // check for proper public key response using waitForSelector - await driver.waitForSelector({ - css: '#bip32PublicKeyResult', - text: '"0x033e98d696ae15caef75fa8dd204a7c5c08d1272b2218ba3c20feeb4c691eec366', - }); - - // wait then run SECP256K1 test - await driver.fill('#bip32Message-secp256k1', 'foo bar'); - await driver.clickElement('#sendBip32-secp256k1'); - - // hit 'approve' on the signature confirmation and wait for window to close - await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog); - await driver.clickElementAndWaitForWindowToClose({ - text: 'Approve', - tag: 'button', - }); - - // switch back to the test-snaps window - await driver.switchToWindowWithTitle(WINDOW_TITLES.TestSnaps); - - // check results of the secp256k1 signature with waitForSelector - await driver.waitForSelector({ - css: '#bip32MessageResult-secp256k1', - text: '"0x3045022100b3ade2992ea3e5eb58c7550e9bddad356e9554233c8b099ebc3cb418e9301ae2022064746e15ae024808f0ba5d860e44dc4c97e65c8cba6f5ef9ea2e8c819930d2dc', - }); - - // scroll further into messages section - const snapButton4 = await driver.findElement('#sendBip32-ed25519'); - await driver.scrollToElement(snapButton4); - - // wait then run ed25519 test - await driver.waitForSelector('#bip32Message-ed25519'); - await driver.fill('#bip32Message-ed25519', 'foo bar'); - await driver.clickElement('#sendBip32-ed25519'); - - // switch to dialog window - await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog); - - // wait for and click 'approve' and wait for window to close - await driver.waitForSelector({ - text: 'Approve', - tag: 'button', - }); - await driver.clickElementAndWaitForWindowToClose({ - text: 'Approve', - tag: 'button', - }); - - // switch back to test-snaps window - await driver.switchToWindowWithTitle(WINDOW_TITLES.TestSnaps); - - // check results of ed25519 signature with waitForSelector - await driver.waitForSelector({ - css: '#bip32MessageResult-ed25519', - text: '"0xf3215b4d6c59aac7e01b4ceef530d1e2abf4857926b85a81aaae3894505699243768a887b7da4a8c2e0f25196196ba290b6531050db8dc15c252bdd508532a0a"', - }); - }, - ); - }); -}); diff --git a/test/e2e/snaps/test-snap-bip-32.spec.ts b/test/e2e/snaps/test-snap-bip-32.spec.ts new file mode 100644 index 000000000000..112a2bace440 --- /dev/null +++ b/test/e2e/snaps/test-snap-bip-32.spec.ts @@ -0,0 +1,124 @@ +import { TestSnaps } from '../page-objects/pages/test-snaps'; +import { Driver } from '../webdriver/driver'; +import { loginWithoutBalanceValidation } from '../page-objects/flows/login.flow'; +import FixtureBuilder from '../fixture-builder'; +import { withFixtures, WINDOW_TITLES } from '../helpers'; +import SnapInstall from '../page-objects/pages/dialog/snap-install'; +import SnapInstallWarning from '../page-objects/pages/dialog/snap-install-warning'; + +describe('Test Snap bip-32', function () { + it('tests various functions of bip-32', async function () { + await withFixtures( + { + fixtures: new FixtureBuilder().build(), + title: this.test?.fullTitle(), + }, + async ({ driver }: { driver: Driver }) => { + await loginWithoutBalanceValidation(driver); + + const testSnaps = new TestSnaps(driver); + const snapInstall = new SnapInstall(driver); + const snapInstallWarning = new SnapInstallWarning(driver); + + // navigate to test snaps page and connect wait for page to load + await testSnaps.openPage(); + + // find, scroll and click connect to the bip32 snap + await testSnaps.clickConnectBip32(); + + // switch to metamask extension and click connect + await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog); + await snapInstall.check_pageIsLoaded(); + await snapInstall.clickNextButton(); + + // click confirm + await snapInstall.clickConfirmButton(); + + // wait for permissions popover, click checkboxes and confirm + await snapInstallWarning.check_pageIsLoaded(); + await snapInstallWarning.clickCheckboxPermission(); + await snapInstallWarning.clickConfirmButton(); + + // wait for and click OK and wait for window to close + await snapInstall.clickNextButton(); + + // switch back to test-snaps window + await driver.switchToWindowWithTitle(WINDOW_TITLES.TestSnaps); + + // wait for npm installation success + await testSnaps.waitForReconnectButton(); + + // scroll to and click get public key + await testSnaps.clickGetPublicKeyButton(); + + // check for proper public key response using waitForSelector + await driver.waitForSelector({ + css: '#bip32PublicKeyResult', + text: '"0x043e98d696ae15caef75fa8dd204a7c5c08d1272b2218ba3c20feeb4c691eec366606ece56791c361a2320e7fad8bcbb130f66d51c591fc39767ab2856e93f8dfb', + }); + + // scroll to and click get compressed public key + await testSnaps.clickGetCompressedPublicKeyButton(); + + // check for proper public key response using waitForSelector + await driver.waitForSelector({ + css: '#bip32PublicKeyResult', + text: '"0x033e98d696ae15caef75fa8dd204a7c5c08d1272b2218ba3c20feeb4c691eec366', + }); + + // wait then run SECP256K1 test + await testSnaps.fillMessageSecp256k1('foo bar'); + + // hit 'approve' on the signature confirmation and wait for window to close + await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog); + await snapInstall.clickApproveButton(); + + // switch back to the test-snaps window + await driver.switchToWindowWithTitle(WINDOW_TITLES.TestSnaps); + + // check results of the secp256k1 signature with waitForSelector + await driver.waitForSelector({ + css: '#bip32MessageResult-secp256k1', + text: '"0x3045022100b3ade2992ea3e5eb58c7550e9bddad356e9554233c8b099ebc3cb418e9301ae2022064746e15ae024808f0ba5d860e44dc4c97e65c8cba6f5ef9ea2e8c819930d2dc', + }); + + // scroll further into messages section + await testSnaps.scrollToSendEd25519(); + + // wait then run ed25519 test + await testSnaps.fillMessageEd25519('foo bar'); + + // switch to dialog window + await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog); + + await snapInstall.clickApproveButton(); + + // switch back to test-snaps window + await driver.switchToWindowWithTitle(WINDOW_TITLES.TestSnaps); + + // check results of ed25519 signature with waitForSelector + await driver.waitForSelector({ + css: '#bip32MessageResult-ed25519', + text: '"0xf3215b4d6c59aac7e01b4ceef530d1e2abf4857926b85a81aaae3894505699243768a887b7da4a8c2e0f25196196ba290b6531050db8dc15c252bdd508532a0a"', + }); + + // wait then run ed25519 test + await testSnaps.fillMessageEd25519Bip32('foo bar'); + + // switch to dialog window + await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog); + + await snapInstall.clickApproveButton(); + + // switch back to test-snaps window + await driver.switchToWindowWithTitle(WINDOW_TITLES.TestSnaps); + + // check results of ed25519 signature with waitForSelector + await driver.waitForSelector({ + css: '#bip32MessageResult-ed25519Bip32', + text: '"0xc279ee3e49f7e392a4e511136c39791e076f9be01d8648f3f1586ecf0f41def1739fa2978f90cfb2da4cf53ccb99405558cffcc4d190199b6949b03b1b8dae05"', + }); + }, + ); + }); +}); diff --git a/test/e2e/snaps/test-snap-bip-44.spec.js b/test/e2e/snaps/test-snap-bip-44.spec.js deleted file mode 100644 index 9846701be34d..000000000000 --- a/test/e2e/snaps/test-snap-bip-44.spec.js +++ /dev/null @@ -1,116 +0,0 @@ -const { withFixtures, unlockWallet, WINDOW_TITLES } = require('../helpers'); -const FixtureBuilder = require('../fixture-builder'); -const { TEST_SNAPS_WEBSITE_URL } = require('./enums'); - -describe('Test Snap bip-44', function () { - it('can pop up bip-44 snap and get private key result', async function () { - await withFixtures( - { - fixtures: new FixtureBuilder().build(), - title: this.test.fullTitle(), - }, - async ({ driver }) => { - await unlockWallet(driver); - - // navigate to test snaps page and connect - await driver.driver.get(TEST_SNAPS_WEBSITE_URL); - - // wait for page to load - await driver.waitForSelector({ - text: 'Installed Snaps', - tag: 'h2', - }); - - // find and scroll to the bip44 snap - const snapButton1 = await driver.findElement('#connectbip44'); - await driver.scrollToElement(snapButton1); - - // added delay for firefox (deflake) - await driver.delayFirefox(1000); - - // wait for and click connect - await driver.waitForSelector('#connectbip44'); - await driver.clickElement('#connectbip44'); - - // switch to metamask extension and click connect and approve - await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog); - await driver.clickElement({ - text: 'Connect', - tag: 'button', - }); - await driver.waitForSelector({ text: 'Confirm' }); - - await driver.clickElementSafe('[data-testid="snap-install-scroll"]'); - - await driver.clickElement({ - text: 'Confirm', - tag: 'button', - }); - - // deal with permissions popover - await driver.waitForSelector('.mm-checkbox__input'); - await driver.clickElement('.mm-checkbox__input'); - await driver.waitForSelector( - '[data-testid="snap-install-warning-modal-confirm"]', - ); - await driver.clickElement( - '[data-testid="snap-install-warning-modal-confirm"]', - ); - - // wait for and click ok and wait for window to close - await driver.waitForSelector({ text: 'OK' }); - await driver.clickElementAndWaitForWindowToClose({ - text: 'OK', - tag: 'button', - }); - - // switch back to test-snaps window - await driver.switchToWindowWithTitle(WINDOW_TITLES.TestSnaps); - - // wait for npm installation success - await driver.waitForSelector({ - css: '#connectbip44', - text: 'Reconnect to BIP-44 Snap', - }); - - // find and click bip44 test - await driver.clickElement('#sendBip44Test'); - - // check the results of the public key test using waitForSelector - await driver.waitForSelector({ - css: '#bip44Result', - text: '"0x86debb44fb3a984d93f326131d4c1db0bc39644f1a67b673b3ab45941a1cea6a385981755185ac4594b6521e4d1e08d1"', - }); - - // enter a message to sign - await driver.pasteIntoField('#bip44Message', '1234'); - const snapButton3 = await driver.findElement('#signBip44Message'); - await driver.scrollToElement(snapButton3); - await driver.waitForSelector('#signBip44Message'); - await driver.clickElement('#signBip44Message'); - - // Switch to approve signature message window - await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog); - - // wait for and click approve and wait for window to close - await driver.waitForSelector({ - text: 'Approve', - tag: 'button', - }); - await driver.clickElementAndWaitForWindowToClose({ - text: 'Approve', - tag: 'button', - }); - - // switch back to test-snaps page - await driver.switchToWindowWithTitle(WINDOW_TITLES.TestSnaps); - - // check the results of the message signature using waitForSelector - await driver.waitForSelector({ - css: '#bip44SignResult', - text: '"0xa41ab87ca50606eefd47525ad90294bbe44c883f6bc53655f1b8a55aa8e1e35df216f31be62e52c7a1faa519420e20810162e07dedb0fde2a4d997ff7180a78232ecd8ce2d6f4ba42ccacad33c5e9e54a8c4d41506bdffb2bb4c368581d8b086"', - }); - }, - ); - }); -}); diff --git a/test/e2e/snaps/test-snap-bip-44.spec.ts b/test/e2e/snaps/test-snap-bip-44.spec.ts new file mode 100644 index 000000000000..ddd905996c57 --- /dev/null +++ b/test/e2e/snaps/test-snap-bip-44.spec.ts @@ -0,0 +1,80 @@ +import { TestSnaps } from '../page-objects/pages/test-snaps'; +import { Driver } from '../webdriver/driver'; +import { loginWithoutBalanceValidation } from '../page-objects/flows/login.flow'; +import FixtureBuilder from '../fixture-builder'; +import { withFixtures, WINDOW_TITLES } from '../helpers'; +import SnapInstall from '../page-objects/pages/dialog/snap-install'; +import SnapInstallWarning from '../page-objects/pages/dialog/snap-install-warning'; + +describe('Test Snap bip-44', function () { + it('can pop up bip-44 snap and get private key result', async function () { + await withFixtures( + { + fixtures: new FixtureBuilder().build(), + title: this.test?.fullTitle(), + }, + async ({ driver }: { driver: Driver }) => { + await loginWithoutBalanceValidation(driver); + + const testSnaps = new TestSnaps(driver); + const snapInstall = new SnapInstall(driver); + const snapInstallWarning = new SnapInstallWarning(driver); + + // navigate to test snaps page and connect wait for page to load + await testSnaps.openPage(); + + // find and scroll to the bip44 snap + await testSnaps.clickConnectBip44(); + + // switch to metamask extension and click connect and approve + await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog); + await snapInstall.check_pageIsLoaded(); + await snapInstall.clickNextButton(); + + // click confirm + await snapInstall.clickConfirmButton(); + + // deal with permissions popover, click checkboxes and confirm + await snapInstallWarning.check_pageIsLoaded(); + await snapInstallWarning.clickCheckboxPermission(); + await snapInstallWarning.clickConfirmButton(); + + // wait for and click ok and wait for window to close + await snapInstall.clickNextButton(); + + // switch back to test-snaps window + await driver.switchToWindowWithTitle(WINDOW_TITLES.TestSnaps); + + // wait for npm installation success + await testSnaps.waitForReconnectBip44Button(); + + // find and click bip44 test + await testSnaps.clickPublicKeyBip44Button(); + + // check the results of the public key test using waitForSelector + await driver.waitForSelector({ + css: '#bip44Result', + text: '"0x86debb44fb3a984d93f326131d4c1db0bc39644f1a67b673b3ab45941a1cea6a385981755185ac4594b6521e4d1e08d1"', + }); + + // enter a message to sign + await testSnaps.fillBip44MessageAndSign('1234'); + + // Switch to approve signature message window + await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog); + + // wait for and click approve and wait for window to close + await snapInstall.clickApproveButton(); + + // switch back to test-snaps page + await driver.switchToWindowWithTitle(WINDOW_TITLES.TestSnaps); + + // check the results of the message signature using waitForSelector + await driver.waitForSelector({ + css: '#bip44SignResult', + text: '"0xa41ab87ca50606eefd47525ad90294bbe44c883f6bc53655f1b8a55aa8e1e35df216f31be62e52c7a1faa519420e20810162e07dedb0fde2a4d997ff7180a78232ecd8ce2d6f4ba42ccacad33c5e9e54a8c4d41506bdffb2bb4c368581d8b086"', + }); + }, + ); + }); +}); From 9104b8e3daead4e06d972e41cb1e05ec5b397c1d Mon Sep 17 00:00:00 2001 From: Pedro Figueiredo Date: Thu, 13 Feb 2025 10:14:08 +0000 Subject: [PATCH 06/24] fix: Avoid nonce flicker when transaction is submitted (#30193) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## **Description** Submitting or cancelling a transaction was clearing the custom nonce field before the confirmation popup had time to close. This PR fixes that. [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/30193?quickstart=1) ## **Related issues** Fixes: https://github.com/MetaMask/MetaMask-planning/issues/4140 ## **Manual testing steps** 1. Go to this page... 2. 3. ## **Screenshots/Recordings** ### **Before** https://github.com/user-attachments/assets/fc803f67-cb8a-4bda-bbaa-745036fae9e3 https://github.com/user-attachments/assets/95a679f8-acba-4155-82a1-d1b536e1c5d8 ### **After** ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --- .../components/confirm/footer/footer.test.tsx | 24 ------------------- .../components/confirm/footer/footer.tsx | 6 ----- 2 files changed, 30 deletions(-) diff --git a/ui/pages/confirmations/components/confirm/footer/footer.test.tsx b/ui/pages/confirmations/components/confirm/footer/footer.test.tsx index b931ec782f65..506d3b9af9f4 100644 --- a/ui/pages/confirmations/components/confirm/footer/footer.test.tsx +++ b/ui/pages/confirmations/components/confirm/footer/footer.test.tsx @@ -136,20 +136,8 @@ describe('ConfirmFooter', () => { // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any .mockImplementation(() => ({} as any)); - const updateCustomNonceSpy = jest - .spyOn(Actions, 'updateCustomNonce') - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - .mockImplementation(() => ({} as any)); - const setNextNonceSpy = jest - .spyOn(Actions, 'setNextNonce') - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - .mockImplementation(() => ({} as any)); fireEvent.click(cancelButton); expect(rejectSpy).toHaveBeenCalled(); - expect(updateCustomNonceSpy).toHaveBeenCalledWith(''); - expect(setNextNonceSpy).toHaveBeenCalledWith(''); }); it('invoke required actions when submit button is clicked', () => { @@ -160,20 +148,8 @@ describe('ConfirmFooter', () => { // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any .mockImplementation(() => ({} as any)); - const updateCustomNonceSpy = jest - .spyOn(Actions, 'updateCustomNonce') - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - .mockImplementation(() => ({} as any)); - const setNextNonceSpy = jest - .spyOn(Actions, 'setNextNonce') - // TODO: Replace `any` with type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - .mockImplementation(() => ({} as any)); fireEvent.click(submitButton); expect(resolveSpy).toHaveBeenCalled(); - expect(updateCustomNonceSpy).toHaveBeenCalledWith(''); - expect(setNextNonceSpy).toHaveBeenCalledWith(''); }); it('displays a danger "Confirm" button there are danger alerts', async () => { diff --git a/ui/pages/confirmations/components/confirm/footer/footer.tsx b/ui/pages/confirmations/components/confirm/footer/footer.tsx index 095caaee88c3..9e20f22a15d3 100644 --- a/ui/pages/confirmations/components/confirm/footer/footer.tsx +++ b/ui/pages/confirmations/components/confirm/footer/footer.tsx @@ -20,11 +20,9 @@ import useAlerts from '../../../../../hooks/useAlerts'; import { rejectPendingApproval, resolvePendingApproval, - setNextNonce, ///: BEGIN:ONLY_INCLUDE_IF(build-main,build-beta,build-flask) updateAndApproveTx, ///: END:ONLY_INCLUDE_IF - updateCustomNonce, } from '../../../../../store/actions'; import { isSignatureTransactionType } from '../../../utils'; import { useConfirmContext } from '../../../context/confirm'; @@ -190,8 +188,6 @@ const Footer = () => { dispatch( rejectPendingApproval(currentConfirmation.id, serializeError(error)), ); - dispatch(updateCustomNonce('')); - dispatch(setNextNonce('')); }, [currentConfirmation], ); @@ -223,8 +219,6 @@ const Footer = () => { } else { dispatch(resolvePendingApproval(currentConfirmation.id, undefined)); } - dispatch(updateCustomNonce('')); - dispatch(setNextNonce('')); }, [currentConfirmation, customNonceValue]); const handleFooterCancel = useCallback(() => { From 9c720d32c7712ff88f44079099a36773dabad448 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ant=C3=B3nio=20Regadas?= Date: Thu, 13 Feb 2025 10:42:54 +0000 Subject: [PATCH 07/24] chore: Refactor the way multichain balances and transactions controllers are being declared in metamask-controller (#30262) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## **Description** This PR refactors the way multichain balances and transactions controllers initialize in metamask-controller, following the new pattern established. I also noticed that the multichain balances controller was not guarded by the flask code fence and added it in, since its only used for the non-evm networks. ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/SOL-152 ## **Manual testing steps** 1. Go to this page... 2. 3. ## **Screenshots/Recordings** ### **Before** ### **After** ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --- .../controller-init/controller-list.ts | 6 ++ .../controller-init/messengers/index.ts | 16 +++++ ...hain-balances-controller-messenger.test.ts | 29 ++++++++ ...ultichain-balances-controller-messenger.ts | 57 ++++++++++++++++ ...-transactions-controller-messenger.test.ts | 29 ++++++++ ...chain-transactions-controller-messenger.ts | 48 ++++++++++++++ ...ultichain-balances-controller-init.test.ts | 62 +++++++++++++++++ .../multichain-balances-controller-init.ts | 22 +++++++ ...chain-transactions-controller-init.test.ts | 62 +++++++++++++++++ ...multichain-transactions-controller-init.ts | 26 ++++++++ app/scripts/controller-init/utils.ts | 13 ++-- app/scripts/metamask-controller.js | 66 +++++-------------- test/e2e/tests/metrics/errors.spec.js | 1 + ...rs-after-init-opt-in-background-state.json | 1 - .../errors-after-init-opt-in-ui-state.json | 11 ++-- 15 files changed, 389 insertions(+), 60 deletions(-) create mode 100644 app/scripts/controller-init/messengers/multichain-balances-controller-messenger.test.ts create mode 100644 app/scripts/controller-init/messengers/multichain-balances-controller-messenger.ts create mode 100644 app/scripts/controller-init/messengers/multichain-transactions-controller-messenger.test.ts create mode 100644 app/scripts/controller-init/messengers/multichain-transactions-controller-messenger.ts create mode 100644 app/scripts/controller-init/multichain/multichain-balances-controller-init.test.ts create mode 100644 app/scripts/controller-init/multichain/multichain-balances-controller-init.ts create mode 100644 app/scripts/controller-init/multichain/multichain-transactions-controller-init.test.ts create mode 100644 app/scripts/controller-init/multichain/multichain-transactions-controller-init.ts diff --git a/app/scripts/controller-init/controller-list.ts b/app/scripts/controller-init/controller-list.ts index 8813acfdd69d..b2e23cc038c5 100644 --- a/app/scripts/controller-init/controller-list.ts +++ b/app/scripts/controller-init/controller-list.ts @@ -11,6 +11,8 @@ import SmartTransactionsController from '@metamask/smart-transactions-controller import { TransactionController } from '@metamask/transaction-controller'; import { TransactionUpdateController } from '@metamask-institutional/transaction-update'; import { AccountsController } from '@metamask/accounts-controller'; +import { MultichainBalancesController } from '@metamask/assets-controllers'; +import { MultichainTransactionsController } from '@metamask/multichain-transactions-controller'; import { CronjobController, ExecutionService, @@ -44,6 +46,8 @@ export type Controller = > | PPOMController | PreferencesController + | MultichainBalancesController + | MultichainTransactionsController | RateLimitController | SmartTransactionsController | SnapController @@ -72,6 +76,8 @@ export type ControllerFlatState = AccountsController['state'] & >['state'] & PPOMController['state'] & PreferencesController['state'] & + MultichainBalancesController['state'] & + MultichainTransactionsController['state'] & SmartTransactionsController['state'] & SnapController['state'] & SnapInsightsController['state'] & diff --git a/app/scripts/controller-init/messengers/index.ts b/app/scripts/controller-init/messengers/index.ts index 573a9a56149a..f43d0336cdd4 100644 --- a/app/scripts/controller-init/messengers/index.ts +++ b/app/scripts/controller-init/messengers/index.ts @@ -17,6 +17,14 @@ import { getTransactionControllerMessenger, getTransactionControllerInitMessenger, } from './transaction-controller-messenger'; +import { + getMultichainBalancesControllerMessenger, + getMultichainBalancesControllerInitMessenger, +} from './multichain-balances-controller-messenger'; +import { + getMultichainTransactionsControllerMessenger, + getMultichainTransactionsControllerInitMessenger, +} from './multichain-transactions-controller-messenger'; export const CONTROLLER_MESSENGERS = { CronjobController: { @@ -50,4 +58,12 @@ export const CONTROLLER_MESSENGERS = { getMessenger: getTransactionControllerMessenger, getInitMessenger: getTransactionControllerInitMessenger, }, + MultichainBalancesController: { + getMessenger: getMultichainBalancesControllerMessenger, + getInitMessenger: getMultichainBalancesControllerInitMessenger, + }, + MultichainTransactionsController: { + getMessenger: getMultichainTransactionsControllerMessenger, + getInitMessenger: getMultichainTransactionsControllerInitMessenger, + }, } as const; diff --git a/app/scripts/controller-init/messengers/multichain-balances-controller-messenger.test.ts b/app/scripts/controller-init/messengers/multichain-balances-controller-messenger.test.ts new file mode 100644 index 000000000000..001613b7e443 --- /dev/null +++ b/app/scripts/controller-init/messengers/multichain-balances-controller-messenger.test.ts @@ -0,0 +1,29 @@ +import { Messenger, RestrictedMessenger } from '@metamask/base-controller'; +import { + getMultichainBalancesControllerMessenger, + getMultichainBalancesControllerInitMessenger, +} from './multichain-balances-controller-messenger'; + +describe('getMultichainBalancesControllerMessenger', () => { + it('returns a restricted messenger', () => { + const messenger = new Messenger(); + const multichainBalancesControllerMessenger = + getMultichainBalancesControllerMessenger(messenger); + + expect(multichainBalancesControllerMessenger).toBeInstanceOf( + RestrictedMessenger, + ); + }); +}); + +describe('getMultichainBalancesControllerInitMessenger', () => { + it('returns a restricted messenger', () => { + const messenger = new Messenger(); + const multichainBalancesControllerInitMessenger = + getMultichainBalancesControllerInitMessenger(messenger); + + expect(multichainBalancesControllerInitMessenger).toBeInstanceOf( + RestrictedMessenger, + ); + }); +}); diff --git a/app/scripts/controller-init/messengers/multichain-balances-controller-messenger.ts b/app/scripts/controller-init/messengers/multichain-balances-controller-messenger.ts new file mode 100644 index 000000000000..836ea8d48b36 --- /dev/null +++ b/app/scripts/controller-init/messengers/multichain-balances-controller-messenger.ts @@ -0,0 +1,57 @@ +import { Messenger } from '@metamask/base-controller'; +import { + AccountsControllerAccountAddedEvent, + AccountsControllerAccountRemovedEvent, + AccountsControllerListMultichainAccountsAction, + AccountsControllerAccountBalancesUpdatesEvent, +} from '@metamask/accounts-controller'; +import { HandleSnapRequest } from '@metamask/snaps-controllers'; +import { + MultichainAssetsControllerGetStateAction, + MultichainAssetsControllerStateChangeEvent, + MultichainBalancesControllerMessenger, +} from '@metamask/assets-controllers'; + +type MessengerEvents = + | AccountsControllerAccountAddedEvent + | AccountsControllerAccountRemovedEvent + | AccountsControllerAccountBalancesUpdatesEvent + | MultichainAssetsControllerStateChangeEvent; + +type MessengerActions = + | AccountsControllerListMultichainAccountsAction + | HandleSnapRequest + | MultichainAssetsControllerGetStateAction; + +export type MultichainBalancesControllerInitMessenger = ReturnType< + typeof getMultichainBalancesControllerInitMessenger +>; + +export function getMultichainBalancesControllerMessenger( + messenger: Messenger, +): MultichainBalancesControllerMessenger { + return messenger.getRestricted({ + name: 'MultichainBalancesController', + allowedEvents: [ + 'AccountsController:accountAdded', + 'AccountsController:accountRemoved', + 'AccountsController:accountBalancesUpdated', + 'MultichainAssetsController:stateChange', + ], + allowedActions: [ + 'AccountsController:listMultichainAccounts', + 'SnapController:handleRequest', + 'MultichainAssetsController:getState', + ], + }) as unknown as MultichainBalancesControllerMessenger; +} + +export function getMultichainBalancesControllerInitMessenger( + messenger: Messenger, +) { + return messenger.getRestricted({ + name: 'MultichainBalancesControllerInit', + allowedEvents: [], + allowedActions: [], + }); +} diff --git a/app/scripts/controller-init/messengers/multichain-transactions-controller-messenger.test.ts b/app/scripts/controller-init/messengers/multichain-transactions-controller-messenger.test.ts new file mode 100644 index 000000000000..afe2681f6197 --- /dev/null +++ b/app/scripts/controller-init/messengers/multichain-transactions-controller-messenger.test.ts @@ -0,0 +1,29 @@ +import { Messenger, RestrictedMessenger } from '@metamask/base-controller'; +import { + getMultichainTransactionsControllerMessenger, + getMultichainTransactionsControllerInitMessenger, +} from './multichain-transactions-controller-messenger'; + +describe('getMultichainTransactionsControllerMessenger', () => { + it('returns a restricted messenger', () => { + const messenger = new Messenger(); + const multichainTransactionsControllerMessenger = + getMultichainTransactionsControllerMessenger(messenger); + + expect(multichainTransactionsControllerMessenger).toBeInstanceOf( + RestrictedMessenger, + ); + }); +}); + +describe('getMultichainTransactionsControllerInitMessenger', () => { + it('returns a restricted messenger', () => { + const messenger = new Messenger(); + const multichainTransactionsControllerInitMessenger = + getMultichainTransactionsControllerInitMessenger(messenger); + + expect(multichainTransactionsControllerInitMessenger).toBeInstanceOf( + RestrictedMessenger, + ); + }); +}); diff --git a/app/scripts/controller-init/messengers/multichain-transactions-controller-messenger.ts b/app/scripts/controller-init/messengers/multichain-transactions-controller-messenger.ts new file mode 100644 index 000000000000..d6d0c0d2a48e --- /dev/null +++ b/app/scripts/controller-init/messengers/multichain-transactions-controller-messenger.ts @@ -0,0 +1,48 @@ +import { Messenger } from '@metamask/base-controller'; +import { + AccountsControllerAccountAddedEvent, + AccountsControllerAccountRemovedEvent, + AccountsControllerListMultichainAccountsAction, + AccountsControllerAccountTransactionsUpdatedEvent, +} from '@metamask/accounts-controller'; +import { HandleSnapRequest } from '@metamask/snaps-controllers'; + +type MessengerEvents = + | AccountsControllerAccountAddedEvent + | AccountsControllerAccountRemovedEvent + | AccountsControllerAccountTransactionsUpdatedEvent; + +type MessengerActions = + | AccountsControllerListMultichainAccountsAction + | HandleSnapRequest; + +export type MultichainTransactionsControllerInitMessenger = ReturnType< + typeof getMultichainTransactionsControllerInitMessenger +>; + +export function getMultichainTransactionsControllerMessenger( + messenger: Messenger, +) { + return messenger.getRestricted({ + name: 'MultichainTransactionsController', + allowedEvents: [ + 'AccountsController:accountAdded', + 'AccountsController:accountRemoved', + 'AccountsController:accountTransactionsUpdated', + ], + allowedActions: [ + 'AccountsController:listMultichainAccounts', + 'SnapController:handleRequest', + ], + }); +} + +export function getMultichainTransactionsControllerInitMessenger( + messenger: Messenger, +) { + return messenger.getRestricted({ + name: 'MultichainTransactionsControllerInit', + allowedEvents: [], + allowedActions: [], + }); +} diff --git a/app/scripts/controller-init/multichain/multichain-balances-controller-init.test.ts b/app/scripts/controller-init/multichain/multichain-balances-controller-init.test.ts new file mode 100644 index 000000000000..a593f7628035 --- /dev/null +++ b/app/scripts/controller-init/multichain/multichain-balances-controller-init.test.ts @@ -0,0 +1,62 @@ +import { + MultichainBalancesController, + MultichainBalancesControllerMessenger, +} from '@metamask/assets-controllers'; +import { Messenger } from '@metamask/base-controller'; +import { buildControllerInitRequestMock } from '../test/utils'; +import { ControllerInitRequest } from '../types'; +import { + getMultichainBalancesControllerInitMessenger, + getMultichainBalancesControllerMessenger, + MultichainBalancesControllerInitMessenger, +} from '../messengers/multichain-balances-controller-messenger'; +import { MultichainBalancesControllerInit } from './multichain-balances-controller-init'; + +jest.mock('@metamask/assets-controllers'); + +function buildInitRequestMock(): jest.Mocked< + ControllerInitRequest< + // @ts-expect-error TODO: figure out why there's a mismatch + MultichainBalancesControllerMessenger, + MultichainBalancesControllerInitMessenger + > +> { + const baseControllerMessenger = new Messenger(); + + return { + ...buildControllerInitRequestMock(), + controllerMessenger: getMultichainBalancesControllerMessenger( + baseControllerMessenger, + ), + initMessenger: getMultichainBalancesControllerInitMessenger( + baseControllerMessenger, + ), + }; +} + +describe('MultichainBalances Controller Init', () => { + const multichainBalancesControllerClassMock = jest.mocked( + MultichainBalancesController, + ); + + beforeEach(() => { + jest.resetAllMocks(); + }); + + it('returns controller instance', () => { + const requestMock = buildInitRequestMock(); + expect( + MultichainBalancesControllerInit(requestMock).controller, + ).toBeInstanceOf(MultichainBalancesController); + }); + + it('initializes with correct messenger and state', () => { + const requestMock = buildInitRequestMock(); + MultichainBalancesControllerInit(requestMock); + + expect(multichainBalancesControllerClassMock).toHaveBeenCalledWith({ + messenger: requestMock.controllerMessenger, + state: requestMock.persistedState.MultichainBalancesController, + }); + }); +}); diff --git a/app/scripts/controller-init/multichain/multichain-balances-controller-init.ts b/app/scripts/controller-init/multichain/multichain-balances-controller-init.ts new file mode 100644 index 000000000000..9bab8037f8e5 --- /dev/null +++ b/app/scripts/controller-init/multichain/multichain-balances-controller-init.ts @@ -0,0 +1,22 @@ +import { + MultichainBalancesController, + MultichainBalancesControllerMessenger, +} from '@metamask/assets-controllers'; +import { ControllerInitFunction } from '../types'; +import { MultichainBalancesControllerInitMessenger } from '../messengers/multichain-balances-controller-messenger'; + +export const MultichainBalancesControllerInit: ControllerInitFunction< + MultichainBalancesController, + // @ts-expect-error TODO: figure out why there's a mismatch + MultichainBalancesControllerMessenger, + MultichainBalancesControllerInitMessenger +> = (request) => { + const { controllerMessenger, persistedState } = request; + + const controller = new MultichainBalancesController({ + messenger: controllerMessenger, + state: persistedState.MultichainBalancesController, + }); + + return { controller }; +}; diff --git a/app/scripts/controller-init/multichain/multichain-transactions-controller-init.test.ts b/app/scripts/controller-init/multichain/multichain-transactions-controller-init.test.ts new file mode 100644 index 000000000000..b67051a1d955 --- /dev/null +++ b/app/scripts/controller-init/multichain/multichain-transactions-controller-init.test.ts @@ -0,0 +1,62 @@ +import { MultichainTransactionsController } from '@metamask/multichain-transactions-controller'; +import { Messenger } from '@metamask/base-controller'; +import { buildControllerInitRequestMock } from '../test/utils'; +import { ControllerInitRequest } from '../types'; +import { + getMultichainTransactionsControllerInitMessenger, + getMultichainTransactionsControllerMessenger, + MultichainTransactionsControllerInitMessenger, +} from '../messengers/multichain-transactions-controller-messenger'; +import { MultichainTransactionsControllerInit } from './multichain-transactions-controller-init'; + +type MultichainTransactionsControllerMessenger = ConstructorParameters< + typeof MultichainTransactionsController +>[0]['messenger']; + +jest.mock('@metamask/multichain-transactions-controller'); + +function buildInitRequestMock(): jest.Mocked< + ControllerInitRequest< + MultichainTransactionsControllerMessenger, + MultichainTransactionsControllerInitMessenger + > +> { + const baseControllerMessenger = new Messenger(); + + return { + ...buildControllerInitRequestMock(), + controllerMessenger: getMultichainTransactionsControllerMessenger( + baseControllerMessenger, + ), + initMessenger: getMultichainTransactionsControllerInitMessenger( + baseControllerMessenger, + ), + }; +} + +describe('MultichainTransactions Controller Init', () => { + const multichainTransactionsControllerClassMock = jest.mocked( + MultichainTransactionsController, + ); + + beforeEach(() => { + jest.resetAllMocks(); + }); + + it('returns controller instance', () => { + const requestMock = buildInitRequestMock(); + expect( + MultichainTransactionsControllerInit(requestMock).controller, + ).toBeInstanceOf(MultichainTransactionsController); + }); + + it('initializes with correct messenger and state', () => { + const requestMock = buildInitRequestMock(); + MultichainTransactionsControllerInit(requestMock); + + expect(multichainTransactionsControllerClassMock).toHaveBeenCalledWith({ + messenger: requestMock.controllerMessenger, + state: requestMock.persistedState.MultichainTransactionsController, + }); + }); +}); diff --git a/app/scripts/controller-init/multichain/multichain-transactions-controller-init.ts b/app/scripts/controller-init/multichain/multichain-transactions-controller-init.ts new file mode 100644 index 000000000000..d20f9cf6d06f --- /dev/null +++ b/app/scripts/controller-init/multichain/multichain-transactions-controller-init.ts @@ -0,0 +1,26 @@ +import { MultichainTransactionsController } from '@metamask/multichain-transactions-controller'; +import { ControllerInitFunction } from '../types'; +import { MultichainTransactionsControllerInitMessenger } from '../messengers/multichain-transactions-controller-messenger'; + +// We are inferring the messenger type from the controllers constructor +// because the messenger is not exported from the package. +type MultichainTransactionsControllerMessenger = ConstructorParameters< + typeof MultichainTransactionsController +>[0]['messenger']; + +export const MultichainTransactionsControllerInit: ControllerInitFunction< + MultichainTransactionsController, + MultichainTransactionsControllerMessenger, + MultichainTransactionsControllerInitMessenger +> = (request) => { + const { controllerMessenger, persistedState } = request; + + const controller = new MultichainTransactionsController({ + messenger: controllerMessenger, + state: persistedState.MultichainTransactionsController, + }); + + return { + controller, + }; +}; diff --git a/app/scripts/controller-init/utils.ts b/app/scripts/controller-init/utils.ts index 2bbaf7abf4ea..0481a7257d3a 100644 --- a/app/scripts/controller-init/utils.ts +++ b/app/scripts/controller-init/utils.ts @@ -36,7 +36,11 @@ type ControllerMessengerCallback = ( BaseControllerMessenger: BaseControllerMessenger, ) => BaseRestrictedControllerMessenger; -type ControllersToInitialize = 'PPOMController' | 'TransactionController'; +type ControllersToInitialize = + | 'PPOMController' + | 'TransactionController' + | 'MultichainBalancesController' + | 'MultichainTransactionsController'; type InitFunction = ControllerInitFunction< @@ -101,7 +105,6 @@ export function initControllers({ const messengerCallbacks = CONTROLLER_MESSENGERS[controllerName]; const controllerMessengerCallback = - // @ts-expect-error TODO: Resolve mismatch between base-controller versions. messengerCallbacks?.getMessenger as ControllerMessengerCallback; const initMessengerCallback = @@ -124,7 +127,6 @@ export function initControllers({ // Instead of suppressing all type errors, we'll be specific about the controllerMessenger mismatch const result = initFunction({ ...finalInitRequest, - // @ts-expect-error TODO: Resolve mismatch between base-controller versions. controllerMessenger: finalInitRequest.controllerMessenger, }); @@ -144,8 +146,9 @@ export function initControllers({ const memStateKey = memStateKeyRaw === null ? undefined : memStateKeyRaw ?? controllerName; - partialControllersByName[controllerName] = controller as Controller & - undefined; + (partialControllersByName as Record)[ + controllerName + ] = controller; controllerApi = { ...controllerApi, diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 20b798177fc9..de1b246a3896 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -13,7 +13,6 @@ import { RatesController, fetchMultiExchangeRate, TokenBalancesController, - MultichainBalancesController, MultichainAssetsController, } from '@metamask/assets-controllers'; import { JsonRpcEngine } from '@metamask/json-rpc-engine'; @@ -161,9 +160,6 @@ import { setEthAccounts, addPermittedEthChainId, } from '@metamask/multichain'; -///: BEGIN:ONLY_INCLUDE_IF(build-flask) -import { MultichainTransactionsController } from '@metamask/multichain-transactions-controller'; -///: END:ONLY_INCLUDE_IF import { isProduction } from '../../shared/modules/environment'; import { methodsRequiringNetworkSwitch, @@ -363,6 +359,10 @@ import { handleBridgeTransactionFailed, handleTransactionFailedTypeBridge, } from './lib/bridge-status/metrics'; +///: BEGIN:ONLY_INCLUDE_IF(build-flask) +import { MultichainBalancesControllerInit } from './controller-init/multichain/multichain-balances-controller-init'; +import { MultichainTransactionsControllerInit } from './controller-init/multichain/multichain-transactions-controller-init'; +///: END:ONLY_INCLUDE_IF import { TransactionControllerInit } from './controller-init/confirmations/transaction-controller-init'; import { PPOMControllerInit } from './controller-init/confirmations/ppom-controller-init'; import { initControllers } from './controller-init/utils'; @@ -980,28 +980,6 @@ export default class MetamaskController extends EventEmitter { state: initState.AnnouncementController, }); - ///: BEGIN:ONLY_INCLUDE_IF(build-flask) - const multichainTransactionsControllerMessenger = - this.controllerMessenger.getRestricted({ - name: 'MultichainTransactionsController', - allowedEvents: [ - 'AccountsController:accountAdded', - 'AccountsController:accountRemoved', - 'AccountsController:accountTransactionsUpdated', - ], - allowedActions: [ - 'AccountsController:listMultichainAccounts', - 'SnapController:handleRequest', - ], - }); - - this.multichainTransactionsController = - new MultichainTransactionsController({ - messenger: multichainTransactionsControllerMessenger, - state: initState.MultichainTransactionsController, - }); - ///: END:ONLY_INCLUDE_IF - const networkOrderMessenger = this.controllerMessenger.getRestricted({ name: 'NetworkOrderController', allowedEvents: ['NetworkController:stateChange'], @@ -1019,25 +997,6 @@ export default class MetamaskController extends EventEmitter { state: initState.AccountOrderController, }); - const multichainBalancesControllerMessenger = - this.controllerMessenger.getRestricted({ - name: 'MultichainBalancesController', - allowedEvents: [ - 'AccountsController:accountAdded', - 'AccountsController:accountRemoved', - 'AccountsController:accountBalancesUpdated', - ], - allowedActions: [ - 'AccountsController:listMultichainAccounts', - 'SnapController:handleRequest', - ], - }); - - this.multichainBalancesController = new MultichainBalancesController({ - messenger: multichainBalancesControllerMessenger, - state: initState.MultichainBalancesController, - }); - const multichainRatesControllerMessenger = this.controllerMessenger.getRestricted({ name: 'RatesController', @@ -2112,6 +2071,10 @@ export default class MetamaskController extends EventEmitter { CronjobController: CronjobControllerInit, PPOMController: PPOMControllerInit, TransactionController: TransactionControllerInit, + ///: BEGIN:ONLY_INCLUDE_IF(build-flask) + MultichainBalancesController: MultichainBalancesControllerInit, + MultichainTransactionsController: MultichainTransactionsControllerInit, + ///: END:ONLY_INCLUDE_IF }; const { @@ -2139,6 +2102,12 @@ export default class MetamaskController extends EventEmitter { this.snapsRegistry = controllersByName.SnapsRegistry; this.ppomController = controllersByName.PPOMController; this.txController = controllersByName.TransactionController; + ///: BEGIN:ONLY_INCLUDE_IF(build-flask) + this.multichainBalancesController = + controllersByName.MultichainBalancesController; + this.multichainTransactionsController = + controllersByName.MultichainTransactionsController; + ///: END:ONLY_INCLUDE_IF this.controllerMessenger.subscribe( 'TransactionController:transactionStatusUpdated', @@ -2260,9 +2229,9 @@ export default class MetamaskController extends EventEmitter { AccountsController: this.accountsController, AppStateController: this.appStateController, AppMetadataController: this.appMetadataController, - MultichainBalancesController: this.multichainBalancesController, MultichainAssetsController: this.multichainAssetsController, ///: BEGIN:ONLY_INCLUDE_IF(build-flask) + MultichainBalancesController: this.multichainBalancesController, MultichainTransactionsController: this.multichainTransactionsController, ///: END:ONLY_INCLUDE_IF KeyringController: this.keyringController, @@ -2314,9 +2283,9 @@ export default class MetamaskController extends EventEmitter { AccountsController: this.accountsController, AppStateController: this.appStateController, AppMetadataController: this.appMetadataController, - MultichainBalancesController: this.multichainBalancesController, MultichainAssetsController: this.multichainAssetsController, ///: BEGIN:ONLY_INCLUDE_IF(build-flask) + MultichainBalancesController: this.multichainBalancesController, MultichainTransactionsController: this.multichainTransactionsController, ///: END:ONLY_INCLUDE_IF NetworkController: this.networkController, @@ -4117,10 +4086,11 @@ export default class MetamaskController extends EventEmitter { ), setName: this.nameController.setName.bind(this.nameController), + ///: BEGIN:ONLY_INCLUDE_IF(build-flask) // MultichainBalancesController multichainUpdateBalance: (accountId) => this.multichainBalancesController.updateBalance(accountId), - + ///: END:ONLY_INCLUDE_IF // Transaction Decode decodeTransactionData: (request) => decodeTransactionData({ diff --git a/test/e2e/tests/metrics/errors.spec.js b/test/e2e/tests/metrics/errors.spec.js index a9ca8cfd7ac3..a3ea386f06b6 100644 --- a/test/e2e/tests/metrics/errors.spec.js +++ b/test/e2e/tests/metrics/errors.spec.js @@ -889,6 +889,7 @@ describe('Sentry errors', function () { showConfirmationAdvancedDetails: true, privacyMode: false, }, + balances: false, smartTransactionsState: { fees: { approvalTxFees: true, // Initialized as undefined diff --git a/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-background-state.json b/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-background-state.json index cddc3c404309..b39c03363257 100644 --- a/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-background-state.json +++ b/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-background-state.json @@ -147,7 +147,6 @@ "accountsAssets": "object", "assetsMetadata": "object" }, - "MultichainBalancesController": { "balances": "object" }, "MultichainRatesController": { "fiatCurrency": "usd", "rates": { diff --git a/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-ui-state.json b/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-ui-state.json index bad4742146ed..51cb7ad56392 100644 --- a/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-ui-state.json +++ b/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-ui-state.json @@ -157,7 +157,8 @@ "previousAppVersion": "", "previousMigrationVersion": 0, "currentMigrationVersion": "number", - "balances": "object", + "accountsAssets": "object", + "assetsMetadata": "object", "selectedNetworkClientId": "string", "networksMetadata": { "networkConfigurationId": { @@ -250,9 +251,6 @@ "ignoredNfts": "object", "domains": "object", "logs": "object", - "methodData": "object", - "lastFetchedBlockNumbers": "object", - "submitHistory": "object", "fiatCurrency": "usd", "rates": { "btc": { "conversionDate": 0, "conversionRate": 0 }, @@ -292,8 +290,6 @@ "cacheTimestamp": "number", "accounts": "object", "accountsByChainId": "object", - "accountsAssets": "object", - "assetsMetadata": "object", "marketData": "object", "unapprovedDecryptMsgs": "object", "unapprovedDecryptMsgCount": 0, @@ -355,6 +351,9 @@ "pendingApprovalCount": "number", "approvalFlows": "object", "storageMetadata": {}, + "methodData": "object", + "lastFetchedBlockNumbers": "object", + "submitHistory": "object", "encryptionKey": "string", "encryptionSalt": "string" }, From 901ce6aad328c309b98524faa9231c25e6cb4e4b Mon Sep 17 00:00:00 2001 From: Mathieu Artu Date: Thu, 13 Feb 2025 11:51:57 +0100 Subject: [PATCH 08/24] feat: disable metametrics when disabling basic functionality (#30210) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## **Description** This PR disables MetaMetrics when turning basic functionality off. [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/30210?quickstart=1) ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/IDENTITY-18 ## **Manual testing steps** 1. Create a new wallet 2. Disable basic functionality in the onboarding settings 3. Finish creating your wallet 4. Go to the privacy settings and verify that both MetaMetrics are off and disabled 5. Turn basic functionality back on 6. Enable MetaMetrics and marketing collection 7. Disable basic functionality 8. Verify that both MetaMetrics toggles are off and disabled 9. Enable basic functionality 10. Verify that both MetaMetrics toggles are not disabled but still off ## **Screenshots/Recordings** ### **Before** ### **After** ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [x] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [x] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. --- .../basic-configuration-modal.test.tsx | 220 ++++++++++++++++++ .../basic-configuration-modal.tsx | 13 +- .../__snapshots__/security-tab.test.js.snap | 9 +- .../metametrics-toggle.test.tsx | 160 +++++++------ .../metametrics-toggle/metametrics-toggle.tsx | 18 +- .../security-tab/security-tab.component.js | 2 + 6 files changed, 339 insertions(+), 83 deletions(-) create mode 100644 ui/components/app/basic-configuration-modal/basic-configuration-modal.test.tsx diff --git a/ui/components/app/basic-configuration-modal/basic-configuration-modal.test.tsx b/ui/components/app/basic-configuration-modal/basic-configuration-modal.test.tsx new file mode 100644 index 000000000000..a87089f22bb6 --- /dev/null +++ b/ui/components/app/basic-configuration-modal/basic-configuration-modal.test.tsx @@ -0,0 +1,220 @@ +import * as React from 'react'; +import { fireEvent, waitFor } from '@testing-library/react'; +import { useLocation } from 'react-router-dom'; +import configureStore from '../../../store/store'; +import { renderWithProvider } from '../../../../test/lib/render-helpers'; +import * as Actions from '../../../store/actions'; +import { + hideBasicFunctionalityModal, + onboardingToggleBasicFunctionalityOff, +} from '../../../ducks/app/app'; +import { ONBOARDING_PRIVACY_SETTINGS_ROUTE } from '../../../helpers/constants/routes'; +import { BasicConfigurationModal } from './basic-configuration-modal'; + +jest.mock('../../../store/actions', () => ({ + setDataCollectionForMarketing: jest.fn(), + setParticipateInMetaMetrics: jest.fn(), + toggleExternalServices: jest.fn(), +})); + +jest.mock('../../../ducks/app/app', () => ({ + hideBasicFunctionalityModal: jest.fn(), + onboardingToggleBasicFunctionalityOff: jest.fn(), +})); + +const mockDispatch = jest.fn(); + +jest.mock('react-redux', () => { + const actual = jest.requireActual('react-redux'); + return { + ...actual, + useDispatch: () => mockDispatch, + }; +}); + +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useLocation: jest.fn(), +})); + +type StateOverrides = { + metamask: { + useExternalServices: T; + }; +}; + +type ArrangeMocksParams = { + isOnboarding?: boolean; + stateOverrides?: StateOverrides; +}; + +type ArrangeMocksReturn = { + toggleBasicFunctionalityButton: HTMLElement; + cancelButton: HTMLElement; + agreementCheckbox: T extends true ? HTMLElement : null; +}; + +const arrangeMocks = ({ + isOnboarding = false, + stateOverrides, +}: ArrangeMocksParams = {}): ArrangeMocksReturn => { + jest.clearAllMocks(); + + (useLocation as jest.Mock).mockReturnValue({ + pathname: isOnboarding + ? ONBOARDING_PRIVACY_SETTINGS_ROUTE + : '/any-other-path', + }); + + const store = configureStore({ + ...stateOverrides, + }); + const { getByTestId, getByTitle } = renderWithProvider( + , + store, + ); + + const agreementCheckbox = stateOverrides?.metamask.useExternalServices + ? getByTitle('basic-configuration-checkbox') + : null; + const toggleBasicFunctionalityButton = getByTestId( + 'basic-configuration-modal-toggle-button', + ); + const cancelButton = getByTestId('basic-configuration-modal-cancel-button'); + + return { + toggleBasicFunctionalityButton, + cancelButton, + agreementCheckbox, + } as ArrangeMocksReturn; +}; + +describe('BasicConfigurationModal', () => { + it('should call hideBasicFunctionalityModal when the cancel button is clicked', () => { + const { cancelButton } = arrangeMocks(); + + expect(cancelButton).toBeEnabled(); + + fireEvent.click(cancelButton); + + expect(hideBasicFunctionalityModal).toHaveBeenCalledTimes(1); + }); + + describe('during onboarding', () => { + it('should render the basic configuration modal', async () => { + const { + agreementCheckbox, + cancelButton, + toggleBasicFunctionalityButton, + } = arrangeMocks({ + isOnboarding: true, + stateOverrides: { + metamask: { + useExternalServices: true, + }, + }, + }); + + expect(agreementCheckbox).toBeInTheDocument(); + expect(cancelButton).toBeInTheDocument(); + expect(toggleBasicFunctionalityButton).toBeInTheDocument(); + }); + + it('should call appropriate actions when the turn off button is clicked', () => { + const { agreementCheckbox, toggleBasicFunctionalityButton } = + arrangeMocks({ + isOnboarding: true, + stateOverrides: { + metamask: { + useExternalServices: true, + }, + }, + }); + + fireEvent.click(agreementCheckbox, { + target: { checked: true }, + }); + + expect(toggleBasicFunctionalityButton).toBeEnabled(); + + fireEvent.click(toggleBasicFunctionalityButton); + + expect(hideBasicFunctionalityModal).toHaveBeenCalledTimes(1); + expect(onboardingToggleBasicFunctionalityOff).toHaveBeenCalledTimes(1); + expect(Actions.setParticipateInMetaMetrics).toHaveBeenCalledTimes(1); + expect(Actions.setParticipateInMetaMetrics).toHaveBeenCalledWith(false); + expect(Actions.setDataCollectionForMarketing).toHaveBeenCalledTimes(1); + expect(Actions.setDataCollectionForMarketing).toHaveBeenCalledWith(false); + }); + }); + + describe('outside onboarding', () => { + it('should render the basic configuration modal', async () => { + const { + agreementCheckbox, + cancelButton, + toggleBasicFunctionalityButton, + } = arrangeMocks({ + isOnboarding: false, + stateOverrides: { + metamask: { + useExternalServices: true, + }, + }, + }); + + expect(agreementCheckbox).toBeInTheDocument(); + expect(cancelButton).toBeInTheDocument(); + expect(toggleBasicFunctionalityButton).toBeInTheDocument(); + }); + + it('should call appropriate actions when the turn off button is clicked', () => { + const { agreementCheckbox, toggleBasicFunctionalityButton } = + arrangeMocks({ + stateOverrides: { + metamask: { + useExternalServices: true, + }, + }, + }); + + fireEvent.click(agreementCheckbox, { + target: { checked: true }, + }); + + waitFor(() => { + expect(toggleBasicFunctionalityButton).toBeEnabled(); + }); + + fireEvent.click(toggleBasicFunctionalityButton); + + expect(hideBasicFunctionalityModal).toHaveBeenCalledTimes(1); + expect(Actions.setParticipateInMetaMetrics).toHaveBeenCalledTimes(1); + expect(Actions.setParticipateInMetaMetrics).toHaveBeenCalledWith(false); + expect(Actions.setDataCollectionForMarketing).toHaveBeenCalledTimes(1); + expect(Actions.setDataCollectionForMarketing).toHaveBeenCalledWith(false); + expect(Actions.toggleExternalServices).toHaveBeenCalledTimes(1); + expect(Actions.toggleExternalServices).toHaveBeenCalledWith(false); + }); + + it('should call the appropriate actions when the turn on button is clicked', () => { + const { toggleBasicFunctionalityButton } = arrangeMocks({ + stateOverrides: { + metamask: { + useExternalServices: false, + }, + }, + }); + + expect(toggleBasicFunctionalityButton).toBeEnabled(); + + fireEvent.click(toggleBasicFunctionalityButton); + + expect(hideBasicFunctionalityModal).toHaveBeenCalledTimes(1); + expect(Actions.setParticipateInMetaMetrics).toHaveBeenCalledTimes(0); + expect(Actions.setDataCollectionForMarketing).toHaveBeenCalledTimes(0); + expect(Actions.toggleExternalServices).toHaveBeenCalledTimes(1); + expect(Actions.toggleExternalServices).toHaveBeenCalledWith(true); + }); + }); +}); diff --git a/ui/components/app/basic-configuration-modal/basic-configuration-modal.tsx b/ui/components/app/basic-configuration-modal/basic-configuration-modal.tsx index 52faaf0384af..652e333ef8aa 100644 --- a/ui/components/app/basic-configuration-modal/basic-configuration-modal.tsx +++ b/ui/components/app/basic-configuration-modal/basic-configuration-modal.tsx @@ -12,7 +12,11 @@ import { FontWeight, } from '../../../helpers/constants/design-system'; import { useI18nContext } from '../../../hooks/useI18nContext'; -import { toggleExternalServices } from '../../../store/actions'; +import { + setDataCollectionForMarketing, + setParticipateInMetaMetrics, + toggleExternalServices, +} from '../../../store/actions'; import { ModalOverlay, ModalContent, @@ -135,6 +139,7 @@ export function BasicConfigurationModal() { size={ButtonSize.Lg} width={BlockSize.Half} variant={ButtonVariant.Secondary} + data-testid="basic-configuration-modal-cancel-button" onClick={closeModal} > {t('cancel')} @@ -144,6 +149,7 @@ export function BasicConfigurationModal() { disabled={!hasAgreed && isExternalServicesEnabled} width={BlockSize.Half} variant={ButtonVariant.Primary} + data-testid="basic-configuration-modal-toggle-button" onClick={() => { const event = onboardingFlow ? { @@ -172,6 +178,11 @@ export function BasicConfigurationModal() { trackEvent(event); + if (isExternalServicesEnabled || onboardingFlow) { + dispatch(setParticipateInMetaMetrics(false)); + dispatch(setDataCollectionForMarketing(false)); + } + if (onboardingFlow) { dispatch(hideBasicFunctionalityModal()); dispatch(onboardingToggleBasicFunctionalityOff()); diff --git a/ui/pages/settings/security-tab/__snapshots__/security-tab.test.js.snap b/ui/pages/settings/security-tab/__snapshots__/security-tab.test.js.snap index 0eea2598ccb9..310fd4d9c0f2 100644 --- a/ui/pages/settings/security-tab/__snapshots__/security-tab.test.js.snap +++ b/ui/pages/settings/security-tab/__snapshots__/security-tab.test.js.snap @@ -1424,18 +1424,16 @@ exports[`Security Tab should match snapshot 1`] = ` >
Participate in MetaMetrics
Participate in MetaMetrics to help us make MetaMask better
@@ -1445,7 +1443,7 @@ exports[`Security Tab should match snapshot 1`] = ` data-testid="participate-in-meta-metrics-toggle" >