Initial Commit
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
<!-- markdownlint-disable MD024 -->
|
||||
|
||||
# Capability Spec Delta: api-router-in-memory (api-router-in-memory)
|
||||
|
||||
**Package**: `@suaveplan/api-router-in-memory`
|
||||
**Status**: PROPOSED
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Dispatch without a socket
|
||||
|
||||
The package SHALL implement `Router` such that `dispatch(request)` runs the full request pipeline in-process and returns a `Response`-shaped value. No socket, port, or HTTP listener is bound.
|
||||
|
||||
#### Scenario: dispatch returns Response without network I/O
|
||||
|
||||
- **WHEN** a route is registered AND `router.dispatch(new Request("/x"))` is called
|
||||
- **THEN** the result is a `Response` AND no network socket is opened (sanity-checked by asserting `Bun.listen`/`net` modules were not invoked)
|
||||
|
||||
**Verified by:** `src/factory/create-in-memory-router.test.ts::"dispatches without opening any network socket"`
|
||||
|
||||
---
|
||||
|
||||
### Requirement: host.fetch entry point matches design doc
|
||||
|
||||
The package SHALL expose `host.fetch(method, path, init?)` returning a `Promise<Response>`. The signature MUST be compatible with the `createTestHost` ergonomics example in §13.2.
|
||||
|
||||
#### Scenario: host.fetch dispatches a POST with body
|
||||
|
||||
- **WHEN** `host.fetch("POST", "/billing/invoices", { body: { amountCents: 10000, currency: "USD" } })` is called against a registered handler
|
||||
- **THEN** the result has `status === 201` AND the body parses to the expected JSON
|
||||
|
||||
**Verified by:** `src/fetch-shape/fetch-shape.test.ts::"host.fetch POST returns 201 with parsed JSON body"`
|
||||
|
||||
---
|
||||
|
||||
### Requirement: Request recording supports assertions
|
||||
|
||||
The router SHALL maintain a `requests` history when `trackRequests: true`. Each entry records method, path, and request-id. `router.reset()` MUST clear the history.
|
||||
|
||||
#### Scenario: history captures every dispatched request
|
||||
|
||||
- **WHEN** three dispatches happen
|
||||
- **THEN** `router.requests` has length 3 AND each entry records the correct method+path
|
||||
|
||||
#### Scenario: reset clears history
|
||||
|
||||
- **WHEN** `router.reset()` is called after dispatches
|
||||
- **THEN** `router.requests` has length 0
|
||||
|
||||
**Verified by:** `src/recording/request-log.test.ts::"captures every dispatched request"` AND `src/recording/request-log.test.ts::"reset clears history"`
|
||||
|
||||
---
|
||||
|
||||
### Requirement: Conforms to Router contract
|
||||
|
||||
The factory SHALL pass `runRouterConformance` from `@suaveplan/api-router/testing` end-to-end.
|
||||
|
||||
#### Scenario: every Router invariant passes
|
||||
|
||||
- **WHEN** `runRouterConformance("in-memory-direct", createInMemoryRouter)` runs
|
||||
- **THEN** every invariant reports passing
|
||||
|
||||
**Verified by:** `src/factory/create-in-memory-router.spec-conformance.test.ts::"in-memory-direct conforms to Router contract"`
|
||||
|
||||
---
|
||||
|
||||
### Requirement: Registered in `api-host/testing` adapter table
|
||||
|
||||
This adapter SHALL be reachable from `createTestHost({ adapters: { router: "in-memory" } })`. The lookup table in `@suaveplan/api-host/testing` SHALL recognize the `"in-memory"` string sentinel and instantiate this factory.
|
||||
|
||||
#### Scenario: createTestHost resolves the in-memory router
|
||||
|
||||
- **WHEN** a test calls `createTestHost({ adapters: { router: "in-memory" } })`
|
||||
- **THEN** `host.router` is an instance of the factory produced by this package
|
||||
|
||||
**Verified by:** `tests/integration/integration.test.ts::"createTestHost resolves router:\"in-memory\" to this adapter"`
|
||||
|
||||
<!-- markdownlint-enable MD024 -->
|
||||
Reference in New Issue
Block a user