Page Object Model(POM) is an object design pattern implementations of Page factory in protractor, where web pages are represented as Typescript classes, and the various elements on the page are defined as a method on the PO classes. All reusable methods are stored in libraries
The folder structure of the POM framework in protractor: 
Page Object class contains all the page object(web elements) for a particular page. For every page present application, we have to write the Page Object class.
Page Object class name should end with PO so that it will be easy for the user to identify the page object class.
Below code is an example for the Page objects in typescript, we will discuss how to form page object in javascript in the next topic.
public static googleSearch = element(by.name("btnK"))
// using method
feelingLucky(){
return element(by.name("btnI"))
}
Complete code for the Page Objects in protractor
import { browser, element, by } from "protractor";
export class GooglePO{
// using variables
public static searchBar = element(by.name("q"))
public static googleSearch = element(by.name("btnK"))
// using method
feelingLucky(){
return element(by.name("btnI"))
}
}
Handle Hidden division Pop Up / Calendar Pop up using Protractor
Sometimes we may have repeating test steps across the script; in such cases, we have to create those steps as re-usable methods. Re-usable methods can be used across multiple scripts in the framework
searchGoogle(searchTerm :string){
GooglePO.searchBar.sendKeys(searchTerm)
GooglePO.searchButton.click()
}
Complete code for Library files
import { GooglePO } from "../PO/GooglePO";
export class GoogleLib{
searchGoogle(searchTerm :string){
GooglePO.searchBar.sendKeys(searchTerm)
GooglePO.searchButton.click()
}
}
Spec files will have our test codes; it is important to have a separate folder for every category.
import { browser } from "protractor";
import { GoogleLib } from "../Lib/GoogleLib";
import { GooglePO } from "../PO/GooglePO";
let googleLib = new GoogleLib()
describe("Page Object Model in Protractor",function(){
browser.ignoreSynchronization = true; // for non-angular websites
it("Search Google",function(){
browser.get("https://google.com")
googleLib.searchGoogle("chercher tech")
});
it("click operation",function(){
browser.get("https://google.com")
GooglePO.feelingLucky().click()
});
});
Conf file for the test
exports.config = {
// launch locally when fields directConnect and seleniumAddress are not provided
chromeDriver: 'D:/Eclipse progs/driverserver/chromedriver.exe',
seleniumServerJar: 'D:/Eclipse progs/jars/selenium-server-standalone-3.11.0.jar',
specs: ['D:Protractor DemoJSFilesLocationPageObjectModel_CherCherTechspecs est.js'],
capabilities: {
browserName: 'chrome'
}
}
By this time, You might have got an idea of how the Page object model will work. If you are only looking for this, then your search ends now.
But if you are looking for enhancements in the page object model, then please do follow the following topics as well.
keep the above structure; I will mention what are the changes to make in the existing file or new file if required
Protractor Interview Questions
While creating a POM framework, it is important to read data from the external files, so in the below code, we would be reading values from JSON File.
In this JSON class, we have to write methods to read and write the data from the JSON file.
JSON data file named as 'cherchertech.json'
{
"name": "karthiq",
"age": 27,
"gender": "Male",
"website": "cherchertech protractor"
}
JSON file Reading Code.
// import the fs module
const fs = require('fs');
export class JSONutility{
public readData(path:string, propertyToRetrieve:string){
// read the file into raw data
let rawdata = fs.readFileSync(path);
// parse the raw data into meaningful JSON format
let author = JSON.parse(rawdata);
let websiteValue = author["website"]
return websiteValue
}
}
Now read the 'website' property from the JSON file as our search term. Please make changes in existing it block or add this as new it block in the test spec file
We have to pass the path of the JSON file and the 'property' to read from the JSON file to make the JSON reading for common to all.
it("Search Google with JSON reading",function(){
browser.get("https://google.com")
let searchTerm = jsonutil.readData("./cherchertech.json", "website")
googleLib.searchGoogle(searchTerm)
});
Scroll an element Into View using JavaScript Executor in Protractor
Data could be stored in Excel sheets as well in Page Object Model(POM); in such cases, we have to create a utility class to read the data from the excel sheet file in POM.
Excel reading utility in typescript protractor
import {Workbook, Row, Cell, Worksheet} from 'exceljs';
const wb:Workbook = new Workbook();
export class EXCELutility{
public readExcel(excelPath:string, sheetName:string,
rowNumber:number, columNumber:number){
// read xlsx file type and return entire function after receiving return
return wb.xlsx.readFile(excelPath).then(function(){
//sheet object
let sheet:Worksheet = wb.getWorksheet(sheetName);
//row objct
let rowObject:Row = sheet.getRow(rowNumber);
// cell object
let cellObject:Cell = rowObject.getCell(columNumber);
// get value from cell
let cellvalue = cellObject.value
// return valu from function
return cellvalue
})
}
}
import { browser } from "protractor";
import { GoogleLib } from "../Lib/GoogleLib";
import { EXCELutility } from "../utility/excelutility";
let googleLib = new GoogleLib()
let excelutil = new EXCELutility();
describe("Page Object Model in Protractor",function(){
browser.ignoreSynchronization = true; // for non-angular websites
it("Search Google",function(){
browser.get("https://chercher.tech")
excelutil.readExcel("test.xlsx", "Sheet1", 2, 1).then(function(searchTerm){
console.log(searchTerm)
googleLib.searchGoogle(searchTerm.toString())
})
});
});
It is crucial to do the in the execution of the framework; In protractor, we will be using the Winston logging package to track the logs.
import {createLogger, format, transports} from 'winston'
export class Logger{
static logger = createLogger({
level: 'info',
format: format.simple(),
transports: [
// - Write to all logs with level `info` and above to `combined.log`
new transports.File({ filename: 'combined.log'}),
// - Write all logs error (and above) to Console/terminal
new transports.Console()
]
});
}
The above logger will write the logs to console and files as well.
Test File and there is no change to the conf file
import { browser } from "protractor";
import { GoogleLib } from "../Lib/GoogleLib";
import { EXCELutility } from "../utility/excelutility";
import { Logger } from "../loggingutility/winstonutility";
let googleLib = new GoogleLib()
let excelutil = new EXCELutility();
let log = Logger.logger
describe("Page Object Model in Protractor",function(){
browser.ignoreSynchronization = true; // for non-angular websites
it("Search Google",function(){
// logging using log methods
log.log("warn", "warn message from test")
browser.get("https://google.com")
// logging using info() methods
log.info("Opening Google webpage")
excelutil.readExcel("test.xlsx", "Sheet1", 2, 1).then(function(searchTerm){
// logging with log method
log.log("info", "The value read from Excel is :"+searchTerm)
console.log(searchTerm)
googleLib.searchGoogle(searchTerm.toString())
})
});
});
I am Pavankumar, Having 8.5 years of experience currently working in Video/Live Analytics project.
Hi, You can cross-check below steps- 1) Check if you properly imported the PO file. or 2) Check whether you have created an object of the PO file. or 3) Check whether the object variable is written correctly.
Hi KarthiQ, Can you please add any videos or article for protractor with Cucumberjs - that would really help many people . Thanks, B.V.Naveen
Hi. Have you already done this topic abot POM in JavaScript?
Hi onotolei, I am intended to do, even i have few paragraphs written on this article but i have commented them as I need to write new article about the JS and POM. I will write it soon.
Hi Karthik, Firstly, thank you the detailed tutorial. I'm trying to follow your approach and implement the same. I'm having trouble directly calling the methods from the PO folder as your calling on your sample code. Ex: I have a PO file abc.po.ts and it has a method export class TcpPO{ //page object using variable public static PageHeader = element(by.xpath("//h1[contains(text(),'simple')]")); //page object using a method create(){ return element(by.id("test")); } When i try to call this method in my spec class AbcPO. create().click(); // this line is throwing me an error {{ Property 'createNewTCP' does not exist on type 'typeof TcpPO'.ts(2339) }} Please help me with this Thanks krishna