Skip to content

Commit

Permalink
Added Tests for Menu Button in Mobile (#43)
Browse files Browse the repository at this point in the history
1. Added Test scripts to validate Menu button that replaces navigation Bar in the Mobile devices
2. Updated the Playwright config(both) to specifically run tests on a mobile viewport for Android devices.
3. Cleaned up the code by separating the repeatable shared functionalities, such as the 'You need help now' section, the website name, and the navigation bar.
  • Loading branch information
varshakrishna-hippo authored Mar 3, 2025
1 parent d0e0685 commit 8f17388
Show file tree
Hide file tree
Showing 8 changed files with 259 additions and 98 deletions.
3 changes: 3 additions & 0 deletions src/e2e/CareLeavers.E2ETests/playwright-ci.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ export default defineConfig({
use: {
browserName: 'chromium',
...devices['Pixel 8'],
isMobile: true,
viewport: { width: 412, height: 914 },
userAgent: devices['Pixel 8']?.userAgent ?? devices['Pixel 7']?.userAgent,
},
},
{
Expand Down
3 changes: 3 additions & 0 deletions src/e2e/CareLeavers.E2ETests/playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ export default defineConfig({
use: {
browserName: 'chromium',
...devices['Pixel 8'],
isMobile: true,
viewport: { width: 412, height: 914 },
userAgent: devices['Pixel 8']?.userAgent ?? devices['Pixel 7']?.userAgent,
},
},
{
Expand Down
16 changes: 12 additions & 4 deletions src/e2e/CareLeavers.E2ETests/src/helpers/urls-to-check.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
export const pagesToTest = [
'/home', // Home page
'/all-support', // About page
];
// List of pages that will have common functionality across the site
// such as WebsiteName Link, Navigation Bar, Cookies, and Footers
export const commonPagesToTest = [
'/home',
'/all-support',
];

// List of helpline-related links to test-Only certain pages will have this link
export const helplineLinksToTest = [
'/home',
'/all-support',
];
154 changes: 150 additions & 4 deletions src/e2e/CareLeavers.E2ETests/src/pages/BasePage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,74 @@ import { Page,Locator, expect, BrowserContext, Cookie } from '@playwright/test';
export class BasePage {
protected readonly page: Page;

//Locator for the Website Title navigation Link
public readonly WebsiteNameLink: Locator;

// Locators for cookie banner and buttons
public readonly cookieBanner: Locator;
public readonly acceptButton: Locator;
public readonly rejectButton: Locator;

//Locators for Navigation Bar
public readonly navLinkHome: Locator;
public readonly navLinkAllSupport: Locator;
public readonly navLinkYourRights: Locator;
public readonly navLinkLeavingCareGuides: Locator;
public readonly navLinkHelplines: Locator;

//Locators for Navigation Bar-Mobile Menu
public readonly hamburgerMenuIcon: Locator;
public readonly mobileMenuLinks: Locator;
public readonly mobileMenuContainer: Locator;
public readonly closeMenuButton: Locator;

//Locators for helplines-If you need Help at the bottom of the page
public readonly helplineLink: Locator;
public readonly ifYouNeedHelpSection: Locator;

//Locators for web page Footers
public readonly footer: Locator;
public readonly footerLinks: Locator;
public readonly cookiePolicyLinkInFooter: Locator;
public readonly licenceLogo: Locator;

constructor(page: Page) {
this.page = page;
//Locator for the Website Title navigation Link
this.WebsiteNameLink = page.locator('a.dfe-header__link--service').nth(1);

// Locators for cookie banner and buttons
this.cookieBanner = page.locator('.govuk-cookie-banner');
this.acceptButton = page.locator('#accept-cookie');
this.rejectButton = page.locator('#reject-cookie');
this.rejectButton = page.locator('#reject-cookie');

//Locators for Navigation Bar
this.navLinkHome = page.locator('a.dfe-header__navigation-link', { hasText: "Home" });
this.navLinkAllSupport = page.locator('a.dfe-header__navigation-link', { hasText: "All support" });
//update locators
this.navLinkYourRights = page.locator('[role="link"][aria-label="Your rights"]');
this.navLinkLeavingCareGuides = page.locator('[role="link"][aria-label="Leaving care guides"]');
this.navLinkHelplines = page.locator('[role="link"][aria-label="Helplines"]');

//Locators for Navigation Bar-Mobile Menu
this.hamburgerMenuIcon = page.locator('#menu-toggle');
this.mobileMenuContainer = page.locator('#header-navigation');
this.mobileMenuLinks = page.locator('.dfe-header__navigation-list a');
this.closeMenuButton = page.locator('#close-menu');

//Locators for helplines-If you need Help at the bottom of the page
this.helplineLink = page.locator('p.govuk-body a.govuk-hyperlink');
this.ifYouNeedHelpSection = page.locator('#If-you-need-help-now');

//Locators for web page Footers
this.footer = page.locator('footer');
this.footerLinks = page.locator('footer a');
this.cookiePolicyLinkInFooter = page.locator('a.govuk-footer__link[href="/pages/cookie-policy"]');
this.licenceLogo = page.locator('svg.govuk-footer__licence-logo');

}

// Navigation method
// Navigates to the specified URL and waits for the page to load.
async navigateTo(url: string) {
await this.page.goto(url, { waitUntil: 'networkidle' });
}
Expand All @@ -36,7 +91,7 @@ export class BasePage {
await expect(this.cookieBanner).not.toBeVisible();
}
async rejectCookies() {
await expect(this.rejectButton).toBeVisible({ timeout: 10000 });
await expect(this.rejectButton).toBeVisible();
await this.rejectButton.click();
// Ensure the banner disappears
await expect(this.cookieBanner).not.toBeVisible();
Expand Down Expand Up @@ -71,11 +126,102 @@ export class BasePage {
value: 'expired',
domain: new URL(baseURL).hostname, // Extract domain from BASE_URL
path: '/',
expires: Date.now() / 1000 - 10, // Set to past time to expire
expires: Date.now() / 1000 - 10, // Set to Past time to expire
secure: true,
httpOnly: true,
sameSite: 'Strict'
}
]);
}

// Navigation Bar functionality
// Helper method to ensure the menu is visible and reopens it if needed
async ensureMenuIsVisible() {
// Check if the menu is visible, if not, click the hamburger menu to open it
const isMenuVisible = await this.mobileMenuContainer.isVisible();
if (!isMenuVisible) {
await this.hamburgerMenuIcon.click();
await expect(this.mobileMenuContainer).toBeVisible(); // Ensure it becomes visible
}
}

//Verify Navigation Bar functionality
async verifyNavigation(isDesktop: boolean) {
if (isDesktop) {
// Verify desktop navigation is visible
await expect(this.page.locator('#header-navigation')).toBeVisible();

const navLinks = [this.navLinkHome, this.navLinkAllSupport /* add other nav links here */];
for (const link of navLinks) {
const href = await link.getAttribute('href');
if (!href) throw new Error('Link does not have an href attribute');

await link.click();
await this.page.waitForURL(new RegExp(href));
}
}
else {
// Click on the hamburger menu to open the mobile menu
await expect(this.hamburgerMenuIcon).toBeVisible();
await this.hamburgerMenuIcon.click();

// Wait and verify that the mobile menu is visible
await expect(this.mobileMenuContainer).toBeVisible();

// Verify the mobile menu links
const mobileLinksCount = await this.mobileMenuLinks.count();
expect(mobileLinksCount).toBeGreaterThan(0);

// Close the mobile menu
await expect(this.closeMenuButton).toBeVisible();
await this.closeMenuButton.click();

// Ensure the menu is closed
await expect(this.mobileMenuContainer).not.toBeVisible();

// click each link and ensure the menu is visible each time
const links = [
{ index: 0, href: '/home' },
{ index: 1, href: '/all-support' },
/*{ index: 2, href: '/status' },
{ index: 3, href: '/guides-advice' },
{ index: 4, href: '/helplines' },*/
];

for (const link of links) {
await this.ensureMenuIsVisible(); // Ensure the menu is visible before clicking
await expect(this.mobileMenuLinks.nth(link.index)).toHaveAttribute('href', link.href);
await this.mobileMenuLinks.nth(link.index).click();
await this.page.waitForURL(new RegExp(link.href));
}
}
}

async verifyFooterLinks() {
//Ensure the footer is visible
await expect(this.footer).toBeVisible();

// Verify the "Cookie Policy" link(in Footer)
const cookiePolicyLink = this.footer.locator('a.govuk-footer__link[href="/pages/cookie-policy"]');
await expect(this.cookiePolicyLinkInFooter).toBeVisible();
await expect(this.cookiePolicyLinkInFooter).toContainText('Cookie Policy');
await expect(this.cookiePolicyLinkInFooter).toHaveAttribute('href', '/pages/cookie-policy');

// Verify the footer logo and licence description
await expect(this.licenceLogo).toBeVisible();
const licenceDescription = this.footer.locator('.govuk-footer__licence-description');
await expect(licenceDescription).toBeVisible();
await expect(licenceDescription).toContainText(/All content is available under the/);

// Verify the Footer links-Crown copyright link and Open Government Licence link
const footerLinksCount = await this.footerLinks.count();
expect(footerLinksCount).toBeGreaterThan(0);

for (let i = 0; i < footerLinksCount; i++) {
const link = this.footerLinks.nth(i);
await expect(link).toBeVisible();
const href = await link.getAttribute('href');
expect(href).not.toBeNull();
}
}
}
100 changes: 22 additions & 78 deletions src/e2e/CareLeavers.E2ETests/src/pages/HomePage.ts
Original file line number Diff line number Diff line change
@@ -1,56 +1,39 @@
import { Page, Locator, expect } from '@playwright/test';
import { BasePage } from './BasePage';
import exp from "node:constants";

export class HomePage extends BasePage {
private supportForCareLeaversLink: Locator;
// Main Header Sections Locators
private mainHeading: Locator;
private firstHeaderParagraph: Locator;
private footer: Locator;

private supportHeading: Locator;

//Sections Locators
private whoIsThisForSection: Locator;
private findSupportSection: Locator;
private helpfulGuidesSection: Locator;
private ifYouNeedHelpSection: Locator;
private helplineLink: Locator;
private footerLinks: Locator;
private homeNavLink: Locator;
private supportForCareLeaversNav: Locator;
private yourRightsNav: Locator;
private leavingCareGuidesNav: Locator;
private helplinesNav: Locator;
private knowWhatSupportSection: Locator;
private GuidesSection: Locator;

//Support cards Sections
private supportCards: Locator;

constructor(page: Page) {
super(page);

//Website title
this.supportForCareLeaversLink = page.locator('a.dfe-header__link--service').nth(1);

let headerSection = page.locator('div#main-header-container')
let contentSection = page.locator('div#main-content-container')

// Main Header section
this.mainHeading = page.locator('h1');
this.firstHeaderParagraph = headerSection.locator('p.govuk-body').first();
this.footer = page.locator('footer');
this.supportHeading = page.locator('h1.govuk-heading-xl');
let headerSection = page.locator('div#main-header-container')
this.firstHeaderParagraph = headerSection.locator('p.govuk-body').first();

// Main Content Sections
this.whoIsThisForSection = page.locator('#Who-is-this-support-for-');
this.findSupportSection = page.locator('#Find-the-right-support');
this.ifYouNeedHelpSection = page.locator('#If-you-need-help-now');
this.helplinesNav = page.locator('[role="link"][aria-label="Helplines"]');
this.helplineLink = page.locator('p.govuk-body a.govuk-hyperlink');
//update locators
this.helpfulGuidesSection = page.locator('#helpful-guides');
this.footerLinks = page.locator('footer a');
this.homeNavLink = page.locator('a.dfe-header__navigation-link', { hasText: "Home" });
this.supportForCareLeaversNav = page.locator('a.dfe-header__navigation-link', { hasText: "All support" });
//update locators
this.yourRightsNav = page.locator('[role="link"][aria-label="Your rights"]');
this.leavingCareGuidesNav = page.locator('[role="link"][aria-label="Leaving care guides"]');
this.knowWhatSupportSection = page.locator('#know-what-support');//update locators
this.GuidesSection = page.locator('#helpful-guides');//update locators

// Generic locator for all cards on the home page
this.supportCards = page.locator('.hf-card-container');

}

async openHomePage() {
Expand All @@ -60,66 +43,27 @@ export class HomePage extends BasePage {

async assertPageElements() {
await this.validateURLContains('/home');

await expect(this.supportForCareLeaversLink).toHaveText(/Support for/i);
// Check if the main heading is visible
await expect(this.mainHeading).toHaveText("Get support if you've been in care");

// Validate first paragraph
await expect(this.firstHeaderParagraph).toContainText("Starting life as an adult can be challenging");

// Check if the "who is this for" section is visible
await expect(this.whoIsThisForSection).toContainText('support for');
// Check if the element has a specific class
await expect(this.page.locator('#Who-is-this-support-for-')).toHaveClass(/govuk-heading-l/);

await expect(this.footer).toContainText("Open Government Licence v3.0");
//to add back when the helpine link is added to mock
// await expect(this.helplineLink).toHaveAttribute('href', 'helplines');

}

async verifySectionsVisibility() {
await expect(this.supportForCareLeaversLink).toBeVisible();
await expect(this.supportHeading).toBeVisible();
await expect(this.firstHeaderParagraph).toBeVisible();
await expect(this.whoIsThisForSection).toBeVisible();
await expect(this.findSupportSection).toBeVisible();
await expect(this.ifYouNeedHelpSection).toBeVisible();
//to add back when the helpine link is added to mock
//await expect(this.helplineLink).toBeVisible();

/*
await expect(this.whatSupportCanYouGetSection).toBeVisible();
await expect(this.helpfulGuidesSection).toBeVisible();
*/
}

async verifyFooterLinks() {
const footerLinksCount = await this.footerLinks.count();
expect(footerLinksCount).toBeGreaterThan(0);

for (let i = 0; i < footerLinksCount; i++) {
const link = this.footerLinks.nth(i);
await expect(link).toBeVisible();
const href = await link.getAttribute('href');
expect(href).not.toBeNull();
}
}

async verifyNavigation() {

await this.homeNavLink.click();
await this.page.waitForURL(/\/home/);

await this.supportForCareLeaversNav.click();
await this.page.waitForURL(/\/all-support/);

/* update locators
await this.yourRightsNav.click();
await this.page.waitForURL(/\/your-rights/);
await this.leavingCareGuidesNav.click();
await this.page.waitForURL(/\/leaving-care/);
await this.helplinesNav.click();
await this.page.waitForURL(/\/helplines/);
*/
}

async clickSupportCard(cardTitle: string, expectedUrl: string) {
// Find the card with the matching title and Click
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { test, expect } from '@playwright/test';
import { BasePage } from '../pages/BasePage';
import { pagesToTest } from '../helpers/urls-to-check';
import { commonPagesToTest } from '../helpers/urls-to-check';

// Main test to validate cookie banner
test.describe('Cookie Banner Functionality', () => {
pagesToTest.forEach((path) => {
commonPagesToTest.forEach((path) => {
test(`Validate cookie banner on ${path}`, async ({ page, context }) => {
const basePage = new BasePage(page);

Expand All @@ -31,7 +31,7 @@ test.describe('Cookie Banner Functionality', () => {

// Test to reject cookies
test.describe('Reject Cookie Functionality', () => {
pagesToTest.forEach((path) => {
commonPagesToTest.forEach((path) => {
test(`Reject cookie banner on ${path}`, async ({ page, context }) => {
const basePage = new BasePage(page);

Expand Down
Loading

0 comments on commit 8f17388

Please sign in to comment.