bdd-vitest 0.1.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +88 -5
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # bdd-vitest
2
2
 
3
- Enforced Given/When/Then for Vitest. Tests become documentation. ~200 lines. Zero config.
3
+ Enforced Given/When/Then for Vitest. Tests become documentation. Zero config.
4
4
 
5
5
  ```ts
6
6
  import { unit, feature, expect } from "bdd-vitest";
@@ -14,7 +14,7 @@ feature("Checkout", () => {
14
14
  });
15
15
  ```
16
16
 
17
- Read just the descriptions - you understand the system without opening production code.
17
+ Read just the descriptions. You understand the system without opening production code.
18
18
 
19
19
  ## Why
20
20
 
@@ -23,7 +23,7 @@ Most test frameworks let you write `it("does something", () => {})` with no stru
23
23
  bdd-vitest makes it impossible:
24
24
 
25
25
  - **Descriptions are required.** Every phase is a `["description", fn]` tuple. TypeScript rejects missing descriptions at compile time.
26
- - **Levels are required.** No generic `scenario` - you must pick `unit`, `component`, `integration`, or `e2e`. Each has enforced timeouts.
26
+ - **Levels are required.** No generic `scenario`. You must pick `unit`, `component`, `integration`, or `e2e`. Each has enforced timeouts.
27
27
  - **Assertions are required.** `then` is mandatory. No test without a check.
28
28
 
29
29
  ## Install
@@ -44,7 +44,7 @@ import { unit, component, integration, e2e } from "bdd-vitest";
44
44
  |-------|---------|-------------------|
45
45
  | `unit` | 100ms | Pure functions, calculations, parsing, validation |
46
46
  | `component` | 5s | One service with mocked deps (mockServer, mockFetch) |
47
- | `integration` | 30s | Multiple real services talking to each other |
47
+ | `integration` | 30s | Real services, real files, real I/O |
48
48
  | `e2e` | 120s | Full system, browser, real network, real database |
49
49
 
50
50
  ```
@@ -74,7 +74,7 @@ component("health check", {
74
74
  });
75
75
  ```
76
76
 
77
- Context flows through - `when` receives `given`'s return, `then` receives both:
77
+ `when` receives `given`'s return. `then` receives both:
78
78
 
79
79
  ```ts
80
80
  unit("FIFO order", {
@@ -138,6 +138,25 @@ component("handles 404", {
138
138
  });
139
139
  ```
140
140
 
141
+ ## Database tests
142
+
143
+ No special API needed. `given` sets up, `cleanup` tears down:
144
+
145
+ ```ts
146
+ integration("finds user by email", {
147
+ given: ["a seeded database", async () => {
148
+ const db = await createTestDb();
149
+ await db.users.insert({ email: "alice@test.com", name: "Alice" });
150
+ return db;
151
+ }],
152
+ when: ["querying", (db) => db.users.findBy({ email: "alice@test.com" })],
153
+ then: ["returns Alice", (user) => expect(user.name).toBe("Alice")],
154
+ cleanup: (db) => db.destroy(),
155
+ });
156
+ ```
157
+
158
+ Works with any database library. Bring your own setup.
159
+
141
160
  ## Table-driven
142
161
 
143
162
  ```ts
@@ -164,6 +183,70 @@ feature("Auth", () => {
164
183
  });
165
184
  ```
166
185
 
186
+ ## Real world example
187
+
188
+ ```ts
189
+ import { unit, component, integration, feature, rule, expect } from "bdd-vitest";
190
+ import { mockServer } from "bdd-vitest/mock-server";
191
+
192
+ feature("Ship AI", () => {
193
+ rule("airlock access", () => {
194
+ unit("denies crew without clearance", {
195
+ given: ["a crew member with no override", () => ({ crew: "Kai", clearance: 0 })],
196
+ when: ["requesting airlock", (ctx) => shipAI.evaluateRequest(ctx)],
197
+ then: ["denies the request", (res) => {
198
+ expect(res.granted).toBe(false);
199
+ expect(res.reason).toContain("insufficient clearance");
200
+ }],
201
+ });
202
+
203
+ unit.outline("clearance levels", [
204
+ { name: "cadet: denied", clearance: 0, expected: false },
205
+ { name: "engineer: denied", clearance: 1, expected: false },
206
+ { name: "commander: granted", clearance: 9, expected: true },
207
+ ], {
208
+ given: (row) => ({ crew: "Kai", clearance: row.clearance as number }),
209
+ when: (ctx) => shipAI.evaluateRequest(ctx),
210
+ then: (res, _ctx, row) => expect(res.granted).toBe(row.expected),
211
+ });
212
+ });
213
+
214
+ rule("crew monitoring API", () => {
215
+ component("reports life signs", {
216
+ given: ["a sensor API", mockServer({
217
+ "GET /crew/kai/vitals": { heartRate: 72, o2: 98, status: "nominal" },
218
+ })],
219
+ when: ["checking vitals", (server) => shipAI.checkCrew("kai", server.url)],
220
+ then: ["reports nominal", (report) => expect(report.status).toBe("nominal")],
221
+ cleanup: (server) => server.close(),
222
+ });
223
+
224
+ component("handles sensor failure", {
225
+ given: ["a failing sensor API", mockServer({
226
+ "GET /crew/kai/vitals": 503,
227
+ })],
228
+ when: ["checking vitals", (server) => shipAI.checkCrew("kai", server.url)],
229
+ then: ["triggers alert", (report) => expect(report.status).toBe("sensor_failure")],
230
+ cleanup: (server) => server.close(),
231
+ });
232
+ });
233
+
234
+ rule("mission log", () => {
235
+ integration("logs all crew requests", {
236
+ given: ["a mission database", async () => {
237
+ const db = await createMissionDb();
238
+ await shipAI.logRequest(db, { crew: "Kai", action: "open_airlock" });
239
+ await shipAI.logRequest(db, { crew: "Yara", action: "check_antenna" });
240
+ return db;
241
+ }],
242
+ when: ["querying the log", (db) => db.logs.findAll()],
243
+ then: ["contains both entries", (logs) => expect(logs).toHaveLength(2)],
244
+ cleanup: (db) => db.destroy(),
245
+ });
246
+ });
247
+ });
248
+ ```
249
+
167
250
  ## API
168
251
 
169
252
  | Export | What |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bdd-vitest",
3
- "version": "0.1.1",
3
+ "version": "1.0.0",
4
4
  "type": "module",
5
5
  "description": "Enforced Given/When/Then for Vitest. ~200 lines. Zero config.",
6
6
  "license": "MIT",