Skip to content

Commit

Permalink
feat(3765): Add modal to include metric id before redirecting to supp…
Browse files Browse the repository at this point in the history
…ort page
  • Loading branch information
DDDDDanica committed Feb 19, 2025
1 parent 2b39e3b commit 77c1d55
Show file tree
Hide file tree
Showing 15 changed files with 482 additions and 45 deletions.
12 changes: 12 additions & 0 deletions app/_locales/en/messages.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 25 additions & 1 deletion test/e2e/page-objects/pages/error-page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,15 @@ class ErrorPage {
private readonly sentryFeedbackSuccessModal =
'[data-testid="error-page-sentry-feedback-success-modal"]';

private readonly visitSupportDataConsentModal =
'[data-testid="visit-support-data-consent-modal"]';

private readonly visitSupportDataConsentModalAcceptButton =
'[data-testid="visit-support-data-consent-modal-accept-button"]';

private readonly visitSupportDataConsentModalRejectButton =
'[data-testid="visit-support-data-consent-modal-reject-button"]';

constructor(driver: Driver) {
this.driver = driver;
}
Expand Down Expand Up @@ -78,14 +87,29 @@ class ErrorPage {
);
}

async contactAndValidateMetaMaskSupport(): Promise<void> {
async contactAndValidateMetamaskSupport(): Promise<void> {
console.log(`Contact metamask support form in a separate page`);
await this.driver.waitUntilXWindowHandles(1);
await this.driver.clickElement(this.contactSupportButton);
}

async consentDataToMetamaskSupport(): Promise<void> {
await this.driver.waitForSelector(this.visitSupportDataConsentModal);
await this.driver.clickElementAndWaitToDisappear(
this.visitSupportDataConsentModalAcceptButton,
);
// metamask, help page
await this.driver.waitUntilXWindowHandles(2);
}

async rejectDataToMetamaskSupport(): Promise<void> {
await this.driver.waitForSelector(this.visitSupportDataConsentModal);
await this.driver.clickElementAndWaitToDisappear(
this.visitSupportDataConsentModalRejectButton,
);
await this.driver.waitUntilXWindowHandles(2);
}

async waitForSentrySuccessModal(): Promise<void> {
await this.driver.waitForSelector(this.sentryFeedbackSuccessModal);
await this.driver.assertElementNotPresent(this.sentryFeedbackSuccessModal);
Expand Down
36 changes: 33 additions & 3 deletions test/e2e/tests/metrics/developer-options-sentry.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import SettingsPage from '../../page-objects/pages/settings/settings-page';
import HeaderNavbar from '../../page-objects/pages/header-navbar';
import DevelopOptions from '../../page-objects/pages/developer-options-page';
import ErrorPage from '../../page-objects/pages/error-page';
import { MOCK_META_METRICS_ID } from '../../constants';

const triggerCrash = async (driver: Driver): Promise<void> => {
const headerNavbar = new HeaderNavbar(driver);
Expand Down Expand Up @@ -41,7 +42,7 @@ describe('Developer Options - Sentry', function (this: Suite) {
{
fixtures: new FixtureBuilder()
.withMetaMetricsController({
metaMetricsId: 'fake-metrics-id',
metaMetricsId: MOCK_META_METRICS_ID,
participateInMetaMetrics: true,
})
.build(),
Expand All @@ -64,7 +65,35 @@ describe('Developer Options - Sentry', function (this: Suite) {
);
});

it('gives option to cause a page crash and offer contact support option', async function () {
it('gives option to cause a page crash and offer contact support option with consenting to share data', async function () {
await withFixtures(
{
fixtures: new FixtureBuilder()
.withMetaMetricsController({
metaMetricsId: MOCK_META_METRICS_ID,
participateInMetaMetrics: true,
})
.build(),
title: this.test?.fullTitle(),
ignoredConsoleErrors: [
'Error#1: Unable to find value of key "developerOptions" for locale "en"',
'React will try to recreate this component tree from scratch using the error boundary you provided, Index.',
],
},
async ({ driver }: { driver: Driver }) => {
await loginWithBalanceValidation(driver);
await triggerCrash(driver);

const errorPage = new ErrorPage(driver);
await errorPage.check_pageIsLoaded();

await errorPage.contactAndValidateMetamaskSupport();
await errorPage.consentDataToMetamaskSupport();
},
);
});

it('gives option to cause a page crash and offer contact support option with rejecting to share data', async function () {
await withFixtures(
{
fixtures: new FixtureBuilder().build(),
Expand All @@ -81,7 +110,8 @@ describe('Developer Options - Sentry', function (this: Suite) {
const errorPage = new ErrorPage(driver);
await errorPage.check_pageIsLoaded();

await errorPage.contactAndValidateMetaMaskSupport();
await errorPage.contactAndValidateMetamaskSupport();
await errorPage.rejectDataToMetamaskSupport();
},
);
});
Expand Down
1 change: 1 addition & 0 deletions ui/components/app/modals/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
@import 'transaction-confirmed/index';
@import 'customize-nonce/index';
@import 'convert-token-to-nft-modal/index';
@import 'visit-support-data-consent-modal/index';

.modal {
z-index: 1050;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`VisitSupportDataConsentModal renders the modal correctly when open 1`] = `
<div
class="mm-modal visit-support-data-consent-modal"
data-testid="visit-support-data-consent-modal"
>
<div
aria-hidden="true"
class="mm-box mm-modal-overlay mm-box--width-full mm-box--height-full mm-box--background-color-overlay-default"
/>
<div
data-focus-guard="true"
style="width: 1px; height: 0px; padding: 0px; overflow: hidden; position: fixed; top: 1px; left: 1px;"
tabindex="0"
/>
<div
data-focus-lock-disabled="false"
>
<div
class="mm-box mm-modal-content mm-box--padding-top-4 mm-box--sm:padding-top-8 mm-box--md:padding-top-12 mm-box--padding-right-4 mm-box--padding-bottom-4 mm-box--sm:padding-bottom-8 mm-box--md:padding-bottom-12 mm-box--padding-left-4 mm-box--display-flex mm-box--justify-content-center mm-box--align-items-flex-start mm-box--width-screen mm-box--height-screen"
>
<section
aria-modal="true"
class="mm-box mm-modal-content__dialog mm-modal-content__dialog--size-sm mm-box--padding-top-4 mm-box--padding-bottom-4 mm-box--display-flex mm-box--flex-direction-column mm-box--width-full mm-box--background-color-background-default mm-box--rounded-lg"
role="dialog"
>
<header
class="mm-box mm-header-base mm-modal-header mm-box--padding-right-4 mm-box--padding-bottom-4 mm-box--padding-left-4 mm-box--display-flex mm-box--justify-content-space-between"
>
<div
class="mm-box mm-box--width-full"
>
<h4
class="mm-box mm-text mm-text--heading-sm mm-text--text-align-center mm-box--color-text-default"
>
Share device details with support
</h4>
</div>
</header>
<div
class="mm-box mm-modal-body visit-support-data-consent-modal__body mm-box--padding-right-4 mm-box--padding-left-4"
>
<p
class="mm-box mm-text mm-text--body-md mm-box--color-text-default"
>
Do you want to share your MetaMask Identifier and app version with our Support Center? This can help us better solve your problem, but is optional.
</p>
</div>
<div
class="mm-box mm-modal-footer mm-box--padding-top-4 mm-box--padding-right-4 mm-box--padding-left-4"
>
<div
class="mm-box mm-box--display-flex mm-box--gap-4"
>
<button
class="mm-box mm-text mm-button-base mm-button-base--size-lg mm-button-secondary mm-text--body-md-medium mm-box--padding-0 mm-box--padding-right-4 mm-box--padding-left-4 mm-box--display-inline-flex mm-box--justify-content-center mm-box--align-items-center mm-box--width-1/2 mm-box--color-primary-default mm-box--background-color-transparent mm-box--rounded-pill mm-box--border-color-primary-default box--border-style-solid box--border-width-1"
data-testid="visit-support-data-consent-modal-reject-button"
>
Don’t share
</button>
<button
class="mm-box mm-text mm-button-base mm-button-base--size-lg mm-button-primary mm-text--body-md-medium mm-box--padding-0 mm-box--padding-right-4 mm-box--padding-left-4 mm-box--display-inline-flex mm-box--justify-content-center mm-box--align-items-center mm-box--width-1/2 mm-box--color-primary-inverse mm-box--background-color-primary-default mm-box--rounded-pill"
data-testid="visit-support-data-consent-modal-accept-button"
data-theme="light"
>
Confirm
</button>
</div>
<div
class="mm-box mm-container mm-container--max-width-sm mm-box--margin-right-auto mm-box--margin-left-auto mm-box--display-flex mm-box--gap-4 mm-box--flex-wrap-wrap mm-box--align-items-center"
/>
</div>
</section>
</div>
</div>
<div
data-focus-guard="true"
style="width: 1px; height: 0px; padding: 0px; overflow: hidden; position: fixed; top: 1px; left: 1px;"
tabindex="0"
/>
</div>
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
@use 'design-system';

.visit-support-data-consent-modal {
&__body {
&__preference-checkbox {
margin-top: 16px;
margin-bottom: 16px;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './visit-support-data-consent-modal';
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from 'react';
import VisitSupportDataConsentModal from '.';

export default {
title: 'Components/App/Modals/VisitSupportDataConsentModal',
};

export const DefaultStory = () => (
<VisitSupportDataConsentModal
version="1.0.0"
isOpen
onClose={() => {}}
/>
);

DefaultStory.storyName = 'Default';
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import React, { useCallback, useContext } from 'react';
import { useSelector } from 'react-redux';
import { useI18nContext } from '../../../../hooks/useI18nContext';
import { selectSessionData } from '../../../../selectors/identity/authentication';
import { getMetaMetricsId } from '../../../../selectors/selectors';
import { openWindow } from '../../../../helpers/utils/window';
import {
Modal,
ModalOverlay,
ModalContent,
ModalHeader,
Box,
ModalFooter,
ButtonPrimary,
ButtonPrimarySize,
ModalBody,
Text,
ButtonSecondary,
ButtonSecondarySize,
} from '../../../../components/component-library';

Check failure on line 20 in ui/components/app/modals/visit-support-data-consent-modal/visit-support-data-consent-modal.tsx

View workflow job for this annotation

GitHub Actions / Test lint / Test lint

Useless path segments for "../../../../components/component-library", should be "../../../component-library"
import {
Display,
TextVariant,
BlockSize,
} from '../../../../helpers/constants/design-system';
import {
MetaMetricsContextProp,
MetaMetricsEventCategory,
MetaMetricsEventName,
} from '../../../../../shared/constants/metametrics';
import { MetaMetricsContext } from '../../../../contexts/metametrics';
import { SUPPORT_LINK } from '../../../../../shared/lib/ui-utils';

type VisitSupportDataConsentModalProps = {
onClose: () => void;
isOpen: boolean;
};

const VisitSupportDataConsentModal: React.FC<
VisitSupportDataConsentModalProps
> = ({ isOpen, onClose }) => {
const version = process.env.METAMASK_VERSION;
const t = useI18nContext();
const trackEvent = useContext(MetaMetricsContext);
const sessionData = useSelector(selectSessionData);
const profileId = sessionData?.profile?.profileId;
const metaMetricsId = useSelector(getMetaMetricsId);

const handleClickContactSupportButton = useCallback(() => {
onClose();
const supportLinkWithUserId = `${SUPPORT_LINK}?metamask_version=${version}&metamask_profile_id=${profileId}&metamask_metametrics_id=${metaMetricsId}`;
trackEvent(
{
category: MetaMetricsEventCategory.Settings,
event: MetaMetricsEventName.SupportLinkClicked,
properties: {
url: supportLinkWithUserId,
},
},
{
contextPropsIntoEventProperties: [MetaMetricsContextProp.PageTitle],
},
);
openWindow(supportLinkWithUserId);
}, [version, profileId, metaMetricsId, trackEvent, onClose]);

const handleClickNoShare = useCallback(() => {
onClose();
trackEvent(
{
category: MetaMetricsEventCategory.Settings,
event: MetaMetricsEventName.SupportLinkClicked,
properties: {
url: SUPPORT_LINK,
},
},
{
contextPropsIntoEventProperties: [MetaMetricsContextProp.PageTitle],
},
);
openWindow(SUPPORT_LINK as string);
}, [onClose, trackEvent]);

return (
<Modal
isOpen={isOpen}
onClose={onClose}
data-testid="visit-support-data-consent-modal"
className="visit-support-data-consent-modal"
>
<ModalOverlay />
<ModalContent>
<ModalHeader>{t('visitSupportDataConsentModalTitle')}</ModalHeader>
<ModalBody
paddingLeft={4}
paddingRight={4}
className="visit-support-data-consent-modal__body"
>
<Text variant={TextVariant.bodyMd}>
{t('visitSupportDataConsentModalDescription')}
</Text>
</ModalBody>

<ModalFooter>
<Box display={Display.Flex} gap={4}>
<ButtonSecondary
size={ButtonSecondarySize.Lg}
width={BlockSize.Half}
onClick={handleClickNoShare}
data-testid="visit-support-data-consent-modal-reject-button"
>
{t('visitSupportDataConsentModalReject')}
</ButtonSecondary>
<ButtonPrimary
size={ButtonPrimarySize.Lg}
width={BlockSize.Half}
onClick={handleClickContactSupportButton}
data-testid="visit-support-data-consent-modal-accept-button"
>
{t('visitSupportDataConsentModalAccept')}
</ButtonPrimary>
</Box>
</ModalFooter>
</ModalContent>
</Modal>
);
};

export default VisitSupportDataConsentModal;
Loading

0 comments on commit 77c1d55

Please sign in to comment.