How to Run End-to-End Tests with Playwright in PropertyWebBuilder

To run E2E tests with Playwright in the PropertyWebBuilder Rails application, execute the playwright:reset, playwright:server, and playwright:test Rake tasks in the e2e environment to orchestrate the multi-tenant test database, Rails server, and browser automation suite.

PropertyWebBuilder is a multi-tenant SaaS platform built on Ruby on Rails that provides real estate website management. The repository ships with a fully integrated Playwright testing stack designed specifically for its multi-tenant architecture, allowing developers to validate tenant isolation, authentication flows, and admin UI interactions through automated browser testing.

Playwright Configuration Architecture

The test runner configuration lives in playwright.config.js at the repository root. This file defines the testing environment without using Playwright’s built-in webServer option, because Rails must be started manually through Rake tasks to support the BYPASS_ADMIN_AUTH mode and multi-tenant sub-domain routing.

Key configuration details include:

  • Test directory./tests/e2e contains all spec files
  • Global setup./tests/e2e/global-setup.js runs once before the suite to verify the E2E database contains seeded tenant data
  • Base URLhttp://tenant-a.e2e.localhost:3001 targets the Rails e2e environment sub-domain
  • ParallelismfullyParallel: true for local development; CI forces single-worker execution via workers: process.env.CI ? 1 : undefined
  • Artifacts – Screenshots capture on failure, while traces and videos record on the first retry, all stored under playwright-report/
  • Browser projects – Chromium runs by default; Firefox and WebKit configurations exist but remain commented out

Rails Rake Tasks for Test Orchestration

All E2E workflow orchestration is centralized in lib/tasks/playwright.rake. These tasks handle database state, server startup, and test execution while printing admin credentials from db/yml_seeds/e2e_users.yml for manual testing reference.

Task Function Command
playwright:reset Drops, creates, migrates, and seeds the e2e database (restricted to RAILS_ENV=e2e) RAILS_ENV=e2e bin/rails playwright:reset
playwright:server Starts Rails on port 3001 with standard admin authentication RAILS_ENV=e2e bin/rails playwright:server
playwright:server_bypass_auth Starts server with BYPASS_ADMIN_AUTH=true to disable admin login for fast integration tests RAILS_ENV=e2e bin/rails playwright:server_bypass_auth
playwright:test Executes scripts/run-e2e-tests.sh to load config and run Playwright RAILS_ENV=e2e bin/rails playwright:test
playwright:ui Launches Playwright’s interactive UI mode RAILS_ENV=e2e bin/rails playwright:ui
playwright:headed Runs tests in headed mode for visual debugging RAILS_ENV=e2e bin/rails playwright:headed
playwright:report Opens the HTML test report using npx playwright show-report RAILS_ENV=e2e bin/rails playwright:report

Test Suite Organization and Fixtures

The tests/e2e/ directory mirrors the application’s functional areas and contains shared infrastructure for multi-tenant testing:


tests/e2e/
├── admin/            # Admin dashboard integration tests

├── auth/             # Multi-tenant authentication and session isolation

├── public/           # Public-facing property browsing and search

├── fixtures/
│   ├── helpers.js    # Reusable Playwright functions (login, navigation)

│   └── test-data.js  # Centralized tenant, user, and route constants

└── global-setup.js   # Pre-suite database verification

The fixtures/test-data.js file exports constants including TENANTS, ADMIN_USERS, PROPERTIES, and ROUTES that remain synchronized with db/seeds/e2e_seeds.rb. The fixtures/helpers.js file implements critical testing primitives such as loginAsAdmin(page, adminUser), goToTenant(page, tenant, path), and CSRF handling utilities.

Multi-Tenant Isolation Testing

Because PropertyWebBuilder serves multiple tenants from a single Rails instance, the E2E suite validates strict isolation across three layers:

  • Sub-domain routing – Each tenant resolves to distinct hosts like tenant-a.e2e.localhost:3001 and tenant-b.e2e.localhost:3001
  • Session isolation – Cookies are scoped per sub-domain; authentication on tenant A never grants access to tenant B
  • Data isolation – Settings, properties, and users are seeded per tenant, with explicit test cases attempting cross-tenant access to verify protection mechanisms

The helper goToTenant(page, tenant, path) centralizes URL construction, while expectToBeLoggedIn and expectToBeOnLoginPage assertions verify correct authentication state per tenant.

Running E2E Tests Locally

Execute the full testing workflow using the Rake task suite. This ensures the database and server are properly configured for the multi-tenant E2E environment.

First, reset and seed the database:

