-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
test: add e2e tests for dashboard and events pages #4548
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
base: master
Are you sure you want to change the base?
Changes from all commits
951e5af
3918299
0b04fa6
c513668
b5f8e1c
6760dc8
656e1fb
89b7fad
b839d8e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| import DashboardPage from './pages/dashboard'; | ||
|
|
||
| describe('Dashboard Page Tests', () => { | ||
| const dashboard = new DashboardPage(); | ||
|
|
||
| beforeEach(() => { | ||
| dashboard.visit(); | ||
| }); | ||
|
|
||
| it('User navigates to the dashboard and verifies header', () => { | ||
| dashboard.verifyHeader(); | ||
| }); | ||
|
|
||
| it('User verifies Hot Topics section', () => { | ||
| dashboard.verifyHotTopicsSection(); | ||
| }); | ||
|
|
||
| it('User verifies Good First Issues section', () => { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you please improve the naming of all these tests? You can refer to the test naming conventions. For example, test names should not start with phrases like The naming should follow a pattern like: |
||
| dashboard.verifyGoodFirstIssuesSection(); | ||
| }); | ||
|
|
||
| it('User verifies all header links point to correct URLs from source', () => { | ||
| dashboard.verifyHeaderLinks(); | ||
| }); | ||
| }); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| import EventsPage from './pages/events'; | ||
|
|
||
| describe('Events Page Tests', () => { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As mentioned above, please review all these namings |
||
| const events = new EventsPage(); | ||
|
|
||
| beforeEach(() => { | ||
| events.visit(); | ||
| }); | ||
|
|
||
| it('User navigates to the events page and verifies main sections and action buttons', () => { | ||
| events.verifyMainVisible(); | ||
| events.verifyActionButtons(); | ||
| }); | ||
|
|
||
| it('User verifies Google Calendar and ICS file button links', () => { | ||
| events.verifyEventButtonsLinks(); | ||
| }); | ||
|
|
||
| it('User verifies recordings section with correct link', () => { | ||
| events.verifyRecordingsSection(); | ||
| events.verifyRecordingsLinkHref(); | ||
| }); | ||
|
|
||
| it('User verifies all event recording links from source', () => { | ||
| events.verifyEventRecordingLinks(); | ||
| }); | ||
|
|
||
| it('User verifies event types section', () => { | ||
| events.verifyEventTypes(); | ||
| }); | ||
|
|
||
| it('User verifies FAQ link points to correct documentation', () => { | ||
| events.verifyFaqLink(); | ||
| }); | ||
|
|
||
| it('User verifies all host profile links', () => { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As mentioned above, please review the naming of all these tests |
||
| events.verifyHostLinks(); | ||
| }); | ||
|
|
||
| it('User verifies event cards have valid links on All tab', () => { | ||
| events.verifyAllEventCards(); | ||
| }); | ||
|
|
||
| it('User switches to Upcoming tab and verifies event cards have valid links', () => { | ||
| events.switchToUpcoming(); | ||
| events.verifyUpcomingEventCards(); | ||
| }); | ||
|
|
||
| it('User switches to Recorded tab and verifies event cards have valid links', () => { | ||
| events.switchToRecorded(); | ||
| events.verifyRecordedEventCards(); | ||
| }); | ||
| }); | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,62 @@ | ||||||||||||||||||||||||||
| class DashboardPage { | ||||||||||||||||||||||||||
| visit() { | ||||||||||||||||||||||||||
| cy.visit('/community/dashboard'); | ||||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These visit() methods are everywhere. They are repeating everywhere. Consider using a single helper like visit(path). This reduces repetition and makes your code DRY. Please review all the methods in all the tests you have added vis multiple PRs. If they can be extract out to shared functions which makes it re-usable and keeps the code DRY |
||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| verifyElementIsVisible(selector) { | ||||||||||||||||||||||||||
| cy.get(selector).should('be.visible'); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| verifyTextVisible(text) { | ||||||||||||||||||||||||||
| cy.contains(text).should('be.visible'); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| verifyHeader() { | ||||||||||||||||||||||||||
| this.verifyElementIsVisible('[data-testid="Header-heading"]'); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| verifyGoodFirstIssuesSection() { | ||||||||||||||||||||||||||
| this.verifyTextVisible('Good First Issues'); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| verifyHotTopicsSection() { | ||||||||||||||||||||||||||
| this.verifyTextVisible('Hot Topics'); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| verifyElementHasAttribute(selector, attribute, value) { | ||||||||||||||||||||||||||
| cy.get(selector).should('have.attr', attribute, value); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
|
Comment on lines
+26
to
+29
|
||||||||||||||||||||||||||
| verifyElementHasAttribute(selector, attribute, value) { | |
| cy.get(selector).should('have.attr', attribute, value); | |
| } |
Copilot
AI
Dec 30, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The verification of the 'Contribution Guide' link is duplicated. Lines 38-42 already verify the href contains 'github.com/asyncapi', then lines 44-46 unnecessarily retrieve the same link again just to check for 'type=source'. These assertions should be combined into a single chain or the link should be aliased to avoid redundant DOM queries.
| this.verifyLinkWithText( | |
| '[data-testid="Button-link"]', | |
| 'Contribution Guide', | |
| 'github.com/asyncapi', | |
| ); | |
| cy.contains('[data-testid="Button-link"]', 'Contribution Guide') | |
| .should('have.attr', 'href') | |
| cy.contains('[data-testid="Button-link"]', 'Contribution Guide') | |
| .should('be.visible') | |
| .and('have.attr', 'href') | |
| .and('include', 'github.com/asyncapi') |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,146 @@ | ||||||||||||||||||||||||||||||||||||||
| class EventsPage { | ||||||||||||||||||||||||||||||||||||||
| visit() { | ||||||||||||||||||||||||||||||||||||||
| cy.visit('/community/events'); | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| verifyElementIsVisible(selector) { | ||||||||||||||||||||||||||||||||||||||
| cy.get(selector).should('be.visible'); | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| verifyMainVisible() { | ||||||||||||||||||||||||||||||||||||||
| this.verifyElementIsVisible('[data-testid="Events-main"]'); | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| verifyActionButtons() { | ||||||||||||||||||||||||||||||||||||||
| this.verifyElementIsVisible('[data-testid="Events-Button"]'); | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| verifyRecordingsSection() { | ||||||||||||||||||||||||||||||||||||||
| this.verifyElementIsVisible('[data-testid="Recordings-Link"]'); | ||||||||||||||||||||||||||||||||||||||
| this.verifyElementIsVisible('[data-testid="RecordingsCard-img"]'); | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| verifyEventTypes() { | ||||||||||||||||||||||||||||||||||||||
| this.verifyElementIsVisible('[data-testid="EventTypesCard"]'); | ||||||||||||||||||||||||||||||||||||||
| this.verifyElementIsVisible('[data-testid="EventTypesCard-others"]'); | ||||||||||||||||||||||||||||||||||||||
| this.verifyElementIsVisible('[data-testid="CommunityMeeting-Card"]'); | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| switchToFilter(label) { | ||||||||||||||||||||||||||||||||||||||
| cy.get('[data-testid="EventFilters-main"]') | ||||||||||||||||||||||||||||||||||||||
| .contains( | ||||||||||||||||||||||||||||||||||||||
| '[data-testid="EventFilter-click"]', | ||||||||||||||||||||||||||||||||||||||
| new RegExp(`^${label}$`, 'i'), | ||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||
| .click(); | ||||||||||||||||||||||||||||||||||||||
| cy.wait(500); | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
| cy.wait(500); | |
| cy.get('[data-testid="EventPostItem-main"]').should('be.visible'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replace arbitrary wait with deterministic synchronization.
Using cy.wait(500) hides timing bugs and flakes whenever the DOM takes longer than half a second (or faster, if debounce finishes earlier). Please wait on a real condition—e.g., chain a .should(...) that asserts the clicked filter’s active state or wait on the network request powering the tab—so Cypress can retry automatically and the test remains stable.
switchToFilter(label) {
cy.get('[data-testid="EventFilters-main"]')
.contains(
'[data-testid="EventFilter-click"]',
new RegExp(`^${label}$`, 'i'),
)
- .click();
- cy.wait(500);
+ .click()
+ .should('have.attr', 'aria-pressed', 'true'); // adjust to the actual active-state indicator
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| switchToFilter(label) { | |
| cy.get('[data-testid="EventFilters-main"]') | |
| .contains( | |
| '[data-testid="EventFilter-click"]', | |
| new RegExp(`^${label}$`, 'i'), | |
| ) | |
| .click(); | |
| cy.wait(500); | |
| } | |
| switchToFilter(label) { | |
| cy.get('[data-testid="EventFilters-main"]') | |
| .contains( | |
| '[data-testid="EventFilter-click"]', | |
| new RegExp(`^${label}$`, 'i'), | |
| ) | |
| .click() | |
| .should('have.attr', 'aria-pressed', 'true'); // adjust to the actual active-state indicator | |
| } |
🤖 Prompt for AI Agents
In cypress/pages/events.js around lines 29 to 37, replace the hard-coded
cy.wait(500) with deterministic synchronization: after clicking the filter,
chain a .should(...) that asserts the clicked filter entered its active state
(for example check the active CSS class or an aria attribute on the filter
element) OR wait on the network request that loads the filtered data by adding a
cy.intercept(...) and cy.wait('@alias') before proceeding; ensure the assertion
or network wait is chained to the existing get/contains/click flow so Cypress
can retry until the condition is met.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@anushkaaaaaaaa Please look into this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!
Copilot
AI
Dec 30, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The method verifyEventCardLinkByTitleAndHref is defined but never used in the test file. This suggests either incomplete test coverage or unnecessary code. If this method is intended for future use, consider removing it until needed to keep the codebase clean. If specific event validation is needed, add corresponding tests.
Copilot
AI
Dec 30, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The method verifyEventCardHrefByIndex is defined but never used in the test file. This suggests either incomplete test coverage or unnecessary code. Consider removing it until needed to keep the codebase clean.
| verifyEventCardHrefByIndex(index, expectedHref) { | |
| cy.get('[data-testid="EventPostItem-main"]') | |
| .eq(index) | |
| .find('a[data-testid="EventPostItem-link"]') | |
| .should('have.attr', 'href', expectedHref); | |
| } |
Copilot
AI
Dec 30, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The methods verifyAllEventCards(), verifyUpcomingEventCards(), and verifyRecordedEventCards() all delegate to the same verifyEventCards() method without any distinction. This creates unnecessary duplication and doesn't provide tab-specific validation. Consider either removing these wrapper methods and calling verifyEventCards() directly from tests, or add tab-specific assertions to validate that the correct subset of events is displayed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Strengthen host link validation.
The method only verifies that the href attribute exists but doesn't validate its content. This weak assertion could allow empty or malformed URLs to pass.
Apply this diff to add meaningful validation:
verifyHostLinks() {
cy.get('a[data-testid="TextLink-href"]')
.should('have.length.greaterThan', 0)
.each(($link) => {
- cy.wrap($link).should('have.attr', 'href');
+ cy.wrap($link)
+ .should('have.attr', 'href')
+ .and('not.be.empty')
+ .and('match', /^https?:\/\/.+/);
});
}This ensures hrefs are non-empty and follow a valid URL pattern.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| verifyHostLinks() { | |
| cy.get('a[data-testid="TextLink-href"]') | |
| .should('have.length.greaterThan', 0) | |
| .each(($link) => { | |
| cy.wrap($link).should('have.attr', 'href'); | |
| }); | |
| } | |
| verifyHostLinks() { | |
| cy.get('a[data-testid="TextLink-href"]') | |
| .should('have.length.greaterThan', 0) | |
| .each(($link) => { | |
| cy.wrap($link) | |
| .should('have.attr', 'href') | |
| .and('not.be.empty') | |
| .and('match', /^https?:\/\/.+/); | |
| }); | |
| } |
🤖 Prompt for AI Agents
In cypress/pages/events.js around lines 138 to 144, the verifyHostLinks() helper
only checks that an href attribute exists but not its content; update it to
assert href is non-empty and matches a URL pattern by fetching each link's href
(cy.wrap($link).invoke('attr', 'href')) and then asserting it is truthy/length>0
and matches a reasonable regex (e.g., starts with http:// or https:// or a
protocol-relative or relative path pattern depending on app requirements);
ensure assertions use Cypress should with match or include to fail on empty or
malformed values.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@anushkaaaaaaaa What is the reason behind making it a resolve? For me, it makes sense to have a stronger assertion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please pay attention to the naming. It is really important in order to have maintainable code.
It is a
test file. Do you think we should have anothertestsappended in the naming? It should be simply like:Dashboard Page