# Memstack Development Webapp Testing

> Use when the user says 'write browser tests', 'test this page', 'playwright test', 'e2e test', 'end to end test', 'browser test', 'test the UI', or needs Playwright-based browser testing for a web application. Do NOT use for unit tests, API tests, or non-browser testing.

- Skill: `cwinvestments/memstack-development-webapp-testing` (Agent Skill)
- Install (CLI): `npx skillmds@latest add cwinvestments/memstack-development-webapp-testing`
- Raw SKILL.md: https://api.skillmd.com/api/skills/cwinvestments/memstack-development-webapp-testing/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Integrations & APIs
- Author: cwinvestments (https://skillmd.com/u/cwinvestments)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/cwinvestments/memstack-development-webapp-testing

---


# Webapp Testing: Writing browser tests...
*Produces Playwright end-to-end tests that verify real user flows in a browser.*

## Activation

| Trigger | Status |
|---------|--------|
| User says "write browser tests" or "playwright test" | ACTIVE |
| User says "test this page" or "e2e test" | ACTIVE |
| User says "test the UI" or "browser test" | ACTIVE |
| User wants unit tests or API tests | NOT this skill: use standard test patterns |
| User wants load testing | NOT this skill |

## Context Guard

- Do NOT use for unit tests (Jest, Vitest without browser)
- Do NOT use for API-only testing (use curl/fetch patterns)
- Do NOT use for performance benchmarking
- This skill ONLY produces Playwright browser tests

## Steps

### Step 1: Assess the target

Determine what to test:

| Parameter | How to find | Example |
|-----------|-------------|---------|
| App URL | Check package.json scripts, .env, or ask | `http://localhost:3000` |
| Framework | Check package.json dependencies | Next.js, React, SvelteKit |
| Auth required? | Check for login pages, auth middleware | Yes/No |
| Key user flows | Ask or infer from routes | Sign up, checkout, search |

```bash
# Check if Playwright is already installed
cat package.json | grep -i playwright

# Check existing test structure
find . -name "*.spec.ts" -o -name "*.test.ts" | head -20
```

### Step 2: Set up Playwright (if not installed)

```bash
npm init playwright@latest
# or
pnpm add -D @playwright/test
npx playwright install
```

Confirm `playwright.config.ts` exists. If not, create with sensible defaults:

```typescript
import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
  testDir: './tests/e2e',
  fullyParallel: true,
  forbidOnly: !!process.env.CI,
  retries: process.env.CI ? 2 : 0,
  workers: process.env.CI ? 1 : undefined,
  reporter: 'html',
  use: {
    baseURL: 'http://localhost:3000',
    trace: 'on-first-retry',
    screenshot: 'only-on-failure',
  },
  projects: [
    { name: 'chromium', use: { ...devices['Desktop Chrome'] } },
  ],
  webServer: {
    command: 'npm run dev',
    url: 'http://localhost:3000',
    reuseExistingServer: !process.env.CI,
  },
});
```

### Step 3: Write tests for each user flow

Follow this structure per flow:

```typescript
import { test, expect } from '@playwright/test';

test.describe('Feature Name', () => {
  test('should [expected behavior] when [action]', async ({ page }) => {
    // Arrange, navigate to the page
    await page.goto('/path');

    // Act, perform user actions
    await page.getByRole('button', { name: 'Submit' }).click();

    // Assert, verify the result
    await expect(page.getByText('Success')).toBeVisible();
  });
});
```

**Test writing rules:**
1. Use `getByRole`, `getByLabel`, `getByText` over CSS selectors: they survive refactors
2. One assertion per test where practical: clear failure messages
3. Name tests as user stories: "should show error when email is invalid"
4. Use `test.describe` to group related flows
5. Add `test.beforeEach` for shared navigation/auth setup
6. Never hardcode waits, use `expect` with auto-waiting or `waitForSelector`

### Step 4: Handle authentication flows

If the app requires login:

```typescript
// tests/e2e/auth.setup.ts
import { test as setup, expect } from '@playwright/test';

setup('authenticate', async ({ page }) => {
  await page.goto('/login');
  await page.getByLabel('Email').fill('test@example.com');
  await page.getByLabel('Password').fill('testpassword');
  await page.getByRole('button', { name: 'Sign in' }).click();
  await expect(page).toHaveURL('/dashboard');

  // Save signed-in state
  await page.context().storageState({ path: '.auth/user.json' });
});
```

Add to `playwright.config.ts`:

```typescript
projects: [
  { name: 'setup', testMatch: /.*\.setup\.ts/ },
  {
    name: 'chromium',
    use: {
      ...devices['Desktop Chrome'],
      storageState: '.auth/user.json',
    },
    dependencies: ['setup'],
  },
],
```

### Step 5: Common test patterns

**Form validation:**
```typescript
test('should show validation errors for empty required fields', async ({ page }) => {
  await page.goto('/form');
  await page.getByRole('button', { name: 'Submit' }).click();
  await expect(page.getByText('Email is required')).toBeVisible();
});
```

**Navigation flow:**
```typescript
test('should navigate from landing to pricing', async ({ page }) => {
  await page.goto('/');
  await page.getByRole('link', { name: 'Pricing' }).click();
  await expect(page).toHaveURL('/pricing');
  await expect(page.getByRole('heading', { name: 'Pricing' })).toBeVisible();
});
```

**API response verification:**
```typescript
test('should load and display data', async ({ page }) => {
  await page.goto('/dashboard');
  await expect(page.getByRole('table')).toBeVisible();
  await expect(page.locator('tbody tr')).toHaveCount(10);
});
```

### Step 6: Run and report

```bash
# Run all tests
npx playwright test

# Run specific test file
npx playwright test tests/e2e/auth.spec.ts

# Run with UI mode for debugging
npx playwright test --ui

# Show HTML report
npx playwright show-report
```

Present results:

```
Playwright tests written:
- [N] test files covering [N] user flows
- Auth setup: [yes/no]
- Flows tested: [list]

Run with: npx playwright test
```

## Disambiguation

- "write browser tests" / "playwright test" / "e2e test" = Webapp Testing
- "write unit tests" / "jest test" / "vitest" = Standard test patterns (not this skill)
- "test the API" / "curl test" = API testing (not this skill)
- "verify my code" / "check this work" = Verify (not this skill)

## Level History

- **Lv.1**: Base: Playwright test generation with role-based selectors, auth flows, common patterns, CI-ready config. (Origin: MemStack v3.5, Apr 2026)

