diff --git a/tests/__screenshots__/Desktop-Chrome/home.spec.ts/column-name-hidden.png b/tests/__screenshots__/Desktop-Chrome/home.spec.ts/column-name-hidden.png new file mode 100644 index 0000000..a7f5d61 Binary files /dev/null and b/tests/__screenshots__/Desktop-Chrome/home.spec.ts/column-name-hidden.png differ diff --git a/tests/__screenshots__/Desktop-Chrome/home.spec.ts/column-visibility-menu.png b/tests/__screenshots__/Desktop-Chrome/home.spec.ts/column-visibility-menu.png new file mode 100644 index 0000000..540cfb0 Binary files /dev/null and b/tests/__screenshots__/Desktop-Chrome/home.spec.ts/column-visibility-menu.png differ diff --git a/tests/__screenshots__/Desktop-Chrome/home.spec.ts/homepage.png b/tests/__screenshots__/Desktop-Chrome/home.spec.ts/homepage.png new file mode 100644 index 0000000..00f2582 Binary files /dev/null and b/tests/__screenshots__/Desktop-Chrome/home.spec.ts/homepage.png differ diff --git a/tests/__screenshots__/Desktop-Chrome/home.spec.ts/initial-data.png b/tests/__screenshots__/Desktop-Chrome/home.spec.ts/initial-data.png new file mode 100644 index 0000000..00f2582 Binary files /dev/null and b/tests/__screenshots__/Desktop-Chrome/home.spec.ts/initial-data.png differ diff --git a/tests/__screenshots__/Desktop-Chrome/home.spec.ts/search-results-empty.png b/tests/__screenshots__/Desktop-Chrome/home.spec.ts/search-results-empty.png new file mode 100644 index 0000000..ad8aa14 Binary files /dev/null and b/tests/__screenshots__/Desktop-Chrome/home.spec.ts/search-results-empty.png differ diff --git a/tests/__screenshots__/Desktop-Chrome/home.spec.ts/search-results-valid.png b/tests/__screenshots__/Desktop-Chrome/home.spec.ts/search-results-valid.png new file mode 100644 index 0000000..41db8db Binary files /dev/null and b/tests/__screenshots__/Desktop-Chrome/home.spec.ts/search-results-valid.png differ diff --git a/tests/__screenshots__/Mobile-Chrome/home.spec.ts/contributions-sorted.png b/tests/__screenshots__/Mobile-Chrome/home.spec.ts/contributions-sorted.png new file mode 100644 index 0000000..d04ec53 Binary files /dev/null and b/tests/__screenshots__/Mobile-Chrome/home.spec.ts/contributions-sorted.png differ diff --git a/tests/__screenshots__/Mobile-Chrome/home.spec.ts/homepage.png b/tests/__screenshots__/Mobile-Chrome/home.spec.ts/homepage.png new file mode 100644 index 0000000..e4aaeff Binary files /dev/null and b/tests/__screenshots__/Mobile-Chrome/home.spec.ts/homepage.png differ diff --git a/tests/__screenshots__/Mobile-Chrome/home.spec.ts/search-results-empty.png b/tests/__screenshots__/Mobile-Chrome/home.spec.ts/search-results-empty.png new file mode 100644 index 0000000..4c245bc Binary files /dev/null and b/tests/__screenshots__/Mobile-Chrome/home.spec.ts/search-results-empty.png differ diff --git a/tests/__screenshots__/Mobile-Chrome/home.spec.ts/search-results-valid.png b/tests/__screenshots__/Mobile-Chrome/home.spec.ts/search-results-valid.png new file mode 100644 index 0000000..bb35e2a Binary files /dev/null and b/tests/__screenshots__/Mobile-Chrome/home.spec.ts/search-results-valid.png differ diff --git a/tests/home.spec.ts b/tests/home.spec.ts index 9a46a02..ba4525f 100644 --- a/tests/home.spec.ts +++ b/tests/home.spec.ts @@ -16,7 +16,7 @@ test.describe('Homepage', () => { { tag: ['@smoke', '@desktop', '@mobile'], }, - async () => { + async ({ page }) => { await test.step('should has data in the row', async () => { await homePage.assertContentInRowIsVisible(); }); @@ -28,6 +28,10 @@ test.describe('Homepage', () => { await test.step('should has faq section', async () => { await homePage.assertFaqSectionIsVisible(); }); + + await test.step('should match homepage visual snapshot', async () => { + await expect(page).toHaveScreenshot('homepage.png', { maxDiffPixelRatio: 0.02 }); + }); } ); @@ -36,7 +40,7 @@ test.describe('Homepage', () => { { tag: ['@smoke', '@desktop', '@mobile'], }, - async () => { + async ({ page }) => { await test.step('When user search with a valid keyword', async () => { await homePage.fillAndSearch('depapp'); }); @@ -44,6 +48,7 @@ test.describe('Homepage', () => { await test.step('Then table should show expected result', async () => { await expect(homePage.getUsername('depapp')).toBeVisible(); await expect(homePage.emptyState).not.toBeVisible(); + await expect(page).toHaveScreenshot('search-results-valid.png', { maxDiffPixelRatio: 0.02 }); }); await test.step('When user search with non existance keyword', async () => { @@ -52,6 +57,7 @@ test.describe('Homepage', () => { await test.step('Then it should show the empty state', async () => { await expect(homePage.emptyState).toBeVisible(); + await expect(page).toHaveScreenshot('search-results-empty.png', { maxDiffPixelRatio: 0.02 }); }); } ); @@ -65,12 +71,13 @@ test.describe('Homepage', () => { { tag: ['@smoke', '@desktop'], }, - async ({ isMobile }) => { + async ({ isMobile, page }) => { test.skip(isMobile, '// NOTE: TEST CASE FOR DESKTOP ONLY'); await test.step('When user click toggle column button', async () => { await expect(homePage.toggleColumnVisibilityBtn).toBeVisible(); await homePage.toggleColumnVisibilityBtn.click(); + await expect(page).toHaveScreenshot('column-visibility-menu.png', { maxDiffPixelRatio: 0.02 }); }); await test.step('And perform toggle hide column "Name"', async () => { @@ -81,6 +88,68 @@ test.describe('Homepage', () => { await test.step('Then column "Name" should become invisible', async () => { await expect(homePage.getName('Sandhika Galih')).not.toBeVisible(); + await expect(page).toHaveScreenshot('column-name-hidden.png', { maxDiffPixelRatio: 0.02 }); + }); + } + ); + + test( + 'should sort by contributions on desktop', + { + tag: ['@smoke', '@desktop'], + }, + async ({ isMobile, page }) => { + test.skip(isMobile, '// NOTE: TEST CASE FOR DESKTOP ONLY'); + + await test.step('Given navigate to homepage', async () => { + await homePage.navigate(); + }); + + await test.step('Should show initial data', async () => { + await homePage.assertContentInRowIsVisible(); + await expect(page).toHaveScreenshot('initial-data.png', { maxDiffPixelRatio: 0.02 }); + }); + + await test.step('When user click header "Contributions"', async () => { + await homePage.contributionsHeader.click(); + }); + + await test.step('And select sort direction Asc', async () => { + await homePage.sortAscButton.click(); + }); + + await test.step('Then data row should sort by contributions', async () => { + await homePage.assertContributionsAreSorted(); + }); + } + ); + + test( + 'should sort by contributions on mobile', + { + tag: ['@smoke', '@mobile'], + }, + async ({ isMobile }) => { + test.skip(!isMobile, '// NOTE: TEST CASE FOR MOBILE ONLY'); + + await test.step('Given navigate to homepage', async () => { + await homePage.navigate(); + }); + + await test.step('Should show initial data', async () => { + await homePage.assertContentInRowIsVisible(); + }); + + await test.step('When user click "Sort" button', async () => { + await homePage.sortButton.click(); + }); + + await test.step('And select sort "By Contributions"', async () => { + await homePage.sortByContributionsButton.click(); + }); + + await test.step('Then data row should sort by contributions', async () => { + await homePage.assertContributionsAreSorted(); }); } ); diff --git a/tests/models/home.page.ts b/tests/models/home.page.ts index 0c0aabf..c1ba861 100644 --- a/tests/models/home.page.ts +++ b/tests/models/home.page.ts @@ -7,6 +7,11 @@ export class HomePage { searchInput: Locator; toggleColumnVisibilityBtn: Locator; columnNameCheckbox: Locator; + contributionsHeader: Locator; + sortButton: Locator; + sortByContributionsButton: Locator; + sortAscButton: Locator; + firstRowContributions: Locator; constructor(private readonly page: Page) { this.searchInput = page.getByPlaceholder(/search username/i); @@ -17,10 +22,16 @@ export class HomePage { this.emptyState = page.getByText(/no results/i); this.toggleColumnVisibilityBtn = page.getByRole('button', { name: /view/i, + exact: true }); this.columnNameCheckbox = page.getByRole('menuitemcheckbox', { name: /name/i, }); + this.contributionsHeader = page.getByRole('button', { name: /contributions/i, exact: true }); + this.sortButton = page.getByRole('button', { name: /sort/i }); + this.sortByContributionsButton = page.getByRole('menuitem', { name: /by contributions/i }); + this.sortAscButton = page.getByRole('menuitem', { name: /ascending/i }); + this.firstRowContributions = page.locator('tbody tr').first().locator('td').nth(6); } async navigate() { @@ -51,4 +62,30 @@ export class HomePage { async assertFaqSectionIsVisible() { await expect(this.faqHeading).toBeVisible(); } + + async sortByContributionsDesktop() { + await this.contributionsHeader.waitFor({ state: 'visible' }); + await this.contributionsHeader.click(); + await this.sortAscButton.waitFor({ state: 'visible' }); + await this.sortAscButton.click(); + } + + async sortByContributionsMobile() { + await this.sortButton.waitFor({ state: 'visible' }); + await this.sortButton.click(); + await this.sortByContributionsButton.waitFor({ state: 'visible' }); + await this.sortByContributionsButton.click(); + } + + async assertContributionsAreSorted() { + // Wait for sorting to complete + await this.page.waitForTimeout(1000); + // Take a snapshot of the sorted table + await expect(this.page).toHaveScreenshot('contributions-sorted.png', { maxDiffPixelRatio: 0.02 }); + // Verify first row has the lowest contribution count + await this.firstRowContributions.waitFor({ state: 'visible' }); + const firstContribution = await this.firstRowContributions.textContent(); + const contributionCount = parseInt(firstContribution || '0', 10); + expect(contributionCount).toBeLessThanOrEqual(100); + } }