SyncingBoarddocs

Testing & Quality Assurance

October 20, 2018~614 wordsarchitecture/testing.md

Testing & Quality Assurance

SyncingBoard enforces strict automated testing across security, rate limiting, URL parsing, and serverless API endpoints using Vitest.


Testing Strategy & Infrastructure

SyncingBoard's test suite runs inside Vitest (yarn test) in zero-network isolation. All external Figma, Miro, Ably, and Upstash Redis network calls are mocked (or isolated behind pure functions) to ensure 100% deterministic test execution in seconds.

graph TD ci["GitHub Actions CI<br/>(.github/workflows/ci.yml)"] --> vitest["Vitest Test Runner<br/>(yarn test)"] vitest --> unit["Unit Tests<br/>(tokens, parsers)"] vitest --> rate["Rate Limiting Tests<br/>(sliding window, 429 headers)"] vitest --> api["API Route Tests<br/>(Figma render, Miro update)"]

Test Suites Breakdown

SyncingBoard includes 123 passing automated tests across 16 specialized test files:

Test FileCategoryFocus Area & Assertions
src/lib/tokens.test.tsSecurityCryptographic token security, SHA-256 one-way hashing (tok:sha256(token)), pairing ID generation, and entropy validation.
src/lib/docs.test.tsDocs EngineDocument indexing, case-insensitive slug resolution (/docs/LICENSE), heading extraction, and word counts.
src/app/miro-plugin/figmaUrlParser.test.tsParsersRegex extraction of fileKey and nodeId from Figma web URLs, desktop app links, and frame selection parameters.
src/app/miro-plugin/penpotUrlParser.test.tsParsersRegex extraction of fileId, pageId, and shapeId from Penpot workspace URLs.
src/lib/rate-limit.test.tsRate LimitingSliding-window algorithm, token-hash caller identification, daily budget counters, and 429 Too Many Requests JSON body + Retry-After headers.
src/app/api/oauth/store/route.test.tsOAuth HandshakeTemporary 300s Redis OAuth state store (POST /api/oauth/store) and one-time token retrieval/deletion (GET + DEL).
src/app/api/docs/search/route.test.tsSearch EngineFull-text search endpoint (GET /api/docs/search?q=...), relevancy scoring, section deep-linking, and term highlighting.
src/app/api/figma/render/route.test.tsAPI RoutesFigma cloud REST image rendering endpoint (POST /api/figma/render), scale parameter validation, and binary image stream forwarding.
src/app/api/figma/render-batch/route.test.tsAPI RoutesMulti-frame batch rendering (POST /api/figma/render-batch), 3-frame batch cap enforcement, and payload transformation.
src/app/api/figma/node-info/route.test.tsAPI Routes & FallbacksFigma frame metadata extraction (POST /api/figma/node-info) and fallback title resolution during network exceptions.
src/app/api/miro/update-image/route.test.tsAPI Routes & CanvasMiro image widget binary updating (PATCH /api/miro/update-image), multipart form parsing, and title metadata signature preservation.
src/lib/relayRedis.test.tsRelay Fairness & PoolsderiveRelayStatusLevel thresholds (incl. 0 ceiling = unlimited), parsePoolLimit, planAcquire/planTransfer (40-session pool: renew/conflict/full), selectEvictionCandidate (oldest-orphan eviction, never evicts an active Miro pairing), planCompanionTokenAcquisition (180-token cap, orphan eviction, full-at-cap) — Redis-free pure planners mirroring the Lua scripts.
src/lib/ablyTokenCache.test.tsClient Cache (R5)Ably token cache: stores/retrieves unexpired tokens, expiry invalidation, reuse within the 2h token TTL.
src/app/api/relay/request/route.test.tsAPI Routes (R4)Async-only relay endpoint: 400 rejection of synchronous callers before any Ably/Redis work, plus the async happy-path (reaches the request path).
src/app/api/relay/status/route.test.tsAPI Routes (R1)Community relay snapshot (activeSessions/maxSessions/status), 503 when the status store is unavailable, transfer-conflict fields (userConflict/activeBoardId), malformed userIdHash ignored without a Redis lookup.
src/app/api/ably/token/route.test.tsAPI Routes (Design B)Pre-external-call validation: 400 for invalid pairingId/sessionId/userIdHash, and the graceful 500 when ABLY_API_KEY is not configured (409/429 capacity decisions are covered by the relayRedis planners).

Running Tests Locally

Run the test suite during development using the following commands:

# Run all 123 tests once
yarn test

# Run tests in interactive watch mode
yarn test --watch

# Run tests with UI dashboard
yarn test --ui

# Verify TypeScript types and ESLint rules
yarn lint

# Verify full production build compilation
yarn build

Mocking Principles & Zero-Network Guarantee

To ensure tests execute fast without requiring real API keys or external services:

  1. Figma REST API: Mocked via global.fetch spies returning sample JSON frame hierarchies and binary PNG buffers.
  2. Upstash Redis: Mocked using in-memory sliding window state stores (Map<string, { count, reset }>) so rate-limiting logic is tested without live Redis connections.
  3. Miro Web SDK: Mocked using synthetic widget objects asserting isLocked, title, and scale properties.
  4. Relay fairness (Redis Lua): The atomic Lua scripts are mirrored as exported pure functions (planAcquire, planTransfer, selectEvictionCandidate, planCompanionTokenAcquisition, planCompanionBinding) tested directly — the Redis behavior is verified without a live Upstash instance, and the Lua executes the same decision rules server-side.
On this page