Below are several practical examples showcasing different browser-testing use cases in LoadForge. All scripts inherit from PlaywrightUser and use the Locust-Playwright integration found in locust_plugins.users.playwright.


1. Basic Navigation & Timing

Navigate through a site and record timings for key page loads.

from locust import task
from locust_plugins.users.playwright import PlaywrightUser, PageWithRetry, pw, event

class NavUser(PlaywrightUser):
    @task
    @pw
    async def home_to_articles(self, page: PageWithRetry):
        async with event(self, "Home"):
            await page.goto("/")
        async with event(self, "Articles"):
            async with page.expect_navigation():
                await page.click('a:has-text("Articles")')

2. Clicking Elements – Different Strategies

Demonstrates clicking links via text, CSS selector, XPath, and nth-child().

from locust import task
from locust_plugins.users.playwright import PlaywrightUser, PageWithRetry, pw

class ClickUser(PlaywrightUser):
    @task
    @pw
    async def click_examples(self, page: PageWithRetry):
        await page.goto("/")
        # By link text
        await page.click('text=Features')
        # By CSS id
        await page.click('#signup-button')
        # By nth-child
        await page.click('nav ul li:nth-child(3) a')
        # By XPath
        await page.click('//footer//a[contains(., "Contact")]')

3. Form Submission & Assertion

Login form submission and verification of successful navigation using an assertion.

from locust import task
from locust_plugins.users.playwright import PlaywrightUser, PageWithRetry, pw

class LoginUser(PlaywrightUser):
    @task
    @pw
    async def login(self, page: PageWithRetry):
        await page.goto("/login")
        await page.fill('input[name="email"]', 'test@example.com')
        await page.fill('input[name="password"]', 'password123')
        async with page.expect_navigation():
            await page.click('button:has-text("Log in")')
        assert await page.locator('text=Dashboard').is_visible(), "Login failed"

4. Performance Metric – Largest Contentful Paint (LCP)

Throttle network, load page, and fire a custom request event marking pass/fail based on LCP.

from locust import task
from locust_plugins.users.playwright import PlaywrightUser, PageWithRetry, pw, event
import time

class LCPUser(PlaywrightUser):
    LCP_THRESHOLD = 1200  # ms

    @task
    @pw
    async def check_lcp(self, page: PageWithRetry):
        cdp = await self.browser_context.new_cdp_session(page)
        await cdp.send('Network.enable')
        await cdp.send('Network.emulateNetworkConditions', {
            'offline': False,
            'downloadThroughput': (1*1024*1024)/8,
            'uploadThroughput':   (1*1024*1024)/8,
            'latency': 50,
        })
        start = time.time()
        async with event(self, "Load home"):
            await page.goto("/")
        await page.wait_for_timeout(1000)
        lcp = await page.evaluate("""
            new Promise(r => {
              new PerformanceObserver(l => r(l.getEntries().at(-1).startTime))
              .observe({type:'largest-contentful-paint', buffered:true});
            })
        """)
        self.environment.events.request.fire(
            request_type="LCP",
            name=f"LCP {'PASS' if lcp<=self.LCP_THRESHOLD else 'FAIL'}",
            start_time=start,
            response_time=lcp,
            response_length=0,
            context={**self.context()},
            url="lcp_metric",
            exception=None if lcp<=self.LCP_THRESHOLD else Exception(f"LCP {lcp:.0f}ms > {self.LCP_THRESHOLD}ms"),
        )

5. Screenshot on Failure

Take a screenshot if a critical element is not visible.

from locust import task
from locust_plugins.users.playwright import PlaywrightUser, PageWithRetry, pw

class ScreenshotUser(PlaywrightUser):
    @task
    @pw
    async def critical_check(self, page: PageWithRetry):
        await page.goto("/")
        if not await page.locator('text=Pricing').is_visible():
            await page.screenshot(path="/tmp/pricing_missing.png", full_page=True)

6. Accessibility (Axe) Scan

Run an Axe accessibility scan directly from the browser context.

from locust import task
from locust_plugins.users.playwright import PlaywrightUser, PageWithRetry, pw, event
import json, time

AXE_SCRIPT_URL = "https://cdnjs.cloudflare.com/ajax/libs/axe-core/4.8.2/axe.min.js"

class AxeUser(PlaywrightUser):
    @task
    @pw
    async def axe_scan(self, page: PageWithRetry):
        async with event(self, "Axe scan"):
            await page.goto("/")
            await page.add_script_tag(url=AXE_SCRIPT_URL)
            results = await page.evaluate("axe.run()")
            violations = results.get('violations', [])
            if violations:
                msg = json.dumps(violations[:3], indent=2)  # limit output
                raise Exception(f"Accessibility issues found: {msg}")

These scripts should provide a solid starting point for common browser-testing scenarios. Modify selectors, thresholds, and URLs to match your application.