Source profileQuality 96/100Review permissions

travisjneuman/.claude/skills/test-specialist/SKILL.md

test-specialist

This skill should be used when writing test cases, fixing bugs, analyzing code for potential issues, or improving test coverage for JavaScript/TypeScript applications. Use this for unit tests, integration tests, end-to-end tests, debugging runtime errors, logic bugs, performance issues, security vulnerabilities, and systematic code analysis.

Source repository stars
94
Declared platforms
0
Static risk flags
2
Last source update
2026-08-13
Source checked
2026-08-25

Decision brief

What it does: where it fits

Systematic testing methodologies and debugging techniques for JS/TS applications.

Best for

  • Writing unit, integration, or E2E tests
  • Fixing bugs and debugging
  • Improving test coverage

Not for

  • Tasks that require unconfirmed production actions or broad system permissions.
  • Environments where the pinned source and install steps cannot be inspected.

Compatibility matrix

Platform support, with evidence labels

PlatformStatusEvidenceWhat to check
CodexNot declaredNo explicit evidencePortability before use
Claude CodeNot declaredNo explicit evidencePortability before use
CursorNot declaredNo explicit evidencePortability before use
Gemini CLINot declaredNo explicit evidencePortability before use
Open the compatibility checker

Installation

Inspect first. Install second.

The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.

Source-detected install commandSource
npx skills add https://github.com/travisjneuman/.claude --skill "skills/test-specialist"
Safe inspection promptEditorial

Inspect the Agent Skill "test-specialist" from https://github.com/travisjneuman/.claude/blob/b8b4dd55d61b9f25d33e3b5427870641a1c8c39c/skills/test-specialist/SKILL.md at commit b8b4dd55d61b9f25d33e3b5427870641a1c8c39c. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.

Workflow

What the source asks the agent to do

  1. 01

    Bug Analysis Process

    1. Reproduce - Document exact steps, expected vs actual 2. Isolate - Binary search, minimal reproduction 3. Root Cause - Trace execution, check assumptions, git blame 4. Fix - Write failing test first, implement fix 5. Validate - Run full suite, test edge cases

    Reproduce - Document exact steps, expected vs actualIsolate - Binary search, minimal reproductionRoot Cause - Trace execution, check assumptions, git blame
  2. 02

    Workflow Decision Tree

    Review the “Workflow Decision Tree” section in the pinned source before continuing.

    Review and apply the “Workflow Decision Tree” source section.
  3. 03

    When to Use

    Writing unit, integration, or E2E tests

    Writing unit, integration, or E2E testsFixing bugs and debuggingImproving test coverage
  4. 04

    Testing Stack by Project

    Review the “Testing Stack by Project” section in the pinned source before continuing.

    Review and apply the “Testing Stack by Project” source section.
  5. 05

    Test Patterns

    Review the “Test Patterns” section in the pinned source before continuing.

    Review and apply the “Test Patterns” source section.

Permission review

Static risk signals and limitations

Network access

medium · line 164

The documentation includes network, browsing, or remote request actions.

await request(app).post("/api/items").expect(401);

Runs scripts

medium · line 529

The documentation asks the agent to run terminal commands or scripts.

npx chromatic --project-token=<token>

Evidence record

Why each signal appears

EvidenceSourceComputedTestedEditorial
SignalValueEvidence typeMeaning
Quality score96/100ComputedDocumentation, specificity, maintenance, and trust rules
Repository stars94SourceRepository attention, not individual Skill quality
Compatibility0 platformsSourceDeclared in the catalog source record
Usage guideautomated source guideEditorialGenerated or reviewed according to the visible evidence level

Pinned source

Provenance and original SKILL.md

Repository
travisjneuman/.claude
Skill path
skills/test-specialist/SKILL.md
Commit
b8b4dd55d61b9f25d33e3b5427870641a1c8c39c
License
MIT
Collected
2026-08-25
Default branch
master
View the original SKILL.md

Test Specialist

Systematic testing methodologies and debugging techniques for JS/TS applications.

When to Use

Use for:

  • Writing unit, integration, or E2E tests
  • Fixing bugs and debugging
  • Improving test coverage
  • Analyzing code for potential issues
  • Security and performance testing

Don't use when:

  • Code review → use generic-code-reviewer
  • Technical debt → use tech-debt-analyzer
  • Feature development → use generic-feature-developer

