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-2144: Calendar E2E #564

Merged
merged 23 commits into from
Nov 29, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
04861fe
oct-2144: calendar e2e
jmikolajczyk Nov 22, 2024
432c51b
oct-2144: milestones fix
jmikolajczyk Nov 22, 2024
2d6db03
oct-2144: calendar e2e fixes
jmikolajczyk Nov 25, 2024
266d585
oct-2144: calendar e2e update
jmikolajczyk Nov 25, 2024
4c5a6d3
Merge branch 'master' into test/oct-2144-calendar-e2e
jmikolajczyk Nov 25, 2024
087bff4
oct-2144: _9calendar
jmikolajczyk Nov 25, 2024
a6cfa43
calendar - test 1
jmikolajczyk Nov 25, 2024
0a62b29
oct-2144: e2e timezone
jmikolajczyk Nov 25, 2024
db50b99
oct-2144: deploy pr epoch duration/desicion window update
jmikolajczyk Nov 26, 2024
b538122
oct-2144: test 2
jmikolajczyk Nov 26, 2024
15acfe9
oct-2144: calendar alert test 1
jmikolajczyk Nov 26, 2024
421bb9a
oct-2144: calendar alert test 2
jmikolajczyk Nov 26, 2024
9a03f85
oct-2144: calendar alert test 3
jmikolajczyk Nov 26, 2024
1f0bbea
oct-2144: calendar alert test 4
jmikolajczyk Nov 26, 2024
22728a3
oct-2144: calendar alert test 5 mobile
jmikolajczyk Nov 26, 2024
cfea52b
oct-2144: calendar alert test 5 all viewports
jmikolajczyk Nov 26, 2024
0deda87
oct-2144: calendar alert test 6 all viewports
jmikolajczyk Nov 26, 2024
52070e4
oct-2144: calendar e2e fixed
jmikolajczyk Nov 26, 2024
bd860f7
oct-2144: calendar alert test 7
jmikolajczyk Nov 26, 2024
abdc761
oct-2144: calendar alert test 8
jmikolajczyk Nov 26, 2024
9a5ca98
oct-2144: calendar alert test 9
jmikolajczyk Nov 26, 2024
c4acac3
oct-2144: calendar alert test 10
jmikolajczyk Nov 27, 2024
ed669aa
oct-2144: calendar e2e - final
jmikolajczyk Nov 27, 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
5 changes: 0 additions & 5 deletions client/cypress/e2e/_3layoutTopBar.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,11 +163,6 @@ Object.values(viewports).forEach(({ device, viewportWidth, viewportHeight }) =>
cy.get('[data-test=LayoutTopBarCalendar]').should('be.visible');
});

it('Epoch info badge opens Calendar on click', () => {
cy.get('[data-test=LayoutTopBarCalendar]').click();
cy.get('[data-test=Calendar]').should('be.visible');
});

it('Connect wallet button is visible', () => {
cy.get('[data-test=LayoutTopBar__Button]').should('be.visible');
});
Expand Down
272 changes: 272 additions & 0 deletions client/cypress/e2e/_8calendar.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,272 @@
// eslint-disable-next-line import/no-extraneous-dependencies
import chaiColors from 'chai-colors';

import { mockCoinPricesServer, visitWithLoader } from 'cypress/utils/e2e';
import { moveTime, setupAndMoveToPlayground } from 'cypress/utils/moveTime';
import viewports from 'cypress/utils/viewports';
import { QUERY_KEYS } from 'src/api/queryKeys';
import {
HAS_ONBOARDING_BEEN_CLOSED,
IS_ONBOARDING_ALWAYS_VISIBLE,
IS_ONBOARDING_DONE,
} from 'src/constants/localStorageKeys';
import { ROOT, ROOT_ROUTES } from 'src/routes/RootRoutes/routes';

chai.use(chaiColors);

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

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

it('Epoch info badge opens Calendar on click', () => {
cy.wait(2000);
cy.get('[data-test=LayoutTopBarCalendar]').click();
cy.get('[data-test=Calendar]').should('be.visible');
});

