top of page

Part 4 - Master the Basics of TypeScript for Effective Playwright Automation - Functions

Updated: Apr 22

Let's say we are building automation tests for our Demo Store. During testing, we often repeat the same steps again and again:


• search for products

• login user

• calculate total price

• validate order success message

• format product text

• verify product category

• process API responses




If we write the same code repeatedly, our script becomes:


• repetitive

• harder to maintain

• difficult to scale

• error-prone


For example, if the login logic changes, we would need to update it everywhere in the code.


This is where functions help us.

A function allows us to group reusable logic into a single block, so we can reuse it multiple times. Instead of writing the same logic repeatedly, we write it once inside a function and call it whenever needed. This makes automation frameworks like Playwright clean, modular, and scalable.

A function is a reusable block of code that performs a specific task.


Think of a function like a small machine:

Input → Processing → Output




Suppose our Demo Store sells both organic and non-organic products.

While writing automation tests, we may need to verify whether a product belongs to the Organic category. Instead of writing the same validation logic in multiple test cases, we create a reusable function.

function isOrganicProduct(productTitle: string): boolean {
 return productTitle.toLowerCase().includes("organic");
}

Calling the function:

console.log(isOrganicProduct("Organic Apple Juice")); console.log(isOrganicProduct("Chocolate Cake"));

Output:

true

false


Now we can reuse this function in multiple automation tests.


Understanding functions becomes easier if we see the two main stages.

  • Function Definition

This is where we define behaviour.

function openDemoShop() {
 console.log("Opening Demo Shop");
}
  • Function Calling


This is where we execute behaviour.

openDemoShop();

Without calling the function, nothing happens.


Function Basic Syntax



Basic Function


When our automation test starts, we may want to log that the website has loaded successfully.

Instead of writing console log repeatedly in every test file, we create a reusable function.

function welcomeMessage() {
 console.log("Welcome to DemoStore");
}
welcomeMessage();

Function with Parameter


Our test automation needs to search for multiple products:


• organic tea

• honey

• green coffee


Instead of creating separate functions for each product, we create one function that accepts a product name dynamically.

function searchProduct(productName: string) {
 console.log("Searching product:", productName);
}
searchProduct("Tea");
searchProduct("Coffee");
searchProduct("Honey");

Function Returning Value


During checkout testing, we must verify whether the price calculation is correct.

Instead of calculating manually in each test case, we create a reusable function, e.g. Use cases in automation:

Verify cart total, validate invoice value, compare UI vs API price

function calculateTotal(price: number, tax: number): number {
 return price + tax;
}
let total = calculateTotal(100, 20);console.log(total);

Use Default Parameter


Suppose our Demo Store applies a default 10% discount if no discount value is provided.

Instead of checking for missing values everywhere, we define a default parameter.

function applyDiscount(price: number, discount: number = 10): number {
 return price - discount;
}
applyDiscount(100);

Use case:

default tax, default discount, default timeout value


Function with Multiple Parameters


While verifying product details, we display both the product name and price together.

Instead of combining values manually everywhere, we create reusable logic.

function createProductLabel(name: string, price: number): string {
 return name + " costs $" + price;
}
console.log(createProductLabel("Tea", 10));

Rest Parameter (Variable Inputs)


A shopping cart may contain multiple items. Sometimes 2 products, sometimes 10.

Instead of limiting the function to fixed inputs, we allow a flexible number of inputs.

function calculateCartTotal(...prices: number[]): number {
 let total = 0; for (let p of prices) {
   total += p;
 }
 return total;
}
calculateCartTotal(100, 200, 300);

Passing an Array to a Function


API often returns a list of products. Automation test may need to validate each product name.

function printProducts(products: string[]): void {
 for (let product of products) {
   console.log(product);
 }}
printProducts(["tea", "coffee"]);

Use case:

loop through search results, validate product list


Passing an Object to a Function


Product usually contains multiple fields:

name price category

Instead of passing each value separately, we pass object.

type Product = { name: string price: number};
function printProduct(product: Product): void {
 console.log(product.name);
}
printProduct({ name: "Tea", price: 100});

Common in API responses.


Calling Function Inside Function


Complex automation logic is often built using smaller, reusable steps.

Format product name before validation.

function formatProductName(name: string): string {
 return name.toUpperCase();
}

Now reuse inside another function.