Testing Stack by Project

Project TypeUnit TestsComponentE2E
React/Next.jsVitest/JestTesting LibraryPlaywright
Node.jsVitest/JestSupertestPlaywright
StaticJest-Playwright

Test Patterns

Unit Tests (AAA Pattern)

describe("calculateTotal", () => {
  test("sums amounts correctly", () => {
    // Arrange
    const items = [{ amount: 100 }, { amount: 50 }];
    // Act
    const total = calculateTotal(items);
    // Assert
    expect(total).toBe(150);
  });

  test("handles empty list", () => {
    expect(calculateTotal([])).toBe(0);
  });
});

Component Tests (User Behavior)

// ✅ Test user behavior, not implementation
it('creates item when user clicks Add', async () => {
  const user = userEvent.setup();
  render(<ItemList />);

  await user.click(screen.getByRole('button', { name: /add/i }));
  await user.type(screen.getByLabelText(/title/i), 'New item');
  await user.click(screen.getByRole('button', { name: /save/i }));

  expect(screen.getByText('New item')).toBeInTheDocument();
});

E2E Tests (Playwright)

import { test, expect } from "@playwright/test";

test("user can complete checkout", async ({ page }) => {
  await page.goto("/products");

  // Add to cart
  await page.click('button:has-text("Add to Cart")');
  await page.click('a:has-text("Cart")');

  // Checkout
  await page.click('button:has-text("Checkout")');
  await page.fill('[name="email"]', "[email protected]");
  await page.click('button:has-text("Place Order")');

  // Verify
  await expect(page.locator("h1")).toContainText("Order Confirmed");
});

Integration Tests

test("POST /items creates item", async () => {
  const response = await request(app)
    .post("/api/items")
    .send({ name: "Test" })
    .expect(201);

  expect(response.body).toMatchObject({ id: expect.any(Number) });
});

Bug Analysis Process

  1. Reproduce - Document exact steps, expected vs actual
  2. Isolate - Binary search, minimal reproduction
  3. Root Cause - Trace execution, check assumptions, git blame
  4. Fix - Write failing test first, implement fix
  5. Validate - Run full suite, test edge cases

Debugging Checklist

When debugging an issue:

  • Can reproduce consistently
  • Minimal reproduction created
  • Console/network logs checked
  • State at failure point inspected
  • Git blame checked for recent changes
  • Failing test written before fix

Common Bug Patterns

Race Conditions

test("handles concurrent updates", async () => {
  const promises = Array.from({ length: 100 }, () => increment());
  await Promise.all(promises);
  expect(getCount()).toBe(100);
});

Null Safety

test.each([null, undefined, "", 0])("handles invalid input: %p", (input) => {
  expect(() => process(input)).toThrow("Invalid");
});

Boundary Values

test("handles edge cases", () => {
  expect(paginate([], 1, 10)).toEqual([]); // empty
  expect(paginate([item], 1, 10)).toEqual([item]); // single
  expect(paginate(items25, 3, 10)).toHaveLength(5); // partial last page
});

Security Tests

test("prevents SQL injection", async () => {
  const malicious = "'; DROP TABLE users; --";
  await expect(search(malicious)).resolves.not.toThrow();
});

test("sanitizes XSS", () => {
  const xss = '<script>alert("xss")</script>';
  expect(sanitize(xss)).not.toContain("<script>");
});

test("requires auth", async () => {
  await request(app).post("/api/items").expect(401);
});

Performance Tests

test("handles large datasets efficiently", () => {
  const largeList = Array.from({ length: 10000 }, (_, i) => ({ value: i }));
  const start = performance.now();
  process(largeList);
  expect(performance.now() - start).toBeLessThan(100);
});

Coverage Targets

Code TypeTarget
Critical paths90%+
Business logic85%+
UI components75%+
Utilities70%+

Test Quality Principles

  1. One behavior per test
  2. Descriptive names - test names explain scenario
  3. Independent tests - no shared state
  4. Cover edge cases - null, empty, boundaries, errors
  5. Mock external deps - tests should be fast
  6. Test behavior - not implementation details

Workflow Decision Tree

