@ephemeral-broker/playwright
v0.1.2
Published
Playwright global setup/teardown for ephemeral-broker
Downloads
11
Maintainers
Readme
@ephemeral-broker/playwright
Playwright global setup/teardown for @ephemeral-broker/core.
Share bootstrap data, tokens, and secrets across parallel Playwright workers without touching disk or opening ports.
Why?
When running Playwright tests in parallel:
- Problem: Each worker regenerates tokens, fetches bootstrap data, makes duplicate API calls
- Solution: Generate once, share via ephemeral broker, workers read from in-memory store
Performance: 80x faster bootstrap (8s → 0.1s per worker)
Features
- ✅ Zero disk I/O - All data stored in-memory via named pipes/UNIX sockets
- ✅ Parallel-safe - No race conditions, each worker reads independently
- ✅ Automatic cleanup - Broker stops when tests complete
- ✅ TTL support - Data expires automatically
- ✅ Secure - No ports opened, filesystem permissions only
Installation
npm install --save-dev @ephemeral-broker/playwright @ephemeral-broker/coreQuick Start
1. Configure Playwright
// playwright.config.js
import { defineConfig } from '@playwright/test'
import { globalSetup, globalTeardown } from '@ephemeral-broker/playwright'
export default defineConfig({
globalSetup,
globalTeardown,
// Broker configuration
ephemeralBroker: {
ttl: 600000, // 10 minutes
debug: false,
seedData: {
cache: {
courseId: 'COURSE_123',
modeIds: { test: 'mode_1' }
},
ephemeral: {
pubToken: 'Bearer abc123...',
adminToken: 'Bearer xyz789...'
}
}
},
// Your existing Playwright config
testDir: './tests',
fullyParallel: true,
workers: 5
})2. Access Data in Tests
// tests/example.spec.js
import { test, expect } from '@playwright/test'
import { Client } from '@ephemeral-broker/core'
test.describe('My Tests', () => {
let client
test.beforeAll(async () => {
// Connect to broker (pipe path set by globalSetup)
client = new Client(process.env.EPHEMERAL_PIPE)
})
test('should use shared bootstrap data', async ({ page }) => {
const courseId = await client.get('courseId')
const token = await client.get('pubToken')
console.log(`Using course: ${courseId}`)
// Use data in your test
await page.goto(`https://app.example.com/courses/${courseId}`)
await page.setExtraHTTPHeaders({
'Authorization': token
})
// ... test assertions
})
})Configuration Options
ephemeralBroker: {
// Time-to-live for cached data (milliseconds)
ttl: 600000, // Default: 10 minutes
// Enable debug logging
debug: false,
// Bootstrap data to seed
seedData: {
// Persistent cache (from .cache files)
cache: {
courseId: 'COURSE_123',
districtId: 'DISTRICT_456',
// ... other bootstrap data
},
// Ephemeral secrets (never persisted)
ephemeral: {
pubToken: 'Bearer ...',
adminToken: 'Bearer ...',
// ... tokens, run metadata
}
}
}How It Works
┌─────────────────────────────────────────────┐
│ Playwright Test Run │
│ │
│ 1. globalSetup: Start broker + seed data │
│ 2. Spawn 5 parallel workers │
│ 3. Workers read from broker (fast!) │
│ 4. globalTeardown: Stop broker + cleanup │
└─────────────────────────────────────────────┘
Named Pipe: /tmp/broker-abc123.sock
├── Worker 1 (reads tokens)
├── Worker 2 (reads tokens)
├── Worker 3 (reads tokens)
├── Worker 4 (reads tokens)
└── Worker 5 (reads tokens)Advanced Usage
Custom Global Setup
If you need to run additional setup logic:
// playwright.config.js
import { globalSetup as brokerSetup, globalTeardown as brokerTeardown, getClient } from '@ephemeral-broker/playwright'
async function customGlobalSetup(config) {
// Start broker first
await brokerSetup(config)
// Get client for custom seeding
const client = getClient()
// Generate fresh tokens
const tokens = await generateTokens()
await client.set('pubToken', tokens.pubToken)
await client.set('adminToken', tokens.adminToken)
// Load cache from file
const cache = JSON.parse(
fs.readFileSync('data/.cache/bootstrap.json', 'utf8')
)
await client.set('cache', cache)
console.log('Custom setup complete!')
}
async function customGlobalTeardown(config) {
console.log('Cleaning up...')
await brokerTeardown(config)
}
export default defineConfig({
globalSetup: customGlobalSetup,
globalTeardown: customGlobalTeardown,
ephemeralBroker: {
ttl: 600000,
debug: true
}
})Load Cache from Files
// playwright.config.js
import fs from 'fs'
const cache = JSON.parse(
fs.readFileSync('data/.cache/satellite.qa.bootstrap.json', 'utf8')
)
export default defineConfig({
globalSetup,
globalTeardown,
ephemeralBroker: {
seedData: {
cache: cache,
ephemeral: {
pubToken: await generateToken(),
runId: Date.now().toString(36)
}
}
}
})Fixture Pattern
For easier access in tests, create a fixture:
// tests/fixtures.js
import { test as base } from '@playwright/test'
import { Client } from '@ephemeral-broker/core'
export const test = base.extend({
broker: async ({}, use) => {
const client = new Client(process.env.EPHEMERAL_PIPE)
await use(client)
}
})
export { expect } from '@playwright/test'// tests/example.spec.js
import { test, expect } from './fixtures'
test('should use broker fixture', async ({ broker, page }) => {
const courseId = await broker.get('courseId')
await page.goto(`https://app.example.com/courses/${courseId}`)
// ...
})API
globalSetup(config)
Starts broker and seeds data. Called automatically by Playwright before all tests.
Parameters:
config(object): Playwright config withephemeralBrokeroptions
Returns: Promise<void>
globalTeardown(config)
Stops broker and cleans up. Called automatically by Playwright after all tests.
Parameters:
config(object): Playwright config
Returns: Promise<void>
getPipePath()
Get current broker pipe path.
Returns: string|null
getClient()
Get a client instance for custom operations.
Returns: Client|null
Environment Variables
Set automatically by globalSetup:
EPHEMERAL_PIPE: Path to broker pipe (e.g.,/tmp/broker-abc123.sock)EPHEMERAL_BROKER_MODE: Set to'true'when broker is active
Examples
See examples/ directory for complete working examples:
- playwright.config.js - Basic configuration
- playwright.advanced.js - Advanced patterns
- tests/example.spec.js - Test examples
Differences from WDIO Plugin
| Feature | WDIO | Playwright |
|---------|------|------------|
| Integration | Service class | Global setup/teardown functions |
| Configuration | services: [[Service, opts]] | globalSetup/globalTeardown + ephemeralBroker |
| Lifecycle | onPrepare/onComplete hooks | Function calls by Playwright |
| Complexity | Class-based | Function-based (simpler!) |
Related Projects
- @ephemeral-broker/core - Core broker package
- @ephemeral-broker/wdio - WebDriverIO plugin
- Playwright - Test automation framework
License
MIT © Kathy Wegrzynowski
