Agent skill

td-integration-test

Write integration tests for the td-sync admin API using the TestHarness in internal/api/testharness_test.go. Use when asked to write, add, or fix integration tests for admin API endpoints (server, users, projects, events, snapshots, CORS, auth). The harness provides a real HTTP server, fluent state builder, and assertion helpers. Tests go in internal/api/admin_integration_test.go.

Stars 188
Forks 24

Install this agent skill to your Project

npx add-skill https://github.com/marcus/td/tree/main/.claude/skills/td-integration-test

SKILL.md

td-sync Admin API Integration Tests

Write integration tests in internal/api/admin_integration_test.go using the harness in internal/api/testharness_test.go. Tests run against a real HTTP server on a random port with isolated temp databases.

Quick Start Pattern

go
func TestIntegration_DescriptiveName(t *testing.T) {
    t.Parallel()
    h := newTestHarness(t)
    state := h.Build().
        WithUser("user@test.com").
        WithAdmin("admin@test.com", "admin:read:server,sync").
        WithProject("proj1", "user@test.com").
        WithEvents("proj1", "user@test.com", 5).
        Done()

    token := state.AdminToken("admin@test.com")
    pid := state.ProjectID("proj1")

    var resp adminEventsResponse
    h.DoJSON("GET", fmt.Sprintf("/v1/admin/projects/%s/events", pid), token, nil, &resp)

    if len(resp.Data) != 5 {
        t.Fatalf("expected 5 events, got %d", len(resp.Data))
    }
}

Harness API

See references/harness-api.md for the complete API reference with all method signatures and detailed usage notes.

Core

  • newTestHarness(t, ...func(*Config)) *TestHarness -- real HTTP server, isolated DB, auto-cleanup
  • h.Do(method, path, token, body) *http.Response -- real HTTP request (caller closes body)
  • h.DoJSON(method, path, token, body, &out) *http.Response -- request + JSON decode (fatals on 4xx/5xx)

State Builder

go
h.Build().
    WithUser(email).                          // sync-scoped key
    WithAdmin(email, scopes).                 // admin key with scopes
    WithProject(name, ownerEmail).            // via API (owner must exist)
    WithMember(projectName, email, role).     // "owner"/"writer"/"reader"
    WithEvents(projectName, userEmail, count).// cycles issues/logs/comments
    WithSnapshot(projectName).                // triggers snapshot build
    WithAuthEvents(count).                    // inserts directly to DB
    WithRateLimitEvents(count).               // inserts directly to DB
    Done() // -> *TestState

Ordering matters: create users before projects, projects before members/events/snapshots.

State Accessors

state.UserToken(email), state.UserID(email), state.AdminToken(email), state.ProjectID(name), state.Harness()

Assertions

  • AssertStatus(t, resp, 200) -- checks status, prints body on failure
  • AssertErrorResponse(t, resp, 403, "insufficient_admin_scope") -- checks status + error code
  • ReadJSON[T](t, resp) T -- generic JSON decode
  • AssertPaginated[T](t, resp, count, hasMore) PaginatedResponse[T] -- checks paginated list
  • AssertCORSHeaders(t, resp, origin) / AssertNoCORSHeaders(t, resp)
  • h.AssertRequiresAdminScope(t, method, path, wrongToken) -- 403 + error code check

Admin Scopes

Scope Endpoints
admin:read:server server/overview, server/config, rate-limit-violations, users, users/{id}, users/{id}/keys, auth/events
admin:read:projects projects, projects/{id}, projects/{id}/members, sync/status, sync/cursors
admin:read:events projects/{id}/events, projects/{id}/events/{seq}, entity-types
admin:read:snapshots projects/{id}/snapshot/meta, projects/{id}/snapshot/query
admin:export projects/{id}/events/export

Response Types

Internal types accessible from test files in package api:

  • serverOverviewResponse -- server overview
  • serverConfigResponse -- server config
  • adminEventsResponse -- {Data []adminEvent, HasMore bool}
  • adminEvent -- single event: ServerSeq, EntityType, EntityID, ActionType, Payload
  • adminSyncStatusResponse -- {EventCount, LastServerSeq, LastEventTime}
  • adminCursorEntry -- {ClientID, LastEventID, LastSyncAt, DistanceFromHead}
  • serverdb.AdminProject -- project: ID, Name, MemberCount, EventCount
  • serverdb.AdminUser -- user: ID, Email, IsAdmin, ProjectCount
  • serverdb.AdminProjectMember -- {UserID, Email, Role}

Rules

  1. Always t.Parallel() -- each harness is isolated
  2. Test name prefix: TestIntegration_
  3. Config overrides via opts: newTestHarness(t, func(cfg *Config) { cfg.CORSAllowedOrigins = []string{"https://x.com"} })
  4. First user created is auto-admin; consume with h.CreateUser("first@test.com") when testing non-admin denial
  5. CORS tests need manual http.NewRequest since Do doesn't support custom headers
  6. Run tests: go test -v -run TestIntegration ./internal/api/

Expand your agent's capabilities with these related and highly-rated skills.

marcus/td

td-task-management

Task management for AI agents across context windows. Use when agents need to track work, log progress, hand off state, and maintain context across sessions. Includes workflows for single-issue focus, multi-issue work sessions, and structured handoffs. Essential for AI-assisted development where context windows reset between sessions.

188 24
Explore
marcus/sidecar

create-prompt

Create prompts for sidecar workspaces. Covers prompt structure (name, ticketMode, body), template variables (ticket with fallbacks), config file locations (global vs project), and scope overrides. Use when creating or modifying prompts in sidecar config files.

940 70
Explore
marcus/sidecar

merge-strategy

Git merge strategies, conflict resolution approaches, merge vs rebase recommendations, and branch integration patterns in sidecar. Covers pull strategy menu, direct merge workflow, squash merge, commit message templates, configurable defaults, and protected branches. Use when working on git merge features or making decisions about merge strategies.

940 70
Explore
marcus/sidecar

keyboard-shortcuts

Reference for keyboard shortcut implementation, keybinding registration, shortcut parity with vim and other TUI tools, and the complete shortcut assignment table across all sidecar plugins. Use when adding or modifying keyboard shortcuts, checking shortcut assignments, resolving key conflicts, or assessing alignment with vim conventions.

940 70
Explore
marcus/sidecar

profile-memory

Profile memory usage in sidecar using Go pprof, system tools, and heap analysis. Covers identifying memory leaks, goroutine leaks, file descriptor accumulation, and CPU profiling. Use when investigating memory issues, profiling performance, debugging memory leaks, or diagnosing unresponsive plugins.

940 70
Explore
marcus/sidecar

create-theme

Create custom color themes for Sidecar, including base theme selection, color overrides, gradient borders, tab styles, per-project themes, community themes, and programmatic theme registration. Use when creating or modifying themes, adjusting UI appearance, or debugging color/style issues. See references/palette-reference.md for the full color palette with all keys and per-theme values.

940 70
Explore

Didn't find tool you were looking for?

Be as detailed as possible for better results