function processProduct(name: string): void {
 console.log("Processing product");
 let formatted = formatProductName(name);
 console.log(formatted);
}
processProduct("tea");

Arrow Function (Modern Function Syntax)


When building automation tests for our Demo Store, we often need to standardise text before validation.For example, product categories in the UI may appear in different formats:

Organic 
ORGANIC 
organic 
Organic Food 
ORGANIC FOOD

If our automation script compares text exactly as displayed, tests may fail due to case differences. To avoid this problem, we convert text into a consistent format before comparison. This is where a small reusable function helps.


const formatCategory = (category: string): string => {
 return category.toLowerCase();
};

Usage:

console.log(formatCategory("ORGANIC"));
console.log(formatCategory("Organic"));
console.log(formatCategory("organic"));

Output:

organic
organic
organic

Now our automation script can reliably compare values.

Suppose our test verifies the category label displayed on the product page:

UI text:

"ORGANIC"

Expected value:

"organic"

Without formatting, comparison fails. With arrow function:

let actualCategory = "ORGANIC";
if(formatCategory(actualCategory) === "organic"){
 console.log("Category validation passed");
}

Why Arrow Functions are Popular


Arrow functions provide shorter and cleaner syntax. They are widely used in modern frameworks. They make code: more readable, less verbose, easier to maintain


Compare Normal Function vs Arrow Function

Normal function

function formatCategory(category: string): string {
 return category.toLowerCase();
}

Arrow function

const formatCategory = (category: string): string => {
 return category.toLowerCase();
};

Short Arrow Function (Single Line)


When logic is very short, arrow functions can be written on a single line.

const doublePrice = (price: number): number => price * 2;


Callback Function (Dynamic Behaviour)


Sometimes behaviour should change based on test scenario. Example:

One test may convert the product name to uppercase. Another may trim spaces.

Instead of fixing logic inside a function, we allow the caller to decide the behaviour.

function processProduct(name: string, action: Function): void { console.log(name);
 action();
}
processProduct("Tea", function () { console.log("processed");
});

 This is a callback using a normal (anonymous) function


Same example using arrow function (callback + arrow)

processProduct("Tea", () => { console.log("processed");});

Callback Returning Value


Suppose pricing logic changes for different customers.Example:

discount logic, tax logic. We want flexible pricing calculation.

function processPrice(price: number, operation: Function): void {
 let result = operation(price);
 console.log(result);
}
processPrice(100, function(p:number){
 return p * 0.9;
});

Note that function processPrice(...): void means:

👉 This function does not return anything to the outside world

The return value is coming from the callback function, not from the main function.


If you want the main function to return a value


Then change:

function processPrice(price: number, operation: Function): number {
 return operation(price);
}

Now:

let finalPrice = processPrice(100, p => p * 0.9);console.log(finalPrice); // 90

✔ Now value is returned outside


example

processPrice(price, applyDiscount)
processPrice(price, applyTax)
processPrice(price, applyCoupon)

Same function, different logic.


Callback with Parameter


 We may want to perform different actions on a product name, like:


• convert to uppercase

• validate text

• format output


Instead of writing multiple functions, we pass the logic as a callback.


function processProduct(name: string, action: (product:string)=>void): void {
 action(name);
}
processProduct("Tea", function(product){
 console.log(product.toUpperCase());
});

Here:

• "Tea" is passed to processProduct

• processProduct calls action(name)

• Callback receives "Tea" as product

• Output → TEA


Arrow Function Version

processProduct("Tea", product => console.log(product.toUpperCase()));

👉 Main function sends data

👉 Callback receives data and decides what to do


A callback with parameter lets you pass data from one function to another for flexible and reusable logic.


Function Scope


Temporary variables used inside a function should not affect global code.

function example() {
 let message = "hello";
}

Protects data integrity.

Nested Function (Closure)


Sometimes inner logic needs access to outer data.

Example:

store configuration settings.

function outerFunction() {
 let storeName = "DemoStore";
 function innerFunction() {
   console.log(storeName); 
}
 innerFunction();
}

Self Invoking Function (IIFE)


When the application loads, initialization logic runs automatically.

(function () {
 console.log("Store initialized");
})();

Recursive Function


Some calculations repeat until a condition is met.

function factorial(n: number): number {
 if (n == 1) {
   return 1;
 }
 return n * factorial(n - 1);
}


Comments


Never Miss a Post. Subscribe Now!

Thanks for submitting!

©anuradha agarwal

    bottom of page