Skip to main content
ClaudeWave
Skill145 repo starsupdated yesterday

Clerk Auth Testing

Testing patterns for Clerk authentication including sign-in flow testing, protected route testing, webhook verification, middleware testing, and organization-based access control

Install in Claude Code
Copy
git clone --depth 1 https://github.com/PramodDutta/qaskills /tmp/clerk-auth-testing && cp -r /tmp/clerk-auth-testing/seed-skills/clerk-auth-testing ~/.claude/skills/clerk-auth-testing
Then start a new Claude Code session; the skill loads automatically.

SKILL.md

# Clerk Auth Testing Skill

You are an expert QA engineer specializing in testing applications that use Clerk for authentication. When the user asks you to write, review, or debug tests for Clerk auth flows, protected routes, middleware, webhooks, or organization-based access control, follow these detailed instructions.

## Core Principles

1. **Use Clerk testing tokens for E2E tests** -- Clerk provides testing tokens that bypass the Clerk hosted UI. Use them in Playwright tests to avoid interacting with iframes and third-party UI.
2. **Mock Clerk in unit tests, integrate in E2E** -- For unit tests, mock `@clerk/nextjs` hooks and helpers. For E2E tests, use real Clerk test instances or testing tokens.
3. **Test the middleware, not Clerk itself** -- Your middleware uses Clerk's `auth()` and `clerkMiddleware()`. Test your route protection logic, not Clerk's JWT verification.
4. **Webhook signature verification is critical** -- Clerk webhooks use Svix for signing. Test that your webhook handler rejects unsigned or tampered payloads.
5. **Organization RBAC requires multi-tenant testing** -- Test that users with different roles in different organizations see the correct content and have the correct permissions.
6. **Session management affects every page** -- Test that expired sessions redirect correctly, session refresh works, and multi-tab scenarios do not cause state inconsistencies.
7. **Graceful degradation when Clerk is unavailable** -- Your app should handle missing Clerk keys or network failures without crashing. Test the degraded state.

## Project Structure

Always organize Clerk auth testing with this structure:

```
src/
  middleware.ts
  app/
    (auth)/
      sign-in/
        [[...sign-in]]/
          page.tsx
      sign-up/
        [[...sign-up]]/
          page.tsx
    (protected)/
      dashboard/
        page.tsx
      admin/
        page.tsx
      settings/
        page.tsx
    api/
      webhooks/
        clerk/
          route.ts
      protected/
        route.ts
  lib/
    auth.ts
    roles.ts
  __tests__/
    unit/
      middleware.test.ts
      auth.test.ts
      roles.test.ts
    integration/
      webhook.test.ts
      protected-routes.test.ts
      organization.test.ts
    e2e/
      sign-in.spec.ts
      sign-up.spec.ts
      protected-flow.spec.ts
      admin-flow.spec.ts
    helpers/
      clerk-mock.ts
      clerk-test-utils.ts
    fixtures/
      clerk-user.fixture.ts
      clerk-webhook.fixture.ts
```

## Clerk Middleware Testing

### Middleware Configuration

```typescript
// src/middleware.ts
import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server';
import { NextResponse } from 'next/server';

const isPublicRoute = createRouteMatcher([
  '/',
  '/sign-in(.*)',
  '/sign-up(.*)',
  '/api/webhooks(.*)',
  '/api/public(.*)',
  '/blog(.*)',
  '/pricing',
]);

const isAdminRoute = createRouteMatcher([
  '/admin(.*)',
  '/api/admin(.*)',
]);

const isApiRoute = createRouteMatcher([
  '/api(.*)',
]);

export default clerkMiddleware(async (auth, req) => {
  const { userId, orgRole } = await auth();

  // Allow public routes
  if (isPublicRoute(req)) {
    return NextResponse.next();
  }

  // Require authentication for all non-public routes
  if (!userId) {
    if (isApiRoute(req)) {
      return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
    }
    const signInUrl = new URL('/sign-in', req.url);
    signInUrl.searchParams.set('redirect_url', req.url);
    return NextResponse.redirect(signInUrl);
  }

  // Admin routes require admin role
  if (isAdminRoute(req)) {
    if (orgRole !== 'org:admin') {
      if (isApiRoute(req)) {
        return NextResponse.json({ error: 'Forbidden' }, { status: 403 });
      }
      return NextResponse.redirect(new URL('/dashboard', req.url));
    }
  }

  return NextResponse.next();
});

export const config = {
  matcher: [
    '/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)',
    '/(api|trpc)(.*)',
  ],
};
```