it('Clicking on overlay closes the Calendar', () => {
cy.wait(2000);
cy.get('[data-test=LayoutTopBarCalendar]').click();
cy.get('[data-test=Calendar]').should('be.visible');
if (isMobile) {
cy.get('[data-test=LayoutTopBarCalendar__ModalCalendar__overflow]').click({
force: true,
});
} else {
cy.get('[data-test=LayoutTopBarCalendar__calendarOverflow]').click();
}
cy.get('[data-test=Calendar]').should('not.exist');
});

it('Active milestone is always visible after calendar open (and has correct style)', () => {
cy.wait(2000);
cy.get('[data-test=LayoutTopBarCalendar]').click();
cy.get('[data-test=CalendarItem][data-is-active=true]').should('be.visible');
cy.get('[data-test=CalendarItem][data-is-active=true]')
.invoke('css', 'opacity')
.should('eq', '1');
cy.get('[data-test=CalendarItem][data-is-active=true]')
.then($el => $el.css('backgroundColor'))
.should('be.colored', '#f1faf8');
cy.get('[data-test=CalendarItem][data-is-active=true]').within(() => {
cy.get('[data-test=CalendarItem__title__day]')
.then($el => $el.css('color'))
.should('be.colored', '#2d9b87');
cy.get('[data-test=CalendarItem__title__monthShort]')
.then($el => $el.css('color'))
.should('be.colored', '#2d9b87');
cy.get('[data-test=CalendarItem__label]')
.then($el => $el.css('color'))
.should('be.colored', '#2d9b87');
cy.get('[data-test=CalendarItem__date]')
.then($el => $el.css('color'))
.should('be.colored', '#2d9b87');
});
});

it('Milestone with "to" param shows end date of event', () => {
cy.wait(2000);
cy.get('[data-test=LayoutTopBarCalendar]').click();
cy.get('[data-test=CalendarItem][data-is-active=true]').within(() => {
cy.get('[data-test=CalendarItem__date]')
.invoke('text')
.should('include', 'Closes 31 January');
});
});

it('Milestone without "to" param shows hour and timezone of event start', () => {
cy.wait(2000);
cy.get('[data-test=LayoutTopBarCalendar]').click();
cy.get('[data-test=CalendarItem]')
.eq(1)
.within(() => {
cy.get('[data-test=CalendarItem__date]').invoke('text').should('include', 'am CET');
});
});

if (isMobile) {
it('User can scroll through milestones by drag&drop vertically', () => {
cy.wait(2000);
cy.get('[data-test=LayoutTopBarCalendar]').click();
cy.get('[data-test=CalendarItem][data-is-active=true]').then($calendarItemActive => {
const { top: calendarItemActiveTop } = $calendarItemActive[0].getBoundingClientRect();

cy.get('[data-test=CalendarItem]').eq(2).should('not.be.visible');
cy.get('[data-test=CalendarItem]')
.eq(2)
.then($prevCalendarItem => {
const { height: prevCalendarItemHeight } =
$prevCalendarItem[0].getBoundingClientRect();
const prevCalendarItemMarginBottm = parseInt(
$prevCalendarItem.css('marginBottom'),
10,
);

const pointerDownPageY = calendarItemActiveTop;
const pointerUpPageY = Math.ceil(
calendarItemActiveTop + prevCalendarItemHeight + prevCalendarItemMarginBottm,
);

cy.get('[data-test=Calendar__wrapper]')
.trigger('pointerdown', {
pageY: pointerDownPageY,
})
.trigger('pointermove', {
pageY: pointerUpPageY,
})
.trigger('pointerup', {
pageY: pointerUpPageY,
});

cy.get('[data-test=CalendarItem]').eq(2).should('be.visible');
});
});
});
} else {
it('User can scroll through milestones by drag&drop horizontally', () => {
cy.wait(2000);
cy.get('[data-test=LayoutTopBarCalendar]').click();
cy.get('[data-test=CalendarItem][data-is-active=true]').then($calendarItemActive => {
const { left: calendarItemActiveLeft } = $calendarItemActive[0].getBoundingClientRect();

cy.get('[data-test=CalendarItem]').eq(2).should('not.be.visible');
cy.get('[data-test=CalendarItem]')
.eq(2)
.then($prevCalendarItem => {
const { width: prevCalendarItemWidth } = $prevCalendarItem[0].getBoundingClientRect();
const prevCalendarItemMarginRight = parseInt(
$prevCalendarItem.css('marginRight'),
10,
);

const pointerDownPageX = calendarItemActiveLeft;
const pointerUpPageX = Math.ceil(
calendarItemActiveLeft + prevCalendarItemWidth + prevCalendarItemMarginRight,
);

cy.get('[data-test=Calendar__wrapper]')
.trigger('pointerdown', {
pageX: pointerDownPageX,
})
.trigger('pointermove', {
pageX: pointerUpPageX,
})
.trigger('pointerup', {
pageX: pointerUpPageX,
});

cy.get('[data-test=CalendarItem]').eq(2).should('be.visible');
});
});
});
}

