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

My performance branch141 #85

Closed
wants to merge 8 commits into from
9 changes: 9 additions & 0 deletions cypress.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const { defineConfig } = require("cypress");

module.exports = defineConfig({
e2e: {
setupNodeEvents(on, config) {
// implement node event listeners here
},
},
});
11 changes: 11 additions & 0 deletions cypress/fixtures/performanceModule.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@


{
"localAppURL": "https://bjo.kax.mybluehost.me/website_db5da506/sample-page/",
"statusCode": 200,
"mouseDownToBeSelected": "Prefetch on Mouse Down",
"mouseHoverToBeSelected": "Prefetch on Mouse Hover (Recommended)",
"requestCount": 0,
"forceReload": true
}

27 changes: 27 additions & 0 deletions cypress/support/commands.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// ***********************************************
// This example commands.js shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************
//
//
// -- This is a parent command --
// Cypress.Commands.add('login', (email, password) => { ... })
//
//
// -- This is a child command --
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
//
//
// -- This is a dual command --
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
//
//
// -- This will overwrite an existing command --
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })


270 changes: 270 additions & 0 deletions cypress/support/pageObjects/performancePageLocators.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,270 @@
class performancePageLocators {
//Locators
_linkPrefetchText = '.newfold-link-prefetch';
_dropDownForLinkPrefetch = '.nfd-select__button-label';
_visitSiteButton = 'a.nfd-button.nfd-bg-white';
_samplePageButton = '.wp-block-pages-list__item__link';
_mouseHoverElement = 'ul.nfd-select__options > li:nth-child(1)';
_mouseDownElement = 'ul.nfd-select__options > li:nth-child(2)';
_excludeKeywordInputField = '#link-prefetch-ignore-keywords';
_isToggleEnabled = '.nfd-toggle--checked';

//All the methods related to performance page.
verifyIfLinkPreFectchIsDisplayed() {
cy.get(this._linkPrefetchText)
.scrollIntoView()
.should('be.visible');
}

verifyIfToggleIsEnabled() {
cy.get(this._isToggleEnabled).then(($toggle) => {
if ($toggle.attr('aria-checked') === 'false') {
cy.wrap($toggle).click();
}
});

cy.get(this._isToggleEnabled).should(
'have.attr',
'aria-checked',
'true'
);
}

verifyTextOfDropDownDesktop(
mouseDownToBeSelected,
mouseHoverToBeSelected
) {
cy.get(this._dropDownForLinkPrefetch).should(($el) => {
const text = $el.text().trim();
expect([
mouseDownToBeSelected,
mouseHoverToBeSelected,
]).to.include(text);
});
}

interceptCallForMouseDownWithoutExclude(selectedDropDown, url, statusCode) {
const forceReload = true;

// Start by intercepting the API request
cy.intercept('GET', url).as('apiRequest');

// Get the dropdown element text
cy.get(this._dropDownForLinkPrefetch).then(($buttonLabel) => {
const selectedText = $buttonLabel.text().trim();

// Adjust command timeout if needed
Cypress.config('defaultCommandTimeout', 4000);

// Check if the correct dropdown option is selected
if (selectedText === selectedDropDown) {
cy.log('Second option is already selected. Proceeding with the test...');
cy.get(this._dropDownForLinkPrefetch).should('have.text', selectedDropDown);
} else {
cy.log('Second option is not selected. Selecting the second option...');
// Select the second option
cy.get(this._dropDownForLinkPrefetch).click();
cy.get(this._mouseDownElement).click();
cy.get(this._dropDownForLinkPrefetch).should('have.text', selectedDropDown);
}

// Clear the input field
cy.get(this._excludeKeywordInputField).clear();

// Visit the site and handle navigation
cy.get(this._visitSiteButton)
.invoke('removeAttr', 'target') // Remove target to prevent opening in a new tab
.click();

// Optionally, reload the page if necessary (only if you want to reset the state)
cy.reload(forceReload);

// Navigate to the sample page and wait for the API request to complete
cy.get(this._samplePageButton).click();
cy.wait('@apiRequest');

// Assert the API response status code
cy.get('@apiRequest')
.its('response.statusCode')
.should('eq', statusCode);

// Go back and then go back again
cy.go('back');
cy.go('back');
});
}

interceptCallForMouseDownWithExclude(selectedDropDown, url, requestCount) {
const forceReload = true;
Cypress.config('defaultCommandTimeout', 4000);
cy.intercept('GET', url).as('apiRequest');

// Extract page name function
const extractPageName = (url) => {
const pageName = url.split('/').filter(Boolean).pop();
cy.log('Extracted page name:', pageName);
expect(pageName).to.not.be.empty;
return pageName;
};

// Action to visit site and check request count
const visitSiteAndCheckRequestCount = (url, pageName) => {
cy.get(this._excludeKeywordInputField)
.clear()
.type(pageName);

cy.intercept('GET', url).as('apiRequest');
cy.get(this._visitSiteButton)
.invoke('removeAttr', 'target')
.click({ force: true });
cy.reload(forceReload);
cy.get(this._samplePageButton).click();
cy.wrap(requestCount).should('equal', 0);
cy.go('back').then(() => {
cy.go('back');
});
};

// Function for dropdown interaction logic
const handleDropdownSelection = () => {
cy.get(this._dropDownForLinkPrefetch).then(($buttonLabel) => {
const selectedText = $buttonLabel.text().trim();

if (selectedText === selectedDropDown) {
cy.log('Second option is already selected. Proceeding with the test...');
cy.get(this._dropDownForLinkPrefetch).should('have.text', selectedDropDown);
} else {
cy.log('Second option is not selected. Selecting the second option...');
cy.get(this._dropDownForLinkPrefetch).click();
cy.get(this._mouseDownElement).click();
cy.get(this._dropDownForLinkPrefetch).should('have.text', selectedDropDown);
}

cy.get(this._visitSiteButton)
.invoke('removeAttr', 'target')
.click();

cy.get(this._samplePageButton)
.invoke('prop', 'href')
.then((url) => {
const pageName = extractPageName(url);
cy.go('back');

visitSiteAndCheckRequestCount(url, pageName);
});
});
};
handleDropdownSelection(); // Call the refactored function
}

interceptCallForMouseHoverWithoutExclude(selectedDropDown, url, statusCode) {
const forceReload = true;
Cypress.config('defaultCommandTimeout', 4000);
cy.intercept('GET', url).as('apiRequest');

// Action to visit site, trigger mouseover, and check the status code
const visitSiteAndCheckStatusCode = () => {
cy.get(this._excludeKeywordInputField).clear();
cy.get(this._visitSiteButton)
.invoke('removeAttr', 'target')
.click();
cy.reload(forceReload);
cy.get(this._samplePageButton).trigger('mouseover');
//cy.get('.wp-block-pages-list__item__link').trigger('mouseover');
cy.wait('@apiRequest');
cy.get('@apiRequest')
.its('response.statusCode')
.should('eq', statusCode);
cy.go('back');
};

// Function for dropdown interaction logic
const handleDropdownSelection = () => {
cy.get(this._dropDownForLinkPrefetch).then(($buttonLabel) => {
const selectedText = $buttonLabel.text().trim();

if (selectedText === selectedDropDown) {
cy.log('First option is already selected. Proceeding with the test...');
cy.get(this._dropDownForLinkPrefetch).should('have.text', selectedDropDown);
} else {
cy.log('First option is not selected. Selecting the first option...');
cy.get(this._dropDownForLinkPrefetch).click();
cy.get(this._mouseHoverElement).click();
cy.get(this._dropDownForLinkPrefetch).should('have.text', selectedDropDown);
}

// Visit site and check API response
visitSiteAndCheckStatusCode();
});
};

handleDropdownSelection(); // Call the refactored function
}

interceptCallForMouseHoverWithExclude(selectedDropDown, url, requestCount) {
const forceReload = true;
Cypress.config('defaultCommandTimeout', 4000);
cy.intercept('GET', url).as('apiRequest');

// Extract page name function
const extractPageName = (url) => {
const pageName = url.split('/').filter(Boolean).pop();
cy.log('Extracted page name:', pageName);
expect(pageName).to.not.be.empty;
return pageName;
};

// Action to visit site and check request count
const visitSiteAndCheckRequestCount = (url, pageName) => {
cy.get(this._excludeKeywordInputField)
.clear()
.type(pageName);

cy.intercept('GET', url).as('apiRequest');
cy.get(this._visitSiteButton)
.invoke('removeAttr', 'target')
.click({ force: true });

cy.reload(forceReload);
cy.get(this._samplePageButton).trigger('mouseover');
cy.wrap(requestCount).should('equal', 0);
cy.go('back').then(() => {
cy.go('back');
});
};

// Function for dropdown interaction logic
const handleDropdownSelection = () => {
cy.get(this._dropDownForLinkPrefetch).then(($buttonLabel) => {
const selectedText = $buttonLabel.text().trim();

if (selectedText === selectedDropDown) {
cy.log('First option is already selected. Proceeding with the test...');
cy.get(this._dropDownForLinkPrefetch).should('have.text', selectedDropDown);
} else {
cy.log('First option is not selected. Selecting the first option...');
cy.get(this._dropDownForLinkPrefetch).click();
cy.get(this._mouseHoverElement).click();
cy.get(this._dropDownForLinkPrefetch).should('have.text', selectedDropDown);
}

// Interact with the sample page and extract URL
cy.get(this._visitSiteButton)
.invoke('removeAttr', 'target')
.click();

cy.get(this._samplePageButton)
.invoke('prop', 'href')
.then((url) => {
const pageName = extractPageName(url);
cy.go('back');

visitSiteAndCheckRequestCount(url, pageName);
});
});
};

handleDropdownSelection(); // Call the refactored function
}
}
export default performancePageLocators;
61 changes: 61 additions & 0 deletions presentation/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Automation Framework Enhancement

