diff --git a/CHANGELOG.md b/CHANGELOG.md index 639d6fb58a2..3ab51e57c83 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,33 @@ ## Current Main Branch +## 6.5.0 - May 4, 2023 +- [#5743](https://github.com/MetaMask/metamask-mobile/pull/5743): [FEATURE] On-ramp: Add buy-crypto deeplink +- [#6201](https://github.com/MetaMask/metamask-mobile/pull/6201): [FIX] [SDK] Missing redirect breaking backward compatibility +- [#6232](https://github.com/MetaMask/metamask-mobile/pull/6232): [FIX] bottom margin for detecting end of the page +- [#6166](https://github.com/MetaMask/metamask-mobile/pull/6166): [FEATURE] trigger walletconnect modal using approval controller +- [#6223](https://github.com/MetaMask/metamask-mobile/pull/6223): [IMPROVEMENT] Update to Node.js v16 +- [#6051](https://github.com/MetaMask/metamask-mobile/pull/6051): [FEATURE] Total balance and portfolio button changed +- [#6156](https://github.com/MetaMask/metamask-mobile/pull/6156): [IMPROVEMENT] On-ramp: Use dynamic list of networks +- [#6145](https://github.com/MetaMask/metamask-mobile/pull/6145): [IMPROVEMENT] Synced and optimized icons +- [#6138](https://github.com/MetaMask/metamask-mobile/pull/6138): [FEATURE] On-ramp: Add orderProcessor exponential backoff for orders +- [#6139](https://github.com/MetaMask/metamask-mobile/pull/6139): [FEATURE] On-ramp: Add same amount rendering as the order details to the order list +- [#6189](https://github.com/MetaMask/metamask-mobile/pull/6189): [FEATURE] On-ramp: Remove hiding the provider modal when quotes refresh +- [#6216](https://github.com/MetaMask/metamask-mobile/pull/6216): [IMPROVEMENT] account icon matches user's preferred identicon +- [#5956](https://github.com/MetaMask/metamask-mobile/pull/5956): [IMPROVEMENT] Show token symbol in verify contract details +- [#5458](https://github.com/MetaMask/metamask-mobile/pull/5458): [IMPROVEMENT] Support sepolia network +- [#6185](https://github.com/MetaMask/metamask-mobile/pull/6185): [FIX] remove pubnub package and associated sync with extension code +- [#6181](https://github.com/MetaMask/metamask-mobile/pull/6181): [IMPROVEMENT] Componentize Header Component +- [#6153](https://github.com/MetaMask/metamask-mobile/pull/6153): [IMPROVEMENT] On-ramp: Refactor order selector by id +- [#6044](https://github.com/MetaMask/metamask-mobile/pull/6044): [IMPROVEMENT] Componentize Badge and Badge Wrapper +- [#6180](https://github.com/MetaMask/metamask-mobile/pull/6180): [IMPROVEMENT] Componentized Overlay Component +- [#6173](https://github.com/MetaMask/metamask-mobile/pull/6173): [REFACTOR] Auto Lock section +- [#6174](https://github.com/MetaMask/metamask-mobile/pull/6174): [IMPROVEMENT] Update Tab bar styles +- [#6056](https://github.com/MetaMask/metamask-mobile/pull/6056): [IMPROVEMENT] Show Identicon for unknown token and if token icon is unknown +- [#6076](https://github.com/MetaMask/metamask-mobile/pull/6076): [BUGFIX] Fixes WalletConnect deep links (wc:// schema) not working properly +- [#6157](https://github.com/MetaMask/metamask-mobile/pull/6157): [REFACTOR] Change Password setting +- [#5718](https://github.com/MetaMask/metamask-mobile/pull/5718): [FIX] Nonce Too Low for Approve Transaction + ## 6.4.0 - Apr 20, 2023 - [#6144](https://github.com/MetaMask/metamask-mobile/pull/6144): [FEATURE] New Crowdin translations by Github Action - [#6143](https://github.com/MetaMask/metamask-mobile/pull/6143): [UPDATE] Crowdin token to use METAMASKBOT_CROWDIN_TOKEN diff --git a/README.md b/README.md index 389292fe0e8..b09b8937a92 100644 --- a/README.md +++ b/README.md @@ -217,7 +217,7 @@ For local testing, the wallet is created using the secret recovery phrase from t ##### iOS All tests live within the e2e/specs folder. -Prequisites for running tests: +Prerequisites for running tests: - Make sure to install `detox-cli` by referring to the instructions mentioned [here](https://wix.github.io/Detox/docs/introduction/getting-started/#detox-prerequisites). - Additionally, install `applesimutils` by following the guidelines provided [here](https://github.com/wix/AppleSimulatorUtils). - Before running any tests, it's recommended to refer to the `iOS section` above and check the latest simulator device specified under `Install the correct simulator`. @@ -246,7 +246,12 @@ If you have already built the application for Detox and want to run a specific t ```bash yarn test:e2e:ios:debug:single e2e/specs/TEST_NAME.spec.js ``` +To run tests associated with a certain tag, you can do so using the `--testNamePattern` flag. For example: +```bash +yarn test:e2e:ios:debug --testNamePattern="Smoke" +``` +This runs all tests that are tagged "Smoke" ##### Android All android tests live within the wdio/feature folder. @@ -286,7 +291,7 @@ To get a better understanding of the internal architecture of this app take a lo ### Storybook -We have begun documenting our components using storybook please read the [Documentation Guidelines](./storybook/DOCUMENTATION_GUIDELINES.md) to get up and running. +We have begun documenting our components using Storybook. Please read the [Documentation Guidelines](./storybook/DOCUMENTATION_GUIDELINES.md) to get up and running. ### Other Docs diff --git a/android/app/build.gradle b/android/app/build.gradle index 37c58900775..53af1d1fba4 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -159,8 +159,8 @@ android { applicationId "io.metamask" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 1100 - versionName "6.4.0" + versionCode 1104 + versionName "6.5.0" multiDexEnabled true testBuildType System.getProperty('testBuildType', 'debug') missingDimensionStrategy "minReactNative", "minReactNative46" diff --git a/app/component-library/components/Modals/ModalMandatory/ModalMandatory.tsx b/app/component-library/components/Modals/ModalMandatory/ModalMandatory.tsx index 3bfb445be03..a0ad536554e 100644 --- a/app/component-library/components/Modals/ModalMandatory/ModalMandatory.tsx +++ b/app/component-library/components/Modals/ModalMandatory/ModalMandatory.tsx @@ -234,7 +234,7 @@ const ModalMandatory = ({ route }: MandatoryModalProps) => { activeOpacity={1} {...generateTestId(Platform, TERMS_OF_USE_CHECKBOX_ICON_ID)} > - + {checkboxText} }, }); +const FieldType = { + Link: 'Link', + Text: 'Text', +}; /** * View that displays the information of a specific ERC-721 Token */ @@ -166,11 +172,10 @@ const CollectibleOverview = ({ }, [collectible.description]); const renderCollectibleInfoRow = useCallback( - (key, value, onPress) => { + ({ key, value, onPress, type }) => { if (!value) return null; - - if (value.toLowerCase().includes('javascript')) { - return null; + if (type === FieldType.Link) { + if (!isLinkSafe(value)) return null; } return ( @@ -203,42 +208,50 @@ const CollectibleOverview = ({ ); const renderCollectibleInfo = () => [ - renderCollectibleInfoRow( - strings('collectible.collectible_token_standard'), - collectible?.standard, - ), - renderCollectibleInfoRow( - strings('collectible.collectible_last_sold'), - collectible?.lastSale?.event_timestamp && + renderCollectibleInfoRow({ + key: strings('collectible.collectible_token_standard'), + value: collectible?.standard, + type: FieldType.Text, + }), + renderCollectibleInfoRow({ + key: strings('collectible.collectible_last_sold'), + value: + collectible?.lastSale?.event_timestamp && toLocaleDate( new Date(collectible?.lastSale?.event_timestamp), ).toString(), - ), - renderCollectibleInfoRow( - strings('collectible.collectible_last_price_sold'), - collectible?.lastSale?.total_price && + type: FieldType.Text, + }), + renderCollectibleInfoRow({ + key: strings('collectible.collectible_last_price_sold'), + value: + collectible?.lastSale?.total_price && `${renderFromWei(collectible?.lastSale?.total_price)} ETH`, - ), - renderCollectibleInfoRow( - strings('collectible.collectible_source'), - collectible?.imageOriginal, - () => openLink(collectible?.imageOriginal), - ), - renderCollectibleInfoRow( - strings('collectible.collectible_link'), - collectible?.externalLink, - () => openLink(collectible?.externalLink), - ), - renderCollectibleInfoRow( - strings('collectible.collectible_asset_contract'), - renderShortAddress(collectible?.address), - () => { + type: FieldType.Text, + }), + renderCollectibleInfoRow({ + key: strings('collectible.collectible_source'), + value: collectible?.imageOriginal, + onPress: () => openLink(collectible?.imageOriginal), + type: FieldType.Link, + }), + renderCollectibleInfoRow({ + key: strings('collectible.collectible_link'), + value: collectible?.externalLink, + onPress: () => openLink(collectible?.externalLink), + type: FieldType.Link, + }), + renderCollectibleInfoRow({ + key: strings('collectible.collectible_asset_contract'), + value: renderShortAddress(collectible?.address), + onPress: () => { if (isMainNet(chainId)) openLink( etherscanLink.createTokenTrackerLink(collectible?.address, chainId), ); }, - ), + type: FieldType.Text, + }), ]; const collectibleToFavorites = useCallback(() => { diff --git a/app/components/UI/FiatOnRampAggregator/Views/AmountToBuy.tsx b/app/components/UI/FiatOnRampAggregator/Views/AmountToBuy.tsx index 4bd1abbf398..65152f27ae5 100644 --- a/app/components/UI/FiatOnRampAggregator/Views/AmountToBuy.tsx +++ b/app/components/UI/FiatOnRampAggregator/Views/AmountToBuy.tsx @@ -663,7 +663,9 @@ const AmountToBuy = () => { description={strings( 'fiat_on_ramp_aggregator.no_tokens_available', { - network: NETWORKS_NAMES[selectedChainId], + network: + NETWORKS_NAMES[selectedChainId] || + strings('fiat_on_ramp_aggregator.this_network'), region: selectedRegion?.name, }, )} diff --git a/app/components/UI/FiatOnRampAggregator/Views/Checkout.tsx b/app/components/UI/FiatOnRampAggregator/Views/Checkout.tsx index 47aeee70091..25a6f9cf073 100644 --- a/app/components/UI/FiatOnRampAggregator/Views/Checkout.tsx +++ b/app/components/UI/FiatOnRampAggregator/Views/Checkout.tsx @@ -1,40 +1,32 @@ import React, { useCallback, useEffect, useState } from 'react'; import { View } from 'react-native'; -import { useDispatch, useSelector } from 'react-redux'; +import { useDispatch } from 'react-redux'; import { parseUrl } from 'query-string'; import { WebView, WebViewNavigation } from 'react-native-webview'; import { useNavigation } from '@react-navigation/native'; -import { CryptoCurrency, Order, Provider } from '@consensys/on-ramp-sdk'; +import { Provider } from '@consensys/on-ramp-sdk'; import { baseStyles } from '../../../../styles/common'; import { useTheme } from '../../../../util/theme'; import { getFiatOnRampAggNavbar } from '../../Navbar'; -import { NATIVE_ADDRESS } from '../../../../constants/on-ramp'; import { useFiatOnRampSDK, SDK } from '../sdk'; import { addFiatCustomIdData, - addFiatOrder, - FiatOrder, removeFiatCustomIdData, } from '../../../../reducers/fiatOrders'; import { CustomIdData } from '../../../../reducers/fiatOrders/types'; -import Engine from '../../../../core/Engine'; -import { toLowerCaseEquals } from '../../../../util/general'; import { createNavigationDetails, useParams, } from '../../../../util/navigation/navUtils'; -import { hexToBN } from '../../../../util/number'; -import { protectWalletModalVisible } from '../../../../actions/user'; import { aggregatorOrderToFiatOrder } from '../orderProcessor/aggregator'; import { createCustomOrderIdData } from '../orderProcessor/customOrderId'; -import { getNotificationDetails } from '..'; -import NotificationManager from '../../../../core/NotificationManager'; import ScreenLayout from '../components/ScreenLayout'; import ErrorView from '../components/ErrorView'; import ErrorViewWithReporting from '../components/ErrorViewWithReporting'; import useAnalytics from '../hooks/useAnalytics'; import { strings } from '../../../../../locales/i18n'; import Routes from '../../../../constants/navigation/Routes'; +import useHandleSuccessfulOrder from '../hooks/useHandleSuccessfulOrder'; interface CheckoutParams { url: string; @@ -58,10 +50,7 @@ const CheckoutWebView = () => { const navigation = useNavigation(); const params = useParams(); const { colors } = useTheme(); - const accounts = useSelector( - (state: any) => - state.engine.backgroundState.AccountTrackerController.accounts, - ); + const handleSuccessfulOrder = useHandleSuccessfulOrder(); const { url: uri, customOrderId, provider } = params; @@ -97,88 +86,6 @@ const CheckoutWebView = () => { dispatch(addFiatCustomIdData(customOrderIdData)); }, [customOrderId, dispatch, selectedAddress, selectedChainId]); - const addTokenToTokensController = useCallback( - async (token: CryptoCurrency) => { - if (!token) return; - - const { address, symbol, decimals, network, name } = token; - const chainId = network?.chainId; - - if ( - Number(chainId) !== Number(selectedChainId) || - address === NATIVE_ADDRESS - ) { - return; - } - - // @ts-expect-error Engine context typing - const { TokensController } = Engine.context; - - if ( - !TokensController.state.tokens.includes((t: any) => - toLowerCaseEquals(t.address, address), - ) - ) { - await TokensController.addToken(address, symbol, decimals, null, name); - } - }, - [selectedChainId], - ); - - const handleAddFiatOrder = useCallback( - (order) => { - dispatch(addFiatOrder(order)); - }, - [dispatch], - ); - - const handleDispatchUserWalletProtection = useCallback(() => { - dispatch(protectWalletModalVisible()); - }, [dispatch]); - - const handleSuccessfulOrder = useCallback( - async (order) => { - // add the order to the redux global store - handleAddFiatOrder(order); - // register the token automatically - await addTokenToTokensController((order as any)?.data?.cryptoCurrency); - - // prompt user to protect his/her wallet - handleDispatchUserWalletProtection(); - // close the checkout webview - // @ts-expect-error navigation prop mismatch - navigation.dangerouslyGetParent()?.pop(); - NotificationManager.showSimpleNotification( - getNotificationDetails(order as any), - ); - trackEvent('ONRAMP_PURCHASE_SUBMITTED', { - provider_onramp: ((order as FiatOrder)?.data as Order)?.provider?.name, - payment_method_id: ((order as FiatOrder)?.data as Order)?.paymentMethod - ?.id, - currency_source: ((order as FiatOrder)?.data as Order)?.fiatCurrency - .symbol, - currency_destination: ((order as FiatOrder)?.data as Order) - ?.cryptoCurrency.symbol, - chain_id_destination: selectedChainId, - order_type: (order as FiatOrder)?.orderType, - is_apple_pay: false, - has_zero_native_balance: accounts[selectedAddress]?.balance - ? (hexToBN(accounts[selectedAddress].balance) as any)?.isZero?.() - : undefined, - }); - }, - [ - accounts, - addTokenToTokensController, - handleAddFiatOrder, - handleDispatchUserWalletProtection, - navigation, - selectedAddress, - selectedChainId, - trackEvent, - ], - ); - const handleNavigationStateChange = async (navState: WebViewNavigation) => { if ( !isRedirectionHandled && diff --git a/app/components/UI/FiatOnRampAggregator/containers/ApplePayButton.tsx b/app/components/UI/FiatOnRampAggregator/containers/ApplePayButton.tsx index 1108f1580ee..20e40e87f60 100644 --- a/app/components/UI/FiatOnRampAggregator/containers/ApplePayButton.tsx +++ b/app/components/UI/FiatOnRampAggregator/containers/ApplePayButton.tsx @@ -1,24 +1,19 @@ import React, { useCallback } from 'react'; import { useDispatch, useSelector } from 'react-redux'; -import { useNavigation } from '@react-navigation/native'; -import { Order, QuoteResponse } from '@consensys/on-ramp-sdk'; -import { protectWalletModalNotVisible } from '../../../../actions/user'; +import { QuoteResponse } from '@consensys/on-ramp-sdk'; import { addAuthenticationUrl, - addFiatOrder, FiatOrder, } from '../../../../reducers/fiatOrders'; import ApplePayButtonComponent from '../components/ApplePayButton'; import useApplePay, { ABORTED } from '../hooks/useApplePay'; -import useAnalytics from '../hooks/useAnalytics'; import Logger from '../../../../util/Logger'; import { strings } from '../../../../../locales/i18n'; import { setLockTime } from '../../../../actions/settings'; import { aggregatorOrderToFiatOrder } from '../orderProcessor/aggregator'; -import { getNotificationDetails } from '..'; import NotificationManager from '../../../../core/NotificationManager'; -import { hexToBN } from '../../../../util/number'; import { useFiatOnRampSDK } from '../sdk'; +import useHandleSuccessfulOrder from '../hooks/useHandleSuccessfulOrder'; function buildAuthenticationUrl(url: string, redirectUrl: string) { const urlObject = new URL(url); @@ -36,66 +31,13 @@ const ApplePayButton = ({ quote: QuoteResponse; label: string; }) => { - const navigation = useNavigation(); - const dispatch = useDispatch(); - const trackEvent = useAnalytics(); const { selectedAddress, selectedChainId, callbackBaseUrl } = useFiatOnRampSDK(); - const accounts = useSelector( - (state: any) => - state.engine.backgroundState.AccountTrackerController.accounts, - ); - + const dispatch = useDispatch(); const [pay] = useApplePay(quote); + const handleSuccessfulOrder = useHandleSuccessfulOrder(); const lockTime = useSelector((state: any) => state.settings.lockTime); - const addOrder = useCallback( - (order) => dispatch(addFiatOrder(order)), - [dispatch], - ); - const protectWalletModalVisible = useCallback( - () => dispatch(protectWalletModalNotVisible()), - [dispatch], - ); - - const handleSuccessfulOrder = useCallback( - (order) => { - const fiatOrder: FiatOrder = { - ...aggregatorOrderToFiatOrder(order), - network: selectedChainId, - account: selectedAddress, - }; - addOrder(fiatOrder); - // @ts-expect-error pop is not defined - navigation.dangerouslyGetParent()?.pop(); - protectWalletModalVisible(); - NotificationManager.showSimpleNotification( - getNotificationDetails(fiatOrder), - ); - trackEvent('ONRAMP_PURCHASE_SUBMITTED', { - provider_onramp: (fiatOrder?.data as Order)?.provider?.name, - payment_method_id: (fiatOrder?.data as Order)?.paymentMethod?.id, - currency_source: (fiatOrder?.data as Order)?.fiatCurrency.symbol, - currency_destination: (fiatOrder?.data as Order)?.cryptoCurrency.symbol, - chain_id_destination: selectedChainId, - is_apple_pay: true, - order_type: fiatOrder.orderType, - has_zero_native_balance: accounts[selectedAddress]?.balance - ? (hexToBN(accounts[selectedAddress].balance) as any)?.isZero?.() - : undefined, - }); - }, - [ - accounts, - addOrder, - selectedChainId, - navigation, - protectWalletModalVisible, - selectedAddress, - trackEvent, - ], - ); - const handlePress = useCallback(async () => { const prevLockTime = lockTime; dispatch(setLockTime(-1)); @@ -109,8 +51,14 @@ const ApplePayButton = ({ ); dispatch(addAuthenticationUrl(authenticationUrl)); } - - handleSuccessfulOrder(paymentResult.order); + if (paymentResult.order) { + const fiatOrder: FiatOrder = { + ...aggregatorOrderToFiatOrder(paymentResult.order), + network: selectedChainId, + account: selectedAddress, + }; + handleSuccessfulOrder(fiatOrder, { isApplePay: true }); + } } } catch (error: any) { NotificationManager.showSimpleNotification({ @@ -130,6 +78,8 @@ const ApplePayButton = ({ dispatch, pay, callbackBaseUrl, + selectedChainId, + selectedAddress, handleSuccessfulOrder, quote.crypto?.symbol, ]); diff --git a/app/components/UI/FiatOnRampAggregator/hooks/useHandleSuccessfulOrder.ts b/app/components/UI/FiatOnRampAggregator/hooks/useHandleSuccessfulOrder.ts new file mode 100644 index 00000000000..f4c680f303a --- /dev/null +++ b/app/components/UI/FiatOnRampAggregator/hooks/useHandleSuccessfulOrder.ts @@ -0,0 +1,118 @@ +import { CryptoCurrency, Order } from '@consensys/on-ramp-sdk'; +import { hexToBN } from '@metamask/controller-utils'; +import { useNavigation } from '@react-navigation/native'; +import { useCallback } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import { getNotificationDetails } from '..'; +import { protectWalletModalVisible } from '../../../../actions/user'; +import { NATIVE_ADDRESS } from '../../../../constants/on-ramp'; +import Engine from '../../../../core/Engine'; +import NotificationManager from '../../../../core/NotificationManager'; +import { addFiatOrder, FiatOrder } from '../../../../reducers/fiatOrders'; +import { toLowerCaseEquals } from '../../../../util/general'; +import useThunkDispatch from '../../../hooks/useThunkDispatch'; +import { useFiatOnRampSDK } from '../sdk'; +import { stateHasOrder } from '../utils'; +import useAnalytics from './useAnalytics'; + +function useHandleSuccessfulOrder() { + const { selectedChainId, selectedAddress } = useFiatOnRampSDK(); + const navigation = useNavigation(); + const dispatch = useDispatch(); + const dispatchThunk = useThunkDispatch(); + const trackEvent = useAnalytics(); + const accounts = useSelector( + (state: any) => + state.engine.backgroundState.AccountTrackerController.accounts, + ); + + const addTokenToTokensController = useCallback( + async (token: CryptoCurrency) => { + if (!token) return; + + const { address, symbol, decimals, network, name } = token; + const chainId = network?.chainId; + + if ( + Number(chainId) !== Number(selectedChainId) || + address === NATIVE_ADDRESS + ) { + return; + } + + const { TokensController } = Engine.context; + + if ( + !TokensController.state.tokens.includes((t: any) => + toLowerCaseEquals(t.address, address), + ) + ) { + await TokensController.addToken(address, symbol, decimals, null, name); + } + }, + [selectedChainId], + ); + + const handleDispatchUserWalletProtection = useCallback(() => { + dispatch(protectWalletModalVisible()); + }, [dispatch]); + + const handleAddFiatOrder = useCallback( + (order) => { + dispatch(addFiatOrder(order)); + }, + [dispatch], + ); + + const handleSuccessfulOrder = useCallback( + async ( + order: FiatOrder, + params?: { + isApplePay?: boolean; + }, + ) => { + await addTokenToTokensController((order as any)?.data?.cryptoCurrency); + handleDispatchUserWalletProtection(); + // @ts-expect-error navigation prop mismatch + navigation.dangerouslyGetParent()?.pop(); + + dispatchThunk((_, getState) => { + const state = getState(); + if (stateHasOrder(state, order)) { + return; + } + handleAddFiatOrder(order); + NotificationManager.showSimpleNotification( + getNotificationDetails(order as any), + ); + trackEvent('ONRAMP_PURCHASE_SUBMITTED', { + provider_onramp: (order?.data as Order)?.provider?.name, + payment_method_id: (order?.data as Order)?.paymentMethod?.id, + currency_source: (order?.data as Order)?.fiatCurrency.symbol, + currency_destination: (order?.data as Order)?.cryptoCurrency.symbol, + chain_id_destination: selectedChainId, + order_type: order?.orderType, + is_apple_pay: Boolean(params?.isApplePay), + has_zero_native_balance: accounts[selectedAddress]?.balance + ? (hexToBN(accounts[selectedAddress].balance) as any)?.isZero?.() + : undefined, + }); + }); + }, + [ + accounts, + addTokenToTokensController, + dispatchThunk, + handleAddFiatOrder, + handleDispatchUserWalletProtection, + navigation, + selectedAddress, + selectedChainId, + trackEvent, + ], + ); + + return handleSuccessfulOrder; +} + +export default useHandleSuccessfulOrder; diff --git a/app/components/UI/FiatOnRampAggregator/hooks/useInAppBrowser.ts b/app/components/UI/FiatOnRampAggregator/hooks/useInAppBrowser.ts index 2b0e7b04829..cc2c58a92a3 100644 --- a/app/components/UI/FiatOnRampAggregator/hooks/useInAppBrowser.ts +++ b/app/components/UI/FiatOnRampAggregator/hooks/useInAppBrowser.ts @@ -2,8 +2,7 @@ import { useCallback } from 'react'; import { Linking } from 'react-native'; import { useDispatch, useSelector } from 'react-redux'; import InAppBrowser from 'react-native-inappbrowser-reborn'; -import { useNavigation } from '@react-navigation/native'; -import { Order, OrderStatusEnum, Provider } from '@consensys/on-ramp-sdk'; +import { OrderStatusEnum, Provider } from '@consensys/on-ramp-sdk'; import BuyAction from '@consensys/on-ramp-sdk/dist/regions/BuyAction'; import useAnalytics from './useAnalytics'; import { callbackBaseDeeplink, SDK, useFiatOnRampSDK } from '../sdk'; @@ -11,16 +10,12 @@ import { createCustomOrderIdData } from '../orderProcessor/customOrderId'; import { aggregatorOrderToFiatOrder } from '../orderProcessor/aggregator'; import { addFiatCustomIdData, - addFiatOrder, FiatOrder, removeFiatCustomIdData, } from '../../../../reducers/fiatOrders'; import { setLockTime } from '../../../../actions/settings'; -import { getNotificationDetails } from '..'; -import { protectWalletModalVisible } from '../../../../actions/user'; -import NotificationManager from '../../../../core/NotificationManager'; -import { hexToBN } from '../../../../util/number'; import Logger from '../../../../util/Logger'; +import useHandleSuccessfulOrder from './useHandleSuccessfulOrder'; export default function useInAppBrowser() { const { @@ -29,60 +24,11 @@ export default function useInAppBrowser() { selectedAsset, selectedChainId, } = useFiatOnRampSDK(); - const navigation = useNavigation(); + const dispatch = useDispatch(); const trackEvent = useAnalytics(); const lockTime = useSelector((state: any) => state.settings.lockTime); - const accounts = useSelector( - (state: any) => - state.engine.backgroundState.AccountTrackerController.accounts, - ); - - const handleSuccessfulOrder = useCallback( - (order: Order) => { - const transformedOrder: FiatOrder = { - ...aggregatorOrderToFiatOrder(order), - account: selectedAddress, - network: selectedChainId, - }; - - // add the order to the redux global store - dispatch(addFiatOrder(transformedOrder)); - - // prompt user to protect his/her wallet - dispatch(protectWalletModalVisible()); - // close the checkout webview - // @ts-expect-error navigation prop mismatch - navigation.dangerouslyGetParent()?.pop(); - NotificationManager.showSimpleNotification( - getNotificationDetails(transformedOrder), - ); - trackEvent('ONRAMP_PURCHASE_SUBMITTED', { - provider_onramp: ((transformedOrder as FiatOrder)?.data as Order) - ?.provider?.name, - payment_method_id: ((transformedOrder as FiatOrder)?.data as Order) - ?.paymentMethod?.id, - currency_source: ((transformedOrder as FiatOrder)?.data as Order) - ?.fiatCurrency.symbol, - currency_destination: ((transformedOrder as FiatOrder)?.data as Order) - ?.cryptoCurrency.symbol, - chain_id_destination: selectedChainId, - is_apple_pay: false, - order_type: (transformedOrder as FiatOrder)?.orderType, - has_zero_native_balance: accounts[selectedAddress]?.balance - ? (hexToBN(accounts[selectedAddress].balance) as any)?.isZero?.() - : undefined, - }); - }, - [ - accounts, - dispatch, - navigation, - selectedAddress, - selectedChainId, - trackEvent, - ], - ); + const handleSuccessfulOrder = useHandleSuccessfulOrder(); const renderInAppBrowser = useCallback( async ( @@ -154,7 +100,13 @@ export default function useInAppBrowser() { return; } - handleSuccessfulOrder(order); + const transformedOrder: FiatOrder = { + ...aggregatorOrderToFiatOrder(order), + account: selectedAddress, + network: selectedChainId, + }; + + handleSuccessfulOrder(transformedOrder); } catch (error) { Logger.error(error as Error, { message: diff --git a/app/components/UI/FiatOnRampAggregator/index.tsx b/app/components/UI/FiatOnRampAggregator/index.tsx index c71c2943da3..55a9198ca07 100644 --- a/app/components/UI/FiatOnRampAggregator/index.tsx +++ b/app/components/UI/FiatOnRampAggregator/index.tsx @@ -2,6 +2,7 @@ import { useDispatch, useSelector } from 'react-redux'; import { InteractionManager, StyleSheet, View } from 'react-native'; import React, { useCallback } from 'react'; import WebView from 'react-native-webview'; +import { Order } from '@consensys/on-ramp-sdk'; import AppConstants from '../../../core/AppConstants'; import { MetaMetricsEvents } from '../../../core/Analytics'; @@ -21,15 +22,16 @@ import { removeAuthenticationUrl, } from '../../../reducers/fiatOrders'; import useInterval from '../../hooks/useInterval'; +import useThunkDispatch, { ThunkAction } from '../../hooks/useThunkDispatch'; import processOrder from './orderProcessor'; import processCustomOrderIdData from './orderProcessor/customOrderId'; import { aggregatorOrderToFiatOrder } from './orderProcessor/aggregator'; import { trackEvent } from './hooks/useAnalytics'; -import { Order } from '@consensys/on-ramp-sdk'; import { AnalyticsEvents } from './types'; import { CustomIdData } from '../../../reducers/fiatOrders/types'; import { callbackBaseUrl } from '../FiatOnRampAggregator/sdk'; import useFetchOnRampNetworks from './hooks/useFetchOnRampNetworks'; +import { stateHasOrder } from './utils'; const POLLING_FREQUENCY = AppConstants.FIAT_ORDERS.POLLING_FREQUENCY; const NOTIFICATION_DURATION = 5000; @@ -215,10 +217,12 @@ async function processCustomOrderId( dispatchUpdateFiatCustomIdData, dispatchRemoveFiatCustomIdData, dispatchAddFiatOrder, + dispatchThunk, }: { dispatchUpdateFiatCustomIdData: (updatedCustomIdData: CustomIdData) => void; dispatchRemoveFiatCustomIdData: (customOrderIdData: CustomIdData) => void; dispatchAddFiatOrder: (fiatOrder: FiatOrder) => void; + dispatchThunk: (thunk: ThunkAction) => void; }, ) { const [customOrderId, fiatOrderResponse] = await processCustomOrderIdData( @@ -227,11 +231,17 @@ async function processCustomOrderId( if (fiatOrderResponse) { const fiatOrder = aggregatorOrderToFiatOrder(fiatOrderResponse); - dispatchAddFiatOrder(fiatOrder); - InteractionManager.runAfterInteractions(() => { - NotificationManager.showSimpleNotification( - getNotificationDetails(fiatOrder), - ); + dispatchThunk((_, getState) => { + const state = getState(); + if (stateHasOrder(state, fiatOrder)) { + return; + } + dispatchAddFiatOrder(fiatOrder); + InteractionManager.runAfterInteractions(() => { + NotificationManager.showSimpleNotification( + getNotificationDetails(fiatOrder), + ); + }); }); dispatchRemoveFiatCustomIdData(customOrderIdData); } else if (customOrderId.expired) { @@ -251,6 +261,7 @@ const styles = StyleSheet.create({ function FiatOrders() { useFetchOnRampNetworks(); const dispatch = useDispatch(); + const dispatchThunk = useThunkDispatch(); const pendingOrders = useSelector(getPendingOrders); const customOrderIds = useSelector(getCustomOrderIds); const authenticationUrls = useSelector(getAuthenticationUrls); @@ -293,6 +304,7 @@ function FiatOrders() { dispatchUpdateFiatCustomIdData, dispatchRemoveFiatCustomIdData, dispatchAddFiatOrder, + dispatchThunk, }), ), ); diff --git a/app/components/UI/FiatOnRampAggregator/sdk/index.tsx b/app/components/UI/FiatOnRampAggregator/sdk/index.tsx index 95cd27bfa87..57eac67260f 100644 --- a/app/components/UI/FiatOnRampAggregator/sdk/index.tsx +++ b/app/components/UI/FiatOnRampAggregator/sdk/index.tsx @@ -33,6 +33,33 @@ import I18n, { I18nEvents } from '../../../../../locales/i18n'; import Device from '../../../../util/device'; import useActivationKeys from '../hooks/useActivationKeys'; +const isDevelopment = process.env.NODE_ENV !== 'production'; +const isInternalBuild = process.env.ONRAMP_INTERNAL_BUILD === 'true'; +const isDevelopmentOrInternalBuild = isDevelopment || isInternalBuild; + +let environment = Environment.Production; +if (isInternalBuild) { + environment = Environment.Staging; +} else if (isDevelopment) { + environment = Environment.Development; +} + +let context = Context.Mobile; +if (Device.isAndroid()) { + context = Context.MobileAndroid; +} else if (Device.isIos()) { + context = Context.MobileIOS; +} + +export const SDK = OnRampSdk.create(environment, context, { + verbose: isDevelopment, + locale: I18n.locale, +}); + +I18nEvents.addListener('localeChanged', (locale) => { + SDK.setLocale(locale); +}); + interface OnRampSDKConfig { POLLING_INTERVAL: number; POLLING_INTERVAL_HIGHLIGHT: number; @@ -74,30 +101,6 @@ interface IProviderProps { children?: React.ReactNode | undefined; } -const isDevelopment = process.env.NODE_ENV !== 'production'; -const isInternalBuild = process.env.ONRAMP_INTERNAL_BUILD === 'true'; -const isDevelopmentOrInternalBuild = isDevelopment || isInternalBuild; - -const CONTEXT = Device.isAndroid() - ? Context.MobileAndroid - : Device.isIos() - ? Context.MobileIOS - : Context.Mobile; -const VERBOSE_SDK = isDevelopment; - -export const SDK = OnRampSdk.create( - isDevelopmentOrInternalBuild ? Environment.Staging : Environment.Production, - CONTEXT, - { - verbose: VERBOSE_SDK, - locale: I18n.locale, - }, -); - -I18nEvents.addListener('localeChanged', (locale) => { - SDK.setLocale(locale); -}); - export const callbackBaseUrl = isDevelopment ? 'https://on-ramp.metaswap-dev.codefi.network/regions/fake-callback' : 'https://on-ramp-content.metaswap.codefi.network/regions/fake-callback'; diff --git a/app/components/UI/FiatOnRampAggregator/utils/index.ts b/app/components/UI/FiatOnRampAggregator/utils/index.ts index 84cf8808d7d..917d504bc83 100644 --- a/app/components/UI/FiatOnRampAggregator/utils/index.ts +++ b/app/components/UI/FiatOnRampAggregator/utils/index.ts @@ -1,11 +1,12 @@ import { AggregatorNetwork } from '@consensys/on-ramp-sdk/dist/API'; import { Order } from '@consensys/on-ramp-sdk'; -import { FiatOrder } from '../../../../reducers/fiatOrders'; import { renderFromTokenMinimalUnit, renderNumber, toTokenMinimalUnit, } from '../../../../util/number'; +import { getOrders, FiatOrder } from '../../../../reducers/fiatOrders'; +import { RootState } from '../../../../reducers/fiatOrders/types'; const isOverAnHour = (minutes: number) => minutes > 59; @@ -148,3 +149,8 @@ export function getOrderAmount(order: FiatOrder) { } return amount; } + +export function stateHasOrder(state: RootState, order: FiatOrder) { + const orders = getOrders(state); + return orders.some((o) => o.id === order.id); +} diff --git a/app/components/UI/Tokens/__snapshots__/index.test.tsx.snap b/app/components/UI/Tokens/__snapshots__/index.test.tsx.snap index 669a0db79a9..d7be9f83a92 100644 --- a/app/components/UI/Tokens/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/Tokens/__snapshots__/index.test.tsx.snap @@ -560,7 +560,57 @@ exports[`Tokens should hide zero balance tokens when setting is on 1`] = ` ], } } - /> + > + + + + + + + > + + + + + + + > + + + + + + + > + + + + + + + > + + + + + + + > + + + + + + + > + + + + + + = ({ tokens }) => { const { colors, themeAppearance } = useTheme(); @@ -276,11 +277,13 @@ const Tokens: React.FC = ({ tokens }) => { balance={secondaryBalance} > + } > {asset.isETH ? ( diff --git a/app/components/UI/WebsiteIcon/index.js b/app/components/UI/WebsiteIcon/index.js index cfde080c528..23b594926f3 100644 --- a/app/components/UI/WebsiteIcon/index.js +++ b/app/components/UI/WebsiteIcon/index.js @@ -86,10 +86,14 @@ export default class WebsiteIcon extends PureComponent { const colors = this.context.colors || mockTheme.colors; const styles = createStyles(colors); const apiLogoUrl = { uri: icon || this.getIconUrl(url) }; - const title = - typeof this.props.title === 'string' - ? this.props.title.substr(0, 1) - : getHost(url).substr(0, 1); + let title = this.props.title; + + if (title !== undefined) { + title = + typeof this.props.title === 'string' + ? this.props.title.substr(0, 1) + : getHost(url).substr(0, 1); + } if (renderIconUrlError && title) { return ( diff --git a/app/components/Views/SendFlow/AddressFrom/AddressFrom.test.tsx b/app/components/Views/SendFlow/AddressFrom/AddressFrom.test.tsx new file mode 100644 index 00000000000..ff73aac0ef1 --- /dev/null +++ b/app/components/Views/SendFlow/AddressFrom/AddressFrom.test.tsx @@ -0,0 +1,61 @@ +import React from 'react'; +import { Provider } from 'react-redux'; +import configureMockStore from 'redux-mock-store'; + +import { render } from '@testing-library/react-native'; + +import Engine from '../../../../core/Engine'; +import SendFlowAddressFrom from './'; + +Engine.init({}); +jest.mock('@react-navigation/native', () => ({ + useNavigation: () => ({ + navigation: {}, + }), + createNavigatorFactory: () => ({}), +})); + +const initialState = { + settings: {}, + engine: { + backgroundState: { + AccountTrackerController: { + accounts: { + '0x0': { + balance: 200, + }, + }, + }, + PreferencesController: { + selectedAddress: '0x0', + identities: { + '0x0': { + address: '0x0', + name: 'Account 1', + }, + }, + }, + }, + }, +}; + +jest.mock('react-redux', () => ({ + ...jest.requireActual('react-redux'), + useSelector: jest + .fn() + .mockImplementation((callback) => callback(initialState)), +})); + +const mockStore = configureMockStore(); +const store = mockStore(initialState); + +describe('SendFlowAddressFrom', () => { + it('should render correctly', () => { + const wrapper = render( + + undefined} /> + , + ); + expect(wrapper).toMatchSnapshot(); + }); +}); diff --git a/app/components/Views/SendFlow/AddressFrom/AddressFrom.tsx b/app/components/Views/SendFlow/AddressFrom/AddressFrom.tsx new file mode 100644 index 00000000000..ca526d1fcc1 --- /dev/null +++ b/app/components/Views/SendFlow/AddressFrom/AddressFrom.tsx @@ -0,0 +1,108 @@ +import React, { useEffect, useState } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; + +import { hexToBN } from '@metamask/controller-utils'; +import { useNavigation } from '@react-navigation/native'; + +import { setSelectedAsset } from '../../../../actions/transaction'; +import Routes from '../../../../constants/navigation/Routes'; +import { + selectNetwork, + selectTicker, +} from '../../../../selectors/networkController'; +import { doENSReverseLookup } from '../../../../util/ENSUtils'; +import { renderFromWei } from '../../../../util/number'; +import { getEther, getTicker } from '../../../../util/transactions'; +import { AddressFrom } from '../../../UI/AddressInputs'; +import { SFAddressFromProps } from './AddressFrom.types'; + +const SendFlowAddressFrom = ({ + fromAccountBalanceState, +}: SFAddressFromProps) => { + const navigation = useNavigation(); + const identities = useSelector( + (state: any) => + state.engine.backgroundState.PreferencesController.identities, + ); + + const accounts = useSelector( + (state: any) => + state.engine.backgroundState.AccountTrackerController.accounts, + ); + + const network = useSelector((state: any) => selectNetwork(state)); + const ticker = useSelector(selectTicker); + + const selectedAddress = useSelector( + (state: any) => + state.engine.backgroundState.PreferencesController.selectedAddress, + ); + + const [accountAddress, setAccountAddress] = useState(selectedAddress); + const [accountName, setAccountName] = useState( + identities[selectedAddress].name, + ); + const [accountBalance, setAccountBalance] = useState(''); + + useEffect(() => { + async function getAccount() { + const ens = await doENSReverseLookup(selectedAddress, network); + const balance = `${renderFromWei( + accounts[selectedAddress].balance, + )} ${getTicker(ticker)}`; + const balanceIsZero = hexToBN(accounts[selectedAddress].balance).isZero(); + setAccountName(ens || identities[selectedAddress].name); + setAccountBalance(balance); + fromAccountBalanceState(balanceIsZero); + } + getAccount(); + }, [ + accounts, + selectedAddress, + ticker, + network, + identities, + fromAccountBalanceState, + ]); + + const dispatch = useDispatch(); + + const selectedAssetAction = (selectedAsset: any) => + dispatch(setSelectedAsset(selectedAsset)); + + const onSelectAccount = async (address: string) => { + const { name } = identities[address]; + const balance = `${renderFromWei(accounts[address].balance)} ${getTicker( + ticker, + )}`; + const ens = await doENSReverseLookup(address); + const accName = ens || name; + const balanceIsZero = hexToBN(accounts[address].balance).isZero(); + selectedAssetAction(getEther(ticker)); + setAccountAddress(address); + setAccountName(accName); + setAccountBalance(balance); + fromAccountBalanceState(balanceIsZero); + }; + + const openAccountSelector = () => { + navigation.navigate(Routes.MODAL.ROOT_MODAL_FLOW, { + screen: Routes.SHEET.ACCOUNT_SELECTOR, + params: { + isSelectOnly: true, + onSelectAccount, + }, + }); + }; + + return ( + + ); +}; + +export default SendFlowAddressFrom; diff --git a/app/components/Views/SendFlow/AddressFrom/AddressFrom.types.ts b/app/components/Views/SendFlow/AddressFrom/AddressFrom.types.ts new file mode 100644 index 00000000000..2f05a877ae2 --- /dev/null +++ b/app/components/Views/SendFlow/AddressFrom/AddressFrom.types.ts @@ -0,0 +1,3 @@ +export interface SFAddressFromProps { + fromAccountBalanceState: (value: boolean) => void; +} diff --git a/app/components/Views/SendFlow/AddressFrom/__snapshots__/AddressFrom.test.tsx.snap b/app/components/Views/SendFlow/AddressFrom/__snapshots__/AddressFrom.test.tsx.snap new file mode 100644 index 00000000000..39eaa4943df --- /dev/null +++ b/app/components/Views/SendFlow/AddressFrom/__snapshots__/AddressFrom.test.tsx.snap @@ -0,0 +1,316 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`SendFlowAddressFrom should render correctly 1`] = ` + + + + From: + + + + + + + + + + + + + + + Account 1 + + + + Balance: + + + + + +  + + + + + +`; diff --git a/app/components/Views/SendFlow/AddressFrom/index.ts b/app/components/Views/SendFlow/AddressFrom/index.ts new file mode 100644 index 00000000000..b81c7b9cd14 --- /dev/null +++ b/app/components/Views/SendFlow/AddressFrom/index.ts @@ -0,0 +1 @@ +export { default } from './AddressFrom'; diff --git a/app/components/Views/SendFlow/AddressTo/AddressTo.test.tsx b/app/components/Views/SendFlow/AddressTo/AddressTo.test.tsx new file mode 100644 index 00000000000..c50db44e732 --- /dev/null +++ b/app/components/Views/SendFlow/AddressTo/AddressTo.test.tsx @@ -0,0 +1,76 @@ +import React from 'react'; +import { Provider } from 'react-redux'; +import configureMockStore from 'redux-mock-store'; + +import { render } from '@testing-library/react-native'; + +import Engine from '../../../../core/Engine'; +import SendFlowAddressTo from './'; + +Engine.init({}); +jest.mock('@react-navigation/native', () => ({ + useNavigation: () => ({ + navigation: {}, + }), + createNavigatorFactory: () => ({}), +})); + +const initialState = { + settings: {}, + engine: { + backgroundState: { + AccountTrackerController: { + accounts: { + '0x0': { + balance: 200, + }, + }, + }, + AddressBookController: { + addressBook: {}, + }, + PreferencesController: { + selectedAddress: '0x0', + identities: { + '0x0': { + address: '0x0', + name: 'Account 1', + }, + }, + }, + }, + }, +}; + +const mockStore = configureMockStore(); +const store = mockStore(initialState); + +jest.mock('react-redux', () => ({ + ...jest.requireActual('react-redux'), + useSelector: jest + .fn() + .mockImplementation((callback) => callback(initialState)), +})); + +describe('SendFlowAddressTo', () => { + it('should render correctly', () => { + const wrapper = render( + + undefined} + inputWidth={undefined} + confusableCollectionArray={undefined} + isFromAddressBook={undefined} + updateParentState={undefined} + onToSelectedAddressChange={undefined} + /> + , + ); + expect(wrapper).toMatchSnapshot(); + }); +}); diff --git a/app/components/Views/SendFlow/AddressTo/AddressTo.tsx b/app/components/Views/SendFlow/AddressTo/AddressTo.tsx new file mode 100644 index 00000000000..af72641ba35 --- /dev/null +++ b/app/components/Views/SendFlow/AddressTo/AddressTo.tsx @@ -0,0 +1,115 @@ +import React from 'react'; +import { Alert } from 'react-native'; +import { useDispatch, useSelector } from 'react-redux'; + +import { useNavigation } from '@react-navigation/native'; + +import { strings } from '../../../../../locales/i18n'; +import { showAlert } from '../../../../actions/alert'; +import { NetworkSwitchErrorType } from '../../../../constants/error'; +import Routes from '../../../../constants/navigation/Routes'; +import Engine from '../../../../core/Engine'; +import { selectNetwork } from '../../../../selectors/networkController'; +import { handleNetworkSwitch } from '../../../../util/networks'; +import { AddressTo } from '../../../UI/AddressInputs'; +import { createQRScannerNavDetails } from '../../QRScanner'; +import { SFAddressToProps } from './AddressTo.types'; + +const SendFlowAddressTo = ({ + addressToReady, + confusableCollectionArray, + highlighted, + inputRef, + inputWidth, + isFromAddressBook, + onSubmit, + onToSelectedAddressChange, + toSelectedAddress, + toSelectedAddressName, + updateParentState, +}: SFAddressToProps) => { + const navigation = useNavigation(); + const dispatch = useDispatch(); + + const network = useSelector(selectNetwork); + + const frequentRpcList = useSelector( + (state: any) => + state.engine.backgroundState.PreferencesController.frequentRpcList, + ); + + const showAlertAction = (config: any) => dispatch(showAlert(config)); + + const onHandleNetworkSwitch = (chain_id: string) => { + try { + const { NetworkController, CurrencyRateController } = Engine.context; + const networkSwitch = handleNetworkSwitch(chain_id, frequentRpcList, { + networkController: NetworkController, + currencyRateController: CurrencyRateController, + }); + + if (!networkSwitch) return; + + showAlertAction({ + isVisible: true, + autodismiss: 5000, + content: 'clipboard-alert', + data: { msg: strings('send.warn_network_change') + network }, + }); + } catch (e: any) { + let alertMessage; + switch (e.message) { + case NetworkSwitchErrorType.missingNetworkId: + alertMessage = strings('send.network_missing_id'); + break; + default: + alertMessage = strings('send.network_not_found_description', { + chain_id, + }); + } + Alert.alert(strings('send.network_not_found_title'), alertMessage); + } + }; + + const onScan = () => { + navigation.navigate( + ...createQRScannerNavDetails({ + onScanSuccess: (meta) => { + if (meta.chain_id) { + onHandleNetworkSwitch(meta.chain_id); + } + if (meta.target_address) { + onToSelectedAddressChange(meta.target_address); + } + }, + origin: Routes.SEND_FLOW.SEND_TO, + }), + ); + }; + + const onToInputFocus = () => { + updateParentState({ highlighted: !highlighted }); + }; + const onClear = () => onToSelectedAddressChange(); + + return ( + + ); +}; + +export default SendFlowAddressTo; diff --git a/app/components/Views/SendFlow/AddressTo/AddressTo.types.ts b/app/components/Views/SendFlow/AddressTo/AddressTo.types.ts new file mode 100644 index 00000000000..aab56bd1fbe --- /dev/null +++ b/app/components/Views/SendFlow/AddressTo/AddressTo.types.ts @@ -0,0 +1,13 @@ +export interface SFAddressToProps { + addressToReady: boolean; + confusableCollectionArray: any; + highlighted: boolean; + inputRef: any; + inputWidth: any; + isFromAddressBook: any; + onSubmit: (address: string) => void; + onToSelectedAddressChange: any; + toSelectedAddress: any; + toSelectedAddressName: any; + updateParentState: any; +} diff --git a/app/components/Views/SendFlow/AddressTo/__snapshots__/AddressTo.test.tsx.snap b/app/components/Views/SendFlow/AddressTo/__snapshots__/AddressTo.test.tsx.snap new file mode 100644 index 00000000000..2af301d8711 --- /dev/null +++ b/app/components/Views/SendFlow/AddressTo/__snapshots__/AddressTo.test.tsx.snap @@ -0,0 +1,163 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`SendFlowAddressTo should render correctly 1`] = ` + + + + To: + + + + + + + + +  + + + + +`; diff --git a/app/components/Views/SendFlow/AddressTo/index.ts b/app/components/Views/SendFlow/AddressTo/index.ts new file mode 100644 index 00000000000..73015feda7b --- /dev/null +++ b/app/components/Views/SendFlow/AddressTo/index.ts @@ -0,0 +1 @@ +export { default } from './AddressTo'; diff --git a/app/components/Views/SendFlow/SendTo/index.test.tsx b/app/components/Views/SendFlow/SendTo/SendTo.test.tsx similarity index 98% rename from app/components/Views/SendFlow/SendTo/index.test.tsx rename to app/components/Views/SendFlow/SendTo/SendTo.test.tsx index b303f77636f..d4a384c52b4 100644 --- a/app/components/Views/SendFlow/SendTo/index.test.tsx +++ b/app/components/Views/SendFlow/SendTo/SendTo.test.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { shallow } from 'enzyme'; -import SendTo from './'; +import SendTo from '.'; import configureMockStore from 'redux-mock-store'; import { Provider } from 'react-redux'; diff --git a/app/components/Views/SendFlow/SendTo/__snapshots__/index.test.tsx.snap b/app/components/Views/SendFlow/SendTo/__snapshots__/SendTo.test.tsx.snap similarity index 90% rename from app/components/Views/SendFlow/SendTo/__snapshots__/index.test.tsx.snap rename to app/components/Views/SendFlow/SendTo/__snapshots__/SendTo.test.tsx.snap index 05a7be90971..45835b957a5 100644 --- a/app/components/Views/SendFlow/SendTo/__snapshots__/index.test.tsx.snap +++ b/app/components/Views/SendFlow/SendTo/__snapshots__/SendTo.test.tsx.snap @@ -2,13 +2,6 @@ exports[`SendTo should render correctly 1`] = ` true; @@ -84,10 +83,6 @@ const dummy = () => true; */ class SendFlow extends PureComponent { static propTypes = { - /** - * Map of accounts to information objects including balances - */ - accounts: PropTypes.object, /** * Map representing the address book */ @@ -156,6 +151,7 @@ class SendFlow extends PureComponent { * Boolean that indicates if the network supports buy */ isNativeTokenBuySupported: PropTypes.bool, + updateParentState: PropTypes.func, }; addressToInputRef = React.createRef(); @@ -165,8 +161,6 @@ class SendFlow extends PureComponent { balanceIsZero: false, addToAddressBookModalVisible: false, fromSelectedAddress: this.props.selectedAddress, - fromAccountName: this.props.identities[this.props.selectedAddress].name, - fromAccountBalance: undefined, toAccount: undefined, toSelectedAddressName: undefined, toSelectedAddressReady: false, @@ -190,8 +184,6 @@ class SendFlow extends PureComponent { componentDidMount = async () => { const { addressBook, - selectedAddress, - accounts, ticker, network, navigation, @@ -199,24 +191,10 @@ class SendFlow extends PureComponent { route, isPaymentRequest, } = this.props; - const { fromAccountName } = this.state; this.updateNavBar(); // For analytics navigation.setParams({ providerType, isPaymentRequest }); const networkAddressBook = addressBook[network] || {}; - const ens = await doENSReverseLookup(selectedAddress, network); - const fromAccountBalance = `${renderFromWei( - accounts[selectedAddress].balance, - )} ${getTicker(ticker)}`; - - setTimeout(() => { - this.setState({ - fromAccountName: ens || fromAccountName, - fromAccountBalance, - balanceIsZero: hexToBN(accounts[selectedAddress].balance).isZero(), - inputWidth: { width: '100%' }, - }); - }, 100); if (!Object.keys(networkAddressBook).length) { setTimeout(() => { this.addressToInputRef && @@ -243,55 +221,6 @@ class SendFlow extends PureComponent { }); }; - onSelectAccount = async (accountAddress) => { - const { ticker, accounts, identities } = this.props; - const { name } = identities[accountAddress]; - const fromAccountBalance = `${renderFromWei( - accounts[accountAddress].balance, - )} ${getTicker(ticker)}`; - const ens = await doENSReverseLookup(accountAddress); - const fromAccountName = ens || name; - // If new account doesn't have the asset - this.props.setSelectedAsset(getEther(ticker)); - this.setState({ - fromAccountName, - fromAccountBalance, - fromSelectedAddress: accountAddress, - balanceIsZero: hexToBN(accounts[accountAddress].balance).isZero(), - }); - }; - - openAccountSelector = () => { - const { navigation } = this.props; - navigation.navigate(Routes.MODAL.ROOT_MODAL_FLOW, { - screen: Routes.SHEET.ACCOUNT_SELECTOR, - params: { - isSelectOnly: true, - onSelectAccount: this.onSelectAccount, - }, - }); - }; - - /** - * This returns the address name from the address book or user accounts if the selectedAddress exist there - * @param {String} toAccount - Address input - * @returns {String | null} - Address or null if toAccount is not in the addressBook or identities array - */ - getAddressNameFromBookOrIdentities = (toAccount) => { - if (!toAccount) return; - - const { addressBook, network, identities } = this.props; - const networkAddressBook = addressBook[network] || {}; - - const checksummedAddress = toChecksumAddress(toAccount); - - return networkAddressBook[checksummedAddress] - ? networkAddressBook[checksummedAddress].name - : identities[checksummedAddress] - ? identities[checksummedAddress].name - : null; - }; - isAddressSaved = () => { const { toAccount } = this.state; const { addressBook, network, identities } = this.props; @@ -302,71 +231,6 @@ class SendFlow extends PureComponent { ); }; - /** - * This set to the state all the information - * that come from validating an ENS or address - * @param {*} toSelectedAddress - The address or the ens writted on the destination input - */ - validateAddressOrENSFromInput = async (toAccount) => { - const { network, addressBook, identities, chainId } = this.props; - const { - addressError, - toEnsName, - addressReady, - toEnsAddress, - addToAddressToAddressBook, - toAddressName, - errorContinue, - isOnlyWarning, - confusableCollection, - } = await validateAddressOrENS({ - toAccount, - network, - addressBook, - identities, - chainId, - }); - - this.setState({ - addressError, - toEnsName, - toSelectedAddressReady: addressReady, - toEnsAddressResolved: toEnsAddress, - addToAddressToAddressBook, - toSelectedAddressName: toAddressName, - errorContinue, - isOnlyWarning, - confusableCollection, - }); - }; - - onToSelectedAddressChange = (toAccount) => { - const addressName = this.getAddressNameFromBookOrIdentities(toAccount); - - /** - * If the address is from addressBook or identities - * then validation is not necessary since it was already validated - */ - if (addressName) { - this.setState({ - toAccount, - toSelectedAddressReady: true, - isFromAddressBook: true, - toSelectedAddressName: addressName, - }); - } else { - this.validateAddressOrENSFromInput(toAccount); - /** - * Because validateAddressOrENSFromInput is an asynchronous function - * we are setting the state here synchronously, so it does not block the UI - * */ - this.setState({ - toAccount, - isFromAddressBook: false, - }); - } - }; - validateToAddress = () => { const { toAccount, toEnsAddressResolved } = this.state; let addressError; @@ -381,10 +245,6 @@ class SendFlow extends PureComponent { return addressError; }; - onToClear = () => { - this.onToSelectedAddressChange(); - }; - onChangeAlias = (alias) => { this.setState({ alias }); }; @@ -438,22 +298,6 @@ class SendFlow extends PureComponent { } }; - onScan = () => { - this.props.navigation.navigate( - ...createQRScannerNavDetails({ - onScanSuccess: (meta) => { - if (meta.chain_id) { - this.handleNetworkSwitch(meta.chain_id); - } - if (meta.target_address) { - this.onToSelectedAddressChange(meta.target_address); - } - }, - origin: Routes.SEND_FLOW.SEND_TO, - }), - ); - }; - onTransactionDirectionSet = async () => { const { setRecipient, navigation, providerType, addRecent } = this.props; const { @@ -461,13 +305,13 @@ class SendFlow extends PureComponent { toAccount, toEnsName, toSelectedAddressName, - fromAccountName, toEnsAddressResolved, } = this.state; if (!this.isAddressSaved()) { const addressError = this.validateToAddress(); if (addressError) return; } + const toAddress = toEnsAddressResolved || toAccount; addRecent(toAddress); setRecipient( @@ -475,7 +319,6 @@ class SendFlow extends PureComponent { toAddress, toEnsName, toSelectedAddressName, - fromAccountName, ); InteractionManager.runAfterInteractions(() => { Analytics.trackEventWithParameters( @@ -594,19 +437,98 @@ class SendFlow extends PureComponent { addressError ); + updateParentState = (state) => { + this.setState({ ...state }); + }; + + fromAccountBalanceState = (value) => { + this.setState({ balanceIsZero: value }); + }; + + getAddressNameFromBookOrIdentities = (toAccount) => { + const { addressBook, identities, network } = this.props; + if (!toAccount) return; + + const networkAddressBook = addressBook[network] || {}; + + const checksummedAddress = toChecksumAddress(toAccount); + + return networkAddressBook[checksummedAddress] + ? networkAddressBook[checksummedAddress].name + : identities[checksummedAddress] + ? identities[checksummedAddress].name + : null; + }; + + validateAddressOrENSFromInput = async (toAccount) => { + const { addressBook, identities, chainId, network } = this.props; + const { + addressError, + toEnsName, + addressReady, + toEnsAddress, + addToAddressToAddressBook, + toAddressName, + errorContinue, + isOnlyWarning, + confusableCollection, + } = await validateAddressOrENS({ + toAccount, + network, + addressBook, + identities, + chainId, + }); + + this.setState({ + addressError, + toEnsName, + toSelectedAddressReady: addressReady, + toEnsAddressResolved: toEnsAddress, + addToAddressToAddressBook, + toSelectedAddressName: toAddressName, + errorContinue, + isOnlyWarning, + confusableCollection, + }); + }; + + onToSelectedAddressChange = (toAccount) => { + const addressName = this.getAddressNameFromBookOrIdentities(toAccount); + + /** + * If the address is from addressBook or identities + * then validation is not necessary since it was already validated + */ + if (addressName) { + this.setState({ + toAccount, + toSelectedAddressReady: true, + isFromAddressBook: true, + toSelectedAddressName: addressName, + }); + } else { + this.validateAddressOrENSFromInput(toAccount); + /** + * Because validateAddressOrENSFromInput is an asynchronous function + * we are setting the state here synchronously, so it does not block the UI + * */ + this.setState({ + toAccount, + isFromAddressBook: false, + }); + } + }; + render = () => { const { ticker, addressBook, network } = this.props; const { - fromSelectedAddress, - fromAccountName, - fromAccountBalance, toAccount, toSelectedAddressReady, toSelectedAddressName, addToAddressToAddressBook, addressError, balanceIsZero, - toInputHighlighted, inputWidth, errorContinue, isOnlyWarning, @@ -614,6 +536,7 @@ class SendFlow extends PureComponent { isFromAddressBook, toEnsAddressResolved, } = this.state; + const colors = this.context.colors || mockTheme.colors; const styles = createStyles(colors); @@ -639,29 +562,23 @@ class SendFlow extends PureComponent { {...generateTestId(Platform, SEND_SCREEN_ID)} > - - @@ -687,10 +604,7 @@ class SendFlow extends PureComponent { {addressError && addressError !== CONTACT_ALREADY_SAVED && ( - + + {!errorContinue && ( ({ - accounts: state.engine.backgroundState.AccountTrackerController.accounts, addressBook: state.engine.backgroundState.AddressBookController.addressBook, chainId: selectChainId(state), selectedAddress: diff --git a/app/components/Views/Settings/Contacts/ContactForm/index.test.tsx b/app/components/Views/Settings/Contacts/ContactForm/index.test.tsx index 42af478505c..3aaeb40407e 100644 --- a/app/components/Views/Settings/Contacts/ContactForm/index.test.tsx +++ b/app/components/Views/Settings/Contacts/ContactForm/index.test.tsx @@ -11,7 +11,7 @@ const initialState = { NetworkController: { isCustomNetwork: false, network: '1', - properties: {}, + networkDetails: {}, providerConfig: { chainId: '1', ticker: 'ETH', type: 'mainnet' }, }, AddressBookController: { diff --git a/app/components/hooks/useThunkDispatch.ts b/app/components/hooks/useThunkDispatch.ts new file mode 100644 index 00000000000..fec5952ee0d --- /dev/null +++ b/app/components/hooks/useThunkDispatch.ts @@ -0,0 +1,11 @@ +import { useDispatch } from 'react-redux'; +import { store } from '../../store'; +type Dispatch = typeof store.dispatch; +type GetState = typeof store.getState; + +export type ThunkAction = (dispatch: Dispatch, getState: GetState) => void; + +function useThunkDispatch() { + return useDispatch<(thunkAction: ThunkAction) => void>(); +} +export default useThunkDispatch; diff --git a/app/constants/error.ts b/app/constants/error.ts index 13ecdc02902..f31c53001b5 100644 --- a/app/constants/error.ts +++ b/app/constants/error.ts @@ -48,3 +48,7 @@ export const VAULT_BACKUP_FAILED_UNDEFINED = 'Unable to backup vault as it is undefined'; export const VAULT_FAILED_TO_GET_VAULT_FROM_BACKUP = 'getVaultFromBackup failed to retrieve vault'; + +// RPCMethodMiddleware +export const TOKEN_NOT_SUPPORTED_FOR_NETWORK = + 'This token is not supported on this network'; diff --git a/app/constants/navigation/Routes.ts b/app/constants/navigation/Routes.ts index 0914aa9a15e..044d1b0d388 100644 --- a/app/constants/navigation/Routes.ts +++ b/app/constants/navigation/Routes.ts @@ -45,6 +45,7 @@ const Routes = { }, SEND_FLOW: { SEND_TO: 'SendTo', + AMOUNT: 'Amount', }, ACCOUNT_BACKUP: { STEP_1_B: 'AccountBackupStep1B', diff --git a/app/constants/test-ids.js b/app/constants/test-ids.js index 572b8e1f63d..421fcf81980 100644 --- a/app/constants/test-ids.js +++ b/app/constants/test-ids.js @@ -58,6 +58,10 @@ export const WHATS_NEW_MODAL_GOT_IT_BUTTON_ID = 'whats-new-modal-got-it-button'; export const INPUT_NETWORK_NAME = 'input-network-name'; export const ADDRESS_BOOK_NEXT_BUTTON = 'address-book-next-button'; +export const NO_ETH_MESSAGE = 'no-eth-message'; +export const SEND_SCREEN = 'send-screen'; +export const ADDRESS_ERROR = 'address-error'; +export const ADD_ADDRESS_BUTTON_ID = 'add-address-button'; // Design System test ids export const CELL_DISPLAY_TEST_ID = 'cell-display'; diff --git a/app/core/DeeplinkManager.js b/app/core/DeeplinkManager.js index ce72cb177ea..5d786c21b06 100644 --- a/app/core/DeeplinkManager.js +++ b/app/core/DeeplinkManager.js @@ -24,7 +24,8 @@ import SDKConnect from '../core/SDKConnect/SDKConnect'; import Routes from '../constants/navigation/Routes'; import Minimizer from 'react-native-minimizer'; import { getAddress } from '../util/address'; -import { allowedToBuy } from '../components/UI/FiatOnRampAggregator'; +import { chainIdSelector, getRampNetworks } from '../reducers/fiatOrders'; +import { isNetworkBuySupported } from '../components/UI/FiatOnRampAggregator/utils'; class DeeplinkManager { constructor({ navigation, frequentRpcList, dispatch, network }) { @@ -188,10 +189,15 @@ class DeeplinkManager { } _handleBuyCrypto() { - // Do nothing for now if use is not in a supported network - if (allowedToBuy(this.network)) { - this.navigation.navigate(Routes.FIAT_ON_RAMP_AGGREGATOR.ID); - } + this.dispatch((_, getState) => { + const state = getState(); + // Do nothing for now if use is not in a supported network + if ( + isNetworkBuySupported(chainIdSelector(state), getRampNetworks(state)) + ) { + this.navigation.navigate(Routes.FIAT_ON_RAMP_AGGREGATOR.ID); + } + }); } parse(url, { browserCallBack, origin, onHandled }) { diff --git a/app/core/RPCMethods/RPCMethodMiddleware.ts b/app/core/RPCMethods/RPCMethodMiddleware.ts index bcbf8be8563..3ef7c85923f 100644 --- a/app/core/RPCMethods/RPCMethodMiddleware.ts +++ b/app/core/RPCMethods/RPCMethodMiddleware.ts @@ -20,6 +20,8 @@ import setOnboardingWizardStep from '../../actions/wizard'; import { v1 as random } from 'uuid'; import { getPermittedAccounts } from '../Permissions'; import AppConstants from '../AppConstants.js'; +import { isSmartContractAddress } from '../../util/transactions'; +import { TOKEN_NOT_SUPPORTED_FOR_NETWORK } from '../../constants/error'; const Engine = ImportedEngine as any; let appVersion = ''; @@ -618,10 +620,19 @@ export const getRpcMethodMiddleware = ({ type, }, } = req; - const { TokensController } = Engine.context; + const { TokensController, NetworkController } = Engine.context; + const { chainId } = NetworkController.state?.providerConfig || {}; checkTabActive(); try { + // Check if token exists on wallet's active network. + const isTokenOnNetwork = await isSmartContractAddress( + address, + chainId, + ); + if (!isTokenOnNetwork) { + throw new Error(TOKEN_NOT_SUPPORTED_FOR_NETWORK); + } const permittedAccounts = await getPermittedAccounts(hostname); // This should return the current active account on the Dapp. const selectedAddress = diff --git a/app/store/index.js b/app/store/index.js index 9ea596c37b1..91a2e2a433f 100644 --- a/app/store/index.js +++ b/app/store/index.js @@ -1,10 +1,11 @@ -import { createStore } from 'redux'; +import { applyMiddleware, createStore } from 'redux'; import { persistStore, persistReducer, createMigrate, createTransform, } from 'redux-persist'; +import thunk from 'redux-thunk'; import AsyncStorage from '@react-native-async-storage/async-storage'; import FilesystemStorage from 'redux-persist-filesystem-storage'; import autoMergeLevel2 from 'redux-persist/lib/stateReconciler/autoMergeLevel2'; @@ -123,7 +124,7 @@ const persistConfig = { const pReducer = persistReducer(persistConfig, rootReducer); -export const store = createStore(pReducer); +export const store = createStore(pReducer, undefined, applyMiddleware(thunk)); /** * Initialize services after persist is completed diff --git a/app/store/migrations.js b/app/store/migrations.js index c7dafc31db0..5173797da8c 100644 --- a/app/store/migrations.js +++ b/app/store/migrations.js @@ -11,6 +11,7 @@ import { DENIED, EXPLORED, } from '../constants/storage'; +import { GOERLI } from '../../app/constants/network'; export const migrations = { // Needed after https://github.com/MetaMask/controllers/pull/152 @@ -63,7 +64,7 @@ export const migrations = { // If the current network does not have a chainId, switch to testnet. state.engine.backgroundState.NetworkController.provider = { ticker: 'ETH', - type: 'goerli', + type: GOERLI, }; } return state; @@ -91,7 +92,7 @@ export const migrations = { // If the current network does not have a chainId, switch to testnet. state.engine.backgroundState.NetworkController.provider = { ticker: 'ETH', - type: 'goerli', + type: GOERLI, chainId: NetworksChainId.goerli, }; } @@ -390,6 +391,26 @@ export const migrations = { return state; }, + 15: (state) => { + const chainId = + state.engine.backgroundState.NetworkController.providerConfig.chainId; + // Deprecate rinkeby, ropsten and Kovan, any user that is on those we fallback to goerli + if (chainId === '4' || chainId === '3' || chainId === '42') { + state.engine.backgroundState.NetworkController.providerConfig = { + chainId: NetworksChainId.goerli, + ticker: 'GoerliETH', + type: GOERLI, + }; + } + return state; + }, + 16: (state) => { + if (state.engine.backgroundState.NetworkController.properties) { + state.engine.backgroundState.NetworkController.networkDetails = + state.engine.backgroundState.NetworkController.properties; + delete state.engine.backgroundState.NetworkController.properties; + } + }, }; -export const version = 14; +export const version = 16; diff --git a/app/util/linkCheck.test.ts b/app/util/linkCheck.test.ts new file mode 100644 index 00000000000..ffd18494b6d --- /dev/null +++ b/app/util/linkCheck.test.ts @@ -0,0 +1,47 @@ +/* eslint-disable no-script-url */ +import isLinkSafe from './linkCheck'; + +jest.mock('../core/Engine', () => ({ + context: { + PhishingController: { + maybeUpdateState: jest.fn(), + test: jest.fn((url: string) => { + if (url === 'phishing.com') return { result: true }; + return { result: false }; + }), + }, + }, +})); + +describe('linkCheck', () => { + it('should correctly check links for safety', () => { + expect(isLinkSafe('htps://ww.example.com/')).toEqual(false); + expect(isLinkSafe('https://ww.example.com/')).toEqual(true); + expect(isLinkSafe('http://example com/page?id=123')).toEqual(false); + expect(isLinkSafe('https://www.example.com/')).toEqual(true); + expect(isLinkSafe('http://phishing.com')).toEqual(false); + expect( + isLinkSafe( + 'https://metamask.app.link/send/pay-Contract-Address@chain-id/transfer?address=Receiver-Address&uint256=1e21', + ), + ).toEqual(false); + + expect(isLinkSafe('javascript:alert(1)')).toEqual(false); + expect(isLinkSafe('j avascript:alert(1);')).toEqual(false); + expect(isLinkSafe(' javascript:alert(1);&tab;')).toEqual(false); + expect(isLinkSafe('javas\x00cript:javascript:alert(1)')).toEqual(false); + expect(isLinkSafe('javas\x07cript:javascript:alert(1)')).toEqual(false); + expect(isLinkSafe('javas\x0Dcript:javascript:alert(1)')).toEqual(false); + expect(isLinkSafe('javas\x0Acript:javascript:alert(1)')).toEqual(false); + expect(isLinkSafe('javas\x08cript:javascript:alert(1)')).toEqual(false); + expect(isLinkSafe('javas\x02cript:javascript:alert(1)')).toEqual(false); + expect(isLinkSafe('javas\x03cript:javascript:alert(1)')).toEqual(false); + expect(isLinkSafe('javas\x04cript:javascript:alert(1)')).toEqual(false); + expect(isLinkSafe('javas\x01cript:javascript:alert(1)')).toEqual(false); + expect(isLinkSafe('javas\x05cript:javascript:alert(1)')).toEqual(false); + expect(isLinkSafe('javas\x0Bcript:javascript:alert(1)')).toEqual(false); + expect(isLinkSafe('javas\x09cript:javascript:alert(1)')).toEqual(false); + expect(isLinkSafe('javas\x06cript:javascript:alert(1)')).toEqual(false); + expect(isLinkSafe('javas\x0Ccript:javascript:alert(1)')).toEqual(false); + }); +}); diff --git a/app/util/linkCheck.ts b/app/util/linkCheck.ts new file mode 100644 index 00000000000..caaf4afc701 --- /dev/null +++ b/app/util/linkCheck.ts @@ -0,0 +1,35 @@ +import Url from 'url-parse'; +import isUrl from 'is-url'; +import { PhishingController as PhishingControllerClass } from '@metamask/phishing-controller'; +import Engine from '../core/Engine'; +const ALLOWED_PROTOCOLS = ['http:', 'https:']; +const DENYLISTED_DOMAINS = ['metamask.app.link']; + +const isAllowedProtocol = (protocol: string): boolean => + ALLOWED_PROTOCOLS.includes(protocol); + +const isAllowedHostname = (hostname: string): boolean => { + const { PhishingController } = Engine.context as { + PhishingController: PhishingControllerClass; + }; + PhishingController.maybeUpdateState(); + const phishingControllerTestResult = PhishingController.test(hostname); + + return !( + phishingControllerTestResult.result || DENYLISTED_DOMAINS.includes(hostname) + ); +}; + +export const isLinkSafe = (link: string): boolean => { + try { + const url = new Url(link); + const { protocol, hostname, href } = url; + return ( + isUrl(href) && isAllowedProtocol(protocol) && isAllowedHostname(hostname) + ); + } catch (err) { + return false; + } +}; + +export default isLinkSafe; diff --git a/bitrise.yml b/bitrise.yml index f0cce505828..be639dde2d9 100644 --- a/bitrise.yml +++ b/bitrise.yml @@ -220,7 +220,7 @@ workflows: - content: |- #!/usr/bin/env bash node -v - METAMASK_ENVIRONMENT='production' yarn test:e2e:ios + METAMASK_ENVIRONMENT='production' yarn test:e2e:ios --testNamePattern='Smoke' title: Detox Build & Test is_always_run: false - custom-test-results-export@1: @@ -620,10 +620,10 @@ app: PROJECT_LOCATION_IOS: ios - opts: is_expand: false - VERSION_NAME: 6.4.0 + VERSION_NAME: 6.5.0 - opts: is_expand: false - VERSION_NUMBER: 1100 + VERSION_NUMBER: 1104 - opts: is_expand: false ANDROID_APK_LINK: '' diff --git a/e2e/resources/collectibles.json b/e2e/resources/collectibles.json new file mode 100644 index 00000000000..cff686786cb --- /dev/null +++ b/e2e/resources/collectibles.json @@ -0,0 +1,6 @@ +{ + "erc1155tokenAddress": "0x306d717D109e0995e0f56027Eb93D9C1d5686dE1", + "erc1155tokenID": "179", + "erc1155collectionName": "Refinable721", + "erc1155tokenName": "Refinable721 #179" +} diff --git a/e2e/specs/add-custom-rpc.spec.js b/e2e/specs/add-custom-rpc.spec.js index 624ff21dba6..0923d20479b 100644 --- a/e2e/specs/add-custom-rpc.spec.js +++ b/e2e/specs/add-custom-rpc.spec.js @@ -1,5 +1,6 @@ 'use strict'; import TestHelpers from '../helpers'; +import { Regression } from '../tags'; import OnboardingView from '../pages/Onboarding/OnboardingView'; import OnboardingCarouselView from '../pages/Onboarding/OnboardingCarouselView'; @@ -28,7 +29,7 @@ const XDAI_URL = 'https://rpc.gnosischain.com'; const MAINNET = 'Ethereum Main Network'; const PASSWORD = '12345678'; -describe('Custom RPC Tests', () => { +describe(Regression('Custom RPC Tests'), () => { beforeEach(() => { jest.setTimeout(170000); }); diff --git a/e2e/specs/addressbook-tests.spec.js b/e2e/specs/addressbook-tests.spec.js index df3b8e4b812..904f0530977 100644 --- a/e2e/specs/addressbook-tests.spec.js +++ b/e2e/specs/addressbook-tests.spec.js @@ -1,4 +1,5 @@ 'use strict'; +import { Smoke } from '../tags'; import OnboardingView from '../pages/Onboarding/OnboardingView'; import OnboardingCarouselView from '../pages/Onboarding/OnboardingCarouselView'; import ProtectYourWalletView from '../pages/Onboarding/ProtectYourWalletView'; @@ -31,7 +32,7 @@ const MYTH_ADDRESS = '0x1FDb169Ef12954F20A15852980e1F0C122BfC1D6'; const MEMO = 'Test adding ENS'; const PASSWORD = '12345678'; -describe('Addressbook Tests', () => { +describe(Smoke('Addressbook Tests'), () => { beforeEach(() => { jest.setTimeout(150000); }); diff --git a/e2e/specs/browser-tests.spec.js b/e2e/specs/browser-tests.spec.js index 8b9bb249b67..1cc2e49f42d 100644 --- a/e2e/specs/browser-tests.spec.js +++ b/e2e/specs/browser-tests.spec.js @@ -1,5 +1,6 @@ 'use strict'; import TestHelpers from '../helpers'; +import { Smoke } from '../tags'; import OnboardingView from '../pages/Onboarding/OnboardingView'; import OnboardingCarouselView from '../pages/Onboarding/OnboardingCarouselView'; @@ -26,7 +27,7 @@ const PASSWORD = '12345678'; const PHISHING_SITE = 'http://www.empowr.com/FanFeed/Home.aspx'; const INVALID_URL = 'https://quackquakc.easq'; -describe('Browser Tests', () => { +describe(Smoke('Browser Tests'), () => { beforeEach(() => { jest.setTimeout(150000); }); diff --git a/e2e/specs/confirmations/advanced-gas-fees.spec.js b/e2e/specs/confirmations/advanced-gas-fees.spec.js index d1deb380d97..e92b6ee6b67 100644 --- a/e2e/specs/confirmations/advanced-gas-fees.spec.js +++ b/e2e/specs/confirmations/advanced-gas-fees.spec.js @@ -1,4 +1,6 @@ 'use strict'; +import { Smoke } from '../../tags'; + import WalletView from '../../pages/WalletView'; import SendView from '../../pages/SendView'; import AmountView from '../../pages/AmountView'; @@ -12,7 +14,7 @@ import WalletActionsModal from '../../pages/modals/WalletActionsModal'; const VALID_ADDRESS = '0xebe6CcB6B55e1d094d9c58980Bc10Fed69932cAb'; -describe('Advanced Gas Fees and Priority Tests', () => { +describe(Smoke('Advanced Gas Fees and Priority Tests'), () => { beforeEach(() => { jest.setTimeout(170000); }); diff --git a/e2e/specs/confirmations/send-eth-flow.spec.js b/e2e/specs/confirmations/send-eth-flow.spec.js index 0aa1c43d8d4..b295ba75ea2 100644 --- a/e2e/specs/confirmations/send-eth-flow.spec.js +++ b/e2e/specs/confirmations/send-eth-flow.spec.js @@ -1,5 +1,6 @@ 'use strict'; +import { Smoke } from '../../tags'; import AmountView from '../../pages/AmountView'; import SendView from '../../pages/SendView'; import TransactionConfirmationView from '../../pages/TransactionConfirmView'; @@ -16,7 +17,7 @@ import Ganache from '../../../app/util/test/ganache'; const validAccount = Accounts.getValidAccount(); const MYTH_ADDRESS = '0x1FDb169Ef12954F20A15852980e1F0C122BfC1D6'; -describe('Send ETH Tests', () => { +describe(Smoke('Send ETH Tests'), () => { let ganacheServer; beforeAll(async () => { jest.setTimeout(150000); diff --git a/e2e/specs/confirmations/send-multisig-address-ios.spec.js b/e2e/specs/confirmations/send-multisig-address-ios.spec.js index 8b7d2108985..4e1cd00145b 100644 --- a/e2e/specs/confirmations/send-multisig-address-ios.spec.js +++ b/e2e/specs/confirmations/send-multisig-address-ios.spec.js @@ -1,4 +1,6 @@ 'use strict'; +import { Regression } from '../../tags'; + import WalletView from '../../pages/WalletView'; import DrawerView from '../../pages/Drawer/DrawerView'; import SendView from '../../pages/SendView'; @@ -11,7 +13,7 @@ import { const MULTISIG_ADDRESS = '0x0C1DD822d1Ddf78b0b702df7BF9fD0991D6255A1'; -describe('Send to multisig address on iOS', () => { +describe(Regression('Send to multisig address on iOS'), () => { beforeEach(() => { jest.setTimeout(170000); }); diff --git a/e2e/specs/deeplinks.spec.js b/e2e/specs/deeplinks.spec.js index eae0faf7e93..74077743bba 100644 --- a/e2e/specs/deeplinks.spec.js +++ b/e2e/specs/deeplinks.spec.js @@ -1,5 +1,6 @@ 'use strict'; import TestHelpers from '../helpers'; +import { Regression } from '../tags'; import ConnectModal from '../pages/modals/ConnectModal'; import NetworkApprovalModal from '../pages/modals/NetworkApprovalModal'; @@ -39,7 +40,7 @@ const networkErrorBodyMessage = const validAccount = Accounts.getValidAccount(); -describe('Deep linking Tests', () => { +describe(Regression('Deep linking Tests'), () => { beforeEach(() => { jest.setTimeout(150000); }); diff --git a/e2e/specs/delete-wallet.spec.js b/e2e/specs/delete-wallet.spec.js index b3bf99d1e0d..ffa6353451b 100644 --- a/e2e/specs/delete-wallet.spec.js +++ b/e2e/specs/delete-wallet.spec.js @@ -1,6 +1,7 @@ 'use strict'; import TestHelpers from '../helpers'; +import { Smoke } from '../tags'; import OnboardingView from '../pages/Onboarding/OnboardingView'; import OnboardingCarouselView from '../pages/Onboarding/OnboardingCarouselView'; @@ -24,123 +25,128 @@ import EnableAutomaticSecurityChecksView from '../pages/EnableAutomaticSecurityC import { acceptTermOfUse } from '../viewHelper'; import Accounts from '../../wdio/helpers/Accounts'; -describe('Import wallet with 24 word SRP, change password then delete wallet flow', () => { - let validAccount; - - beforeAll(() => { - validAccount = Accounts.getValidAccount(); - }); - - beforeEach(() => { - jest.setTimeout(150000); - }); - - it('should go to import wallet view', async () => { - await OnboardingCarouselView.isVisible(); - await OnboardingCarouselView.tapOnGetStartedButton(); - - await OnboardingView.isVisible(); - await OnboardingView.tapImportWalletFromSeedPhrase(); - - await MetaMetricsOptIn.isVisible(); - await MetaMetricsOptIn.tapAgreeButton(); - await acceptTermOfUse(); - - await ImportWalletView.isVisible(); - }); - - it('should import wallet with valid secret recovery phrase and password', async () => { - await ImportWalletView.clearSecretRecoveryPhraseInputBox(); - await ImportWalletView.enterSecretRecoveryPhrase(validAccount.seedPhrase); - await ImportWalletView.enterPassword(validAccount.password); - await ImportWalletView.reEnterPassword(validAccount.password); - }); - it('Should dismiss Automatic Security checks screen', async () => { - await TestHelpers.delay(3500); - await EnableAutomaticSecurityChecksView.isVisible(); - await EnableAutomaticSecurityChecksView.tapNoThanks(); - }); - - it('should dismiss the onboarding wizard', async () => { - // dealing with flakiness on bitrise. - await TestHelpers.delay(1000); - try { - await OnboardingWizardModal.isVisible(); - await OnboardingWizardModal.tapNoThanksButton(); - await OnboardingWizardModal.isNotVisible(); - } catch { - // - } - }); - - it('should tap on "Got it" to dimiss the whats new modal', async () => { - // dealing with flakiness on bitrise. - await TestHelpers.delay(2500); - try { - await WhatsNewModal.isVisible(); - await WhatsNewModal.tapCloseButton(); - } catch { - // - } - }); - - it('should go to settings then security & privacy', async () => { - // Open Drawer - await WalletView.tapDrawerButton(); // tapping burger menu - - await DrawerView.isVisible(); - await DrawerView.tapSettings(); - - await SettingsView.tapSecurityAndPrivacy(); - await SecurityAndPrivacyView.scrollToChangePasswordView(); - - await SecurityAndPrivacyView.isChangePasswordSectionVisible(); - }); - - it('should confirm password before changing it', async () => { - await SecurityAndPrivacyView.tapChangePasswordButton(); - - await ChangePasswordView.isVisible(); - await ChangePasswordView.typeInConfirmPasswordInputBox( - validAccount.password, - ); - //await ChangePasswordView.tapConfirmButton(); - }); - - it('should change the password', async () => { - const NEW_PASSWORD = '11111111'; - await ChangePasswordView.enterPassword(NEW_PASSWORD); - await ChangePasswordView.reEnterPassword(NEW_PASSWORD); - await ChangePasswordView.tapIUnderstandCheckBox(); - - await ChangePasswordView.tapResetPasswordButton(); - }); - - it('should open drawer and log out', async () => { - await device.disableSynchronization(); // because the SRP tutorial video prevents the test from moving forward - await SecurityAndPrivacyView.tapBackButton(); - await device.enableSynchronization(); - - await SettingsView.tapCloseButton(); - - await WalletView.tapDrawerButton(); - - await DrawerView.isVisible(); - await DrawerView.tapLockAccount(); - await DrawerView.tapYesAlertButton(); - await LoginView.isVisible(); - }); - - it('should tap reset wallet button', async () => { - await LoginView.tapResetWalletButton(); - - await DeleteWalletModal.isVisible(); - }); - it('should delete wallet', async () => { - await DeleteWalletModal.tapIUnderstandButton(); - await DeleteWalletModal.typeDeleteInInputBox(); - await DeleteWalletModal.tapDeleteMyWalletButton(); - await TestHelpers.delay(2000); - await OnboardingView.isVisible(); - }); -}); +describe( + Smoke( + 'Import wallet with 24 word SRP, change password then delete wallet flow', + ), + () => { + let validAccount; + + beforeAll(() => { + validAccount = Accounts.getValidAccount(); + }); + + beforeEach(() => { + jest.setTimeout(150000); + }); + + it('should go to import wallet view', async () => { + await OnboardingCarouselView.isVisible(); + await OnboardingCarouselView.tapOnGetStartedButton(); + + await OnboardingView.isVisible(); + await OnboardingView.tapImportWalletFromSeedPhrase(); + + await MetaMetricsOptIn.isVisible(); + await MetaMetricsOptIn.tapAgreeButton(); + await acceptTermOfUse(); + + await ImportWalletView.isVisible(); + }); + + it('should import wallet with valid secret recovery phrase and password', async () => { + await ImportWalletView.clearSecretRecoveryPhraseInputBox(); + await ImportWalletView.enterSecretRecoveryPhrase(validAccount.seedPhrase); + await ImportWalletView.enterPassword(validAccount.password); + await ImportWalletView.reEnterPassword(validAccount.password); + }); + it('Should dismiss Automatic Security checks screen', async () => { + await TestHelpers.delay(3500); + await EnableAutomaticSecurityChecksView.isVisible(); + await EnableAutomaticSecurityChecksView.tapNoThanks(); + }); + + it('should dismiss the onboarding wizard', async () => { + // dealing with flakiness on bitrise. + await TestHelpers.delay(1000); + try { + await OnboardingWizardModal.isVisible(); + await OnboardingWizardModal.tapNoThanksButton(); + await OnboardingWizardModal.isNotVisible(); + } catch { + // + } + }); + + it('should tap on "Got it" to dimiss the whats new modal', async () => { + // dealing with flakiness on bitrise. + await TestHelpers.delay(2500); + try { + await WhatsNewModal.isVisible(); + await WhatsNewModal.tapCloseButton(); + } catch { + // + } + }); + + it('should go to settings then security & privacy', async () => { + // Open Drawer + await WalletView.tapDrawerButton(); // tapping burger menu + + await DrawerView.isVisible(); + await DrawerView.tapSettings(); + + await SettingsView.tapSecurityAndPrivacy(); + await SecurityAndPrivacyView.scrollToChangePasswordView(); + + await SecurityAndPrivacyView.isChangePasswordSectionVisible(); + }); + + it('should confirm password before changing it', async () => { + await SecurityAndPrivacyView.tapChangePasswordButton(); + + await ChangePasswordView.isVisible(); + await ChangePasswordView.typeInConfirmPasswordInputBox( + validAccount.password, + ); + //await ChangePasswordView.tapConfirmButton(); + }); + + it('should change the password', async () => { + const NEW_PASSWORD = '11111111'; + await ChangePasswordView.enterPassword(NEW_PASSWORD); + await ChangePasswordView.reEnterPassword(NEW_PASSWORD); + await ChangePasswordView.tapIUnderstandCheckBox(); + + await ChangePasswordView.tapResetPasswordButton(); + }); + + it('should open drawer and log out', async () => { + await device.disableSynchronization(); // because the SRP tutorial video prevents the test from moving forward + await SecurityAndPrivacyView.tapBackButton(); + await device.enableSynchronization(); + + await SettingsView.tapCloseButton(); + + await WalletView.tapDrawerButton(); + + await DrawerView.isVisible(); + await DrawerView.tapLockAccount(); + await DrawerView.tapYesAlertButton(); + await LoginView.isVisible(); + }); + + it('should tap reset wallet button', async () => { + await LoginView.tapResetWalletButton(); + + await DeleteWalletModal.isVisible(); + }); + it('should delete wallet', async () => { + await DeleteWalletModal.tapIUnderstandButton(); + await DeleteWalletModal.typeDeleteInInputBox(); + await DeleteWalletModal.tapDeleteMyWalletButton(); + await TestHelpers.delay(2000); + await OnboardingView.isVisible(); + }); + }, +); diff --git a/e2e/specs/onboarding-wizard-opt-in.spec.js b/e2e/specs/onboarding-wizard-opt-in.spec.js index 5cad9d44d0b..ff61f9d2820 100644 --- a/e2e/specs/onboarding-wizard-opt-in.spec.js +++ b/e2e/specs/onboarding-wizard-opt-in.spec.js @@ -1,5 +1,6 @@ 'use strict'; import TestHelpers from '../helpers'; +import { Regression } from '../tags'; import OnboardingView from '../pages/Onboarding/OnboardingView'; import OnboardingCarouselView from '../pages/Onboarding/OnboardingCarouselView'; @@ -25,133 +26,136 @@ import { acceptTermOfUse } from '../viewHelper'; const PASSWORD = '12345678'; -describe('Onboarding wizard opt-in, metametrics opt out from settings', () => { - it('should be able to opt-in of the onboarding-wizard', async () => { - await OnboardingCarouselView.isVisible(); - await OnboardingCarouselView.tapOnGetStartedButton(); - - await OnboardingView.isVisible(); - await OnboardingView.tapCreateWallet(); - - await MetaMetricsOptIn.isVisible(); - await MetaMetricsOptIn.tapAgreeButton(); - await acceptTermOfUse(); - - await CreatePasswordView.isVisible(); - }); - it('should be able to create a new wallet', async () => { - await CreatePasswordView.enterPassword(PASSWORD); - await CreatePasswordView.reEnterPassword(PASSWORD); - await CreatePasswordView.tapIUnderstandCheckBox(); - await CreatePasswordView.tapCreatePasswordButton(); - }); - - it('Should skip backup check', async () => { - // Check that we are on the Secure your wallet screen - await ProtectYourWalletView.isVisible(); - await ProtectYourWalletView.tapOnRemindMeLaterButton(); - - await SkipAccountSecurityModal.tapIUnderstandCheckBox(); - await SkipAccountSecurityModal.tapSkipButton(); - await WalletView.isVisible(); - }); - - it('Should dismiss Automatic Security checks screen', async () => { - await TestHelpers.delay(3500); - await EnableAutomaticSecurityChecksView.isVisible(); - await EnableAutomaticSecurityChecksView.tapNoThanks(); - }); - - it('should dismiss the onboarding wizard', async () => { - // dealing with flakiness on bitrise. - await TestHelpers.delay(1000); - try { - await OnboardingWizardModal.isVisible(); - await OnboardingWizardModal.tapNoThanksButton(); - await OnboardingWizardModal.isNotVisible(); - } catch { - // - } - }); - - it('should tap on "Got it" Button in the whats new modal', async () => { - // dealing with flakiness on bitrise. - await TestHelpers.delay(2500); - try { - await WhatsNewModal.isVisible(); - await WhatsNewModal.tapCloseButton(); - } catch { - // - } - }); - - it('should dismiss the protect your wallet modal', async () => { - await ProtectYourWalletModal.isCollapsedBackUpYourWalletModalVisible(); - await TestHelpers.delay(1000); - - await ProtectYourWalletModal.tapRemindMeLaterButton(); - - await SkipAccountSecurityModal.tapIUnderstandCheckBox(); - await SkipAccountSecurityModal.tapSkipButton(); - - await WalletView.isVisible(); - }); - - it('should check that metametrics is enabled in settings', async () => { - await WalletView.tapDrawerButton(); // tapping burger menu - - await DrawerView.isVisible(); - await DrawerView.tapSettings(); - - await SettingsView.tapSecurityAndPrivacy(); - - await SecurityAndPrivacy.scrollToBottomOfView(); - TestHelpers.delay(2000); - await SecurityAndPrivacy.isMetaMetricsToggleOn(); - - TestHelpers.delay(1500); - }); - - it('should disable metametrics', async () => { - await SecurityAndPrivacy.tapMetaMetricsToggle(); - await SecurityAndPrivacy.isMetaMetricsToggleOff(); - - TestHelpers.delay(1500); - await SecurityAndPrivacy.tapOKAlertButton(); - await SecurityAndPrivacy.isMetaMetricsToggleOff(); - }); - - it('should relaunch the app and log in', async () => { - // Relaunch app - await TestHelpers.relaunchApp(); - - await LoginView.isVisible(); - await LoginView.enterPassword(PASSWORD); - - await WalletView.isVisible(); - }); - - it('should dismiss the onboarding wizard after logging in', async () => { - // dealing with flakiness on bitrise. - await TestHelpers.delay(1000); - try { - await OnboardingWizardModal.isVisible(); - await OnboardingWizardModal.tapNoThanksButton(); - await OnboardingWizardModal.isNotVisible(); - } catch { - // - } - }); - - it('should verify metametrics is turned off', async () => { - await WalletView.tapDrawerButton(); // tapping burger menu - - await DrawerView.isVisible(); - await DrawerView.tapSettings(); - - await SettingsView.tapSecurityAndPrivacy(); - - await SecurityAndPrivacy.scrollToBottomOfView(); - await SecurityAndPrivacy.isMetaMetricsToggleOff(); - }); -}); +describe( + Regression('Onboarding wizard opt-in, metametrics opt out from settings'), + () => { + it('should be able to opt-in of the onboarding-wizard', async () => { + await OnboardingCarouselView.isVisible(); + await OnboardingCarouselView.tapOnGetStartedButton(); + + await OnboardingView.isVisible(); + await OnboardingView.tapCreateWallet(); + + await MetaMetricsOptIn.isVisible(); + await MetaMetricsOptIn.tapAgreeButton(); + await acceptTermOfUse(); + + await CreatePasswordView.isVisible(); + }); + it('should be able to create a new wallet', async () => { + await CreatePasswordView.enterPassword(PASSWORD); + await CreatePasswordView.reEnterPassword(PASSWORD); + await CreatePasswordView.tapIUnderstandCheckBox(); + await CreatePasswordView.tapCreatePasswordButton(); + }); + + it('Should skip backup check', async () => { + // Check that we are on the Secure your wallet screen + await ProtectYourWalletView.isVisible(); + await ProtectYourWalletView.tapOnRemindMeLaterButton(); + + await SkipAccountSecurityModal.tapIUnderstandCheckBox(); + await SkipAccountSecurityModal.tapSkipButton(); + await WalletView.isVisible(); + }); + + it('Should dismiss Automatic Security checks screen', async () => { + await TestHelpers.delay(3500); + await EnableAutomaticSecurityChecksView.isVisible(); + await EnableAutomaticSecurityChecksView.tapNoThanks(); + }); + + it('should dismiss the onboarding wizard', async () => { + // dealing with flakiness on bitrise. + await TestHelpers.delay(1000); + try { + await OnboardingWizardModal.isVisible(); + await OnboardingWizardModal.tapNoThanksButton(); + await OnboardingWizardModal.isNotVisible(); + } catch { + // + } + }); + + it('should tap on "Got it" Button in the whats new modal', async () => { + // dealing with flakiness on bitrise. + await TestHelpers.delay(2500); + try { + await WhatsNewModal.isVisible(); + await WhatsNewModal.tapCloseButton(); + } catch { + // + } + }); + + it('should dismiss the protect your wallet modal', async () => { + await ProtectYourWalletModal.isCollapsedBackUpYourWalletModalVisible(); + await TestHelpers.delay(1000); + + await ProtectYourWalletModal.tapRemindMeLaterButton(); + + await SkipAccountSecurityModal.tapIUnderstandCheckBox(); + await SkipAccountSecurityModal.tapSkipButton(); + + await WalletView.isVisible(); + }); + + it('should check that metametrics is enabled in settings', async () => { + await WalletView.tapDrawerButton(); // tapping burger menu + + await DrawerView.isVisible(); + await DrawerView.tapSettings(); + + await SettingsView.tapSecurityAndPrivacy(); + + await SecurityAndPrivacy.scrollToBottomOfView(); + TestHelpers.delay(2000); + await SecurityAndPrivacy.isMetaMetricsToggleOn(); + + TestHelpers.delay(1500); + }); + + it('should disable metametrics', async () => { + await SecurityAndPrivacy.tapMetaMetricsToggle(); + await SecurityAndPrivacy.isMetaMetricsToggleOff(); + + TestHelpers.delay(1500); + await SecurityAndPrivacy.tapOKAlertButton(); + await SecurityAndPrivacy.isMetaMetricsToggleOff(); + }); + + it('should relaunch the app and log in', async () => { + // Relaunch app + await TestHelpers.relaunchApp(); + + await LoginView.isVisible(); + await LoginView.enterPassword(PASSWORD); + + await WalletView.isVisible(); + }); + + it('should dismiss the onboarding wizard after logging in', async () => { + // dealing with flakiness on bitrise. + await TestHelpers.delay(1000); + try { + await OnboardingWizardModal.isVisible(); + await OnboardingWizardModal.tapNoThanksButton(); + await OnboardingWizardModal.isNotVisible(); + } catch { + // + } + }); + + it('should verify metametrics is turned off', async () => { + await WalletView.tapDrawerButton(); // tapping burger menu + + await DrawerView.isVisible(); + await DrawerView.tapSettings(); + + await SettingsView.tapSecurityAndPrivacy(); + + await SecurityAndPrivacy.scrollToBottomOfView(); + await SecurityAndPrivacy.isMetaMetricsToggleOff(); + }); + }, +); diff --git a/e2e/specs/permission-system-delete-wallet.spec.js b/e2e/specs/permission-system-delete-wallet.spec.js index 57ff9336034..b101a7330d0 100644 --- a/e2e/specs/permission-system-delete-wallet.spec.js +++ b/e2e/specs/permission-system-delete-wallet.spec.js @@ -1,5 +1,6 @@ 'use strict'; import TestHelpers from '../helpers'; +import { Regression } from '../tags'; import OnboardingView from '../pages/Onboarding/OnboardingView'; import ProtectYourWalletView from '../pages/Onboarding/ProtectYourWalletView'; @@ -27,91 +28,93 @@ import { const TEST_DAPP = 'https://metamask.github.io/test-dapp/'; const PASSWORD = '12345678'; - -describe('Permission System: Deleting wallet after connecting to a dapp', () => { - beforeEach(() => { - jest.setTimeout(150000); - }); - - it('should import wallet and go to the wallet view', async () => { - await importWalletWithRecoveryPhrase(); - }); - - it('should navigate to browser', async () => { - await TabBarComponent.tapBrowser(); - await Browser.isVisible(); - }); - - it('should connect to the test dapp', async () => { - await TestHelpers.delay(3000); - // Tap on search in bottom navbar - await Browser.tapUrlInputBox(); - await Browser.navigateToURL(TEST_DAPP); - await TestHelpers.delay(3000); - await TestHelpers.tapAtPoint( - BROWSER_SCREEN_ID, - testDappConnectButtonCooridinates, - ); - await ConnectModal.isVisible(); - await ConnectModal.tapConnectButton(); - }); - - it('should navigate to wallet view', async () => { - await TestHelpers.delay(3000); - await TabBarComponent.tapWallet(); - // Check that we are on the browser screen - await WalletView.isVisible(); - }); - - it('should open drawer and log out', async () => { - await WalletView.tapDrawerButton(); - await DrawerView.isVisible(); - await DrawerView.tapLockAccount(); - await DrawerView.tapYesAlertButton(); - await LoginView.isVisible(); - }); - - it('should tap reset wallet button', async () => { - await LoginView.tapResetWalletButton(); - - await DeleteWalletModal.isVisible(); - }); - it('should delete wallet', async () => { - await DeleteWalletModal.tapIUnderstandButton(); - await DeleteWalletModal.typeDeleteInInputBox(); - await DeleteWalletModal.tapDeleteMyWalletButton(); - await OnboardingView.isDeleteWalletToastVisible(); - }); - - it('should create new wallet', async () => { - await OnboardingView.deleteWalletToastisNotVisible(); - await OnboardingView.tapCreateWallet(); - - await CreatePasswordView.isVisible(); - await CreatePasswordView.enterPassword(PASSWORD); - await CreatePasswordView.reEnterPassword(PASSWORD); - await CreatePasswordView.tapIUnderstandCheckBox(); - await CreatePasswordView.tapCreatePasswordButton(); - }); - - it('Should skip backup check', async () => { - await ProtectYourWalletView.isVisible(); - await ProtectYourWalletView.tapOnRemindMeLaterButton(); - - await SkipAccountSecurityModal.tapIUnderstandCheckBox(); - await SkipAccountSecurityModal.tapSkipButton(); - await WalletView.isVisible(); - }); - - it('should go to browser', async () => { - await TabBarComponent.tapBrowser(); - await Browser.isVisible(); - }); - - it('should no longer be connected to the dapp', async () => { - await Browser.tapNetworkAvatarButtonOnBrowser(); - await ConnectedAccountsModal.isNotVisible(); - await NetworkListModal.isVisible(); - await NetworkListModal.tapNetworkListCloseIcon(); - }); -}); +describe( + Regression('Onboarding wizard opt-in, metametrics opt out from settings'), + () => { + beforeEach(() => { + jest.setTimeout(150000); + }); + + it('should import wallet and go to the wallet view', async () => { + await importWalletWithRecoveryPhrase(); + }); + + it('should navigate to browser', async () => { + await TabBarComponent.tapBrowser(); + await Browser.isVisible(); + }); + + it('should connect to the test dapp', async () => { + await TestHelpers.delay(3000); + // Tap on search in bottom navbar + await Browser.tapUrlInputBox(); + await Browser.navigateToURL(TEST_DAPP); + await TestHelpers.delay(3000); + await TestHelpers.tapAtPoint( + BROWSER_SCREEN_ID, + testDappConnectButtonCooridinates, + ); + await ConnectModal.isVisible(); + await ConnectModal.tapConnectButton(); + }); + + it('should navigate to wallet view', async () => { + await TestHelpers.delay(3000); + await TabBarComponent.tapWallet(); + // Check that we are on the browser screen + await WalletView.isVisible(); + }); + + it('should open drawer and log out', async () => { + await WalletView.tapDrawerButton(); + await DrawerView.isVisible(); + await DrawerView.tapLockAccount(); + await DrawerView.tapYesAlertButton(); + await LoginView.isVisible(); + }); + + it('should tap reset wallet button', async () => { + await LoginView.tapResetWalletButton(); + + await DeleteWalletModal.isVisible(); + }); + it('should delete wallet', async () => { + await DeleteWalletModal.tapIUnderstandButton(); + await DeleteWalletModal.typeDeleteInInputBox(); + await DeleteWalletModal.tapDeleteMyWalletButton(); + await OnboardingView.isDeleteWalletToastVisible(); + }); + + it('should create new wallet', async () => { + await OnboardingView.deleteWalletToastisNotVisible(); + await OnboardingView.tapCreateWallet(); + + await CreatePasswordView.isVisible(); + await CreatePasswordView.enterPassword(PASSWORD); + await CreatePasswordView.reEnterPassword(PASSWORD); + await CreatePasswordView.tapIUnderstandCheckBox(); + await CreatePasswordView.tapCreatePasswordButton(); + }); + + it('Should skip backup check', async () => { + await ProtectYourWalletView.isVisible(); + await ProtectYourWalletView.tapOnRemindMeLaterButton(); + + await SkipAccountSecurityModal.tapIUnderstandCheckBox(); + await SkipAccountSecurityModal.tapSkipButton(); + await WalletView.isVisible(); + }); + + it('should go to browser', async () => { + await TabBarComponent.tapBrowser(); + await Browser.isVisible(); + }); + + it('should no longer be connected to the dapp', async () => { + await Browser.tapNetworkAvatarButtonOnBrowser(); + await ConnectedAccountsModal.isNotVisible(); + await NetworkListModal.isVisible(); + await NetworkListModal.tapNetworkListCloseIcon(); + }); + }, +); diff --git a/e2e/specs/permission-system-removing-imported-account.spec.js b/e2e/specs/permission-system-removing-imported-account.spec.js index 2b6a275cd64..acd4e5c1751 100644 --- a/e2e/specs/permission-system-removing-imported-account.spec.js +++ b/e2e/specs/permission-system-removing-imported-account.spec.js @@ -1,6 +1,6 @@ 'use strict'; import TestHelpers from '../helpers'; - +import { Smoke } from '../tags'; import WalletView from '../pages/WalletView'; import ImportAccountView from '../pages/ImportAccountView'; import TabBarComponent from '../pages/TabBarComponent'; @@ -24,108 +24,110 @@ import { } from '../viewHelper'; const TEST_DAPP = 'https://metamask.github.io/test-dapp/'; -const GOERLI = 'Goerli Test Network'; +const SEPOLIA = 'Sepolia Test Network'; const accountPrivateKey = Accounts.getAccountPrivateKey(); - -describe('Permission System Test: Revoking accounts after connecting to a dapp', () => { - beforeEach(() => { - jest.setTimeout(150000); - }); - - it('should import wallet and go to the wallet view', async () => { - await importWalletWithRecoveryPhrase(); - }); - - it('should navigate to browser', async () => { - await TestHelpers.delay(2000); - await TabBarComponent.tapBrowser(); - await Browser.isVisible(); - }); - - it('should connect to the test dapp', async () => { - await TestHelpers.delay(3000); - await Browser.tapUrlInputBox(); - await Browser.navigateToURL(TEST_DAPP); - await TestHelpers.delay(3000); - await TestHelpers.tapAtPoint( - BROWSER_SCREEN_ID, - testDappConnectButtonCooridinates, - ); - await ConnectModal.isVisible(); - }); - - it('should go to multiconnect in the connect account modal', async () => { - await ConnectModal.tapConnectMultipleAccountsButton(); - }); - - it('should import account', async () => { - await ConnectModal.tapImportAccountButton(); - await ImportAccountView.isVisible(); - await ImportAccountView.enterPrivateKey(accountPrivateKey.keys); - await ImportAccountView.isImportSuccessSreenVisible(); - await ImportAccountView.tapCloseButtonOnImportSuccess(); - }); - - it('should connect multiple accounts to a dapp', async () => { - await ConnectModal.tapSelectAllButton(); - - await ConnectModal.tapAccountConnectMultiSelectButton(); - }); - - it('should switch to Goreli', async () => { - await Browser.tapNetworkAvatarButtonOnBrowser(); - await ConnectedAccountsModal.tapNetworksPicker(); - await NetworkListModal.changeNetwork(GOERLI); - }); - - it('should dismiss the network education modal', async () => { - await NetworkEducationModal.isVisible(); - await NetworkEducationModal.tapGotItButton(); - await NetworkEducationModal.isNotVisible(); - }); - - it('should set the imported account as primary account', async () => { - await TestHelpers.delay(1500); - await ConnectedAccountsModal.tapToSetAsPrimaryAccount(); - }); - - it('should submit a EIP1559 transaction ', async () => { - await TestHelpers.swipe(BROWSER_SCREEN_ID, 'up', 'slow', 0.1); - await TestHelpers.tapAtPoint( - BROWSER_SCREEN_ID, - testDappSendEIP1559ButtonCoordinates, - ); - - await TransactionConfirmationView.isBalanceVisible(); - await TestHelpers.tapByText('Confirm', 1); - await TransactionConfirmationView.isBalanceNotVisible(); - }); - - it('should navigate to wallet view', async () => { - await TabBarComponent.tapWallet(); - await WalletView.isVisible(); - }); - - it('should remove imported account', async () => { - // Wait for page to load - await WalletView.tapIdenticon(); - await AccountListView.isVisible(); - await AccountListView.longPressImportedAccount(); - await AccountListView.tapYesToRemoveImportedAccountAlertButton(); - await AccountListView.accountNameNotVisible('Account 2'); - }); - - it('should return to browser', async () => { - await AccountListView.swipeToDimssAccountsModal(); - await TabBarComponent.tapBrowser(); - // Check that we are on the browser screen - await Browser.isVisible(); - }); - - it('imported account is not visible', async () => { - await Browser.tapNetworkAvatarButtonOnBrowser(); - await ConnectedAccountsModal.isVisible(); - await AccountListView.accountNameNotVisible('Account 2'); - }); -}); +describe( + Smoke('Permission System Test: Revoking accounts after connecting to a dapp'), + () => { + beforeEach(() => { + jest.setTimeout(150000); + }); + + it('should import wallet and go to the wallet view', async () => { + await importWalletWithRecoveryPhrase(); + }); + + it('should navigate to browser', async () => { + await TestHelpers.delay(2000); + await TabBarComponent.tapBrowser(); + await Browser.isVisible(); + }); + + it('should connect to the test dapp', async () => { + await TestHelpers.delay(3000); + await Browser.tapUrlInputBox(); + await Browser.navigateToURL(TEST_DAPP); + await TestHelpers.delay(3000); + await TestHelpers.tapAtPoint( + BROWSER_SCREEN_ID, + testDappConnectButtonCooridinates, + ); + await ConnectModal.isVisible(); + }); + + it('should go to multiconnect in the connect account modal', async () => { + await ConnectModal.tapConnectMultipleAccountsButton(); + }); + + it('should import account', async () => { + await ConnectModal.tapImportAccountButton(); + await ImportAccountView.isVisible(); + await ImportAccountView.enterPrivateKey(accountPrivateKey.keys); + await ImportAccountView.isImportSuccessSreenVisible(); + await ImportAccountView.tapCloseButtonOnImportSuccess(); + }); + + it('should connect multiple accounts to a dapp', async () => { + await ConnectModal.tapSelectAllButton(); + + await ConnectModal.tapAccountConnectMultiSelectButton(); + }); + + it('should switch to Sepolia', async () => { + await Browser.tapNetworkAvatarButtonOnBrowser(); + await ConnectedAccountsModal.tapNetworksPicker(); + await NetworkListModal.changeNetwork(SEPOLIA); + }); + + it('should dismiss the network education modal', async () => { + await NetworkEducationModal.isVisible(); + await NetworkEducationModal.tapGotItButton(); + await NetworkEducationModal.isNotVisible(); + }); + + it('should set the imported account as primary account', async () => { + await TestHelpers.delay(1500); + await ConnectedAccountsModal.tapToSetAsPrimaryAccount(); + }); + + it('should submit a EIP1559 transaction ', async () => { + await TestHelpers.swipe(BROWSER_SCREEN_ID, 'up', 'slow', 0.1); + await TestHelpers.tapAtPoint( + BROWSER_SCREEN_ID, + testDappSendEIP1559ButtonCoordinates, + ); + + await TransactionConfirmationView.isBalanceVisible(); + await TestHelpers.tapByText('Confirm', 1); + await TransactionConfirmationView.isBalanceNotVisible(); + }); + + it('should navigate to wallet view', async () => { + await TabBarComponent.tapWallet(); + await WalletView.isVisible(); + }); + + it('should remove imported account', async () => { + // Wait for page to load + await WalletView.tapIdenticon(); + await AccountListView.isVisible(); + await AccountListView.longPressImportedAccount(); + await AccountListView.tapYesToRemoveImportedAccountAlertButton(); + await AccountListView.accountNameNotVisible('Account 2'); + }); + + it('should return to browser', async () => { + await AccountListView.swipeToDimssAccountsModal(); + await TabBarComponent.tapBrowser(); + // Check that we are on the browser screen + await Browser.isVisible(); + }); + + it('imported account is not visible', async () => { + await Browser.tapNetworkAvatarButtonOnBrowser(); + await ConnectedAccountsModal.isVisible(); + await AccountListView.accountNameNotVisible('Account 2'); + }); + }, +); diff --git a/e2e/specs/permission-system-revoke-single-account.spec.js b/e2e/specs/permission-system-revoke-single-account.spec.js index de02367ab41..7c6428fe043 100644 --- a/e2e/specs/permission-system-revoke-single-account.spec.js +++ b/e2e/specs/permission-system-revoke-single-account.spec.js @@ -1,5 +1,6 @@ 'use strict'; import TestHelpers from '../helpers'; +import { Regression } from '../tags'; import OnboardingView from '../pages/Onboarding/OnboardingView'; import OnboardingCarouselView from '../pages/Onboarding/OnboardingCarouselView'; @@ -29,7 +30,7 @@ import { const TEST_DAPP = 'https://metamask.github.io/test-dapp/'; const PASSWORD = '12345678'; -describe('Revoke Single Account after connecting to a dapp', () => { +describe(Regression('Revoke Single Account after connecting to a dapp'), () => { beforeEach(() => { jest.setTimeout(150000); }); diff --git a/e2e/specs/permission-system-revoking-multiple-accounts.spec.js b/e2e/specs/permission-system-revoking-multiple-accounts.spec.js index 28e13fd4772..6cf94b06f9c 100644 --- a/e2e/specs/permission-system-revoking-multiple-accounts.spec.js +++ b/e2e/specs/permission-system-revoking-multiple-accounts.spec.js @@ -1,5 +1,6 @@ 'use strict'; import TestHelpers from '../helpers'; +import { Regression } from '../tags'; import Browser from '../pages/Drawer/Browser'; import { BROWSER_SCREEN_ID } from '../../wdio/screen-objects/testIDs/BrowserScreen/BrowserScreen.testIds'; @@ -19,81 +20,86 @@ import { const SUSHI_SWAP = 'https://app.sushi.com/swap'; const TEST_DAPP = 'https://metamask.github.io/test-dapp/'; -describe('Connecting to multiple dapps and revoking permission on one but staying connected to the other', () => { - beforeEach(() => { - jest.setTimeout(150000); - }); - - it('should import wallet and go to the wallet view', async () => { - await importWalletWithRecoveryPhrase(); - }); - - it('should navigate to browser', async () => { - await TabBarComponent.tapBrowser(); - // Check that we are on the browser screen - await Browser.isVisible(); - }); - - it('should connect to sushi swap dapp', async () => { - await TestHelpers.delay(3000); - // Tap on search in bottom navbar - await Browser.tapUrlInputBox(); - await Browser.navigateToURL(SUSHI_SWAP); - await ConnectModal.isVisible(); - await ConnectModal.tapConnectButton(); - await Browser.isAccountToastVisible('Account 1'); - }); - - it('should go to the test dapp', async () => { - // Tap on search in bottom navbar - await Browser.tapOpenAllTabsButton(); - await Browser.tapOpenNewTabButton(); - await Browser.tapUrlInputBox(); - await Browser.navigateToURL(TEST_DAPP); - await Browser.waitForBrowserPageToLoad(); - await TestHelpers.tapAtPoint( - BROWSER_SCREEN_ID, - testDappConnectButtonCooridinates, - ); - await ConnectModal.isVisible(); - }); - - it('should go to multiconnect in the connect account modal', async () => { - await ConnectModal.tapConnectMultipleAccountsButton(); - }); - - it('should connect with multiple accounts', async () => { - // Wait for page to load - await ConnectModal.tapCreateAccountButton(); - await AccountListView.isNewAccountNameVisible(); - await AccountListView.tapAccountByName('Account 2'); - - await ConnectModal.tapAccountConnectMultiSelectButton(); - }); - - it('should revoke accounts', async () => { - await Browser.tapNetworkAvatarButtonOnBrowser(); - await ConnectedAccountsModal.tapPermissionsButton(); - await TestHelpers.delay(1500); - await ConnectedAccountsModal.tapRevokeAllButton(); - Browser.isRevokeAllAccountToastVisible(); - }); - - it('should no longer be connected to the test dapp', async () => { - await Browser.tapNetworkAvatarButtonOnBrowser(); - await ConnectedAccountsModal.isNotVisible(); - await NetworkListModal.tapNetworkListCloseIcon(); - }); - - it('should open sushi swap dapp', async () => { - // Wait for page to load - await Browser.tapOpenAllTabsButton(); - await TestHelpers.tapByText('app.sushi.com'); - }); - - it('should still be connected to sushi swap', async () => { - // Wait for page to load - await Browser.tapNetworkAvatarButtonOnBrowser(); - await ConnectedAccountsModal.isVisible(); - }); -}); +describe( + Regression( + 'Connecting to multiple dapps and revoking permission on one but staying connected to the other', + ), + () => { + beforeEach(() => { + jest.setTimeout(150000); + }); + + it('should import wallet and go to the wallet view', async () => { + await importWalletWithRecoveryPhrase(); + }); + + it('should navigate to browser', async () => { + await TabBarComponent.tapBrowser(); + // Check that we are on the browser screen + await Browser.isVisible(); + }); + + it('should connect to sushi swap dapp', async () => { + await TestHelpers.delay(3000); + // Tap on search in bottom navbar + await Browser.tapUrlInputBox(); + await Browser.navigateToURL(SUSHI_SWAP); + await ConnectModal.isVisible(); + await ConnectModal.tapConnectButton(); + await Browser.isAccountToastVisible('Account 1'); + }); + + it('should go to the test dapp', async () => { + // Tap on search in bottom navbar + await Browser.tapOpenAllTabsButton(); + await Browser.tapOpenNewTabButton(); + await Browser.tapUrlInputBox(); + await Browser.navigateToURL(TEST_DAPP); + await Browser.waitForBrowserPageToLoad(); + await TestHelpers.tapAtPoint( + BROWSER_SCREEN_ID, + testDappConnectButtonCooridinates, + ); + await ConnectModal.isVisible(); + }); + + it('should go to multiconnect in the connect account modal', async () => { + await ConnectModal.tapConnectMultipleAccountsButton(); + }); + + it('should connect with multiple accounts', async () => { + // Wait for page to load + await ConnectModal.tapCreateAccountButton(); + await AccountListView.isNewAccountNameVisible(); + await AccountListView.tapAccountByName('Account 2'); + + await ConnectModal.tapAccountConnectMultiSelectButton(); + }); + + it('should revoke accounts', async () => { + await Browser.tapNetworkAvatarButtonOnBrowser(); + await ConnectedAccountsModal.tapPermissionsButton(); + await TestHelpers.delay(1500); + await ConnectedAccountsModal.tapRevokeAllButton(); + Browser.isRevokeAllAccountToastVisible(); + }); + + it('should no longer be connected to the test dapp', async () => { + await Browser.tapNetworkAvatarButtonOnBrowser(); + await ConnectedAccountsModal.isNotVisible(); + await NetworkListModal.tapNetworkListCloseIcon(); + }); + + it('should open sushi swap dapp', async () => { + // Wait for page to load + await Browser.tapOpenAllTabsButton(); + await TestHelpers.tapByText('app.sushi.com'); + }); + + it('should still be connected to sushi swap', async () => { + // Wait for page to load + await Browser.tapNetworkAvatarButtonOnBrowser(); + await ConnectedAccountsModal.isVisible(); + }); + }, +); diff --git a/e2e/specs/request-token-flow.spec.js b/e2e/specs/request-token-flow.spec.js index 1c1a9416a9b..8e3a1bb10de 100644 --- a/e2e/specs/request-token-flow.spec.js +++ b/e2e/specs/request-token-flow.spec.js @@ -1,4 +1,6 @@ 'use strict'; +import { Smoke } from '../tags'; + import OnboardingView from '../pages/Onboarding/OnboardingView'; import OnboardingCarouselView from '../pages/Onboarding/OnboardingCarouselView'; import ProtectYourWalletView from '../pages/Onboarding/ProtectYourWalletView'; @@ -24,7 +26,7 @@ import { acceptTermOfUse } from '../viewHelper'; const SAI_CONTRACT_ADDRESS = '0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359'; const PASSWORD = '12345678'; -describe('Request Token Flow', () => { +describe(Smoke('Request Token Flow'), () => { beforeEach(() => { jest.setTimeout(150000); }); diff --git a/e2e/specs/send-ERC-token.spec.js b/e2e/specs/send-ERC-token.spec.js index ca3f7138f80..255c6d35b83 100644 --- a/e2e/specs/send-ERC-token.spec.js +++ b/e2e/specs/send-ERC-token.spec.js @@ -1,4 +1,6 @@ 'use strict'; +import { Smoke } from '../tags'; + import TestHelpers from '../helpers'; import WalletView from '../pages/WalletView'; @@ -16,7 +18,7 @@ const AVAX_URL = 'https://api.avax-test.network/ext/C/rpc'; const TOKEN_ADDRESS = '0x5425890298aed601595a70AB815c96711a31Bc65'; const SEND_ADDRESS = '0xebe6CcB6B55e1d094d9c58980Bc10Fed69932cAb'; -describe('Send ERC Token', () => { +describe(Smoke('Send ERC Token'), () => { beforeAll(async () => { await importWalletWithRecoveryPhrase(); }); diff --git a/e2e/specs/start-exploring.spec.js b/e2e/specs/start-exploring.spec.js index c40541fbaa2..ac4dcfbb04a 100644 --- a/e2e/specs/start-exploring.spec.js +++ b/e2e/specs/start-exploring.spec.js @@ -1,4 +1,5 @@ 'use strict'; +import { Smoke } from '../tags'; import TestHelpers from '../helpers'; @@ -21,7 +22,7 @@ import { acceptTermOfUse } from '../viewHelper'; const ACCOUNT = 'Test Account One'; const PASSWORD = '12345678'; -describe('Start Exploring', () => { +describe(Smoke('Start Exploring'), () => { beforeEach(() => { jest.setTimeout(150000); }); diff --git a/e2e/specs/wallet-tests.spec.js b/e2e/specs/wallet-tests.spec.js index 720a488461b..b65f3c51d59 100644 --- a/e2e/specs/wallet-tests.spec.js +++ b/e2e/specs/wallet-tests.spec.js @@ -1,22 +1,21 @@ 'use strict'; -import TestHelpers from '../helpers'; +import { Smoke } from '../tags'; +import TestHelpers from '../helpers'; import WalletView from '../pages/WalletView'; import AccountListView from '../pages/AccountListView'; import ImportAccountView from '../pages/ImportAccountView'; - import DrawerView from '../pages/Drawer/DrawerView'; - import AddCustomTokenView from '../pages/AddCustomTokenView'; import ImportTokensView from '../pages/ImportTokensView'; - import NetworkListModal from '../pages/modals/NetworkListModal'; import RequestPaymentModal from '../pages/modals/RequestPaymentModal'; import NetworkEducationModal from '../pages/modals/NetworkEducationModal'; import { importWalletWithRecoveryPhrase } from '../viewHelper'; import Accounts from '../../wdio/helpers/Accounts'; +import Collectibles from '../resources/collectibles.json'; -describe('Wallet Tests', () => { +describe(Smoke('Wallet Tests'), () => { const GOERLI = 'Goerli Test Network'; const ETHEREUM = 'Ethereum Main Network'; @@ -24,9 +23,7 @@ describe('Wallet Tests', () => { // I should NEVER hold any eth or token const TEST_PRIVATE_KEY = 'cbfd798afcfd1fd8ecc48cbecb6dc7e876543395640b758a90e11d986e758ad1'; - const COLLECTIBLE_CONTRACT_ADDRESS = - '0x306d717D109e0995e0f56027Eb93D9C1d5686dE1'; - const COLLECTIBLE_IDENTIFIER = '179'; + const BLT_TOKEN_ADDRESS = '0x107c4504cd79c5d2696ea0030a8dd4e92601b82e'; const validAccount = Accounts.getValidAccount(); @@ -86,6 +83,7 @@ describe('Wallet Tests', () => { await RequestPaymentModal.isPublicAddressCorrect(validAccount.address); await RequestPaymentModal.closeRequestModal(); + await WalletView.isVisible(); }); @@ -124,18 +122,18 @@ describe('Wallet Tests', () => { await WalletView.tapImportNFTButton(); await AddCustomTokenView.isVisible(); - await AddCustomTokenView.typeInNFTAddress(COLLECTIBLE_CONTRACT_ADDRESS); - await AddCustomTokenView.typeInNFTIdentifier(COLLECTIBLE_IDENTIFIER); + await AddCustomTokenView.typeInNFTAddress(Collectibles.erc1155tokenAddress); + await AddCustomTokenView.typeInNFTIdentifier(Collectibles.erc1155tokenID); await WalletView.isVisible(); // Wait for asset to load await TestHelpers.delay(3000); - await WalletView.isNFTVisibleInWallet('Refinable721'); - // Tap on Crypto Kitty - await WalletView.tapOnNFTInWallet('Refinable721'); + await WalletView.isNFTVisibleInWallet(Collectibles.erc1155collectionName); + // Tap on Collectible + await WalletView.tapOnNFTInWallet(Collectibles.erc1155collectionName); - await WalletView.isNFTNameVisible('Refinable721 #179'); + await WalletView.isNFTNameVisible(Collectibles.erc1155tokenName); await WalletView.scrollUpOnNFTsTab(); }); diff --git a/e2e/tags.js b/e2e/tags.js new file mode 100644 index 00000000000..7e95c4c8713 --- /dev/null +++ b/e2e/tags.js @@ -0,0 +1,8 @@ +const tags = { + regression: 'Regression', + smoke: 'Smoke', +}; +const Smoke = (testName) => `${tags.smoke} ${testName}`; +const Regression = (testName) => `${tags.regression} ${testName}`; + +export { Smoke, Regression }; diff --git a/ios/MetaMask.xcodeproj/project.pbxproj b/ios/MetaMask.xcodeproj/project.pbxproj index 9841bdbb271..e9423193bb2 100644 --- a/ios/MetaMask.xcodeproj/project.pbxproj +++ b/ios/MetaMask.xcodeproj/project.pbxproj @@ -1132,7 +1132,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMaskDebug.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 1100; + CURRENT_PROJECT_VERSION = 1104; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 48XVW22RCG; @@ -1168,7 +1168,7 @@ "\"$(SRCROOT)/MetaMask/System/Library/Frameworks\"", ); LLVM_LTO = YES; - MARKETING_VERSION = 6.4.0; + MARKETING_VERSION = 6.5.0; ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = ( "$(inherited)", @@ -1199,7 +1199,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMask.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 1100; + CURRENT_PROJECT_VERSION = 1104; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = 48XVW22RCG; ENABLE_BITCODE = NO; @@ -1235,7 +1235,7 @@ "\"$(SRCROOT)/MetaMask/System/Library/Frameworks\"", ); LLVM_LTO = YES; - MARKETING_VERSION = 6.4.0; + MARKETING_VERSION = 6.5.0; ONLY_ACTIVE_ARCH = NO; OTHER_CFLAGS = ( "$(inherited)", @@ -1345,7 +1345,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMaskDebug.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 1100; + CURRENT_PROJECT_VERSION = 1104; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 48XVW22RCG; @@ -1381,7 +1381,7 @@ "\"$(SRCROOT)/MetaMask/System/Library/Frameworks\"", ); LLVM_LTO = YES; - MARKETING_VERSION = 6.4.0; + MARKETING_VERSION = 6.5.0; ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = ( "$(inherited)", @@ -1412,7 +1412,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMask.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 1100; + CURRENT_PROJECT_VERSION = 1104; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = 48XVW22RCG; ENABLE_BITCODE = NO; @@ -1448,7 +1448,7 @@ "\"$(SRCROOT)/MetaMask/System/Library/Frameworks\"", ); LLVM_LTO = YES; - MARKETING_VERSION = 6.4.0; + MARKETING_VERSION = 6.5.0; ONLY_ACTIVE_ARCH = NO; OTHER_CFLAGS = ( "$(inherited)", diff --git a/locales/languages/de.json b/locales/languages/de.json index 3976bcec3e4..a63a3f79fa8 100644 --- a/locales/languages/de.json +++ b/locales/languages/de.json @@ -108,6 +108,37 @@ "content": "Suchen Sie nach Seiten oder geben Sie eine URL ein, wenn Sie wissen, wohin sie wollen." } }, + "onboarding_wizard_new": { + "coachmark": { + "action_back": "No thanks", + "action_next": "Take the tour", + "progress_next": "Got it" + }, + "step1": { + "title": "Welcome to your wallet!", + "content1": "On the blockchain, you need a wallet (and maybe some ETH). So let’s take a look at how to use your MetaMask wallet." + }, + "step2": { + "title": "Your accounts", + "content1": "This is your account and unique public address (0x...). Create more accounts by tapping the arrow icon." + }, + "step3": { + "title": "Managing your account", + "content1": "Edit your account name, view transactions on Etherscan, share your public key, and see your private key by tapping this icon" + }, + "step4": { + "title": "Using your wallet", + "content1": "Buy, send, swap, and receive assets by tapping this icon" + }, + "step5": { + "title": "Exploring web3", + "content1": "Open the browser by tapping this icon" + }, + "step6": { + "title": "Using the browser", + "content1": "Search for sites by keyword or enter a URL. Have fun out there! " + } + }, "create_wallet": { "title": "Erstellen Ihres Wallets ...", "subtitle": "Das sollte nicht lang dauern" @@ -800,7 +831,30 @@ "buy_description": "Krypto mit Bargeld kaufen", "swap_description": "Zwischen Tokens tauschen", "send_description": "Krypto an ein beliebiges Konto senden", - "receive_description": "Krypto erhalten" + "receive_description": "Krypto erhalten", + "chart_time_period": { + "1d": "Today", + "7d": "Past 7 days", + "1w": "Past week", + "1m": "Past month", + "3m": "Past 3 months", + "1y": "Past year", + "3y": "Past 3 years" + }, + "chart_time_period_navigation": { + "1d": "1D", + "7d": "7D", + "1w": "1W", + "1m": "1M", + "3m": "3M", + "1y": "1Y", + "3y": "3Y" + }, + "your_balance": "Your balance", + "unable_to_load_balance": "Unable to load your balance", + "about": "About", + "activity": "{{symbol}} activity", + "disclaimer": "Market data is provided by one or more third-party data sources, including CoinGecko. Such third-party content is provided solely for informational purposes and should not be treated as advice to buy, sell, or use any particular asset. MetaMask does not suggest the use of this content for any particular purpose and is not responsible for its accuracy." }, "account_details": { "title": "Kontodetails", @@ -1222,7 +1276,6 @@ "add_other_network_here": "hier entdecken.", "you_can": "Sie können aber auch", "add_network": "weitere Netzwerke manuell hinzufügen.", - "deprecated_network_msg": "Aufgrund der Protokolländerungen von Ethereum: Rinkeby, Ropsten, Kovan funktionieren die Testnetzwerke möglicherweise nicht mehr so zuverlässig und werden bald veraltet sein.", "select_network": "Netzwerk wählen" }, "select": { @@ -1788,6 +1841,7 @@ "webview_received_error": "WebView erhielt Fehler-Statuscode: {{code}}", "no_tokens_available_title": "Keine Token verfügbar", "no_tokens_available": "Derzeit gibt es keine Kryptowährungen, die in {{network}} in der {{region}} gekauft werden können.", + "this_network": "this network", "change_payment_method": "Zahlungsmethode ändern", "try_different_region": "Andere Region ausprobieren", "return_home": "Zur Startseite zurückkehren", diff --git a/locales/languages/el.json b/locales/languages/el.json index 653d45f41e5..e39461b364c 100644 --- a/locales/languages/el.json +++ b/locales/languages/el.json @@ -108,6 +108,37 @@ "content": "Ψάξτε για ιστοσελίδες ή πληκτρολογήστε ένα URL εάν γνωρίζετε τον προορισμό σας." } }, + "onboarding_wizard_new": { + "coachmark": { + "action_back": "No thanks", + "action_next": "Take the tour", + "progress_next": "Got it" + }, + "step1": { + "title": "Welcome to your wallet!", + "content1": "On the blockchain, you need a wallet (and maybe some ETH). So let’s take a look at how to use your MetaMask wallet." + }, + "step2": { + "title": "Your accounts", + "content1": "This is your account and unique public address (0x...). Create more accounts by tapping the arrow icon." + }, + "step3": { + "title": "Managing your account", + "content1": "Edit your account name, view transactions on Etherscan, share your public key, and see your private key by tapping this icon" + }, + "step4": { + "title": "Using your wallet", + "content1": "Buy, send, swap, and receive assets by tapping this icon" + }, + "step5": { + "title": "Exploring web3", + "content1": "Open the browser by tapping this icon" + }, + "step6": { + "title": "Using the browser", + "content1": "Search for sites by keyword or enter a URL. Have fun out there! " + } + }, "create_wallet": { "title": "Δημιουργούμε το πορτοφόλι σας...", "subtitle": "Δεν θα πάρει πολύ" @@ -800,7 +831,30 @@ "buy_description": "Αγοράστε κρυπτονομίσματα με μετρητά", "swap_description": "Ανταλλαγή μεταξύ tokens", "send_description": "Στείλτε κρυπτονομίσματα σε οποιονδήποτε λογαριασμό", - "receive_description": "Λάβετε κρυπτονομίσματα" + "receive_description": "Λάβετε κρυπτονομίσματα", + "chart_time_period": { + "1d": "Today", + "7d": "Past 7 days", + "1w": "Past week", + "1m": "Past month", + "3m": "Past 3 months", + "1y": "Past year", + "3y": "Past 3 years" + }, + "chart_time_period_navigation": { + "1d": "1D", + "7d": "7D", + "1w": "1W", + "1m": "1M", + "3m": "3M", + "1y": "1Y", + "3y": "3Y" + }, + "your_balance": "Your balance", + "unable_to_load_balance": "Unable to load your balance", + "about": "About", + "activity": "{{symbol}} activity", + "disclaimer": "Market data is provided by one or more third-party data sources, including CoinGecko. Such third-party content is provided solely for informational purposes and should not be treated as advice to buy, sell, or use any particular asset. MetaMask does not suggest the use of this content for any particular purpose and is not responsible for its accuracy." }, "account_details": { "title": "Λεπτομέρειες Λογαριασμού", @@ -1222,7 +1276,6 @@ "add_other_network_here": "εδώ.", "you_can": "Ή μπορείτε", "add_network": "να προσθέσετε περισσότερα δίκτυα χειροκίνητα.", - "deprecated_network_msg": "Λόγω των αλλαγών στο πρωτόκολλο του Ethereum: τα δοκιμαστικά δίκτυα Rinkeby, Ropsten, Kovan μπορεί να μη λειτουργούν και τόσο αξιόπιστα και θα καταργηθούν σύντομα.", "select_network": "Επιλέξτε ένα δίκτυο" }, "select": { @@ -1788,6 +1841,7 @@ "webview_received_error": "Το WebView έλαβε έναν κωδικό κατάστασης σφάλματος: {{code}}", "no_tokens_available_title": "Κανένα διαθέσιμο Token", "no_tokens_available": "Δεν υπάρχουν προς το παρόν διαθέσιμα token για αγορά στο {{network}} με την επιλεγμένη μέθοδο πληρωμής.", + "this_network": "this network", "change_payment_method": "Αλλάξτε μέθοδο πληρωμής", "try_different_region": "Δοκιμάστε μια άλλη περιοχή", "return_home": "Επιστροφή στην Αρχική Σελίδα", diff --git a/locales/languages/en.json b/locales/languages/en.json index 6a86ee45a33..c257e403365 100644 --- a/locales/languages/en.json +++ b/locales/languages/en.json @@ -1841,6 +1841,7 @@ "webview_received_error": "WebView received error status code: {{code}}", "no_tokens_available_title": "No Tokens Available", "no_tokens_available": "There are currently no tokens available to purchase on {{network}} with the selected payment method.", + "this_network": "this network", "change_payment_method": "Change payment method", "try_different_region": "Try a different region", "return_home": "Return to Home Screen", diff --git a/locales/languages/es.json b/locales/languages/es.json index ba643aac79b..05433e6628a 100644 --- a/locales/languages/es.json +++ b/locales/languages/es.json @@ -108,6 +108,37 @@ "content": "Busque los sitios o escriba una dirección URL si sabe adónde va." } }, + "onboarding_wizard_new": { + "coachmark": { + "action_back": "No thanks", + "action_next": "Take the tour", + "progress_next": "Got it" + }, + "step1": { + "title": "Welcome to your wallet!", + "content1": "On the blockchain, you need a wallet (and maybe some ETH). So let’s take a look at how to use your MetaMask wallet." + }, + "step2": { + "title": "Your accounts", + "content1": "This is your account and unique public address (0x...). Create more accounts by tapping the arrow icon." + }, + "step3": { + "title": "Managing your account", + "content1": "Edit your account name, view transactions on Etherscan, share your public key, and see your private key by tapping this icon" + }, + "step4": { + "title": "Using your wallet", + "content1": "Buy, send, swap, and receive assets by tapping this icon" + }, + "step5": { + "title": "Exploring web3", + "content1": "Open the browser by tapping this icon" + }, + "step6": { + "title": "Using the browser", + "content1": "Search for sites by keyword or enter a URL. Have fun out there! " + } + }, "create_wallet": { "title": "Creando su cartera…", "subtitle": "Este proceso no debería tardar mucho" @@ -800,7 +831,30 @@ "buy_description": "Comprar criptomonedas con efectivo", "swap_description": "Intercambiar entre tokens", "send_description": "Enviar criptomonedas a cualquier cuenta", - "receive_description": "Recibir criptomonedas" + "receive_description": "Recibir criptomonedas", + "chart_time_period": { + "1d": "Today", + "7d": "Past 7 days", + "1w": "Past week", + "1m": "Past month", + "3m": "Past 3 months", + "1y": "Past year", + "3y": "Past 3 years" + }, + "chart_time_period_navigation": { + "1d": "1D", + "7d": "7D", + "1w": "1W", + "1m": "1M", + "3m": "3M", + "1y": "1Y", + "3y": "3Y" + }, + "your_balance": "Your balance", + "unable_to_load_balance": "Unable to load your balance", + "about": "About", + "activity": "{{symbol}} activity", + "disclaimer": "Market data is provided by one or more third-party data sources, including CoinGecko. Such third-party content is provided solely for informational purposes and should not be treated as advice to buy, sell, or use any particular asset. MetaMask does not suggest the use of this content for any particular purpose and is not responsible for its accuracy." }, "account_details": { "title": "Detalles de la cuenta", @@ -874,7 +928,7 @@ "gas_fee_average": "PROMEDIO", "gas_fee_slow": "LENTO", "hex_data": "Datos hexadecimales", - "custom_nonce": "Mientras tanto", + "custom_nonce": "Nonce", "this_is_an_advanced": "Esta es una función avanzada que se usa para cancelar o acelerar transacciones pendientes.", "current_suggested_nonce": "Nonce actual sugerido:", "edit_transaction_nonce": "Editar nonce de transacción", @@ -1143,7 +1197,7 @@ "address_from_balance": "Saldo:", "status": "Estado", "date": "Fecha", - "nonce": "Mientras tanto", + "nonce": "Nonce", "from_device_label": "de este dispositivo", "import_wallet_row": "Cuenta agregada a este dispositivo", "import_wallet_label": "Cuenta agregada", @@ -1222,7 +1276,6 @@ "add_other_network_here": "aquí.", "you_can": "O puede", "add_network": "agregar más redes manualmente.", - "deprecated_network_msg": "Debido a los cambios de protocolo de Ethereum: es posible que las redes de prueba de Rinkeby, Ropsten y Kovan no funcionen de manera tan confiable y queden obsoletas pronto.", "select_network": "Seleccionar una red" }, "select": { @@ -1788,6 +1841,7 @@ "webview_received_error": "WebView recibió un código de estado de error: {{code}}", "no_tokens_available_title": "No hay tokens disponibles", "no_tokens_available": "En este momento no hay tokens disponibles para comprar en {{network}} con el método de pago seleccionado.", + "this_network": "this network", "change_payment_method": "Cambiar el método de pago", "try_different_region": "Pruebe una región distinta", "return_home": "Volver a la pantalla de inicio", @@ -2143,7 +2197,7 @@ "aggressive": "Agresivo", "low_fee_warning": "Tome nota de su tiempo de procesamiento. Las transacciones futuras se pondrán en la cola después de esta.", "edit_priority": "Editar prioridad", - "speed_up_transaction": "Agilizar transacción", + "speed_up_transaction": "Acelerar transacción", "cancel_transaction": "Cancelar transacción", "new_gas_fee": "Nueva tarifa de gas", "edit_suggested_gas_fee": "Editar tarifa de gas sugerida", diff --git a/locales/languages/fr.json b/locales/languages/fr.json index b38fad43b03..9015a658a83 100644 --- a/locales/languages/fr.json +++ b/locales/languages/fr.json @@ -108,6 +108,37 @@ "content": "Recherchez des sites, ou saisissez une URL si vous connaissez l’adresse." } }, + "onboarding_wizard_new": { + "coachmark": { + "action_back": "No thanks", + "action_next": "Take the tour", + "progress_next": "Got it" + }, + "step1": { + "title": "Welcome to your wallet!", + "content1": "On the blockchain, you need a wallet (and maybe some ETH). So let’s take a look at how to use your MetaMask wallet." + }, + "step2": { + "title": "Your accounts", + "content1": "This is your account and unique public address (0x...). Create more accounts by tapping the arrow icon." + }, + "step3": { + "title": "Managing your account", + "content1": "Edit your account name, view transactions on Etherscan, share your public key, and see your private key by tapping this icon" + }, + "step4": { + "title": "Using your wallet", + "content1": "Buy, send, swap, and receive assets by tapping this icon" + }, + "step5": { + "title": "Exploring web3", + "content1": "Open the browser by tapping this icon" + }, + "step6": { + "title": "Using the browser", + "content1": "Search for sites by keyword or enter a URL. Have fun out there! " + } + }, "create_wallet": { "title": "Création de votre portefeuille…", "subtitle": "Cela ne devrait prendre que quelques instants." @@ -800,7 +831,30 @@ "buy_description": "Acheter des crypto-actifs en payant en espèces", "swap_description": "Échange de jetons", "send_description": "Envoyer des crypto-actifs vers n’importe quel compte", - "receive_description": "Recevoir des crypto-actifs" + "receive_description": "Recevoir des crypto-actifs", + "chart_time_period": { + "1d": "Today", + "7d": "Past 7 days", + "1w": "Past week", + "1m": "Past month", + "3m": "Past 3 months", + "1y": "Past year", + "3y": "Past 3 years" + }, + "chart_time_period_navigation": { + "1d": "1D", + "7d": "7D", + "1w": "1W", + "1m": "1M", + "3m": "3M", + "1y": "1Y", + "3y": "3Y" + }, + "your_balance": "Your balance", + "unable_to_load_balance": "Unable to load your balance", + "about": "About", + "activity": "{{symbol}} activity", + "disclaimer": "Market data is provided by one or more third-party data sources, including CoinGecko. Such third-party content is provided solely for informational purposes and should not be treated as advice to buy, sell, or use any particular asset. MetaMask does not suggest the use of this content for any particular purpose and is not responsible for its accuracy." }, "account_details": { "title": "Détails du compte", @@ -1222,7 +1276,6 @@ "add_other_network_here": "ici.", "you_can": "Ou vous pouvez", "add_network": "ajouter manuellement d’autres réseaux.", - "deprecated_network_msg": "En raison des changements apportés au protocole d’Ethereum, les réseaux testnet Rinkeby, Ropsten et Kovan peuvent ne pas fonctionner d’une manière aussi fiable qu’auparavant et deviendront bientôt obsolètes.", "select_network": "Sélectionner un réseau" }, "select": { @@ -1788,6 +1841,7 @@ "webview_received_error": "WebView a reçu le code d’erreur : {{code}}", "no_tokens_available_title": "Aucun jeton disponible", "no_tokens_available": "Il n'y a actuellement aucun jeton que vous pouvez acheter sur {{network}} en utilisant le moyen de paiement sélectionné.", + "this_network": "this network", "change_payment_method": "Changer de mode de paiement", "try_different_region": "Essayez une autre région", "return_home": "Retour à l’écran d’accueil", diff --git a/locales/languages/hi.json b/locales/languages/hi.json index 4a8f1d9eb93..9b287b2b77f 100644 --- a/locales/languages/hi.json +++ b/locales/languages/hi.json @@ -108,6 +108,37 @@ "content": "अगर आप जानते हैं कि आप कहां जा रहे हैं, साइट को खोजें, या कोई URL टाइप करें।" } }, + "onboarding_wizard_new": { + "coachmark": { + "action_back": "No thanks", + "action_next": "Take the tour", + "progress_next": "Got it" + }, + "step1": { + "title": "Welcome to your wallet!", + "content1": "On the blockchain, you need a wallet (and maybe some ETH). So let’s take a look at how to use your MetaMask wallet." + }, + "step2": { + "title": "Your accounts", + "content1": "This is your account and unique public address (0x...). Create more accounts by tapping the arrow icon." + }, + "step3": { + "title": "Managing your account", + "content1": "Edit your account name, view transactions on Etherscan, share your public key, and see your private key by tapping this icon" + }, + "step4": { + "title": "Using your wallet", + "content1": "Buy, send, swap, and receive assets by tapping this icon" + }, + "step5": { + "title": "Exploring web3", + "content1": "Open the browser by tapping this icon" + }, + "step6": { + "title": "Using the browser", + "content1": "Search for sites by keyword or enter a URL. Have fun out there! " + } + }, "create_wallet": { "title": "आपका वॉलेट बनाया जा रहा है...", "subtitle": "इसमें ज्यादा समय नहीं लगना चाहिए" @@ -800,7 +831,30 @@ "buy_description": "नकद के साथ क्रिप्टो खरीदें", "swap_description": "टोकन के बीच विनिमय", "send_description": "किसी भी खाते में क्रिप्टो भेजें", - "receive_description": "क्रिप्टो प्राप्त करें" + "receive_description": "क्रिप्टो प्राप्त करें", + "chart_time_period": { + "1d": "Today", + "7d": "Past 7 days", + "1w": "Past week", + "1m": "Past month", + "3m": "Past 3 months", + "1y": "Past year", + "3y": "Past 3 years" + }, + "chart_time_period_navigation": { + "1d": "1D", + "7d": "7D", + "1w": "1W", + "1m": "1M", + "3m": "3M", + "1y": "1Y", + "3y": "3Y" + }, + "your_balance": "Your balance", + "unable_to_load_balance": "Unable to load your balance", + "about": "About", + "activity": "{{symbol}} activity", + "disclaimer": "Market data is provided by one or more third-party data sources, including CoinGecko. Such third-party content is provided solely for informational purposes and should not be treated as advice to buy, sell, or use any particular asset. MetaMask does not suggest the use of this content for any particular purpose and is not responsible for its accuracy." }, "account_details": { "title": "अकाउंट का विवरण", @@ -1222,7 +1276,6 @@ "add_other_network_here": "यहां।", "you_can": "या आप", "add_network": "मैन्युअल रूप से अधिक नेटवर्क जोड़ें।", - "deprecated_network_msg": "Ethereum प्रोटोकॉल परिवर्तनों के कारण: Rinkeby, Ropsten, Kovan टेस्ट नेटवर्क मज़बूती से काम करने में असमर्थ हो सकते हैं और जल्द ही अप्रचलित हो जाएंगे।", "select_network": "एक नेटवर्क चुनें" }, "select": { @@ -1788,6 +1841,7 @@ "webview_received_error": "WebView को त्रुटि का स्टेटस कोड प्राप्त हुआ: {{code}}", "no_tokens_available_title": "कोई टोकन उपलब्ध नहीं है", "no_tokens_available": "चयनित भुगतान विधि के साथ {{network}} पर खरीदने के लिए फिलहाल कोई टोकन उपलब्ध नहीं हैं।", + "this_network": "this network", "change_payment_method": "भुगतान का तरीका बदलें", "try_different_region": "कोई दूसरा क्षेत्र आज़माएं", "return_home": "होम स्क्रीन पर लौटें", diff --git a/locales/languages/id.json b/locales/languages/id.json index 5d4ec70976b..e8e6605af7d 100644 --- a/locales/languages/id.json +++ b/locales/languages/id.json @@ -108,6 +108,37 @@ "content": "Telusuri situs, atau ketikkan URL jika Anda mengetahui tujuan Anda." } }, + "onboarding_wizard_new": { + "coachmark": { + "action_back": "No thanks", + "action_next": "Take the tour", + "progress_next": "Got it" + }, + "step1": { + "title": "Welcome to your wallet!", + "content1": "On the blockchain, you need a wallet (and maybe some ETH). So let’s take a look at how to use your MetaMask wallet." + }, + "step2": { + "title": "Your accounts", + "content1": "This is your account and unique public address (0x...). Create more accounts by tapping the arrow icon." + }, + "step3": { + "title": "Managing your account", + "content1": "Edit your account name, view transactions on Etherscan, share your public key, and see your private key by tapping this icon" + }, + "step4": { + "title": "Using your wallet", + "content1": "Buy, send, swap, and receive assets by tapping this icon" + }, + "step5": { + "title": "Exploring web3", + "content1": "Open the browser by tapping this icon" + }, + "step6": { + "title": "Using the browser", + "content1": "Search for sites by keyword or enter a URL. Have fun out there! " + } + }, "create_wallet": { "title": "Membuat dompet Anda...", "subtitle": "Tidak perlu menunggu lama" @@ -800,7 +831,30 @@ "buy_description": "Beli kripto dengan uang tunai", "swap_description": "Pertukaran antar token", "send_description": "Kirim kripto ke akun mana pun", - "receive_description": "Terima kripto" + "receive_description": "Terima kripto", + "chart_time_period": { + "1d": "Today", + "7d": "Past 7 days", + "1w": "Past week", + "1m": "Past month", + "3m": "Past 3 months", + "1y": "Past year", + "3y": "Past 3 years" + }, + "chart_time_period_navigation": { + "1d": "1D", + "7d": "7D", + "1w": "1W", + "1m": "1M", + "3m": "3M", + "1y": "1Y", + "3y": "3Y" + }, + "your_balance": "Your balance", + "unable_to_load_balance": "Unable to load your balance", + "about": "About", + "activity": "{{symbol}} activity", + "disclaimer": "Market data is provided by one or more third-party data sources, including CoinGecko. Such third-party content is provided solely for informational purposes and should not be treated as advice to buy, sell, or use any particular asset. MetaMask does not suggest the use of this content for any particular purpose and is not responsible for its accuracy." }, "account_details": { "title": "Detail Akun", @@ -1222,7 +1276,6 @@ "add_other_network_here": "di sini.", "you_can": "Atau Anda dapat", "add_network": "menambahkan lebih banyak jaringan secara manual.", - "deprecated_network_msg": "Sehubungan dengan perubahan protokol Ethereum: jaringan uji Rinkeby, Ropsten, Kovan mungkin tidak dapat beroperasi dengan baik dan akan segera dihentikan.", "select_network": "Pilih jaringan" }, "select": { @@ -1788,6 +1841,7 @@ "webview_received_error": "WebView menerima kode status galat: {{code}}", "no_tokens_available_title": "Token Tidak Tersedia", "no_tokens_available": "Saat ini tidak ada token yang tersedia untuk dibeli di {{network}} dengan metode pembayaran yang dipilih.", + "this_network": "this network", "change_payment_method": "Ubah metode pembayaran", "try_different_region": "Coba wilayah lain", "return_home": "Kembali ke Layar Beranda", diff --git a/locales/languages/ja.json b/locales/languages/ja.json index d4c4842e59e..a23127bbf42 100644 --- a/locales/languages/ja.json +++ b/locales/languages/ja.json @@ -108,6 +108,37 @@ "content": "サイトを検索するか、アクセス先がわかっている場合はURLを入力します。" } }, + "onboarding_wizard_new": { + "coachmark": { + "action_back": "No thanks", + "action_next": "Take the tour", + "progress_next": "Got it" + }, + "step1": { + "title": "Welcome to your wallet!", + "content1": "On the blockchain, you need a wallet (and maybe some ETH). So let’s take a look at how to use your MetaMask wallet." + }, + "step2": { + "title": "Your accounts", + "content1": "This is your account and unique public address (0x...). Create more accounts by tapping the arrow icon." + }, + "step3": { + "title": "Managing your account", + "content1": "Edit your account name, view transactions on Etherscan, share your public key, and see your private key by tapping this icon" + }, + "step4": { + "title": "Using your wallet", + "content1": "Buy, send, swap, and receive assets by tapping this icon" + }, + "step5": { + "title": "Exploring web3", + "content1": "Open the browser by tapping this icon" + }, + "step6": { + "title": "Using the browser", + "content1": "Search for sites by keyword or enter a URL. Have fun out there! " + } + }, "create_wallet": { "title": "ウォレットを作成中...", "subtitle": "少しだけお待ちください" @@ -800,7 +831,30 @@ "buy_description": "現金で仮想通貨を購入します", "swap_description": "トークン同士を交換します", "send_description": "仮想通貨を任意のアカウントに送金します", - "receive_description": "仮想通貨を受け取ります" + "receive_description": "仮想通貨を受け取ります", + "chart_time_period": { + "1d": "Today", + "7d": "Past 7 days", + "1w": "Past week", + "1m": "Past month", + "3m": "Past 3 months", + "1y": "Past year", + "3y": "Past 3 years" + }, + "chart_time_period_navigation": { + "1d": "1D", + "7d": "7D", + "1w": "1W", + "1m": "1M", + "3m": "3M", + "1y": "1Y", + "3y": "3Y" + }, + "your_balance": "Your balance", + "unable_to_load_balance": "Unable to load your balance", + "about": "About", + "activity": "{{symbol}} activity", + "disclaimer": "Market data is provided by one or more third-party data sources, including CoinGecko. Such third-party content is provided solely for informational purposes and should not be treated as advice to buy, sell, or use any particular asset. MetaMask does not suggest the use of this content for any particular purpose and is not responsible for its accuracy." }, "account_details": { "title": "アカウント詳細", @@ -1222,7 +1276,6 @@ "add_other_network_here": "こちらから検出できます。", "you_can": "または", "add_network": "他のネットワークを手動で追加できます。", - "deprecated_network_msg": "Ethereum のプロトコル変更のため: Rinkeby、Ropsten、Kovan テストネットワークは動作が安定しない可能性があり、近いうちに非推奨になります。", "select_network": "ネットワークを選択" }, "select": { @@ -1788,6 +1841,7 @@ "webview_received_error": "WebView がエラーステータスコード {{code}} を受信しました", "no_tokens_available_title": "利用可能なトークンがありません", "no_tokens_available": "現在{{network}}に選択した支払方法で購入可能なトークンがありません。", + "this_network": "this network", "change_payment_method": "支払方法を変更", "try_different_region": "他の地域を試す", "return_home": "ホーム画面に戻る", diff --git a/locales/languages/ko.json b/locales/languages/ko.json index d2bf1697365..44b689372f2 100644 --- a/locales/languages/ko.json +++ b/locales/languages/ko.json @@ -108,6 +108,37 @@ "content": "사이트를 검색하거나 URL을 입력하세요." } }, + "onboarding_wizard_new": { + "coachmark": { + "action_back": "No thanks", + "action_next": "Take the tour", + "progress_next": "Got it" + }, + "step1": { + "title": "Welcome to your wallet!", + "content1": "On the blockchain, you need a wallet (and maybe some ETH). So let’s take a look at how to use your MetaMask wallet." + }, + "step2": { + "title": "Your accounts", + "content1": "This is your account and unique public address (0x...). Create more accounts by tapping the arrow icon." + }, + "step3": { + "title": "Managing your account", + "content1": "Edit your account name, view transactions on Etherscan, share your public key, and see your private key by tapping this icon" + }, + "step4": { + "title": "Using your wallet", + "content1": "Buy, send, swap, and receive assets by tapping this icon" + }, + "step5": { + "title": "Exploring web3", + "content1": "Open the browser by tapping this icon" + }, + "step6": { + "title": "Using the browser", + "content1": "Search for sites by keyword or enter a URL. Have fun out there! " + } + }, "create_wallet": { "title": "지갑 생성 중...", "subtitle": "오래 걸리지 않을 것입니다" @@ -800,7 +831,30 @@ "buy_description": "현금으로 암호화폐 구입", "swap_description": "토큰 간 교환", "send_description": "원하는 계정에 암호화폐 보내기", - "receive_description": "암호화폐 수령" + "receive_description": "암호화폐 수령", + "chart_time_period": { + "1d": "Today", + "7d": "Past 7 days", + "1w": "Past week", + "1m": "Past month", + "3m": "Past 3 months", + "1y": "Past year", + "3y": "Past 3 years" + }, + "chart_time_period_navigation": { + "1d": "1D", + "7d": "7D", + "1w": "1W", + "1m": "1M", + "3m": "3M", + "1y": "1Y", + "3y": "3Y" + }, + "your_balance": "Your balance", + "unable_to_load_balance": "Unable to load your balance", + "about": "About", + "activity": "{{symbol}} activity", + "disclaimer": "Market data is provided by one or more third-party data sources, including CoinGecko. Such third-party content is provided solely for informational purposes and should not be treated as advice to buy, sell, or use any particular asset. MetaMask does not suggest the use of this content for any particular purpose and is not responsible for its accuracy." }, "account_details": { "title": "계정 상세 내역", @@ -1222,7 +1276,6 @@ "add_other_network_here": "여기에서 확인하세요.", "you_can": "또는 다음을 확인하세요:", "add_network": "네트워크를 직접 추가할 수도 있습니다.", - "deprecated_network_msg": "이더리움 프로토콜 변경으로 인해 Rinkeby, Ropsten, Kovan 테스트 네트워크가 안정적으로 작동하지 않을 수 있습니다. 해당 네트워크는 곧 사용이 중단될 예정입니다.", "select_network": "네트워크 선택" }, "select": { @@ -1788,6 +1841,7 @@ "webview_received_error": "WebView 수신 오류 코드: {{code}}", "no_tokens_available_title": "사용 가능한 토큰 없음", "no_tokens_available": "현재 {{network}}에서 선택한 결제 방식으로 구매할 수 있는 토큰이 없습니다.", + "this_network": "this network", "change_payment_method": "결제 방법 변경", "try_different_region": "다른 지역을 시도하세요", "return_home": "홈 화면으로 돌아가기", diff --git a/locales/languages/pt.json b/locales/languages/pt.json index c21db3fb14c..362ba92dc75 100644 --- a/locales/languages/pt.json +++ b/locales/languages/pt.json @@ -108,6 +108,37 @@ "content": "Pesquise por sites ou digite um URL caso saiba para onde quer ir." } }, + "onboarding_wizard_new": { + "coachmark": { + "action_back": "No thanks", + "action_next": "Take the tour", + "progress_next": "Got it" + }, + "step1": { + "title": "Welcome to your wallet!", + "content1": "On the blockchain, you need a wallet (and maybe some ETH). So let’s take a look at how to use your MetaMask wallet." + }, + "step2": { + "title": "Your accounts", + "content1": "This is your account and unique public address (0x...). Create more accounts by tapping the arrow icon." + }, + "step3": { + "title": "Managing your account", + "content1": "Edit your account name, view transactions on Etherscan, share your public key, and see your private key by tapping this icon" + }, + "step4": { + "title": "Using your wallet", + "content1": "Buy, send, swap, and receive assets by tapping this icon" + }, + "step5": { + "title": "Exploring web3", + "content1": "Open the browser by tapping this icon" + }, + "step6": { + "title": "Using the browser", + "content1": "Search for sites by keyword or enter a URL. Have fun out there! " + } + }, "create_wallet": { "title": "Criando sua carteira...", "subtitle": "Não deve demorar muito" @@ -800,7 +831,30 @@ "buy_description": "Compre criptomoedas com dinheiro", "swap_description": "Faça câmbio entre tokens", "send_description": "Envie criptomoedas para qualquer conta", - "receive_description": "Receba criptomoedas" + "receive_description": "Receba criptomoedas", + "chart_time_period": { + "1d": "Today", + "7d": "Past 7 days", + "1w": "Past week", + "1m": "Past month", + "3m": "Past 3 months", + "1y": "Past year", + "3y": "Past 3 years" + }, + "chart_time_period_navigation": { + "1d": "1D", + "7d": "7D", + "1w": "1W", + "1m": "1M", + "3m": "3M", + "1y": "1Y", + "3y": "3Y" + }, + "your_balance": "Your balance", + "unable_to_load_balance": "Unable to load your balance", + "about": "About", + "activity": "{{symbol}} activity", + "disclaimer": "Market data is provided by one or more third-party data sources, including CoinGecko. Such third-party content is provided solely for informational purposes and should not be treated as advice to buy, sell, or use any particular asset. MetaMask does not suggest the use of this content for any particular purpose and is not responsible for its accuracy." }, "account_details": { "title": "Detalhes da conta", @@ -1222,7 +1276,6 @@ "add_other_network_here": "aqui.", "you_can": "Ou você pode", "add_network": "adicionar mais redes manualmente.", - "deprecated_network_msg": "Devido às mudanças de protocolo do Ethereum, as redes de teste Rinkeby, Ropsten e Kovan podem não funcionar com a mesma confiança e serão descontinuadas em breve.", "select_network": "Selecione uma rede" }, "select": { @@ -1788,6 +1841,7 @@ "webview_received_error": "O WebView recebeu o código de status de erro: {{code}}", "no_tokens_available_title": "Nenhum token disponível", "no_tokens_available": "No momento, não há tokens disponíveis para compra em {{network}} com a forma de pagamento selecionada.", + "this_network": "this network", "change_payment_method": "Alterar método de pagamento", "try_different_region": "Tente uma região diferente", "return_home": "Voltar à tela inicial", diff --git a/locales/languages/ru.json b/locales/languages/ru.json index 68b01963476..4a239f941ef 100644 --- a/locales/languages/ru.json +++ b/locales/languages/ru.json @@ -108,6 +108,37 @@ "content": "Найдите сайты или введите URL-адрес, если знаете, куда направляетесь." } }, + "onboarding_wizard_new": { + "coachmark": { + "action_back": "No thanks", + "action_next": "Take the tour", + "progress_next": "Got it" + }, + "step1": { + "title": "Welcome to your wallet!", + "content1": "On the blockchain, you need a wallet (and maybe some ETH). So let’s take a look at how to use your MetaMask wallet." + }, + "step2": { + "title": "Your accounts", + "content1": "This is your account and unique public address (0x...). Create more accounts by tapping the arrow icon." + }, + "step3": { + "title": "Managing your account", + "content1": "Edit your account name, view transactions on Etherscan, share your public key, and see your private key by tapping this icon" + }, + "step4": { + "title": "Using your wallet", + "content1": "Buy, send, swap, and receive assets by tapping this icon" + }, + "step5": { + "title": "Exploring web3", + "content1": "Open the browser by tapping this icon" + }, + "step6": { + "title": "Using the browser", + "content1": "Search for sites by keyword or enter a URL. Have fun out there! " + } + }, "create_wallet": { "title": "Создание кошелька...", "subtitle": "Это не займет много времени" @@ -800,7 +831,30 @@ "buy_description": "Покупайте криптовалюту за наличные", "swap_description": "Обменивайте одни токены на другие", "send_description": "Отправляйте криптовалюту на любой счет", - "receive_description": "Получайте криптовалюту" + "receive_description": "Получайте криптовалюту", + "chart_time_period": { + "1d": "Today", + "7d": "Past 7 days", + "1w": "Past week", + "1m": "Past month", + "3m": "Past 3 months", + "1y": "Past year", + "3y": "Past 3 years" + }, + "chart_time_period_navigation": { + "1d": "1D", + "7d": "7D", + "1w": "1W", + "1m": "1M", + "3m": "3M", + "1y": "1Y", + "3y": "3Y" + }, + "your_balance": "Your balance", + "unable_to_load_balance": "Unable to load your balance", + "about": "About", + "activity": "{{symbol}} activity", + "disclaimer": "Market data is provided by one or more third-party data sources, including CoinGecko. Such third-party content is provided solely for informational purposes and should not be treated as advice to buy, sell, or use any particular asset. MetaMask does not suggest the use of this content for any particular purpose and is not responsible for its accuracy." }, "account_details": { "title": "Реквизиты счета", @@ -1222,7 +1276,6 @@ "add_other_network_here": "здесь.", "you_can": "Или вы можете", "add_network": "добавить другие сети вручную.", - "deprecated_network_msg": "Из-за изменений протокола Ethereum: тестовые сети Rinkeby, Ropsten, Kovan могут работать не так надежно и скоро будут признаны устаревшими.", "select_network": "Выбрать сеть" }, "select": { @@ -1788,6 +1841,7 @@ "webview_received_error": "WebView получил код состояния ошибки: {{code}}", "no_tokens_available_title": "Нет доступных токенов", "no_tokens_available": "В настоящее время нет токенов, доступных для покупки в {{network}} в {{region}}", + "this_network": "this network", "change_payment_method": "Изменить способ оплаты", "try_different_region": "Попробуйте другой регион", "return_home": "Назад на главный экран", diff --git a/locales/languages/tl.json b/locales/languages/tl.json index 5b26324e588..bc8baba6d73 100644 --- a/locales/languages/tl.json +++ b/locales/languages/tl.json @@ -108,6 +108,37 @@ "content": "Maghanap ng site o mag-type ng URL kung alam mo kung saan ka pupunta." } }, + "onboarding_wizard_new": { + "coachmark": { + "action_back": "No thanks", + "action_next": "Take the tour", + "progress_next": "Got it" + }, + "step1": { + "title": "Welcome to your wallet!", + "content1": "On the blockchain, you need a wallet (and maybe some ETH). So let’s take a look at how to use your MetaMask wallet." + }, + "step2": { + "title": "Your accounts", + "content1": "This is your account and unique public address (0x...). Create more accounts by tapping the arrow icon." + }, + "step3": { + "title": "Managing your account", + "content1": "Edit your account name, view transactions on Etherscan, share your public key, and see your private key by tapping this icon" + }, + "step4": { + "title": "Using your wallet", + "content1": "Buy, send, swap, and receive assets by tapping this icon" + }, + "step5": { + "title": "Exploring web3", + "content1": "Open the browser by tapping this icon" + }, + "step6": { + "title": "Using the browser", + "content1": "Search for sites by keyword or enter a URL. Have fun out there! " + } + }, "create_wallet": { "title": "Ginagawa ang iyong wallet...", "subtitle": "Hindi ito aabutin nang matagal" @@ -800,7 +831,30 @@ "buy_description": "Bumili ng crypto gamit ang cash", "swap_description": "Palitan sa pagitan ng mga token", "send_description": "Magpadala ng crypto sa anumang account", - "receive_description": "Tumanggap ng crypto" + "receive_description": "Tumanggap ng crypto", + "chart_time_period": { + "1d": "Today", + "7d": "Past 7 days", + "1w": "Past week", + "1m": "Past month", + "3m": "Past 3 months", + "1y": "Past year", + "3y": "Past 3 years" + }, + "chart_time_period_navigation": { + "1d": "1D", + "7d": "7D", + "1w": "1W", + "1m": "1M", + "3m": "3M", + "1y": "1Y", + "3y": "3Y" + }, + "your_balance": "Your balance", + "unable_to_load_balance": "Unable to load your balance", + "about": "About", + "activity": "{{symbol}} activity", + "disclaimer": "Market data is provided by one or more third-party data sources, including CoinGecko. Such third-party content is provided solely for informational purposes and should not be treated as advice to buy, sell, or use any particular asset. MetaMask does not suggest the use of this content for any particular purpose and is not responsible for its accuracy." }, "account_details": { "title": "Mga Detalye ng Account", @@ -1222,7 +1276,6 @@ "add_other_network_here": "dito.", "you_can": "O maaari kang", "add_network": "magdagdag pa ng mga network nang manu-mano.", - "deprecated_network_msg": "Dahil sa mga pagbabago ng protokol ng Ethereum: ang mga test network na Rinkeby, Ropsten, at Kovan ay maaaring hindi gumana tulad ng maaasahan at malapit nang itigil ang paggamit.", "select_network": "Pumili ng network" }, "select": { @@ -1788,6 +1841,7 @@ "webview_received_error": "Ang WebView ay nakatanggap ng error status code: {{code}}", "no_tokens_available_title": "Walang Available na Token", "no_tokens_available": "Kasalukuyang walang mga token na available upang bilhin sa {{network}} gamit ang napiling paraan ng pagbabayad.", + "this_network": "this network", "change_payment_method": "Baguhin ang paraan ng pagbabayad", "try_different_region": "Subukan ang ibang rehiyon", "return_home": "Bumalik sa Home Screen", diff --git a/locales/languages/tr.json b/locales/languages/tr.json index 4e41217bfe3..346e9764bfd 100644 --- a/locales/languages/tr.json +++ b/locales/languages/tr.json @@ -108,6 +108,37 @@ "content": "Siteleri arayabilir veya nereye yönlendirildiğinizi biliyorsanız bir URL adresi girebilirsiniz." } }, + "onboarding_wizard_new": { + "coachmark": { + "action_back": "No thanks", + "action_next": "Take the tour", + "progress_next": "Got it" + }, + "step1": { + "title": "Welcome to your wallet!", + "content1": "On the blockchain, you need a wallet (and maybe some ETH). So let’s take a look at how to use your MetaMask wallet." + }, + "step2": { + "title": "Your accounts", + "content1": "This is your account and unique public address (0x...). Create more accounts by tapping the arrow icon." + }, + "step3": { + "title": "Managing your account", + "content1": "Edit your account name, view transactions on Etherscan, share your public key, and see your private key by tapping this icon" + }, + "step4": { + "title": "Using your wallet", + "content1": "Buy, send, swap, and receive assets by tapping this icon" + }, + "step5": { + "title": "Exploring web3", + "content1": "Open the browser by tapping this icon" + }, + "step6": { + "title": "Using the browser", + "content1": "Search for sites by keyword or enter a URL. Have fun out there! " + } + }, "create_wallet": { "title": "Cüzdanınız oluşturuluyor...", "subtitle": "Bu işlem uzun sürmeyecektir" @@ -800,7 +831,30 @@ "buy_description": "Nakit ile kripto satın alın", "swap_description": "Tokenler arasında takas yapın", "send_description": "Dilediğin hesaba kripto gönderin", - "receive_description": "Kripto alın" + "receive_description": "Kripto alın", + "chart_time_period": { + "1d": "Today", + "7d": "Past 7 days", + "1w": "Past week", + "1m": "Past month", + "3m": "Past 3 months", + "1y": "Past year", + "3y": "Past 3 years" + }, + "chart_time_period_navigation": { + "1d": "1D", + "7d": "7D", + "1w": "1W", + "1m": "1M", + "3m": "3M", + "1y": "1Y", + "3y": "3Y" + }, + "your_balance": "Your balance", + "unable_to_load_balance": "Unable to load your balance", + "about": "About", + "activity": "{{symbol}} activity", + "disclaimer": "Market data is provided by one or more third-party data sources, including CoinGecko. Such third-party content is provided solely for informational purposes and should not be treated as advice to buy, sell, or use any particular asset. MetaMask does not suggest the use of this content for any particular purpose and is not responsible for its accuracy." }, "account_details": { "title": "Hesap Bilgileri", @@ -1222,7 +1276,6 @@ "add_other_network_here": "Burada daha fazla ağ keşfedebilirsiniz.", "you_can": "Veya", "add_network": "manuel olarak daha fazla ekleyebilirsiniz.", - "deprecated_network_msg": "Ethereum'da yaşanan protokol değişikliklerinden dolayı: Rinkeby, Ropsten, Kovan test ağları güvenilir bir şekilde çalışmayabilir ve yakında kullanım dışı olacak.", "select_network": "Bir ağ seçin" }, "select": { @@ -1788,6 +1841,7 @@ "webview_received_error": "WebView şu hata durum kodunu aldı: {{code}}", "no_tokens_available_title": "Token Yok", "no_tokens_available": "Şu anda {{network}} üzerinde seçili ödeme yöntemi ile mevcut token bulunmamaktadır.", + "this_network": "this network", "change_payment_method": "Ödeme yöntemini değiştir", "try_different_region": "Farklı bir bölge deneyin", "return_home": "Ana Ekrana Geri Dön", diff --git a/locales/languages/vi.json b/locales/languages/vi.json index 3031b060875..4423a62163a 100644 --- a/locales/languages/vi.json +++ b/locales/languages/vi.json @@ -108,6 +108,37 @@ "content": "Tìm kiếm trang web hoặc gõ địa chỉ URL nếu bạn biết trang web bạn muốn đến." } }, + "onboarding_wizard_new": { + "coachmark": { + "action_back": "No thanks", + "action_next": "Take the tour", + "progress_next": "Got it" + }, + "step1": { + "title": "Welcome to your wallet!", + "content1": "On the blockchain, you need a wallet (and maybe some ETH). So let’s take a look at how to use your MetaMask wallet." + }, + "step2": { + "title": "Your accounts", + "content1": "This is your account and unique public address (0x...). Create more accounts by tapping the arrow icon." + }, + "step3": { + "title": "Managing your account", + "content1": "Edit your account name, view transactions on Etherscan, share your public key, and see your private key by tapping this icon" + }, + "step4": { + "title": "Using your wallet", + "content1": "Buy, send, swap, and receive assets by tapping this icon" + }, + "step5": { + "title": "Exploring web3", + "content1": "Open the browser by tapping this icon" + }, + "step6": { + "title": "Using the browser", + "content1": "Search for sites by keyword or enter a URL. Have fun out there! " + } + }, "create_wallet": { "title": "Đang tạo ví của bạn...", "subtitle": "Sẽ không tốn nhiều thời gian" @@ -800,7 +831,30 @@ "buy_description": "Mua tiền mã hóa bằng tiền", "swap_description": "Chuyển đổi giữa các token", "send_description": "Gửi tiền mã hóa đến bất kỳ tài khoản nào", - "receive_description": "Nhận tiền mã hóa" + "receive_description": "Nhận tiền mã hóa", + "chart_time_period": { + "1d": "Today", + "7d": "Past 7 days", + "1w": "Past week", + "1m": "Past month", + "3m": "Past 3 months", + "1y": "Past year", + "3y": "Past 3 years" + }, + "chart_time_period_navigation": { + "1d": "1D", + "7d": "7D", + "1w": "1W", + "1m": "1M", + "3m": "3M", + "1y": "1Y", + "3y": "3Y" + }, + "your_balance": "Your balance", + "unable_to_load_balance": "Unable to load your balance", + "about": "About", + "activity": "{{symbol}} activity", + "disclaimer": "Market data is provided by one or more third-party data sources, including CoinGecko. Such third-party content is provided solely for informational purposes and should not be treated as advice to buy, sell, or use any particular asset. MetaMask does not suggest the use of this content for any particular purpose and is not responsible for its accuracy." }, "account_details": { "title": "Chi tiết tài khoản", @@ -1222,7 +1276,6 @@ "add_other_network_here": "tại đây.", "you_can": "Hoặc bạn có thể", "add_network": "thêm thủ công các mạng khác.", - "deprecated_network_msg": "Do những thay đổi trong giao thức của Ethereum: các mạng thử nghiệm Rinkeby, Ropsten, Kovan có thể không hoạt động đáng tin cậy và sẽ sớm bị ngừng sử dụng.", "select_network": "Chọn mạng" }, "select": { @@ -1788,6 +1841,7 @@ "webview_received_error": "WebView đã nhận được mã trạng thái lỗi: {{code}}", "no_tokens_available_title": "Hiện không có token nào", "no_tokens_available": "Hiện không có token nào để mua trên {{network}} bằng phương thức thanh toán đã chọn.", + "this_network": "this network", "change_payment_method": "Thay đổi phương thức thanh toán", "try_different_region": "Hãy thử một khu vực khác", "return_home": "Quay lại Màn hình chính", diff --git a/locales/languages/zh.json b/locales/languages/zh.json index 443d5f392cd..4fc905998a4 100644 --- a/locales/languages/zh.json +++ b/locales/languages/zh.json @@ -108,6 +108,37 @@ "content": "搜索站点;如果您知道要前往的目的地,键入 URL。" } }, + "onboarding_wizard_new": { + "coachmark": { + "action_back": "No thanks", + "action_next": "Take the tour", + "progress_next": "Got it" + }, + "step1": { + "title": "Welcome to your wallet!", + "content1": "On the blockchain, you need a wallet (and maybe some ETH). So let’s take a look at how to use your MetaMask wallet." + }, + "step2": { + "title": "Your accounts", + "content1": "This is your account and unique public address (0x...). Create more accounts by tapping the arrow icon." + }, + "step3": { + "title": "Managing your account", + "content1": "Edit your account name, view transactions on Etherscan, share your public key, and see your private key by tapping this icon" + }, + "step4": { + "title": "Using your wallet", + "content1": "Buy, send, swap, and receive assets by tapping this icon" + }, + "step5": { + "title": "Exploring web3", + "content1": "Open the browser by tapping this icon" + }, + "step6": { + "title": "Using the browser", + "content1": "Search for sites by keyword or enter a URL. Have fun out there! " + } + }, "create_wallet": { "title": "正在创建您的钱包...", "subtitle": "这应该不需要很长时间" @@ -800,7 +831,30 @@ "buy_description": "用现金购买加密货币", "swap_description": "代币之间的兑换", "send_description": "向任何账户发送加密货币", - "receive_description": "接收加密货币" + "receive_description": "接收加密货币", + "chart_time_period": { + "1d": "Today", + "7d": "Past 7 days", + "1w": "Past week", + "1m": "Past month", + "3m": "Past 3 months", + "1y": "Past year", + "3y": "Past 3 years" + }, + "chart_time_period_navigation": { + "1d": "1D", + "7d": "7D", + "1w": "1W", + "1m": "1M", + "3m": "3M", + "1y": "1Y", + "3y": "3Y" + }, + "your_balance": "Your balance", + "unable_to_load_balance": "Unable to load your balance", + "about": "About", + "activity": "{{symbol}} activity", + "disclaimer": "Market data is provided by one or more third-party data sources, including CoinGecko. Such third-party content is provided solely for informational purposes and should not be treated as advice to buy, sell, or use any particular asset. MetaMask does not suggest the use of this content for any particular purpose and is not responsible for its accuracy." }, "account_details": { "title": "账户详细信息", @@ -1222,7 +1276,6 @@ "add_other_network_here": "这里。", "you_can": "或者您可以", "add_network": "手动添加更多网络。", - "deprecated_network_msg": "由于以太坊的协议有变化:Rinkeby、Ropsten、Kovan测试网络可能无法可靠地工作,很快就会被弃用。", "select_network": "选择网络" }, "select": { @@ -1788,6 +1841,7 @@ "webview_received_error": "WebView收到错误状态代码:{{code}}", "no_tokens_available_title": "无可用代币", "no_tokens_available": "当前{{network}}上没有可用的代币,无法使用所选支付方式购买。", + "this_network": "this network", "change_payment_method": "更改付款方式", "try_different_region": "请尝试其他区域", "return_home": "返回主屏幕", diff --git a/package.json b/package.json index 4fc102c9ff2..070aa711a1d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "metamask", - "version": "6.4.0", + "version": "6.5.0", "private": true, "scripts": { "audit:ci": "./scripts/yarn-audit.sh", @@ -54,7 +54,7 @@ "test:e2e": "yarn test:e2e:ios && yarn test:e2e:android", "test:e2e:ios": "detox build -c ios.sim.release && detox test -c ios.sim.release", "test:e2e:ios:debug": "detox build -c ios.sim.debug && detox test -c ios.sim.debug", - "test:e2e:ios:debug:single":"detox test -c ios.sim.debug", + "test:e2e:ios:debug:single": "detox test -c ios.sim.debug", "test:e2e:android": "detox build -c android.emu.release && detox test -c android.emu.release --record-videos failing", "test:e2e:android:qa": "detox build -c android.emu.release.qa && detox test -c android.emu.release.qa --record-videos failing", "test:wdio:ios": "yarn wdio ./wdio/config/ios.config.debug.js", @@ -113,6 +113,8 @@ "react-native-level-fs/**/bl": "^1.2.3", "react-native-level-fs/**/semver": "^4.3.2", "@metamask/contract-metadata": "^2.1.0", + "@metamask/controller-utils": "~3.0.0", + "@metamask/approval-controller": "~2.0.0", "@exodus/react-native-payments/validator": "^13.7.0", "react-devtools-core": "4.22.1", "**/got": "^11.8.5", @@ -137,30 +139,31 @@ "@eth-optimism/contracts": "0.0.0-2021919175625", "@ethereumjs/common": "^2.3.1", "@ethereumjs/tx": "^3.2.1", + "@ethersproject/abi": "^5.7.0", "@exodus/react-native-payments": "git+https://github.com/MetaMask/react-native-payments.git#dbc8cbbed570892d2fea5e3d183bf243e062c1e5", "@keystonehq/bc-ur-registry-eth": "^0.7.7", "@keystonehq/metamask-airgapped-keyring": "^0.3.0", "@keystonehq/ur-decoder": "^0.6.1", - "@metamask/address-book-controller": "^1.1.0", - "@metamask/approval-controller": "^1.1.0", - "@metamask/assets-controllers": "4.0.0", - "@metamask/base-controller": "^1.1.2", - "@metamask/composable-controller": "^1.0.2", + "@metamask/address-book-controller": "^2.0.0", + "@metamask/approval-controller": "~2.0.0", + "@metamask/assets-controllers": "5.0.0", + "@metamask/base-controller": "^2.0.0", + "@metamask/composable-controller": "^2.0.0", "@metamask/contract-metadata": "^2.1.0", - "@metamask/controller-utils": "^2.0.0", + "@metamask/controller-utils": "~3.0.0", "@metamask/design-tokens": "^1.11.1", "@metamask/eth-sig-util": "^4.0.1", "@metamask/etherscan-link": "^2.0.0", - "@metamask/gas-fee-controller": "^3.0.0", + "@metamask/gas-fee-controller": "4.0.0", "@metamask/keyring-controller": "^1.0.1", - "@metamask/message-manager": "^1.0.2", - "@metamask/network-controller": "^3.0.0", - "@metamask/permission-controller": "^2.0.0", - "@metamask/phishing-controller": "^2.0.0", + "@metamask/message-manager": "^2.0.0", + "@metamask/network-controller": "^5.0.0", + "@metamask/permission-controller": "~3.0.0", + "@metamask/phishing-controller": "^3.0.0", "@metamask/preferences-controller": "^2.1.0", "@metamask/sdk-communication-layer": "0.2.2", "@metamask/swaps-controller": "^6.8.0", - "@metamask/transaction-controller": "^3.0.0", + "@metamask/transaction-controller": "4.0.0", "@ngraveio/bc-ur": "^1.1.6", "@react-native-async-storage/async-storage": "1.17.10", "@react-native-clipboard/clipboard": "^1.8.4", @@ -306,6 +309,7 @@ "redux-mock-store": "1.5.4", "redux-persist": "6.0.0", "redux-persist-filesystem-storage": "^3.0.0", + "redux-thunk": "^2.4.2", "reselect": "^4.0.0", "rn-fetch-blob": "^0.12.0", "socket.io-client": "^4.5.3", @@ -323,6 +327,8 @@ "devDependencies": { "@babel/core": "^7.12.9", "@babel/runtime": "^7.12.5", + "@cucumber/message-streams": "^4.0.1", + "@cucumber/messages": "^22.0.0", "@lavamoat/allow-scripts": "^1.0.6", "@metamask/eslint-config": "^7.0.0", "@metamask/eslint-config-typescript": "^7.0.0", @@ -337,6 +343,7 @@ "@storybook/react-native": "^5.3.25", "@testing-library/react-hooks": "^8.0.1", "@types/enzyme": "^3.10.9", + "@types/is-url": "^1.2.30", "@types/jest": "^27.0.1", "@types/react": "^17.0.11", "@types/react-native": "^0.64.10", @@ -345,6 +352,7 @@ "@types/react-native-vector-icons": "^6.4.8", "@types/react-native-video": "^5.0.13", "@types/redux-mock-store": "^1.0.3", + "@types/url-parse": "^1.4.8", "@typescript-eslint/eslint-plugin": "^4.20.0", "@typescript-eslint/parser": "^4.20.0", "@wdio/appium-service": "^7.19.1", @@ -362,7 +370,6 @@ "babel-loader": "^8.2.3", "browserstack-local": "^1.5.1", "chromedriver": "^99.0.0", - "concat-cli": "4.0.0", "detox": "^19.11.0", "dotenv": "^16.0.3", "enzyme": "3.9.0", @@ -403,11 +410,7 @@ "rn-nodeify": "10.0.1", "stack-beautifier": "1.0.2", "typescript": "^4.4.2", - "wdio-chromedriver-service": "^7.3.2", - "wdio-cucumber-reporter": "^0.0.2", "wdio-cucumberjs-json-reporter": "^4.4.3", - "wdio-image-comparison-service": "^3.1.0", - "wdio-vscode-service": "^0.1.5", "xml2js": "^0.5.0" }, "config": { diff --git a/patches/@metamask+assets-controllers+4.0.0.patch b/patches/@metamask+assets-controllers+5.0.0.patch similarity index 93% rename from patches/@metamask+assets-controllers+4.0.0.patch rename to patches/@metamask+assets-controllers+5.0.0.patch index d9917a56783..c0dbfc04147 100644 --- a/patches/@metamask+assets-controllers+4.0.0.patch +++ b/patches/@metamask+assets-controllers+5.0.0.patch @@ -24,10 +24,25 @@ index 332c87d..c110f41 100644 * Enumerate assets assigned to an owner. * diff --git a/node_modules/@metamask/assets-controllers/dist/Standards/ERC20Standard.js b/node_modules/@metamask/assets-controllers/dist/Standards/ERC20Standard.js -index 9ddbc28..acdc28a 100644 +index 9ddbc28..2d12e33 100644 --- a/node_modules/@metamask/assets-controllers/dist/Standards/ERC20Standard.js +++ b/node_modules/@metamask/assets-controllers/dist/Standards/ERC20Standard.js -@@ -57,6 +57,27 @@ class ERC20Standard { +@@ -13,7 +13,13 @@ exports.ERC20Standard = void 0; + const contracts_1 = require("@ethersproject/contracts"); + const metamask_eth_abis_1 = require("@metamask/metamask-eth-abis"); + const ethereumjs_util_1 = require("ethereumjs-util"); +-const abi_utils_1 = require("@metamask/abi-utils"); ++ ++// Revert to use @ethersproject/abi to fix BigInt compatibility issue ++// Issue reported here - https://github.com/MetaMask/metamask-mobile/issues/6307 ++// TODO - Remove patch once app is upgraded to React Native 0.71.6 ++// const abi_utils_1 = require("@metamask/abi-utils"); ++const ethers_project_abi = require('@ethersproject/abi'); ++ + const controller_utils_1 = require("@metamask/controller-utils"); + const utils_1 = require("@metamask/utils"); + const assetsUtil_1 = require("../assetsUtil"); +@@ -57,6 +63,27 @@ class ERC20Standard { } }); } @@ -55,6 +70,25 @@ index 9ddbc28..acdc28a 100644 /** * Query for symbol for a given ERC20 asset. * +@@ -68,10 +95,16 @@ class ERC20Standard { + // Signature for calling `symbol()` + const payload = { to: address, data: '0x95d89b41' }; + const result = yield this.provider.call(payload); +- (0, utils_1.assertIsStrictHexString)(result); ++ ++ // TODO - Remove patch once app is upgraded to RN 0.71.6 ++ // (0, utils_1.assertIsStrictHexString)(result); ++ + // Parse as string - treat empty string as failure + try { +- const decoded = (0, abi_utils_1.decodeSingle)('string', result); ++ // TODO - Remove patch once app is upgraded to React Native 0.71.6 ++ const decoded = ethers_project_abi.abiCoder.decode(['string'], result)[0]; ++ // const decoded = (0, abi_utils_1.decodeSingle)('string', result); ++ + if ((decoded === null || decoded === void 0 ? void 0 : decoded.length) > 0) { + return decoded; + } diff --git a/node_modules/@metamask/assets-controllers/dist/TokenDetectionController.js b/node_modules/@metamask/assets-controllers/dist/TokenDetectionController.js index 4ed4990..da18116 100644 --- a/node_modules/@metamask/assets-controllers/dist/TokenDetectionController.js diff --git a/scripts/build.sh b/scripts/build.sh index 979842ea2b8..a3ad4e781b5 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -396,7 +396,7 @@ startWatcher() { yarn --ignore-engines build:static-logos if [ "$MODE" == "clean" ]; then watchman watch-del-all - rm -rf $TMPDIR/react-* + rm -rf $TMPDIR/metro-cache react-native start -- --reset-cache else react-native start diff --git a/wdio.conf.js b/wdio.conf.js index 64e641e43cc..d501d68690b 100644 --- a/wdio.conf.js +++ b/wdio.conf.js @@ -31,6 +31,10 @@ export const config = { // specs: ['./wdio/features/**/*.feature'], + suites: { + confirmations: ['./wdio/features/Confirmations/*.feature'] + }, + // Patterns to exclude. exclude: [ // 'path/to/excluded/files' @@ -52,6 +56,7 @@ export const config = { // from the same test should run tests. // maxInstances: 10, + specFileRetries: 1, // // If you have trouble getting all important capabilities together, check out the // Sauce Labs platform configurator - a great tool to configure your capabilities: @@ -116,7 +121,7 @@ export const config = { baseUrl: 'http://localhost', // // Default timeout for all waitFor* commands. - waitforTimeout: 100000, + waitforTimeout: 40000, // // Default timeout in milliseconds for request // if browser driver or grid doesn't send response diff --git a/wdio/features/Accounts/CreatingWalletAccount.feature b/wdio/features/Accounts/CreatingWalletAccount.feature index fbf7ac543f6..bd4f5d2d4be 100644 --- a/wdio/features/Accounts/CreatingWalletAccount.feature +++ b/wdio/features/Accounts/CreatingWalletAccount.feature @@ -1,6 +1,6 @@ @androidApp @smoke -Feature: Creating account in wallet +Feature: Create Account Scenario: Import wallet Given the app displayed the splash animation @@ -14,5 +14,4 @@ Feature: Creating account in wallet When I tap on the Identicon Then the account list should be visible When I tap on Create a new account - Then A new account is created - And I am on the new account + Then I am on the new account diff --git a/wdio/features/Accounts/ImportingAccount.feature b/wdio/features/Accounts/ImportingAccount.feature index 5ddbdb40ab6..6799eaafb1d 100644 --- a/wdio/features/Accounts/ImportingAccount.feature +++ b/wdio/features/Accounts/ImportingAccount.feature @@ -1,8 +1,8 @@ @androidApp -@smoke -Feature: Importing account in wallet +@regression +Feature: Import Aaccount - Scenario: Import wallet + Scenario: Import Wallet Given the app displayed the splash animation And I have imported my wallet And I tap No Thanks on the Enable security check screen diff --git a/wdio/features/BrowserFlow/AddFavorite.feature b/wdio/features/BrowserFlow/AddFavorite.feature index da44bdc2247..448cff33c93 100644 --- a/wdio/features/BrowserFlow/AddFavorite.feature +++ b/wdio/features/BrowserFlow/AddFavorite.feature @@ -1,6 +1,6 @@ @androidApp @smoke -Feature: This feature file covers adding favorite websites in browser. +Feature: Browser Add Favorite Scenario: Adding browser Favorites Add, click and delete favorites. Display favorites in the Favorites tab of home.metamask.io diff --git a/wdio/features/BrowserFlow/InvalidURL.feature b/wdio/features/BrowserFlow/InvalidURL.feature index 1f00baf5944..4f65eb616c7 100644 --- a/wdio/features/BrowserFlow/InvalidURL.feature +++ b/wdio/features/BrowserFlow/InvalidURL.feature @@ -1,6 +1,6 @@ @androidApp @smoke -Feature: This feature file covers invalid url functionality in the browser. +Feature: Browser Invalid URL Scenario: Searching an invalid url and prompts the user with an error message Given the app displayed the splash animation diff --git a/wdio/features/BrowserFlow/PhishingDetection.feature b/wdio/features/BrowserFlow/PhishingDetection.feature index e23bc049739..9aedc84400e 100644 --- a/wdio/features/BrowserFlow/PhishingDetection.feature +++ b/wdio/features/BrowserFlow/PhishingDetection.feature @@ -1,6 +1,6 @@ @androidApp @smoke -Feature: This feature file covers phishing detection functionality the browser. +Feature: Browser Phishing Detection Scenario: Visiting a malicious website prompts the user with the phishing detection warning Given the app displayed the splash animation diff --git a/wdio/features/BrowserFlow/RemovingImportedAccountAfterConnectingToDapp.feature b/wdio/features/BrowserFlow/RemovingImportedAccountAfterConnectingToDapp.feature index fadaa6174e6..1c342c46633 100644 --- a/wdio/features/BrowserFlow/RemovingImportedAccountAfterConnectingToDapp.feature +++ b/wdio/features/BrowserFlow/RemovingImportedAccountAfterConnectingToDapp.feature @@ -1,5 +1,6 @@ -@androidApp -@regression +@androidApp +@smoke + Feature: Importing account via private then revoking permissions Scenario: Import wallet @@ -11,7 +12,7 @@ Feature: Importing account via private then revoking permissions Scenario: User grants permission to a sushiswap to access one of their accounts When I navigate to the browser - # When I tap on button with text "Wallet" + # When I tap on button with text "Wallet" And I navigate to "https://app.sushi.com/swap" Then the connect modal should be displayed And I connect my active wallet to the dapp diff --git a/wdio/features/BrowserFlow/RevokingSingleAccount.feature b/wdio/features/BrowserFlow/RevokingSingleAccount.feature index 0589a7ca10b..3db0e9163ad 100644 --- a/wdio/features/BrowserFlow/RevokingSingleAccount.feature +++ b/wdio/features/BrowserFlow/RevokingSingleAccount.feature @@ -1,6 +1,6 @@ -@androidApp +@androidApp @regression -Feature: Permission system in MetaMask Mobile +Feature: Revoking access to a dapp while connected to one account. Scenario: Import wallet Given the app displayed the splash animation diff --git a/wdio/features/Confirmations/SendEthEOA.feature b/wdio/features/Confirmations/SendEthEOA.feature new file mode 100644 index 00000000000..0c59cb176a5 --- /dev/null +++ b/wdio/features/Confirmations/SendEthEOA.feature @@ -0,0 +1,58 @@ +@androidApp +@confirmations +@regression + +Feature: Sending ETH to an EOA + A user should be able to send ETH to another EOA address. + + Scenario: Import wallet + Given the app displayed the splash animation + And I have imported my wallet + And I tap No Thanks on the Enable security check screen + And I tap No thanks on the onboarding welcome tutorial + + Scenario: Setting up Ganache local network + Given Ganache server is started + And I close the Whats New modal + When I tap on the burger menu + And I tap on "Settings" in the menu + And In settings I tap on "Networks" + And I tap on the Add Network button + Then "POPULAR" tab is displayed on networks screen + And "CUSTOM NETWORKS" tab is displayed on networks screen + + When I tap on the "CUSTOM NETWORKS" tab + + When I type "" into Network name field + And I type "" into the RPC url field + And I type "" into the Chain ID field + And I type "" into the Network symbol field + + When I tap on the Add button + And I tap on Got it in the network education modal + Then I should see the added network name "" in the top navigation bar + + Examples: + | Network | rpcUrl | ChainID | Symbol | + | Localhost 8545 | http://localhost:8545 | 1337 | ETH | + + Scenario Outline: Sending ETH to an EOA from inside MetaMask wallet + When On the Main Wallet view I tap "ETHER" + And On the Main Wallet view I tap "Send" + And I enter address "
" in the sender's input box + When I tap button "Next" on Send To view + Then I proceed to the amount view + + When I type amount "" into amount input field + And I tap button "Next" on the Amount view + Then I should be taken to the transaction confirmation view + And the token amount to be sent is visible + + When I tap button "Send" on Confirm Amount view + Then I am taken to the token overview screen + And the transaction is submitted with Transaction Complete! toast appearing + Then Ganache server is stopped + + Examples: + | Address | Amount | + | 0x1FDb169Ef12954F20A15852980e1F0C122BfC1D6 | 1 | \ No newline at end of file diff --git a/wdio/features/Onboarding/CreateNewWallet.feature b/wdio/features/Onboarding/CreateNewWallet.feature index 4cf9cf0ffa3..32c2761caeb 100644 --- a/wdio/features/Onboarding/CreateNewWallet.feature +++ b/wdio/features/Onboarding/CreateNewWallet.feature @@ -1,12 +1,12 @@ @androidApp -@smoke -Feature: New wallet flow +@regression +Feature: Create New Wallet Scenario: Onboarding New walllet - User opens the app for first time and creates a new wallet. + User opens the app for first time and creates a new wallet. Given the Welcome Screen is displayed When I tap "Get started" - Then "Wallet setup" is displayed + Then Wallet setup screen is displayed When On Wallet Setup Screen I tap "Create a new wallet" And On Wallet Setup Screen I tap "Agree" And Terms of Use is displayed diff --git a/wdio/features/Onboarding/ImportWallet.feature b/wdio/features/Onboarding/ImportWallet.feature index 9e0ccf5b2ca..7e45e487685 100644 --- a/wdio/features/Onboarding/ImportWallet.feature +++ b/wdio/features/Onboarding/ImportWallet.feature @@ -1,14 +1,12 @@ @androidApp -@smoke +@regression Feature: Import Wallet - Users can use the app to import an existing wallet or create a new one. + Users can use the app to import an existing wallet or create a new one. - Scenario Outline: Import Wallet - Manual input SR - After a user completes the onboarding process then they are presented - with the option to create a new wallet and back it up. + Scenario: Get Started Given the Welcome Screen is displayed When I tap "Get started" - Then "Wallet setup" is displayed + Then Wallet setup screen is displayed When I tap "Import using Secret Recovery Phrase" Then "Help us improve MetaMask" is displayed When I tap "I agree" @@ -16,12 +14,40 @@ Feature: Import Wallet And I agree to terms And Terms of Use is not displayed Then "Import from seed" is displayed + + Scenario Outline: Password Strength + When I type in new password field + Then password strength is displayed + Examples: + | password | strength | + | metapass1 | Password strength: Weak | + | Metapass12345 | Password strength: Good | + | Metapass12345!@ | Password strength: Strong | + + Scenario Outline: Password Matching + When I type in confirm password field + Then green check mark is displayed + Examples: + | password | + | Metapass12345!@ | + + Scenario Outline: Invalid SRP + When I type in SRP field + And I tap "Import" + Then device alert is displayed + And I tap Yes on alert + + Examples: + | invalid_SRP | error | + | fold media south not valid secret recovery phrase pause cloth just raven | Invalid Secret Recovery Phrase | + | fold media south add since false relax immense pause cloth just | Secret Recovery Phrases contain 12, 15, 18, 21, or 24 words | + + Scenario Outline: Import Wallet When I type in SRP field - And I type in new password field And I type in confirm password field And I tap "Import" And I tap No Thanks on the Enable security check screen Then "Welcome to your new wallet!" is displayed Examples: - | SRP | password | - | fold media south add since false relax immense pause cloth just raven | metapass1 | + | SRP | password | + | fold media south add since false relax immense pause cloth just raven | Metapass12345!@ | diff --git a/wdio/features/Onboarding/ImportWalletRegression.feature b/wdio/features/Onboarding/ImportWalletRegression.feature deleted file mode 100644 index 2bc04fa60ee..00000000000 --- a/wdio/features/Onboarding/ImportWalletRegression.feature +++ /dev/null @@ -1,53 +0,0 @@ -@androidApp -@regression -Feature: Import Wallet Regression - Users can use the app to import an existing wallet or create a new one. - - Scenario: Get Started - Given the Welcome Screen is displayed - When I tap "Get started" - Then "Wallet setup" is displayed - When I tap "Import using Secret Recovery Phrase" - Then "Help us improve MetaMask" is displayed - When I tap "I agree" - And Terms of Use is displayed - And I agree to terms - And Terms of Use is not displayed - Then "Import from seed" is displayed - - Scenario Outline: Password Strength - When I type in new password field - Then password strength is displayed - Examples: - | password | strength | - | metapass1 | Password strength: Weak | - | Metapass12345 | Password strength: Good | - | Metapass12345!@ | Password strength: Strong | - - Scenario Outline: Password Matching - When I type in confirm password field - Then green check mark is displayed - Examples: - | password | - | Metapass12345!@ | - - Scenario Outline: Invalid SRP - When I type in SRP field - And I tap "Import" - Then device alert is displayed - And I tap Yes on alert - - Examples: - | invalid_SRP | error | - | fold media south not valid secret recovery phrase pause cloth just raven | Invalid Secret Recovery Phrase | - | fold media south add since false relax immense pause cloth just | Secret Recovery Phrases contain 12, 15, 18, 21, or 24 words | - - Scenario Outline: Import Wallet - When I type in SRP field - And I type in confirm password field - And I tap "Import" - And I tap No Thanks on the Enable security check screen - Then "Welcome to your new wallet!" is displayed - Examples: - | SRP | password | - | fold media south add since false relax immense pause cloth just raven | Metapass12345!@ | diff --git a/wdio/features/Onboarding/OnboardingCarousel.feature b/wdio/features/Onboarding/OnboardingCarousel.feature index f95558259e1..59f9cf6879b 100644 --- a/wdio/features/Onboarding/OnboardingCarousel.feature +++ b/wdio/features/Onboarding/OnboardingCarousel.feature @@ -1,11 +1,11 @@ @androidApp @smoke -Feature: Onboarding +Feature: Onboarding Carousel Users can install MetaMask mobile app from the device app store and read the onboarding carousel Scenario: New app install setup on a mobile device - This is the onboarding process after a new user installs the mobile app - and launches the app for the first time. + This is the onboarding process after a new user installs the mobile app + and launches the app for the first time. Given the app displayed the splash animation And the splash animation disappears And the Welcome Screen is displayed @@ -15,7 +15,5 @@ Feature: Onboarding Then "Your gateway to web3" carousel item is displayed When I swipe left on the carousel And I tap "Get started" - Then "Wallet setup" is displayed - And "Import an existing wallet or create a new one" is displayed - And "Import using Secret Recovery Phrase" is displayed - And "Create a new wallet" is displayed + Then Wallet setup screen is displayed + diff --git a/wdio/features/Onboarding/TermsOfUse.feature b/wdio/features/Onboarding/TermsOfUse.feature index 85021b292aa..17f083d454f 100644 --- a/wdio/features/Onboarding/TermsOfUse.feature +++ b/wdio/features/Onboarding/TermsOfUse.feature @@ -1,4 +1,4 @@ -@androidApp +@androidApp @regression Feature: Terms of Use @@ -6,7 +6,7 @@ Feature: Terms of Use Given the app displayed the splash animation And the Welcome Screen is displayed When I tap "Get started" - Then "Wallet setup" is displayed + Then Wallet setup screen is displayed When I tap "Import using Secret Recovery Phrase" Then "Help us improve MetaMask" is displayed When I tap "I agree" @@ -19,7 +19,7 @@ Feature: Terms of Use And the splash animation disappears Then the Welcome Screen is displayed When I tap "Get started" - Then "Wallet setup" is displayed + Then Wallet setup screen is displayed When I tap "Import using Secret Recovery Phrase" Then Terms of Use is displayed @@ -34,6 +34,6 @@ Feature: Terms of Use And the splash animation disappears Then the Welcome Screen is displayed When I tap "Get started" - Then "Wallet setup" is displayed + Then Wallet setup screen is displayed When I tap "Import using Secret Recovery Phrase" Then Terms of Use is not displayed diff --git a/wdio/features/SecurityAndPrivacy/DeleteWallet.feature b/wdio/features/SecurityAndPrivacy/DeleteWallet.feature index 6aea89cf9e5..88b039b94cf 100644 --- a/wdio/features/SecurityAndPrivacy/DeleteWallet.feature +++ b/wdio/features/SecurityAndPrivacy/DeleteWallet.feature @@ -17,4 +17,4 @@ Feature: This feature deletes the wallet from the Security and Privacy View And I tap I understand, continue on Delete wallet modal And I type "delete" on Delete wallet modal permanently And I tap Delete my wallet on Delete wallet modal permanently - Then "Wallet setup" is displayed + Then Wallet setup screen is displayed diff --git a/wdio/features/Wallet/ExploringWizard.feature b/wdio/features/Wallet/ExploringWizard.feature index b751efb04fc..db064c12ce9 100644 --- a/wdio/features/Wallet/ExploringWizard.feature +++ b/wdio/features/Wallet/ExploringWizard.feature @@ -13,10 +13,10 @@ Feature: Exploring wizard When On the onboarding wizard I tap on "Got it" button Then the tutorial modal heading should read "Edit Account Name" And there should be an explanation about adding a nickname to your account. - #When I tap and hold on the account Name - #Then I should be able to edit the account Name - #When I enter "Big Bank" for account name - #Then the account nickname should read "Big Bank" + When I tap and hold on the account Name + Then I should be able to edit the account Name + When I enter "Big Bank" for account name + Then the account nickname should read "Big Bank" When On the onboarding wizard I tap on "Got it" button Then the tutorial modal heading should read "Main Menu" And there should be an explanation of the what exists within the main menu. @@ -36,18 +36,18 @@ Feature: Exploring wizard Then the onboarding wizard is no longer visible And I close the Whats New modal - # Scenario: A user should be able to tap the Skip button - # Given the app displayed the splash animation - # And I have imported my wallet - # And I tap No Thanks on the Enable security check screen - # And the onboarding wizard is visible on wallet view - # When On the onboarding wizard I tap on "Take a Tour" button - # Then the tutorial modal heading should read "Your Accounts" - # And there should be an explanation of the accounts functionality. - # When On the onboarding wizard I tap on "Got it" button - # Then the tutorial modal heading should read "Edit Account Name" - # And there should be an explanation about adding a nickname to your account. - # When On the onboarding wizard I tap on "Skip" button - # Then the onboarding wizard is no longer visible - # And the "Skip" button is no longer visible - # And I close the Whats New modal +# Scenario: A user should be able to tap the Skip button +# Given the app displayed the splash animation +# And I have imported my wallet +# And I tap No Thanks on the Enable security check screen +# And the onboarding wizard is visible on wallet view +# When On the onboarding wizard I tap on "Take a Tour" button +# Then the tutorial modal heading should read "Your Accounts" +# And there should be an explanation of the accounts functionality. +# When On the onboarding wizard I tap on "Got it" button +# Then the tutorial modal heading should read "Edit Account Name" +# And there should be an explanation about adding a nickname to your account. +# When On the onboarding wizard I tap on "Skip" button +# Then the onboarding wizard is no longer visible +# And the "Skip" button is no longer visible +# And I close the Whats New modal diff --git a/wdio/features/Wallet/ImportCustomToken.feature b/wdio/features/Wallet/ImportCustomToken.feature index 125563e78a6..18408955cca 100644 --- a/wdio/features/Wallet/ImportCustomToken.feature +++ b/wdio/features/Wallet/ImportCustomToken.feature @@ -1,6 +1,6 @@ @androidApp @smoke -Feature: Adding a custom token to your wallet +Feature: Import Custom Token Scenario: Import wallet Given the app displayed the splash animation diff --git a/wdio/features/Wallet/LockResetWallet.feature b/wdio/features/Wallet/LockResetWallet.feature index fc37c4a7cf5..9c8d2861a8a 100644 --- a/wdio/features/Wallet/LockResetWallet.feature +++ b/wdio/features/Wallet/LockResetWallet.feature @@ -1,5 +1,5 @@ @androidApp -@regression +@smoke Feature: Lock and Reset Wallet Scenario: Import account @@ -24,4 +24,4 @@ Feature: Lock and Reset Wallet And I tap I understand, continue on Delete wallet modal And I type "delete" on Delete wallet modal permanently And I tap Delete my wallet on Delete wallet modal permanently - Then "Wallet setup" is displayed + Then Wallet setup screen is displayed diff --git a/wdio/features/Wallet/SendToken.feature b/wdio/features/Wallet/SendToken.feature index c6143405906..ed46deb49b6 100644 --- a/wdio/features/Wallet/SendToken.feature +++ b/wdio/features/Wallet/SendToken.feature @@ -1,5 +1,5 @@ @androidApp -@smoke +@regression Feature: Sending Native and ERC Tokens Scenario: Import wallet @@ -10,55 +10,23 @@ Feature: Sending Native and ERC Tokens And I close the Whats New modal Then I am on the wallet view - Scenario Outline: Adding AVAX testnet to my networks list - Given I tap on the navbar network title button - And I tap on the Add a Network button - And I tap on the "CUSTOM NETWORKS" tab - And I type "" into Network name field - And I type "" into the RPC url field - And I type "" into the Chain ID field - And I type "" into the Network symbol field - When I tap on the Add button - And I tap on Got it in the network education modal - Then I see "" visible in the top navigation bar - Examples: - | Network | rpcUrl | ChainID | Symbol | - | AVAX Fuji | https://api.avax-test.network/ext/C/rpc | 43113 | AVAX | - - Scenario Outline: Import Custom AVAX Fuji Token + Scenario Outline: Import ChainLink Token Given I tap on the navbar network title button And I tap on on Networks list to switch + And I tap on Got it in the network education modal + Then I see "" visible in the top navigation bar When I tap Import Tokens - And I type into token Address field + And I type into token Address field Then The Token Symbol is displayed When I tap on the Import button Then I should see "Imported Token" toast message Examples: - | NETWORK | TOKENADDRESS | - | AVAX Fuji | 0x5425890298aed601595a70AB815c96711a31Bc65 | - - Scenario Outline: A user can send native tokens to an Address via the wallet view send button - Given I see "" visible in the top navigation bar - And On the Main Wallet view I tap on the Send Action - And I enter address "
" in the sender's input box - When I tap button "Next" on Send To view - Then I proceed to the amount view - When I type amount "" into amount input field - And I tap button "Next" on the Amount view - Then I should be taken to the transaction confirmation view - And the token being sent is visible - And the token amount to be sent is visible - When I tap button Send on Confirm Amount view - And Sending token takes me to main wallet view - - Examples: - | NETWORK | TOKEN | AMOUNT | Address | - | AVAX Fuji | AVAX | 0.005 | 0x2990079bcdEe240329a520d2444386FC119da21a | + | NETWORK | TOKEN_ADDRESS | + | Sepolia Test Network | 0x779877A7B0D9E8603169DdbD7836e478b4624789 | Scenario Outline: A user can send ERC-20 tokens to an Address via token overview screen Given I am on the wallet view - And I see "" visible in the top navigation bar - When I tap Token containing text "" + When I tap Token containing text "" Then I am taken to the token overview screen When I tap button Send on Token screen view And I enter address "
" in the sender's input box @@ -66,19 +34,35 @@ Feature: Sending Native and ERC Tokens And I type amount "" into amount input field And I tap button "Next" on the Amount view Then I should be taken to the transaction confirmation view - And the token being sent is visible + And the token being sent is visible And the token amount to be sent is visible - When I tap button Send on Confirm Amount view - Then I am taken to the token overview screen - + When I tap button "Send" on Confirm Amount view + # Then the transaction is submitted with Transaction Complete! toast appearing + And I am taken to the token overview screen + Examples: + | TOKEN_NAME | TOKEN_SYMBOL | AMOUNT | Address | + | ChainLink Token | LINK | 0.002 | 0x2990079bcdEe240329a520d2444386FC119da21a | + Scenario Outline: A user can send native tokens to an Address via the wallet view send button + When I tap back from the Token overview page + And On the Main Wallet view I tap on the Send Action + And I enter address "
" in the sender's input box + When I tap button "Next" on Send To view + Then I proceed to the amount view + When I type amount "" into amount input field + And I tap button "Next" on the Amount view + Then I should be taken to the transaction confirmation view + And the token being sent is visible + And the token amount to be sent is visible + When I tap button "Send" on Confirm Amount view + # Then the transaction is submitted with Transaction Complete! toast appearing + And Sending token takes me to main wallet view Examples: - | NETWORK | TOKEN | AMOUNT | Address | - | AVAX Fuji | USDC | 0.002 | 0x2990079bcdEe240329a520d2444386FC119da21a | + | TOKEN | AMOUNT | Address | + | SepoliaETH | 0.002 | 0x2990079bcdEe240329a520d2444386FC119da21a | Scenario Outline: A user tries to send an invalid amount - Given I tap back from the Token overview page - And I am on the wallet view + When I am on the wallet view And On the Main Wallet view I tap on the Send Action And I enter address "
" in the sender's input box When I tap button "Next" on Send To view @@ -86,5 +70,5 @@ Feature: Sending Native and ERC Tokens And I tap button "Next" on the Amount view Then "Insufficient funds" is visible Examples: - | NETWORK | TOKEN | AMOUNT | Address | - | AVAX Fuji | 1 USDC | 121212121212121212121 | 0x2990079bcdEe240329a520d2444386FC119da21a | + | AMOUNT | Address | + | 25 | 0x2990079bcdEe240329a520d2444386FC119da21a | diff --git a/wdio/helpers/Accounts.js b/wdio/helpers/Accounts.js index c7b072a8027..ffddf1ac6b6 100644 --- a/wdio/helpers/Accounts.js +++ b/wdio/helpers/Accounts.js @@ -3,7 +3,6 @@ const INCORRECT_SECRET_RECOVERY_PHRASE = 'gain lemon refuse sunny identify diesel hand endless first involve wink size'; const CORRECT_PASSWORD = `12345678`; const SHORT_PASSWORD = `1234567`; - const INCORRECT_PASSWORD = `12345679`; class Accounts { diff --git a/wdio/helpers/Selectors.js b/wdio/helpers/Selectors.js index e643b41a479..f79005c4d22 100644 --- a/wdio/helpers/Selectors.js +++ b/wdio/helpers/Selectors.js @@ -18,7 +18,7 @@ class Selectors { } } - static async getElementsByPlatform(id) { + static async getXpathByContentDesc(id) { return driver.$$(`//*[@content-desc='${id}']`); } diff --git a/wdio/screen-objects/AccountListComponent.js b/wdio/screen-objects/AccountListComponent.js index 6a95450085d..1aa1b3582ff 100644 --- a/wdio/screen-objects/AccountListComponent.js +++ b/wdio/screen-objects/AccountListComponent.js @@ -21,7 +21,7 @@ class AccountListComponent { } get accountsListed() { - return Selectors.getElementsByPlatform(CELL_TITLE_TEST_ID); + return Selectors.getXpathByContentDesc(CELL_TITLE_TEST_ID); } async tapCreateAccountButton() { diff --git a/wdio/screen-objects/CommonScreen.js b/wdio/screen-objects/CommonScreen.js index 0e5f5a39367..052bb4bf61d 100644 --- a/wdio/screen-objects/CommonScreen.js +++ b/wdio/screen-objects/CommonScreen.js @@ -1,6 +1,7 @@ import Selectors from '../helpers/Selectors'; import Gestures from '../helpers/Gestures'; import { ANDROID_PROGRESS_BAR, TOAST_ID } from './testIDs/Common.testIds'; +import { NOTIFICATION_TITLE } from './testIDs/Components/Notification.testIds'; class CommonScreen { get toast() { @@ -11,6 +12,10 @@ class CommonScreen { return Selectors.getElementByCss(ANDROID_PROGRESS_BAR); } + get TokenNotificationTitle() { + return Selectors.getElementByPlatform(NOTIFICATION_TITLE); + } + async waitForToastToDisplay() { const element = await this.toast; await element.waitForExist(); @@ -44,6 +49,11 @@ class CommonScreen { // Taps text that contains the string await Gestures.tapByTextContaining(text); } + + async checkNoNotification() { + const notification = await this.TokenNotificationTitle; + await notification.waitForExist({reverse: true}) + } } export default new CommonScreen(); diff --git a/wdio/screen-objects/EnableSecurityChecksScreen.js b/wdio/screen-objects/EnableSecurityChecksScreen.js index b0668da9749..ceae5d7eefa 100644 --- a/wdio/screen-objects/EnableSecurityChecksScreen.js +++ b/wdio/screen-objects/EnableSecurityChecksScreen.js @@ -18,6 +18,8 @@ class EnableAutomaticSecurityChecksScreen { } async tapNoThanksButton() { + const element = await this.noThanksButton; + await element.waitForExist(1500); await Gestures.waitAndTap(this.noThanksButton); } diff --git a/wdio/screen-objects/Modals/TabBarModal.js b/wdio/screen-objects/Modals/TabBarModal.js index dbff4736c21..b8307875c0b 100644 --- a/wdio/screen-objects/Modals/TabBarModal.js +++ b/wdio/screen-objects/Modals/TabBarModal.js @@ -39,7 +39,9 @@ class TabBarModal { } async tapActionButton() { - await Gestures.waitAndTap(this.actionButton); + const actionButton = await this.actionButton + await actionButton.waitForExist(); + await Gestures.longPress(actionButton, 500); } } diff --git a/wdio/screen-objects/Modals/TermOfUseScreen.js b/wdio/screen-objects/Modals/TermOfUseScreen.js index 63a7f695ad7..70b3ed2e811 100644 --- a/wdio/screen-objects/Modals/TermOfUseScreen.js +++ b/wdio/screen-objects/Modals/TermOfUseScreen.js @@ -36,6 +36,11 @@ class TermOfUseScreen { await container.waitForDisplayed(); } + async textIsDisplayed() { + const termsText = await Selectors.getXpathElementByTextContains('Last Updated') + await termsText.waitForDisplayed(); + } + async isNotDisplayed() { const container = await this.container; await container.waitForExist({ reverse: true}); @@ -52,6 +57,16 @@ class TermOfUseScreen { await driver.pause(500); } + async acceptIsEnabled() { + const element = await this.acceptButton; + return element.isEnabled(); + } + + async isCheckBoxChecked() { + const element = await this.checkbox; + return element.isEnabled(); + } + async tapAcceptButton() { await Gestures.tap(this.acceptButton); } diff --git a/wdio/screen-objects/Onboarding/OnboardingCarousel.js b/wdio/screen-objects/Onboarding/OnboardingCarousel.js index 914b9499dba..3f4bc9ff245 100644 --- a/wdio/screen-objects/Onboarding/OnboardingCarousel.js +++ b/wdio/screen-objects/Onboarding/OnboardingCarousel.js @@ -31,8 +31,15 @@ class WelcomeScreen { async waitForSplashAnimationToDisplay() { const elem = await this.splashScreenMetamaskAnimationId; - await elem.waitForExist(); + const getStartedElem = await this.getStartedButton; + try { + await elem.waitForExist(); + } catch (error) { + console.log(`Splash screen animation element '${this.splashScreenMetamaskAnimationId}' not found`) + await getStartedElem.waitForExist(); + } } + async waitForSplashAnimationToNotExit() { const elem = await this.splashScreenMetamaskAnimationId; diff --git a/wdio/screen-objects/TokenOverviewScreen.js b/wdio/screen-objects/TokenOverviewScreen.js index 83b6a10f4f7..df8282562fd 100644 --- a/wdio/screen-objects/TokenOverviewScreen.js +++ b/wdio/screen-objects/TokenOverviewScreen.js @@ -20,7 +20,9 @@ class TokenOverviewScreen { } async tapBackButton() { - await Gestures.waitAndTap(this.backButtonTokenOverview); + const element = await this.backButtonTokenOverview; + await element.waitForDisplayed(); + await Gestures.waitAndTap(element); } async isTokenOverviewVisible() { diff --git a/wdio/screen-objects/WalletMainScreen.js b/wdio/screen-objects/WalletMainScreen.js index 030bfc2e0b0..efa5a79aeb7 100644 --- a/wdio/screen-objects/WalletMainScreen.js +++ b/wdio/screen-objects/WalletMainScreen.js @@ -1,6 +1,6 @@ import Selectors from '../helpers/Selectors'; import Gestures from '../helpers/Gestures.js'; -import {WALLET_CONTAINER_ID} from './testIDs/Screens/WalletScreen-testIds.js'; +import { WALLET_CONTAINER_ID } from './testIDs/Screens/WalletScreen-testIds.js'; import { ONBOARDING_WIZARD_STEP_1_CONTAINER_ID, ONBOARDING_WIZARD_STEP_1_NO_THANKS_ID, @@ -23,11 +23,11 @@ import { WALLET_VIEW_BURGER_ICON_ID, } from './testIDs/Screens/WalletView.testIds'; -import {DRAWER_VIEW_SETTINGS_TEXT_ID} from './testIDs/Screens/DrawerView.testIds'; +import { DRAWER_VIEW_SETTINGS_TEXT_ID } from './testIDs/Screens/DrawerView.testIds'; -import {NOTIFICATION_TITLE} from './testIDs/Components/Notification.testIds'; -import {TAB_BAR_WALLET_BUTTON} from './testIDs/Components/TabBar.testIds'; -import {BACK_BUTTON_SIMPLE_WEBVIEW} from './testIDs/Components/SimpleWebView.testIds'; +import { NOTIFICATION_TITLE } from './testIDs/Components/Notification.testIds'; +import { TAB_BAR_WALLET_BUTTON } from './testIDs/Components/TabBar.testIds'; +import { BACK_BUTTON_SIMPLE_WEBVIEW } from './testIDs/Components/SimpleWebView.testIds'; class WalletMainScreen { get wizardContainer() { @@ -152,7 +152,7 @@ class WalletMainScreen { } async tapImportNFTButton() { - await Gestures.swipe({x: 100, y: 500}, {x: 100, y: 10}); + await Gestures.swipe({ x: 100, y: 500 }, { x: 100, y: 10 }); await Gestures.waitAndTap(this.ImportNFT); } @@ -190,7 +190,7 @@ class WalletMainScreen { async isTokenTextVisible(token) { const tokenText = await Selectors.getXpathElementByTextContains(token); await expect(tokenText).toBeDisplayed(); - await tokenText.waitForExist({reverse: true}); + await tokenText.waitForExist({ reverse: true }); } async isOnboardingWizardVisible() { @@ -199,13 +199,13 @@ class WalletMainScreen { async isMainWalletViewVisible() { const element = await this.mainWalletView; - await element.waitForDisplayed(); + await element.waitForDisplayed(2500); } async waitForNotificationToDisplayed() { const element = await this.TokenNotificationTitle; await element.waitForDisplayed(); - await element.waitForExist({reverse: true}); + await element.waitForExist({ reverse: true }); } async isToastNotificationDisplayed() { @@ -213,7 +213,7 @@ class WalletMainScreen { await element.waitForDisplayed(); expect(await element.getText()).toContain('Transaction'); expect(await element.getText()).toContain('Complete!'); - await element.waitForExist({reverse: true}); + await element.waitForExist({ reverse: true }); } async isNetworkNavbarTitle(text) { diff --git a/wdio/step-definitions/common-steps.js b/wdio/step-definitions/common-steps.js index 53272b553a7..e56658cb848 100644 --- a/wdio/step-definitions/common-steps.js +++ b/wdio/step-definitions/common-steps.js @@ -1,4 +1,4 @@ -import {Given, Then, When} from '@wdio/cucumber-framework'; +import { Given, Then, When } from '@wdio/cucumber-framework'; import Accounts from '../helpers/Accounts'; import WelcomeScreen from '../screen-objects/Onboarding/OnboardingCarousel'; import OnboardingScreen from '../screen-objects/Onboarding/OnboardingScreen'; @@ -13,7 +13,12 @@ import SkipAccountSecurityModal from '../screen-objects/Modals/SkipAccountSecuri import OnboardingWizardModal from '../screen-objects/Modals/OnboardingWizardModal.js'; import LoginScreen from '../screen-objects/LoginScreen'; import TermOfUseScreen from '../screen-objects/Modals/TermOfUseScreen'; -import WhatsNewModal from "../screen-objects/Modals/WhatsNewModal"; +import WhatsNewModal from '../screen-objects/Modals/WhatsNewModal'; + +import Ganache from '../../app/util/test/ganache'; + +const ganacheServer = new Ganache(); +const validAccount = Accounts.getValidAccount(); Then(/^the Welcome Screen is displayed$/, async () => { await WelcomeScreen.waitForScreenToDisplay(); @@ -29,6 +34,7 @@ Given(/^the splash animation disappears$/, async () => { Then(/^Terms of Use is displayed$/, async () => { await TermOfUseScreen.isDisplayed(); + await TermOfUseScreen.textIsDisplayed(); }); When(/^I agree to terms$/, async () => { @@ -51,11 +57,15 @@ Given(/^I have imported my wallet$/, async () => { await MetaMetricsScreen.isScreenTitleVisible(); await MetaMetricsScreen.tapIAgreeButton(); await TermOfUseScreen.isDisplayed(); - await driver.pause(5000); + await TermOfUseScreen.textIsDisplayed(); await TermOfUseScreen.tapAgreeCheckBox(); await TermOfUseScreen.tapScrollEndButton(); - await driver.pause(); - await TermOfUseScreen.tapAcceptButton(); + if (!await TermOfUseScreen.isCheckBoxChecked()){ + await TermOfUseScreen.tapAgreeCheckBox(); + await TermOfUseScreen.tapAcceptButton(); + } else { + await TermOfUseScreen.tapAcceptButton(); + } await ImportFromSeedScreen.isScreenTitleVisible(); await ImportFromSeedScreen.typeSecretRecoveryPhrase(validAccount.seedPhrase); await ImportFromSeedScreen.typeNewPassword(validAccount.password); @@ -117,7 +127,7 @@ Given(/^I tap No thanks on the onboarding welcome tutorial/, async () => { }); Then(/^"([^"]*)?" is visible/, async (text) => { - const timeout = 1000; + const timeout = 2500; await driver.pause(timeout); await CommonScreen.isTextDisplayed(text); }); @@ -134,6 +144,12 @@ Then(/^"([^"]*)?" is not displayed/, async (text) => { await CommonScreen.isTextElementNotDisplayed(text); }); +Then(/^"([^"]*)?" is displayed/, async (text) => { + const timeout = 1000; + await driver.pause(timeout); + await CommonScreen.isTextDisplayed(text); +}); + Then(/^Sending token takes me to main wallet view/, async () => { const timeout = 1000; await driver.pause(timeout); @@ -186,6 +202,7 @@ When(/^I unlock wallet with (.*)$/, async (password) => { Then( /^I tap (.*) "([^"]*)?" on (.*) (.*) view/, async (elementType, button, screen, type) => { + await CommonScreen.checkNoNotification(); // Notification appears a little late and inteferes with clicking function await CommonScreen.tapOnText(button); }, ); @@ -224,8 +241,17 @@ When(/^the toast is displayed$/, async () => { await CommonScreen.waitForToastToDisplay(); await CommonScreen.waitForToastToDisappear(); }); + Given(/^I close the Whats New modal$/, async () => { await WhatsNewModal.waitForDisplay(); await WhatsNewModal.tapCloseButton(); await WhatsNewModal.waitForDisappear(); }); + +Given(/^Ganache server is started$/, async () => { + await ganacheServer.start({ mnemonic: validAccount.seedPhrase }); +}); + +Then(/^Ganache server is stopped$/, async () => { + await ganacheServer.quit(); +}); \ No newline at end of file diff --git a/wdio/step-definitions/create-new-wallet-account.steps.js b/wdio/step-definitions/create-new-wallet-account.steps.js index 09e782a15ec..a2f29f9e2b4 100644 --- a/wdio/step-definitions/create-new-wallet-account.steps.js +++ b/wdio/step-definitions/create-new-wallet-account.steps.js @@ -17,6 +17,5 @@ When(/^A new account is created/, async () => { Then(/^I am on the new account/, async () => { await WalletMainScreen.tapIdenticon(); - await AccountListComponent.isComponentNotDisplayed(); - await WalletAccountModal.isAccountNameLabelEqualTo('Account 2'); + await WalletAccountModal.isAccountNameLabelEqualTo('Account 2'); // this could be better. This stemp could be a bit more dynmic }); diff --git a/wdio/step-definitions/import-wallet-via-private-key.steps.js b/wdio/step-definitions/import-wallet-via-private-key.steps.js index 48bf9e53709..c4e26cf87ce 100644 --- a/wdio/step-definitions/import-wallet-via-private-key.steps.js +++ b/wdio/step-definitions/import-wallet-via-private-key.steps.js @@ -31,6 +31,7 @@ Then(/^The account is imported/, async () => { }); Then(/^I should see an error (.*)/, async (errorMessage) => { + await driver.pause(1000); await ImportAccountScreen.isAlertTextVisible(errorMessage); await driver.acceptAlert(); }); diff --git a/wdio/step-definitions/onboarding.steps.js b/wdio/step-definitions/onboarding.steps.js index 48d0eab2926..c020b5c522a 100644 --- a/wdio/step-definitions/onboarding.steps.js +++ b/wdio/step-definitions/onboarding.steps.js @@ -16,9 +16,6 @@ Then(/^"([^"]*)?" is displayed/, async (text) => { await WelcomeScreen.waitForSplashAnimationToDisplay(); await WelcomeScreen.waitForSplashAnimationToNotExit(); break; - case 'Wallet setup': - await OnboardingScreen.isScreenTitleVisible(); - break; case 'Import an existing wallet or create a new one': await OnboardingScreen.isScreenDescriptionVisible(); break; @@ -91,6 +88,11 @@ When(/^I tap "([^"]*)"/, async (text) => { } }); +Then(/^Wallet setup screen is displayed/, async () => { + // await driver.pause(3000); + await OnboardingScreen.isScreenTitleVisible(); +}); + When(/^I type (.*) in SRP field/, async (text) => { await ImportFromSeedScreen.typeSecretRecoveryPhrase(text); }); diff --git a/wdio/step-definitions/send-flow.steps.js b/wdio/step-definitions/send-flow.steps.js index db810eb9c83..0a76720c5fa 100644 --- a/wdio/step-definitions/send-flow.steps.js +++ b/wdio/step-definitions/send-flow.steps.js @@ -6,6 +6,7 @@ import AmountScreen from '../screen-objects/AmountScreen'; import WalletMainScreen from '../screen-objects/WalletMainScreen'; import TokenOverviewScreen from '../screen-objects/TokenOverviewScreen'; import TransactionConfirmScreen from '../screen-objects/TransactionConfirmScreen'; +import CommonScreen from '../screen-objects/CommonScreen'; Then(/^On the Address book modal Cancel button is enabled/, async () => { await AddressBookModal.isCancelButtonEnabled(); @@ -30,7 +31,9 @@ Then(/^I tap the Save button/, async () => { Given( /^I enter address "([^"]*)?" in the sender's input box/, async (address) => { + await CommonScreen.checkNoNotification(); // Notification appears a little late and inteferes with clicking function await SendScreen.typeAddressInSendAddressField(address); + await driver.hideKeyboard(); }, ); @@ -104,11 +107,13 @@ Then( /^I enter invalid address "([^"]*)?" into senders input field/, async (address) => { await SendScreen.typeAddressInSendAddressField(address); + await driver.hideKeyboard(); }, ); Then(/^I type amount "([^"]*)?" into amount input field/, async (amount) => { await AmountScreen.enterAmount(amount); + await driver.hideKeyboard(); }); Then( @@ -124,6 +129,7 @@ Then(/^I am taken to the token overview screen/, async () => { Then(/^I tap back from the Token overview page/, async () => { await TokenOverviewScreen.tapBackButton(); + await TokenOverviewScreen.tapBackButton();// Double tap seems to work best on BS }); When(/^I tap button Send on Token screen view$/, async () => { diff --git a/wdio/step-definitions/wallet-view.steps.js b/wdio/step-definitions/wallet-view.steps.js index 6490eec7021..bb143e4539f 100644 --- a/wdio/step-definitions/wallet-view.steps.js +++ b/wdio/step-definitions/wallet-view.steps.js @@ -77,6 +77,7 @@ Then(/^Wallet view is displayed$/, async () => { }); Given(/^On the Main Wallet view I tap on the Send Action$/, async () => { + await CommonScreen.checkNoNotification(); await TabBarModal.tapActionButton(); await WalletActionModal.tapSendButton(); }); diff --git a/wdio/utils/generateTestReports.js b/wdio/utils/generateTestReports.js index 60fab93507a..0c413b5e444 100644 --- a/wdio/utils/generateTestReports.js +++ b/wdio/utils/generateTestReports.js @@ -1,6 +1,13 @@ -const fs = require('fs'); -const xml2js = require('xml2js'); -const { generate } = require('multiple-cucumber-html-reporter'); +import { + readdirSync, + readFileSync, + existsSync, + mkdirSync, + renameSync, + writeFileSync, +} from 'fs'; +import { Parser } from 'xml2js'; +import { generate } from 'multiple-cucumber-html-reporter'; function generateTestReports() { // Generate the report when it all tests are done @@ -10,37 +17,38 @@ function generateTestReports() { // for more options see https://github.com/wswebcreation/multiple-cucumber-html-reporter#options }); - const testSuites = fs.readdirSync('./wdio/reports/junit-results'); + const testSuites = readdirSync('./wdio/reports/junit-results'); testSuites.forEach((testSuite) => { - const file = fs.readFileSync( + const file = readFileSync( `./wdio/reports/junit-results/${testSuite}`, 'utf8', ); - const parser = new xml2js.Parser(); + const parser = new Parser(); parser.parseString(file, (err, result) => { - if (err) { - throw err; - } - const suiteName = result.testsuites.testsuite[0].$.name; - // Create dir for each test suite - if (!fs.existsSync(`./wdio/reports/junit-results/${suiteName}`)) { - fs.mkdirSync(`./wdio/reports/junit-results/${suiteName}`); - fs.renameSync( - `./wdio/reports/junit-results/${testSuite}`, - `./wdio/reports/junit-results/${suiteName}/${suiteName}.xml`, - ); - // Create test-info.json file for each test suite - const testInfo = { - 'test-name': suiteName, - }; - fs.writeFileSync( - `./wdio/reports/junit-results/${suiteName}/test-info.json`, - JSON.stringify(testInfo), - ); + try { + const suiteName = result.testsuites.testsuite[0].$.name; + // Create dir for each test suite + if (!existsSync(`./wdio/reports/junit-results/${suiteName}`)) { + mkdirSync(`./wdio/reports/junit-results/${suiteName}`); + renameSync( + `./wdio/reports/junit-results/${testSuite}`, + `./wdio/reports/junit-results/${suiteName}/${suiteName}.xml`, + ); + // Create test-info.json file for each test suite + const testInfo = { + 'test-name': suiteName, + }; + writeFileSync( + `./wdio/reports/junit-results/${suiteName}/test-info.json`, + JSON.stringify(testInfo), + ); + } + } catch (error) { + //do nothing for now } }); }); } -module.exports = generateTestReports; +export default generateTestReports; diff --git a/yarn.lock b/yarn.lock index 6425b076007..0b528436785 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1636,6 +1636,13 @@ dependencies: "@cucumber/messages" "^19.0.0" +"@cucumber/gherkin@26.0.3": + version "26.0.3" + resolved "https://registry.yarnpkg.com/@cucumber/gherkin/-/gherkin-26.0.3.tgz#6ffe37570c608caa329784161305056135a19c96" + integrity sha512-xwJHi//bLFEU1drIyw2yswwUHnnVWO4XcyVBbCTDs6DkSh262GkogFI/IWwChZqJfOXnPglzLGxR1DibcZsILA== + dependencies: + "@cucumber/messages" "19.1.4 - 21" + "@cucumber/gherkin@^24.1.0": version "24.1.0" resolved "https://registry.yarnpkg.com/@cucumber/gherkin/-/gherkin-24.1.0.tgz#ca2dcbe11f5f7d7f30fd073280550bd6eca2363c" @@ -1656,7 +1663,7 @@ resolved "https://registry.yarnpkg.com/@cucumber/html-formatter/-/html-formatter-20.0.0.tgz#d0958b2d53a6f5ce0fb6f6d7eac88902e9b31030" integrity sha512-I6ZzUZ0CkaaPm6QHThoCRmdcuEIV9kJlNjaWvQ3PRkJm0OscQkQ0SXL/j73U30RDPiCAWwtq6ZSeQrgkTnSK+Q== -"@cucumber/message-streams@4.0.1": +"@cucumber/message-streams@4.0.1", "@cucumber/message-streams@^4.0.1": version "4.0.1" resolved "https://registry.yarnpkg.com/@cucumber/message-streams/-/message-streams-4.0.1.tgz#a5339d3504594bb2edb5732aaae94dddb24d0970" integrity sha512-Kxap9uP5jD8tHUZVjTWgzxemi/0uOsbGjd4LBOSxcJoOCRbESFwemUzilJuzNTB8pcTQUh8D5oudUyxfkJOKmA== @@ -1678,10 +1685,10 @@ reflect-metadata "0.1.13" uuid "8.3.2" -"@cucumber/messages@19.1.4", "@cucumber/messages@^19.0.0", "@cucumber/messages@^19.1.4": - version "19.1.4" - resolved "https://registry.yarnpkg.com/@cucumber/messages/-/messages-19.1.4.tgz#5cefc47cac3004c0bc38d42933042ec248bb747c" - integrity sha512-Pksl0pnDz2l1+L5Ug85NlG6LWrrklN9qkMxN5Mv+1XZ3T6u580dnE6mVaxjJRdcOq4tR17Pc0RqIDZMyVY1FlA== +"@cucumber/messages@19.1.4 - 21", "@cucumber/messages@21.0.1": + version "21.0.1" + resolved "https://registry.yarnpkg.com/@cucumber/messages/-/messages-21.0.1.tgz#1468cef60d6da4d4f540a70ab1265f6540f44f51" + integrity sha512-pGR7iURM4SF9Qp1IIpNiVQ77J9kfxMkPOEbyy+zRmGABnWWCsqMpJdfHeh9Mb3VskemVw85++e15JT0PYdcR3g== dependencies: "@types/uuid" "8.3.4" class-transformer "0.5.1" @@ -1698,6 +1705,26 @@ reflect-metadata "0.1.13" uuid "8.3.2" +"@cucumber/messages@^19.0.0", "@cucumber/messages@^19.1.4": + version "19.1.4" + resolved "https://registry.yarnpkg.com/@cucumber/messages/-/messages-19.1.4.tgz#5cefc47cac3004c0bc38d42933042ec248bb747c" + integrity sha512-Pksl0pnDz2l1+L5Ug85NlG6LWrrklN9qkMxN5Mv+1XZ3T6u580dnE6mVaxjJRdcOq4tR17Pc0RqIDZMyVY1FlA== + dependencies: + "@types/uuid" "8.3.4" + class-transformer "0.5.1" + reflect-metadata "0.1.13" + uuid "9.0.0" + +"@cucumber/messages@^22.0.0": + version "22.0.0" + resolved "https://registry.yarnpkg.com/@cucumber/messages/-/messages-22.0.0.tgz#2d86974ebd73046f66d217334c2245365c7990d4" + integrity sha512-EuaUtYte9ilkxcKmfqGF9pJsHRUU0jwie5ukuZ/1NPTuHS1LxHPsGEODK17RPRbZHOFhqybNzG2rHAwThxEymg== + dependencies: + "@types/uuid" "9.0.1" + class-transformer "0.5.1" + reflect-metadata "0.1.13" + uuid "9.0.0" + "@cucumber/tag-expressions@4.1.0": version "4.1.0" resolved "https://registry.yarnpkg.com/@cucumber/tag-expressions/-/tag-expressions-4.1.0.tgz#9a91b0e0dd2f2ba703e3038c52b49b9ac06c2c6f" @@ -3911,21 +3938,6 @@ resolved "https://registry.yarnpkg.com/@log4js-node/log4js-api/-/log4js-api-1.0.2.tgz#7a8143fb33f077df3e579dca7f18fea74a02ec8b" integrity sha512-6SJfx949YEWooh/CUPpJ+F491y4BYJmknz4hUN1+RHvKoUEynKbRmhnwbk/VLmh4OthLLDNCyWXfbh4DG1cTXA== -"@mapbox/node-pre-gyp@^1.0.0": - version "1.0.10" - resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.10.tgz#8e6735ccebbb1581e5a7e652244cadc8a844d03c" - integrity sha512-4ySo4CjzStuprMwk35H5pPbkymjv1SF3jGLj6rAHp/xT/RF7TL7bd9CTm1xDY49K2qF7jmR/g7k+SkLETP6opA== - dependencies: - detect-libc "^2.0.0" - https-proxy-agent "^5.0.0" - make-dir "^3.1.0" - node-fetch "^2.6.7" - nopt "^5.0.0" - npmlog "^5.0.1" - rimraf "^3.0.2" - semver "^7.3.5" - tar "^6.1.11" - "@metamask/abi-utils@^1.1.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@metamask/abi-utils/-/abi-utils-1.2.0.tgz#068e1b0f5e423dfae96961e0e5276a7c1babc03a" @@ -3934,40 +3946,40 @@ "@metamask/utils" "^3.4.1" superstruct "^1.0.3" -"@metamask/address-book-controller@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@metamask/address-book-controller/-/address-book-controller-1.1.0.tgz#45106353c113c17357bb23a5191eb0bd56cbfc8d" - integrity sha512-J2oJkt2cgiSdl/qwjG4hVlCn9bSdB/WxkS3m4zwC8BEv/pJPfxkgl/yyNp9hk/JVCRigTGe5CTuFwkoRjzz8zQ== +"@metamask/address-book-controller@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@metamask/address-book-controller/-/address-book-controller-2.0.0.tgz#5866282c0c1c95e7c6cf7058b86962e74c9955fd" + integrity sha512-gifdVdIKOWMK/UGX97CucpBXQy+Yk4KmOWd2j9Hbu6j296htqdAvo2NfvVTGtUG2JRNnNg3qsGIJ8V/lVntSww== dependencies: - "@metamask/base-controller" "^1.1.2" - "@metamask/controller-utils" "^2.0.0" + "@metamask/base-controller" "^2.0.0" + "@metamask/controller-utils" "^3.0.0" -"@metamask/approval-controller@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@metamask/approval-controller/-/approval-controller-1.1.0.tgz#1f0c89ffa3a60600f69886ffb9a8bd06ef823b32" - integrity sha512-6RFPMUayRDxe1ZrkDPIqPNSQ10pMUB1uGr8c52X7gm+EEaS3OnZV4qLMASvwpu7gNQe5dFiCZPypRHlM5qiq+A== +"@metamask/approval-controller@^2.0.0", "@metamask/approval-controller@~2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@metamask/approval-controller/-/approval-controller-2.0.0.tgz#a4a129ba9377465257c6dc632a92af9273b3a112" + integrity sha512-NbRJdtyfPyY810xGcZqI+MqtvouRC39pYBCA+BZCvXEoam0b+g9Z/j0QOMLrplSSWM7OsNNQP5Q/Ge1R07ERmw== dependencies: - "@metamask/base-controller" "^1.1.2" - "@metamask/controller-utils" "^2.0.0" + "@metamask/base-controller" "^2.0.0" + "@metamask/controller-utils" "^3.0.0" eth-rpc-errors "^4.0.0" immer "^9.0.6" nanoid "^3.1.31" -"@metamask/assets-controllers@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@metamask/assets-controllers/-/assets-controllers-4.0.0.tgz#81278619128cf6b22503584eebcd25a529e42386" - integrity sha512-e/ngelUbyo6drDsIm/lzh7qf43Laju/sxDLaEtolRWJDVW8ZiTrWzCAVQ1m7aduVIS7WDUR51uKzsxiTWY19cA== +"@metamask/assets-controllers@5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@metamask/assets-controllers/-/assets-controllers-5.0.0.tgz#6622fa3e400a4d380ec7d36bb8ba4159f33788ee" + integrity sha512-Ix93B4SRMmvUVwyVvz4SkjaWBwTD1HMvxmeFyWxhE18k46wTSKsq5bQ3pk7D5jgcWFDFdgFJ4Mv1TCcW2dDbnw== dependencies: "@ethersproject/bignumber" "^5.7.0" "@ethersproject/contracts" "^5.7.0" "@ethersproject/providers" "^5.7.0" "@metamask/abi-utils" "^1.1.0" - "@metamask/base-controller" "^1.1.2" + "@metamask/base-controller" "^2.0.0" "@metamask/contract-metadata" "^2.1.0" - "@metamask/controller-utils" "^2.0.0" + "@metamask/controller-utils" "^3.0.0" "@metamask/metamask-eth-abis" "3.0.0" - "@metamask/network-controller" "^3.0.0" - "@metamask/preferences-controller" "^1.0.2" + "@metamask/network-controller" "^5.0.0" + "@metamask/preferences-controller" "^2.0.0" "@metamask/utils" "^3.3.1" "@types/uuid" "^8.3.0" abort-controller "^3.0.0" @@ -3989,14 +4001,6 @@ "@metamask/controller-utils" "^1.0.0" immer "^9.0.6" -"@metamask/base-controller@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@metamask/base-controller/-/base-controller-1.1.2.tgz#92643d16a322664adae924cf45806c96c6704e30" - integrity sha512-lOV3dyaTw+dTZOYkpjFwKN4DfOlvRpALknUlOzoFg+ChLeva8T7E4/pyo52FOEtxhajsq9/77soGm729oaNGMA== - dependencies: - "@metamask/controller-utils" "^2.0.0" - immer "^9.0.6" - "@metamask/base-controller@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@metamask/base-controller/-/base-controller-2.0.0.tgz#8f9130df3edaa270ade00378cf57917545d44617" @@ -4015,43 +4019,19 @@ pbkdf2 "^3.0.9" randombytes "^2.0.1" -"@metamask/composable-controller@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@metamask/composable-controller/-/composable-controller-1.0.2.tgz#d6c7528084e34c17df3009efe1d9cd58bdf69187" - integrity sha512-nDFlFKsajuiw/HaeLqBUuEfpgUpRZenY0a0atiWwNQ2B3EETPATICaPT179owgXiXUI3rhQdRmLn7sX6WEs5GQ== +"@metamask/composable-controller@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@metamask/composable-controller/-/composable-controller-2.0.0.tgz#a3549c5ad150d2c74e575987968de4b8f8ae5d9b" + integrity sha512-vc1OVUtP/h9BYtYQtcJxbwzXKg/ELUguZ7XzT/yEIFUJh9m+1c8f1YPq7wYq1qmSF37U/5O4e/1d7GhJRJw9Dg== dependencies: - "@metamask/base-controller" "^1.1.2" + "@metamask/base-controller" "^2.0.0" "@metamask/contract-metadata@^1.31.0", "@metamask/contract-metadata@^2.1.0": version "2.2.0" resolved "https://registry.yarnpkg.com/@metamask/contract-metadata/-/contract-metadata-2.2.0.tgz#277764d0d56e37180ae7644a9d11eb96295b36fc" integrity sha512-SM6A4C7vXNbVpgMTX67kfW8QWvu3eSXxMZlY5PqZBTkvri1s9zgQ0uwRkK5r2VXNEoVmXCDnnEX/tX5EzzgNUQ== -"@metamask/controller-utils@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@metamask/controller-utils/-/controller-utils-1.0.0.tgz#2e2261b65c3f38ba0c5b893743fca8cce764339c" - integrity sha512-LXIpnmF/C5/vCBX0u2DiUWA55utZy54guUV+A8qUYmz8PvZrXfK7mdq1zlk8z0aq+aO0rHHfSVbTNacEE3TlAQ== - dependencies: - eth-ens-namehash "^2.0.8" - eth-rpc-errors "^4.0.0" - ethereumjs-util "^7.0.10" - ethjs-unit "^0.1.6" - fast-deep-equal "^3.1.3" - isomorphic-fetch "^3.0.0" - -"@metamask/controller-utils@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@metamask/controller-utils/-/controller-utils-2.0.0.tgz#11b7639b7724b67c4ad983fd1185313fff2217be" - integrity sha512-dwpF1qPIGzTr6kMAJQmX6/eVtRPrBBMlB9oiHnOhHN2mYPqd6fCnesyA3TsqM8I65mTjqrkV4OtPtz6pzYvclw== - dependencies: - eth-ens-namehash "^2.0.8" - eth-rpc-errors "^4.0.0" - ethereumjs-util "^7.0.10" - ethjs-unit "^0.1.6" - fast-deep-equal "^3.1.3" - isomorphic-fetch "^3.0.0" - -"@metamask/controller-utils@^3.0.0": +"@metamask/controller-utils@^1.0.0", "@metamask/controller-utils@^3.0.0", "@metamask/controller-utils@^3.1.0", "@metamask/controller-utils@~3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@metamask/controller-utils/-/controller-utils-3.0.0.tgz#e0984cdab14280409297671b5858891527c5e4ee" integrity sha512-JjFWBZnnh5DSX2tRsw5xtXxaqVkTzaW7mkSZ+lL3LoCAw47Cf8zGP1kGR6VKxcceKi+MpEFvZr7gf1OFnOoEjw== @@ -4144,14 +4124,14 @@ resolved "https://registry.yarnpkg.com/@metamask/etherscan-link/-/etherscan-link-2.1.0.tgz#c0be8e68445b7b83cf85bcc03a56cdf8e256c973" integrity sha512-ADuWlTUkFfN2vXlz81Bg/0BA+XRor+CdK1055p6k7H6BLIPoDKn9SBOFld9haQFuR9cKh/JYHcnlSIv5R4fUEw== -"@metamask/gas-fee-controller@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@metamask/gas-fee-controller/-/gas-fee-controller-3.0.0.tgz#6b6c81ba9e553b253e4875bacf6f84e17d2238e1" - integrity sha512-5kFnfqimsRAJKydjG8jgGFdosjDI42+72vIPuGeCZkSV93KsXX30NjrQQD6Sl1ZJjyfmysdQbFS6unsOheU0lg== +"@metamask/gas-fee-controller@4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@metamask/gas-fee-controller/-/gas-fee-controller-4.0.0.tgz#b3532373ed1a245aaecdd23903a02951e20ee47b" + integrity sha512-dIN8e4UAU8uOjUk4Zl1l8fwsWk8vFpFoeng2VHvfxkvDkK5XxNbxF4IidffRnoJpCaynNWNH0Y+7QrtSR3qf+w== dependencies: - "@metamask/base-controller" "^1.1.2" - "@metamask/controller-utils" "^2.0.0" - "@metamask/network-controller" "^3.0.0" + "@metamask/base-controller" "^2.0.0" + "@metamask/controller-utils" "^3.0.0" + "@metamask/network-controller" "^5.0.0" "@types/uuid" "^8.3.0" babel-runtime "^6.26.0" eth-query "^2.1.2" @@ -4189,13 +4169,13 @@ jsonschema "^1.2.4" uuid "^8.3.2" -"@metamask/message-manager@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@metamask/message-manager/-/message-manager-1.0.2.tgz#2474ed1a3f60884bf79d47533b61bb55baf26614" - integrity sha512-HX4e4GnpQxAQLGL+BeHxZcjTBgt0a4S2MBpLoEvgStMHpfiuEanZfhKTgDUR12BKcctw9SMyfcKNvyKBaxYD6Q== +"@metamask/message-manager@^2.0.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@metamask/message-manager/-/message-manager-2.1.0.tgz#0048eb56d37798a4d92bba51bc816e02b2983ed3" + integrity sha512-tHa+Hky2cLJAkmKa1wx+8s7Daxpa9E/OJJQ62666ASgAFqV+cvxilGAcTwUOYnx+ZHa1kzvGatE0KePsnHJ2HQ== dependencies: - "@metamask/base-controller" "^1.1.2" - "@metamask/controller-utils" "^2.0.0" + "@metamask/base-controller" "^2.0.0" + "@metamask/controller-utils" "^3.1.0" "@types/uuid" "^8.3.0" eth-sig-util "^3.0.0" ethereumjs-util "^7.0.10" @@ -4212,13 +4192,13 @@ resolved "https://registry.yarnpkg.com/@metamask/mobile-provider/-/mobile-provider-2.1.0.tgz#685b2f6a55d24197af3f26de4dd0bb78e10ac83e" integrity sha512-VuVUIZ5jEQmLaU8SJC8692crxtNncsxyR9q5j1J6epyMHUU75WTtQdq7VSsu1ghkmP9NXNAz3inlWOGsbT8lLA== -"@metamask/network-controller@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@metamask/network-controller/-/network-controller-3.0.0.tgz#f43dd9588240bed187a078da2bd3f758b3338172" - integrity sha512-SjffWl0kLqeT6F4X2EFHkPu5fkCMF+hblqM+BvDnDoanSFDk7Dcw+jXKSv7sw5QDX2DcfYtqvZbms2VWXu3x6g== +"@metamask/network-controller@^5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@metamask/network-controller/-/network-controller-5.0.0.tgz#7f14a06f9ebec738888d6e2bf10ae05a4caabcb6" + integrity sha512-rYZl/geh3+M03umPJrWkkMhy+hJL6L0P7rV+KwzFwgfE8jL3EdB+Z9PtIVkGj0qj/8QIswhP3j/xAFWzyRlsZw== dependencies: - "@metamask/base-controller" "^1.1.2" - "@metamask/controller-utils" "^2.0.0" + "@metamask/base-controller" "^2.0.0" + "@metamask/controller-utils" "^3.0.0" async-mutex "^0.2.6" babel-runtime "^6.26.0" eth-json-rpc-infura "^5.1.0" @@ -4234,14 +4214,14 @@ "@metamask/safe-event-emitter" "^2.0.0" through2 "^2.0.3" -"@metamask/permission-controller@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@metamask/permission-controller/-/permission-controller-2.0.0.tgz#04135b7164a13df71f0f9b70de0a9fbd09f8a15a" - integrity sha512-KKnRc1F+N7fI8AXNxS+X21E1X0yQrBoqCGDn1WX5QPPOZ/wjvDbrPxaCK/Vkd2TxDosJ2jmA5HSl2TFY5X7U0w== +"@metamask/permission-controller@~3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@metamask/permission-controller/-/permission-controller-3.0.0.tgz#2c58f749c4fc192743fd2e5fad5ffa503ba1c068" + integrity sha512-902jw48yetCsNo6DGrXKHDWWz/QzdmC90O6Am5WgUmwUlboU9Mr0uS8Fp8b7qPQiDZRXz8PvckodyEX2XNW+tQ== dependencies: - "@metamask/approval-controller" "^1.1.0" - "@metamask/base-controller" "^1.1.2" - "@metamask/controller-utils" "^2.0.0" + "@metamask/approval-controller" "^2.0.0" + "@metamask/base-controller" "^2.0.0" + "@metamask/controller-utils" "^3.0.0" "@metamask/types" "^1.1.0" "@types/deep-freeze-strict" "^1.1.0" deep-freeze-strict "^1.1.1" @@ -4250,16 +4230,15 @@ json-rpc-engine "^6.1.0" nanoid "^3.1.31" -"@metamask/phishing-controller@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@metamask/phishing-controller/-/phishing-controller-2.0.0.tgz#4a5471a70af5353d4c33a4f9a756f7e0070cb163" - integrity sha512-dI8LQD4q4o2pVvBTWGpjnrK+MMwV1/CkmKh6ga0hy4aDDcw7hLJuDGM3b+R7lPvS3QEb0WJNH76qyaIeR2FQaw== +"@metamask/phishing-controller@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@metamask/phishing-controller/-/phishing-controller-3.0.0.tgz#6a5d93f29354468e416f670d2892e3228b5fd562" + integrity sha512-U5TTGod1up/qiClswmjyfZjedzuj1wOcrHSYWyD2u4f1Tq0slcF9vbqV2nDWHslK6z+3hyuUTESd48SZ61sFjA== dependencies: - "@metamask/base-controller" "^1.1.2" - "@metamask/controller-utils" "^2.0.0" + "@metamask/base-controller" "^2.0.0" + "@metamask/controller-utils" "^3.0.0" "@types/punycode" "^2.1.0" eth-phishing-detect "^1.2.0" - isomorphic-fetch "^3.0.0" punycode "^2.1.1" "@metamask/preferences-controller@^1.0.1": @@ -4270,15 +4249,7 @@ "@metamask/base-controller" "^1.1.1" "@metamask/controller-utils" "^1.0.0" -"@metamask/preferences-controller@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@metamask/preferences-controller/-/preferences-controller-1.0.2.tgz#44deb138f63763ac2300753fde36616d791c1402" - integrity sha512-oITXsI5sypaIv2rzr07zvfiWB8L906mB2ff/MVOHR+dgAq8bgmcym01jdJEu8YlVQgFB63E+C6qgtm0F7AwEww== - dependencies: - "@metamask/base-controller" "^1.1.2" - "@metamask/controller-utils" "^2.0.0" - -"@metamask/preferences-controller@^2.1.0": +"@metamask/preferences-controller@^2.0.0", "@metamask/preferences-controller@^2.1.0": version "2.1.0" resolved "https://registry.yarnpkg.com/@metamask/preferences-controller/-/preferences-controller-2.1.0.tgz#c3ed464259f3f969ff492167c368752d23db3924" integrity sha512-/GvYSaCCT0DVDZLlt8eiJDcw7WNFeIMpssP0X0+MK+Ye5eGEMp0Wo0n5uoMOKDR+x3HnWo5YuVGHBlSCnusEeg== @@ -4317,16 +4288,16 @@ human-standard-token-abi "^2.0.0" web3 "^0.20.7" -"@metamask/transaction-controller@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@metamask/transaction-controller/-/transaction-controller-3.0.0.tgz#91b556b3c88787c854328b64822eaa14c59ce292" - integrity sha512-xlJIWUFznki3Nh+txI6cKVwKYgF79itmef9Ml5icjBfLOsyMe7up4I/SJ+228+fWw1PycYClmCyIbHc3vREZXA== +"@metamask/transaction-controller@4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@metamask/transaction-controller/-/transaction-controller-4.0.0.tgz#adf95691861f8839180772bbfd16409126d85a2f" + integrity sha512-CR1LzcA10TotuH4DSCGJlquYh4P1yDVkP+3VGkyGk6XL2Co5wy3igt8dIs1WKebccPEP540oy7yYG4amcW9hVw== dependencies: "@ethereumjs/common" "^2.6.1" "@ethereumjs/tx" "^3.5.2" - "@metamask/base-controller" "^1.1.2" - "@metamask/controller-utils" "^2.0.0" - "@metamask/network-controller" "^3.0.0" + "@metamask/base-controller" "^2.0.0" + "@metamask/controller-utils" "^3.0.0" + "@metamask/network-controller" "^5.0.0" async-mutex "^0.2.6" babel-runtime "^6.26.0" eth-method-registry "1.1.0" @@ -5525,11 +5496,25 @@ resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d" integrity sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag== -"@types/fs-extra@^9.0.4": - version "9.0.13" - resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-9.0.13.tgz#7594fbae04fe7f1918ce8b3d213f74ff44ac1f45" - integrity sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA== +"@types/fs-extra@^11.0.1": + version "11.0.1" + resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-11.0.1.tgz#f542ec47810532a8a252127e6e105f487e0a6ea5" + integrity sha512-MxObHvNl4A69ofaTRU8DFqvgzzv8s9yRtaPPm5gud9HDNvpB3GPQFvNuTWAI59B9huVGV5jXYJwbCsmBsOGYWA== + dependencies: + "@types/jsonfile" "*" + "@types/node" "*" + +"@types/gitconfiglocal@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@types/gitconfiglocal/-/gitconfiglocal-2.0.1.tgz#c134f9fb03d71917afa35c14f3b82085520509a6" + integrity sha512-AYC38la5dRwIfbrZhPNIvlGHlIbH+kdl2j8A37twoCQyhKPPoRPfVmoBZKajpLIfV7SMboU6MZ6w/RmZLH68IQ== + +"@types/glob@^8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@types/glob/-/glob-8.1.0.tgz#b63e70155391b0584dce44e7ea25190bbc38f2fc" + integrity sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w== dependencies: + "@types/minimatch" "^5.1.2" "@types/node" "*" "@types/graceful-fs@^4.1.2": @@ -5574,6 +5559,11 @@ resolved "https://registry.yarnpkg.com/@types/is-glob/-/is-glob-4.0.2.tgz#c243dd0d09eac2992130142419ff2308ffd988bf" integrity sha512-4j5G9Y5jljDSICQ1R2f/Rcyoj6DZmYGneny+p/cDkjep0rkqNg0W73Ty0bVjMUTZgLXHf8oiMjg1XC3CDwCz+g== +"@types/is-url@^1.2.30": + version "1.2.30" + resolved "https://registry.yarnpkg.com/@types/is-url/-/is-url-1.2.30.tgz#85567e8bee4fee69202bc3448f9fb34b0d56c50a" + integrity sha512-AnlNFwjzC8XLda5VjRl4ItSd8qp8pSNowvsut0WwQyBWHpOxjxRJm8iO6uETWqEyLdYdb9/1j+Qd9gQ4l5I4fw== + "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": version "2.0.3" resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz#4ba8ddb720221f432e443bd5f9117fd22cfd4762" @@ -5626,6 +5616,13 @@ resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= +"@types/jsonfile@*": + version "6.1.1" + resolved "https://registry.yarnpkg.com/@types/jsonfile/-/jsonfile-6.1.1.tgz#ac84e9aefa74a2425a0fb3012bdea44f58970f1b" + integrity sha512-GSgiRCVeapDN+3pqA35IkQwasaCh/0YFH5dEF6S88iDvEn901DjOeH3/QPY+XYP1DFzDZPvIvfeEgk+7br5png== + dependencies: + "@types/node" "*" + "@types/keyv@*": version "3.1.4" resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.4.tgz#3ccdb1c6751b0c7e52300bcdacd5bcbf8faa75b6" @@ -5669,6 +5666,11 @@ resolved "https://registry.yarnpkg.com/@types/lru-cache/-/lru-cache-5.1.1.tgz#c48c2e27b65d2a153b19bfc1a317e30872e01eef" integrity sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw== +"@types/minimatch@^5.1.2": + version "5.1.2" + resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca" + integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA== + "@types/mockery@^1.4.29": version "1.4.30" resolved "https://registry.yarnpkg.com/@types/mockery/-/mockery-1.4.30.tgz#25f07fa7340371c7ee0fb9239511a34e0a19d5b7" @@ -5952,6 +5954,11 @@ resolved "https://registry.yarnpkg.com/@types/ua-parser-js/-/ua-parser-js-0.7.36.tgz#9bd0b47f26b5a3151be21ba4ce9f5fa457c5f190" integrity sha512-N1rW+njavs70y2cApeIw1vLMYXRwfBy+7trgavGuuTfOd7j1Yh7QTRc/yqsPl6ncokt72ZXuxEU0PiCp9bSwNQ== +"@types/url-parse@^1.4.8": + version "1.4.8" + resolved "https://registry.yarnpkg.com/@types/url-parse/-/url-parse-1.4.8.tgz#c3825047efbca1295b7f1646f38203d9145130d6" + integrity sha512-zqqcGKyNWgTLFBxmaexGUKQyWqeG7HjXj20EuQJSJWwXe54BjX0ihIo5cJB9yAQzH8dNugJ9GvkBYMjPXs/PJw== + "@types/uuid@8.3.1", "@types/uuid@^8.3.0": version "8.3.1" resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.1.tgz#1a32969cf8f0364b3d8c8af9cc3555b7805df14f" @@ -5962,6 +5969,11 @@ resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.4.tgz#bd86a43617df0594787d38b735f55c805becf1bc" integrity sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw== +"@types/uuid@9.0.1": + version "9.0.1" + resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.1.tgz#98586dc36aee8dacc98cc396dbca8d0429647aa6" + integrity sha512-rFT3ak0/2trgvp4yYZo5iKFEPsET7vKydKF+VRCxlQ9bpheehyAJH89dAkaLEq/j/RZXJIqcgsmPJKUP1Z28HA== + "@types/validator@^13.1.3": version "13.7.10" resolved "https://registry.yarnpkg.com/@types/validator/-/validator-13.7.10.tgz#f9763dc0933f8324920afa9c0790308eedf55ca7" @@ -6139,16 +6151,6 @@ "@typescript-eslint/types" "4.30.0" eslint-visitor-keys "^2.0.0" -"@vscode/test-electron@^2.1.3": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@vscode/test-electron/-/test-electron-2.2.0.tgz#b90c76b8f076f9cf2d885f14b3c5fc3f586b9419" - integrity sha512-xk2xrOTMG75/hxO8OVVZ+GErv9gmdZwOD8rEHV3ty3n1Joav2yFcfrmqD6Ukref27U13LEL8gVvSHzauGAK5nQ== - dependencies: - http-proxy-agent "^4.0.1" - https-proxy-agent "^5.0.0" - rimraf "^3.0.2" - unzipper "^0.10.11" - "@walletconnect/browser-utils@^1.7.1": version "1.7.1" resolved "https://registry.yarnpkg.com/@walletconnect/browser-utils/-/browser-utils-1.7.1.tgz#2a28846cd4d73166debbbf7d470e78ba25616f5e" @@ -6281,61 +6283,65 @@ "@walletconnect/window-getters" "^1.0.0" "@wdio/appium-service@^7.19.1": - version "7.25.1" - resolved "https://registry.yarnpkg.com/@wdio/appium-service/-/appium-service-7.25.1.tgz#800f35eb8c9e73a79de852ca71d927905650a54a" - integrity sha512-EMUdwP2P8EYTf+KR8B3QrDJv3HF3XWKEdbeUERYlAmc2aJqrDxcxVH/ztbpFHDCRw9Acoao62hJ2s0Gm5VpRxA== - dependencies: - "@types/fs-extra" "^9.0.4" - "@wdio/config" "7.25.1" - "@wdio/logger" "7.19.0" - "@wdio/types" "7.25.1" - fs-extra "^10.0.0" + version "7.31.1" + resolved "https://registry.yarnpkg.com/@wdio/appium-service/-/appium-service-7.31.1.tgz#c86a056cbdcd382388fec5143c710183636e244f" + integrity sha512-C+bzKNpJMvxbLf64U4wO4zHb8N0JXRX3Kk5HcxjYTaCrkqSY8zfcg7UHORTqcgFju3JFYEz4NMwT5nlrvOqyEQ== + dependencies: + "@types/fs-extra" "^11.0.1" + "@wdio/config" "7.31.1" + "@wdio/logger" "7.26.0" + "@wdio/types" "7.30.2" + fs-extra "^11.1.1" param-case "^3.0.0" "@wdio/browserstack-service@^7.26.0": - version "7.28.1" - resolved "https://registry.yarnpkg.com/@wdio/browserstack-service/-/browserstack-service-7.28.1.tgz#69db230634eea60fd33802f4a1f54eca18d1f9ff" - integrity sha512-aUulloEvAPQOkbBnmf7oPI6faOcMCwibRRJuwXEM5R1VpJeXvmLRgfZXZe9T+j/zXwvBVfJ1KDEk65Oyvwc/cg== + version "7.31.1" + resolved "https://registry.yarnpkg.com/@wdio/browserstack-service/-/browserstack-service-7.31.1.tgz#839c9d9ed6022227c8910e0a30c28c67ddb603e0" + integrity sha512-2OVAphX/Oz4n/R38mQvSSW6v/XQhVIfJot/XKLnnOwRLa/SF2HZgxF+cFJdyeHBBHCJmr8qISmYd1JnT/ttzIQ== dependencies: - "@types/node" "^18.0.0" + "@types/gitconfiglocal" "^2.0.1" "@wdio/logger" "7.26.0" - "@wdio/types" "7.26.0" + "@wdio/reporter" "7.25.4" + "@wdio/types" "7.30.2" browserstack-local "^1.4.5" form-data "^4.0.0" + git-repo-info "^2.1.1" + gitconfiglocal "^2.1.0" got "^11.0.2" - webdriverio "7.28.1" + uuid "^8.3.2" + webdriverio "7.31.1" "@wdio/cli@^7.19.1": - version "7.25.2" - resolved "https://registry.yarnpkg.com/@wdio/cli/-/cli-7.25.2.tgz#81b1933457184c4fcd705d13e96798e4ad229900" - integrity sha512-jpQmPR14D2nIBKby6I21zSHNQAPayZXmu+3IBNRe3SDTNEAHb9jZuyhj4IdoaPilfXrJAzQ2BRql6/T2oA29Yw== + version "7.31.1" + resolved "https://registry.yarnpkg.com/@wdio/cli/-/cli-7.31.1.tgz#c6d3905a64ebb31973940bf3cbe660c566632724" + integrity sha512-LEBZ6+a+ptfete6QjBnuFV2FWawilTQGzTeK7zWLc6sgCFxSV2+ifOHvw19p531WhVknm9ZX4s/GelurMhB/6w== dependencies: "@types/ejs" "^3.0.5" - "@types/fs-extra" "^9.0.4" + "@types/fs-extra" "^11.0.1" "@types/inquirer" "^8.1.2" "@types/lodash.flattendeep" "^4.4.6" "@types/lodash.pickby" "^4.6.6" "@types/lodash.union" "^4.6.6" "@types/node" "^18.0.0" "@types/recursive-readdir" "^2.2.0" - "@wdio/config" "7.25.1" - "@wdio/logger" "7.19.0" - "@wdio/protocols" "7.22.0" - "@wdio/types" "7.25.1" - "@wdio/utils" "7.25.1" + "@wdio/config" "7.31.1" + "@wdio/logger" "7.26.0" + "@wdio/protocols" "7.27.0" + "@wdio/types" "7.30.2" + "@wdio/utils" "7.30.2" async-exit-hook "^2.0.1" chalk "^4.0.0" chokidar "^3.0.0" cli-spinners "^2.1.0" ejs "^3.0.1" - fs-extra "^10.0.0" + fs-extra "^11.1.1" inquirer "8.2.4" lodash.flattendeep "^4.4.0" lodash.pickby "^4.6.0" lodash.union "^4.6.0" - mkdirp "^1.0.4" + mkdirp "^3.0.0" recursive-readdir "^2.2.2" - webdriverio "7.25.2" + webdriverio "7.31.1" yargs "^17.0.0" yarn-install "^1.0.0" @@ -6367,44 +6373,35 @@ deepmerge "^4.0.0" glob "^7.1.2" -"@wdio/config@7.25.1": - version "7.25.1" - resolved "https://registry.yarnpkg.com/@wdio/config/-/config-7.25.1.tgz#1a094e639343466adcea678fc443daef041dc7b3" - integrity sha512-7I3L+TE75gvh8jiv8cE/Ch9S9erDgrZG9o5587OlNKfpgFciT7DH7/efPXzYwh8YPFV3grFaydxaaoYzDv6PDA== - dependencies: - "@wdio/logger" "7.19.0" - "@wdio/types" "7.25.1" - "@wdio/utils" "7.25.1" - deepmerge "^4.0.0" - glob "^8.0.3" - -"@wdio/config@7.26.0": - version "7.26.0" - resolved "https://registry.yarnpkg.com/@wdio/config/-/config-7.26.0.tgz#56710cf7cf2e5a60eafd91d7a399e49a028b6eb8" - integrity sha512-GO6kFGgFrx2Hiq+Ww6V9I7cZfShPjfPVhPy3uXnKN2B4FilX8ilLAp5cIFuMuHPeOQq0crYX9cnLYXka6dCGgg== +"@wdio/config@7.31.1": + version "7.31.1" + resolved "https://registry.yarnpkg.com/@wdio/config/-/config-7.31.1.tgz#53550a164c970403628525ecdc5e0c3f96a0ff30" + integrity sha512-WAfswbCatwiaDVqy6kfF/5T8/WS/US/SRhBGUFrfBuGMIe+RRoHgy7jURFWSvUIE7CNHj8yvs46fLUcxhXjzcQ== dependencies: + "@types/glob" "^8.1.0" "@wdio/logger" "7.26.0" - "@wdio/types" "7.26.0" - "@wdio/utils" "7.26.0" + "@wdio/types" "7.30.2" + "@wdio/utils" "7.30.2" deepmerge "^4.0.0" glob "^8.0.3" "@wdio/cucumber-framework@^7.19.1": - version "7.25.1" - resolved "https://registry.yarnpkg.com/@wdio/cucumber-framework/-/cucumber-framework-7.25.1.tgz#5a34539b854da653929ffe53236e6e3988e767f6" - integrity sha512-FhyO1cFmCtti9Vj3lG9P8HYXppdQmLvFQP3fMlKpbDOcXHsyslzO7CMl1puf6etJhy9ik/6G1XPygiO+IY8X7g== + version "7.31.1" + resolved "https://registry.yarnpkg.com/@wdio/cucumber-framework/-/cucumber-framework-7.31.1.tgz#032ffbe53c1923e3acbf990cd4d2462a67eefdbf" + integrity sha512-UEjIQRCl847UdBZNjWQqBTsd8Ejk+gV9tfs5k8p2/cIvMLMEbb6Eq2FJY7YbjRAlEWpVTqXpC9N4kqu6LszazA== dependencies: "@cucumber/cucumber" "8.6.0" - "@cucumber/gherkin" "24.0.0" + "@cucumber/gherkin" "26.0.3" "@cucumber/gherkin-streams" "^5.0.0" - "@cucumber/messages" "19.1.4" + "@cucumber/messages" "21.0.1" + "@types/glob" "^8.1.0" "@types/is-glob" "^4.0.1" "@types/long" "^4.0.1" "@types/mockery" "^1.4.29" "@types/sinonjs__fake-timers" "^8.1.2" - "@wdio/logger" "7.19.0" - "@wdio/types" "7.25.1" - "@wdio/utils" "7.25.1" + "@wdio/logger" "7.26.0" + "@wdio/types" "7.30.2" + "@wdio/utils" "7.30.2" expect-webdriverio "^3.0.0" glob "^8.0.3" is-glob "^4.0.0" @@ -6412,28 +6409,28 @@ mockery "^2.1.0" "@wdio/junit-reporter@^7.25.4": - version "7.28.0" - resolved "https://registry.yarnpkg.com/@wdio/junit-reporter/-/junit-reporter-7.28.0.tgz#76b8087ae98109590e637138ef1dbccd91a485ad" - integrity sha512-fG525KED4VAdkZUtc/s5JD4DrvwKzxlE3Onvz1HNi3W3TQGJtdNqY55RHMEVsVwRwTzrC3WU34MHKP/qCmtwlw== + version "7.31.1" + resolved "https://registry.yarnpkg.com/@wdio/junit-reporter/-/junit-reporter-7.31.1.tgz#b446a023b1e92f465fb235d75c77db941e7b4cf8" + integrity sha512-2hqZrUnIOthyNi0DmN/2Zg0nGWBpmNvvFh94f2VHCofIe79f+eCqaMAqhVNsd2TpmYxpUv3sX9TmDzgWhhAmZA== dependencies: "@types/json-stringify-safe" "^5.0.0" "@types/validator" "^13.1.3" - "@wdio/reporter" "7.28.0" - "@wdio/types" "7.26.0" + "@wdio/reporter" "7.31.1" + "@wdio/types" "7.30.2" json-stringify-safe "^5.0.1" junit-report-builder "^3.0.0" validator "^13.0.0" "@wdio/local-runner@^7.19.1": - version "7.25.2" - resolved "https://registry.yarnpkg.com/@wdio/local-runner/-/local-runner-7.25.2.tgz#e2fe3f366018d80b01c3c58153b5bd85e97b3e3d" - integrity sha512-6FXuGSX7UNpMLmH2k0dpCZRxgiX7nF6kDN+NjUyUNdp2H6qLHxkOdpNTI0rIijamHEFADjGoeYAluybu6QtbmA== + version "7.31.1" + resolved "https://registry.yarnpkg.com/@wdio/local-runner/-/local-runner-7.31.1.tgz#d600b00e66e67ebf67533cedaf2d5aefd3bf4494" + integrity sha512-yzhUJVWvVBeCWUHOxA9M5cAFMQ2RyNrrZxNOfSxBLyUytXnPIUHvvwP28Cugx/Hu1jTap98YNy6qszoC7K5P2g== dependencies: "@types/stream-buffers" "^3.0.3" - "@wdio/logger" "7.19.0" - "@wdio/repl" "7.25.1" - "@wdio/runner" "7.25.2" - "@wdio/types" "7.25.1" + "@wdio/logger" "7.26.0" + "@wdio/repl" "7.30.2" + "@wdio/runner" "7.31.1" + "@wdio/types" "7.30.2" async-exit-hook "^2.0.1" split2 "^4.0.0" stream-buffers "^3.0.2" @@ -6468,16 +6465,6 @@ loglevel-plugin-prefix "^0.8.4" strip-ansi "^6.0.0" -"@wdio/logger@7.19.0", "@wdio/logger@^7.17.3", "@wdio/logger@^7.19.0", "@wdio/logger@^7.5.3": - version "7.19.0" - resolved "https://registry.yarnpkg.com/@wdio/logger/-/logger-7.19.0.tgz#23697a4b4aaea56c3bd477a0393af2a5c175fc85" - integrity sha512-xR7SN/kGei1QJD1aagzxs3KMuzNxdT/7LYYx+lt6BII49+fqL/SO+5X0FDCZD0Ds93AuQvvz9eGyzrBI2FFXmQ== - dependencies: - chalk "^4.0.0" - loglevel "^1.6.0" - loglevel-plugin-prefix "^0.8.4" - strip-ansi "^6.0.0" - "@wdio/logger@7.26.0": version "7.26.0" resolved "https://registry.yarnpkg.com/@wdio/logger/-/logger-7.26.0.tgz#2c105a00f63a81d52de969fef5a54a9035146b2d" @@ -6503,11 +6490,6 @@ resolved "https://registry.yarnpkg.com/@wdio/protocols/-/protocols-7.16.7.tgz#8a160d59f0c028ff2dda6a1599a86a801a79bcb8" integrity sha512-Wv40pNQcLiPzQ3o98Mv4A8T1EBQ6k4khglz/e2r16CTm+F3DDYh8eLMAsU5cgnmuwwDKX1EyOiFwieykBn5MCg== -"@wdio/protocols@7.22.0": - version "7.22.0" - resolved "https://registry.yarnpkg.com/@wdio/protocols/-/protocols-7.22.0.tgz#d89faef687cb08981d734bbc5e5dffc6fb5a064c" - integrity sha512-8EXRR+Ymdwousm/VGtW3H1hwxZ/1g1H99A1lF0U4GuJ5cFWHCd0IVE5H31Z52i8ZruouW8jueMkGZPSo2IIUSQ== - "@wdio/protocols@7.27.0": version "7.27.0" resolved "https://registry.yarnpkg.com/@wdio/protocols/-/protocols-7.27.0.tgz#8e2663ec877dce7a5f76b021209c18dd0132e853" @@ -6534,49 +6516,42 @@ dependencies: "@wdio/utils" "7.16.14" -"@wdio/repl@7.25.1": - version "7.25.1" - resolved "https://registry.yarnpkg.com/@wdio/repl/-/repl-7.25.1.tgz#9c0e1b9a3db90ff438fde63f34da1f3966bcca58" - integrity sha512-3DUtOrLi5thba22IBn/XQ7caFrbXtYOg3750UtXxUuxXU4QHkKq1AN8+WXr4Rq2EnXfB2G9t9pEdqjZSv9oPAw== - dependencies: - "@wdio/utils" "7.25.1" - -"@wdio/repl@7.26.0": - version "7.26.0" - resolved "https://registry.yarnpkg.com/@wdio/repl/-/repl-7.26.0.tgz#bf0703f46ad379107b9cfc254c3eccbd5cd6d848" - integrity sha512-2YxbXNfYVGVLrffUJzl/l5s8FziDPl917eLP62gkEH/H5IV27Pnwx3Iyu0KOEaBzgntnURANlwhCZFXQ4OPq8Q== +"@wdio/repl@7.30.2": + version "7.30.2" + resolved "https://registry.yarnpkg.com/@wdio/repl/-/repl-7.30.2.tgz#a92592078cb892d5bd14c2b300ef01ae6c8baf90" + integrity sha512-aW4nuMI+gbRmxmL4jMarBjuiQ+cFscr/8jHDt5hGx/gc/f7ifrZa4t6M5H8vFIKsvjUwl9lZRiVO4NVvvp6+cg== dependencies: - "@wdio/utils" "7.26.0" + "@wdio/utils" "7.30.2" -"@wdio/reporter@7.25.1": - version "7.25.1" - resolved "https://registry.yarnpkg.com/@wdio/reporter/-/reporter-7.25.1.tgz#a241745b20136393568958e29840d49caa873f02" - integrity sha512-MLEiuoQGFn1ZD5FvzWFdsInuJT7TF/E1sg81mwlMjm5iFpuTvbPCUQq3uJ24xnXfMbw/HLZUnhPqC47+KTKTkw== +"@wdio/reporter@7.25.4": + version "7.25.4" + resolved "https://registry.yarnpkg.com/@wdio/reporter/-/reporter-7.25.4.tgz#b6a69652dd0c4ec131255000af128eac403a18b9" + integrity sha512-M37qzEmF5qNffyZmRQGjDlrXqWW21EFvgW8wsv1b/NtfpZc0c0MoRpeh6BnvX1KcE4nCXfjXgSJPOqV4ZCzUEQ== dependencies: "@types/diff" "^5.0.0" "@types/node" "^18.0.0" "@types/object-inspect" "^1.8.0" "@types/supports-color" "^8.1.0" "@types/tmp" "^0.2.0" - "@wdio/types" "7.25.1" + "@wdio/types" "7.25.4" diff "^5.0.0" fs-extra "^10.0.0" object-inspect "^1.10.3" supports-color "8.1.1" -"@wdio/reporter@7.28.0": - version "7.28.0" - resolved "https://registry.yarnpkg.com/@wdio/reporter/-/reporter-7.28.0.tgz#a2fd5e08209784efe92236796aedf1a2c6734638" - integrity sha512-KK8rLTYRHI6mdljg+Jgfift1s+UJIupBG+F8KcPjRilbgk7UOoqYorfq7d24bHrVjRuvoOIDAfAGeFFbGinR7g== +"@wdio/reporter@7.31.1": + version "7.31.1" + resolved "https://registry.yarnpkg.com/@wdio/reporter/-/reporter-7.31.1.tgz#3f0e71d34c134c0e8b3f3ff33ffffe815d568d62" + integrity sha512-0xd3RtavOast2ihu46/ndj+EI5auXTh9EO6odBixLtDbwAXYQ9LIPfbIUg7iTuCI48y/UVT9vw9nNWMd3UDMNA== dependencies: "@types/diff" "^5.0.0" "@types/node" "^18.0.0" "@types/object-inspect" "^1.8.0" "@types/supports-color" "^8.1.0" "@types/tmp" "^0.2.0" - "@wdio/types" "7.26.0" + "@wdio/types" "7.30.2" diff "^5.0.0" - fs-extra "^11.1.0" + fs-extra "^11.1.1" object-inspect "^1.10.3" supports-color "8.1.1" @@ -6596,28 +6571,28 @@ object-inspect "^1.10.3" supports-color "8.1.1" -"@wdio/runner@7.25.2": - version "7.25.2" - resolved "https://registry.yarnpkg.com/@wdio/runner/-/runner-7.25.2.tgz#1991c8fa09d9840f8bb3d645f47722418ab25043" - integrity sha512-0fQe9qmYPmbZ+PiDmZw6uy9XEx0A8+VhQAxyUSp/K9NCDUABY+I1tCSHCY/0mzlwk+ykscn8+qhaN1g9LvBtPA== +"@wdio/runner@7.31.1": + version "7.31.1" + resolved "https://registry.yarnpkg.com/@wdio/runner/-/runner-7.31.1.tgz#2839e11c18f7ea17c0786c83683bbae8f6df9f23" + integrity sha512-D36KWd6GviqAx0imupOSo0kkAc5AOamFBb0yHv4TK4F0AlokXu0Sh0EbZdmQxAhhudrlk/L1OhGLLCk7XxSoXA== dependencies: - "@wdio/config" "7.25.1" - "@wdio/logger" "7.19.0" - "@wdio/types" "7.25.1" - "@wdio/utils" "7.25.1" + "@wdio/config" "7.31.1" + "@wdio/logger" "7.26.0" + "@wdio/types" "7.30.2" + "@wdio/utils" "7.30.2" deepmerge "^4.0.0" gaze "^1.1.2" - webdriver "7.25.1" - webdriverio "7.25.2" + webdriver "7.31.1" + webdriverio "7.31.1" "@wdio/spec-reporter@^7.19.1": - version "7.25.1" - resolved "https://registry.yarnpkg.com/@wdio/spec-reporter/-/spec-reporter-7.25.1.tgz#01315a3ff718bcc017bd59696b856b09e15b6293" - integrity sha512-CazLMJGWh0b+eWtiSmWGfFCl+nB1LHwST30gWsBJ44Xtd/rwl7rXi76Uq/qE2a2kwUs0Od6NLK7ZCa+ISejqwQ== + version "7.31.1" + resolved "https://registry.yarnpkg.com/@wdio/spec-reporter/-/spec-reporter-7.31.1.tgz#c025a94f202336b19cf79485f2cbf581bc13ae15" + integrity sha512-Ta0XSDYliaB4k8lEbYweegN0Cz/Dycz6oTbn2ZUU48DyGfq7AtLYw7UB9+3SQ6Q/ao5cMEEh6Q8zvLXhw9+ovw== dependencies: "@types/easy-table" "^1.2.0" - "@wdio/reporter" "7.25.1" - "@wdio/types" "7.25.1" + "@wdio/reporter" "7.31.1" + "@wdio/types" "7.30.2" chalk "^4.0.0" easy-table "^1.1.1" pretty-ms "^7.0.0" @@ -6630,18 +6605,18 @@ "@types/node" "^17.0.4" got "^11.8.1" -"@wdio/types@7.25.1": - version "7.25.1" - resolved "https://registry.yarnpkg.com/@wdio/types/-/types-7.25.1.tgz#9e06f5479bc3c95f78811ba77dd96470417f882a" - integrity sha512-9Xt2U0YXYxRW4UvMFwjt+44UkfhwrI1gPhW+y56SubpyKaUfdNGberteboQoR/7Os1SVtJry4FohEZNmFzPK6g== +"@wdio/types@7.25.4": + version "7.25.4" + resolved "https://registry.yarnpkg.com/@wdio/types/-/types-7.25.4.tgz#6f8f028e3108dc880de5068264695f1572e65352" + integrity sha512-muvNmq48QZCvocctnbe0URq2FjJjUPIG4iLoeMmyF0AQgdbjaUkMkw3BHYNHVTbSOU9WMsr2z8alhj/I2H6NRQ== dependencies: "@types/node" "^18.0.0" got "^11.8.1" -"@wdio/types@7.26.0": - version "7.26.0" - resolved "https://registry.yarnpkg.com/@wdio/types/-/types-7.26.0.tgz#70bc879c5dbe316a0eebbac4a46f0f66430b1d84" - integrity sha512-mOTfWAGQ+iT58iaZhJMwlUkdEn3XEWE4jthysMLXFnSuZ2eaODVAiK31SmlS/eUqgSIaupeGqYUrtCuSNbLefg== +"@wdio/types@7.30.2": + version "7.30.2" + resolved "https://registry.yarnpkg.com/@wdio/types/-/types-7.30.2.tgz#0baa4b8249aa1d98a545144e6fb494f1b186b24f" + integrity sha512-uZ8o7FX8RyBsaXiOWa59UKTCHTtADNvOArYTcHNEIzt+rh4JdB/uwqfc8y4TCNA2kYm7PWaQpUFwpStLeg0H1Q== dependencies: "@types/node" "^18.0.0" got "^11.8.1" @@ -6670,22 +6645,13 @@ "@wdio/types" "7.16.14" p-iteration "^1.1.8" -"@wdio/utils@7.25.1": - version "7.25.1" - resolved "https://registry.yarnpkg.com/@wdio/utils/-/utils-7.25.1.tgz#29bfe7e2dcd4f9b31868f069afa1eb761e96b8a7" - integrity sha512-DL+nDRVgzruJLhedBUQEMUcojLoGwsjCQCYWram4NfwAIIkxcAX/5Y4vHSut3OoW2bEHl3R8/FQ4B/ivIr2EoQ== - dependencies: - "@wdio/logger" "7.19.0" - "@wdio/types" "7.25.1" - p-iteration "^1.1.8" - -"@wdio/utils@7.26.0": - version "7.26.0" - resolved "https://registry.yarnpkg.com/@wdio/utils/-/utils-7.26.0.tgz#e282d072ccbacbe583f6d1b192c0320cede170c1" - integrity sha512-pVq2MPXZAYLkKGKIIHktHejnHqg4TYKoNYSi2EDv+I3GlT8VZKXHazKhci82ov0tD+GdF27+s4DWNDCfGYfBdQ== +"@wdio/utils@7.30.2": + version "7.30.2" + resolved "https://registry.yarnpkg.com/@wdio/utils/-/utils-7.30.2.tgz#d4642c3b8333f3f2ae9d46229098c0a77c3f887b" + integrity sha512-np7I+smszFUennbQKdzbMN/zUL3s3EZq9pCCUcTRjjs9TE4tnn0wfmGdoz2o7REYu6kn9NfFFJyVIM2VtBbKEA== dependencies: "@wdio/logger" "7.26.0" - "@wdio/types" "7.26.0" + "@wdio/types" "7.30.2" p-iteration "^1.1.8" "@xmldom/xmldom@^0.x": @@ -7639,18 +7605,6 @@ aproba@^1.0.3: resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== -arch@^2.1.1: - version "2.2.0" - resolved "https://registry.yarnpkg.com/arch/-/arch-2.2.0.tgz#1bc47818f305764f23ab3306b0bfc086c5a29d11" - integrity sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ== - -archive-type@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/archive-type/-/archive-type-4.0.0.tgz#f92e72233056dfc6969472749c267bdb046b1d70" - integrity sha512-zV4Ky0v1F8dBrdYElwTvQhweQ0P7Kwc1aluqJsYtOBP01jXcWCyW2IEfI1YiqsG+Iy7ZR+o5LF1N+PGECBxHWA== - dependencies: - file-type "^4.2.0" - archiver-utils@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/archiver-utils/-/archiver-utils-2.1.0.tgz#e8a460e94b693c3e3da182a098ca6285ba9249e2" @@ -8326,13 +8280,6 @@ babel-preset-jest@^26.6.2: babel-plugin-jest-hoist "^26.6.2" babel-preset-current-node-syntax "^1.0.0" -babel-runtime@^5.8.25: - version "5.8.38" - resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-5.8.38.tgz#1c0b02eb63312f5f087ff20450827b425c9d4c19" - integrity sha512-KpgoA8VE/pMmNCrnEeeXqFG24TIH11Z3ZaimIhJWsin8EbfZy3WzFKUTIan10ZIDgRVvi9EkLbruJElJC9dRlg== - dependencies: - core-js "^1.0.0" - babel-runtime@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" @@ -8429,7 +8376,7 @@ bech32@1.1.4: resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== -big-integer@1.6.x, big-integer@^1.6.17: +big-integer@1.6.x: version "1.6.51" resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.51.tgz#0df92a5d9880560d3ff2d5fd20245c889d130686" integrity sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg== @@ -8458,14 +8405,6 @@ binary-extensions@^2.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== -binary@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/binary/-/binary-0.3.0.tgz#9f60553bc5ce8c3386f3b553cff47462adecaa79" - integrity sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg== - dependencies: - buffers "~0.1.1" - chainsaw "~0.1.0" - bindings@^1.2.1, bindings@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" @@ -8491,7 +8430,7 @@ bip66@^1.1.5: dependencies: safe-buffer "^5.0.1" -bl@^1.0.0, bl@^1.2.3, bl@~0.8.1: +bl@^1.2.3, bl@~0.8.1: version "1.2.3" resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.3.tgz#1e8dd80142eac80d7158c9dccc047fb620e035e7" integrity sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww== @@ -8518,11 +8457,6 @@ bluebird@3.x, bluebird@^3.1.1, bluebird@^3.4.7, bluebird@^3.5.0, bluebird@^3.5.1 resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== -bluebird@~3.4.1: - version "3.4.7" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.4.7.tgz#f72d760be09b7f76d08ed8fae98b289a8d05fab3" - integrity sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA== - bmp-js@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/bmp-js/-/bmp-js-0.1.0.tgz#e05a63f796a6c1ff25f4771ec7adadc148c07233" @@ -8860,11 +8794,6 @@ buffer-from@^1.0.0, buffer-from@^1.1.1: resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== -buffer-indexof-polyfill@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz#d2732135c5999c64b277fcf9b1abe3498254729c" - integrity sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A== - buffer-xor@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" @@ -8903,11 +8832,6 @@ buffer@^6.0.3: base64-js "^1.3.1" ieee754 "^1.2.1" -buffers@~0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/buffers/-/buffers-0.1.1.tgz#b24579c3bed4d6d396aeee6d9a8ae7f5482ab7bb" - integrity sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ== - bufferutil@4.0.5: version "4.0.5" resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.5.tgz#da9ea8166911cc276bf677b8aed2d02d31f59028" @@ -9041,11 +8965,6 @@ camelcase-keys@^3.0.0: camelcase "^3.0.0" map-obj "^1.0.0" -camelcase@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" - integrity sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8= - camelcase@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" @@ -9091,15 +9010,6 @@ caniuse-lite@^1.0.30001349: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001352.tgz#cc6f5da3f983979ad1e2cdbae0505dccaa7c6a12" integrity sha512-GUgH8w6YergqPQDGWhJGt8GDRnY0L/iJVQcU3eJ46GYf52R8tk0Wxp0PymuFVZboJYXGiCqwozAYZNRjVj6IcA== -canvas@^2.9.1: - version "2.10.1" - resolved "https://registry.yarnpkg.com/canvas/-/canvas-2.10.1.tgz#fbfd4b1b3b106c3454481d79d363ebadf8811c08" - integrity sha512-29pIjn9uwTUsIgJUNd7GXxKk8sg4iyJwLm1wIilNIqX1mVzXSc2nUij9exW1LqNpis1d2ebMYfMqTWcokZ4pdA== - dependencies: - "@mapbox/node-pre-gyp" "^1.0.0" - nan "^2.15.0" - simple-get "^3.0.3" - capital-case@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/capital-case/-/capital-case-1.0.4.tgz#9d130292353c9249f6b00fa5852bee38a717e669" @@ -9144,13 +9054,6 @@ chai@^4.3.4: pathval "^1.1.1" type-detect "^4.0.5" -chainsaw@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/chainsaw/-/chainsaw-0.1.0.tgz#5eab50b28afe58074d0d58291388828b5e5fbc98" - integrity sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ== - dependencies: - traverse ">=0.3.0 <0.4" - chalk@^1.1.1, chalk@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" @@ -9456,16 +9359,7 @@ cli-width@^3.0.0: resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw== -clipboardy@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/clipboardy/-/clipboardy-2.3.0.tgz#3c2903650c68e46a91b388985bc2774287dba290" - integrity sha512-mKhiIL2DrQIsuXMgBgnfEHOZOryC7kY7YO//TN6c63wlEm3NG5tz+YgY5rVi29KCmq/QQjKYvM7a19+MDOTHOQ== - dependencies: - arch "^2.1.1" - execa "^1.0.0" - is-wsl "^2.1.1" - -cliui@^3.0.3, cliui@^3.2.0: +cliui@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0= @@ -9691,7 +9585,7 @@ commander@9.3.0: resolved "https://registry.yarnpkg.com/commander/-/commander-9.3.0.tgz#f619114a5a2d2054e0d9ff1b31d5ccf89255e26b" integrity sha512-hv95iU5uXPbK83mjrJKuZyFM/LBAoCV/XhVGkS5Je6tl7sxr6A0ITMw5WoRV46/UaJ46Nllm3Xt7IaJhXTIkzw== -commander@^2.19.0, commander@^2.8.1, commander@^2.9.0: +commander@^2.19.0: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== @@ -9779,15 +9673,6 @@ compression@^1.7.1: safe-buffer "5.1.2" vary "~1.1.2" -concat-cli@4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/concat-cli/-/concat-cli-4.0.0.tgz#a73a0fb0d18b25804ebe703bcc35922324dbf74d" - integrity sha1-pzoPsNGLJYBOvnA7zDWSIyTb900= - dependencies: - chalk "^1.1.1" - concat "^1.0.0" - yargs "^3.30.0" - concat-stream@^1.4.4: version "1.6.2" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" @@ -9798,13 +9683,6 @@ concat-stream@^1.4.4: readable-stream "^2.2.2" typedarray "^0.0.6" -concat@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/concat/-/concat-1.0.3.tgz#40f3353089d65467695cb1886b45edd637d8cca8" - integrity sha1-QPM1MInWVGdpXLGIa0Xt1jfYzKg= - dependencies: - commander "^2.9.0" - connect@^3.6.5: version "3.7.0" resolved "https://registry.yarnpkg.com/connect/-/connect-3.7.0.tgz#5d49348910caa5e07a01800b030d0c35f20484f8" @@ -9820,7 +9698,7 @@ console-control-strings@^1.0.0, console-control-strings@^1.1.0, console-control- resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= -content-disposition@0.5.4, content-disposition@^0.5.2: +content-disposition@0.5.4: version "0.5.4" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== @@ -9904,11 +9782,6 @@ core-js-compat@^3.14.0: browserslist "^4.16.6" semver "7.0.0" -core-js@^1.0.0: - version "1.2.7" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636" - integrity sha512-ZiPp9pZlgxpWRu0M+YWbm6+aQ84XEfH1JRXvfOc/fILWI0VKhLC2LX13X1NYq4fULzLMq7Hfh43CSo2/aIaUPA== - core-js@^2.4.0, core-js@^2.5.7, core-js@^2.6.5: version "2.6.12" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" @@ -10349,59 +10222,6 @@ decompress-response@^6.0.0: dependencies: mimic-response "^3.1.0" -decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/decompress-tar/-/decompress-tar-4.1.1.tgz#718cbd3fcb16209716e70a26b84e7ba4592e5af1" - integrity sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ== - dependencies: - file-type "^5.2.0" - is-stream "^1.1.0" - tar-stream "^1.5.2" - -decompress-tarbz2@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz#3082a5b880ea4043816349f378b56c516be1a39b" - integrity sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A== - dependencies: - decompress-tar "^4.1.0" - file-type "^6.1.0" - is-stream "^1.1.0" - seek-bzip "^1.0.5" - unbzip2-stream "^1.0.9" - -decompress-targz@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/decompress-targz/-/decompress-targz-4.1.1.tgz#c09bc35c4d11f3de09f2d2da53e9de23e7ce1eee" - integrity sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w== - dependencies: - decompress-tar "^4.1.1" - file-type "^5.2.0" - is-stream "^1.1.0" - -decompress-unzip@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/decompress-unzip/-/decompress-unzip-4.0.1.tgz#deaaccdfd14aeaf85578f733ae8210f9b4848f69" - integrity sha512-1fqeluvxgnn86MOh66u8FjbtJpAFv5wgCT9Iw8rcBqQcCo5tO8eiJw7NNTrvt9n4CRBVq7CstiS922oPgyGLrw== - dependencies: - file-type "^3.8.0" - get-stream "^2.2.0" - pify "^2.3.0" - yauzl "^2.4.2" - -decompress@^4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/decompress/-/decompress-4.2.1.tgz#007f55cc6a62c055afa37c07eb6a4ee1b773f118" - integrity sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ== - dependencies: - decompress-tar "^4.0.0" - decompress-tarbz2 "^4.0.0" - decompress-targz "^4.0.0" - decompress-unzip "^4.0.1" - graceful-fs "^4.1.10" - make-dir "^1.0.0" - pify "^2.3.0" - strip-dirs "^2.0.0" - dedent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.6.0.tgz#0e6da8f0ce52838ef5cec5c8f9396b0c1b64a3cb" @@ -10694,15 +10514,10 @@ devtools-protocol@0.0.981744: resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.981744.tgz#9960da0370284577d46c28979a0b32651022bacf" integrity sha512-0cuGS8+jhR67Fy7qG3i3Pc7Aw494sb9yG9QgpG97SFVWwolgYjlhJg7n+UaHxOQT30d1TYu/EYe9k01ivLErIg== -devtools-protocol@^0.0.1056733: - version "0.0.1056733" - resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.1056733.tgz#55bb1d56761014cc221131cca5e6bad94eefb2b9" - integrity sha512-CmTu6SQx2g3TbZzDCAV58+LTxVdKplS7xip0g5oDXpZ+isr0rv5dDP8ToyVRywzPHkCCPKgKgScEcwz4uPWDIA== - -devtools-protocol@^0.0.1084670: - version "0.0.1084670" - resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.1084670.tgz#853b4e14f9324fd7b8b52a191d403364ceb0aa79" - integrity sha512-6iZb5kgfopmFMzJZD3rk0Ipa9WBd7VzTw+2yoOeBmg1/araNAhrFVWYQQkWo7aTFsNLdmGLtZlTOP6c2WG9UfA== +devtools-protocol@^0.0.1130274: + version "0.0.1130274" + resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.1130274.tgz#1cd0c472a84fc9a09becaaed35a247a6eab9310c" + integrity sha512-kIozBWajgsi1g0W8yzALI4ZdCp6KG1yWaq8NN1ehQM3zX6JRegLSzfexz7XT5eFjmq1RkpMYgeKmfi3GsHrCLw== devtools-protocol@^0.0.973690: version "0.0.973690" @@ -10743,37 +10558,18 @@ devtools@7.16.16: ua-parser-js "^1.0.1" uuid "^8.0.0" -devtools@7.25.1: - version "7.25.1" - resolved "https://registry.yarnpkg.com/devtools/-/devtools-7.25.1.tgz#64ad59db9a769e68d70afbf1bc1b456bd9ced7e8" - integrity sha512-01T8QZeiD92MpI/7rP8kUflN3XcMqv2moa07123OjjENuuOhYxRWmJ7xj94txnF5PJp1Cv8/jvK8EUbnEHf6MQ== +devtools@7.31.1: + version "7.31.1" + resolved "https://registry.yarnpkg.com/devtools/-/devtools-7.31.1.tgz#c7a5db22d720a83f57871138da76125948be346a" + integrity sha512-QU8rMSspKk3c/mX0uawIlRslwH7F+sdTGBZseXgAA5XIgqWbanCQdfHLvxcEzJJHRE5Gq6vGPJIAjq/z9Z4j/Q== dependencies: "@types/node" "^18.0.0" "@types/ua-parser-js" "^0.7.33" - "@wdio/config" "7.25.1" - "@wdio/logger" "7.19.0" - "@wdio/protocols" "7.22.0" - "@wdio/types" "7.25.1" - "@wdio/utils" "7.25.1" - chrome-launcher "^0.15.0" - edge-paths "^2.1.0" - puppeteer-core "^13.1.3" - query-selector-shadow-dom "^1.0.0" - ua-parser-js "^1.0.1" - uuid "^9.0.0" - -devtools@7.28.1: - version "7.28.1" - resolved "https://registry.yarnpkg.com/devtools/-/devtools-7.28.1.tgz#9699e0ca41c9a3adfa351d8afac2928f8e1d381c" - integrity sha512-sDoszzrXDMLiBQqsg9A5gDqDBwhH4sjYzJIW15lQinB8qgNs0y4o1zdfNlqiKs4HstCA2uFixQeibbDCyMa7hQ== - dependencies: - "@types/node" "^18.0.0" - "@types/ua-parser-js" "^0.7.33" - "@wdio/config" "7.26.0" + "@wdio/config" "7.31.1" "@wdio/logger" "7.26.0" "@wdio/protocols" "7.27.0" - "@wdio/types" "7.26.0" - "@wdio/utils" "7.26.0" + "@wdio/types" "7.30.2" + "@wdio/utils" "7.30.2" chrome-launcher "^0.15.0" edge-paths "^2.1.0" puppeteer-core "^13.1.3" @@ -10961,23 +10757,6 @@ dotenv@^16.0.3: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.3.tgz#115aec42bac5053db3c456db30cc243a5a836a07" integrity sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ== -download@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/download/-/download-8.0.0.tgz#afc0b309730811731aae9f5371c9f46be73e51b1" - integrity sha512-ASRY5QhDk7FK+XrQtQyvhpDKanLluEEQtWl/J7Lxuf/b+i8RYh997QeXvL85xitrmRKVlx9c7eTrcRdq2GS4eA== - dependencies: - archive-type "^4.0.0" - content-disposition "^0.5.2" - decompress "^4.2.1" - ext-name "^5.0.0" - file-type "^11.1.0" - filenamify "^3.0.0" - get-stream "^4.1.0" - got "^8.3.1" - make-dir "^2.1.0" - p-event "^2.1.0" - pify "^4.0.1" - drbg.js@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/drbg.js/-/drbg.js-1.0.1.tgz#3e36b6c42b37043823cdbc332d58f31e2445480b" @@ -10994,13 +10773,6 @@ dtrace-provider@~0.8: dependencies: nan "^2.14.0" -duplexer2@~0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1" - integrity sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA== - dependencies: - readable-stream "^2.0.2" - duplexer@~0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" @@ -11158,7 +10930,7 @@ encodeurl@~1.0.2: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= -end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.0, end-of-stream@^1.4.1: +end-of-stream@^1.1.0, end-of-stream@^1.4.0, end-of-stream@^1.4.1: version "1.4.4" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== @@ -12903,9 +12675,9 @@ expand-template@^2.0.3: integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg== expect-webdriverio@^3.0.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/expect-webdriverio/-/expect-webdriverio-3.4.0.tgz#32944cefaae3380285ee8d3a88edc1a3b9ed4612" - integrity sha512-7Ivy1IB35pmkbCcI36un2OMytGEYCy1PcdqrlDnWZBzTpewAO14r+gO2FSuO5kNpDWm3gZSD4NYLG1KXJOlI3w== + version "3.6.0" + resolved "https://registry.yarnpkg.com/expect-webdriverio/-/expect-webdriverio-3.6.0.tgz#529dd8a05cf952ed31c28541f8411f8d30182dc9" + integrity sha512-8HuVToXDVzkKgUKIUzW/v3bP4ZoMDEwCjX9QmlRlMIvjt3HOSzSIBnRMv8lpeVTUKoR9DZNr/lSuKH4Amx4BBg== dependencies: expect "^28.1.0" jest-matcher-utils "^28.1.0" @@ -12977,14 +12749,6 @@ ext-list@^2.0.0: dependencies: mime-db "^1.28.0" -ext-name@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/ext-name/-/ext-name-5.0.0.tgz#70781981d183ee15d13993c8822045c506c8f0a6" - integrity sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ== - dependencies: - ext-list "^2.0.0" - sort-keys-length "^1.0.0" - ext@^1.1.2: version "1.7.0" resolved "https://registry.yarnpkg.com/ext/-/ext-1.7.0.tgz#0ea4383c0103d60e70be99e9a7f11027a33c4f5f" @@ -13236,31 +13000,6 @@ file-entry-cache@^5.0.1: dependencies: flat-cache "^2.0.1" -file-type@^11.1.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-11.1.0.tgz#93780f3fed98b599755d846b99a1617a2ad063b8" - integrity sha512-rM0UO7Qm9K7TWTtA6AShI/t7H5BPjDeGVDaNyg9BjHAj3PysKy7+8C8D137R88jnR3rFJZQB/tFgydl5sN5m7g== - -file-type@^3.8.0: - version "3.9.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9" - integrity sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA== - -file-type@^4.2.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-4.4.0.tgz#1b600e5fca1fbdc6e80c0a70c71c8dba5f7906c5" - integrity sha512-f2UbFQEk7LXgWpi5ntcO86OeA/cC80fuDDDaX/fZ2ZGel+AF7leRQqBBW1eJNiiQkrZlAoM6P+VYP5P6bOlDEQ== - -file-type@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-5.2.0.tgz#2ddbea7c73ffe36368dfae49dc338c058c2b8ad6" - integrity sha512-Iq1nJ6D2+yIO4c8HHg4fyVb8mAJieo1Oloy1mLLaB2PvezNedhBVm+QU7g0qM42aiMbRXTxKKwGD17rjKNJYVQ== - -file-type@^6.1.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-6.2.0.tgz#e50cd75d356ffed4e306dc4f5bcf52a79903a919" - integrity sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg== - file-type@^9.0.0: version "9.0.0" resolved "https://registry.yarnpkg.com/file-type/-/file-type-9.0.0.tgz#a68d5ad07f486414dfb2c8866f73161946714a18" @@ -13278,20 +13017,6 @@ filelist@^1.0.1: dependencies: minimatch "^5.0.1" -filename-reserved-regex@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz#abf73dfab735d045440abfea2d91f389ebbfa229" - integrity sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ== - -filenamify@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/filenamify/-/filenamify-3.0.0.tgz#9603eb688179f8c5d40d828626dcbb92c3a4672c" - integrity sha512-5EFZ//MsvJgXjBAFJ+Bh2YaCTRF/VP1YOmGrgt+KJ4SFRLjI87EIdwLLuT6wQX0I4F9W41xutobzczjsOKlI/g== - dependencies: - filename-reserved-regex "^2.0.0" - strip-outer "^1.0.0" - trim-repeated "^1.0.0" - fill-range@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" @@ -13573,7 +13298,7 @@ fs-extra@^1.0.0: jsonfile "^2.1.0" klaw "^1.0.0" -fs-extra@^10.0.0, fs-extra@^10.0.1, fs-extra@^10.1.0: +fs-extra@^10.0.0, fs-extra@^10.1.0: version "10.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== @@ -13582,10 +13307,10 @@ fs-extra@^10.0.0, fs-extra@^10.0.1, fs-extra@^10.1.0: jsonfile "^6.0.1" universalify "^2.0.0" -fs-extra@^11.1.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.1.0.tgz#5784b102104433bb0e090f48bfc4a30742c357ed" - integrity sha512-0rcTq621PD5jM/e0a3EJoGC/1TC5ZBCERW82LQuwfGnCa1V8w7dpYH1yNu+SLb6E5dkeCBzKEyLGlFrnr+dUyw== +fs-extra@^11.1.1: + version "11.1.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.1.1.tgz#da69f7c39f3b002378b0954bb6ae7efdc0876e2d" + integrity sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ== dependencies: graceful-fs "^4.2.0" jsonfile "^6.0.1" @@ -13618,7 +13343,7 @@ fs-extra@^8.1.0: jsonfile "^4.0.0" universalify "^0.1.0" -fs-extra@^9.0.0, fs-extra@^9.0.1, fs-extra@^9.1.0: +fs-extra@^9.0.0, fs-extra@^9.0.1: version "9.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== @@ -13664,16 +13389,6 @@ fsevents@^2.1.2, fsevents@~2.3.2: resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== -fstream@^1.0.12: - version "1.0.12" - resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045" - integrity sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg== - dependencies: - graceful-fs "^4.1.2" - inherits "~2.0.0" - mkdirp ">=0.5 0" - rimraf "2" - ftp-response-parser@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/ftp-response-parser/-/ftp-response-parser-1.0.1.tgz#3b9d33f8edd5fb8e4700b8f778c462e5b1581f89" @@ -13866,15 +13581,7 @@ get-stdin@^6.0.0: resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g== -get-stream@^2.2.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-2.3.1.tgz#5f38f93f346009666ee0150a054167f91bdd95de" - integrity sha512-AUGhbbemXxrZJRD5cDvKtQxLuYaIbNtDTK8YqupCI393Q2KSTreEsLUN3ZxAWFGiKTzL6nKuzfcIvieflUX9qA== - dependencies: - object-assign "^4.0.1" - pinkie-promise "^2.0.0" - -get-stream@^4.0.0, get-stream@^4.1.0: +get-stream@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== @@ -13921,6 +13628,18 @@ gifwrap@^0.9.2: image-q "^4.0.0" omggif "^1.0.10" +git-repo-info@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/git-repo-info/-/git-repo-info-2.1.1.tgz#220ffed8cbae74ef8a80e3052f2ccb5179aed058" + integrity sha512-8aCohiDo4jwjOwma4FmYFd3i97urZulL8XL24nIPxuE+GZnfsAyy/g2Shqx6OjUiFKUXZM+Yy+KHnOmmA3FVcg== + +gitconfiglocal@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/gitconfiglocal/-/gitconfiglocal-2.1.0.tgz#07c28685c55cc5338b27b5acbcfe34aeb92e43d1" + integrity sha512-qoerOEliJn3z+Zyn1HW2F6eoYJqKwS6MgC9cztTLUB/xLWX8gD/6T60pKn4+t/d6tP7JlybI7Z3z+I572CR/Vg== + dependencies: + ini "^1.3.2" + github-from-package@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" @@ -14011,7 +13730,7 @@ gopd@^1.0.1: dependencies: get-intrinsic "^1.1.3" -got@^11.0.2, got@^11.8.1, got@^11.8.5, got@^8.3.1: +got@^11.0.2, got@^11.8.1, got@^11.8.5: version "11.8.5" resolved "https://registry.yarnpkg.com/got/-/got-11.8.5.tgz#ce77d045136de56e8f024bebb82ea349bc730046" integrity sha512-o0Je4NvQObAuZPHLFoRSkdG2lTgtcynqymzg2Vupdx6PorhaT5MCbIyXG6d4D94kk8ZG57QeosgdiqfJWhEhlQ== @@ -14028,15 +13747,10 @@ got@^11.0.2, got@^11.8.1, got@^11.8.5, got@^8.3.1: p-cancelable "^2.0.0" responselike "^2.0.0" -graceful-fs@^4.1.10, graceful-fs@^4.2.2, graceful-fs@^4.2.3, graceful-fs@^4.2.9: - version "4.2.10" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" - integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== - -graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.4: - version "4.2.6" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee" - integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ== +graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.3, graceful-fs@^4.2.4, graceful-fs@^4.2.9: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== graceful-fs@~2.0.0: version "2.0.3" @@ -14609,7 +14323,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -14629,7 +14343,7 @@ ini@2.0.0, ini@^2.0.0: resolved "https://registry.yarnpkg.com/ini/-/ini-2.0.0.tgz#e5fd556ecdd5726be978fa1001862eacb0a94bc5" integrity sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA== -ini@^1.3.4, ini@~1.3.0: +ini@^1.3.2, ini@^1.3.4, ini@~1.3.0: version "1.3.8" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== @@ -15035,11 +14749,6 @@ is-nan@^1.2.1: call-bind "^1.0.0" define-properties "^1.1.3" -is-natural-number@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8" - integrity sha512-Y4LTamMe0DDQIIAlaer9eKebAlDSV6huy+TWhJVPlzZh2o4tRP5SQWFlLn5N0To4mDD22/qdOq+veo1cSISLgQ== - is-negative-zero@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24" @@ -16641,11 +16350,6 @@ lint-staged@10.5.4: string-argv "0.3.1" stringify-object "^3.3.0" -listenercount@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/listenercount/-/listenercount-1.0.1.tgz#84c8a72ab59c4725321480c975e6508342e70937" - integrity sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ== - listr2@^3.2.2: version "3.10.0" resolved "https://registry.yarnpkg.com/listr2/-/listr2-3.10.0.tgz#58105a53ed7fa1430d1b738c6055ef7bb006160f" @@ -16987,23 +16691,16 @@ ltgt@^2.1.3, ltgt@~2.2.0: resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.2.1.tgz#f35ca91c493f7b73da0e07495304f17b31f87ee5" integrity sha1-81ypHEk/e3PaDgdJUwTxezH4fuU= -luxon@^3.0.4: - version "3.2.1" - resolved "https://registry.yarnpkg.com/luxon/-/luxon-3.2.1.tgz#14f1af209188ad61212578ea7e3d518d18cee45f" - integrity sha512-QrwPArQCNLAKGO/C+ZIilgIuDnEnKx5QYODdDtbFaxzsbZcc/a7WFq7MhsVYgRlwawLtvOUESTlfJ+hc/USqPg== +luxon@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/luxon/-/luxon-3.3.0.tgz#d73ab5b5d2b49a461c47cedbc7e73309b4805b48" + integrity sha512-An0UCfG/rSiqtAIiBPO0Y9/zAnHUZxAMiCpTd5h2smgsj7GGmcenvrvww2cqNA8/4A5ZrD1gJpHN2mIHZQF+Mg== lz-string@^1.4.4: version "1.4.4" resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.4.4.tgz#c0d8eaf36059f705796e1e344811cf4c498d3a26" integrity sha512-0ckx7ZHRPqb0oUm8zNr+90mtf9DQB60H1wMCjBtfi62Kl3a7JbHob6gA2bC+xRvZoOL+1hzUK8jeuEIQE8svEQ== -make-dir@^1.0.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" - integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ== - dependencies: - pify "^3.0.0" - make-dir@^2.0.0, make-dir@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" @@ -18083,7 +17780,7 @@ minimalistic-crypto-utils@^1.0.1: resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= -minimatch@5.1.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.2, minimatch@^5.0.0, minimatch@^5.0.1, minimatch@^5.1.0, minimatch@~3.0.2: +minimatch@5.1.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.2, minimatch@^5.0.0, minimatch@^5.0.1, minimatch@^5.1.0, minimatch@^6.0.4, minimatch@~3.0.2: version "5.1.0" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.0.tgz#1717b464f4971b144f6aabe8f2d0b8e4511e09c7" integrity sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg== @@ -18137,23 +17834,28 @@ mkdirp@0.x.x, mkdirp@^0.5.1, mkdirp@^0.5.5, mkdirp@~0.5.0, mkdirp@~0.5.1: dependencies: minimist "^1.2.5" -"mkdirp@>=0.5 0", mkdirp@^0.5.3, mkdirp@^0.5.6: +mkdirp@^0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.3.5.tgz#de3e5f8961c88c787ee1368df849ac4413eca8d7" + integrity sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc= + +mkdirp@^0.5.3, mkdirp@^0.5.6: version "0.5.6" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== dependencies: minimist "^1.2.6" -mkdirp@^0.3.5: - version "0.3.5" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.3.5.tgz#de3e5f8961c88c787ee1368df849ac4413eca8d7" - integrity sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc= - mkdirp@^1.0.0, mkdirp@^1.0.3, mkdirp@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== +mkdirp@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-3.0.1.tgz#e44e4c5607fb279c168241713cc6e0fea9adcb50" + integrity sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg== + mockery@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mockery/-/mockery-2.1.0.tgz#5b0aef1ff564f0f8139445e165536c7909713470" @@ -18266,16 +17968,16 @@ multihashes@^0.4.15, multihashes@~0.4.15: varint "^5.0.0" multiple-cucumber-html-reporter@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/multiple-cucumber-html-reporter/-/multiple-cucumber-html-reporter-3.0.1.tgz#06560e37b6699bc4a5792b6c87cee4f3504aa4ee" - integrity sha512-ccmDnlD/RK7321/TwpoOJ5D6Me2lQRsMTl21rpPvxItnPcpFIx9nMyHmQsL0tjIgn03n8v/p0rxFK+gJzzO+AQ== + version "3.4.0" + resolved "https://registry.yarnpkg.com/multiple-cucumber-html-reporter/-/multiple-cucumber-html-reporter-3.4.0.tgz#03db1772834952c70555ee16074d26c308d18ca4" + integrity sha512-Y2FQA/OosmlsB/ZQUPJvnkKKYFKa/J+Qv2QUl5PsO3BC77jXwyPE8fAWopLH+CEYlRTs7fcdfydmWFitGMFi0A== dependencies: find "^0.3.0" - fs-extra "^10.1.0" + fs-extra "^11.1.1" jsonfile "^6.1.0" - lodash "^4.17.19" - luxon "^3.0.4" - open "^8.4.0" + lodash "^4.17.21" + luxon "^3.3.0" + open "^8.4.2" uuid "^9.0.0" mute-stream@0.0.7: @@ -18311,11 +18013,6 @@ nan@^2.0.5, nan@^2.14.0, nan@^2.2.1: resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01" integrity sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw== -nan@^2.15.0: - version "2.17.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.17.0.tgz#c0150a2368a182f033e9aa5195ec76ea41a199cb" - integrity sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ== - nanoclone@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/nanoclone/-/nanoclone-0.2.1.tgz#dd4090f8f1a110d26bb32c49ed2f5b9235209ed4" @@ -18716,7 +18413,7 @@ npmlog@4.x, npmlog@^4.0.1, npmlog@^4.1.2: gauge "~2.7.3" set-blocking "~2.0.0" -npmlog@^5.0.0, npmlog@^5.0.1: +npmlog@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-5.0.1.tgz#f06678e80e29419ad67ab964e0fa69959c1eb8b0" integrity sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw== @@ -19058,10 +18755,10 @@ open@^7.4.2: is-docker "^2.0.0" is-wsl "^2.1.1" -open@^8.2.0, open@^8.4.0: - version "8.4.0" - resolved "https://registry.yarnpkg.com/open/-/open-8.4.0.tgz#345321ae18f8138f82565a910fdc6b39e8c244f8" - integrity sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q== +open@^8.2.0, open@^8.4.2: + version "8.4.2" + resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9" + integrity sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ== dependencies: define-lazy-prop "^2.0.0" is-docker "^2.1.1" @@ -19180,13 +18877,6 @@ p-each-series@^2.1.0: resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-2.2.0.tgz#105ab0357ce72b202a8a8b94933672657b5e2a9a" integrity sha512-ycIL2+1V32th+8scbpTvyHNaHe02z0sjgh91XXjAk+ZeXoPN4Z46DVUnzdso0aX4KckKw0FNNFHdjZ2UsZvxiA== -p-event@^2.1.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/p-event/-/p-event-2.3.1.tgz#596279ef169ab2c3e0cae88c1cfbb08079993ef6" - integrity sha512-NQCqOFhbpVTMX4qMe8PF8lbGtzZ+LCiN7pcNrb/413Na7+TRoe1xkKUzuWa/YEJdGQ0FvKtj35EEbDoVPO2kbA== - dependencies: - p-timeout "^2.0.1" - p-finally@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" @@ -19244,13 +18934,6 @@ p-map@^4.0.0: dependencies: aggregate-error "^3.0.0" -p-timeout@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-2.0.1.tgz#d8dd1979595d2dc0139e1fe46b8b646cb3cdf038" - integrity sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA== - dependencies: - p-finally "^1.0.0" - p-try@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" @@ -19596,7 +19279,7 @@ pify@4.0.1, pify@^4.0.1: resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== -pify@^2.0.0, pify@^2.3.0: +pify@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= @@ -21247,7 +20930,7 @@ readable-stream@1.0.33: isarray "0.0.1" string_decoder "~0.10.x" -"readable-stream@2 || 3", readable-stream@^3.0.0, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: +"readable-stream@2 || 3", readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== @@ -21266,7 +20949,7 @@ readable-stream@^1.0.26-4, readable-stream@^1.0.27-1, readable-stream@^1.0.31, r isarray "0.0.1" string_decoder "~0.10.x" -readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.2.2, readable-stream@^2.2.9, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6: +readable-stream@^2.0.0, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.2.2, readable-stream@^2.2.9, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== @@ -21361,6 +21044,11 @@ redux-persist@6.0.0: resolved "https://registry.yarnpkg.com/redux-persist/-/redux-persist-6.0.0.tgz#b4d2972f9859597c130d40d4b146fecdab51b3a8" integrity sha512-71LLMbUq2r02ng2We9S215LtPu3fY0KgaGE0k8WRgl6RkqxtGfl7HUozz1Dftwsb0D/5mZ8dwAaPbtnzfvbEwQ== +redux-thunk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.4.2.tgz#b9d05d11994b99f7a91ea223e8b04cf0afa5ef3b" + integrity sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q== + redux@4.1.1, redux@^4.0.0, redux@^4.0.5: version "4.1.1" resolved "https://registry.yarnpkg.com/redux/-/redux-4.1.1.tgz#76f1c439bb42043f985fbd9bf21990e60bd67f47" @@ -21745,13 +21433,6 @@ rgb2hex@^0.1.0: resolved "https://registry.yarnpkg.com/rgb2hex/-/rgb2hex-0.1.10.tgz#4fdd432665273e2d5900434940ceba0a04c8a8a8" integrity sha512-vKz+kzolWbL3rke/xeTE2+6vHmZnNxGyDnaVW4OckntAIcc7DcZzWkQSfxMDwqHS8vhgySnIFyBUH7lIk6PxvQ== -rimraf@2, rimraf@2.x.x, rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.3: - version "2.7.1" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" - integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== - dependencies: - glob "^7.1.3" - rimraf@2.6.3, rimraf@~2.6.2: version "2.6.3" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" @@ -21759,6 +21440,13 @@ rimraf@2.6.3, rimraf@~2.6.2: dependencies: glob "^7.1.3" +rimraf@2.x.x, rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.3: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + rimraf@3.0.2, rimraf@^3.0.0, rimraf@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" @@ -22071,13 +21759,6 @@ seed-random@~2.2.0: resolved "https://registry.yarnpkg.com/seed-random/-/seed-random-2.2.0.tgz#2a9b19e250a817099231a5b99a4daf80b7fbed54" integrity sha512-34EQV6AAHQGhoc0tn/96a9Fsi6v2xdqe/dMUwljGRaFOzR3EgRmECvD0O8vi8X+/uQ50LGHfkNu/Eue5TPKZkQ== -seek-bzip@^1.0.5: - version "1.0.6" - resolved "https://registry.yarnpkg.com/seek-bzip/-/seek-bzip-1.0.6.tgz#35c4171f55a680916b52a07859ecf3b5857f21c4" - integrity sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ== - dependencies: - commander "^2.8.1" - selenium-webdriver@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/selenium-webdriver/-/selenium-webdriver-3.6.0.tgz#2ba87a1662c020b8988c981ae62cb2a01298eafc" @@ -22255,7 +21936,7 @@ set-value@^2.0.0, set-value@^2.0.1, set-value@^4.0.1: is-plain-object "^2.0.4" is-primitive "^3.0.1" -setimmediate@^1.0.5, setimmediate@~1.0.4: +setimmediate@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= @@ -22743,13 +22424,6 @@ split-string@^3.0.2: dependencies: extend-shallow "^3.0.0" -split2@^3.2.2: - version "3.2.2" - resolved "https://registry.yarnpkg.com/split2/-/split2-3.2.2.tgz#bf2cf2a37d838312c249c89206fd7a17dd12365f" - integrity sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg== - dependencies: - readable-stream "^3.0.0" - split2@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/split2/-/split2-4.1.0.tgz#101907a24370f85bb782f08adaabe4e281ecf809" @@ -23115,13 +22789,6 @@ strip-bom@^4.0.0: resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== -strip-dirs@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/strip-dirs/-/strip-dirs-2.1.0.tgz#4987736264fc344cf20f6c34aca9d13d1d4ed6c5" - integrity sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g== - dependencies: - is-natural-number "^4.0.1" - strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" @@ -23149,13 +22816,6 @@ strip-json-comments@^3.0.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1 resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== -strip-outer@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/strip-outer/-/strip-outer-1.0.1.tgz#b2fd2abf6604b9d1e6013057195df836b8a9d631" - integrity sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg== - dependencies: - escape-string-regexp "^1.0.2" - sudo-prompt@^9.0.0: version "9.2.1" resolved "https://registry.yarnpkg.com/sudo-prompt/-/sudo-prompt-9.2.1.tgz#77efb84309c9ca489527a4e749f287e6bdd52afd" @@ -23282,19 +22942,6 @@ tar-fs@2.1.1, tar-fs@^2.0.0, tar-fs@^2.1.1: pump "^3.0.0" tar-stream "^2.1.4" -tar-stream@^1.5.2: - version "1.6.2" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" - integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A== - dependencies: - bl "^1.0.0" - buffer-alloc "^1.2.0" - end-of-stream "^1.0.0" - fs-constants "^1.0.0" - readable-stream "^2.3.0" - to-buffer "^1.1.1" - xtend "^4.0.0" - tar-stream@^2.1.0, tar-stream@^2.1.4, tar-stream@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" @@ -23306,7 +22953,7 @@ tar-stream@^2.1.0, tar-stream@^2.1.4, tar-stream@^2.2.0: inherits "^2.0.3" readable-stream "^3.1.1" -tar@6.1.11, tar@^6.0.2, tar@^6.1.11: +tar@6.1.11, tar@^6.0.2: version "6.1.11" resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621" integrity sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA== @@ -23480,13 +23127,6 @@ tinycolor2@^1.4.1: resolved "https://registry.yarnpkg.com/tinycolor2/-/tinycolor2-1.4.2.tgz#3f6a4d1071ad07676d7fa472e1fac40a719d8803" integrity sha512-vJhccZPs965sV/L2sU4oRQVAos0pQXwsvTLkWYdqJ+a8Q5kPFzJTuOFwy7UniPli44NKQGAglksjvOcpo95aZA== -tmp-promise@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/tmp-promise/-/tmp-promise-3.0.3.tgz#60a1a1cc98c988674fcbfd23b6e3367bdeac4ce7" - integrity sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ== - dependencies: - tmp "^0.2.0" - tmp@0.0.30: version "0.0.30" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.30.tgz#72419d4a8be7d6ce75148fd8b324e593a711c2ed" @@ -23501,7 +23141,7 @@ tmp@^0.0.33: dependencies: os-tmpdir "~1.0.2" -tmp@^0.2.0, tmp@^0.2.1: +tmp@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ== @@ -23513,11 +23153,6 @@ tmpl@1.0.x: resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== -to-buffer@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" - integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg== - to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" @@ -23609,11 +23244,6 @@ traverse-chain@~0.1.0: resolved "https://registry.yarnpkg.com/traverse-chain/-/traverse-chain-0.1.0.tgz#61dbc2d53b69ff6091a12a168fd7d433107e40f1" integrity sha512-up6Yvai4PYKhpNp5PkYtx50m3KbwQrqDwbuZP/ItyL64YEWHAvH6Md83LFLV/GRSk/BoUVwwgUzX6SOQSbsfAg== -"traverse@>=0.3.0 <0.4": - version "0.3.9" - resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.3.9.tgz#717b8f220cc0bb7b44e40514c22b2e8bbc70d8b9" - integrity sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ== - traverse@~0.6.3: version "0.6.6" resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.6.6.tgz#cbdf560fd7b9af632502fed40f918c157ea97137" @@ -23629,13 +23259,6 @@ treeify@~1.0.1: resolved "https://registry.yarnpkg.com/treeify/-/treeify-1.0.1.tgz#69b3cd022022a168424e7cfa1ced44c939d3eb2f" integrity sha1-abPNAiAioWhCTnz6HO1EyTnT6y8= -trim-repeated@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/trim-repeated/-/trim-repeated-1.0.0.tgz#e3646a2ea4e891312bf7eace6cfb05380bc01c21" - integrity sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg== - dependencies: - escape-string-regexp "^1.0.2" - triple-beam@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.3.0.tgz#a595214c7298db8339eeeee083e4d10bd8cb8dd9" @@ -23853,7 +23476,7 @@ unbox-primitive@^1.0.2: has-symbols "^1.0.3" which-boxed-primitive "^1.0.2" -unbzip2-stream@1.4.3, unbzip2-stream@^1.0.9, unbzip2-stream@^1.3.3: +unbzip2-stream@1.4.3, unbzip2-stream@^1.3.3: version "1.4.3" resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz#b0da04c4371311df771cdc215e87f2130991ace7" integrity sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg== @@ -23866,11 +23489,6 @@ underscore@1.12.1, underscore@~1.4.4, underscore@~1.5.2: resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.12.1.tgz#7bb8cc9b3d397e201cf8553336d262544ead829e" integrity sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw== -undici@^4.15.1: - version "4.16.0" - resolved "https://registry.yarnpkg.com/undici/-/undici-4.16.0.tgz#469bb87b3b918818d3d7843d91a1d08da357d5ff" - integrity sha512-tkZSECUYi+/T1i4u+4+lwZmQgLXd4BLGlrc7KZPcLIW7Jpq99+Xpc30ONv7nS6F5UNOxp/HBZSSL9MafUrvJbw== - unicode-canonical-property-names-ecmascript@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818" @@ -23970,22 +23588,6 @@ untildify@^4.0.0: resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" integrity sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw== -unzipper@^0.10.11: - version "0.10.11" - resolved "https://registry.yarnpkg.com/unzipper/-/unzipper-0.10.11.tgz#0b4991446472cbdb92ee7403909f26c2419c782e" - integrity sha512-+BrAq2oFqWod5IESRjL3S8baohbevGcVA+teAIOYWM3pDVdseogqbzhhvvmiyQrUNKFUnDMtELW3X8ykbyDCJw== - dependencies: - big-integer "^1.6.17" - binary "~0.3.0" - bluebird "~3.4.1" - buffer-indexof-polyfill "~1.0.0" - duplexer2 "~0.1.4" - fstream "^1.0.12" - graceful-fs "^4.2.2" - listenercount "~1.0.1" - readable-stream "~2.3.6" - setimmediate "~1.0.4" - upper-case-first@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/upper-case-first/-/upper-case-first-2.0.2.tgz#992c3273f882abd19d1e02894cc147117f844324" @@ -24308,23 +23910,6 @@ wcwidth@^1.0.1: dependencies: defaults "^1.0.3" -wdio-chromedriver-service@^7.3.2: - version "7.3.2" - resolved "https://registry.yarnpkg.com/wdio-chromedriver-service/-/wdio-chromedriver-service-7.3.2.tgz#569053df4ceaf6ce9e43bebcdd540197f516e313" - integrity sha512-4M3OqFzBSC4FdbqkfwOrUMeroMEuyIFCHfcUebkU6tJ1w5GenWO61YweJ8NKlhPZx9nkO8223+20MpvBjv+fTg== - dependencies: - "@wdio/logger" "^7.5.3" - fs-extra "^9.1.0" - split2 "^3.2.2" - tcp-port-used "^1.0.1" - -wdio-cucumber-reporter@^0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/wdio-cucumber-reporter/-/wdio-cucumber-reporter-0.0.2.tgz#6dc9efee8e2bbe225a175f9fd1d4e9871c1252c2" - integrity sha512-BvVcsXZY1sV8G2hgZzQGw/5pKB2Zs8E/7Vjrb9efUSrxYBjqJoo/331ZDrMsYAqvdbCfuzxOAi+g8ekLDGYY1g== - dependencies: - babel-runtime "^5.8.25" - wdio-cucumberjs-json-reporter@^4.4.3: version "4.4.3" resolved "https://registry.yarnpkg.com/wdio-cucumberjs-json-reporter/-/wdio-cucumberjs-json-reporter-4.4.3.tgz#3727a85acac6bc95480dcb5ec4df56063711d0a1" @@ -24337,28 +23922,6 @@ wdio-cucumberjs-json-reporter@^4.4.3: strip-ansi "^6.0.1" webdriverio "~7.16.13" -wdio-image-comparison-service@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/wdio-image-comparison-service/-/wdio-image-comparison-service-3.1.1.tgz#402192bb2fdc1a3ef2ba46c654b5ac253f1b8c8d" - integrity sha512-W0JQNAbz3kEAAOz7erJB00APw0y5um3DbI60BAHNQrq8K5Q/vVNNgjmjQaQkpJ8bcUoqoQIJJBdU9zZT88DcWg== - dependencies: - "@wdio/logger" "^7.19.0" - webdriver-image-comparison "0.20.3" - -wdio-vscode-service@^0.1.5: - version "0.1.13" - resolved "https://registry.yarnpkg.com/wdio-vscode-service/-/wdio-vscode-service-0.1.13.tgz#e8ccc148cb063bd20c15bf0a2d098238e0b13b5d" - integrity sha512-C6xvGT5CmHAvyIe7+S7TuggOIhEZbias9GsB6kMEIT7n2DNgBBmSDZtHzQIqVWlJTWBTx2MtObLwQsUKG9JkOA== - dependencies: - "@vscode/test-electron" "^2.1.3" - "@wdio/logger" "^7.17.3" - clipboardy "^2.3.0" - download "^8.0.0" - slash "^3.0.0" - tmp-promise "^3.0.3" - undici "^4.15.1" - wdio-chromedriver-service "^7.3.2" - weak@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/weak/-/weak-1.0.1.tgz#ab99aab30706959aa0200cb8cf545bb9cb33b99e" @@ -24406,15 +23969,6 @@ web3@^0.20.7: xhr2-cookies "^1.1.0" xmlhttprequest "*" -webdriver-image-comparison@0.20.3: - version "0.20.3" - resolved "https://registry.yarnpkg.com/webdriver-image-comparison/-/webdriver-image-comparison-0.20.3.tgz#4d89d3cf2ebdb67c2316c572baf492a8fdf59e0f" - integrity sha512-rSMOB/maanlcIqzFCqSY676I6p8h2Ewa/XFxBKdZb8XLk64QjEdtGlXcdT8Cbz0Kuf8k1+bhfbwAKgpIBBWvvg== - dependencies: - canvas "^2.9.1" - chalk "^4.1.2" - fs-extra "^10.0.1" - webdriver@5.23.0: version "5.23.0" resolved "https://registry.yarnpkg.com/webdriver/-/webdriver-5.23.0.tgz#5373e3e43803aaf962da24b47bbdb98bf8f84cc6" @@ -24455,101 +24009,53 @@ webdriver@7.16.16: ky "^0.29.0" lodash.merge "^4.6.1" -webdriver@7.25.1: - version "7.25.1" - resolved "https://registry.yarnpkg.com/webdriver/-/webdriver-7.25.1.tgz#0e9a98093f0a572b846048eb7a5e422db04f58bd" - integrity sha512-BmR5RT37EGNJj/O/GTCqBKXV/Jr9V4oQTTDaurZixVKW0ubG7uyfrhiklzuWUtmES9VualTKgQumhGhchBTC6g== - dependencies: - "@types/node" "^18.0.0" - "@wdio/config" "7.25.1" - "@wdio/logger" "7.19.0" - "@wdio/protocols" "7.22.0" - "@wdio/types" "7.25.1" - "@wdio/utils" "7.25.1" - got "^11.0.2" - ky "0.30.0" - lodash.merge "^4.6.1" - -webdriver@7.27.0: - version "7.27.0" - resolved "https://registry.yarnpkg.com/webdriver/-/webdriver-7.27.0.tgz#41d23a6c38bd79ea868f0b9fb9c9e3d4b6e4f8bd" - integrity sha512-870uIBnrGJ86g3DdYjM+PHhqdWf6NxysSme1KIs6irWxK+LqcaWKWhN75PldE+04xJB2mVWt1tKn0NBBFTWeMg== +webdriver@7.31.1: + version "7.31.1" + resolved "https://registry.yarnpkg.com/webdriver/-/webdriver-7.31.1.tgz#2dafdef92b59dc6456023ac92a9707d7331ecdb6" + integrity sha512-nCdJLxRnYvOMFqTEX7sqQtF/hV/Jgov0Y6ICeOm1DMTlZSRRDaUsBMlEAPkEwif9uBJYdM0znv8qzfX358AGqQ== dependencies: "@types/node" "^18.0.0" - "@wdio/config" "7.26.0" + "@wdio/config" "7.31.1" "@wdio/logger" "7.26.0" "@wdio/protocols" "7.27.0" - "@wdio/types" "7.26.0" - "@wdio/utils" "7.26.0" + "@wdio/types" "7.30.2" + "@wdio/utils" "7.30.2" got "^11.0.2" ky "0.30.0" lodash.merge "^4.6.1" -webdriverio@7.25.2: - version "7.25.2" - resolved "https://registry.yarnpkg.com/webdriverio/-/webdriverio-7.25.2.tgz#9fcb360d7ac47118b886bfa911a6f06bffafc932" - integrity sha512-lZwHh1G2Zxg4LmVQZZZNhKAqjGoSxoDaqlAf0ojh/3DcWVxMpFtaj0mksrqCyVhObudb2dopOX26beWPyKwL4A== +webdriverio@7.31.1: + version "7.31.1" + resolved "https://registry.yarnpkg.com/webdriverio/-/webdriverio-7.31.1.tgz#631171ff8f2a7c0b34014079465489b54ecc9a3a" + integrity sha512-ri8L7A8VbJ2lZyndu0sG56d2zBot7SXdeI95Kni43e0pd/5Xm4IMAPdWB60yS8vqrP8goJU2iuQ8/ltry4IDbQ== dependencies: "@types/aria-query" "^5.0.0" "@types/node" "^18.0.0" - "@wdio/config" "7.25.1" - "@wdio/logger" "7.19.0" - "@wdio/protocols" "7.22.0" - "@wdio/repl" "7.25.1" - "@wdio/types" "7.25.1" - "@wdio/utils" "7.25.1" - archiver "^5.0.0" - aria-query "^5.0.0" - css-shorthand-properties "^1.1.1" - css-value "^0.0.1" - devtools "7.25.1" - devtools-protocol "^0.0.1056733" - fs-extra "^10.0.0" - grapheme-splitter "^1.0.2" - lodash.clonedeep "^4.5.0" - lodash.isobject "^3.0.2" - lodash.isplainobject "^4.0.6" - lodash.zip "^4.2.0" - minimatch "^5.0.0" - puppeteer-core "^13.1.3" - query-selector-shadow-dom "^1.0.0" - resq "^1.9.1" - rgb2hex "0.2.5" - serialize-error "^8.0.0" - webdriver "7.25.1" - -webdriverio@7.28.1: - version "7.28.1" - resolved "https://registry.yarnpkg.com/webdriverio/-/webdriverio-7.28.1.tgz#b6a7567ee0c9e93a8bd525aa393090a7a87a7f60" - integrity sha512-fz0nALbRpEPvJf8+ptwPoyxlpknQonOzpXeBFqGjxcUoQ6eT817xZG8Cp35KJmra1KXQCrQVjO+9yy8bROZcig== - dependencies: - "@types/aria-query" "^5.0.0" - "@types/node" "^18.0.0" - "@wdio/config" "7.26.0" + "@wdio/config" "7.31.1" "@wdio/logger" "7.26.0" "@wdio/protocols" "7.27.0" - "@wdio/repl" "7.26.0" - "@wdio/types" "7.26.0" - "@wdio/utils" "7.26.0" + "@wdio/repl" "7.30.2" + "@wdio/types" "7.30.2" + "@wdio/utils" "7.30.2" archiver "^5.0.0" aria-query "^5.0.0" css-shorthand-properties "^1.1.1" css-value "^0.0.1" - devtools "7.28.1" - devtools-protocol "^0.0.1084670" - fs-extra "^11.1.0" + devtools "7.31.1" + devtools-protocol "^0.0.1130274" + fs-extra "^11.1.1" grapheme-splitter "^1.0.2" lodash.clonedeep "^4.5.0" lodash.isobject "^3.0.2" lodash.isplainobject "^4.0.6" lodash.zip "^4.2.0" - minimatch "^5.0.0" + minimatch "^6.0.4" puppeteer-core "^13.1.3" query-selector-shadow-dom "^1.0.0" resq "^1.9.1" rgb2hex "0.2.5" serialize-error "^8.0.0" - webdriver "7.27.0" + webdriver "7.31.1" webdriverio@^5.10.9: version "5.23.0" @@ -24775,11 +24281,6 @@ wide-align@^1.1.2, wide-align@^1.1.5: dependencies: string-width "^1.0.2 || 2 || 3 || 4" -window-size@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.4.tgz#f8e1aa1ee5a53ec5bf151ffa09742a6ad7697876" - integrity sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY= - winston-transport@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.5.0.tgz#6e7b0dd04d393171ed5e4e4905db265f7ab384fa" @@ -25097,7 +24598,7 @@ xtend@~3.0.0: resolved "https://registry.yarnpkg.com/xtend/-/xtend-3.0.0.tgz#5cce7407baf642cba7becda568111c493f59665a" integrity sha1-XM50B7r2Qsunvs2laBEcST9ZZlo= -y18n@^3.2.0, y18n@^3.2.1, "y18n@^3.2.1 || ^4.0.0", y18n@^3.2.2, y18n@^4.0.0, y18n@^5.0.5: +y18n@^3.2.1, "y18n@^3.2.1 || ^4.0.0", y18n@^3.2.2, y18n@^4.0.0, y18n@^5.0.5: version "3.2.2" resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.2.tgz#85c901bd6470ce71fc4bb723ad209b70f7f28696" integrity sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ== @@ -25251,19 +24752,6 @@ yargs@^17.0.0: y18n "^5.0.5" yargs-parser "^21.0.0" -yargs@^3.30.0: - version "3.32.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.32.0.tgz#03088e9ebf9e756b69751611d2a5ef591482c995" - integrity sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU= - dependencies: - camelcase "^2.0.1" - cliui "^3.0.3" - decamelize "^1.1.1" - os-locale "^1.4.0" - string-width "^1.0.1" - window-size "^0.1.4" - y18n "^3.2.0" - yargs@^7.0.2: version "7.1.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.2.tgz#63a0a5d42143879fdbb30370741374e0641d55db" @@ -25292,7 +24780,7 @@ yarn-install@^1.0.0: chalk "^1.1.3" cross-spawn "^4.0.2" -yauzl@^2.10.0, yauzl@^2.4.2, yauzl@^2.7.0: +yauzl@^2.10.0, yauzl@^2.7.0: version "2.10.0" resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" integrity sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==