diff --git a/app/components/Nav/App/index.js b/app/components/Nav/App/index.js
index 2965348a569..331754de1be 100644
--- a/app/components/Nav/App/index.js
+++ b/app/components/Nav/App/index.js
@@ -63,6 +63,7 @@ import AccountConnect from '../../../components/Views/AccountConnect';
import AccountPermissions from '../../../components/Views/AccountPermissions';
import { AccountPermissionsScreens } from '../../../components/Views/AccountPermissions/AccountPermissions.types';
import AccountPermissionsConfirmRevokeAll from '../../../components/Views/AccountPermissions/AccountPermissionsConfirmRevokeAll';
+import ConnectionDetails from '../../../components/Views/AccountPermissions/ConnectionDetails';
import { SRPQuiz } from '../../Views/Quiz';
import { TurnOffRememberMeModal } from '../../../components/UI/TurnOffRememberMeModal';
import AssetHideConfirmation from '../../Views/AssetHideConfirmation';
@@ -424,6 +425,10 @@ const RootModalFlow = () => (
name={Routes.SHEET.REVOKE_ALL_ACCOUNT_PERMISSIONS}
component={AccountPermissionsConfirmRevokeAll}
/>
+
{renderTopIcon()}
-
+
+ {!isRenderedAsBottomSheet && (
+ {
+ navigate(Routes.MODAL.ROOT_MODAL_FLOW, {
+ screen: Routes.SHEET.CONNECTION_DETAILS,
+ params: {
+ hostInfo: {
+ metadata: {
+ origin:
+ currentPageInformation?.url &&
+ new URL(currentPageInformation?.url).hostname,
+ },
+ },
+ connectionDateTime: new Date().getTime(),
+ },
+ });
+ }}
+ testID={SDKSelectorsIDs.CONNECTION_DETAILS_BUTTON}
+ />
+ )}
+
);
}
@@ -150,20 +178,24 @@ const PermissionsSummary = ({
);
+ const onRevokeAllHandler = useCallback(async () => {
+ await Engine.context.PermissionController.revokeAllPermissions(hostname);
+ navigate('PermissionsManager');
+ }, [hostname, navigate]);
+
const toggleRevokeAllPermissionsModal = useCallback(() => {
navigate(Routes.MODAL.ROOT_MODAL_FLOW, {
screen: Routes.SHEET.REVOKE_ALL_ACCOUNT_PERMISSIONS,
params: {
hostInfo: {
metadata: {
- origin:
- currentPageInformation?.url &&
- new URL(currentPageInformation?.url).hostname,
+ origin: hostname,
},
},
+ onRevokeAll: !isRenderedAsBottomSheet && onRevokeAllHandler,
},
});
- }, [navigate, currentPageInformation?.url]);
+ }, [navigate, isRenderedAsBottomSheet, onRevokeAllHandler, hostname]);
const getAccountLabel = useCallback(() => {
if (isAlreadyConnected) {
@@ -346,10 +378,10 @@ const PermissionsSummary = ({
{!isAlreadyConnected || isNetworkSwitch
? strings('permissions.title_dapp_url_wants_to', {
- dappUrl: new URL(currentPageInformation.url).hostname,
+ dappUrl: hostname,
})
: strings('permissions.title_dapp_url_has_approval_to', {
- dappUrl: new URL(currentPageInformation.url).hostname,
+ dappUrl: hostname,
})}
diff --git a/app/components/UI/PermissionsSummary/__snapshots__/PermissionsSummary.test.tsx.snap b/app/components/UI/PermissionsSummary/__snapshots__/PermissionsSummary.test.tsx.snap
index 5fb871e2b3d..dc178c8b497 100644
--- a/app/components/UI/PermissionsSummary/__snapshots__/PermissionsSummary.test.tsx.snap
+++ b/app/components/UI/PermissionsSummary/__snapshots__/PermissionsSummary.test.tsx.snap
@@ -99,6 +99,7 @@ exports[`PermissionsSummary should render correctly 1`] = `
{
>([]);
const { toastRef } = useContext(ToastContext);
- const accountAvatarType = useSelector((state: RootState) =>
- state.settings.useBlockieIcon
- ? AvatarAccountType.Blockies
- : AvatarAccountType.JazzIcon,
- );
// origin is set to the last active tab url in the browser which can conflict with sdk
const inappBrowserOrigin: string = useSelector(getActiveTabUrl, isEqual);
@@ -439,11 +432,6 @@ const AccountConnect = (props: AccountConnectProps) => {
};
const connectedAccountLength = selectedAddresses.length;
const activeAddress = selectedAddresses[0];
- const activeAccountName = getAccountNameWithENS({
- accountAddress: activeAddress,
- accounts,
- ensByAccountAddress,
- });
try {
setIsLoading(true);
@@ -463,26 +451,15 @@ const AccountConnect = (props: AccountConnectProps) => {
source: eventSource,
});
let labelOptions: ToastOptions['labelOptions'] = [];
- if (connectedAccountLength > 1) {
- labelOptions = [
- { label: `${connectedAccountLength} `, isBold: true },
- {
- label: `${strings('toast.accounts_connected')}`,
- },
- { label: `\n${activeAccountName} `, isBold: true },
- { label: strings('toast.now_active') },
- ];
- } else {
- labelOptions = [
- { label: `${activeAccountName} `, isBold: true },
- { label: strings('toast.connected_and_active') },
- ];
+
+ if (connectedAccountLength >= 1) {
+ labelOptions = [{ label: `${strings('toast.permissions_updated')}` }];
}
+
toastRef?.current?.showToast({
- variant: ToastVariants.Account,
+ variant: ToastVariants.Network,
labelOptions,
- accountAddress: activeAddress,
- accountAvatarType,
+ networkImageSource: faviconSource,
hasNoTimeout: false,
});
} catch (e) {
@@ -496,14 +473,12 @@ const AccountConnect = (props: AccountConnectProps) => {
eventSource,
selectedAddresses,
hostInfo,
- accounts,
- ensByAccountAddress,
- accountAvatarType,
toastRef,
accountsLength,
channelIdOrHostname,
triggerDappViewedEvent,
trackEvent,
+ faviconSource,
]);
const handleCreateAccount = useCallback(
diff --git a/app/components/Views/AccountConnect/AccountConnectMultiSelector/AccountConnectMultiSelector.tsx b/app/components/Views/AccountConnect/AccountConnectMultiSelector/AccountConnectMultiSelector.tsx
index 157534a5c53..3dc556a5f01 100644
--- a/app/components/Views/AccountConnect/AccountConnectMultiSelector/AccountConnectMultiSelector.tsx
+++ b/app/components/Views/AccountConnect/AccountConnectMultiSelector/AccountConnectMultiSelector.tsx
@@ -21,6 +21,7 @@ import AccountSelectorList from '../../../UI/AccountSelectorList';
import HelpText, {
HelpTextSeverity,
} from '../../../../component-library/components/Form/HelpText';
+import Engine from '../../../../core/Engine';
// Internal dependencies.
import { ConnectAccountBottomSheetSelectorsIDs } from '../../../../../e2e/selectors/Browser/ConnectAccountBottomSheet.selectors';
@@ -84,6 +85,11 @@ const AccountConnectMultiSelector = ({
[accounts, selectedAddresses, onSelectAddress],
);
+ const onRevokeAllHandler = useCallback(async () => {
+ await Engine.context.PermissionController.revokeAllPermissions(hostname);
+ navigate('PermissionsManager');
+ }, [hostname, navigate]);
+
const toggleRevokeAllAccountPermissionsModal = useCallback(() => {
navigate(Routes.MODAL.ROOT_MODAL_FLOW, {
screen: Routes.SHEET.REVOKE_ALL_ACCOUNT_PERMISSIONS,
@@ -93,9 +99,10 @@ const AccountConnectMultiSelector = ({
origin: urlWithProtocol && new URL(urlWithProtocol).hostname,
},
},
+ onRevokeAll: !isRenderedAsBottomSheet && onRevokeAllHandler,
},
});
- }, [navigate, urlWithProtocol]);
+ }, [navigate, urlWithProtocol, isRenderedAsBottomSheet, onRevokeAllHandler]);
const renderSelectAllButton = useCallback(
() =>
diff --git a/app/components/Views/AccountPermissions/AccountPermissions.tsx b/app/components/Views/AccountPermissions/AccountPermissions.tsx
index ed6589becd9..42101ac25ef 100755
--- a/app/components/Views/AccountPermissions/AccountPermissions.tsx
+++ b/app/components/Views/AccountPermissions/AccountPermissions.tsx
@@ -196,8 +196,7 @@ const AccountPermissions = (props: AccountPermissionsProps) => {
useEffect(() => {
if (
previousPermittedAccounts.current === undefined &&
- permittedAccountsByHostname.length === 0 &&
- isRenderedAsBottomSheet
+ permittedAccountsByHostname.length === 0
) {
// TODO - Figure out better UX instead of auto dismissing. However, we cannot be in this state as long as accounts are not connected.
hideSheet();
diff --git a/app/components/Views/AccountPermissions/AccountPermissionsConfirmRevokeAll/AccountPermissionsConfirmRevokeAll.tsx b/app/components/Views/AccountPermissions/AccountPermissionsConfirmRevokeAll/AccountPermissionsConfirmRevokeAll.tsx
index fa06c49bbc6..8d3082a2ef7 100644
--- a/app/components/Views/AccountPermissions/AccountPermissionsConfirmRevokeAll/AccountPermissionsConfirmRevokeAll.tsx
+++ b/app/components/Views/AccountPermissions/AccountPermissionsConfirmRevokeAll/AccountPermissionsConfirmRevokeAll.tsx
@@ -26,6 +26,7 @@ interface AccountPermissionsConfirmRevokeAllProps {
hostInfo: {
metadata: { origin: string };
};
+ onRevokeAll?: () => void;
};
};
}
@@ -37,6 +38,7 @@ const AccountPermissionsConfirmRevokeAll = (
hostInfo: {
metadata: { origin: hostname },
},
+ onRevokeAll,
} = props.route.params;
const { styles } = useStyles(styleSheet, {});
@@ -48,12 +50,18 @@ const AccountPermissionsConfirmRevokeAll = (
const revokeAllAccounts = useCallback(async () => {
try {
- await Engine.context.PermissionController.revokeAllPermissions(hostname);
- sheetRef.current?.onCloseBottomSheet();
+ if (onRevokeAll) {
+ onRevokeAll();
+ } else {
+ await Engine.context.PermissionController.revokeAllPermissions(
+ hostname,
+ );
+ sheetRef.current?.onCloseBottomSheet();
+ }
} catch (e) {
Logger.log(`Failed to revoke all accounts for ${hostname}`, e);
}
- }, [hostname, Engine.context.PermissionController]);
+ }, [hostname, Engine.context.PermissionController, onRevokeAll]);
const onCancel = () => {
sheetRef.current?.onCloseBottomSheet();
diff --git a/app/components/Views/AccountPermissions/ConnectionDetails/ConnectionDetails.styles.ts b/app/components/Views/AccountPermissions/ConnectionDetails/ConnectionDetails.styles.ts
new file mode 100644
index 00000000000..4cd67a1f432
--- /dev/null
+++ b/app/components/Views/AccountPermissions/ConnectionDetails/ConnectionDetails.styles.ts
@@ -0,0 +1,26 @@
+// Third party dependencies.
+import { StyleSheet } from 'react-native';
+
+/**
+ * Style sheet function for AccountConnectMultiSelector screen.
+ * @returns StyleSheet object.
+ */
+const styleSheet = () =>
+ StyleSheet.create({
+ container: {
+ paddingHorizontal: 16,
+ alignItems: 'center',
+ },
+ descriptionContainer: {
+ marginBottom: 16,
+ },
+ buttonsContainer: {
+ flexDirection: 'row',
+ gap: 16,
+ },
+ button: {
+ flex: 1,
+ },
+ });
+
+export default styleSheet;
diff --git a/app/components/Views/AccountPermissions/ConnectionDetails/ConnectionDetails.tsx b/app/components/Views/AccountPermissions/ConnectionDetails/ConnectionDetails.tsx
new file mode 100644
index 00000000000..49463cd91de
--- /dev/null
+++ b/app/components/Views/AccountPermissions/ConnectionDetails/ConnectionDetails.tsx
@@ -0,0 +1,76 @@
+// Third party dependencies
+import React, { useRef } from 'react';
+
+// External dependencies
+import { View } from 'react-native';
+import BottomSheetHeader from '../../../../component-library/components/BottomSheets/BottomSheetHeader';
+import Button, {
+ ButtonVariants,
+ ButtonSize,
+} from '../../../../component-library/components/Buttons/Button';
+import Text, {
+ TextVariant,
+} from '../../../../component-library/components/Texts/Text';
+import { strings } from '../../../../../locales/i18n';
+import BottomSheet, {
+ BottomSheetRef,
+} from '../../../../component-library/components/BottomSheets/BottomSheet';
+import { useStyles } from '../../../../component-library/hooks';
+import styleSheet from './ConnectionDetails.styles';
+
+interface ConnectionDetailsProps {
+ route: {
+ params: {
+ connectionDateTime?: number;
+ };
+ };
+}
+
+const AccountPermissionsConfirmRevokeAll = (props: ConnectionDetailsProps) => {
+ const { connectionDateTime = 123456789 } = props.route.params;
+
+ const { styles } = useStyles(styleSheet, {});
+
+ const sheetRef = useRef(null);
+
+ const onDismiss = () => {
+ sheetRef.current?.onCloseBottomSheet();
+ };
+
+ const formatConnectionDate = (timestamp: number) =>
+ new Date(timestamp).toLocaleDateString('en-US', {
+ month: 'short',
+ day: 'numeric',
+ year: 'numeric',
+ });
+
+ return (
+
+
+
+
+ {strings('permissions.connection_details_title')}
+
+
+
+
+ {strings('permissions.connection_details_description', {
+ connectionDateTime: formatConnectionDate(connectionDateTime),
+ })}
+
+
+
+
+
+
+
+ );
+};
+
+export default AccountPermissionsConfirmRevokeAll;
diff --git a/app/components/Views/AccountPermissions/ConnectionDetails/index.ts b/app/components/Views/AccountPermissions/ConnectionDetails/index.ts
new file mode 100644
index 00000000000..508efb8efe9
--- /dev/null
+++ b/app/components/Views/AccountPermissions/ConnectionDetails/index.ts
@@ -0,0 +1 @@
+export { default } from './ConnectionDetails';
diff --git a/app/components/Views/NetworkConnect/NetworkConnectMultiSelector/NetworkConnectMultiSelector.tsx b/app/components/Views/NetworkConnect/NetworkConnectMultiSelector/NetworkConnectMultiSelector.tsx
index d44f7b3bea5..7f865484329 100644
--- a/app/components/Views/NetworkConnect/NetworkConnectMultiSelector/NetworkConnectMultiSelector.tsx
+++ b/app/components/Views/NetworkConnect/NetworkConnectMultiSelector/NetworkConnectMultiSelector.tsx
@@ -159,6 +159,11 @@ const NetworkConnectMultiSelector = ({
[networks, selectedChainIds],
);
+ const onRevokeAllHandler = useCallback(async () => {
+ await Engine.context.PermissionController.revokeAllPermissions(hostname);
+ navigate('PermissionsManager');
+ }, [hostname, navigate]);
+
const toggleRevokeAllNetworkPermissionsModal = useCallback(() => {
navigate(Routes.MODAL.ROOT_MODAL_FLOW, {
screen: Routes.SHEET.REVOKE_ALL_ACCOUNT_PERMISSIONS,
@@ -168,13 +173,14 @@ const NetworkConnectMultiSelector = ({
origin: urlWithProtocol && new URL(urlWithProtocol).hostname,
},
},
+ onRevokeAll: !isRenderedAsBottomSheet && onRevokeAllHandler,
},
});
- }, [navigate, urlWithProtocol]);
+ }, [navigate, urlWithProtocol, isRenderedAsBottomSheet, onRevokeAllHandler]);
+
const areAllNetworksSelected = networks
.map(({ id }) => id)
.every((id) => selectedChainIds?.includes(id));
-
const areAnyNetworksSelected = selectedChainIds?.length !== 0;
const areNoNetworksSelected = selectedChainIds?.length === 0;
diff --git a/app/components/Views/Settings/PermissionsSettings/PermissionItem/PermissionItem.tsx b/app/components/Views/Settings/PermissionsSettings/PermissionItem/PermissionItem.tsx
index d0eb1bc2dfc..5705ce2141a 100644
--- a/app/components/Views/Settings/PermissionsSettings/PermissionItem/PermissionItem.tsx
+++ b/app/components/Views/Settings/PermissionsSettings/PermissionItem/PermissionItem.tsx
@@ -11,13 +11,10 @@ import Icon, {
IconSize,
} from '../../../../../component-library/components/Icons/Icon';
import styleSheet from './PermissionItem.style';
-import {
- PermissionListItemViewModel,
- PermissionSource,
-} from './PermissionItem.types';
+import { PermissionListItemViewModel } from './PermissionItem.types';
import WebsiteIcon from '../../../../../components/UI/WebsiteIcon';
-import Tag from '../../../../../component-library/components/Tags/Tag';
import { strings } from '../../../../../../locales/i18n';
+import { useFavicon } from '../../../../hooks/useFavicon';
interface PermissionListItemProps {
item: PermissionListItemViewModel;
@@ -29,10 +26,11 @@ const PermissionItem: React.FC = ({
onPress,
}) => {
const { styles } = useStyles(styleSheet, {});
+ const faviconUrl = useFavicon(item.dappHostName);
return (
-
+
@@ -40,32 +38,19 @@ const PermissionItem: React.FC = ({
- {item.numberOfAccountPermissions}
+ {item.numberOfAccountPermissions}{' '}
{item.numberOfAccountPermissions > 1
? strings('app_settings.accounts')
: strings('app_settings.account')}
•
- {item.numberOfNetworkPermissions}
+ {item.numberOfNetworkPermissions}{' '}
{item.numberOfNetworkPermissions > 1
? strings('app_settings.networks')
: strings('app_settings.network')}
-
-
-
-
-
diff --git a/app/components/Views/Settings/PermissionsSettings/PermissionItem/__snapshots__/PermissionItem.test.tsx.snap b/app/components/Views/Settings/PermissionsSettings/PermissionItem/__snapshots__/PermissionItem.test.tsx.snap
index 26274e0fa98..0f349286650 100644
--- a/app/components/Views/Settings/PermissionsSettings/PermissionItem/__snapshots__/PermissionItem.test.tsx.snap
+++ b/app/components/Views/Settings/PermissionsSettings/PermissionItem/__snapshots__/PermissionItem.test.tsx.snap
@@ -133,6 +133,7 @@ exports[`PermissionItem renders correctly 1`] = `
}
>
5
+
accounts
2
+
networks
-
-
-
-
- WalletConnect
-
-
-
-
;
@@ -53,6 +64,52 @@ const PermissionsManager = (props: SDKSessionsManagerProps) => {
const { colors, typography } = useTheme();
const styles = createStyles(colors, typography, safeAreaInsets);
const { navigation } = props;
+ const [inAppBrowserPermissions, setInAppBrowserPermissions] = useState<
+ PermissionListItemViewModel[]
+ >([]);
+ const subjects = useSelector(
+ (state: RootState) =>
+ (
+ state.engine.backgroundState
+ .PermissionController as PermissionControllerState
+ ).subjects,
+ );
+
+ useEffect(() => {
+ const uuidRegex =
+ /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
+ const walletConnectRegex = /^https?:\/\//;
+ const inAppBrowserSubjects: any[] = [];
+
+ Object.entries(subjects || {}).forEach(([key, value]) => {
+ if (key === 'npm:@metamask/message-signing-snap') return;
+
+ if (
+ !uuidRegex.test(key) &&
+ !walletConnectRegex.test((value as { origin: string }).origin)
+ ) {
+ inAppBrowserSubjects.push(value);
+ }
+ });
+
+ const mappedInAppBrowserPermissions: PermissionListItemViewModel[] =
+ inAppBrowserSubjects.map((subject) => ({
+ dappLogoUrl: '',
+ dappHostName: subject.origin,
+ numberOfAccountPermissions:
+ subject.permissions?.eth_accounts?.caveats?.[0]?.value?.length ?? 0,
+ numberOfNetworkPermissions:
+ subject.permissions?.['endowment:permitted-chains']?.caveats?.[0]
+ ?.value?.length ?? 0,
+ permissionSource: PermissionSource.MetaMaskBrowser,
+ }));
+
+ const mappedPermissions: PermissionListItemViewModel[] = [
+ ...mappedInAppBrowserPermissions,
+ ];
+
+ setInAppBrowserPermissions(mappedPermissions);
+ }, [subjects]);
useEffect(() => {
navigation.setOptions(
@@ -65,36 +122,38 @@ const PermissionsManager = (props: SDKSessionsManagerProps) => {
);
}, [navigation, colors]);
- const goToPermissionsDetails = useCallback(() => {
- navigation.navigate('AccountPermissionsAsFullScreen', {
- hostInfo: {
- metadata: {
- origin: 'https://app.uniswap.org/',
+ const goToPermissionsDetails = useCallback(
+ (permissionItem: PermissionListItemViewModel) => {
+ navigation.navigate('AccountPermissionsAsFullScreen', {
+ hostInfo: {
+ metadata: {
+ origin: permissionItem.dappHostName,
+ },
},
- },
- isRenderedAsBottomSheet: false,
- });
- }, [navigation]);
+ isRenderedAsBottomSheet: false,
+ });
+ },
+ [navigation],
+ );
const renderPermissions = useCallback(
() => (
<>
- {
- /* TODO: replace mock data with real data once available */
- isMultichainVersion1Enabled &&
- mockPermissionItems.map((mockPermissionItem, _index) => (
-
- ))
- }
+ {isMultichainVersion1Enabled &&
+ inAppBrowserPermissions.map((permissionItem, index) => (
+ {
+ goToPermissionsDetails(permissionItem);
+ }}
+ />
+ ))}
>
),
- [goToPermissionsDetails],
+ [goToPermissionsDetails, inAppBrowserPermissions],
);
const renderEmptyResult = () => (
@@ -114,7 +173,7 @@ const PermissionsManager = (props: SDKSessionsManagerProps) => {
style={styles.perissionsWrapper}
testID={SDKSelectorsIDs.SESSION_MANAGER_CONTAINER}
>
- {isMultichainVersion1Enabled && mockPermissionItems.length
+ {isMultichainVersion1Enabled && inAppBrowserPermissions.length
? renderPermissions()
: renderEmptyResult()}
diff --git a/app/constants/navigation/Routes.ts b/app/constants/navigation/Routes.ts
index 986f216ae83..1a5197f213b 100644
--- a/app/constants/navigation/Routes.ts
+++ b/app/constants/navigation/Routes.ts
@@ -103,6 +103,7 @@ const Routes = {
ACCOUNT_CONNECT: 'AccountConnect',
ACCOUNT_PERMISSIONS: 'AccountPermissions',
REVOKE_ALL_ACCOUNT_PERMISSIONS: 'RevokeAllAccountPermissions',
+ CONNECTION_DETAILS: 'ConnectionDetails',
NETWORK_SELECTOR: 'NetworkSelector',
RETURN_TO_DAPP_MODAL: 'ReturnToDappModal',
ACCOUNT_ACTIONS: 'AccountActions',
diff --git a/e2e/selectors/Settings/SDK.selectors.js b/e2e/selectors/Settings/SDK.selectors.js
index 6411cdd1375..3d3dde6739c 100644
--- a/e2e/selectors/Settings/SDK.selectors.js
+++ b/e2e/selectors/Settings/SDK.selectors.js
@@ -1,3 +1,4 @@
export const SDKSelectorsIDs = {
SESSION_MANAGER_CONTAINER: 'sdk-session-manager',
+ CONNECTION_DETAILS_BUTTON: 'connection-details-button',
};
diff --git a/locales/languages/en.json b/locales/languages/en.json
index 0e22f5e0b41..35616e1495c 100644
--- a/locales/languages/en.json
+++ b/locales/languages/en.json
@@ -1874,7 +1874,10 @@
"connected_to": "Connected to ",
"manage_permissions": "Manage Permissions",
"edit": "Edit",
- "cancel": "Cancel"
+ "cancel": "Cancel",
+ "got_it": "Got it",
+ "connection_details_title": "Connection Details",
+ "connection_details_description": "You connected to this site using the MetaMask browser on {{connectionDateTime}}"
},
"select": {
"cancel": "Cancel",
diff --git a/sonar-project.properties b/sonar-project.properties
index 33a00fb92ff..8c88e9d9529 100644
--- a/sonar-project.properties
+++ b/sonar-project.properties
@@ -15,7 +15,7 @@ sonar.exclusions=**.stories.**, e2e/**, wdio/**
sonar.test.inclusions=**.test.**
# Excluded project files from coverage.
-sonar.coverage.exclusions=**AccountConnectMultiSelector**, **AccountPermissionsConfirmRevokeAll**, **PermissionsSettings**, **NetworkConnectMultiSelector**, **NetworkSelectorList**, **PermissionsSummary**, **AccountConnect.tsx, **util/test**, **AccountPermissions.tsx, **NetworkVerificationInfo.tsx,
+sonar.coverage.exclusions=**AccountConnectMultiSelector**, **AccountPermissionsConfirmRevokeAll**, **PermissionsSettings**, **NetworkConnectMultiSelector**, **NetworkSelectorList**, **PermissionsSummary**, **AccountConnect.tsx, **util/test**, **AccountPermissions.tsx, **NetworkVerificationInfo.tsx, **ConnectionDetails**
# Test coverage path in GitHub action
sonar.javascript.lcov.reportPaths=/coverage/lcov.info