Skip to content

Commit f3cf353

Browse files
committed
docs: update to Probitas 0.5.0 API - migrate assertion methods
Update all documentation and example code to use Probitas 0.5.0 assertion API: - toBeSuccessful() → toBeOk() (universal across all clients) - toHaveContentContaining() → toHaveDataMatching() (HTTP, GraphQL, gRPC) - toHaveContent() → toHaveValueMatching()/toHaveDocMatching() (Redis, MongoDB) - toHaveRowCount() → toHaveRowsCount() (SQL clients) - toHaveHeader() → toHaveHeadersProperty() (HTTP) - toHaveText() → toHaveTextContaining() (HTTP) Add comprehensive documentation for presence/count assertions: - HTTP: toHaveDataPresent() - GraphQL: toHaveErrorsPresent(), toHaveExtensionsProperty() - SQL: toHaveRowsPresent(), toHaveRowCountGreaterThan() - MongoDB: toHaveDocsPresent(), toHaveInsertedCount() - Redis: toHaveValuePresent(), toHaveValueCount() Updated files: - docs/overview.md, docs/client.md, docs/scenario.md - data/index/*.probitas.ts (5 example files) - probitas/site-health.probitas.ts - .claude/content.md
1 parent 4595aba commit f3cf353

9 files changed

Lines changed: 125 additions & 88 deletions

File tree

.claude/content.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ export default scenario("Example")
8686
.resource("http", client.http.createHttpClient())
8787
.step("make request", async ({ http }) => {
8888
const res = await http.get("/api/users");
89-
expect(res).toBeSuccessful().toHaveStatus(200);
89+
expect(res).toBeOk().toHaveStatus(200);
9090
})
9191
.build();
9292
```

data/index/graphql_api.probitas.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ export default scenario("GraphQL API Test", {
1616
`);
1717

1818
expect(res)
19-
.toBeSuccessful()
20-
.toHaveContentContaining({ echo: "Hello GraphQL" });
19+
.toBeOk()
20+
.toHaveDataMatching({ echo: "Hello GraphQL" });
2121
})
2222
.step("echo - with variables", async (ctx) => {
2323
const { gql } = ctx.resources;
@@ -31,8 +31,8 @@ export default scenario("GraphQL API Test", {
3131
);
3232

3333
expect(res)
34-
.toBeSuccessful()
35-
.toHaveContentContaining({ echo: "variable message" });
34+
.toBeOk()
35+
.toHaveDataMatching({ echo: "variable message" });
3636
})
3737
.step("createMessage - mutation", async (ctx) => {
3838
const { gql } = ctx.resources;
@@ -45,6 +45,6 @@ export default scenario("GraphQL API Test", {
4545
}
4646
`);
4747

48-
expect(res).toBeSuccessful();
48+
expect(res).toBeOk();
4949
})
5050
.build();

data/index/grpc_service.probitas.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ export default scenario("gRPC Service Test", {
1414
});
1515

1616
expect(res)
17-
.toBeSuccessful()
18-
.toHaveContentContaining({ message: "Hello from probitas" });
17+
.toBeOk()
18+
.toHaveDataMatching({ message: "Hello from probitas" });
1919
})
2020
.step("EchoWithDelay - delayed response", async (ctx) => {
2121
const { grpc } = ctx.resources;
@@ -25,8 +25,8 @@ export default scenario("gRPC Service Test", {
2525
});
2626

2727
expect(res)
28-
.toBeSuccessful()
29-
.toHaveContentContaining({ message: "delayed" })
28+
.toBeOk()
29+
.toHaveDataMatching({ message: "delayed" })
3030
.toHaveDurationLessThan(5000);
3131
})
3232
.build();

data/index/redis_cache.probitas.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,14 @@ export default scenario("Redis Cache Test", {
1919
await redis.set(key, "hello world");
2020
const res = await redis.get(key);
2121

22-
expect(res).toBeSuccessful().toHaveContent("hello world");
22+
expect(res).toBeOk().toHaveValueMatching("hello world");
2323
})
2424
.step("INCR counter", async (ctx) => {
2525
const { redis } = ctx.resources;
2626
await redis.set("test:counter", "0");
2727
const res = await redis.incr("test:counter");
2828

29-
expect(res).toBeSuccessful().toHaveContent(1);
29+
expect(res).toBeOk().toHaveValueMatching(1);
3030

3131
// Cleanup
3232
await redis.del("test:counter");

data/index/user_api.probitas.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ export default scenario("User API Integration Test", {
3737
const res = await http.get(`/users/${user.id}`);
3838

3939
expect(res)
40-
.toBeSuccessful()
40+
.toBeOk()
4141
.toHaveStatus(200)
42-
.toHaveContentContaining({ id: user.id, name: user.name });
42+
.toHaveDataMatching({ id: user.id, name: user.name });
4343
})
4444
.build();

docs/client.md

Lines changed: 63 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export default scenario("API Test")
2626
.step("Make request", async (ctx) => {
2727
const { http } = ctx.resources;
2828
const res = await http.get("/health");
29-
expect(res).toBeSuccessful();
29+
expect(res).toBeOk();
3030
})
3131
.build();
3232
```
@@ -118,16 +118,17 @@ Validate responses with chainable assertions:
118118

119119
```typescript
120120
expect(res)
121-
.toBeSuccessful() // Status 2xx
121+
.toBeOk() // Status 2xx
122122
.toHaveStatus(200) // Exact status code
123-
.toHaveHeader("content-type", /application\/json/) // Content-Type pattern
124-
.toHaveContentContaining({ name: "Alice" }) // Partial JSON match
123+
.toHaveHeadersProperty("content-type", /application\/json/) // Content-Type pattern
124+
.toHaveDataMatching({ name: "Alice" }) // Partial JSON match
125125
.toHaveDurationLessThan(1000); // Response time limit
126126

127127
// Additional assertions
128-
expect(res).not.toBeSuccessful(); // Status not 2xx
129-
expect(res).toHaveHeader("X-Request-Id");
130-
expect(res).toHaveText(/success/);
128+
expect(res).not.toBeOk(); // Status not 2xx
129+
expect(res).toHaveHeadersProperty("X-Request-Id");
130+
expect(res).toHaveTextContaining(/success/);
131+
expect(res).toHaveDataPresent(); // Check if response has data
131132
```
132133

133134
## SQL Clients
@@ -201,15 +202,20 @@ Validate query results:
201202

202203
```typescript
203204
expect(result)
204-
.toBeSuccessful()
205-
.toHaveRowCount(1)
206-
.toHaveContentContaining({ name: "Alice" });
205+
.toBeOk()
206+
.toHaveRowsCount(1)
207+
.toHaveRowsMatching({ name: "Alice" });
207208

208209
// Match multiple rows
209-
expect(result).toHaveContent([
210+
expect(result).toHaveRowsMatching([
210211
{ id: 1, name: "Alice" },
211212
{ id: 2, name: "Bob" },
212213
]);
214+
215+
// Additional row assertions
216+
expect(result).toHaveRowsPresent(); // Check if query returned any rows
217+
expect(result).toHaveRowCountGreaterThan(0); // More than 0 rows
218+
expect(result).toHaveRowCountLessThanOrEqual(10); // At most 10 rows
213219
```
214220

215221
## gRPC Client
@@ -235,7 +241,7 @@ const res = await grpc.call("echo.EchoService", "Echo", {
235241
message: "Hello",
236242
});
237243

238-
expect(res).toBeSuccessful().toHaveContentContaining({ message: "Hello" });
244+
expect(res).toBeOk().toHaveDataMatching({ message: "Hello" });
239245
const data = res.data();
240246
```
241247

@@ -250,7 +256,7 @@ for await (
250256
count: 3,
251257
})
252258
) {
253-
expect(res).toBeSuccessful();
259+
expect(res).toBeOk();
254260
messages.push(res.data());
255261
}
256262
```
@@ -269,7 +275,7 @@ const res = await grpc.clientStream(
269275
yield { message: "Third" };
270276
},
271277
);
272-
expect(res).toBeSuccessful();
278+
expect(res).toBeOk();
273279
```
274280

275281
### Bidirectional Streaming
@@ -287,7 +293,7 @@ for await (
287293
},
288294
)
289295
) {
290-
expect(res).toBeSuccessful();
296+
expect(res).toBeOk();
291297
console.log("Received:", res.data());
292298
}
293299
```
@@ -310,7 +316,7 @@ const res = await connect.call("echo.EchoService", "Echo", {
310316
message: "Hello",
311317
});
312318

313-
expect(res).toBeSuccessful().toHaveContentContaining({ message: "Hello" });
319+
expect(res).toBeOk().toHaveDataMatching({ message: "Hello" });
314320
```
315321

316322
### Server Streaming
@@ -321,7 +327,7 @@ for await (
321327
count: 3,
322328
})
323329
) {
324-
expect(res).toBeSuccessful();
330+
expect(res).toBeOk();
325331
console.log("Received:", res.data());
326332
}
327333
```
@@ -360,7 +366,7 @@ const res = await graphql.query(
360366
{ id: "1" },
361367
);
362368

363-
expect(res).toBeSuccessful().toHaveContentContaining({
369+
expect(res).toBeOk().toHaveDataMatching({
364370
user: { name: "Alice" },
365371
});
366372
const user = res.data().user;
@@ -383,7 +389,7 @@ const res = await graphql.mutate(
383389
{ input: { name: "Alice", email: "alice@example.com" } },
384390
);
385391

386-
expect(res).toBeSuccessful();
392+
expect(res).toBeOk();
387393
const newUser = res.data().createUser;
388394
```
389395

@@ -402,11 +408,26 @@ const subscription = graphql.subscribe(outdent`
402408
`);
403409

404410
for await (const res of subscription) {
405-
expect(res).toBeSuccessful();
411+
expect(res).toBeOk();
406412
console.log("New user:", res.data().userCreated);
407413
}
408414
```
409415

416+
### Error and Extension Assertions
417+
418+
Check for GraphQL errors and extensions:
419+
420+
```typescript
421+
// Check for errors
422+
expect(res).toHaveErrorsPresent(); // Has GraphQL errors
423+
expect(res).toHaveErrorCount(2); // Exactly 2 errors
424+
expect(res).toHaveErrorCountGreaterThan(0); // Has at least 1 error
425+
426+
// Check for extensions
427+
expect(res).toHaveExtensionsProperty("tracing"); // Has tracing extension
428+
expect(res).toHaveExtensionsPropertyContaining("tracing", { version: 1 }); // Extension with value
429+
```
430+
410431
## Redis Client
411432

412433
The Redis client provides operations for strings, hashes, lists, and sets.
@@ -428,7 +449,7 @@ Common Redis operations:
428449
await redis.set("key", "value");
429450
await redis.set("key", "value", { ex: 3600 }); // With TTL
430451
const result = await redis.get("key");
431-
expect(result).toBeSuccessful().toHaveContent("value");
452+
expect(result).toBeOk().toHaveValueMatching("value");
432453

433454
// Hashes
434455
await redis.hset("user:1", { name: "Alice", age: "30" });
@@ -444,6 +465,12 @@ const tags = await redis.smembers("tags");
444465

445466
// Delete
446467
await redis.del("key");
468+
469+
// Value assertions
470+
expect(result).toHaveValuePresent(); // Check if value exists
471+
expect(result).toHaveValueMatching("expected"); // Match exact value
472+
expect(result).toHaveValueContaining("substring"); // Value contains substring
473+
expect(result).toHaveValueCount(5); // String length or collection size
447474
```
448475

449476
## MongoDB Client
@@ -471,11 +498,11 @@ const result = await users.insertOne({
471498
name: "Alice",
472499
email: "alice@example.com",
473500
});
474-
expect(result).toBeSuccessful();
501+
expect(result).toBeOk();
475502

476503
// Find
477504
const user = await users.findOne({ _id: result.insertedId });
478-
expect(user).toBeSuccessful().toHaveContentContaining({ name: "Alice" });
505+
expect(user).toBeOk().toHaveDocMatching({ name: "Alice" });
479506

480507
// Find many
481508
const allUsers = await users.find({ age: { $gte: 18 } }).toArray();
@@ -488,6 +515,14 @@ await users.updateOne(
488515

489516
// Delete
490517
await users.deleteOne({ _id: result.insertedId });
518+
519+
// Document assertions
520+
expect(result).toHaveDocsPresent(); // Check if documents were returned
521+
expect(result).toHaveDocsCount(5); // Exactly 5 documents
522+
expect(result).toHaveDocsMatching([...]); // Match multiple documents
523+
expect(result).toHaveInsertedCount(1); // 1 document inserted
524+
expect(result).toHaveModifiedCount(1); // 1 document modified
525+
expect(result).toHaveDeletedCount(1); // 1 document deleted
491526
```
492527

493528
## Deno KV Client
@@ -506,7 +541,7 @@ By default, an in-memory database is used for testing.
506541
// Set and get
507542
await kv.set(["users", "1"], { name: "Alice" });
508543
const result = await kv.get(["users", "1"]);
509-
expect(result).toBeSuccessful().toHaveContent({ name: "Alice" });
544+
expect(result).toBeOk().toHaveValueMatching({ name: "Alice" });
510545

511546
// List by prefix
512547
const users = await kv.list({ prefix: ["users"] });
@@ -551,7 +586,7 @@ await channel.sendToQueue("my-queue", content);
551586

552587
// Receive message
553588
const result = await channel.get("my-queue");
554-
expect(result).toBeSuccessful().toHaveContent();
589+
expect(result).toBeOk();
555590
if (result.message) {
556591
await channel.ack(result.message);
557592
}
@@ -584,7 +619,7 @@ await sqs.ensureQueue("my-queue");
584619

585620
// Send message
586621
const result = await sqs.send(JSON.stringify({ event: "user.created" }));
587-
expect(result).toBeSuccessful().toHaveMessageId();
622+
expect(result).toBeOk().toHaveMessageId();
588623

589624
// Receive and process
590625
const messages = await sqs.receive({ maxMessages: 10 });
@@ -652,7 +687,7 @@ Use assertions for expected successes, explicit checks for expected failures:
652687
```typescript
653688
// Expected success - use assertions
654689
const res = await http.get("/users/1");
655-
expect(res).toBeSuccessful().toHaveStatus(200);
690+
expect(res).toBeOk().toHaveStatus(200);
656691

657692
// Expected failure - disable throwing, check manually
658693
const res = await http.get("/users/nonexistent", { throwOnError: false });
@@ -670,7 +705,7 @@ Use retry configuration for network-dependent operations. See
670705
const res = await http.get("/external-api", {
671706
retry: { maxAttempts: 3, backoff: "exponential" },
672707
});
673-
expect(res).toBeSuccessful();
708+
expect(res).toBeOk();
674709
}, {
675710
timeout: 10000, // Allow time for retries
676711
})

docs/overview.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ other backend services.
1212
message queues with unified APIs
1313
- **Type-safe**: Full type inference through the builder chain
1414
- **Fluent assertions**: Natural syntax like
15-
`expect(result).toBeSuccessful().toHaveContentContaining({...})`
15+
`expect(result).toBeOk().toHaveDataMatching({...})`
1616

1717
## Installation
1818

@@ -72,9 +72,9 @@ export default scenario("User API Test")
7272
const res = await http.get("/users/1");
7373

7474
expect(res)
75-
.toBeSuccessful()
75+
.toBeOk()
7676
.toHaveStatus(200)
77-
.toHaveContentContaining({ id: 1 });
77+
.toHaveDataMatching({ id: 1 });
7878
})
7979
.build();
8080
```
@@ -184,19 +184,19 @@ The `expect()` function auto-dispatches based on result type:
184184
```typescript
185185
// HTTP response
186186
expect(httpResponse)
187-
.toBeSuccessful()
187+
.toBeOk()
188188
.toHaveStatus(200)
189-
.toHaveContentContaining({ id: 1 });
189+
.toHaveDataMatching({ id: 1 });
190190

191191
// SQL result
192192
expect(sqlResult)
193-
.toHaveRowCount(1)
194-
.toHaveContentContaining({ name: "Alice" });
193+
.toHaveRowsCount(1)
194+
.toHaveRowsMatching({ name: "Alice" });
195195

196196
// gRPC response
197197
expect(grpcResponse)
198-
.toBeSuccessful()
199-
.toHaveContentContaining({ id: "123" });
198+
.toBeOk()
199+
.toHaveDataMatching({ id: "123" });
200200
```
201201

202202
## Included Utilities

0 commit comments

Comments
 (0)