Playwright

Playwright Security Testing

Add 250+ security checks to your Playwright E2E tests. Detect XSS vectors, CSP issues, insecure cookies, and more - automatically during your existing test runs.

Quick Start with Playwright

1. Install QAstell

npm install qastell

2. Add Security Auditing to Your Test

import { test, expect } from '@playwright/test';
import { SecurityAuditor } from 'qastell';

test('homepage should pass security audit', async ({ page }) => {
  await page.goto('https://your-app.com');

  // Run 250+ security checks
  const auditor = new SecurityAuditor(page);
  await auditor.assertNoViolations();
});

3. Run Your Tests

npx playwright test

Zero Configuration: QAstell automatically detects Playwright pages. Just pass your page object to SecurityAuditor and you're done.

Complete Playwright Example

Here's a comprehensive example showing security auditing integrated into a typical Playwright test:

import { test, expect } from '@playwright/test';
import { SecurityAuditor } from 'qastell';
import * as fs from 'fs';

test.describe('Security Audits', () => {

  test('login page security', async ({ page }) => {
    await page.goto('/login');

    const auditor = new SecurityAuditor(page);

    // Strict audit - fail on any violation
    await auditor.assertNoViolations();
  });

  test('dashboard with thresholds', async ({ page }) => {
    await page.goto('/dashboard');

    const auditor = new SecurityAuditor(page);

    // Gradual adoption - allow some low-severity issues
    await auditor.assertNoViolations({
      thresholds: {
        info: 10,
        low: 5,
        medium: 0,
        high: 0,
        critical: 0,
      },
    });
  });

  test('generate security report', async ({ page }) => {
    await page.goto('/');

    const auditor = new SecurityAuditor(page);
    const results = await auditor.audit();

    // Save HTML report
    fs.writeFileSync('security-report.html', results.toHTML());

    // Log summary
    console.log(`Found ${results.summary.total} issues`);
  });

});

Playwright-Specific Features

Works with All Playwright APIs

QAstell works with Playwright's Page object from any source:

// From test fixtures
test('fixture page', async ({ page }) => {
  const auditor = new SecurityAuditor(page);
});

// From browser context
const context = await browser.newContext();
const page = await context.newPage();
const auditor = new SecurityAuditor(page);

// From browser directly
const page = await browser.newPage();
const auditor = new SecurityAuditor(page);

Multi-Page Testing

Audit multiple pages in a single test:

test('audit user journey', async ({ page }) => {
  const pagesToAudit = ['/', '/login', '/dashboard', '/settings'];

  for (const url of pagesToAudit) {
    await page.goto(url);
    const auditor = new SecurityAuditor(page);
    await auditor.assertNoViolations();
  }
});

Integration with Playwright Config

Set up license globally in your Playwright configuration:

// playwright.config.ts
import { defineConfig } from '@playwright/test';
import { initLicense } from 'qastell';

// Initialize license once at config load
initLicense(process.env.QASTELL_LICENSE);

export default defineConfig({
  // ... your config
});

Parallel Workers

Playwright runs tests in parallel worker processes by default. For the simplest setup with parallel workers, use the environment variable approach:

# Environment variable is inherited by all workers
QASTELL_LICENSE="your-key" npx playwright test --workers=4

The license is automatically read from QASTELL_LICENSE by each worker process. See parallel execution for more details on scan counting behavior.

Force Framework Detection

If you're using custom page wrappers and auto-detection fails, you can force Playwright mode:

const auditor = new SecurityAuditor(page, { framework: 'playwright' });

// Verify the detected framework
console.log(auditor.getFramework()); // 'playwright'

What Gets Checked

QAstell runs 250+ security checks across these categories when using Playwright:

Using a Different Framework?

Reporter Integration

QAstell integrates with popular test reporters to display security results alongside your test results.

Allure Reporter

Attach security results to Allure reports (works with both Allure 2 and Allure 3):

import { test, expect } from '@playwright/test';
import { SecurityAuditor, ReportConnector, adapters } from 'qastell';
import { allure } from 'allure-playwright';

test('security audit', async ({ page }) => {
  await page.goto('https://example.com');
  const auditor = new SecurityAuditor(page);
  const results = await auditor.audit();

  // Create adapter for Allure
  const adapter = adapters.allure(allure);
  const connector = new ReportConnector(adapter);

  // Attach markdown summary inline, HTML report as attachment
  await connector.attach(results, {
    inline: 'markdown',
    attachments: ['html'],
  });

  expect(results.passed()).toBe(true);
});

Playwright HTML Reporter

Attach results to Playwright's built-in HTML reporter:

import { test, expect } from '@playwright/test';
import { SecurityAuditor, ReportConnector, adapters } from 'qastell';

test('security audit', async ({ page }, testInfo) => {
  await page.goto('https://example.com');
  const auditor = new SecurityAuditor(page);
  const results = await auditor.audit();

  // Create adapter for Playwright testInfo
  const adapter = adapters.playwright(testInfo);
  const connector = new ReportConnector(adapter);

  // Attach compact HTML summary inline, full report as attachment
  await connector.attach(results, {
    inline: 'htmlSummary',
    attachments: ['html'],
  });

  expect(results.passed()).toBe(true);
});

Cucumber BDD

Playwright works seamlessly with Cucumber for BDD-style security tests:

// steps/security.steps.ts
import { When, Then } from '@cucumber/cucumber';
import { SecurityAuditor, ReportConnector, adapters } from 'qastell';

When('I perform a security audit', async function() {
  const auditor = new SecurityAuditor(this.page);
  this.auditResults = await auditor.audit();
});

Then('the audit results should be attached to the report', async function() {
  // Create adapter for Cucumber (uses World context)
  const adapter = adapters.cucumber(this);
  const connector = new ReportConnector(adapter);

  // Attach markdown summary to Cucumber report
  await connector.attach(this.auditResults, {
    inline: 'markdown',
  });
});

See the playwright-cucumber and playwright-cucumber-multi examples for complete working implementations.

See the Reporter Integration section for all available adapters and formatters.

Next Steps