Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OCT-2125: Metrics E2E #570

Merged
merged 10 commits into from
Dec 5, 2024
2 changes: 1 addition & 1 deletion client/cypress/e2e/_12settings.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -262,8 +262,8 @@ Object.values(viewports).forEach(
cy.getAllLocalStorage().then(() => {
expect(localStorage.getItem(IS_ONBOARDING_ALWAYS_VISIBLE)).eq('true');
});

cy.reload();

cy.get('[data-test=ModalOnboarding]').should('be.visible');
cy.get('[data-test=ModalOnboarding__Button]').click();

Expand Down
188 changes: 188 additions & 0 deletions client/cypress/e2e/_13metrics.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
// eslint-disable-next-line import/no-extraneous-dependencies
import chaiColors from 'chai-colors';

import { mockCoinPricesServer, visitWithLoader } from 'cypress/utils/e2e';
import viewports from 'cypress/utils/viewports';
import {
HAS_ONBOARDING_BEEN_CLOSED,
IS_ONBOARDING_ALWAYS_VISIBLE,
IS_ONBOARDING_DONE,
} from 'src/constants/localStorageKeys';
import { ROOT_ROUTES } from 'src/routes/RootRoutes/routes';

chai.use(chaiColors);

Object.values(viewports).forEach(
({ device, viewportWidth, viewportHeight, isMobile, isTablet }) => {
describe(`[AW IS OPEN] Metrics: ${device}`, { viewportHeight, viewportWidth }, () => {
before(() => {
cy.clearLocalStorage();
});

beforeEach(() => {
mockCoinPricesServer();
localStorage.setItem(IS_ONBOARDING_ALWAYS_VISIBLE, 'false');
localStorage.setItem(IS_ONBOARDING_DONE, 'true');
localStorage.setItem(HAS_ONBOARDING_BEEN_CLOSED, 'true');
visitWithLoader(ROOT_ROUTES.metrics.absolute);
});

it('Metrics title is visible and has correct text', () => {
cy.get('[data-test=MetricsView__title]').should('be.visible');
cy.get('[data-test=MetricsView__title]').invoke('text').should('eq', 'Explore the data');
});

it('"Epoch" secion is visible', () => {
cy.get('[data-test=MetricsEpoch]').should('be.visible');
});

it('"General" secion is visible', () => {
cy.get('[data-test=MetricsGeneral]').should('be.visible');
});

it('"Epoch" section title is visible and has correct text', () => {
cy.get('[data-test=MetricsEpochHeader__title]').should('be.visible');
cy.get('[data-test=MetricsEpochHeader__title]')
.invoke('text')
.should('eq', isMobile || isTablet ? 'E3 Allocation' : 'Epoch 3 Allocation Window');
});

it('"General" section title is visible and has correct text', () => {
cy.get('[data-test=MetricsGeneral__header__title]').should('be.visible');
cy.get('[data-test=MetricsGeneral__header__title]')
.invoke('text')
.should('eq', 'General metrics');
});

it('"Epoch" section title has "OPEN" badge when AW is open', () => {
cy.get('[data-test=MetricsEpochHeader__openBadge]').should('be.visible');
cy.get('[data-test=MetricsEpochHeader__openBadge]').invoke('text').should('eq', 'Open');
cy.get('[data-test=MetricsEpochHeader__openBadge]')
.then($el => $el.css('backgroundColor'))
.should('be.colored', '#2d9b87');
cy.get('[data-test=MetricsEpochHeader__openBadge]')
.then($el => $el.css('textTransform'))
.should('eq', 'uppercase');
});

it('User is able to change epoch via arrow buttons', () => {
cy.get('[data-test=MetricsEpochHeader__NavigationArrows]').should('be.visible');
cy.get('[data-test=MetricsEpochHeader__NavigationArrows__leftArrow]').click();
cy.get('[data-test=MetricsEpochHeader__title]')
.invoke('text')
.should('eq', isMobile || isTablet ? 'E2 Allocation' : 'Epoch 2 Allocation Window');
cy.get('[data-test=MetricsEpochHeader__NavigationArrows__rightArrow]').click();
cy.get('[data-test=MetricsEpochHeader__title]')
.invoke('text')
.should('eq', isMobile || isTablet ? 'E3 Allocation' : 'Epoch 3 Allocation Window');
});

it('"Epoch" section title has epoch dates range when epoch is past', () => {
cy.get('[data-test=MetricsEpochHeader__openBadge]').should('be.visible');
cy.get('[data-test=MetricsEpochHeader__epochDuration]').should('not.exist');
cy.get('[data-test=MetricsEpochHeader__NavigationArrows__leftArrow]').click();
cy.get('[data-test=MetricsEpochHeader__openBadge]').should('not.exist');
cy.get('[data-test=MetricsEpochHeader__epochDuration]').should('be.visible');
});

it('Next arrow button is disabled when there is no more next epochs', () => {
cy.get('[data-test=MetricsEpochHeader__NavigationArrows__rightArrow]')
.then($el => $el.css('backgroundColor'))
.should('be.colored', '#fafafa');
cy.get('[data-test=MetricsEpochHeader__NavigationArrows__rightArrowSvg] path')
.then($el => $el.css('fill'))
.should('be.colored', '#ebebeb');
cy.get('[data-test=MetricsEpochHeader__title]')
.invoke('text')
.should('eq', isMobile || isTablet ? 'E3 Allocation' : 'Epoch 3 Allocation Window');
cy.get('[data-test=Layout__body]').scrollIntoView();
cy.get('[data-test=MetricsEpochHeader__NavigationArrows__rightArrow]').click();
cy.get('[data-test=MetricsEpochHeader__title]')
.invoke('text')
.should('eq', isMobile || isTablet ? 'E3 Allocation' : 'Epoch 3 Allocation Window');
});

it('Prev arrow button is disabled when there is no more prev epochs ', () => {
cy.get('[data-test=MetricsEpochHeader__NavigationArrows__leftArrow]')
.then($el => $el.css('backgroundColor'))
.should('be.colored', '#fafafa');
cy.get('[data-test=MetricsEpochHeader__NavigationArrows__leftArrowSvg] path')
.then($el => $el.css('fill'))
.should('be.colored', '#9ea39e');
cy.get('[data-test=MetricsEpochHeader__title]')
.invoke('text')
.should('eq', isMobile || isTablet ? 'E3 Allocation' : 'Epoch 3 Allocation Window');
cy.get('[data-test=Layout__body]').scrollIntoView();
cy.get('[data-test=MetricsEpochHeader__NavigationArrows__leftArrow]').click();
cy.wait(1000);
cy.get('[data-test=Layout__body]').scrollIntoView();
cy.get('[data-test=MetricsEpochHeader__NavigationArrows__leftArrow]').click();
cy.get('[data-test=MetricsEpochHeader__title]')
.invoke('text')
.should('eq', isMobile || isTablet ? 'E1 Allocation' : 'Epoch 1 Allocation Window');
cy.get('[data-test=MetricsEpochHeader__NavigationArrows__leftArrow]')
.then($el => $el.css('backgroundColor'))
.should('be.colored', '#fafafa');
cy.get('[data-test=MetricsEpochHeader__NavigationArrows__leftArrowSvg] path')
.then($el => $el.css('fill'))
.should('be.colored', '#ebebeb');
cy.get('[data-test=Layout__body]').scrollIntoView();
cy.get('[data-test=MetricsEpochHeader__NavigationArrows__leftArrow]').click();
cy.get('[data-test=MetricsEpochHeader__title]')
.invoke('text')
.should('eq', isMobile || isTablet ? 'E1 Allocation' : 'Epoch 1 Allocation Window');
});

it('All tiles in "Epoch" section are visible in correct order', () => {
const metricsEpochGridTilesDataTest = [
'MetricsEpochGridTopProjects',
'MetricsEpochGridFundsUsage',
'MetricsEpochGridTotalUsers',
'MetricsEpochGridPatrons',
'MetricsEpochGridRewardsUnused',
'MetricsEpochGridUnallocatedValue',
'MetricsEpochGridTotalDonations',
'MetricsEpochGridTotalMatchingFund',
'MetricsEpochGridCurrentDonors',
'MetricsEpochGridAverageLeverage',
'MetricsEpochGridDonationsVsMatching',
'MetricsEpochGridDonationsVsPersonalAllocations',
];

cy.get('[data-test=MetricsEpoch__MetricsGrid]')
.children()
.should('have.length', metricsEpochGridTilesDataTest.length);

for (let i = 0; i < metricsEpochGridTilesDataTest.length; i++) {
cy.get('[data-test=MetricsEpoch__MetricsGrid]')
.children()
.eq(i)
.invoke('data', 'test')
.should('eq', metricsEpochGridTilesDataTest[i]);
}
});

it('All tiles in "General" section are visible in correct order', () => {
const metricsGeneralGridTilesDataTest = [
'MetricsGeneralGridCumulativeGlmLocked',
'MetricsGeneralGridWalletsWithGlmLocked',
'MetricsGeneralGridTotalGlmLockedAndTotalSupply',
'MetricsGeneralGridTotalProjects',
'MetricsGeneralGridTotalEthStaked',
];

cy.get('[data-test=MetricsGeneral__MetricsGrid]')
.children()
.should('have.length', metricsGeneralGridTilesDataTest.length);

for (let i = 0; i < metricsGeneralGridTilesDataTest.length; i++) {
cy.get('[data-test=MetricsGeneral__MetricsGrid]')
.children()
.eq(i)
.invoke('data', 'test')
.should('eq', metricsGeneralGridTilesDataTest[i]);
}
});
});
},
);
5 changes: 3 additions & 2 deletions client/src/components/Metrics/MetricsEpoch/MetricsEpoch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import useLockedsData from 'hooks/subgraph/useLockedsData';
import styles from './MetricsEpoch.module.scss';

const MetricsEpoch = (): ReactElement => {
const dataTestRoot = 'MetricsEpoch';
const { epoch, lastEpoch } = useMetricsEpoch();
const { isFetching: isFetchingCurrentEpoch } = useCurrentEpoch();
const { isFetching: isFetchingCurrentEpochProps } = useCurrentEpochProps();
Expand Down Expand Up @@ -91,9 +92,9 @@ const MetricsEpoch = (): ReactElement => {
isFetchingEpochPatrons;

return (
<div className={styles.root} id={METRICS_EPOCH_ID}>
<div className={styles.root} data-test={dataTestRoot} id={METRICS_EPOCH_ID}>
<MetricsEpochHeader />
<MetricsGrid className={styles.grid} dataTest="MetricsEpoch__MetricsGrid">
<MetricsGrid className={styles.grid} dataTest={`${dataTestRoot}__MetricsGrid`}>
<MetricsEpochGridTopProjects className={styles.topProjects} isLoading={isLoading} />
<MetricsEpochGridFundsUsage
className={styles.fundsUsage}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const MetricsEpochDonationsProgressBar: FC<MetricsEpochDonationsProgressBarProps
: (100 - donationsValue).toFixed(2).replace(dotAndZeroes, '');

return (
<div className={styles.root}>
<div className={styles.root} data-test="MetricsEpochDonationsProgressBar">
<ProgressBar
className={styles.progressBar}
progressPercentage={donationsValue}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const MetricsEpochGridFundsUsage: FC<MetricsEpochGridFundsUsageProps> = ({
totalUserDonationsWithPatronRewards,
unusedRewards,
}) => {
const dataTestRoot = 'MetricsEpochGridFundsUsage';
const { t } = useTranslation('translation', { keyPrefix: 'views.metrics' });
const { epoch } = useMetricsEpoch();
const { data: epochInfo } = useEpochInfo(epoch);
Expand Down Expand Up @@ -160,7 +161,7 @@ const MetricsEpochGridFundsUsage: FC<MetricsEpochGridFundsUsageProps> = ({
return (
<MetricsGridTile
className={cx(styles.root, className)}
dataTest="MetricsEpochGridFundsUsage"
dataTest={dataTestRoot}
groups={[
{
children: (
Expand All @@ -174,7 +175,7 @@ const MetricsEpochGridFundsUsage: FC<MetricsEpochGridFundsUsageProps> = ({
</div>
<div
className={cx(styles.value, isLoading && styles.isLoading)}
data-test="MetricsEpochGridFundsUsage__total"
data-test={`${dataTestRoot}__total`}
>
{!isLoading &&
getValuesToDisplay({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const MetricsEpochGridTopProjects: FC<MetricsEpochGridTopProjectsProps> = ({
isLoading,
className,
}) => {
const dataTestRoot = 'MetricsEpochGridTopProjects';
const { i18n, t } = useTranslation('translation', { keyPrefix: 'views.metrics' });
const { epoch, lastEpoch } = useMetricsEpoch();
const { isLargeDesktop } = useMediaQuery();
Expand All @@ -33,12 +34,12 @@ const MetricsEpochGridTopProjects: FC<MetricsEpochGridTopProjectsProps> = ({
return (
<MetricsGridTile
className={cx(styles.root, className)}
dataTest="MetricsEpochGridTopProjects"
dataTest={dataTestRoot}
groups={[
{
children: (
<MetricsProjectsList
dataTest="MetricsEpochGridTopProjects__list"
dataTest={`${dataTestRoot}__projectsList`}
isLoading={isLoading}
numberOfSkeletons={12}
projects={projects}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ const MetricsEpochGridTotalDonations: FC<MetricsEpochGridTotalDonationsProps> =
totalUserDonations,
className,
}) => {
const dataTestRoot = 'MetricsEpochGridTotalDonations';

const { t } = useTranslation('translation', { keyPrefix: 'views.metrics' });

const getValuesToDisplay = useGetValuesToDisplay();
Expand All @@ -28,12 +30,12 @@ const MetricsEpochGridTotalDonations: FC<MetricsEpochGridTotalDonationsProps> =
return (
<MetricsGridTile
className={className}
dataTest="MetricsEpochGridTotalDonations"
dataTest={dataTestRoot}
groups={[
{
children: (
<MetricsGridTileValue
dataTest="MetricsEpochGridTotalDonations__MetricsGridTileValue"
dataTest={`${dataTestRoot}__totalDonations`}
isLoading={isLoading}
size="S"
subvalue={totalUserDonationsValues.secondary}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const MetricsEpochGridUnallocatedValue: FC<MetricsEpochGridUnallocatedValueProps
isLoading,
className,
}) => {
const dataTestRoot = 'MetricsEpochGridUnallocatedValue';
const { t } = useTranslation('translation', { keyPrefix: 'views.metrics' });

const { epoch } = useMetricsEpoch();
Expand All @@ -31,12 +32,12 @@ const MetricsEpochGridUnallocatedValue: FC<MetricsEpochGridUnallocatedValueProps
return (
<MetricsGridTile
className={className}
dataTest="MetricsEpochGridUnallocatedValue"
dataTest={dataTestRoot}
groups={[
{
children: (
<MetricsGridTileValue
dataTest="MetricsEpochGridUnallocatedValue"
dataTest={`${dataTestRoot}__unallocatedValue`}
isLoading={isLoading}
size="S"
subvalue={unallocatedValue.secondary}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import useIsDecisionWindowOpen from 'hooks/queries/useIsDecisionWindowOpen';
import styles from './MetricsEpochHeader.module.scss';

const MetricsEpochHeader = (): ReactElement => {
const dataTestRoot = 'MetricsEpochHeader';
const { t } = useTranslation('translation', { keyPrefix: 'views.metrics' });
const { isDesktop } = useMediaQuery();
const { epoch, lastEpoch, setEpoch } = useMetricsEpoch();
Expand All @@ -24,18 +25,24 @@ const MetricsEpochHeader = (): ReactElement => {

return (
<MetricsSectionHeader
dataTest={dataTestRoot}
title={t(isDesktop ? 'epochAllocationWindow' : 'epochAllocation', { epoch })}
>
<div className={styles.epochInfo}>
{isCurrentOpenEpoch ? (
<div className={styles.badge}>{t('open')}</div>
<div className={styles.badge} data-test={`${dataTestRoot}__openBadge`}>
{t('open')}
</div>
) : (
<div className={styles.epochDurationLabel}>{epochDurationLabel}</div>
<div className={styles.epochDurationLabel} data-test={`${dataTestRoot}__epochDuration`}>
{epochDurationLabel}
</div>
)}
</div>
<NavigationArrows
className={styles.arrows}
classNamePrevButton={styles.arrowLeft}
dataTest={`${dataTestRoot}__NavigationArrows`}
isNextButtonDisabled={isRightArrowDisabled}
isPrevButtonDisabled={isLeftArrowDisabled}
onClickNextButton={() => setEpoch(epoch + 1)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import useSettingsStore from 'store/settings/store';
import styles from './MetricsGeneral.module.scss';

const MetricsGeneral = (): ReactElement => {
const dataTestRoot = 'MetricsGeneral';
const { t } = useTranslation('translation', { keyPrefix: 'views.metrics' });
const {
data: { displayCurrency },
Expand All @@ -43,9 +44,9 @@ const MetricsGeneral = (): ReactElement => {
isFetchingProjectsEpoch;

return (
<div className={styles.root} id={METRICS_GENERAL_ID}>
<MetricsSectionHeader title={t('generalMetrics')} />
<MetricsGrid className={styles.grid} dataTest="MetricsGeneral__MetricsGrid">
<div className={styles.root} data-test={dataTestRoot} id={METRICS_GENERAL_ID}>
<MetricsSectionHeader dataTest={`${dataTestRoot}__header`} title={t('generalMetrics')} />
<MetricsGrid className={styles.grid} dataTest={`${dataTestRoot}__MetricsGrid`}>
<MetricsGeneralGridCumulativeGlmLocked />
<MetricsGeneralGridWalletsWithGlmLocked />
<MetricsGeneralGridTotalGlmLockedAndTotalSupply isLoading={isLoading} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ const MetricsSectionHeader: FC<MetricsSectionHeaderProps> = ({
}) => {
return (
<div className={styles.root} data-test={dataTest}>
<div className={styles.title}>{title}</div>
<div className={styles.title} data-test={`${dataTest}__title`}>
{title}
</div>
{children}
</div>
);
Expand Down
Loading
Loading