Skip to content

Commit

Permalink
OCT-2125: Metrics E2E (#570)
Browse files Browse the repository at this point in the history
## Description
Check after [PR-567](#567)
## Definition of Done

1. [ ] If required, the desciption of your change is added to the [QA
changelog](https://www.notion.so/octantapp/Changelog-for-the-QA-d96fa3b411cf488bb1d8d9a598d88281)
2. [ ] Acceptance criteria are met.
3. [ ] PR is manually tested before the merge by developer(s).
    - [ ] Happy path is manually checked.
4. [ ] PR is manually tested by QA when their assistance is required
(1).
- [ ] Octant Areas & Test Cases are checked for impact and updated if
required (2).
5. [ ] Unit tests are added unless there is a reason to omit them.
6. [ ] Automated tests are added when required.
7. [ ] The code is merged.
8. [ ] Tech documentation is added / updated, reviewed and approved
(including mandatory approval by a code owner, should such exist for
changed files).
    - [ ] BE: Swagger documentation is updated.
9. [ ] When required by QA:
    - [ ] Deployed to the relevant environment.
    - [ ] Passed system tests.

---

(1) Developer(s) in coordination with QA decide whether it's required.
For small tickets introducing small changes QA assistance is most
probably not required.

(2) [Octant Areas & Test
Cases](https://docs.google.com/spreadsheets/d/1cRe6dxuKJV3a4ZskAwWEPvrFkQm6rEfyUCYwLTYw_Cc).
  • Loading branch information
jmikolajczyk authored Dec 5, 2024
2 parents fe7372f + 5679c98 commit 986243a
Show file tree
Hide file tree
Showing 15 changed files with 234 additions and 26 deletions.
5 changes: 1 addition & 4 deletions client/cypress/e2e/_08onboardingTOSAccepted.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,7 @@ Object.values(viewports).forEach(
cy.get('[data-test=ModalOnboarding]').should('be.visible');
cy.get('[data-test=ModalOnboarding__Button]').click();
cy.reload();
// For the unknown reason reloads sometimes cause app to disconnect in E2E env.
cy.disconnectMetamaskWalletFromAllDapps();
cy.reload();
connectWalletOnboarding();
cy.wait(1000);
cy.get('[data-test=ModalOnboarding]').should('be.visible');
});

Expand Down
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
191 changes: 191 additions & 0 deletions client/cypress/e2e/_13metrics.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
// 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', { scrollBehavior: false }, () => {
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',
{ scrollBehavior: false },
() => {
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=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 ',
{ scrollBehavior: false },
() => {
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=MetricsEpochHeader__NavigationArrows__leftArrow]').click();
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=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
Loading

0 comments on commit 986243a

Please sign in to comment.