## Introduction
We've made slight modifications to our existing automation framework to make it more efficient, maintainable, and scalable. This document outlines the changes and benefits of the new approach.

## Old Approach
Previously, the framework used basic automation scripts with hardcoded locators, leading to duplication and maintenance challenges. Locators were spread across the test scripts, making them harder to modify and causing potential errors in large test suites.

## What is POM (Page Object Model)?
The **Page Object Model (POM)** is a design pattern that centralizes locators and methods for a specific page into a dedicated class. This allows the test scripts to interact with the page objects rather than dealing with raw HTML or elements directly.

### Benefits of POM:
- **Reuse locators** across different test cases.
- **Modify locators in one place**, reducing the effort for maintenance.
- **Centralized management** of page interactions to improve readability and scalability.

## Implementing POM
We introduced the Page Object Model design pattern to centralize locators and methods, reducing duplication and improving maintainability. With POM, locators can be updated in a single place, minimizing errors and making the framework easier to scale

### How POM Works:
- **POM is a design pattern where locators and methods for a specific page are centralized into a class.**
- Each class contains all the methods and locators needed to interact with the page and verify its behavior.
- Test scripts interact with the page objects instead of directly manipulating raw HTML or page elements.

### Key Components:

1. **Module-Wise JSON for Static Data:**
- Stores constant data (e.g., strings, values) for tests.
- Updates to the data only need to be done in one place, which automatically applies across all tests using that data.

