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/e2econtains all spec files - Global setup –
./tests/e2e/global-setup.jsruns once before the suite to verify the E2E database contains seeded tenant data - Base URL –
http://tenant-a.e2e.localhost:3001targets the Railse2eenvironment sub-domain - Parallelism –
fullyParallel: truefor local development; CI forces single-worker execution viaworkers: 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:3001andtenant-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
- Configuration –
playwright.config.jsdefines the E2E environment targetingtenant-a.e2e.localhost:3001withtests/e2e/as the test directory andglobal-setup.jsfor pre-flight checks - Orchestration –
lib/tasks/playwright.rakeprovides the complete workflow:playwright:resetfor database state,playwright:serverfor Rails startup, andplaywright:testfor 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_AUTHmode both integrate with the Rake workflow for flexible integration testing - Debugging – UI mode, headed mode, and HTML reports via
playwright:reportprovide 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →