🕒 Topics to Cover
1. `.first()` vs `.nth()` locators
Understanding element selection strategies
2. `.allTextContents()`
Fetching multiple values efficiently
3. Dropdown handling
Using `.selectOption()` method
4. Debug with `page.pause()`
Interactive debugging techniques
5. Checkbox/Radio handling
State management and validation
6. Advanced Assertions
Truthy/Falsy validations
🔹 Real-time QA Scenarios
1. `.first()` vs `.nth()` Locators
// Selecting first email field
await page.locator('.js-input-column input').first().fill("qa_first@example.com");
// Selecting specific field by index
await page.locator('.js-input-column input').nth(0).fill("qa_nth0@example.com");
💡 QA Angle: Selecting the first text box on signup page vs picking specific field.
👉 Interview Q: What's the difference between `.first()`, `.nth(0)`, and `.all()`?
Answer:
• .first(): Selects the first element in a collection. More semantic and readable.
• .nth(0): Selects the element at index 0 (first element). Functionally same as .first().
• .all(): Returns all matching elements as an array of locators.
Key Difference: .first() and .nth(0) return a single locator, while .all() returns an array of locators.
• .first(): Selects the first element in a collection. More semantic and readable.
• .nth(0): Selects the element at index 0 (first element). Functionally same as .first().
• .all(): Returns all matching elements as an array of locators.
Key Difference: .first() and .nth(0) return a single locator, while .all() returns an array of locators.
2. Extracting Multiple Titles
// Get all product titles
const allTitles = await page.locator('.product-title a').allTextContents();
console.log(allTitles);
// Validate no blank titles
const hasBlankTitles = allTitles.some(title => !title.trim());
await expect(hasBlankTitles).toBeFalsy();
💡 QA Angle: Collect all product names on homepage → validate none are blank/duplicates.
👉 Interview Q: What's the difference between `.textContent()` and `.allTextContents()`?
Answer:
• .textContent(): Works with a single element and returns a string.
• .allTextContents(): Works with multiple elements and returns an array of strings.
Example:
• .textContent(): Works with a single element and returns a string.
• .allTextContents(): Works with multiple elements and returns an array of strings.
Example:
const singleText = await page.locator('.title').textContent(); // Returns: "Product Name"const allTexts = await page.locator('.title').allTextContents(); // Returns: ["Product 1", "Product 2", "Product 3"]
3. Dropdown Handling
// Change currency dropdown
const dropdown = page.locator("select#currency-selector");
await dropdown.selectOption("INR");
// Verify price updates
const priceElement = page.locator('.product-price').first();
await expect(priceElement).toContainText("₹");
💡 QA Angle: Change site currency from default USD → INR, verify price update.
👉 Interview Q: What happens if you use `.fill()` instead of `.selectOption()` on a <select> element?
Answer:
Using .fill() on a select element will:
• Type the text into the field
• NOT change the selected option
• May cause test failures
Correct approach: Always use .selectOption() for dropdowns to properly change the selection.
Using .fill() on a select element will:
• Type the text into the field
• NOT change the selected option
• May cause test failures
Correct approach: Always use .selectOption() for dropdowns to properly change the selection.
4. Debug Pause
// Pause execution for debugging
await page.pause();
// Continue with form interaction
await page.locator('#email1').fill("test@example.com");
💡 QA Angle: Stop test mid-way, inspect product details form in PrestaShop.
👉 Interview Q: How is `page.pause()` different from running with `PWDEBUG=1`?
Answer:
• page.pause(): Pauses execution at a specific point in your test code.
• PWDEBUG=1: Runs the entire test in debug mode with step-by-step execution from start.
Use cases:
• Use page.pause() when you want to inspect a specific moment
• Use PWDEBUG=1 when you want to debug the entire test flow
• page.pause(): Pauses execution at a specific point in your test code.
• PWDEBUG=1: Runs the entire test in debug mode with step-by-step execution from start.
Use cases:
• Use page.pause() when you want to inspect a specific moment
• Use PWDEBUG=1 when you want to debug the entire test flow
5. Checkbox/Radio Handling
// Check newsletter subscription
const newsletter = page.locator('#newsletter-checkbox');
await newsletter.check();
await expect(newsletter).toBeChecked();
// Uncheck if needed
await newsletter.uncheck();
await expect(newsletter).not.toBeChecked();
// Radio button selection
await page.locator('input[name="gender"][value="female"]').check();
await expect(page.locator('input[name="gender"][value="female"]')).toBeChecked();
💡 QA Angle: On checkout page, check/uncheck "Subscribe to Newsletter".
👉 Interview Q: What's the difference between `isChecked()`, `toBeChecked()`, and `check()`?
Answer:
• isChecked(): Returns the current state as a boolean (true/false).
• toBeChecked(): An assertion that validates the element is checked.
• check(): Action that changes the state by checking the element.
Example:
• isChecked(): Returns the current state as a boolean (true/false).
• toBeChecked(): An assertion that validates the element is checked.
• check(): Action that changes the state by checking the element.
Example:
const state = await checkbox.isChecked(); // Returns: true/falseawait expect(checkbox).toBeChecked(); // Assertionawait checkbox.check(); // Action
6. Assertions with Falsy/Truthy
// Check promo code field is hidden initially
const promoCode = page.locator('#promo-code');
await expect(promoCode).toBeFalsy(); // field should not exist initially
// Show promo code field after certain action
await page.locator('#show-promo').click();
await expect(promoCode).toBeVisible();
// Validate form submission
const isFormValid = await page.locator('#terms-checkbox').isChecked();
await expect(isFormValid).toBeTruthy();
💡 QA Angle: Check that promo code box is hidden until a certain step.
👉 Interview Q: When would you use `toBeFalsy()` vs `toBeHidden()`?
Answer:
• toBeFalsy(): Checks if an element doesn't exist or is null/undefined.
• toBeHidden(): Checks if an element exists but is not visible (display: none, visibility: hidden, etc.).
Use cases:
• Use toBeFalsy() when testing if an element should not exist in DOM
• Use toBeHidden() when testing if an element exists but is hidden by CSS
• toBeFalsy(): Checks if an element doesn't exist or is null/undefined.
• toBeHidden(): Checks if an element exists but is not visible (display: none, visibility: hidden, etc.).
Use cases:
• Use toBeFalsy() when testing if an element should not exist in DOM
• Use toBeHidden() when testing if an element exists but is hidden by CSS
🎯 Practice Exercises
Exercise 1: Multi-field Form Validation
Create a test that:
- Fills the first email field using `.first()`
- Fills the second email field using `.nth(1)`
- Selects a country from dropdown
- Checks the newsletter checkbox
- Validates all fields are properly filled
Exercise 2: Currency Conversion Test
Create a test that:
- Changes currency to INR using dropdown
- Extracts all product prices using `.allTextContents()`
- Validates all prices show ₹ symbol
- Changes to EUR and validates € symbol
Exercise 3: Form State Management
Create a test that:
- Validates promo code field is initially hidden
- Triggers promo code field visibility
- Fills and validates promo code
- Tests radio button selection
- Uses `page.pause()` for debugging