Circular reference can create a problem in your Automation Framework!
Md Maruf Mallick
(Serving Notice Period) Automation Test Engineer| Playwright with JavaScript| Cucumber| Selenium with Java| Rest Assured| Git| Jenkins(CI/CT)| JIRA| ALM.
Recently I came across a problem in my JavaScript based Playwright automation framework and after doing a R&D I got to know about the concept of "Circular Reference"! Now the question is how the circular reference is creating the problems in Automation framework and how can someone overcome this situation?
To need to know about this please go through it.
A circular reference in JavaScript occurs when two or more objects reference each other directly or indirectly, creating a cycle. This can happen with variables, objects, functions, or modules. Circular references can lead to problems such as:
When developing a Playwright automation framework with Cucumber, circular references can arise if page objects depend on each other directly. Refactoring to eliminate these circular references is essential for maintaining a clean and maintainable codebase. Here's how you can refactor your framework:
Problem Example
Consider you have two page objects: LoginPage and DashboardPage, where each page object references the other, leading to a circular dependency.
// loginPage.js
const DashboardPage = require('./dashboardPage');
class LoginPage {
??? constructor(page) {
??????? this.page = page;
??????? this.dashboardPage = new DashboardPage(page);
??? }
async login() {
??????? // Login logic
??????? await this.dashboardPage.navigateToDashboard();
??? }
}
module.exports = LoginPage;?
// dashboardPage.js
const LoginPage = require('./loginPage');
class DashboardPage {
??? constructor(page) {
??????? this.page = page;
??????? this.loginPage = new LoginPage(page);
??? }
??? async navigateToDashboard() {
??????? // Navigation logic
??????? await this.loginPage.login();
??? }
}
module.exports = DashboardPage;
?If you develop code like this it will create the problem of "Circular Reference".
Refactoring Strategy:
Using an Intermediary Service
Create a service class to manage interactions between page objects, breaking the direct circular reference.
Define Page Objects:
// loginPage.js
=====================================================
class LoginPage {
constructor(page) {
this.page = page;
}
async login() {
领英推荐
// Login logic
}
}
module.exports = LoginPage;
// dashboardPage.js
class DashboardPage {
constructor(page) {
this.page = page;
}
async navigateToDashboard() {
// Navigation logic
}
}
module.exports = DashboardPage;
Create the Intermediary Service:
========================================================
// pageService.js
const LoginPage = require('./loginPage');
const DashboardPage = require('./dashboardPage');
class PageService {
constructor(page) {
this.page = page;
this.loginPage = new LoginPage(page);
this.dashboardPage = new DashboardPage(page);
}
async loginAndNavigate() {
await this.loginPage.login();
await this.dashboardPage.navigateToDashboard();
}
}
module.exports = PageService;
Use the Service in Your Test:
=======================================================
// index.js
const { chromium } = require('playwright');
const PageService = require('./pageService');
(async () => {
const browser = await chromium.launch();
const page = await browser.newPage();
const pageService = new PageService(page);
await pageService.loginAndNavigate();
await browser.close();
})();