Skip to content
WordPress

Complete Guide: Setting Up Playwright E2E Testing with Local WordPress

· · 8 min read

Introduction

End-to-end (E2E) testing is crucial for ensuring your WordPress site works correctly from a user’s perspective. In this comprehensive guide, we’ll walk through setting up Playwright, a powerful modern testing framework, with Local (by Flywheel) WordPress development environment. Whether you’re testing a simple blog or a complex BuddyPress community, this guide will get you up and running.

Table of Contents

  1. Prerequisites
  2. Why Playwright for WordPress Testing?
  3. Setting Up Your Environment
  4. Installing Playwright
  5. Configuring Playwright for Local WordPress
  6. Writing Your First Tests
  7. Advanced Testing Scenarios
  8. Debugging and Troubleshooting
  9. Best Practices
  10. Common Issues and Solutions

Prerequisites {#prerequisites}

Before we begin, ensure you have:

  • Local (by Flywheel) installed with at least one WordPress site
  • Node.js (version 16 or higher) and npm installed
  • Basic knowledge of JavaScript
  • A code editor (VS Code recommended)

To check your Node.js version:

node --version  # Should output v16.x.x or higher
npm --version   # Should output 6.x.x or higher

Why Playwright for WordPress Testing? {#why-playwright}

Playwright offers several advantages for WordPress testing:

  • Cross-browser Support: Test on Chromium, Firefox, and WebKit with a single API
  • Auto-wait: Automatically waits for elements to be ready before acting
  • Powerful Selectors: Multiple ways to locate elements reliably
  • Visual Testing: Built-in screenshot and video recording capabilities
  • Fast Execution: Runs tests in parallel for quick feedback
  • Great Developer Experience: Excellent debugging tools and UI mode

Setting Up Your Environment {#environment-setup}

Step 1: Locate Your Local WordPress Site

Local typically stores sites in these locations:

macOS:

~/Local Sites/your-site-name

Windows:

C:\Users\YourName\Local Sites\your-site-name

Step 2: Find Your Site’s URL

In the Local app, find your site’s URL. It’s usually:

  • http://yoursite.local
  • https://yoursite.local (if SSL is enabled)

Step 3: Navigate to Your Site Directory

Open terminal/command prompt and navigate to your site:

# macOS
cd ~/Local\ Sites/your-site-name/app/public

# Windows
cd "C:\Users\YourName\Local Sites\your-site-name\app\public"

Installing Playwright {#installing-playwright}

Step 1: Create a Testing Directory

mkdir playwright-tests
cd playwright-tests

Step 2: Initialize npm Project

npm init -y

Step 3: Install Playwright

npm install --save-dev @playwright/test

Step 4: Install Playwright Browsers

npx playwright install

This downloads browser binaries for Chromium, Firefox, and WebKit.

Step 5: Verify Installation

Create a package.json with test scripts:

{
  "name": "playwright-tests",
  "version": "1.0.0",
  "scripts": {
    "test": "playwright test",
    "test:ui": "playwright test --ui",
    "test:headed": "playwright test --headed",
    "report": "playwright show-report"
  },
  "devDependencies": {
    "@playwright/test": "^1.41.0"
  }
}

Configuring Playwright for Local WordPress {#configuration}

Create playwright.config.js in your playwright-tests directory:

const { devices } = require('@playwright/test');

module.exports = {
  // Test timeout
  timeout: 30000,
  
  // Test retries on failure
  retries: 1,
  
  // Reporter configuration
  reporter: [
    ['html'],
    ['list']
  ],
  
  use: {
    // Your Local WordPress URL
    baseURL: 'http://yoursite.local',
    
    // Ignore HTTPS errors for self-signed certificates
    ignoreHTTPSErrors: true,
    
    // Collect trace on failure
    trace: 'on-first-retry',
    
    // Take screenshot on failure
    screenshot: 'only-on-failure',
    
    // Video recording
    video: 'retain-on-failure',
  },
  
  // Configure projects for different browsers
  projects: [
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
    },
    {
      name: 'firefox',
      use: { ...devices['Desktop Firefox'] },
    },
    {
      name: 'webkit',
      use: { ...devices['Desktop Safari'] },
    },
  ],
};

Handling Local’s SSL Certificates

If your Local site uses HTTPS with self-signed certificates, the ignoreHTTPSErrors: true setting handles this automatically.

Writing Your First Tests {#first-tests}

Basic WordPress Test

Create wordpress-basic.spec.js:

const { test, expect } = require('@playwright/test');

test.describe('WordPress Basic Tests', () => {
  test('homepage loads correctly', async ({ page }) => {
    // Navigate to homepage
    await page.goto('/');
    
    // Check if site title exists
    const siteTitle = page.locator('.site-title');
    await expect(siteTitle).toBeVisible();
    
    // Take a screenshot
    await page.screenshot({ path: 'screenshots/homepage.png' });
  });

  test('admin login works', async ({ page }) => {
    // Go to login page
    await page.goto('/wp-login.php');
    
    // Fill in credentials
    await page.fill('#user_login', 'your-username');
    await page.fill('#user_pass', 'your-password');
    
    // Submit form
    await page.click('#wp-submit');
    
    // Verify login successful
    await expect(page).toHaveURL(/.*wp-admin.*/);
    await expect(page.locator('#wpadminbar')).toBeVisible();
  });

  test('create a new post', async ({ page }) => {
    // Login first
    await page.goto('/wp-login.php');
    await page.fill('#user_login', 'your-username');
    await page.fill('#user_pass', 'your-password');
    await page.click('#wp-submit');
    
    // Navigate to new post
    await page.goto('/wp-admin/post-new.php');
    
    // Fill in post details
    await page.fill('.editor-post-title__input', 'Test Post from Playwright');
    
    // Click into the editor and add content
    await page.click('.block-editor-default-block-appender__content');
    await page.keyboard.type('This is automated test content.');
    
    // Publish post
    await page.click('.editor-post-publish-button__button');
    
    // Confirm publish
    const publishButton = page.locator('.editor-post-publish-button');
    await publishButton.click();
    
    // Verify post published
    await expect(page.locator('.components-snackbar')).toBeVisible();
  });
});

Running Your Tests

# Run all tests
npm test

# Run with UI mode (recommended for development)
npm run test:ui

# Run in headed mode (see the browser)
npm run test:headed

# Run specific test file
npm test wordpress-basic.spec.js

Advanced Testing Scenarios {#advanced-testing}

Testing with Page Objects Pattern

Create page-objects/LoginPage.js:

class LoginPage {
  constructor(page) {
    this.page = page;
    this.usernameInput = page.locator('#user_login');
    this.passwordInput = page.locator('#user_pass');
    this.submitButton = page.locator('#wp-submit');
    this.rememberMe = page.locator('#rememberme');
  }

  async goto() {
    await this.page.goto('/wp-login.php');
  }

  async login(username, password, remember = false) {
    await this.usernameInput.fill(username);
    await this.passwordInput.fill(password);
    
    if (remember) {
      await this.rememberMe.check();
    }
    
    await this.submitButton.click();
    await this.page.waitForURL('**/wp-admin/**');
  }
}

module.exports = { LoginPage };

Using the Page Object:

const { test, expect } = require('@playwright/test');
const { LoginPage } = require('./page-objects/LoginPage');

test('login using page object', async ({ page }) => {
  const loginPage = new LoginPage(page);
  await loginPage.goto();
  await loginPage.login('your-username', 'your-password');
  
  await expect(page.locator('#wpadminbar')).toBeVisible();
});

Testing BuddyPress Features

const { test, expect } = require('@playwright/test');

test.describe('BuddyPress Tests', () => {
  test.beforeEach(async ({ page }) => {
    // Login before each test
    await page.goto('/wp-login.php');
    await page.fill('#user_login', 'your-username');
    await page.fill('#user_pass', 'your-password');
    await page.click('#wp-submit');
  });

  test('post activity update', async ({ page }) => {
    await page.goto('/activity/');
    
    // Post new activity
    const activityInput = page.locator('#whats-new');
    await activityInput.fill('Testing BuddyPress with Playwright!');
    
    // Submit activity
    await page.click('#aw-whats-new-submit');
    
    // Verify activity posted
    await expect(page.locator('.activity-content').first()).toContainText('Testing BuddyPress');
  });

  test('view member profile', async ({ page }) => {
    await page.goto('/members/');
    
    // Click first member
    await page.click('.members-list li:first-child .list-title a');
    
    // Verify profile page loaded
    await expect(page.locator('#item-header')).toBeVisible();
  });
});

Testing WooCommerce

test('add product to cart', async ({ page }) => {
  await page.goto('/shop/');
  
  // Click first product
  await page.click('.products .product:first-child a');
  
  // Add to cart
  await page.click('.single_add_to_cart_button');
  
  // Verify added to cart
  await expect(page.locator('.woocommerce-message')).toContainText('has been added to your cart');
  
  // Go to cart
  await page.click('.cart-contents');
  
  // Verify product in cart
  await expect(page.locator('.cart_item')).toBeVisible();
});

Debugging and Troubleshooting {#debugging}

Using Playwright Inspector

# Run with inspector
npx playwright test --debug

# Debug specific test
npx playwright test wordpress-basic.spec.js --debug

Debugging Tips

  1. Use page.pause() to pause execution:
await page.pause(); // Opens Playwright Inspector
  1. Take screenshots during tests:
await page.screenshot({ path: 'debug.png', fullPage: true });
  1. Use console.log for debugging:
const title = await page.title();
console.log('Page title:', title);
  1. Enable verbose logging:
DEBUG=pw:api npm test

Using Trace Viewer

When a test fails, Playwright creates a trace file:

# View trace
npx playwright show-trace test-results/*/trace.zip

Best Practices {#best-practices}

1. Use Data Attributes for Reliable Selectors

Add data attributes to your WordPress theme:

<button data-test="submit-comment" type="submit">Submit</button>

Then in tests:

await page.click('[data-test="submit-comment"]');

2. Create Reusable Helper Functions

Create helpers/wordpress.js:

async function loginToWordPress(page, username, password) {
  await page.goto('/wp-login.php');
  await page.fill('#user_login', username);
  await page.fill('#user_pass', password);
  await page.click('#wp-submit');
  await page.waitForURL('**/wp-admin/**');
}

async function createPost(page, title, content) {
  await page.goto('/wp-admin/post-new.php');
  await page.fill('.editor-post-title__input', title);
  await page.click('.block-editor-default-block-appender__content');
  await page.keyboard.type(content);
  await page.click('.editor-post-publish-button__button');
  await page.click('.editor-post-publish-button');
}

module.exports = { loginToWordPress, createPost };

3. Use Environment Variables

Create .env file:

WP_USERNAME=your-username
WP_PASSWORD=your-password
WP_BASE_URL=http://yoursite.local

Install dotenv:

npm install --save-dev dotenv

Use in tests:

require('dotenv').config();

const username = process.env.WP_USERNAME;
const password = process.env.WP_PASSWORD;

4. Organize Tests by Feature

playwright-tests/
├── tests/
│   ├── auth/
│   │   └── login.spec.js
│   ├── content/
│   │   ├── posts.spec.js
│   │   └── pages.spec.js
│   └── buddypress/
│       ├── activity.spec.js
│       └── members.spec.js
├── page-objects/
├── helpers/
└── playwright.config.js

5. Use Fixtures for Common Setup

Create custom fixtures:

const base = require('@playwright/test');

exports.test = base.test.extend({
  authenticatedPage: async ({ page }, use) => {
    // Login before test
    await page.goto('/wp-login.php');
    await page.fill('#user_login', 'username');
    await page.fill('#user_pass', 'password');
    await page.click('#wp-submit');
    
    // Use the authenticated page
    await use(page);
    
    // Cleanup after test
    await page.goto('/wp-login.php?action=logout');
  },
});

Common Issues and Solutions {#common-issues}

Issue 1: Cannot Connect to Local Site

Solution: Add to hosts file if needed:

# macOS/Linux: /etc/hosts
# Windows: C:\Windows\System32\drivers\etc\hosts

127.0.0.1   yoursite.local
::1         yoursite.local

Issue 2: SSL Certificate Errors

Solution: Already handled by ignoreHTTPSErrors: true in config.

Issue 3: Tests Timeout

Solution: Increase timeout in config or specific test:

test('slow test', async ({ page }) => {
  test.setTimeout(60000); // 60 seconds
  // ... test code
});

Issue 4: Module Not Found Errors

Solution: Clean install:

rm -rf node_modules package-lock.json
npm install

Issue 5: Elements Not Found

Solution: Use better waiting strategies:

// Wait for element to be visible
await page.waitForSelector('.my-element', { state: 'visible' });

// Wait for network to be idle
await page.waitForLoadState('networkidle');

Continuous Integration

GitHub Actions Example

Create .github/workflows/playwright.yml:

name: Playwright Tests
on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  test:
    timeout-minutes: 60
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
    - uses: actions/setup-node@v3
      with:
        node-version: 18
    - name: Install dependencies
      run: npm ci
    - name: Install Playwright Browsers
      run: npx playwright install --with-deps
    - name: Run Playwright tests
      run: npm test
    - uses: actions/upload-artifact@v3
      if: always()
      with:
        name: playwright-report
        path: playwright-report/
        retention-days: 30

Conclusion

You now have a complete Playwright testing setup for your Local WordPress site! This foundation allows you to:

  • Test critical user flows automatically
  • Catch bugs before they reach production
  • Have confidence when making changes
  • Save time on manual testing

Start with simple tests and gradually build your test suite. Remember, the goal is not 100% coverage but testing the most important user journeys.

Additional Resources

Next Steps

  1. Write tests for your most critical user flows
  2. Set up CI/CD pipeline
  3. Add visual regression testing
  4. Integrate with your deployment process
  5. Share this guide with your team!

Happy testing! 🚀

Varun Dubey
Varun Dubey

We specialize in web design &amp; development, search engine optimization and web marketing, eCommerce, multimedia solutions, content writing, graphic and logo design. We build web solutions, which evolve with the changing needs of your business.