Skip to content
Back to skills

Testing Guide

ASecurity

Defines Seagull testing strategy, tradeoffs, and required coverage. Use when adding or updating tests, implementing features that touch backend/frontend, introducing concurrency/locks, or when asked how to structure/run tests in this repo.

  • 207 stars
  • 0 votes
  • 0 copies
  • 5 views
  • Added February 7, 2026
developmentgobashsqlreactnodetestingapifrontendbackend

Works with

  • cli
  • api

Security analysis

A100/100

Pro scans all 9 files and shows the line behind each finding

Scanned February 12, 2026

npx -y skills add NeverSight/skills_feed --skill testing-guide --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Testing Guide?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Testing Guide
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/neversight-testing-guide/badge)](https://www.skillsdirectory.com/skills/neversight-testing-guide)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: testing-guide
description: Defines Seagull testing strategy, tradeoffs, and required coverage. Use when adding or updating tests, implementing features that touch backend/frontend, introducing concurrency/locks, or when asked how to structure/run tests in this repo.
---

# Seagull Testing Guide

## Quick start (default approach)

When implementing a feature that touches backend/frontend:

1. **Classify behavior**:
   - **service semantics** (pure rules): put tests near the service
   - **cross-layer behavior** (tRPC + react-query + cache invalidation + timers): use `packages/test-integration`
   - **deployment-shape behavior** (real Postgres + pooling + true concurrency): run strict smoke tests pre-release

2. **Prefer real integrations over hook mocks**:
   - Do **not** mock `useMutation` when the goal is react-query/tRPC integration.
   - Only mock/alias **platform-only deps** (Expo/RN modules that break node/jsdom).

3. **Use header-injected identity for multi-user tests**:
   - Client: set `httpBatchLink({ headers: () => ({ 'x-test-user-id': userId }) })`
   - Server: in `createContext({ headers })`, read `headers.get('x-test-user-id')`

4. **Test DB schema is schema-driven (no hand-written DDL)**:
   - `packages/test-integration/src/db/pglite.ts` applies a generated `packages/test-integration/src/db/schema.sql` (single file)
   - Generate it from current Drizzle schema before running tests:
     - `pnpm -F @acme/test-integration db:schema`
   - `pnpm -F @acme/test-integration test` should run `db:schema` first (so forgetting to regenerate only breaks tests, not production).
   - PGlite compatibility: we polyfill `gen_random_uuid()` used by Drizzle schema/DDL.
   - This prevents schema drift and avoids migration ordering/duplication issues in tests.

## Where tests live

- **Cross-layer**: `packages/test-integration/src/**`
  - in-memory tRPC fetch: `packages/test-integration/src/trpc/inMemoryFetch.ts`
  - PGlite DB harness: `packages/test-integration/src/db/pglite.ts`
  - Test schema SQL (generated): `packages/test-integration/src/db/schema.sql`
  - Generator script: `packages/test-integration/scripts/generate-schema-sql.mjs`
  - example tests:
    - expiry: `packages/test-integration/src/trpc/tripLock.expiry.test.ts`
    - concurrency smoke: `packages/test-integration/src/trpc/tripLock.concurrent.test.ts`
  - Expo business examples:
    - trip/edit: `packages/test-integration/src/expo/trip/edit/**`
    - wishlist: `packages/test-integration/src/expo/wishlist/**`
- **Backend package tests**: `packages/api/src/**/*.test.ts`

## How to run

```bash
pnpm test
pnpm -F @acme/test-integration test
pnpm -F @acme/test-integration typecheck
pnpm -F @acme/api test
pnpm -F @acme/api typecheck
```

## When DB schema changes

After changing `packages/db/src/schema.ts` (or schema modules), regenerate test schema SQL so PGlite tests stay in sync:

```bash
pnpm -F @acme/test-integration db:schema
```

## Test case style rules

- **One behavior per test**: a test name should read like a requirement.
- **Assert the contract**:
  - success payload shape
  - error code (`CONFLICT`, `UNAUTHORIZED`, etc.)
  - cache behavior (invalidate/refetch) where relevant
- **Avoid flakiness**:
  - prefer deterministic triggers over “sleep”
  - if time is essential, isolate it (DB state manipulation or controlled timers)

## FK/seed policy (important after migrations reuse)

- PGlite applies real FK/unique constraints from Drizzle migrations.
- If you insert rows directly, **seed required parents first** (notably `"user"`).
- Prefer seed helpers in `packages/test-integration/src/trpc/api/seed.ts`:
  - `seedUser/seedTrip/seedWishlistJar/...` (helpers ensure required parents exist).
- For router/hook tests that use `createApiTestServer()`, authenticated requests (via header or cookie `x-test-user-id`) will **auto-upsert `"user"`** to keep tests concise.

## Concurrency policy (locks/idempotency)

### Implementation guidance

For lock acquisition, prefer **DB-atomic** statements (e.g. `onConflictDoUpdate + where + returning`) so correctness does not depend on JS scheduling.

### Testing guidance

Use two stages:
- **CI/PR smoke (fast)**: multi-user `Promise.allSettled` concurrency test verifying:
  - exactly one success, rest `CONFLICT`
  - no raw DB errors leak to the client
- **Pre-release strict smoke**: run the same scenario against **real Postgres** to cover pooling/isolation/scheduler differences.

## Definition of Done (mandatory coverage)

When a feature is “done”, tests must cover **all necessary scenarios** (not “at least one test”).

### Backend (packages/api)
- **Service rules**: cover all branches and boundary cases (expiry edges, ownership checks, conflict mapping, empty-return defenses).
- **tRPC route changes**: cover:
  - happy path
  - key failure path(s) with correct error codes/shape
  - at least one invalid input path

### Frontend (Expo business layer)
- **Effects/polling/side effects**: cover:
  - trigger conditions and call counts
  - success and failure behavior (invalidate/refetch, error handling)
  - cleanup (intervals/subscriptions released)

### Cross-layer (default required)
- Any feature that touches backend interaction (query/mutation/errors/cache/timers/concurrency) must add `packages/test-integration` tests covering all necessary scenarios.

## Reference

For the full written guide, see `docs/testing.md`.

Files in this skill

  • SKILL.md5.3 KB
  • description_cn.txt211 B
  • description_de.txt344 B
  • description_en.txt240 B
  • description_es.txt297 B
  • description_fr.txt346 B
  • description_ja.txt348 B
  • description_ko.txt332 B
  • description_tw.txt211 B

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.