### Middleware Unit Tests

```typescript
// __tests__/unit/middleware.test.ts
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { NextRequest } from 'next/server';

// Mock @clerk/nextjs/server before importing middleware
vi.mock('@clerk/nextjs/server', () => {
  const createRouteMatcher = (patterns: string[]) => {
    return (req: NextRequest) => {
      const pathname = req.nextUrl.pathname;
      return patterns.some((pattern) => {
        const regex = new RegExp('^' + pattern.replace('(.*)', '.*') + '$');
        return regex.test(pathname);
      });
    };
  };

  let mockAuthData = { userId: null as string | null, orgRole: null as string | null };

  const clerkMiddleware = (handler: (auth: () => Promise<any>, req: NextRequest) => any) => {
    return (req: NextRequest) => {
      const auth = async () => mockAuthData;
      return handler(auth, req);
    };
  };

  return {
    clerkMiddleware,
    createRouteMatcher,
    __setMockAuth: (data: typeof mockAuthData) => {
      mockAuthData = data;
    },
  };
});

import middleware from '../../src/middleware';
import { __setMockAuth } from '@clerk/nextjs/server';

function createRequest(path: string, method = 'GET'): NextRequest {
  return new NextRequest(new URL(path, 'http://localhost:3000'), { method });
}

describe('Clerk Middleware', () => {
  beforeEach(() => {
    __setMockAuth({ userId: null, orgRole: null });
  });

  describe('Public routes', () => {
    const publicPaths = ['/', '/sign-in', '/sign-up', '/blog', '/blog/my-post', '/pricing', '/api/webhooks/clerk'];

    it.each(publicPaths)('should allow unauthenticated access to %s', async (path) => {
      const req = createRequest(path);
      const response = await middleware(req);

      // Public routes should pass through (not redirect)
      expect(response.status).not.toBe(302);
      expect(response.status).not.toBe(401);
    });
  });

  describe('Protected routes (unauthentic
axe-core Accessibility AutomationSkill

Automated accessibility testing with axe-core integrated into CI pipelines, including custom rule configuration, issue prioritization, and remediation guidance.

A/B Test ValidationSkill

Validating A/B test implementations including traffic splitting accuracy, statistical significance calculation, metric tracking, and experiment cleanup.

Accessibility A11y EnhancedSkill

Comprehensive WCAG compliance and accessibility testing covering ARIA, keyboard navigation, screen readers, color contrast, and automated a11y validation.

Accessibility AuditorSkill

Comprehensive WCAG 2.1 AA compliance testing combining automated axe-core scans with manual keyboard navigation, screen reader compatibility, and focus management verification

AFL++ Fuzzing TestingSkill

American Fuzzy Lop Plus Plus mutation-based fuzz testing for finding crashes, hangs, and security vulnerabilities in binary programs.

Agent Browser AutomationSkill

Fast Rust-based headless browser automation CLI with Node.js fallback for AI agents, featuring navigation, clicking, typing, snapshots, and structured commands optimized for agent workflows.

Agentic Testing PatternsSkill

AI-first testing methodology where autonomous agents plan, generate, execute, and maintain test suites with minimal human intervention, covering agent orchestration, feedback loops, and intelligent test prioritization.

AI Agent EvaluationSkill

Comprehensive evaluation patterns for AI agents including multi-turn conversation testing, LLM-as-judge frameworks, benchmark suites, regression detection, and systematic eval pipelines for measuring agent quality and safety.