if (isMobile) {
it('User can close Calendar by clicking on close button (X) in top-right corner', () => {
cy.wait(2000);
cy.get('[data-test=LayoutTopBarCalendar]').click();
cy.get('[data-test=Calendar]').should('be.visible');
cy.get('[data-test=LayoutTopBarCalendar__ModalCalendar__Button]').click();
cy.get('[data-test=Calendar]').should('not.exist');
});
}
});
});

describe('move time - AW IS OPEN - less than 24h to change AW', () => {
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 closed, when it is not, move time', () => {
setupAndMoveToPlayground();

cy.window().then(async win => {
moveTime(win, 'nextEpochDecisionWindowOpenLessThan24H').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, isDesktop, isLargeDesktop }) => {
describe(`[AW IS OPEN < 24h] Calendar: ${device}`, { viewportHeight, viewportWidth }, () => {
before(() => {
cy.clearLocalStorage();
});

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

it('Allocation window milestone has alert style when AW is going to change in less than 24h', () => {
cy.wait(2000);
cy.get('[data-test=LayoutTopBarCalendar]').click();
cy.get('[data-test=CalendarItem][data-is-active=true]').should('be.visible');
cy.get('[data-test=CalendarItem][data-is-active=true]')
.invoke('css', 'opacity')
.should('eq', '1');
cy.get('[data-test=CalendarItem][data-is-active=true]')
.then($el => $el.css('backgroundColor'))
.should('be.colored', '#fff5f4');
cy.get('[data-test=CalendarItem][data-is-active=true]').within(() => {
cy.get('[data-test=CalendarItem__title__day]')
.then($el => $el.css('color'))
.should('be.colored', '#ff6157');
cy.get('[data-test=CalendarItem__title__monthShort]')
.then($el => $el.css('color'))
.should('be.colored', '#ff6157');
cy.get('[data-test=CalendarItem__label]')
.invoke('text')
.should('eq', 'Allocation window');
cy.get('[data-test=CalendarItem__label]')
.then($el => $el.css('color'))
.should('be.colored', '#ff6157');
cy.get('[data-test=CalendarItem__date]')
.then($el => $el.css('color'))
.should('be.colored', '#ff6157');
});
});

if (isDesktop || isLargeDesktop) {
it('Allocation window milestone with alert style shows time to change AW on hover', () => {
cy.wait(2000);
cy.get('[data-test=LayoutTopBarCalendar]').click();
cy.get('[data-test=CalendarItem][data-is-active=true]')
.realHover()
.then($el => $el.css('backgroundColor'))
.should('be.colored', '#ffeae6');
cy.get('[data-test=CalendarItem][data-is-active=true]')
.realHover()
.within(() => {
cy.get('[data-test=CalendarItem__date]').invoke('text').should('contain', 'hours');
});
});
}
});
},
);
1 change: 1 addition & 0 deletions client/cypress/support/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
import 'cypress-real-events';
import './commands';
1 change: 1 addition & 0 deletions client/cypress/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"@synthetixio/synpress/support",
"cypress-wait-until",
"@testing-library/cypress",
"cypress-real-events",
"../global"
],
"outDir": "./output"
Expand Down
32 changes: 23 additions & 9 deletions client/cypress/utils/moveTime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,12 @@ export const mutateAsyncMakeSnapshot = (
});
});

