diff --git a/client/cypress/e2e/layout.cy.ts b/client/cypress/e2e/layout.cy.ts deleted file mode 100644 index 9ea9954d24..0000000000 --- a/client/cypress/e2e/layout.cy.ts +++ /dev/null @@ -1,126 +0,0 @@ -import { navigateWithCheck, mockCoinPricesServer } from 'cypress/utils/e2e'; -import viewports from 'cypress/utils/viewports'; -import { IS_ONBOARDING_ALWAYS_VISIBLE, IS_ONBOARDING_DONE } from 'src/constants/localStorageKeys'; -import { navigationTabs } from 'src/constants/navigationTabs/navigationTabs'; -import { ROOT, ROOT_ROUTES } from 'src/routes/RootRoutes/routes'; - -Object.values(viewports).forEach(({ device, viewportWidth, viewportHeight }) => { - describe(`layout: ${device}`, { viewportHeight, viewportWidth }, () => { - before(() => { - cy.clearLocalStorage(); - cy.setupMetamask(); - }); - - beforeEach(() => { - mockCoinPricesServer(); - cy.disconnectMetamaskWalletFromAllDapps(); - localStorage.setItem(IS_ONBOARDING_ALWAYS_VISIBLE, 'false'); - localStorage.setItem(IS_ONBOARDING_DONE, 'true'); - cy.visit(ROOT.absolute); - }); - - it('renders top bar', () => { - cy.get('[data-test=MainLayout__Header]').should('be.visible'); - }); - - it('Clicking on Octant logo scrolls view to the top on logo click (projects view)', () => { - cy.scrollTo(0, 500); - cy.get('[data-test=MainLayout__Logo]').click(); - // waiting for scrolling to finish - cy.wait(2000); - cy.window().then(cyWindow => { - expect(cyWindow.scrollY).to.be.eq(0); - }); - }); - - it('Clicking on Octant logo redirects to projects view (outside projects view)', () => { - navigateWithCheck(ROOT_ROUTES.settings.absolute); - cy.get('[data-test=SettingsView]').should('be.visible'); - cy.get('[data-test=MainLayout__Logo]').click(); - cy.get('[data-test=ProjectsView]').should('be.visible'); - }); - - it('Clicking on Octant logo redirects to projects view (outside projects view) with memorized scrollY', () => { - cy.scrollTo(0, 500); - navigateWithCheck(ROOT_ROUTES.settings.absolute); - cy.get('[data-test=SettingsView]').should('be.visible'); - cy.get('[data-test=MainLayout__Logo]').click(); - cy.get('[data-test=ProjectsView]').should('be.visible'); - cy.window().then(cyWindow => { - expect(cyWindow.scrollY).to.be.eq(500); - }); - }); - - it('renders bottom navbar', () => { - cy.get('[data-test=Navbar]').should('be.visible'); - }); - - it('bottom navbar allows to change views', () => { - navigationTabs.forEach(({ to }) => { - navigateWithCheck(to); - }); - }); - - it('"Connect" button is visible when wallet is disconnected', () => { - cy.get('[data-test=MainLayout__Button--connect]').should('be.visible'); - cy.get('[data-test=MainLayout__Button--connect]').click(); - }); - - it('"Connect" button opens "ModalConnectWallet"', () => { - cy.get('[data-test=MainLayout__Button--connect]').click(); - cy.get('[data-test=ModalConnectWallet]').should('be.visible'); - }); - - it('"ModalConnectWallet" always shows "WalletConnect" option', () => { - cy.get('[data-test=MainLayout__Button--connect]').click(); - cy.get('[data-test=ModalConnectWallet]').within(() => { - cy.get('[data-test=ConnectWallet__BoxRounded--walletConnect]').should('be.visible'); - }); - }); - - it('"ModalConnectWallet" shows "Browser wallet" and "WalletConnect" options (MetaMask wallet detected)', () => { - cy.get('[data-test=MainLayout__Button--connect]').click(); - cy.get('[data-test=ModalConnectWallet]').within(() => { - cy.get('[data-test=ConnectWallet__BoxRounded--walletConnect]').should('be.visible'); - cy.get('[data-test=ConnectWallet__BoxRounded--browserWallet]').should('be.visible'); - }); - }); - - it('"ModalConnectWallet" has overflow enabled', () => { - cy.get('[data-test=MainLayout__Button--connect]').click(); - cy.get('[data-test=ModalConnectWallet__overflow]').should('exist'); - }); - - it('Clicking background when "ModalConnectWallet" is open, closes Modal', () => { - cy.get('[data-test=MainLayout__Button--connect]').click(); - cy.get('[data-test=ModalConnectWallet__overflow]').click({ force: true }); - cy.get('[data-test=ModalConnectWallet]').should('not.exist'); - }); - - it('"ModalConnectWallet" has "cross" icon button in header', () => { - cy.get('[data-test=MainLayout__Button--connect]').click(); - cy.get('[data-test=ModalConnectWallet__Button]').should('be.visible'); - }); - - it('Clicking on "X" mark in "ModalConnectWallet", closes Modal', () => { - cy.get('[data-test=MainLayout__Button--connect]').click(); - cy.get('[data-test=ModalConnectWallet__Button]').click(); - cy.get('[data-test=ModalConnectWallet]').should('not.exist'); - }); - - it('Clicking on "WalletConnect" option, opens Web3Modal', () => { - cy.get('[data-test=MainLayout__Button--connect]').click(); - cy.get('[data-test=ConnectWallet__BoxRounded--walletConnect]').click(); - cy.get('w3m-modal').find('#w3m-modal', { includeShadowDom: true }).should('be.visible'); - }); - - it('Clicking on "Browser wallet" option connects with MetaMask wallet', () => { - cy.get('[data-test=MainLayout__Button--connect]').click(); - cy.get('[data-test=ConnectWallet__BoxRounded--browserWallet]').click(); - cy.switchToMetamaskNotification(); - cy.acceptMetamaskAccess(); - cy.get('[data-test=MainLayout__Button--connect]').should('not.exist'); - cy.get('[data-test=ProfileInfo]').should('exist'); - }); - }); -}); diff --git a/client/cypress/e2e/metrics.cy.ts b/client/cypress/e2e/metrics.cy.ts deleted file mode 100644 index 829fbfbf1c..0000000000 --- a/client/cypress/e2e/metrics.cy.ts +++ /dev/null @@ -1,126 +0,0 @@ -import { mockCoinPricesServer, visitWithLoader } from 'cypress/utils/e2e'; -import viewports from 'cypress/utils/viewports'; -import { IS_ONBOARDING_ALWAYS_VISIBLE, IS_ONBOARDING_DONE } from 'src/constants/localStorageKeys'; -import { ROOT_ROUTES } from 'src/routes/RootRoutes/routes'; - -Object.values(viewports).forEach(({ device, viewportWidth, viewportHeight, isDesktop }) => { - describe(`metrics: ${device}`, { viewportHeight, viewportWidth }, () => { - before(() => { - /** - * Global Metamask setup done by Synpress is not always done. - * Since Synpress needs to have valid provider to fetch the data from contracts, - * setupMetamask is required in each test suite. - */ - cy.setupMetamask(); - }); - - beforeEach(() => { - mockCoinPricesServer(); - localStorage.setItem(IS_ONBOARDING_ALWAYS_VISIBLE, 'false'); - localStorage.setItem(IS_ONBOARDING_DONE, 'true'); - visitWithLoader(ROOT_ROUTES.metrics.absolute); - }); - - it('renders total projects tile', () => { - cy.get('[data-test=MetricsGeneralGridTotalProjects]').should('be.visible'); - }); - - it('renders total eth staked tile', () => { - cy.get('[data-test=MetricsGeneralGridTotalEthStaked]').should('be.visible'); - }); - - it('renders tile with total glm locked and % of 1B total supply groups', () => { - cy.get('[data-test=MetricsGeneralGridTotalGlmLockedAndTotalSupply]').should('be.visible'); - cy.get('[data-test=MetricsGeneralGridTotalGlmLockedAndTotalSupply]') - .children() - .should('have.length', 2); - }); - - it('renders wallet with glm locked graph tile', () => { - cy.get('[data-test=MetricsGeneralGridWalletsWithGlmLocked]').should('be.visible'); - }); - - it('renders cumulative glm locked graph tile', () => { - cy.get('[data-test=MetricsGeneralGridCumulativeGlmLocked]').should('be.visible'); - }); - - it('renders tiles in correct order', () => { - const metricsEpochGridTilesDataTest = [ - 'MetricsEpochGridTopProjects', - 'MetricsEpochGridTotalDonationsAndPersonal', - 'MetricsEpochGridDonationsVsPersonalAllocations', - 'MetricsEpochGridFundsUsage', - 'MetricsEpochGridTotalUsers', - 'MetricsEpochGridPatrons', - 'MetricsEpochGridCurrentDonors', - 'MetricsEpochGridAverageLeverage', - 'MetricsEpochGridRewardsUnusedAndUnallocatedValue', - 'MetricsEpochGridBelowThreshold', - ]; - - const metricsGeneralGridTilesDataTest = [ - 'MetricsGeneralGridTotalGlmLockedAndTotalSupply', - 'MetricsGeneralGridTotalProjects', - 'MetricsGeneralGridTotalEthStaked', - 'MetricsGeneralGridCumulativeGlmLocked', - 'MetricsGeneralGridWalletsWithGlmLocked', - ]; - - 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]); - } - - 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]); - } - }); - - it('renders grid with 4 columns on desktop or with 2 columns on other devices', () => { - cy.get('[data-test=MetricsEpoch__MetricsGrid]').then(el => { - const width = parseInt(el.css('width'), 10); - const rowGap = parseInt(el.css('rowGap'), 10); - - const columnWidth = isDesktop ? (width - 3 * rowGap) / 4 : (width - rowGap) / 2; - - cy.get('[data-test=MetricsEpoch__MetricsGrid]').should( - 'have.css', - 'grid-template-columns', - isDesktop - ? `${columnWidth}px ${columnWidth}px ${columnWidth}px ${columnWidth}px` - : `${columnWidth}px ${columnWidth}px`, - ); - }); - - cy.get('[data-test=MetricsGeneral__MetricsGrid]').then(el => { - const width = parseInt(el.css('width'), 10); - const rowGap = parseInt(el.css('rowGap'), 10); - - const columnWidth = isDesktop ? (width - 3 * rowGap) / 4 : (width - rowGap) / 2; - - cy.get('[data-test=MetricsGeneral__MetricsGrid]').should( - 'have.css', - 'grid-template-columns', - isDesktop - ? `${columnWidth}px ${columnWidth}px ${columnWidth}px ${columnWidth}px` - : `${columnWidth}px ${columnWidth}px`, - ); - }); - }); - }); -}); diff --git a/client/cypress/e2e/onboarding.cy.ts b/client/cypress/e2e/onboarding.cy.ts deleted file mode 100644 index e528f9e87f..0000000000 --- a/client/cypress/e2e/onboarding.cy.ts +++ /dev/null @@ -1,380 +0,0 @@ -import { visitWithLoader, navigateWithCheck, mockCoinPricesServer } from 'cypress/utils/e2e'; -import viewports from 'cypress/utils/viewports'; -import { stepsDecisionWindowClosed } from 'src/hooks/helpers/useOnboardingSteps/steps'; -import { ROOT, ROOT_ROUTES } from 'src/routes/RootRoutes/routes'; - -import Chainable = Cypress.Chainable; - -const connectWallet = ( - isTOSAccepted: boolean, - shouldVisit = true, - shouldReload = false, -): Chainable => { - cy.intercept('GET', '/user/*/tos', { body: { accepted: isTOSAccepted } }); - cy.disconnectMetamaskWalletFromAllDapps(); - if (shouldVisit) { - visitWithLoader(ROOT.absolute, ROOT_ROUTES.projects.absolute); - } - if (shouldReload) { - cy.reload(); - } - cy.get('[data-test=MainLayout__Button--connect]').click(); - cy.get('[data-test=ConnectWallet__BoxRounded--browserWallet]').click(); - cy.switchToMetamaskNotification(); - return cy.acceptMetamaskAccess(); -}; - -const beforeSetup = () => { - mockCoinPricesServer(); - cy.clearLocalStorage(); - cy.setupMetamask(); - window.innerWidth = Cypress.config().viewportWidth; - window.innerHeight = Cypress.config().viewportHeight; -}; - -const checkCurrentElement = (el: number, isCurrent: boolean): Chainable => { - return cy - .get('[data-test=ModalOnboarding__ProgressStepperSlim__element]') - .eq(el) - .invoke('attr', 'data-iscurrent') - .should('eq', `${isCurrent}`); -}; - -const checkProgressStepperSlimIsCurrentAndClickNext = (index, isCurrent = true): Chainable => { - checkCurrentElement(index - 1, isCurrent); - return cy - .get('[data-test=ModalOnboarding__ProgressStepperSlim__element]') - .eq(index) - .click({ force: true }); -}; - -const checkChangeStepsWithArrowKeys = (isTOSAccepted: boolean) => { - checkCurrentElement(0, true); - - [ - { el: 1, key: 'ArrowRight' }, - { el: 2, key: 'ArrowRight' }, - // { el: 3, key: 'ArrowRight' }, - // { el: 3, key: 'ArrowRight' }, - // { el: 2, key: 'ArrowLeft' }, - { el: 1, key: 'ArrowLeft' }, - { el: 0, key: 'ArrowLeft' }, - { el: 0, key: 'ArrowLeft' }, - ].forEach(({ key, el }) => { - cy.get('body').trigger('keydown', { key }); - checkCurrentElement(el, isTOSAccepted || el === 0); - - if (!isTOSAccepted) { - checkCurrentElement(0, true); - } - }); -}; - -const checkChangeStepsByClickingEdgeOfTheScreenUpTo25px = (isTOSAccepted: boolean) => { - checkCurrentElement(0, true); - - cy.get('[data-test=ModalOnboarding]').then(element => { - const leftEdgeX = element.offsetParent().offset()?.left as number; - const rightEdgeX = (leftEdgeX as number) + element.innerWidth()!; - - [ - { clientX: rightEdgeX - 25, el: 1 }, - { clientX: rightEdgeX - 10, el: 2 }, - // { clientX: rightEdgeX - 5, el: 3 }, - // rightEdgeX === browser right frame - // { clientX: rightEdgeX - 1, el: 3 }, - // { clientX: leftEdgeX + 25, el: 2 }, - { clientX: leftEdgeX + 10, el: 1 }, - { clientX: leftEdgeX + 5, el: 0 }, - { clientX: leftEdgeX, el: 0 }, - ].forEach(({ clientX, el }) => { - cy.get('[data-test=ModalOnboarding]').click(clientX, element.height()! / 2); - checkCurrentElement(el, isTOSAccepted || el === 0); - - if (!isTOSAccepted) { - checkCurrentElement(0, true); - } - }); - }); -}; - -const checkChangeStepsByClickingEdgeOfTheScreenMoreThan25px = (isTOSAccepted: boolean) => { - checkCurrentElement(0, true); - - cy.get('[data-test=ModalOnboarding]').then(element => { - const leftEdgeX = element.offsetParent().offset()?.left as number; - const rightEdgeX = (leftEdgeX as number) + element.innerWidth()!; - - [ - { clientX: rightEdgeX - 25, el: 1 }, - { clientX: rightEdgeX - 26, el: 1 }, - { clientX: leftEdgeX + 26, el: 1 }, - { clientX: leftEdgeX + 25, el: 0 }, - ].forEach(({ clientX, el }) => { - cy.get('[data-test=ModalOnboarding]').click(clientX, element.height()! / 2); - checkCurrentElement(el, isTOSAccepted || el === 0); - - if (!isTOSAccepted) { - checkCurrentElement(0, true); - } - }); - }); -}; - -const checkChangeStepsBySwipingOnScreenDifferenceMoreThanOrEqual5px = (isTOSAccepted: boolean) => { - checkCurrentElement(0, true); - - [ - { - el: 1, - touchMoveClientX: window.innerWidth / 2 - 5, - touchStartClientX: window.innerWidth / 2, - }, - { - el: 2, - touchMoveClientX: window.innerWidth / 2 - 5, - touchStartClientX: window.innerWidth / 2, - }, - { - el: 2, - touchMoveClientX: window.innerWidth / 2 - 5, - touchStartClientX: window.innerWidth / 2, - }, - // { - // el: 3, - // touchMoveClientX: window.innerWidth / 2 - 5, - // touchStartClientX: window.innerWidth / 2, - // }, - { - el: 2, - touchMoveClientX: window.innerWidth / 2 + 5, - touchStartClientX: window.innerWidth / 2, - }, - { - el: 1, - touchMoveClientX: window.innerWidth / 2 + 5, - touchStartClientX: window.innerWidth / 2, - }, - { - el: 0, - touchMoveClientX: window.innerWidth / 2 + 5, - touchStartClientX: window.innerWidth / 2, - }, - { - el: 0, - touchMoveClientX: window.innerWidth / 2 + 5, - touchStartClientX: window.innerWidth / 2, - }, - ].forEach(({ touchStartClientX, touchMoveClientX, el }) => { - cy.get('[data-test=ModalOnboarding]').trigger('touchstart', { - touches: [{ clientX: touchStartClientX }], - }); - cy.get('[data-test=ModalOnboarding]').trigger('touchmove', { - touches: [{ clientX: touchMoveClientX }], - }); - checkCurrentElement(el, isTOSAccepted || el === 0); - - if (!isTOSAccepted) { - checkCurrentElement(0, true); - } - }); -}; - -const checkChangeStepsBySwipingOnScreenDifferenceLessThanl5px = (isTOSAccepted: boolean) => { - checkCurrentElement(0, true); - - [ - { - el: 1, - touchMoveClientX: window.innerWidth / 2 - 5, - touchStartClientX: window.innerWidth / 2, - }, - { - el: 1, - touchMoveClientX: window.innerWidth / 2 - 4, - touchStartClientX: window.innerWidth / 2, - }, - { - el: 1, - touchMoveClientX: window.innerWidth / 2 + 4, - touchStartClientX: window.innerWidth / 2, - }, - { - el: 0, - touchMoveClientX: window.innerWidth / 2 + 5, - touchStartClientX: window.innerWidth / 2, - }, - ].forEach(({ touchStartClientX, touchMoveClientX, el }) => { - cy.get('[data-test=ModalOnboarding]').trigger('touchstart', { - touches: [{ clientX: touchStartClientX }], - }); - cy.get('[data-test=ModalOnboarding]').trigger('touchmove', { - touches: [{ clientX: touchMoveClientX }], - }); - checkCurrentElement(el, isTOSAccepted || el === 0); - - if (!isTOSAccepted) { - checkCurrentElement(0, true); - } - }); -}; - -Object.values(viewports).forEach(({ device, viewportWidth, viewportHeight }) => { - describe(`onboarding (TOS accepted): ${device}`, { viewportHeight, viewportWidth }, () => { - before(() => { - beforeSetup(); - }); - - beforeEach(() => { - connectWallet(true); - }); - - it('user is able to click through entire onboarding flow', () => { - for (let i = 1; i < stepsDecisionWindowClosed.length - 1; i++) { - checkProgressStepperSlimIsCurrentAndClickNext(i); - } - - cy.get('[data-test=ModalOnboarding__ProgressStepperSlim__element]') - .eq(stepsDecisionWindowClosed.length - 1) - .click(); - cy.get('[data-test=ModalOnboarding__Button]').click(); - cy.get('[data-test=ModalOnboarding]').should('not.exist'); - cy.get('[data-test=ProjectsView__ProjectsList]').should('be.visible'); - }); - - it('user is able to close the modal by clicking button in the top-right', () => { - cy.get('[data-test=ModalOnboarding]').should('be.visible'); - cy.get('[data-test=ModalOnboarding__Button]').click(); - cy.get('[data-test=ModalOnboarding]').should('not.exist'); - cy.get('[data-test=ProjectsView__ProjectsList]').should('be.visible'); - }); - - it('renders every time page is refreshed when "Always show Allocate onboarding" option is checked', () => { - cy.get('[data-test=ModalOnboarding__Button]').click(); - navigateWithCheck(ROOT_ROUTES.settings.absolute); - cy.get('[data-test=SettingsShowOnboardingBox__InputToggle]').check().should('be.checked'); - cy.reload(); - cy.get('[data-test=ModalOnboarding]').should('be.visible'); - }); - - it('renders only once when "Always show Allocate onboarding" option is not checked', () => { - cy.get('[data-test=ModalOnboarding__Button]').click(); - navigateWithCheck(ROOT_ROUTES.settings.absolute); - cy.get('[data-test=SettingsShowOnboardingBox__InputToggle]').should('not.be.checked'); - cy.reload(); - cy.get('[data-test=ModalOnboarding]').should('not.exist'); - }); - - it('user can change steps with arrow keys (left, right)', () => { - checkChangeStepsWithArrowKeys(true); - }); - - it('user can change steps by clicking the edge of the screen (up to 25px from each edge)', () => { - checkChangeStepsByClickingEdgeOfTheScreenUpTo25px(true); - }); - - it('user cannot change steps by clicking the edge of the screen (more than 25px from each edge)', () => { - checkChangeStepsByClickingEdgeOfTheScreenMoreThan25px(true); - }); - - it('user can change steps by swiping on screen (difference more than or equal 5px)', () => { - checkChangeStepsBySwipingOnScreenDifferenceMoreThanOrEqual5px(true); - }); - - it('user cannot change steps by swiping on screen (difference less than 5px)', () => { - checkChangeStepsBySwipingOnScreenDifferenceLessThanl5px(true); - }); - - it('user cannot change steps by swiping on screen (difference less than 5px)', () => { - checkChangeStepsBySwipingOnScreenDifferenceLessThanl5px(true); - }); - - it('user is able to close the onboarding, and after disconnecting & connecting, onboarding does not show up again', () => { - cy.get('[data-test=ModalOnboarding]').should('be.visible'); - cy.get('[data-test=ModalOnboarding__Button]').click(); - cy.get('[data-test=ModalOnboarding]').should('not.exist'); - connectWallet(true, false, true); - cy.get('[data-test=ModalOnboarding]').should('not.exist'); - }); - }); -}); - -Object.values(viewports).forEach(({ device, viewportWidth, viewportHeight }) => { - describe(`onboarding (TOS not accepted): ${device}`, { viewportHeight, viewportWidth }, () => { - before(() => { - beforeSetup(); - }); - - beforeEach(() => { - cy.intercept( - { - method: 'POST', - url: '/user/*/tos', - }, - { body: { accepted: true }, statusCode: 200 }, - ); - connectWallet(false); - }); - - it('onboarding TOS step should be first and active', () => { - checkCurrentElement(0, true); - cy.get('[data-test=ModalOnboardingTOS]').should('be.visible'); - }); - - it('user is not able to click through entire onboarding flow', () => { - for (let i = 1; i < stepsDecisionWindowClosed.length; i++) { - checkProgressStepperSlimIsCurrentAndClickNext(i, i === 1); - } - }); - - it('user is not able to close the modal by clicking button in the top-right', () => { - cy.get('[data-test=ModalOnboarding]').should('be.visible'); - cy.get('[data-test=ModalOnboarding__Button]').click({ force: true }); - cy.get('[data-test=ModalOnboarding]').should('be.visible'); - }); - - it('renders every time page is refreshed', () => { - cy.get('[data-test=ModalOnboarding]').should('be.visible'); - cy.reload(); - cy.get('[data-test=ModalOnboarding]').should('be.visible'); - }); - - it('user cannot change steps with arrow keys (left, right)', () => { - checkChangeStepsWithArrowKeys(false); - }); - - it('user can change steps by clicking the edge of the screen (up to 25px from each edge)', () => { - checkChangeStepsByClickingEdgeOfTheScreenUpTo25px(false); - }); - - it('user cannot change steps by clicking the edge of the screen (more than 25px from each edge)', () => { - checkChangeStepsByClickingEdgeOfTheScreenMoreThan25px(false); - }); - - it('user cannot change steps by swiping on screen (difference more than or equal 5px)', () => { - checkChangeStepsBySwipingOnScreenDifferenceMoreThanOrEqual5px(false); - }); - - it('user cannot change steps by swiping on screen (difference less than 5px)', () => { - checkChangeStepsBySwipingOnScreenDifferenceLessThanl5px(false); - }); - - it('TOS acceptance changes onboarding step to next step', () => { - checkCurrentElement(0, true); - cy.get('[data-test=TOS_InputCheckbox]').check(); - cy.switchToMetamaskNotification(); - cy.confirmMetamaskSignatureRequest(); - checkCurrentElement(1, true); - }); - - it('TOS acceptance allows the user to close the modal by clicking button in the top-right', () => { - checkCurrentElement(0, true); - cy.get('[data-test=TOS_InputCheckbox]').check(); - cy.switchToMetamaskNotification(); - cy.confirmMetamaskSignatureRequest(); - checkCurrentElement(1, true); - cy.get('[data-test=ModalOnboarding__Button]').click(); - cy.get('[data-test=ModalOnboarding]').should('not.exist'); - }); - }); -}); diff --git a/client/cypress/e2e/patronMode.cy.ts b/client/cypress/e2e/patronMode.cy.ts deleted file mode 100644 index b5f3455c47..0000000000 --- a/client/cypress/e2e/patronMode.cy.ts +++ /dev/null @@ -1,724 +0,0 @@ -import { connectWallet, mockCoinPricesServer, visitWithLoader } from 'cypress/utils/e2e'; -import viewports from 'cypress/utils/viewports'; -import { IS_ONBOARDING_ALWAYS_VISIBLE, IS_ONBOARDING_DONE } from 'src/constants/localStorageKeys'; -import { ROOT_ROUTES } from 'src/routes/RootRoutes/routes'; - -Object.values(viewports).forEach(({ device, viewportWidth, viewportHeight, isDesktop }) => { - describe(`patron mode (disabled): ${device}`, { viewportHeight, viewportWidth }, () => { - before(() => { - /** - * Global Metamask setup done by Synpress is not always done. - * Since Synpress needs to have valid provider to fetch the data from contracts, - * setupMetamask is required in each test suite. - */ - cy.setupMetamask(); - }); - - beforeEach(() => { - mockCoinPricesServer(); - localStorage.setItem(IS_ONBOARDING_ALWAYS_VISIBLE, 'false'); - localStorage.setItem(IS_ONBOARDING_DONE, 'true'); - visitWithLoader(ROOT_ROUTES.settings.absolute); - connectWallet(true, false); - }); - - it('patron badge should not exist ', () => { - cy.get('[data-test=ProfileInfo__badge]').should('not.exist'); - }); - - it('Patron mode toggle is not checked', () => { - cy.get('[data-test=SettingsPatronModeBox__InputToggle]').should('not.be.checked'); - }); - - if (isDesktop) { - it('Patron mode tooltip is visible on hover and has correct text', () => { - cy.get('[data-test=SettingsPatronModeBox__Tooltip]').trigger('mouseover'); - cy.get('[data-test=SettingsPatronModeBox__Tooltip__content]').should('be.visible'); - cy.get('[data-test=SettingsPatronModeBox__Tooltip__content]') - .invoke('text') - .should( - 'eq', - 'Patron mode is for token holders who want to support Octant. It disables allocation to yourself or projects. All rewards go directly to the matching fund with no action required by the patron.', - ); - }); - } - - it('Checking patron mode opens patron mode modal', () => { - cy.get('[data-test=SettingsPatronModeBox__InputToggle]').check(); - cy.get('[data-test=ModalPatronMode]').should('be.visible'); - }); - - it('Patron mode modal last paragraph has correct text', () => { - cy.get('[data-test=SettingsPatronModeBox__InputToggle]').check(); - cy.get('[data-test=SettingsPatronMode__fourthParagraph]') - .invoke('text') - .should('eq', 'Slide the switch below all the way to the right to enable patron mode.'); - }); - - it('Slider is visible', () => { - cy.get('[data-test=SettingsPatronModeBox__InputToggle]').check(); - cy.get('[data-test=PatronModeSlider]').should('be.visible'); - }); - - it('Slider has correct label', () => { - cy.get('[data-test=SettingsPatronModeBox__InputToggle]').check(); - cy.get('[data-test=PatronModeSlider__label]') - .invoke('text') - .should('eq', 'Slide right to confirm'); - }); - - it('Slider button is visible ', () => { - cy.get('[data-test=SettingsPatronModeBox__InputToggle]').check(); - cy.get('[data-test=PatronModeSlider__button]').should('be.visible'); - }); - - it('Slider button has right arrow inside', () => { - cy.get('[data-test=SettingsPatronModeBox__InputToggle]').check(); - cy.get('[data-test=PatronModeSlider__button__arrow]') - .should('be.visible') - .should('have.css', 'transform', 'none'); - }); - - it('Slider button is on the left side', () => { - cy.get('[data-test=SettingsPatronModeBox__InputToggle]').check(); - cy.get('[data-test=PatronModeSlider]').then(sliderEl => { - const sliderLeftDistance = sliderEl[0].getBoundingClientRect().left; - const sliderLeftPadding = parseInt(sliderEl.css('paddingLeft'), 10); - - cy.get('[data-test=PatronModeSlider__button]').then(sliderButtonEl => { - const sliderButtonLeftDistance = sliderButtonEl[0].getBoundingClientRect().left; - - expect(sliderButtonLeftDistance).to.be.eq(sliderLeftDistance + sliderLeftPadding); - }); - }); - }); - - it('Slider button returns to the starting point if user drops it below or equal 50% of slider width', () => { - cy.get('[data-test=SettingsPatronModeBox__InputToggle]').check(); - - cy.get('[data-test=PatronModeSlider]').then(sliderEl => { - const sliderDimensions = sliderEl[0].getBoundingClientRect(); - const sliderWidth = sliderDimensions.width; - const sliderLeftPadding = parseInt(sliderEl.css('paddingLeft'), 10); - const sliderRightPadding = parseInt(sliderEl.css('paddingRight'), 10); - - cy.get('[data-test=PatronModeSlider__button]').then(sliderButtonEl => { - const sliderButtonDimensions = sliderButtonEl[0].getBoundingClientRect(); - - const sliderButtonWidth = sliderButtonDimensions.width; - - const sliderTrackWidth = - sliderWidth - sliderLeftPadding - sliderRightPadding - sliderButtonWidth; - - const pointerDownPageX = sliderButtonDimensions.x; - const pointerMovePageX = sliderButtonDimensions.x + sliderTrackWidth / 2; - - cy.get('[data-test=PatronModeSlider__button]') - .trigger('pointerdown', { - pageX: pointerDownPageX, - }) - .trigger('pointermove', { - pageX: pointerMovePageX, - }) - .wait(1000) - .then(sliderButtonElAfterPointerMove => { - const sliderButtonDimensionsAfterPointerMove = - sliderButtonElAfterPointerMove[0].getBoundingClientRect(); - expect(sliderButtonDimensionsAfterPointerMove.x).eq(pointerMovePageX); - }) - .trigger('pointerup') - .wait(1000) - .then(sliderButtonElAfterPointerUp => { - const sliderButtonDimensionsAfterPointerUp = - sliderButtonElAfterPointerUp[0].getBoundingClientRect(); - expect(sliderButtonDimensionsAfterPointerUp.x).eq(pointerDownPageX); - }); - }); - }); - }); - - it('Slider elements change color while moving slider button', () => { - cy.get('[data-test=SettingsPatronModeBox__InputToggle]').check(); - - cy.get('[data-test=PatronModeSlider]').then(sliderEl => { - const sliderDimensions = sliderEl[0].getBoundingClientRect(); - const sliderWidth = sliderDimensions.width; - const sliderLeftPadding = parseInt(sliderEl.css('paddingLeft'), 10); - const sliderRightPadding = parseInt(sliderEl.css('paddingRight'), 10); - - cy.get('[data-test=PatronModeSlider__button]').then(sliderButtonEl => { - const sliderButtonDimensions = sliderButtonEl[0].getBoundingClientRect(); - - const sliderButtonWidth = sliderButtonDimensions.width; - - const sliderTrackWidth = - sliderWidth - sliderLeftPadding - sliderRightPadding - sliderButtonWidth; - - const slider0PercentagePageX = sliderButtonDimensions.x; - const slider25PercentagePageX = sliderButtonDimensions.x + sliderTrackWidth / 4; - const slider50PercentagePageX = sliderButtonDimensions.x + sliderTrackWidth / 2; - const slider75PercentagePageX = sliderButtonDimensions.x + 3 * (sliderTrackWidth / 4); - const slider100PercentagePageX = sliderButtonDimensions.x + sliderTrackWidth; - - // 0% - cy.get('[data-test=PatronModeSlider__button]').trigger('pointerdown', { - pageX: slider0PercentagePageX, - }); - cy.get('[data-test=PatronModeSlider]').should( - 'have.css', - 'background-color', - 'rgb(243, 243, 243)', - ); - cy.get('[data-test=PatronModeSlider__button]').should( - 'have.css', - 'background-color', - 'rgb(255, 255, 255)', - ); - cy.get('[data-test=PatronModeSlider__button__arrow__path]').should( - 'have.css', - 'fill', - 'rgb(23, 23, 23)', - ); - cy.get('[data-test=PatronModeSlider__label]') - .should('have.css', 'color', 'rgb(158, 163, 158)') - .should('have.css', 'opacity', '1'); - - // 25% - cy.get('[data-test=PatronModeSlider__button]').trigger('pointermove', { - pageX: slider25PercentagePageX, - }); - cy.get('[data-test=PatronModeSlider]').should( - 'have.css', - 'background-color', - 'rgba(212, 224, 221, 0.95)', - ); - cy.get('[data-test=PatronModeSlider__button]').should( - 'have.css', - 'background-color', - 'rgb(222, 234, 231)', - ); - cy.get('[data-test=PatronModeSlider__button__arrow__path]').should( - 'have.css', - 'fill', - 'rgb(129, 129, 129)', - ); - cy.get('[data-test=PatronModeSlider__label]') - .should('have.css', 'color', 'rgb(158, 163, 158)') - .should('have.css', 'opacity', '0.75'); - - // 50% - cy.get('[data-test=PatronModeSlider__button]').trigger('pointermove', { - pageX: slider50PercentagePageX, - }); - cy.get('[data-test=PatronModeSlider]').should( - 'have.css', - 'background-color', - 'rgba(175, 204, 197, 0.9)', - ); - cy.get('[data-test=PatronModeSlider__button]').should( - 'have.css', - 'background-color', - 'rgb(183, 211, 204)', - ); - cy.get('[data-test=PatronModeSlider__button__arrow__path]').should( - 'have.css', - 'fill', - 'rgb(181, 181, 181)', - ); - cy.get('[data-test=PatronModeSlider__label]') - .should('have.css', 'color', 'rgb(158, 163, 158)') - .should('have.css', 'opacity', '0.5'); - - // 75% - cy.get('[data-test=PatronModeSlider__button]').trigger('pointermove', { - pageX: slider75PercentagePageX, - }); - cy.get('[data-test=PatronModeSlider]').should( - 'have.css', - 'background-color', - 'rgba(128, 181, 169, 0.85)', - ); - cy.get('[data-test=PatronModeSlider__button]').should( - 'have.css', - 'background-color', - 'rgb(133, 185, 173)', - ); - cy.get('[data-test=PatronModeSlider__button__arrow__path]').should( - 'have.css', - 'fill', - 'rgb(221, 221, 221)', - ); - cy.get('[data-test=PatronModeSlider__label]') - .should('have.css', 'color', 'rgb(158, 163, 158)') - .should('have.css', 'opacity', '0.25'); - - // 100% - cy.get('[data-test=PatronModeSlider__button]').trigger('pointermove', { - pageX: slider100PercentagePageX, - }); - cy.get('[data-test=PatronModeSlider]').should( - 'have.css', - 'background-color', - 'rgba(45, 155, 135, 0.8)', - ); - cy.get('[data-test=PatronModeSlider__button]').should( - 'have.css', - 'background-color', - 'rgb(45, 155, 135)', - ); - cy.get('[data-test=PatronModeSlider__button__arrow__path]').should( - 'have.css', - 'fill', - 'rgb(255, 255, 255)', - ); - cy.get('[data-test=PatronModeSlider__label]') - .should('have.css', 'color', 'rgb(158, 163, 158)') - .should('have.css', 'opacity', '0'); - }); - }); - }); - - it('Slider button goes to the end of track if user drops it above 50% of slider width + animation after signature', () => { - cy.get('[data-test=SettingsPatronModeBox__InputToggle]').check(); - - cy.get('[data-test=PatronModeSlider]').then(sliderEl => { - const sliderDimensions = sliderEl[0].getBoundingClientRect(); - const sliderWidth = sliderDimensions.width; - const sliderLeftPadding = parseInt(sliderEl.css('paddingLeft'), 10); - const sliderRightPadding = parseInt(sliderEl.css('paddingRight'), 10); - - cy.get('[data-test=PatronModeSlider__button]').then(sliderButtonEl => { - const sliderButtonDimensions = sliderButtonEl[0].getBoundingClientRect(); - - const sliderButtonWidth = sliderButtonDimensions.width; - - const sliderTrackWidth = - sliderWidth - sliderLeftPadding - sliderRightPadding - sliderButtonWidth; - - const pointerDownPageX = sliderButtonDimensions.x; - const pointerMovePageX = sliderButtonDimensions.x + (sliderTrackWidth / 2 + 1); - const pointerUpPageX = sliderDimensions.right - sliderRightPadding - sliderButtonWidth; - - cy.get('[data-test=PatronModeSlider__button]') - .trigger('pointerdown', { - pageX: pointerDownPageX, - }) - .trigger('pointermove', { - pageX: pointerMovePageX, - }) - .wait(1000) - .then(sliderButtonElAfterPointerMove => { - const sliderButtonDimensionsAfterPointerMove = - sliderButtonElAfterPointerMove[0].getBoundingClientRect(); - expect(sliderButtonDimensionsAfterPointerMove.x).eq(pointerMovePageX); - }) - .trigger('pointerup') - .wait(1000) - .then(sliderButtonElAfterPointerUp => { - const sliderButtonDimensionsAfterPointerUp = - sliderButtonElAfterPointerUp[0].getBoundingClientRect(); - expect(sliderButtonDimensionsAfterPointerUp.x).eq(pointerUpPageX); - }); - - cy.confirmMetamaskSignatureRequest(); - cy.switchToCypressWindow(); - cy.get('[data-test=PatronModeSlider__button]').should('not.exist'); - cy.get('[data-test=PatronModeSlider__label]').should('not.exist'); - cy.get('[data-test=PatronModeSlider__status-label]') - .invoke('text') - .should('eq', 'Patron mode enabled'); - cy.wait(500); - cy.get('[data-test=ModalPatronMode]').should('not.exist'); - }); - }); - }); - }); - - describe(`patron mode (enabled): ${device}`, { viewportHeight, viewportWidth }, () => { - before(() => { - /** - * Global Metamask setup done by Synpress is not always done. - * Since Synpress needs to have valid provider to fetch the data from contracts, - * setupMetamask is required in each test suite. - */ - cy.setupMetamask(); - }); - - beforeEach(() => { - localStorage.setItem(IS_ONBOARDING_ALWAYS_VISIBLE, 'false'); - localStorage.setItem(IS_ONBOARDING_DONE, 'true'); - visitWithLoader(ROOT_ROUTES.settings.absolute); - connectWallet(true, true); - }); - - it('patron badge is visible and has correct label, background and text-transform prop', () => { - cy.get('[data-test=ProfileInfo__badge]').should('be.visible'); - cy.get('[data-test=ProfileInfo__badge]').invoke('text').should('eq', 'Patron'); - cy.get('[data-test=ProfileInfo__badge]') - .should('have.css', 'background-color', 'rgb(104, 91, 138)') - .should('have.css', 'text-transform', 'uppercase'); - }); - - it('Navbar has 4 items - projects, earn, metrics, settings', () => { - const navbarChildrenDataTest = [ - 'Navbar__Button--Projects', - 'Navbar__Button--Earn', - 'Navbar__Button--Metrics', - 'Navbar__Button--Settings', - ]; - - cy.get('[data-test=Navbar__buttons]') - .children() - .should('have.length', navbarChildrenDataTest.length); - - for (let i = 0; i < navbarChildrenDataTest.length; i++) { - cy.get('[data-test=Navbar__buttons]') - .children() - .eq(i) - .invoke('data', 'test') - .should('eq', navbarChildrenDataTest[i]); - } - }); - - it('route /allocate redirects to /projects', () => { - visitWithLoader(ROOT_ROUTES.allocation.absolute, ROOT_ROUTES.projects.absolute); - cy.get('[data-test=ProjectsView]').should('be.visible'); - }); - - it('BoxPersonalAllocation has correct title and sections labels', () => { - visitWithLoader(ROOT_ROUTES.earn.absolute); - cy.get('[data-test=BoxPersonalAllocation__title]') - .invoke('text') - .should('eq', 'Patron earnings'); - cy.get('[data-test=BoxPersonalAllocation__Section__label]') - .eq(0) - .invoke('text') - .should('eq', 'Current epoch'); - cy.get('[data-test=BoxPersonalAllocation__Section__label]') - .eq(1) - .invoke('text') - .should('eq', 'All time'); - }); - - it('Patron mode toggle is checked', () => { - cy.get('[data-test=SettingsPatronModeBox__InputToggle]').should('be.checked'); - }); - - if (isDesktop) { - it('Patron mode tooltip is visible on hover and has correct text', () => { - cy.get('[data-test=SettingsPatronModeBox__Tooltip]').trigger('mouseover'); - cy.get('[data-test=SettingsPatronModeBox__Tooltip__content]').should('be.visible'); - cy.get('[data-test=SettingsPatronModeBox__Tooltip__content]') - .invoke('text') - .should( - 'eq', - 'Patron mode is for token holders who want to support Octant. It disables allocation to yourself or projects. All rewards go directly to the matching fund with no action required by the patron.', - ); - }); - } - - it('Unchecking patron mode opens patron mode modal', () => { - cy.get('[data-test=SettingsPatronModeBox__InputToggle]').uncheck(); - cy.get('[data-test=ModalPatronMode]').should('be.visible'); - }); - - it('Patron mode modal last paragraph has correct text', () => { - cy.get('[data-test=SettingsPatronModeBox__InputToggle]').uncheck(); - cy.get('[data-test=SettingsPatronMode__fourthParagraph]') - .invoke('text') - .should('eq', 'Slide the switch below all the way to the left to disable patron mode.'); - }); - - it('Slider is visible', () => { - cy.get('[data-test=SettingsPatronModeBox__InputToggle]').uncheck(); - cy.get('[data-test=PatronModeSlider]').should('be.visible'); - }); - - it('Slider has correct label', () => { - cy.get('[data-test=SettingsPatronModeBox__InputToggle]').uncheck(); - cy.get('[data-test=PatronModeSlider__label]') - .invoke('text') - .should('eq', 'Slide left to confirm'); - }); - - it('Slider button is visible', () => { - cy.get('[data-test=SettingsPatronModeBox__InputToggle]').uncheck(); - cy.get('[data-test=PatronModeSlider__button]').should('be.visible'); - }); - - it('Slider button has left arrow inside', () => { - cy.get('[data-test=SettingsPatronModeBox__InputToggle]').uncheck(); - cy.get('[data-test=PatronModeSlider__button__arrow]') - .should('be.visible') - .should('have.css', 'transform', 'matrix(-1, 0, 0, -1, 0, 0)'); - }); - - it('Slider button is on the right side', () => { - cy.get('[data-test=SettingsPatronModeBox__InputToggle]').uncheck(); - cy.get('[data-test=PatronModeSlider]').then(sliderEl => { - const sliderRightDistance = sliderEl[0].getBoundingClientRect().right; - const sliderRightPadding = parseInt(sliderEl.css('paddingRight'), 10); - - cy.get('[data-test=PatronModeSlider__button]').then(sliderButtonEl => { - const sliderButtonRightDistance = sliderButtonEl[0].getBoundingClientRect().right; - - expect(sliderButtonRightDistance).to.be.eq(sliderRightDistance - sliderRightPadding); - }); - }); - }); - - it('Slider button returns to the starting point if user drops it below or equal 50% of slider width', () => { - cy.get('[data-test=SettingsPatronModeBox__InputToggle]').uncheck(); - - cy.get('[data-test=PatronModeSlider]').then(sliderEl => { - const sliderDimensions = sliderEl[0].getBoundingClientRect(); - const sliderWidth = sliderDimensions.width; - const sliderLeftPadding = parseInt(sliderEl.css('paddingLeft'), 10); - const sliderRightPadding = parseInt(sliderEl.css('paddingRight'), 10); - - cy.get('[data-test=PatronModeSlider__button]').then(sliderButtonEl => { - const sliderButtonDimensions = sliderButtonEl[0].getBoundingClientRect(); - - const sliderButtonWidth = sliderButtonDimensions.width; - - const sliderTrackWidth = - sliderWidth - sliderLeftPadding - sliderRightPadding - sliderButtonWidth; - - const pointerDownPageX = sliderButtonDimensions.right; - const pointerMovePageX = sliderButtonDimensions.right - sliderTrackWidth / 2; - - cy.get('[data-test=PatronModeSlider__button]') - .trigger('pointerdown', { - pageX: pointerDownPageX, - }) - .trigger('pointermove', { - pageX: pointerMovePageX, - }) - .wait(1000) - .then(sliderButtonElAfterPointerMove => { - const sliderButtonDimensionsAfterPointerMove = - sliderButtonElAfterPointerMove[0].getBoundingClientRect(); - expect(sliderButtonDimensionsAfterPointerMove.right).eq(pointerMovePageX); - }) - .trigger('pointerup') - .wait(1000) - .then(sliderButtonElAfterPointerUp => { - const sliderButtonDimensionsAfterPointerUp = - sliderButtonElAfterPointerUp[0].getBoundingClientRect(); - expect(sliderButtonDimensionsAfterPointerUp.right).eq(pointerDownPageX); - }); - }); - }); - }); - - it('Slider elements change color while moving slider button', () => { - cy.get('[data-test=SettingsPatronModeBox__InputToggle]').uncheck(); - - cy.get('[data-test=PatronModeSlider]').then(sliderEl => { - const sliderDimensions = sliderEl[0].getBoundingClientRect(); - const sliderWidth = sliderDimensions.width; - const sliderLeftPadding = parseInt(sliderEl.css('paddingLeft'), 10); - const sliderRightPadding = parseInt(sliderEl.css('paddingRight'), 10); - - cy.get('[data-test=PatronModeSlider__button]').then(sliderButtonEl => { - const sliderButtonDimensions = sliderButtonEl[0].getBoundingClientRect(); - - const sliderButtonWidth = sliderButtonDimensions.width; - - const sliderTrackWidth = - sliderWidth - sliderLeftPadding - sliderRightPadding - sliderButtonWidth; - - const slider0PercentagePageX = sliderButtonDimensions.right; - const slider25PercentagePageX = sliderButtonDimensions.right - sliderTrackWidth / 4; - const slider50PercentagePageX = sliderButtonDimensions.right - sliderTrackWidth / 2; - const slider75PercentagePageX = sliderButtonDimensions.right - 3 * (sliderTrackWidth / 4); - const slider100PercentagePageX = sliderButtonDimensions.right - sliderTrackWidth; - - // 0% - cy.get('[data-test=PatronModeSlider__button]').trigger('pointerdown', { - pageX: slider0PercentagePageX, - }); - cy.get('[data-test=PatronModeSlider]').should( - 'have.css', - 'background-color', - 'rgb(243, 243, 243)', - ); - cy.get('[data-test=PatronModeSlider__button]').should( - 'have.css', - 'background-color', - 'rgb(255, 255, 255)', - ); - cy.get('[data-test=PatronModeSlider__button__arrow__path]').should( - 'have.css', - 'fill', - 'rgb(23, 23, 23)', - ); - cy.get('[data-test=PatronModeSlider__label]') - .should('have.css', 'color', 'rgb(158, 163, 158)') - .should('have.css', 'opacity', '1'); - - // 25% - cy.get('[data-test=PatronModeSlider__button]').trigger('pointermove', { - pageX: slider25PercentagePageX, - }); - cy.get('[data-test=PatronModeSlider]').should( - 'have.css', - 'background-color', - 'rgba(212, 224, 221, 0.95)', - ); - cy.get('[data-test=PatronModeSlider__button]').should( - 'have.css', - 'background-color', - 'rgb(222, 234, 231)', - ); - cy.get('[data-test=PatronModeSlider__button__arrow__path]').should( - 'have.css', - 'fill', - 'rgb(129, 129, 129)', - ); - cy.get('[data-test=PatronModeSlider__label]') - .should('have.css', 'color', 'rgb(158, 163, 158)') - .should('have.css', 'opacity', '0.75'); - - // 50% - cy.get('[data-test=PatronModeSlider__button]').trigger('pointermove', { - pageX: slider50PercentagePageX, - waitForAnimations: true, - }); - cy.get('[data-test=PatronModeSlider]').should( - 'have.css', - 'background-color', - 'rgba(175, 204, 197, 0.9)', - ); - cy.get('[data-test=PatronModeSlider__button]').should( - 'have.css', - 'background-color', - 'rgb(183, 211, 204)', - ); - cy.get('[data-test=PatronModeSlider__button__arrow__path]').should( - 'have.css', - 'fill', - 'rgb(181, 181, 181)', - ); - cy.get('[data-test=PatronModeSlider__label]') - .should('have.css', 'color', 'rgb(158, 163, 158)') - .should('have.css', 'opacity', '0.5'); - - // 75% - cy.get('[data-test=PatronModeSlider__button]').trigger('pointermove', { - pageX: slider75PercentagePageX, - waitForAnimations: true, - }); - cy.get('[data-test=PatronModeSlider]').should( - 'have.css', - 'background-color', - 'rgba(128, 181, 169, 0.85)', - ); - cy.get('[data-test=PatronModeSlider__button]').should( - 'have.css', - 'background-color', - 'rgb(133, 185, 173)', - ); - cy.get('[data-test=PatronModeSlider__button__arrow__path]').should( - 'have.css', - 'fill', - 'rgb(221, 221, 221)', - ); - cy.get('[data-test=PatronModeSlider__label]') - .should('have.css', 'color', 'rgb(158, 163, 158)') - .should('have.css', 'opacity', '0.25'); - - // 100% - cy.get('[data-test=PatronModeSlider__button]').trigger('pointermove', { - pageX: slider100PercentagePageX, - }); - cy.get('[data-test=PatronModeSlider]').should( - 'have.css', - 'background-color', - 'rgba(45, 155, 135, 0.8)', - ); - cy.get('[data-test=PatronModeSlider__button]').should( - 'have.css', - 'background-color', - 'rgb(45, 155, 135)', - ); - cy.get('[data-test=PatronModeSlider__button__arrow__path]').should( - 'have.css', - 'fill', - 'rgb(255, 255, 255)', - ); - cy.get('[data-test=PatronModeSlider__label]') - .should('have.css', 'color', 'rgb(158, 163, 158)') - .should('have.css', 'opacity', '0'); - }); - }); - }); - - it('Slider button goes to the end of track if user drops it above 50% of slider width + animation after signature', () => { - cy.get('[data-test=SettingsPatronModeBox__InputToggle]').uncheck(); - - cy.get('[data-test=PatronModeSlider]').then(sliderEl => { - const sliderDimensions = sliderEl[0].getBoundingClientRect(); - const sliderWidth = sliderDimensions.width; - const sliderLeftPadding = parseInt(sliderEl.css('paddingLeft'), 10); - const sliderRightPadding = parseInt(sliderEl.css('paddingRight'), 10); - - cy.get('[data-test=PatronModeSlider__button]').then(sliderButtonEl => { - const sliderButtonDimensions = sliderButtonEl[0].getBoundingClientRect(); - - const sliderButtonWidth = sliderButtonDimensions.width; - - const sliderTrackWidth = - sliderWidth - sliderLeftPadding - sliderRightPadding - sliderButtonWidth; - - const pointerDownPageX = sliderButtonDimensions.right; - const pointerMovePageX = sliderButtonDimensions.right - (sliderTrackWidth / 2 + 1); - const pointerUpPageX = sliderDimensions.left + sliderLeftPadding; - - cy.get('[data-test=PatronModeSlider__button]') - .trigger('pointerdown', { - pageX: pointerDownPageX, - }) - .trigger('pointermove', { - pageX: pointerMovePageX, - }) - .wait(1000) - .then(sliderButtonElAfterPointerMove => { - const sliderButtonDimensionsAfterPointerMove = - sliderButtonElAfterPointerMove[0].getBoundingClientRect(); - expect(sliderButtonDimensionsAfterPointerMove.right).eq(pointerMovePageX); - }) - .trigger('pointerup') - .wait(1000) - .then(sliderButtonElAfterPointerUp => { - const sliderButtonDimensionsAfterPointerUp = - sliderButtonElAfterPointerUp[0].getBoundingClientRect(); - expect(sliderButtonDimensionsAfterPointerUp.x).eq(pointerUpPageX); - }); - - cy.confirmMetamaskSignatureRequest(); - cy.switchToCypressWindow(); - cy.get('[data-test=PatronModeSlider__button]').should('not.exist'); - cy.get('[data-test=PatronModeSlider__label]').should('not.exist'); - cy.get('[data-test=PatronModeSlider__status-label]') - .invoke('text') - .should('eq', 'Patron mode disabled'); - cy.wait(500); - cy.get('[data-test=ModalPatronMode]').should('not.exist'); - }); - }); - }); - - it('when entering project view, button icon changes to chevronLeft', () => { - visitWithLoader(ROOT_ROUTES.projects.absolute); - cy.get('[data-test^=ProjectsView__ProjectsListItem').first().click(); - cy.get('[data-test=Navbar__Button--Projects]') - .find('svg') - // HTML tag can't be self-closing in CY. - .should( - 'have.html', - '', - ); - }); - }); -}); diff --git a/client/cypress/e2e/project.cy.ts b/client/cypress/e2e/project.cy.ts deleted file mode 100644 index e811fb70aa..0000000000 --- a/client/cypress/e2e/project.cy.ts +++ /dev/null @@ -1,181 +0,0 @@ -import { connectWallet, mockCoinPricesServer, visitWithLoader } from 'cypress/utils/e2e'; -import { getNamesOfProjects } from 'cypress/utils/projects'; -import viewports from 'cypress/utils/viewports'; -import { IS_ONBOARDING_DONE } from 'src/constants/localStorageKeys'; -import { ROOT_ROUTES } from 'src/routes/RootRoutes/routes'; - -import Chainable = Cypress.Chainable; - -const getButtonAddToAllocate = (): Chainable => { - const projectListItemFirst = cy.get('[data-test=ProjectListItem').first(); - - return projectListItemFirst.find('[data-test=ProjectListItemHeader__ButtonAddToAllocate]'); -}; - -const checkProjectItemElements = (): Chainable => { - cy.get('[data-test^=ProjectsView__ProjectsListItem').first().click(); - const projectListItemFirst = cy.get('[data-test=ProjectListItem').first(); - projectListItemFirst.get('[data-test=ProjectListItemHeader__Img]').should('be.visible'); - projectListItemFirst.get('[data-test=ProjectListItemHeader__name]').should('be.visible'); - getButtonAddToAllocate().should('be.visible'); - projectListItemFirst.get('[data-test=ProjectListItemHeader__Button]').should('be.visible'); - projectListItemFirst.get('[data-test=ProjectListItem__Description]').should('be.visible'); - - cy.get('[data-test=ProjectListItem__Donors]') - .first() - .scrollIntoView({ offset: { left: 0, top: 100 } }); - - cy.get('[data-test=ProjectListItem__Donors]').first().should('be.visible'); - cy.get('[data-test=ProjectListItem__Donors__DonorsHeader__count]') - .first() - .should('be.visible') - .should('have.text', '0'); - return cy.get('[data-test=ProjectListItem__Donors__noDonationsYet]').first().should('be.visible'); -}; - -Object.values(viewports).forEach(({ device, viewportWidth, viewportHeight }) => { - describe(`project: ${device}`, { viewportHeight, viewportWidth }, () => { - let projectNames: string[] = []; - - beforeEach(() => { - mockCoinPricesServer(); - localStorage.setItem(IS_ONBOARDING_DONE, 'true'); - visitWithLoader(ROOT_ROUTES.projects.absolute); - cy.get('[data-test^=ProjectItemSkeleton').should('not.exist'); - - /** - * This could be done in before hook, but CY wipes the state after each test - * (could be disabled, but creates other problems) - */ - if (projectNames.length === 0) { - projectNames = getNamesOfProjects(); - } - }); - - it('entering project view directly renders content', () => { - cy.get('[data-test^=ProjectsView__ProjectsListItem').first().click(); - cy.reload(); - const projectListItemFirst = cy.get('[data-test=ProjectListItem').first(); - projectListItemFirst.get('[data-test=ProjectListItemHeader__Img]').should('be.visible'); - projectListItemFirst.get('[data-test=ProjectListItemHeader__name]').should('be.visible'); - }); - - it('entering project view renders all its elements', () => { - checkProjectItemElements(); - }); - - it('entering project view renders all its elements with fallback IPFS provider', () => { - cy.intercept('GET', '**/ipfs/**', req => { - if (req.url.includes('infura')) { - req.destroy(); - } - }); - - checkProjectItemElements(); - }); - - it('entering project view shows Toast with info about IPFS failure when all providers fail', () => { - cy.intercept('GET', '**/ipfs/**', req => { - req.destroy(); - }); - - cy.get('[data-test=Toast--ipfsMessage').should('be.visible'); - }); - - it('entering project view allows to add it to allocation and remove, triggering change of the icon, change of the number in navbar', () => { - cy.get('[data-test^=ProjectsView__ProjectsListItem').first().click(); - - getButtonAddToAllocate().click(); - - // cy.get('@buttonAddToAllocate').click(); - cy.get('[data-test=Navbar__numberOfAllocations]').contains(1); - getButtonAddToAllocate().click(); - cy.get('[data-test=Navbar__numberOfAllocations]').should('not.exist'); - }); - - it('Entering project view allows scroll only to the last project', () => { - cy.get('[data-test^=ProjectsView__ProjectsListItem]').first().click(); - - for (let i = 0; i < projectNames.length; i++) { - cy.get('[data-test=ProjectListItem]').should( - 'have.length.greaterThan', - i === projectNames.length - 1 ? projectNames.length - 1 : i, - ); - cy.get('[data-test=ProjectListItemHeader__name]') - .eq(i) - .scrollIntoView({ offset: { left: 0, top: -150 } }) - .contains(projectNames[i]); - cy.get('[data-test=ProjectListItem__Donors]') - .eq(i) - .scrollIntoView({ offset: { left: 0, top: -150 } }) - .should('be.visible'); - } - }); - - it('"Back to top" button is displayed if the user has scrolled past the start of the final project description', () => { - cy.get('[data-test^=ProjectsView__ProjectsListItem]').first().click(); - - for (let i = 0; i < projectNames.length - 1; i++) { - cy.get('[data-test=ProjectListItem__Donors]') - .eq(i) - .scrollIntoView({ offset: { left: 0, top: 100 } }); - - if (i === projectNames.length - 1) { - cy.get('[data-test=ProjectBackToTopButton__Button]').should('be.visible'); - } - } - }); - - it('Clicking on "Back to top" button scrolls to the top of view (first project is visible)', () => { - cy.get('[data-test^=ProjectsView__ProjectsListItem]').first().click(); - - for (let i = 0; i < projectNames.length - 1; i++) { - cy.get('[data-test=ProjectListItem__Donors]') - .eq(i) - .scrollIntoView({ offset: { left: 0, top: 100 } }); - - if (i === projectNames.length - 1) { - cy.get('[data-test=ProjectBackToTopButton__Button]').click(); - cy.get('[data-test=ProjectListItem]').eq(0).should('be.visible'); - } - } - }); - }); - - describe(`project (patron mode): ${device}`, { viewportHeight, viewportWidth }, () => { - let projectNames: string[] = []; - - before(() => { - /** - * Global Metamask setup done by Synpress is not always done. - * Since Synpress needs to have valid provider to fetch the data from contracts, - * setupMetamask is required in each test suite. - */ - cy.setupMetamask(); - }); - - beforeEach(() => { - mockCoinPricesServer(); - localStorage.setItem(IS_ONBOARDING_DONE, 'true'); - visitWithLoader(ROOT_ROUTES.projects.absolute); - connectWallet(true, true); - cy.get('[data-test^=ProjectItemSkeleton').should('not.exist'); - - /** - * This could be done in before hook, but CY wipes the state after each test - * (could be disabled, but creates other problems) - */ - if (projectNames.length === 0) { - projectNames = getNamesOfProjects(); - } - }); - - it('button "add to allocate" is disabled', () => { - for (let i = 0; i < projectNames.length; i++) { - cy.get('[data-test^=ProjectsView__ProjectsListItem]').eq(i).click(); - getButtonAddToAllocate().should('be.visible').should('be.disabled'); - cy.go('back'); - } - }); - }); -}); diff --git a/client/cypress/e2e/projects.cy.ts b/client/cypress/e2e/projects.cy.ts deleted file mode 100644 index b19b864cb4..0000000000 --- a/client/cypress/e2e/projects.cy.ts +++ /dev/null @@ -1,239 +0,0 @@ -// eslint-disable-next-line import/no-extraneous-dependencies -import chaiColors from 'chai-colors'; - -import { connectWallet, mockCoinPricesServer, visitWithLoader } from 'cypress/utils/e2e'; -import { getNamesOfProjects } from 'cypress/utils/projects'; -import viewports from 'cypress/utils/viewports'; -import { IS_ONBOARDING_DONE } from 'src/constants/localStorageKeys'; -import getMilestones from 'src/constants/milestones'; -import { ROOT_ROUTES } from 'src/routes/RootRoutes/routes'; - -import Chainable = Cypress.Chainable; - -chai.use(chaiColors); - -function checkProjectItemElements(index, name, isPatronMode = false): Chainable { - cy.get('[data-test^=ProjectsView__ProjectsListItem') - .eq(index) - .find('[data-test=ProjectsListItem__imageProfile]') - .should('be.visible'); - cy.get('[data-test^=ProjectsView__ProjectsListItem]') - .eq(index) - .should('be.visible') - .get('[data-test=ProjectsListItem__name]') - .should('be.visible') - .contains(name); - cy.get('[data-test^=ProjectsView__ProjectsListItem') - .eq(index) - .find('[data-test=ProjectsListItem__IntroDescription]') - .should('be.visible'); - cy.get('[data-test^=ProjectsView__ProjectsListItem') - .eq(index) - .find('[data-test=ProjectsListItem__ButtonAddToAllocate]') - .should('be.visible'); - - if (isPatronMode) { - cy.get('[data-test^=ProjectsView__ProjectsListItem') - .eq(index) - .find('[data-test=ProjectsListItem__ButtonAddToAllocate]') - .should('be.disabled'); - } - - return cy - .get('[data-test^=ProjectsView__ProjectsListItem') - .eq(index) - .find('[data-test=ProjectRewards]') - .should('be.visible'); - // TODO OCT-663 Make CY check if rewards are available (Epoch 2, decision window open). - // return cy - // .get('[data-test^=ProjectsView__ProjectsListItem') - // .eq(index) - // .find('[data-test=ProjectRewards__currentTotal__label]') - // .should('be.visible'); -} - -function addProjectToAllocate(index, numberOfAddedProjects): Chainable { - cy.get('[data-test^=ProjectsView__ProjectsListItem') - .eq(index) - .find('[data-test=ProjectsListItem__imageProfile]') - .should('be.visible'); - cy.get('[data-test^=ProjectsView__ProjectsListItem') - .eq(index) - .find('[data-test=ProjectsListItem__IntroDescription]') - .should('be.visible'); - cy.get('[data-test^=ProjectsView__ProjectsListItem') - .eq(index) - .find('[data-test=ProjectsListItem__ButtonAddToAllocate]') - .scrollIntoView(); - cy.get('[data-test^=ProjectsView__ProjectsListItem') - .eq(index) - .find('[data-test=ProjectsListItem__ButtonAddToAllocate]') - .click(); - cy.get('[data-test^=ProjectsView__ProjectsListItem') - .eq(index) - .find('[data-test=ProjectsListItem__ButtonAddToAllocate]') - .find('svg') - .find('path') - .then($el => $el.css('fill')) - .should('be.colored', '#FF6157'); - cy.get('[data-test^=ProjectsView__ProjectsListItem') - .eq(index) - .find('[data-test=ProjectsListItem__ButtonAddToAllocate]') - .find('svg') - .find('path') - .then($el => $el.css('stroke')) - .should('be.colored', '#FF6157'); - cy.get('[data-test=Navbar__numberOfAllocations]').contains(numberOfAddedProjects + 1); - visitWithLoader(ROOT_ROUTES.allocation.absolute); - cy.get('[data-test=AllocationItem]').should('have.length', numberOfAddedProjects + 1); - return cy.go('back'); -} - -function removeProjectFromAllocate(numberOfProjects, numberOfAddedProjects, index): Chainable { - cy.get('[data-test^=ProjectsView__ProjectsListItem') - .eq(index) - .find('[data-test=ProjectsListItem__ButtonAddToAllocate]') - .scrollIntoView(); - cy.get('[data-test^=ProjectsView__ProjectsListItem') - .eq(index) - .find('[data-test=ProjectsListItem__ButtonAddToAllocate]') - .click(); - visitWithLoader(ROOT_ROUTES.allocation.absolute); - cy.get('[data-test=AllocationItem]').should('have.length', numberOfAddedProjects - 1); - if (index < numberOfProjects - 1) { - cy.get('[data-test=Navbar__numberOfAllocations]').contains(numberOfAddedProjects - 1); - } else { - cy.get('[data-test=Navbar__numberOfAllocations]').should('not.exist'); - } - return cy.go('back'); -} - -Object.values(viewports).forEach(({ device, viewportWidth, viewportHeight }) => { - describe(`projects: ${device}`, { viewportHeight, viewportWidth }, () => { - let projectNames: string[] = []; - - beforeEach(() => { - mockCoinPricesServer(); - localStorage.setItem(IS_ONBOARDING_DONE, 'true'); - visitWithLoader(ROOT_ROUTES.projects.absolute); - cy.get('[data-test^=ProjectItemSkeleton').should('not.exist'); - - /** - * This could be done in before hook, but CY wipes the state after each test - * (could be disabled, but creates other problems) - */ - if (projectNames.length === 0) { - projectNames = getNamesOfProjects(); - } - }); - - it('user is able to see all the projects in the view', () => { - for (let i = 0; i < projectNames.length; i++) { - cy.get('[data-test^=ProjectsView__ProjectsListItem]').eq(i).scrollIntoView(); - checkProjectItemElements(i, projectNames[i]); - } - }); - - it('user is able to add & remove the first and the last project to/from allocation, triggering change of the icon, change of the number in navbar', () => { - // This test checks the first and the last elements only to save time. - cy.get('[data-test=Navbar__numberOfAllocations]').should('not.exist'); - - addProjectToAllocate(0, 0); - addProjectToAllocate(projectNames.length - 1, 1); - removeProjectFromAllocate(projectNames.length, 2, 0); - removeProjectFromAllocate(projectNames.length, 1, projectNames.length - 1); - }); - - it('user is able to add project to allocation in ProjectsView and remove it from allocation in AllocationView', () => { - cy.get('[data-test=Navbar__numberOfAllocations]').should('not.exist'); - addProjectToAllocate(0, 0); - visitWithLoader(ROOT_ROUTES.allocation.absolute); - cy.get('[data-test=AllocationItemSkeleton]').should('not.exist'); - cy.get('[data-test=AllocationItem]').then(el => { - const { x } = el[0].getBoundingClientRect(); - cy.get('[data-test=AllocationItem]') - .trigger('pointerdown') - .trigger('pointermove', { pageX: x - 20 }) - .trigger('pointerup'); - cy.get('[data-test=AllocationItem__removeButton]').should('be.visible'); - cy.get('[data-test=AllocationItem__removeButton]').click(); - cy.get('[data-test=AllocationItem__removeButton]').should('not.exist'); - cy.get('[data-test=AllocationItem]').should('not.exist'); - cy.get('[data-test=Navbar__numberOfAllocations]').should('not.exist'); - }); - - it('ProjectsTimelineWidgetItem with href opens link when clicked without mouse movement', () => { - const milestones = getMilestones(); - cy.get('[data-test=ProjectsTimelineWidget]').should('be.visible'); - cy.get('[data-test=ProjectsTimelineWidgetItem]').should('have.length', milestones.length); - for (let i = 0; i < milestones.length; i++) { - if (milestones[i].href) { - cy.get('[data-test=ProjectsTimelineWidgetItem]') - .eq(i) - .within(() => { - cy.get('[data-test=ProjectsTimelineWidgetItem__Svg--arrowTopRight]').should( - 'be.visible', - ); - }); - - cy.get('[data-test=ProjectsTimelineWidgetItem]') - .eq(i) - .then(el => { - const { x } = el[0].getBoundingClientRect(); - cy.get('[data-test=ProjectsTimelineWidgetItem]') - .eq(i) - .trigger('mousedown') - .trigger('mouseup', { clientX: x + 10 }); - cy.location('pathname').should('eq', ROOT_ROUTES.projects.absolute); - - cy.get('[data-test=ProjectsTimelineWidgetItem]') - .eq(i) - .trigger('mousedown') - .trigger('mouseup'); - cy.location('pathname').should('not.eq', ROOT_ROUTES.projects.absolute); - }); - } - } - }); - }); - }); - - describe(`projects (patron mode): ${device}`, { viewportHeight, viewportWidth }, () => { - let projectNames: string[] = []; - - before(() => { - /** - * Global Metamask setup done by Synpress is not always done. - * Since Synpress needs to have valid provider to fetch the data from contracts, - * setupMetamask is required in each test suite. - */ - cy.setupMetamask(); - }); - - beforeEach(() => { - mockCoinPricesServer(); - localStorage.setItem(IS_ONBOARDING_DONE, 'true'); - visitWithLoader(ROOT_ROUTES.projects.absolute); - connectWallet(true, true); - cy.get('[data-test^=ProjectItemSkeleton').should('not.exist'); - /** - * This could be done in before hook, but CY wipes the state after each test - * (could be disabled, but creates other problems) - */ - if (projectNames.length === 0) { - projectNames = getNamesOfProjects(); - } - }); - - after(() => { - cy.disconnectMetamaskWalletFromAllDapps(); - }); - - it('button "add to allocate" is disabled', () => { - for (let i = 0; i < projectNames.length; i++) { - cy.get('[data-test^=ProjectsView__ProjectsListItem]').eq(i).scrollIntoView(); - checkProjectItemElements(i, projectNames[i], true); - } - }); - }); -}); diff --git a/client/cypress/e2e/projectsArchive.cy.ts b/client/cypress/e2e/projectsArchive.cy.ts deleted file mode 100644 index d2abe9b5d0..0000000000 --- a/client/cypress/e2e/projectsArchive.cy.ts +++ /dev/null @@ -1,103 +0,0 @@ -import { checkLocationWithLoader, visitWithLoader } from 'cypress/utils/e2e'; -import viewports from 'cypress/utils/viewports'; -import { QUERY_KEYS } from 'src/api/queryKeys'; -import { IS_ONBOARDING_ALWAYS_VISIBLE, IS_ONBOARDING_DONE } from 'src/constants/localStorageKeys'; -import { ROOT_ROUTES } from 'src/routes/RootRoutes/routes'; - -let wasEpochMoved = false; - -Object.values(viewports).forEach(({ device, viewportWidth, viewportHeight }) => { - describe(`projects archive: ${device}`, { viewportHeight, viewportWidth }, () => { - beforeEach(() => { - localStorage.setItem(IS_ONBOARDING_ALWAYS_VISIBLE, 'false'); - localStorage.setItem(IS_ONBOARDING_DONE, 'true'); - visitWithLoader(ROOT_ROUTES.projects.absolute); - }); - - it('moves to the next epoch', () => { - // Move time only once, for the first device. - if (!wasEpochMoved) { - cy.window().then(async win => { - const currentEpochBefore = Number( - win.clientReactQuery.getQueryData(QUERY_KEYS.currentEpoch), - ); - await win.mutateAsyncMoveEpoch(); - const currentEpochAfter = Number( - win.clientReactQuery.getQueryData(QUERY_KEYS.currentEpoch), - ); - wasEpochMoved = true; - expect(currentEpochBefore + 1).to.eq(currentEpochAfter); - }); - } else { - expect(true).to.be.true; - } - }); - - it('renders archive elements + clicking on epoch archive ProjectsListItem opens ProjectView for particular epoch and project', () => { - cy.get('[data-test=MainLayout__body]').then(el => { - const mainLayoutPaddingTop = parseInt(el.css('paddingTop'), 10); - - cy.get('[data-test=ProjectsView__ProjectsList]') - .should('be.visible') - .children() - .then(children => { - children[children.length - 1].scrollIntoView(); - cy.window().then(window => window.scrollTo(0, window.scrollY - mainLayoutPaddingTop)); - cy.wait(1000); - // header test - cy.get('[data-test=ProjectsView__ProjectsList__header--archive]').should('be.visible'); - - // list test - cy.get('[data-test=ProjectsView__ProjectsList--archive]').first().should('be.visible'); - cy.get('[data-test=ProjectsView__ProjectsList--archive]') - .first() - .children() - .then(childrenArchive => { - const numberOfArchivedProjects = childrenArchive.length - 2; // archived projects tiles - (header + divider)[2] - for (let i = 0; i < numberOfArchivedProjects; i++) { - cy.get(`[data-test=ProjectsView__ProjectsListItem--archive--${i}]`) - .first() - .scrollIntoView(); - cy.window().then(window => - window.scrollTo(0, window.scrollY - mainLayoutPaddingTop), - ); - // list item test - cy.get(`[data-test=ProjectsView__ProjectsListItem--archive--${i}]`) - .first() - .should('be.visible') - .within(() => { - // rewards test - cy.get('[data-test=ProjectRewards]').should('be.visible'); - }); - - if (numberOfArchivedProjects - 1) { - cy.get('[data-test=ProjectsView__ProjectsList--archive]') - .first() - .should('have.length', 1); - } - - cy.get(`[data-test=ProjectsView__ProjectsListItem--archive--${i}]`) - .first() - .invoke('data', 'address') - .then(address => { - cy.get(`[data-test=ProjectsView__ProjectsListItem--archive--${i}]`) - .first() - .invoke('data', 'epoch') - .then(epoch => { - cy.get(`[data-test=ProjectsView__ProjectsListItem--archive--${i}]`) - .first() - .click(); - checkLocationWithLoader( - `${ROOT_ROUTES.project.absolute}/${epoch}/${address}`, - ); - cy.go('back'); - checkLocationWithLoader(ROOT_ROUTES.projects.absolute); - }); - }); - } - }); - }); - }); - }); - }); -}); diff --git a/client/cypress/e2e/rewardsCalculator.cy.ts b/client/cypress/e2e/rewardsCalculator.cy.ts deleted file mode 100644 index 361153ff90..0000000000 --- a/client/cypress/e2e/rewardsCalculator.cy.ts +++ /dev/null @@ -1,252 +0,0 @@ -import { ETH_USD, mockCoinPricesServer, visitWithLoader } from 'cypress/utils/e2e'; -import viewports from 'cypress/utils/viewports'; -import { IS_ONBOARDING_ALWAYS_VISIBLE, IS_ONBOARDING_DONE } from 'src/constants/localStorageKeys'; -import { ROOT_ROUTES } from 'src/routes/RootRoutes/routes'; -import getFormattedEthValue from 'src/utils/getFormattedEthValue'; -import { parseUnitsBigInt } from 'src/utils/parseUnitsBigInt'; - -Object.values(viewports).forEach(({ device, viewportWidth, viewportHeight, isDesktop }) => { - describe(`rewards calculator: ${device}`, { viewportHeight, viewportWidth }, () => { - beforeEach(() => { - mockCoinPricesServer(); - localStorage.setItem(IS_ONBOARDING_ALWAYS_VISIBLE, 'false'); - localStorage.setItem(IS_ONBOARDING_DONE, 'true'); - visitWithLoader(ROOT_ROUTES.earn.absolute); - }); - - it('renders calculator icon inside box', () => { - cy.get('[data-test=Tooltip__rewardsCalculator__body]').should('be.visible'); - }); - - if (isDesktop) { - it('tooltip is visible on calculator icon hover and has correct text', () => { - cy.get('[data-test=Tooltip__rewardsCalculator').trigger('mouseover'); - cy.get('[data-test=Tooltip__rewardsCalculator__content') - .should('be.visible') - .invoke('text') - .should('eq', 'Calculate rewards'); - }); - } - - it('clicking on rewards calculator icon opens rewards calculator modal', () => { - cy.get('[data-test=Tooltip__rewardsCalculator__body]').click(); - cy.get('[data-test=ModalRewardsCalculator]').should('be.visible'); - }); - - it('default values in rewards calculator are 90 days and 5000 GLM', () => { - cy.get('[data-test=Tooltip__rewardsCalculator__body]').click(); - cy.get('[data-test=RewardsCalculator__InputText--crypto]').invoke('val').should('eq', '5000'); - cy.get('[data-test=RewardsCalculator__InputText--days]').invoke('val').should('eq', '90'); - }); - - it('calculator fetches rewards values in ETH and USD based on DAYS and GLM fields', () => { - cy.intercept('POST', '/rewards/estimated_budget').as('postEstimatedRewards'); - cy.get('[data-test=Tooltip__rewardsCalculator__body]').click(); - cy.get('[data-test=RewardsCalculator__InputText--estimatedRewards--crypto__Loader]').should( - 'be.visible', - ); - cy.get('[data-test=RewardsCalculator__InputText--estimatedRewards--fiat__Loader]').should( - 'be.visible', - ); - cy.wait('@postEstimatedRewards'); - - cy.get('@postEstimatedRewards').then( - ({ - response: { - body: { budget }, - }, - }) => { - const rewardsEth = getFormattedEthValue(parseUnitsBigInt(budget, 'wei')).value; - const rewardsUsd = (parseFloat(rewardsEth) * ETH_USD).toFixed(2); - - cy.get( - '[data-test=RewardsCalculator__InputText--estimatedRewards--crypto__Loader]', - ).should('not.exist'); - cy.get('[data-test=RewardsCalculator__InputText--estimatedRewards--fiat__Loader]').should( - 'not.exist', - ); - cy.get('[data-test=RewardsCalculator__InputText--estimatedRewards--crypto]') - .invoke('val') - .should('eq', rewardsEth); - cy.get('[data-test=RewardsCalculator__InputText--estimatedRewards--fiat]') - .invoke('val') - .should('eq', rewardsUsd); - }, - ); - - cy.intercept('POST', '/rewards/estimated_budget').as('postEstimatedRewardsGlmValueChange'); - cy.get('[data-test=RewardsCalculator__InputText--crypto]').type('500000'); - cy.get('[data-test=RewardsCalculator__InputText--estimatedRewards--crypto__Loader]').should( - 'be.visible', - ); - cy.get('[data-test=RewardsCalculator__InputText--estimatedRewards--fiat__Loader]').should( - 'be.visible', - ); - cy.wait('@postEstimatedRewardsGlmValueChange'); - - cy.get('@postEstimatedRewardsGlmValueChange').then( - ({ - response: { - body: { budget }, - }, - }) => { - const rewardsEth = getFormattedEthValue(parseUnitsBigInt(budget, 'wei')).value; - const rewardsUsd = (parseFloat(rewardsEth) * ETH_USD).toFixed(2); - - cy.get( - '[data-test=RewardsCalculator__InputText--estimatedRewards--crypto__Loader]', - ).should('not.exist'); - cy.get('[data-test=RewardsCalculator__InputText--estimatedRewards--fiat__Loader]').should( - 'not.exist', - ); - cy.get('[data-test=RewardsCalculator__InputText--estimatedRewards--crypto]') - .invoke('val') - .should('eq', rewardsEth); - cy.get('[data-test=RewardsCalculator__InputText--estimatedRewards--fiat]') - .invoke('val') - .should('eq', rewardsUsd); - }, - ); - - cy.intercept('POST', '/rewards/estimated_budget').as('postEstimatedRewardsDaysValueChange'); - cy.get('[data-test=RewardsCalculator__InputText--days]').clear().type('900'); - cy.get('[data-test=RewardsCalculator__InputText--estimatedRewards--crypto__Loader]').should( - 'be.visible', - ); - cy.get('[data-test=RewardsCalculator__InputText--estimatedRewards--fiat__Loader]').should( - 'be.visible', - ); - cy.wait('@postEstimatedRewardsDaysValueChange'); - - cy.get('@postEstimatedRewardsDaysValueChange').then( - ({ - response: { - body: { budget }, - }, - }) => { - const rewardsEth = getFormattedEthValue(parseUnitsBigInt(budget, 'wei')).value; - const rewardsUsd = (parseFloat(rewardsEth) * ETH_USD).toFixed(2); - - cy.get( - '[data-test=RewardsCalculator__InputText--estimatedRewards--crypto__Loader]', - ).should('not.exist'); - cy.get('[data-test=RewardsCalculator__InputText--estimatedRewards--fiat__Loader]').should( - 'not.exist', - ); - cy.get('[data-test=RewardsCalculator__InputText--estimatedRewards--crypto]') - .invoke('val') - .should('eq', rewardsEth); - cy.get('[data-test=RewardsCalculator__InputText--estimatedRewards--fiat]') - .invoke('val') - .should('eq', rewardsUsd); - }, - ); - }); - - it('If DAYS or GLM input is empty rewards inputs are empty too', () => { - cy.get('[data-test=Tooltip__rewardsCalculator__body]').click(); - cy.get('[data-test=RewardsCalculator__InputText--crypto]').clear(); - cy.get('[data-test=RewardsCalculator__InputText--estimatedRewards--crypto__Loader]').should( - 'not.exist', - ); - cy.get('[data-test=RewardsCalculator__InputText--estimatedRewards--fiat__Loader]').should( - 'not.exist', - ); - cy.get('[data-test=RewardsCalculator__InputText--estimatedRewards--crypto]') - .invoke('val') - .should('eq', ''); - cy.get('[data-test=RewardsCalculator__InputText--estimatedRewards--fiat]') - .invoke('val') - .should('eq', ''); - - cy.get('[data-test=RewardsCalculator__InputText--days]').clear(); - cy.get('[data-test=RewardsCalculator__InputText--estimatedRewards--crypto__Loader]').should( - 'not.exist', - ); - cy.get('[data-test=RewardsCalculator__InputText--estimatedRewards--fiat__Loader]').should( - 'not.exist', - ); - cy.get('[data-test=RewardsCalculator__InputText--estimatedRewards--crypto]') - .invoke('val') - .should('eq', ''); - cy.get('[data-test=RewardsCalculator__InputText--estimatedRewards--fiat]') - .invoke('val') - .should('eq', ''); - - cy.get('[data-test=RewardsCalculator__InputText--crypto]').type('5000'); - cy.get('[data-test=RewardsCalculator__InputText--estimatedRewards--crypto__Loader]').should( - 'not.exist', - ); - cy.get('[data-test=RewardsCalculator__InputText--estimatedRewards--fiat__Loader]').should( - 'not.exist', - ); - cy.get('[data-test=RewardsCalculator__InputText--estimatedRewards--crypto]') - .invoke('val') - .should('eq', ''); - cy.get('[data-test=RewardsCalculator__InputText--estimatedRewards--fiat]') - .invoke('val') - .should('eq', ''); - }); - - it('Max GLM amount is 1000000000', () => { - cy.intercept('POST', '/rewards/estimated_budget').as('postEstimatedRewards'); - - cy.get('[data-test=Tooltip__rewardsCalculator__body]').click(); - - cy.get('[data-test=RewardsCalculator__InputText--crypto]').type('1000000000'); - cy.wait('@postEstimatedRewards'); - - cy.get('@postEstimatedRewards').then( - ({ - response: { - body: { budget }, - }, - }) => { - const rewardsEth = getFormattedEthValue(parseUnitsBigInt(budget, 'wei')).value; - const rewardsUsd = (parseFloat(rewardsEth) * ETH_USD).toFixed(2); - - cy.get('[data-test=RewardsCalculator__InputText--estimatedRewards--crypto]') - .invoke('val') - .should('eq', rewardsEth); - cy.get('[data-test=RewardsCalculator__InputText--estimatedRewards--fiat]') - .invoke('val') - .should('eq', rewardsUsd); - - cy.get('[data-test=RewardsCalculator__InputText--crypto]') - .clear() - .type('1000000001') - .should('have.css', 'border-color', 'rgb(255, 97, 87)'); - cy.get('[data-test=RewardsCalculator__InputText--crypto__error]') - .should('be.visible') - .invoke('text') - .should('eq', 'That isn’t a valid amount'); - cy.get('[data-test=RewardsCalculator__InputText--estimatedRewards--crypto]') - .invoke('val') - .should('eq', ''); - cy.get('[data-test=RewardsCalculator__InputText--estimatedRewards--fiat]') - .invoke('val') - .should('eq', ''); - }, - ); - }); - - it('Closing the modal successfully cancels the request /estimated_budget', () => { - cy.window().then(win => { - cy.spy(win.console, 'error').as('consoleErrSpy'); - }); - - cy.get('[data-test=Tooltip__rewardsCalculator__body]').click(); - - cy.get('[data-test=RewardsCalculator__InputText--estimatedRewards--crypto__Loader]').should( - 'be.visible', - ); - - cy.get('[data-test=ModalRewardsCalculator__Button]').click(); - cy.get('[data-test=ModalRewardsCalculator').should('not.be.visible'); - - cy.on('uncaught:exception', error => { - expect(error.code).to.equal('ERR_CANCELED'); - }); - }); - }); -}); diff --git a/client/cypress/e2e/routes.cy.ts b/client/cypress/e2e/routes.cy.ts deleted file mode 100644 index 1d2dc113b8..0000000000 --- a/client/cypress/e2e/routes.cy.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { mockCoinPricesServer, visitWithLoader } from 'cypress/utils/e2e'; -import viewports from 'cypress/utils/viewports'; -import { ROOT, ROOT_ROUTES } from 'src/routes/RootRoutes/routes'; - -Object.values(viewports).forEach(({ device, viewportWidth, viewportHeight }) => { - describe(`routes (wallet not connected): ${device}`, { viewportHeight, viewportWidth }, () => { - before(() => { - mockCoinPricesServer(); - cy.clearLocalStorage(); - }); - - it('empty route redirects to projects view', () => { - visitWithLoader(ROOT.absolute, ROOT_ROUTES.projects.absolute); - cy.get('[data-test=ProjectsView]').should('be.visible'); - }); - - it('allocation route redirects to allocation view', () => { - visitWithLoader(ROOT_ROUTES.allocation.absolute); - cy.get('[data-test=AllocationView]').should('be.visible'); - }); - - it('earn route redirects to earn view', () => { - visitWithLoader(ROOT_ROUTES.earn.absolute); - cy.get('[data-test=EarnView]').should('be.visible'); - }); - - it('metrics route redirects to metrics view', () => { - visitWithLoader(ROOT_ROUTES.metrics.absolute); - cy.get('[data-test=MetricsView]').should('be.visible'); - }); - - it('projects route redirects to projects view', () => { - visitWithLoader(ROOT_ROUTES.projects.absolute); - cy.get('[data-test=ProjectsView]').should('be.visible'); - }); - - it('settings route redirects to settings view', () => { - visitWithLoader(ROOT_ROUTES.settings.absolute); - cy.get('[data-test=SettingsView]').should('be.visible'); - }); - }); -}); diff --git a/client/cypress/e2e/settings.cy.ts b/client/cypress/e2e/settings.cy.ts deleted file mode 100644 index 087b77329e..0000000000 --- a/client/cypress/e2e/settings.cy.ts +++ /dev/null @@ -1,188 +0,0 @@ -import { visitWithLoader, navigateWithCheck, mockCoinPricesServer } from 'cypress/utils/e2e'; -import viewports from 'cypress/utils/viewports'; -import { FIAT_CURRENCIES_SYMBOLS, DISPLAY_CURRENCIES } from 'src/constants/currencies'; -import { - ARE_OCTANT_TIPS_ALWAYS_VISIBLE, - DISPLAY_CURRENCY, - IS_CRYPTO_MAIN_VALUE_DISPLAY, - IS_ONBOARDING_ALWAYS_VISIBLE, - IS_ONBOARDING_DONE, -} from 'src/constants/localStorageKeys'; -import { ROOT_ROUTES } from 'src/routes/RootRoutes/routes'; -import getValueCryptoToDisplay from 'src/utils/getValueCryptoToDisplay'; - -Object.values(viewports).forEach(({ device, viewportWidth, viewportHeight }) => { - describe(`settings: ${device}`, { viewportHeight, viewportWidth }, () => { - beforeEach(() => { - mockCoinPricesServer(); - localStorage.setItem(IS_ONBOARDING_ALWAYS_VISIBLE, 'false'); - localStorage.setItem(IS_ONBOARDING_DONE, 'true'); - visitWithLoader(ROOT_ROUTES.settings.absolute); - }); - - it('"Always show Allocate onboarding" option toggle works', () => { - cy.get('[data-test=SettingsShowOnboardingBox__InputToggle]').check(); - cy.get('[data-test=SettingsShowOnboardingBox__InputToggle]').should('be.checked'); - cy.getAllLocalStorage().then(() => { - expect(localStorage.getItem(IS_ONBOARDING_ALWAYS_VISIBLE)).eq('true'); - }); - - cy.get('[data-test=SettingsShowOnboardingBox__InputToggle]').click(); - cy.get('[data-test=SettingsShowOnboardingBox__InputToggle]').should('not.be.checked'); - cy.getAllLocalStorage().then(() => { - expect(localStorage.getItem(IS_ONBOARDING_ALWAYS_VISIBLE)).eq('false'); - }); - - cy.get('[data-test=SettingsShowOnboardingBox__InputToggle]').click(); - cy.get('[data-test=SettingsShowOnboardingBox__InputToggle]').should('be.checked'); - cy.getAllLocalStorage().then(() => { - expect(localStorage.getItem(IS_ONBOARDING_ALWAYS_VISIBLE)).eq('true'); - }); - }); - - it('"Use crypto as main value display" option is checked by default', () => { - cy.get('[data-test=SettingsCryptoMainValueBox__InputToggle]').should('be.checked'); - cy.getAllLocalStorage().then(() => { - expect(localStorage.getItem(IS_CRYPTO_MAIN_VALUE_DISPLAY)).eq('true'); - }); - }); - - it('"Use crypto as main value display" option toggle works', () => { - cy.get('[data-test=SettingsCryptoMainValueBox__InputToggle]').check(); - cy.get('[data-test=SettingsCryptoMainValueBox__InputToggle]').should('be.checked'); - cy.getAllLocalStorage().then(() => { - expect(localStorage.getItem(IS_CRYPTO_MAIN_VALUE_DISPLAY)).eq('true'); - }); - - cy.get('[data-test=SettingsCryptoMainValueBox__InputToggle]').click(); - cy.get('[data-test=SettingsCryptoMainValueBox__InputToggle]').should('not.be.checked'); - cy.getAllLocalStorage().then(() => { - expect(localStorage.getItem(IS_CRYPTO_MAIN_VALUE_DISPLAY)).eq('false'); - }); - - cy.get('[data-test=SettingsCryptoMainValueBox__InputToggle]').click(); - cy.get('[data-test=SettingsCryptoMainValueBox__InputToggle]').should('be.checked'); - cy.getAllLocalStorage().then(() => { - expect(localStorage.getItem(IS_CRYPTO_MAIN_VALUE_DISPLAY)).eq('true'); - }); - }); - - it('"Use crypto as main value display" option by default displays crypto value as primary in DoubleValue component', () => { - navigateWithCheck(ROOT_ROUTES.earn.absolute); - - const cryptoValue = getValueCryptoToDisplay({ - cryptoCurrency: 'golem', - valueCrypto: BigInt(0), - }); - - cy.get('[data-test=BoxGlmLock__Section--effective__DoubleValue__primary]') - .invoke('text') - .should('eq', cryptoValue); - cy.get('[data-test=BoxGlmLock__Section--effective__DoubleValue__secondary]') - .invoke('text') - .should('not.eq', cryptoValue); - }); - - it('"Use crypto as main value display" option changes DoubleValue sections order', () => { - cy.get('[data-test=SettingsCryptoMainValueBox__InputToggle]').uncheck(); - navigateWithCheck(ROOT_ROUTES.earn.absolute); - - const cryptoValue = getValueCryptoToDisplay({ - cryptoCurrency: 'golem', - valueCrypto: BigInt(0), - }); - - cy.get('[data-test=BoxGlmLock__Section--effective__DoubleValue__primary]') - .invoke('text') - .should('not.eq', cryptoValue); - cy.get('[data-test=BoxGlmLock__Section--effective__DoubleValue__secondary]') - .invoke('text') - .should('eq', cryptoValue); - }); - - it('"Choose a display currency" option works', () => { - cy.getAllLocalStorage().then(() => { - expect(localStorage.getItem(DISPLAY_CURRENCY)).eq('"usd"'); - }); - - for (let i = 0; i < DISPLAY_CURRENCIES.length - 1; i++) { - const displayCurrency = DISPLAY_CURRENCIES[i]; - const displayCurrencyToUppercase = displayCurrency.toUpperCase(); - const nextDisplayCurrencyToUppercase = - i < DISPLAY_CURRENCIES.length - 1 ? DISPLAY_CURRENCIES[i + 1].toUpperCase() : undefined; - - cy.get('[data-test=SettingsCurrencyBox__InputSelect--currency__SingleValue]').contains( - displayCurrencyToUppercase, - ); - navigateWithCheck(ROOT_ROUTES.earn.absolute); - - if (FIAT_CURRENCIES_SYMBOLS[displayCurrency]) { - cy.get('[data-test=BoxGlmLock__Section--effective__DoubleValue__secondary]').contains( - FIAT_CURRENCIES_SYMBOLS[displayCurrency], - ); - } else { - cy.get('[data-test=BoxGlmLock__Section--effective__DoubleValue__secondary]').contains( - displayCurrencyToUppercase, - ); - } - - navigateWithCheck(ROOT_ROUTES.settings.absolute); - cy.get('[data-test=SettingsCurrencyBox__InputSelect--currency]').click(); - cy.get( - `[data-test=SettingsCurrencyBox__InputSelect--currency__Option--${nextDisplayCurrencyToUppercase}]`, - ).click(); - } - }); - - it('"Always show Octant tips" option toggle works', () => { - cy.get('[data-test=SettingsShowTipsBox__InputToggle]').check(); - cy.get('[data-test=SettingsShowTipsBox__InputToggle]').should('be.checked'); - cy.getAllLocalStorage().then(() => { - expect(localStorage.getItem(ARE_OCTANT_TIPS_ALWAYS_VISIBLE)).eq('true'); - }); - - cy.get('[data-test=SettingsShowTipsBox__InputToggle]').click(); - cy.get('[data-test=SettingsShowTipsBox__InputToggle]').should('not.be.checked'); - cy.getAllLocalStorage().then(() => { - expect(localStorage.getItem(ARE_OCTANT_TIPS_ALWAYS_VISIBLE)).eq('false'); - }); - - cy.get('[data-test=SettingsShowTipsBox__InputToggle]').click(); - cy.get('[data-test=SettingsShowTipsBox__InputToggle]').should('be.checked'); - cy.getAllLocalStorage().then(() => { - expect(localStorage.getItem(ARE_OCTANT_TIPS_ALWAYS_VISIBLE)).eq('true'); - }); - }); - - it('"Always show Octant tips" works (checked)', () => { - cy.get('[data-test=SettingsShowTipsBox__InputToggle]').check(); - - navigateWithCheck(ROOT_ROUTES.earn.absolute); - cy.get('[data-test=EarnView__TipTile--connectWallet]').should('exist'); - cy.get('[data-test=EarnView__TipTile--connectWallet]').should('be.visible'); - - cy.get('[data-test=EarnView__TipTile--connectWallet__Button]').click(); - cy.get('[data-test=EarnView__TipTile--connectWallet]').should('not.exist'); - - cy.reload(); - - cy.get('[data-test=EarnView__TipTile--connectWallet]').should('exist'); - cy.get('[data-test=EarnView__TipTile--connectWallet]').should('be.visible'); - }); - - it('"Always show Octant tips" works (unchecked)', () => { - cy.get('[data-test=SettingsShowTipsBox__InputToggle]').uncheck(); - - navigateWithCheck(ROOT_ROUTES.earn.absolute); - cy.get('[data-test=EarnView__TipTile--connectWallet]').should('exist'); - cy.get('[data-test=EarnView__TipTile--connectWallet]').should('be.visible'); - - cy.get('[data-test=EarnView__TipTile--connectWallet__Button]').click(); - cy.get('[data-test=EarnView__TipTile--connectWallet]').should('not.exist'); - - cy.reload(); - - cy.get('[data-test=EarnView__TipTile--connectWallet]').should('not.exist'); - }); - }); -}); diff --git a/client/src/sentry.ts b/client/src/sentry.ts index 4a7e555d65..c8cc190669 100644 --- a/client/src/sentry.ts +++ b/client/src/sentry.ts @@ -1,18 +1,19 @@ // eslint-disable-next-line no-restricted-syntax import * as Sentry from '@sentry/react'; -import env from 'env'; +// import env from 'env'; Sentry.init({ dsn: 'https://207392fdfee5b8348be75b27b53c0e82@o4506778713194496.ingest.sentry.io/4506778715881472', - integrations: [Sentry.browserTracingIntegration()], + // TODO OCT-1525 enable browserTracingIntegration or remove this TODO. + // integrations: [Sentry.browserTracingIntegration()], // Capture 100% of the transactions // Set 'tracePropagationTargets' to control for which URLs distributed tracing should be enabled - tracePropagationTargets: [ - env.serverEndpoint, - ...env.ipfsGateways.split(','), - ], + // tracePropagationTargets: [ + // env.serverEndpoint, + // ...env.ipfsGateways.split(','), + // ], // Performance Monitoring - tracesSampleRate: 1.0, + // tracesSampleRate: 1.0, // Session Replay });