SituationAction
Adding featureWrite test first (TDD)
Fixing bugWrite failing test, then fix
Improving coverageFind gaps, prioritize critical paths
Code reviewCheck edge cases, error handling

Python Testing (pytest)

Fixtures and Parametrize

import pytest
from myapp.services import UserService

@pytest.fixture
def user_service(db_session):
    """Provide a UserService with test database."""
    return UserService(session=db_session)

@pytest.fixture
def sample_user(user_service):
    """Create and return a sample user."""
    return user_service.create(name="Test User", email="[email protected]")

class TestUserService:
    def test_create_user(self, user_service):
        user = user_service.create(name="John", email="[email protected]")
        assert user.name == "John"
        assert user.id is not None

    def test_get_user_not_found(self, user_service):
        with pytest.raises(UserNotFoundError, match="User 999 not found"):
            user_service.get(999)

    @pytest.mark.parametrize("email,is_valid", [
        ("[email protected]", True),
        ("[email protected]", True),
        ("invalid", False),
        ("@example.com", False),
        ("", False),
    ])
    def test_validate_email(self, user_service, email: str, is_valid: bool):
        assert user_service.validate_email(email) == is_valid

Mocking

from unittest.mock import Mock, patch, AsyncMock

def test_send_notification(user_service):
    with patch("myapp.services.email_client") as mock_email:
        mock_email.send = Mock(return_value=True)
        user_service.notify(user_id=1, message="Hello")
        mock_email.send.assert_called_once_with(
            to="[email protected]",
            body="Hello",
        )

# Async mocking
@pytest.mark.asyncio
async def test_fetch_data():
    with patch("myapp.client.fetch", new_callable=AsyncMock) as mock_fetch:
        mock_fetch.return_value = {"status": "ok"}
        result = await process_data()
        assert result["status"] == "ok"

conftest.py Patterns

# tests/conftest.py
import pytest
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

@pytest.fixture(scope="session")
def engine():
    return create_engine("sqlite:///:memory:")

@pytest.fixture(scope="function")
def db_session(engine):
    Base.metadata.create_all(engine)
    Session = sessionmaker(bind=engine)
    session = Session()
    yield session
    session.rollback()
    session.close()
    Base.metadata.drop_all(engine)

Go Testing

Table-Driven Tests

func TestCalculateDiscount(t *testing.T) {
    tests := []struct {
        name     string
        amount   float64
        code     string
        want     float64
        wantErr  bool
    }{
        {
            name:   "valid 10% discount",
            amount: 100.0,
            code:   "SAVE10",
            want:   90.0,
        },
        {
            name:   "no discount",
            amount: 100.0,
            code:   "",
            want:   100.0,
        },
        {
            name:    "invalid code",
            amount:  100.0,
            code:    "INVALID",
            wantErr: true,
        },
        {
            name:   "zero amount",
            amount: 0,
            code:   "SAVE10",
            want:   0,
        },
    }

    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            got, err := CalculateDiscount(tt.amount, tt.code)
            if (err != nil) != tt.wantErr {
                t.Errorf("CalculateDiscount() error = %v, wantErr %v", err, tt.wantErr)
                return
            }
            if got != tt.want {
                t.Errorf("CalculateDiscount() = %v, want %v", got, tt.want)
            }
        })
    }
}

Testify Assertions and Mocks

import (
    "testing"
    "github.com/stretchr/testify/assert"
    "github.com/stretchr/testify/mock"
    "github.com/stretchr/testify/require"
)

// Mock
type MockUserRepo struct {
    mock.Mock
}

func (m *MockUserRepo) FindByID(id string) (*User, error) {
    args := m.Called(id)
    if args.Get(0) == nil {
        return nil, args.Error(1)
    }
    return args.Get(0).(*User), args.Error(1)
}

func TestGetUser(t *testing.T) {
    repo := new(MockUserRepo)
    repo.On("FindByID", "123").Return(&User{ID: "123", Name: "John"}, nil)

    service := NewUserService(repo)
    user, err := service.GetUser("123")

    require.NoError(t, err)
    assert.Equal(t, "John", user.Name)
    repo.AssertExpectations(t)
}

