All files / pages CheckoutPage.js

100% Statements 110/110
100% Branches 8/8
100% Functions 7/7
100% Lines 110/110

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 1111x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 1x 1x 1x 1x 1x 5x 5x 5x 1x 1x 1x 1x 1x 1x 1x 1x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 1x 1x 1x 1x 1x 1x 1x 4x 4x 4x 1x 1x 1x 1x 1x 1x 4x 4x 4x 4x 4x 4x 4x 4x 4x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x  
// @ts-check
const { expect } = require('@playwright/test');
const { BasePage } = require('./BasePage');
const { HeaderComponent } = require('./components/HeaderComponent');
 
/**
 * CheckoutPage POM handles order review, address verification, payment, and invoice download.
 */
class CheckoutPage extends BasePage {
  /**
   * @param {import('@playwright/test').Page} page
   */
  constructor(page) {
    super(page);
    this.header = new HeaderComponent(page);
 
    this.addressDetailsHeading = page.getByText('Address Details', { exact: true });
    this.reviewOrderHeading = page.getByText('Review Your Order', { exact: true });
    this.deliveryAddressSection = page.locator('#address_delivery');
    this.billingAddressSection = page.locator('#address_invoice');
    this.orderCommentTextarea = page.locator('textarea[name="message"]');
    this.placeOrderButton = page.getByRole('link', { name: 'Place Order' });
 
    // Payment Form Locators
    this.paymentHeading = page.getByText('Payment', { exact: true });
    this.nameOnCardInput = page.locator('[data-qa="name-on-card"]');
    this.cardNumberInput = page.locator('[data-qa="card-number"]');
    this.cvcInput = page.locator('[data-qa="cvc"]');
    this.expiryMonthInput = page.locator('[data-qa="expiry-month"]');
    this.expiryYearInput = page.locator('[data-qa="expiry-year"]');
    this.payAndConfirmButton = page.locator('[data-qa="pay-button"]');
    this.orderPlacedHeading = page.locator('[data-qa="order-placed"]');
    this.orderSuccessMessage = page.getByText(/order (?:has been placed successfully|has been confirmed)/i).first();
    this.downloadInvoiceLink = page.getByRole('link', { name: 'Download Invoice' });
    this.continueButton = page.locator('[data-qa="continue-button"]');
  }
 
  /**
   * Verifies checkout address and review sections are visible.
   */
  async verifyCheckoutSections() {
    await expect(this.deliveryAddressSection).toBeVisible({ timeout: 15000 });
    await expect(this.billingAddressSection).toBeVisible({ timeout: 15000 });
  }
 
  /**
   * Asserts address fields match user registration information.
   * @param {any} user
   */
  async verifyAddressDetails(user) {
    await this.verifyCheckoutSections();
    for (const section of [this.deliveryAddressSection, this.billingAddressSection]) {
      await expect(section).toContainText(`${user.title}. ${user.firstName} ${user.lastName}`);
      await expect(section).toContainText(user.company);
      await expect(section).toContainText(user.address1);
      if (user.address2) await expect(section).toContainText(user.address2);
      await expect(section).toContainText(user.city);
      await expect(section).toContainText(user.state);
      await expect(section).toContainText(user.zipcode);
      await expect(section).toContainText(user.country);
      await expect(section).toContainText(user.mobile);
    }
  }
 
  /**
   * Enters order comment and clicks 'Place Order'.
   * @param {string} comment
   */
  async placeOrder(comment = 'Please deliver safely.') {
    await this.orderCommentTextarea.fill(comment);
    await this.placeOrderButton.click();
  }
 
  /**
   * Fills credit card payment details and confirms order.
   * @param {{ nameOnCard: string, cardNumber: string, cvc: string, expiryMonth: string, expiryYear: string }} payment
   */
  async payAndConfirm(payment) {
    await this.nameOnCardInput.fill(payment.nameOnCard);
    await this.cardNumberInput.fill(payment.cardNumber);
    await this.cvcInput.fill(payment.cvc);
    await this.expiryMonthInput.fill(payment.expiryMonth);
    await this.expiryYearInput.fill(payment.expiryYear);
    await this.payAndConfirmButton.click();
    await expect(this.orderPlacedHeading).toBeVisible();
    await expect(this.orderSuccessMessage).toBeVisible();
  }
 
  /**
   * Downloads the invoice and verifies suggested filename.
   * @returns {Promise<import('@playwright/test').Download>}
   */
  async downloadInvoice() {
    const downloadPromise = this.page.waitForEvent('download');
    await this.downloadInvoiceLink.click();
    const download = await downloadPromise;
    expect(download.suggestedFilename()).toMatch(/invoice.*\.txt/i);
    await expect(download.failure()).resolves.toBeNull();
    return download;
  }
 
  /**
   * Clicks 'Continue' button on order confirmation page.
   */
  async clickContinue() {
    await this.continueButton.click();
  }
}
 
module.exports = { CheckoutPage };