Advanced JavaScript for QA

Day 3: Functions, Async & Promises

Building Robust Test Automation with OpenCart

Today we'll master JavaScript's power features to create professional test automation. From simple functions to complex async operations - everything through OpenCart testing scenarios.

1.5 Hours
12 QA Engineers
5 Core Concepts

Warm-up: The Async Challenge

Think about this: When testing OpenCart's checkout process, what happens if the payment gateway takes 3 seconds to respond?

🤔 The Problem

In manual testing, you wait. In automation, we need to handle this intelligently!

// What if this takes 3 seconds? const paymentResult = processPayment(); // How do we handle the delay?

Today's Learning Journey

Strings

String manipulation and operations

Functions & Callbacks

Building reusable test components

Async Programming

Why we need it in testing

Promises

Handling future results

Async/Await

Making async code readable

Functions: Your Test Building Blocks

Functions are like reusable test components. Instead of writing the same login code 10 times, we write it once!

🐛 Real QA Scenario: The Login Nightmare

Imagine testing OpenCart's admin panel. You need to login before every test:

❌ Without Functions (Repetitive)

// Test 1: Check products
await page.goto('/admin');
await page.fill('#input-username', 'admin');
await page.fill('#input-password', 'password');
await page.click('button[type="submit"]');
// ... test logic

// Test 2: Check orders  
await page.goto('/admin');
await page.fill('#input-username', 'admin');
await page.fill('#input-password', 'password');
await page.click('button[type="submit"]');
// ... test logic

✅ With Functions (Clean)

async function loginToAdmin() {
    await page.goto('/admin');
    await page.fill('#input-username', 'admin');
    await page.fill('#input-password', 'password');
    await page.click('button[type="submit"]');
}

// Test 1: Check products
await loginToAdmin();
// ... test logic

// Test 2: Check orders
await loginToAdmin();
// ... test logic

Function Declaration

Traditional way to define functions

QA Use: Main test functions, setup/teardown
function loginToAdmin() {
    // login logic
}

Arrow Functions

Modern, concise function syntax

QA Use: Callbacks, short utility functions
const loginToAdmin = () => {
    // login logic
}

Callbacks

Functions passed as parameters

QA Use: Event handlers, async operations
function afterLogin(callback) {
    // login logic
    callback(); // Execute after login
}

🎮 Interactive Demo: Function Factory

Create Your Test Function

Output

Click "Run Function" to see the result!

🤔 Quick Check: Function Understanding

Which function type would you use for a reusable login function in your test suite?

📝 Mini Assignment: Create a Test Utility

Write a function called validateProductDetails that takes a product object and returns true if all required fields are present.

Async Programming: Why We Need It

In web testing, everything takes time. Page loads, API calls, animations - we need to handle these delays intelligently.

🐛 Real QA Scenario: The Loading Race

Testing OpenCart's product search with filters:

❌ The Problem: Race Conditions

// This fails because page isn't loaded yet
await page.click('#search-button');
await page.click('#filter-category'); // Error!

Why it fails: The search results take 2 seconds to load, but our code tries to click the filter immediately.

✅ The Solution: Async Handling

// Wait for the page to be ready
await page.click('#search-button');
await page.waitForSelector('.product-grid');
await page.click('#filter-category'); // Success!

Why it works: We wait for the product grid to appear before proceeding.

🤔 Why Do We Need Async Programming?

Page Loading

Web pages don't load instantly. Elements appear gradually.

API Calls

Server responses take time. Payment processing, data fetching.

Animations

UI animations and transitions need time to complete.

Database Operations

Creating orders, updating inventory takes time.

🎮 Interactive Demo: Async vs Sync

Simulation Output

Click a button to see the difference!

🤔 Quick Check: Async Understanding

When testing a form submission that takes 3 seconds, what should you do?

Promises: Handling Future Results

Promises are like contracts. "I promise to give you a result when this operation completes."

🐛 Real QA Scenario: The Payment Promise

Testing OpenCart's checkout process:

1️⃣ User clicks "Pay Now"

const paymentPromise = processPayment(orderData);
// paymentPromise is a "contract"

2️⃣ Payment Gateway Processes

// Promise is "pending" - processing...

3️⃣ Result Arrives

paymentPromise
    .then(result => console.log('Payment successful!'))
    .catch(error => console.log('Payment failed!'));

📊 Promise States in Testing

Pending

Operation in progress

await page.click('#submit')

Fulfilled

Operation completed successfully

// Element clicked successfully

Rejected

Operation failed

// Element not found

🎮 Interactive Demo: Promise Chain

Step 1: Login

Step 2: Search Product

Step 3: Add to Cart

Promise Chain Output

Click steps to see the promise chain in action!

🤔 Quick Check: Promise Understanding

What happens if a promise is rejected in your test?

Async/Await: Making Async Code Readable

Async/await is syntactic sugar that makes promises look like regular synchronous code.

🐛 Real QA Scenario: The Complete Checkout Flow

Let's compare different approaches to writing the same test:

❌ Promise Chains (Hard to Read)

loginToAdmin()
    .then(() => searchProduct('iPhone'))
    .then(() => addToCart())
    .then(() => proceedToCheckout())
    .then(() => fillShippingDetails())
    .then(() => processPayment())
    .then(() => verifyOrder())
    .catch(error => console.error(error));

✅ Async/Await (Clean & Readable)

async function completeCheckout() {
    try {
        await loginToAdmin();
        await searchProduct('iPhone');
        await addToCart();
        await proceedToCheckout();
        await fillShippingDetails();
        await processPayment();
        await verifyOrder();
        console.log('Checkout completed!');
    } catch (error) {
        console.error('Checkout failed:', error);
    }
}

🎯 Why Async/Await is Better for QA

Readable

Code flows naturally, like reading a test script

Debuggable

Easy to set breakpoints and debug step by step

Error Handling

Simple try/catch blocks for error management

Team Friendly

Even non-developers can understand the flow

🎮 Interactive Demo: Async/Await in Action

Execution Flow

Click to see the difference in execution flow!

🤔 Quick Check: Async/Await Understanding

What keyword do you use to wait for a promise to complete?

📝 Final Assignment: Complete Test Flow

Write an async function that completes a full OpenCart purchase flow: