@trieb.work/nextjs-turbo-redis-cache
Version:
Designed for speed, scalability, and optimized performance, nextjs-turbo-redis-cache is your custom cache handler for demanding production environments.
180 lines (130 loc) • 10.7 kB
Markdown
# Test Structure
```
test/
├── playwright/ # E2E tests — browser automation (Playwright)
├── vitest/ # Unit + Integration tests (Vitest)
│ ├── unit/ # Pure unit tests (no external deps)
│ └── integration/ # Integration tests (Redis + Next.js server)
│ └── cache-components/ # Cache Components integration (Next.js 16+)
└── nextjs-test-projects/ # Next.js app fixtures (shared across test types)
```
## Overview
| Layer | Runner | What it validates | Needs Redis? | Needs Next.js app? |
| --------------- | ---------- | ----------------------------------------------------------------------- | ------------ | ------------------ |
| **Unit** | Vitest | Logic in isolation (serializer, prefix resolution, reconnect handling) | No | No |
| **Integration** | Vitest | Cache handler ↔ Redis ↔ Next.js HTTP responses (server-side plumbing) | Yes | Yes |
| **E2E** | Playwright | User-facing behavior in a real browser (Cache Components / `use cache`) | Yes | Yes |
---
## Unit Tests (`test/vitest/unit/`)
**Runner:** Vitest
**Command:** `pnpm test:unit`
**Config:** `vite.config.ts`
Fast tests with no external dependencies. Mocks are used where needed.
| File | What it tests |
| ----------------------------------------- | -------------------------------------------------------------------------------- |
| `serializer.test.ts` | `CacheValueSerializer` interface, JSON round-trips, singleton stability |
| `index.test.ts` | `RedisStringsHandler` constructor options, default behaviors |
| `utils/prefix.test.ts` | `resolveKeyPrefix` logic (BUILD_ID fallback, env var precedence) |
| `reconnect-socket-already-opened.test.ts` | Regression: reconnect logic doesn't call `connect()` when socket is already open |
```bash
pnpm test:unit # single run
pnpm test:unit:watch # watch mode
pnpm test:unit:coverage # with coverage report (used in CI)
```
---
## Integration Tests (`test/vitest/integration/`)
**Runner:** Vitest
**Command:** `pnpm test:integration`
**Config:** `vite.config.ts`
**Requires:** Redis on localhost:6379, pre-built Next.js test app
These tests spawn a real Next.js server as a child process, make `fetch()` requests against it, and verify both HTTP responses and Redis state directly.
### Standard Integration (`nextjs-cache-handler.integration.test.ts`)
Full cache lifecycle: static pages, fetch caching, revalidation, tag invalidation, TTL behavior. In CI this runs against a matrix of Next.js versions (15.4–16.2).
```bash
pnpm test:integration
```
### BUILD_ID Prefix (`build-id-prefix.integration.test.ts`)
Verifies that when neither `KEY_PREFIX` nor `VERCEL_URL` is set, the handler falls back to `.next/BUILD_ID` as the Redis key prefix. Runs in its own CI job because it needs a clean environment without those env vars.
```bash
pnpm test:integration:build-id-prefix
```
### Cache Components (`cache-components/`)
Integration tests specific to Next.js 16 Cache Components (`use cache`). Uses `next-app-16-2-6-cache-components` as the test app.
| File | What it tests |
| -------------------------------------- | ------------------------------------------------------------------------------------------------------ |
| `cache-components.integration.test.ts` | `use cache` lifecycle: store, retrieve, tag invalidation, `cacheLife` expiry |
| `redis-kill-reconnect.test.ts` | Graceful recovery when Redis drops and reconnects (main client ping only) |
| `redis-subscriber-outage.test.ts` | Issue #86: subscriber PubSub does not recover after Redis outage (expected to fail until bug is fixed) |
| `redis-quit-vs-disconnect.test.ts` | `quit()` does not reliably close a subscriber during an outage; `disconnect()` does |
`redis-kill-reconnect.test.ts` uses a container runtime and auto-detects `podman` first, then `docker`. You can force runtime selection with `CONTAINER_RUNTIME=podman` or `CONTAINER_RUNTIME=docker`.
```bash
pnpm test:integration:cache-components
```
**Prerequisites for all integration tests:**
```bash
cd test/nextjs-test-projects/<app-name>
pnpm install && pnpm build
```
---
## E2E Tests (`test/playwright/`)
**Runner:** Playwright
**Command:** `pnpm test:e2e`
**Config:** `playwright.config.ts`
**Requires:** Redis on localhost:6379 (Playwright auto-starts `next-app-16-2-6-cache-components` via `webServer`)
Browser-based tests that validate Cache Components behavior from the user's perspective. Playwright was introduced because the Cache Components (`use cache`) feature in Next.js 16 relies on interactions that `fetch()` alone cannot reproduce:
- **Server Actions** are triggered by form submissions / button clicks — requires a real browser context
- `**updateTag`\*\* must be called from within a Server Action — needs actual UI interaction to verify
- **Cookie-based cache keys** depend on the browser sending cookies during navigation
- **Stale-while-revalidate** effects are only observable through page reloads and DOM diffing
The Vitest cache-components integration tests verify the server-side plumbing (Redis state, HTTP responses). Playwright closes the gap by testing the full user-facing flow.
| File | What it tests |
| -------------------- | -------------------------------------------------------------------------------------------------------------------- |
| `cache-lab.spec.ts` | `use cache` stability, tag invalidation (`updateTag`/`revalidateTag`), runtime cookie-based cache keys, SWR behavior |
| `update-tag.spec.ts` | `updateTag` via Server Actions (button click → action → UI update) |
```bash
pnpm test:e2e
# Test against a specific Next.js version:
PLAYWRIGHT_TEST_APP=next-app-16-0-11-cache-components pnpm test:e2e
# Or point at an already-running server:
PLAYWRIGHT_BASE_URL=http://localhost:3001 pnpm test:e2e
```
---
## Next.js Test Projects (`test/nextjs-test-projects/`)
Minimal Next.js applications used as fixtures. They are not test runners — they provide the server that tests run against.
| App | Next.js | Used by |
| ----------------------------------- | ------- | -------------------------------------------------------------- |
| `next-app-15-4-11` | 15.4.11 | Integration (matrix, default for local), build-id-prefix |
| `next-app-16-0-11` | 16.0.11 | Integration (matrix) |
| `next-app-16-2-6` | 16.2.6 | Integration (matrix) |
| `next-app-16-0-11-cache-components` | 16.0.11 | Integration (cache-components matrix), E2E (Playwright matrix) |
| `next-app-16-2-6-cache-components` | 16.2.6 | Integration (cache-components matrix), E2E (Playwright matrix) |
| `next-app-customized` | — | Example of custom config (referenced in project README) |
---
## CI Jobs
The CI workflow (`.github/workflows/ci.yml`) is structured as:
```
lint-and-unit → Lint + Unit Tests + Coverage
├── integration → Matrix: 3 Next.js versions (15.4–16.2)
├── integration-build-id-prefix → Isolated BUILD_ID prefix test
├── integration-cache-components → Matrix: 16.0.11 + 16.2.6 cache-components
└── e2e → Matrix: Playwright against 16.0.11 + 16.2.6
```
`lint-and-unit` runs first as a gate. All other jobs run in parallel after it passes.
| CI Job | Test App(s) | What runs |
| ------------------------------ | --------------------------------------------------------- | --------------------------------------------------------------- |
| `lint-and-unit` | — | `pnpm lint` + `pnpm test:unit:coverage` |
| `integration` | `next-app-15-4-11`, `next-app-16-0-11`, `next-app-16-2-6` | `pnpm test:integration` (per matrix entry) |
| `integration-build-id-prefix` | `next-app-15-4-11` | `pnpm test:integration:build-id-prefix` |
| `integration-cache-components` | `next-app-16-{0-3,2-3}-cache-components` | `pnpm test:integration:cache-components` + Redis kill/reconnect |
| `e2e` | `next-app-16-{0-3,2-3}-cache-components` | `pnpm test:e2e` (Playwright) |
---
## Environment Variables
| Variable | Used by | Description |
| ----------------------- | ------------------------------ | ------------------------------------------------------------------------- |
| `NEXT_TEST_APP` | Integration | Which test app to use (default: `next-app-15-4-11`) |
| `CACHE_COMPONENTS_APP` | Integration (cache-components) | Which cache-components app (default: `next-app-16-2-6-cache-components`) |
| `PLAYWRIGHT_TEST_APP` | E2E | Which app Playwright starts (default: `next-app-16-2-6-cache-components`) |
| `PLAYWRIGHT_BASE_URL` | E2E | Override base URL (skips `webServer` auto-start) |
| `SKIP_BUILD` | Integration | Skip Next.js build if app is pre-built |
| `DEBUG_INTEGRATION` | Integration | Print child process stdout/stderr |
| `CACHE_COMPONENTS_PORT` | Integration (cache-components) | Port for the server (default: 3065) |