2. **Locators Class for Page Elements:**
- Each page has its own dedicated Locators class, ensuring modularity.
- Updates to locators are reflected across all tests that use those locators.

3. **Test Class Incorporates Data and Methods:**
- Test classes import and use the data and locators, keeping them separate from the test logic itself.

## Benefits of the New Approach

### ✅ Reduced Maintenance Effort:
Changes in locators or static data require only a single update, significantly reducing maintenance time and the likelihood of errors.

### ✅ Improved Reusability:
Common methods and locators are reusable across different test cases, improving efficiency and reducing redundancy.

### ✅ Scalability:
The framework is built to scale easily, supporting new pages and tests as the project grows without significant refactoring.

### ✅ Cleaner, More Maintainable Code:
The modular structure of the framework decouples test logic, data, and locators, making the code easier to read, maintain, and extend.

### ✅ Reduced Risk of Errors:
Centralizing the management of locators and static data reduces the risk of errors that can occur when locators are duplicated or incorrectly updated in multiple places.

## Conclusion
By implementing the Page Object Model (POM), we have significantly improved the efficiency, maintainability, and scalability of our automation framework. The benefits of centralized locators, reusable data, and clear modularization are evident. This new approach will enable the team to:
- **Reduce errors** by managing locators and data centrally.
- **Speed up updates** by modifying locators or data in a single place.
- **Scale the framework** to accommodate new pages and tests as the project grows.

With these improvements, our framework is more robust, adaptable, and easier to maintain, supporting the long-term success of the project
Loading
Loading