// HTTP handler testing
func TestGetUserHandler(t *testing.T) {
    req := httptest.NewRequest("GET", "/users/123", nil)
    w := httptest.NewRecorder()

    handler := NewHandler(mockService)
    handler.GetUser(w, req)

    assert.Equal(t, http.StatusOK, w.Code)

    var user User
    err := json.NewDecoder(w.Body).Decode(&user)
    require.NoError(t, err)
    assert.Equal(t, "123", user.ID)
}

Rust Testing

Unit and Integration Tests

// src/lib.rs - Unit tests (same file)
pub fn calculate_discount(amount: f64, percentage: f64) -> Result<f64, DiscountError> {
    if percentage < 0.0 || percentage > 100.0 {
        return Err(DiscountError::InvalidPercentage(percentage));
    }
    Ok(amount * (1.0 - percentage / 100.0))
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_valid_discount() {
        let result = calculate_discount(100.0, 10.0).unwrap();
        assert!((result - 90.0).abs() < f64::EPSILON);
    }

    #[test]
    fn test_zero_discount() {
        assert_eq!(calculate_discount(100.0, 0.0).unwrap(), 100.0);
    }

    #[test]
    fn test_invalid_percentage() {
        assert!(matches!(
            calculate_discount(100.0, 150.0),
            Err(DiscountError::InvalidPercentage(_))
        ));
    }

    #[test]
    fn test_negative_percentage() {
        assert!(calculate_discount(100.0, -10.0).is_err());
    }
}

// tests/integration_test.rs - Integration tests (separate file)
use my_crate::calculate_discount;

#[test]
fn test_full_workflow() {
    let original = 200.0;
    let discounted = calculate_discount(original, 25.0).unwrap();
    assert_eq!(discounted, 150.0);
}

Property-Based Testing (proptest)

use proptest::prelude::*;

proptest! {
    #[test]
    fn discount_never_exceeds_original(amount in 0.0f64..10000.0, pct in 0.0f64..100.0) {
        let result = calculate_discount(amount, pct).unwrap();
        prop_assert!(result <= amount);
        prop_assert!(result >= 0.0);
    }

    #[test]
    fn roundtrip_serialization(name in "[a-zA-Z]{1,50}", age in 0u32..150) {
        let user = User { name: name.clone(), age };
        let json = serde_json::to_string(&user).unwrap();
        let deserialized: User = serde_json::from_str(&json).unwrap();
        prop_assert_eq!(user, deserialized);
    }
}

Visual Regression Testing

Playwright Screenshots

import { test, expect } from "@playwright/test";

test("homepage visual regression", async ({ page }) => {
  await page.goto("/");
  await expect(page).toHaveScreenshot("homepage.png", {
    maxDiffPixelRatio: 0.01,
  });
});

test("component states", async ({ page }) => {
  await page.goto("/components");

  // Default state
  await expect(page.locator(".card")).toHaveScreenshot("card-default.png");

  // Hover state
  await page.locator(".card").hover();
  await expect(page.locator(".card")).toHaveScreenshot("card-hover.png");

  // Full page with specific viewport
  await page.setViewportSize({ width: 375, height: 812 }); // iPhone
  await expect(page).toHaveScreenshot("homepage-mobile.png");
});

// Update snapshots: npx playwright test --update-snapshots

Percy (Cloud Visual Testing)

import percySnapshot from "@percy/playwright";

test("visual test with Percy", async ({ page }) => {
  await page.goto("/dashboard");
  await percySnapshot(page, "Dashboard");
  // Percy compares across browsers and viewport sizes
});

Chromatic (Storybook Visual Testing)

# Run Chromatic on Storybook stories
npx chromatic --project-token=<token>

# CI integration
# Chromatic captures every story as a visual snapshot
# and detects pixel-level changes across PRs
ToolApproachBest For
PlaywrightLocal screenshot comparisonE2E visual tests, free
PercyCloud cross-browser comparisonMulti-browser, team review
ChromaticStorybook story snapshotsComponent library visual QA

See Also

Frequently asked questions

What to verify before installation and use

What does the test-specialist source document cover?

Systematic testing methodologies and debugging techniques for JS/TS applications.

How do I install test-specialist?

The source record exposes this install command: npx skills add https://github.com/travisjneuman/.claude --skill "skills/test-specialist". Inspect the command and pinned source before running it.

Which permission-related actions were detected?

Static rules flagged network, exec-script in the source; the page lists the matching lines and excerpts.

Alternatives

Compare before choosing