RAILS_ENV=e2e bin/rails playwright:reset

Next, start the Rails server in a dedicated terminal. Choose standard authentication for full flow testing:

RAILS_ENV=e2e bin/rails playwright:server

Or use bypass mode for faster integration tests that skip admin login:

RAILS_ENV=e2e bin/rails playwright:server_bypass_auth

Finally, run the test suite:

RAILS_ENV=e2e bin/rails playwright:test

To run a specific spec file, pass the path after --:

RAILS_ENV=e2e bin/rails playwright:test -- tests/e2e/public/property-search.spec.js

For debugging failures, use the debug flag or UI mode:

npx playwright test --debug
RAILS_ENV=e2e bin/rails playwright:ui

After execution, generate and view the HTML report:

RAILS_ENV=e2e bin/rails playwright:report

Code Example: Admin Authentication Flow

The following excerpt from tests/e2e/auth/admin_login.spec.js demonstrates the multi-tenant login pattern using shared fixtures:

import { test, expect } from '@playwright/test';
import { TENANTS, ADMIN_USERS } from '../fixtures/test-data';
import { loginAsAdmin, expectToBeLoggedIn } from '../fixtures/helpers';

test('Tenant A admin can log in', async ({ page }) => {
  await loginAsAdmin(page, ADMIN_USERS.TENANT_A);
  await expectToBeLoggedIn(page);
});

The loginAsAdmin implementation in tests/e2e/fixtures/helpers.js handles navigation to the tenant-specific login page, form filling, and CSRF token management.

Code Example: Cross-Layer Integration Testing

This pattern from tests/e2e/admin/site-settings-integration.spec.js validates that admin changes propagate to the public site:

test('changing company name updates homepage', async ({ page }) => {
  const tenant = TENANTS.A;
  
  // Access admin with bypass auth
  await goToAdminPage(page, tenant, '/site_admin/website/settings');
  
  // Modify setting
  await page.fill('input#company_name', 'Acme Real Estate');
  await saveAndWait(page, 'Save');
  
  // Verify on public site
  await page.goto(`${tenant.baseURL}/`);
  await expect(page.locator('body')).toContainText('Acme Real Estate');
});

Summary

  • Configurationplaywright.config.js defines the E2E environment targeting tenant-a.e2e.localhost:3001 with tests/e2e/ as the test directory and global-setup.js for pre-flight checks
  • Orchestrationlib/tasks/playwright.rake provides the complete workflow: playwright:reset for database state, playwright:server for Rails startup, and playwright:test for execution
  • Multi-tenant support – The suite validates tenant isolation through sub-domain routing, session scoping, and data separation using fixtures from tests/e2e/fixtures/test-data.js
  • Execution modes – Standard authentication testing and BYPASS_ADMIN_AUTH mode both integrate with the Rake workflow for flexible integration testing
  • Debugging – UI mode, headed mode, and HTML reports via playwright:report provide comprehensive debugging capabilities

Frequently Asked Questions

How do I run a single E2E test file instead of the full suite?

Use the playwright:test Rake task with the -- separator followed by the spec path. For example: RAILS_ENV=e2e bin/rails playwright:test -- tests/e2e/auth/admin_login.spec.js. The -- passes the file argument directly to the underlying Playwright CLI invoked by scripts/run-e2e-tests.sh.

What is the difference between playwright:server and playwright:server_bypass_auth?

playwright:server starts Rails on port 3001 with normal admin authentication enabled, requiring valid credentials from db/yml_seeds/e2e_users.yml. playwright:server_bypass_auth sets BYPASS_ADMIN_AUTH=true, which disables the admin login requirement entirely, allowing faster integration tests that skip authentication flows.

Why does the E2E setup require manual database resetting instead of using Playwright's built-in webServer?

The PropertyWebBuilder architecture requires specific Rails startup procedures to support multi-tenant sub-domain routing and the optional BYPASS_ADMIN_AUTH mode. The playwright:reset and playwright:server tasks in lib/tasks/playwright.rake handle these Rails-specific requirements that Playwright’s generic webServer option cannot accommodate, such as printing admin credentials and verifying the e2e environment constraints.

How does the test suite ensure tenant data isolation?

The global-setup.js script verifies that tenant-a exists in the E2E database before running tests. Individual specs use the TENANTS constants from fixtures/test-data.js to construct sub-domain URLs like tenant-a.e2e.localhost:3001, while helper functions like loginAsAdmin and goToTenant ensure cookies and sessions remain scoped to specific tenants, preventing cross-tenant authentication leakage.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →