Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

OCT-2127 Project E2E #586

Merged
merged 21 commits into from
Dec 19, 2024
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
b7e16cc
feat: initial prototype
aziolek Dec 11, 2024
0e6e120
test: disable test for fiat
aziolek Dec 11, 2024
86b4df6
test: transition in progress
aziolek Dec 11, 2024
c2038e5
test: adjustment of header, numberOfAllocations indicator, scrolling …
aziolek Dec 12, 2024
515bd63
test: adjustment of header, numberOfAllocations indicator, scrolling …
aziolek Dec 12, 2024
a390833
test: adjustment of header, numberOfAllocations indicator, scrolling …
aziolek Dec 12, 2024
a0b2df0
test: adjustment of header, numberOfAllocations indicator, scrolling …
aziolek Dec 13, 2024
1ea0fbb
test: adjustment of header, numberOfAllocations indicator, scrolling …
aziolek Dec 13, 2024
6e919bf
feat: assertions for donors & milestones
aziolek Dec 15, 2024
76902ca
test: readd removed tests
aziolek Dec 15, 2024
ef2b7a2
test: fixes for mobile donors
aziolek Dec 16, 2024
d7a8ddb
fix: milestones nested in the response from the hook
aziolek Dec 16, 2024
2645ae7
fix: schemas
aziolek Dec 16, 2024
efe630f
Merge branch 'master' into test/oct-2127-e2e-project-view
aziolek Dec 17, 2024
8083c5d
feat: checks for no milestones, sharing and button
aziolek Dec 17, 2024
22558a3
test: get => find
aziolek Dec 18, 2024
a4402d6
fix: toggle crypto, find share button
aziolek Dec 18, 2024
dec83b7
fix: remove duplicated check
aziolek Dec 18, 2024
f2264f6
fix: reroute, first / visible checks
aziolek Dec 18, 2024
5402a76
fix: reroute, first / visible checks
aziolek Dec 18, 2024
1f99503
test: increase wait after route change
aziolek Dec 19, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
314 changes: 314 additions & 0 deletions client/cypress/e2e/_16project.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,314 @@
import {
changeMainValueToCryptoToggle,
// changeMainValueToFiat,
checkProjectsViewLoaded,
connectWallet,
mockCoinPricesServer,
visitWithLoader,
} from 'cypress/utils/e2e';
import { moveTime, setupAndMoveToPlayground } from 'cypress/utils/moveTime';
import { getNamesOfProjects } from 'cypress/utils/projects';
import viewports from 'cypress/utils/viewports';
import { QUERY_KEYS } from 'src/api/queryKeys';
import {
HAS_ONBOARDING_BEEN_CLOSED,
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 Chainable = Cypress.Chainable;

const getButtonAddToAllocate = (): Chainable<any> => {
const projectListItemFirst = cy.get('[data-test=ProjectListItem').first();

return projectListItemFirst
.find('[data-test=ProjectListItemHeader__ButtonAddToAllocate]')
.filter(':visible');
};

const checkProjectItemElements = (areMiddleSectionsVisible: boolean): Chainable<any> => {
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__ButtonAddToAllocate]')
.should('be.visible');
projectListItemFirst.get('[data-test=ProjectListItem__Description]').should('be.visible');
projectListItemFirst.get('[data-test=ProjectRewards__currentTotal__label]').should('be.visible');

if (areMiddleSectionsVisible) {
projectListItemFirst
.get('[data-test=ProjectRewards__donationsToDisplay__label]')
.should('be.visible');
projectListItemFirst
.get('[data-test=ProjectRewards__matchFunding__label]')
.should('be.visible');
}

projectListItemFirst.get('[data-test=ProjectRewards__donors]').should('be.visible');

if (areMiddleSectionsVisible) {
projectListItemFirst.get('[data-test=ProjectRewards__donors]').click();
} else {
projectListItemFirst.get('[data-test=ProjectRewards__Button--donors]').click();
}
cy.get('[data-test^=ModalFullDonorsList').should('be.visible');
cy.get('[data-test^=ModalFullDonorsList__Button').click();
cy.get('[data-test^=ModalFullDonorsList').should('not.exist');

projectListItemFirst
.find('[data-test=ProjectListItemButtonsWebsiteAndShare__websiteLink]')
.should('be.visible');

projectListItemFirst
.find('[data-test=ProjectListItemButtonsWebsiteAndShare__Tooltip]')
.should('be.visible');
projectListItemFirst.find('[data-test=ProjectListItemButtonsWebsiteAndShare__Tooltip]').click();
cy.window().then(win => {
projectListItemFirst.find('[data-test=ProjectListItemButtonsWebsiteAndShare__Tooltip]').click();
win.navigator.clipboard.readText().then(text => {
expect(text).to.eq(cy.url());
});
});
projectListItemFirst
.get('[data-test=ProjectMilestonesNoResults]')
.scrollIntoView()
.should('be.visible');
return projectListItemFirst
.get('[data-test=ProjectMilestonesNoResults__header]')
.invoke('text')
.should('eq', 'Nothing to report yet. Check back again soon');
};

const getHeartedProjectsIndicator = (isNavbarVisible: boolean): Chainable<any> => {
return cy.get(
isNavbarVisible
? '[data-test=LayoutNavbar__numberOfAllocations]'
: '[data-test=LayoutTopBar__numberOfAllocations]',
);
};

const checkHeartedProjectsIndicator = (isNavbarVisible: boolean, number = 1): Chainable<any> => {
return getHeartedProjectsIndicator(isNavbarVisible).contains(number);
};

describe('move time - AW IS OPEN - less than 24h to change AW', () => {
jmikolajczyk marked this conversation as resolved.
Show resolved Hide resolved
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();
});

it('allocation window is open, when it is not, move time', () => {
setupAndMoveToPlayground();

cy.window().then(async win => {
moveTime(win, 'nextEpochDecisionWindowOpen').then(() => {
cy.get('[data-test=PlaygroundView]').should('be.visible');
const isDecisionWindowOpenAfter = win.clientReactQuery.getQueryData(
QUERY_KEYS.isDecisionWindowOpen,
);
expect(isDecisionWindowOpenAfter).to.be.true;
});
});
});
});

Object.values(viewports).forEach(
({ device, viewportWidth, viewportHeight, isMobile, isTablet }) => {
describe(`[AW IS OPEN] Project: ${device}`, { viewportHeight, viewportWidth }, () => {
let projectNames: string[] = [];

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.projects.absolute);
checkProjectsViewLoaded();

/**
* 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(!isMobile && !isTablet);
});

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(!isMobile && !isTablet);
});

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();
checkHeartedProjectsIndicator(isMobile || isTablet);
getButtonAddToAllocate().click();
getHeartedProjectsIndicator(isMobile || isTablet).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 } })
.should('be.visible');
cy.get('[data-test=ProjectMilestones]')
.eq(i)
.scrollIntoView({ offset: { left: 0, top: 100 } })
.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=ProjectMilestones]')
.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=ProjectMilestones]')
.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');
}
}
});

it(`shows current total (${IS_CRYPTO_MAIN_VALUE_DISPLAY}: true)`, () => {
cy.get('[data-test^=ProjectsView__ProjectsListItem').first().click();
cy.get('[data-test=ProjectRewards__currentTotal__number]')
.first()
.invoke('text')
.should('eq', '0 ETH');
});

it(`shows current total (${IS_CRYPTO_MAIN_VALUE_DISPLAY}: false)`, () => {
changeMainValueToCryptoToggle(!isMobile && !isTablet, 'fiat');
visitWithLoader(ROOT_ROUTES.projects.absolute);
cy.get('[data-test^=ProjectsView__ProjectsListItem').first().click();
cy.get('[data-test=ProjectRewards__currentTotal__number]')
.first()
.invoke('text')
.should('eq', '$0.00');
});
});

describe(`projects (IPFS failure): ${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(() => {
cy.intercept('GET', '**/ipfs/**', req => {
req.destroy();
});

mockCoinPricesServer();
localStorage.setItem(IS_ONBOARDING_ALWAYS_VISIBLE, 'false');
localStorage.setItem(IS_ONBOARDING_DONE, 'true');
localStorage.setItem(HAS_ONBOARDING_BEEN_CLOSED, 'true');
visitWithLoader(ROOT_ROUTES.projects.absolute);
});

it('entering project view shows Toast with info about IPFS failure when all providers fail', () => {
cy.get('[data-test=Toast--ipfsMessage').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_ALWAYS_VISIBLE, 'false');
localStorage.setItem(IS_ONBOARDING_DONE, 'true');
localStorage.setItem(HAS_ONBOARDING_BEEN_CLOSED, 'true');
visitWithLoader(ROOT_ROUTES.projects.absolute);
connectWallet({ isPatronModeEnabled: true });
checkProjectsViewLoaded();

/**
* 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).click();
getButtonAddToAllocate().should('be.visible').should('be.disabled');
cy.go('back');
}
});
});
},
);
35 changes: 35 additions & 0 deletions client/cypress/utils/e2e.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import { IS_CRYPTO_MAIN_VALUE_DISPLAY } from 'src/constants/localStorageKeys';
import { ROOT_ROUTES } from 'src/routes/RootRoutes/routes';

import { ConnectWalletParameters } from './types';

import Chainable = Cypress.Chainable;
Expand Down Expand Up @@ -100,3 +103,35 @@ export const checkProjectsViewLoaded = (): Chainable<any> => {

return cy.get('[data-test^=ProjectItemSkeleton').should('not.exist');
};

export const changeMainValueToCryptoToggle = (
isDesktopTypeView: boolean,
changeToCryptoOrFiat: 'crypto' | 'fiat',
): Chainable<any> => {
visitWithLoader(
ROOT_ROUTES.settings.absolute,
isDesktopTypeView ? ROOT_ROUTES.home.absolute : ROOT_ROUTES.settings.absolute,
);
if (isDesktopTypeView) {
cy.get('[data-test=SettingsDrawer]').should('be.visible');
cy.get('[data-test=SettingsView]').should('not.exist');
} else {
cy.get('[data-test=SettingsDrawer]').should('not.exist');
cy.get('[data-test=SettingsView]').should('be.visible');
}
if (changeToCryptoOrFiat === 'crypto') {
cy.get('[data-test=SettingsCryptoMainValueBox__InputToggle]').check({ force: true });
cy.get('[data-test=SettingsCryptoMainValueBox__InputToggle]').should('be.checked');
cy.getAllLocalStorage().then(() => {
jmikolajczyk marked this conversation as resolved.
Show resolved Hide resolved
expect(localStorage.getItem(IS_CRYPTO_MAIN_VALUE_DISPLAY)).eq('true');
});
} else {
cy.get('[data-test=SettingsCryptoMainValueBox__InputToggle]').uncheck({ force: true });
cy.get('[data-test=SettingsCryptoMainValueBox__InputToggle]').should('be.checked');
}
return cy.getAllLocalStorage().then(() => {
expect(localStorage.getItem(IS_CRYPTO_MAIN_VALUE_DISPLAY)).eq(
changeToCryptoOrFiat === 'crypto' ? 'true' : 'false',
);
});
};
Loading
Loading