const mutateAsyncMoveToDecisionWindowOpen = (cypressWindow: Cypress.AUTWindow): Promise<any> =>
const mutateAsyncMoveToDecisionWindowOpen = (
cypressWindow: Cypress.AUTWindow,
isLessThan24HoursToChangeAW?: boolean,
): Promise<any> =>
new Cypress.Promise(resolve => {
cypressWindow.mutateAsyncMoveToDecisionWindowOpen().then(() => {
cypressWindow.mutateAsyncMoveToDecisionWindowOpen(isLessThan24HoursToChangeAW).then(() => {
resolve(true);
});
});
Expand All @@ -51,12 +54,17 @@ const waitForLoadersToDisappear = (): Chainable<any> => {
return cy.get('[data-test=SyncView]', { timeout: 60000 }).should('not.exist');
};

const moveToDecisionWindowOpen = (cypressWindow: Cypress.AUTWindow): Chainable<any> => {
const moveToDecisionWindowOpen = (
cypressWindow: Cypress.AUTWindow,
isLessThan24HoursToChangeAW?: boolean,
): Chainable<any> => {
waitForLoadersToDisappear();
cy.wrap(null).then(() => {
return mutateAsyncMoveToDecisionWindowOpen(cypressWindow).then(str => {
expect(str).to.eq(true);
});
return mutateAsyncMoveToDecisionWindowOpen(cypressWindow, isLessThan24HoursToChangeAW).then(
str => {
expect(str).to.eq(true);
},
);
});
waitForLoadersToDisappear();
// Waiting 2s is a way to prevent the effects of slowing down the e2e environment (data update).
Expand Down Expand Up @@ -100,7 +108,10 @@ const moveToDecisionWindowClosed = (cypressWindow: Cypress.AUTWindow): Chainable
*/
export const moveTime = (
cypressWindow: Cypress.AUTWindow,
moveTo: 'nextEpochDecisionWindowClosed' | 'nextEpochDecisionWindowOpen',
moveTo:
| 'nextEpochDecisionWindowClosed'
| 'nextEpochDecisionWindowOpen'
| 'nextEpochDecisionWindowOpenLessThan24H',
connectWalletParams?: ConnectWalletParameters,
): Chainable<any> => {
const isDecisionWindowOpen = cypressWindow.clientReactQuery.getQueryData(
Expand All @@ -114,8 +125,11 @@ export const moveTime = (
cy.reload();
}

if (moveTo === 'nextEpochDecisionWindowOpen') {
moveToDecisionWindowOpen(cypressWindow);
if (
moveTo === 'nextEpochDecisionWindowOpen' ||
moveTo === 'nextEpochDecisionWindowOpenLessThan24H'
) {
moveToDecisionWindowOpen(cypressWindow, moveTo === 'nextEpochDecisionWindowOpenLessThan24H');
} else {
moveToDecisionWindowOpen(cypressWindow);
// Reload is needed to get updated data in the app
Expand Down
6 changes: 3 additions & 3 deletions client/cypress/utils/viewports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ type Viewport = {
isMobile: boolean;
isTablet: boolean;
viewportHeight: number;
viewportWidth: 471 | 755 | 1280 | 1920;
viewportWidth: 390 | 755 | 1280 | 1920;
};

type Viewports = {
Expand Down Expand Up @@ -37,8 +37,8 @@ const viewports: Viewports = {
isLargeDesktop: false,
isMobile: true,
isTablet: false,
viewportHeight: 1020,
viewportWidth: 471,
viewportHeight: 844,
viewportWidth: 390,
},
tablet: {
device: 'tablet',
Expand Down
1 change: 1 addition & 0 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"@wagmi/core": "^2.14.1",
"axios": "^1.7.2",
"classnames": "^2.5.1",
"cypress-real-events": "^1.13.0",
"date-fns": "^3.6.0",
"dotenv": "^16.4.5",
"formik": "^2.4.6",
Expand Down
Loading
Loading