@griffin-app/griffin-ts 0.1.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 (89) hide show
  1. package/ASSERTIONS_QUICK_REF.md +161 -0
  2. package/README.md +297 -0
  3. package/dist/assertions.d.ts +136 -0
  4. package/dist/assertions.d.ts.map +1 -0
  5. package/dist/assertions.js +230 -0
  6. package/dist/assertions.js.map +1 -0
  7. package/dist/builder.d.ts +168 -0
  8. package/dist/builder.d.ts.map +1 -0
  9. package/dist/builder.js +165 -0
  10. package/dist/builder.js.map +1 -0
  11. package/dist/constants.d.ts +5 -0
  12. package/dist/constants.d.ts.map +1 -0
  13. package/dist/constants.js +6 -0
  14. package/dist/constants.js.map +1 -0
  15. package/dist/example-sequential.d.ts +11 -0
  16. package/dist/example-sequential.d.ts.map +1 -0
  17. package/dist/example-sequential.js +160 -0
  18. package/dist/example-sequential.js.map +1 -0
  19. package/dist/example.d.ts +9 -0
  20. package/dist/example.d.ts.map +1 -0
  21. package/dist/example.js +36 -0
  22. package/dist/example.js.map +1 -0
  23. package/dist/frequency.d.ts +15 -0
  24. package/dist/frequency.d.ts.map +1 -0
  25. package/dist/frequency.js +34 -0
  26. package/dist/frequency.js.map +1 -0
  27. package/dist/http-methods.d.ts +6 -0
  28. package/dist/http-methods.d.ts.map +1 -0
  29. package/dist/http-methods.js +9 -0
  30. package/dist/http-methods.js.map +1 -0
  31. package/dist/index.d.ts +24 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +62 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/response-formats.d.ts +4 -0
  36. package/dist/response-formats.d.ts.map +1 -0
  37. package/dist/response-formats.js +7 -0
  38. package/dist/response-formats.js.map +1 -0
  39. package/dist/schema-exports.d.ts +6 -0
  40. package/dist/schema-exports.d.ts.map +1 -0
  41. package/dist/schema-exports.js +43 -0
  42. package/dist/schema-exports.js.map +1 -0
  43. package/dist/schema.d.ts +311 -0
  44. package/dist/schema.d.ts.map +1 -0
  45. package/dist/schema.js +214 -0
  46. package/dist/schema.js.map +1 -0
  47. package/dist/secrets.d.ts +56 -0
  48. package/dist/secrets.d.ts.map +1 -0
  49. package/dist/secrets.js +74 -0
  50. package/dist/secrets.js.map +1 -0
  51. package/dist/sequential-builder.d.ts +127 -0
  52. package/dist/sequential-builder.d.ts.map +1 -0
  53. package/dist/sequential-builder.js +128 -0
  54. package/dist/sequential-builder.js.map +1 -0
  55. package/dist/shared.d.ts +8 -0
  56. package/dist/shared.d.ts.map +1 -0
  57. package/dist/shared.js +36 -0
  58. package/dist/shared.js.map +1 -0
  59. package/dist/target.d.ts +33 -0
  60. package/dist/target.d.ts.map +1 -0
  61. package/dist/target.js +53 -0
  62. package/dist/target.js.map +1 -0
  63. package/dist/type-exports.d.ts +6 -0
  64. package/dist/type-exports.d.ts.map +1 -0
  65. package/dist/type-exports.js +7 -0
  66. package/dist/type-exports.js.map +1 -0
  67. package/dist/wait.d.ts +9 -0
  68. package/dist/wait.d.ts.map +1 -0
  69. package/dist/wait.js +8 -0
  70. package/dist/wait.js.map +1 -0
  71. package/package.json +43 -0
  72. package/src/assertions.ts +327 -0
  73. package/src/builder.ts +336 -0
  74. package/src/constants.ts +5 -0
  75. package/src/example-sequential.ts +191 -0
  76. package/src/example.ts +55 -0
  77. package/src/frequency.ts +38 -0
  78. package/src/http-methods.ts +5 -0
  79. package/src/index.ts +70 -0
  80. package/src/response-formats.ts +3 -0
  81. package/src/schema-exports.ts +43 -0
  82. package/src/schema.ts +289 -0
  83. package/src/secrets.ts +112 -0
  84. package/src/sequential-builder.ts +254 -0
  85. package/src/shared.ts +46 -0
  86. package/src/target.ts +55 -0
  87. package/src/type-exports.ts +20 -0
  88. package/src/wait.ts +4 -0
  89. package/tsconfig.json +20 -0
@@ -0,0 +1,161 @@
1
+ # Assertion DSL Quick Reference
2
+
3
+ ## Basic Structure
4
+
5
+ ```typescript
6
+ .assert((state) => [
7
+ Assert(state["node_name"].accessor["path"]).predicate(),
8
+ ])
9
+ ```
10
+
11
+ ## Accessors
12
+
13
+ | Accessor | Description | Example |
14
+ | ---------- | -------------------- | --------------------------------------- |
15
+ | `.body` | Response body (JSON) | `state["node"].body["data"]["id"]` |
16
+ | `.headers` | Response headers | `state["node"].headers["content-type"]` |
17
+ | `.status` | HTTP status code | `state["node"].status` |
18
+
19
+ ## Array Access
20
+
21
+ ```typescript
22
+ state["node"].body["items"].at(0)["name"]; // First item
23
+ state["node"].body["matrix"].at(2).at(3); // 2D array
24
+ ```
25
+
26
+ ## Unary Predicates
27
+
28
+ | Predicate | Description | Negation |
29
+ | -------------- | ---------------------------- | -------------------------------- |
30
+ | `.isNull()` | Value is null | `.not.isNull()` / `.isDefined()` |
31
+ | `.isDefined()` | Value is not null | `.not.isDefined()` / `.isNull()` |
32
+ | `.isTrue()` | Value is true | `.not.isTrue()` |
33
+ | `.isFalse()` | Value is false | `.not.isFalse()` |
34
+ | `.isEmpty()` | String/array/object is empty | `.not.isEmpty()` |
35
+
36
+ ## Binary Predicates - Equality
37
+
38
+ | Predicate | Description | Example |
39
+ | ---------------- | --------------------- | ------------------------------------- |
40
+ | `.equals(x)` | Value equals x | `Assert(status).equals(200)` |
41
+ | `.not.equals(x)` | Value doesn't equal x | `Assert(error).not.equals("timeout")` |
42
+
43
+ ## Binary Predicates - Comparison
44
+
45
+ | Predicate | Description | Example |
46
+ | ------------------------ | ----------- | ------------------------------------ |
47
+ | `.greaterThan(x)` | Value > x | `Assert(count).greaterThan(0)` |
48
+ | `.greaterThanOrEqual(x)` | Value >= x | `Assert(age).greaterThanOrEqual(18)` |
49
+ | `.lessThan(x)` | Value < x | `Assert(time_ms).lessThan(500)` |
50
+ | `.lessThanOrEqual(x)` | Value <= x | `Assert(score).lessThanOrEqual(100)` |
51
+
52
+ Negations reverse the operator:
53
+
54
+ - `.not.greaterThan(100)` → value <= 100
55
+ - `.not.lessThan(0)` → value >= 0
56
+
57
+ ## Binary Predicates - Strings
58
+
59
+ | Predicate | Description | Example |
60
+ | -------------------- | --------------------------- | ---------------------------------------- |
61
+ | `.contains(x)` | String contains x | `Assert(type).contains("json")` |
62
+ | `.not.contains(x)` | String doesn't contain x | `Assert(url).not.contains("staging")` |
63
+ | `.startsWith(x)` | String starts with x | `Assert(path).startsWith("/api/")` |
64
+ | `.not.startsWith(x)` | String doesn't start with x | `Assert(version).not.startsWith("v1.")` |
65
+ | `.endsWith(x)` | String ends with x | `Assert(email).endsWith("@example.com")` |
66
+ | `.not.endsWith(x)` | String doesn't end with x | `Assert(file).not.endsWith(".tmp")` |
67
+
68
+ ## Common Patterns
69
+
70
+ ### Status Checks
71
+
72
+ ```typescript
73
+ Assert(state["node"].status).equals(200);
74
+ Assert(state["node"].status).lessThan(400); // Any success
75
+ Assert(state["node"].status).not.equals(500); // Not server error
76
+ ```
77
+
78
+ ### Existence Checks
79
+
80
+ ```typescript
81
+ Assert(state["node"].body["id"]).not.isNull();
82
+ Assert(state["node"].body["data"]).isDefined();
83
+ Assert(state["node"].body["items"]).not.isEmpty();
84
+ ```
85
+
86
+ ### Value Validation
87
+
88
+ ```typescript
89
+ Assert(state["node"].body["email"]).equals("test@example.com");
90
+ Assert(state["node"].body["age"]).greaterThanOrEqual(18);
91
+ Assert(state["node"].body["score"]).lessThan(100);
92
+ ```
93
+
94
+ ### String Matching
95
+
96
+ ```typescript
97
+ Assert(state["node"].headers["content-type"]).contains("application/json");
98
+ Assert(state["node"].body["version"]).startsWith("v2.");
99
+ Assert(state["node"].body["email"]).endsWith("@example.com");
100
+ ```
101
+
102
+ ### Boolean Checks
103
+
104
+ ```typescript
105
+ Assert(state["node"].body["active"]).isTrue();
106
+ Assert(state["node"].body["deleted"]).isFalse();
107
+ Assert(state["node"].body["verified"]).not.isFalse();
108
+ ```
109
+
110
+ ### Array Elements
111
+
112
+ ```typescript
113
+ Assert(state["node"].body["items"].at(0)["name"]).equals("First");
114
+ Assert(state["node"].body["users"].at(2)["active"]).isTrue();
115
+ ```
116
+
117
+ ## Multi-Node Example
118
+
119
+ ```typescript
120
+ createTestBuilder({ name: "user-flow" })
121
+ .request("create", { method: POST /* ... */ })
122
+ .request("verify", { method: GET /* ... */ })
123
+ .assert((state) => [
124
+ // Check create response
125
+ Assert(state["create"].status).equals(201),
126
+ Assert(state["create"].body["id"]).not.isNull(),
127
+
128
+ // Check verify response
129
+ Assert(state["verify"].status).equals(200),
130
+ Assert(state["verify"].body["email"]).equals("test@example.com"),
131
+ ]);
132
+ ```
133
+
134
+ ## Type Safety
135
+
136
+ TypeScript provides autocomplete and errors:
137
+
138
+ ```typescript
139
+ .request("user_create", { /* ... */ })
140
+ .assert((state) => [
141
+ state["user_create"] // ✓ Autocomplete shows this node
142
+ state["typo"] // ❌ TypeScript error
143
+
144
+ state["user_create"].body // ✓ Valid accessor
145
+ state["user_create"].invalid // ❌ TypeScript error
146
+ ])
147
+ ```
148
+
149
+ ## Cheat Sheet
150
+
151
+ | Task | Code |
152
+ | ----------------- | -------------------------------------------------------- |
153
+ | Status is 200 | `Assert(state["n"].status).equals(200)` |
154
+ | Body field exists | `Assert(state["n"].body["x"]).not.isNull()` |
155
+ | String contains | `Assert(state["n"].body["msg"]).contains("ok")` |
156
+ | Number in range | `Assert(state["n"].body["age"]).greaterThanOrEqual(18)` |
157
+ | Boolean true | `Assert(state["n"].body["active"]).isTrue()` |
158
+ | Header has value | `Assert(state["n"].headers["x-id"]).not.isEmpty()` |
159
+ | Array not empty | `Assert(state["n"].body["items"]).not.isEmpty()` |
160
+ | First array item | `Assert(state["n"].body["items"].at(0)["name"])...` |
161
+ | Nested object | `Assert(state["n"].body["user"]["profile"]["email"])...` |
package/README.md ADDED
@@ -0,0 +1,297 @@
1
+ # griffin Test System
2
+
3
+ The griffin Test System provides a TypeScript DSL for defining API tests. Tests are written in TypeScript and output JSON test plans that can be executed by the plan executor.
4
+
5
+ ## Features
6
+
7
+ - TypeScript DSL for defining API checks
8
+ - Chainable API for building test plans
9
+ - Support for endpoints, waits, assertions, and edges
10
+ - Outputs JSON test plans for execution
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ npm install griffin
16
+ ```
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ npm install
22
+ npm run build
23
+ ```
24
+
25
+ ## Usage
26
+
27
+ Create test files in `__griffin__` directories. When executed, they output JSON test plans.
28
+
29
+ griffin provides two builder APIs:
30
+
31
+ - **`createTestBuilder`**: Simple sequential tests (recommended for most use cases)
32
+ - **`createGraphBuilder`**: Complex graphs with parallel execution and branching
33
+
34
+ ### Sequential Builder (Recommended for Simple Tests)
35
+
36
+ The sequential builder automatically connects steps in order - no need to manage edges manually.
37
+
38
+ ```typescript
39
+ import { GET, createTestBuilder, JSON, Frequency } from "griffin-ts";
40
+
41
+ const plan = createTestBuilder({
42
+ name: "health-check",
43
+ frequency: Frequency.every(1).minute(),
44
+ })
45
+ .request({
46
+ method: GET,
47
+ response_format: JSON,
48
+ path: "/health",
49
+ })
50
+ .assert([
51
+ { type: "status", expected: 200 },
52
+ { type: "body", expected: { status: "ok" } },
53
+ ])
54
+ .build();
55
+
56
+ export default plan;
57
+ ```
58
+
59
+ #### Sequential Example with Waits
60
+
61
+ ```typescript
62
+ import {
63
+ GET,
64
+ POST,
65
+ createTestBuilder,
66
+ JSON,
67
+ Frequency,
68
+ Wait,
69
+ } from "griffin-ts";
70
+
71
+ const plan = createTestBuilder({
72
+ name: "create-and-verify-user",
73
+ frequency: Frequency.every(5).minute(),
74
+ })
75
+ .request({
76
+ method: POST,
77
+ response_format: JSON,
78
+ path: "/api/v1/users",
79
+ body: { name: "Test User", email: "test@example.com" },
80
+ })
81
+ .assert([{ type: "status", expected: 201 }])
82
+ .wait(Wait.seconds(2))
83
+ .request({
84
+ method: GET,
85
+ response_format: JSON,
86
+ path: "/api/v1/users/test@example.com",
87
+ })
88
+ .assert([
89
+ { type: "status", expected: 200 },
90
+ { type: "body.name", expected: "Test User" },
91
+ ])
92
+ .build();
93
+
94
+ export default plan;
95
+ ```
96
+
97
+ ### Graph Builder (For Complex Workflows)
98
+
99
+ The graph builder gives you full control over the test graph, enabling parallel execution and complex branching.
100
+
101
+ ```typescript
102
+ import {
103
+ GET,
104
+ POST,
105
+ createGraphBuilder,
106
+ Endpoint,
107
+ Assertion,
108
+ WaitNode,
109
+ JSON,
110
+ START,
111
+ END,
112
+ Frequency,
113
+ Wait,
114
+ } from "griffin-ts";
115
+
116
+ const plan = createGraphBuilder({
117
+ name: "foo-bar-check",
118
+ frequency: Frequency.every(1).minute(),
119
+ })
120
+ .addNode(
121
+ "create_foo",
122
+ Endpoint({
123
+ method: POST,
124
+ response_format: JSON,
125
+ path: "/api/v1/foo",
126
+ body: { name: "test", value: 42 },
127
+ }),
128
+ )
129
+ .addNode(
130
+ "get_foo",
131
+ Endpoint({
132
+ method: GET,
133
+ response_format: JSON,
134
+ path: "/api/v1/foo/1",
135
+ }),
136
+ )
137
+ .addNode("wait_between", WaitNode(Wait.seconds(2)))
138
+ .addNode("check_status", Assertion([{ type: "status", expected: 200 }]))
139
+ .addEdge(START, "create_foo")
140
+ .addEdge("create_foo", "wait_between")
141
+ .addEdge("wait_between", "get_foo")
142
+ .addEdge("get_foo", "check_status")
143
+ .addEdge("check_status", END)
144
+ .build();
145
+
146
+ export default plan;
147
+ ```
148
+
149
+ ### Using Secrets
150
+
151
+ griffin supports secure secret management for API keys, tokens, and other credentials. Secrets are referenced in your test plans and resolved at runtime by the configured secret providers.
152
+
153
+ #### With Sequential Builder
154
+
155
+ ```typescript
156
+ import { GET, createTestBuilder, JSON, Frequency, secret } from "griffin-ts";
157
+
158
+ const plan = createTestBuilder({
159
+ name: "authenticated-check",
160
+ frequency: Frequency.every(5).minute(),
161
+ })
162
+ .request({
163
+ method: GET,
164
+ response_format: JSON,
165
+ path: "/api/protected",
166
+ headers: {
167
+ // Use environment variable
168
+ "X-API-Key": secret("env:API_KEY"),
169
+ // Use AWS Secrets Manager
170
+ Authorization: secret("aws:prod/api-token"),
171
+ // Extract field from JSON secret
172
+ "X-Custom-Header": secret("aws:prod/config", { field: "customHeader" }),
173
+ },
174
+ body: {
175
+ // Secrets can also be used in request bodies
176
+ apiKey: secret("env:API_KEY"),
177
+ },
178
+ })
179
+ .assert([{ type: "status", expected: 200 }])
180
+ .build();
181
+
182
+ export default plan;
183
+ ```
184
+
185
+ #### With Graph Builder
186
+
187
+ ```typescript
188
+ import {
189
+ GET,
190
+ createGraphBuilder,
191
+ Endpoint,
192
+ Assertion,
193
+ JSON,
194
+ START,
195
+ END,
196
+ Frequency,
197
+ secret,
198
+ } from "griffin-ts";
199
+
200
+ const plan = createGraphBuilder({
201
+ name: "authenticated-check",
202
+ frequency: Frequency.every(5).minute(),
203
+ })
204
+ .addNode(
205
+ "authenticated_request",
206
+ Endpoint({
207
+ method: GET,
208
+ response_format: JSON,
209
+ path: "/api/protected",
210
+ headers: {
211
+ "X-API-Key": secret("env:API_KEY"),
212
+ Authorization: secret("aws:prod/api-token"),
213
+ },
214
+ }),
215
+ )
216
+ .addNode("verify", Assertion([{ type: "status", expected: 200 }]))
217
+ .addEdge(START, "authenticated_request")
218
+ .addEdge("authenticated_request", "verify")
219
+ .addEdge("verify", END)
220
+ .build();
221
+
222
+ export default plan;
223
+ ```
224
+
225
+ #### Secret Providers
226
+
227
+ **Environment Variables** (always available):
228
+
229
+ ```typescript
230
+ secret("env:VARIABLE_NAME");
231
+ ```
232
+
233
+ **AWS Secrets Manager** (requires AWS configuration):
234
+
235
+ ```typescript
236
+ secret("aws:secret-name");
237
+ secret("aws:secret-name", { field: "key" }); // Extract field from JSON secret
238
+ secret("aws:secret-name", { version: "AWSPREVIOUS" }); // Pin to specific version
239
+ ```
240
+
241
+ **HashiCorp Vault** (requires Vault configuration):
242
+
243
+ ```typescript
244
+ secret("vault:secret/data/path");
245
+ secret("vault:secret/data/path", { field: "key" });
246
+ secret("vault:secret/data/path", { version: "2" });
247
+ ```
248
+
249
+ See the [griffin-runner CONFIG.md](../griffin-runner/CONFIG.md) for configuration details.
250
+
251
+ ### API Reference
252
+
253
+ #### Sequential Builder Methods
254
+
255
+ - **`.request(config)`**: Add an HTTP endpoint request
256
+ - **`.wait(duration)`**: Add a delay (use `Wait.seconds(n)` or `Wait.minutes(n)`)
257
+ - **`.assert(assertions)`**: Add assertions to validate responses
258
+ - **`.build()`**: Generate the final test plan
259
+
260
+ #### Graph Builder Methods
261
+
262
+ - **`.addNode(name, node)`**: Add a node to the graph using `Endpoint()`, `WaitNode()`, or `Assertion()`
263
+ - **`.addEdge(from, to)`**: Connect two nodes (use `START` and `END` constants for entry/exit)
264
+ - **`.build()`**: Generate the final test plan (validates all nodes are connected)
265
+
266
+ #### General
267
+
268
+ - **Frequency**: Use `Frequency.every(n).minute()`, `.hour()`, or `.day()` (note the parentheses)
269
+ - **Secrets**: Use `secret("provider:path")` to reference secrets that are resolved at runtime
270
+ - **Assertions**: Currently in development - assertion functions are stored but not yet evaluated during execution
271
+
272
+ ## Output
273
+
274
+ The test system outputs a JSON test plan to stdout when `plan.create()` is called. This JSON is consumed by the plan executor. Example output:
275
+
276
+ ```json
277
+ {
278
+ "name": "health-check",
279
+ "frequency": {
280
+ "every": 1,
281
+ "unit": "minute"
282
+ },
283
+ "nodes": [
284
+ {
285
+ "id": "health",
286
+ "type": "endpoint",
287
+ "method": "GET",
288
+ "path": "/health",
289
+ "response_format": "JSON"
290
+ }
291
+ ],
292
+ "edges": [
293
+ { "from": "__START__", "to": "health" },
294
+ { "from": "health", "to": "__END__" }
295
+ ]
296
+ }
297
+ ```
@@ -0,0 +1,136 @@
1
+ /**
2
+ * Rich assertion DSL for constructing type-safe test assertions with JSONPath support.
3
+ *
4
+ * This module provides:
5
+ * - StateProxy: Tracks node access patterns and converts them to JSONPath
6
+ * - Assert: Builder for creating assertions with fluent API
7
+ * - Support for unary and binary predicates with negation
8
+ */
9
+ /**
10
+ * Identifies which node and which part of its result we're asserting on
11
+ */
12
+ export interface PathDescriptor {
13
+ nodeId: string;
14
+ accessor: "body" | "headers" | "status";
15
+ path: string[];
16
+ }
17
+ /**
18
+ * Unary predicates that check a property without comparing to a value
19
+ */
20
+ export declare enum UnaryPredicate {
21
+ IS_NULL = "IS_NULL",
22
+ IS_NOT_NULL = "IS_NOT_NULL",
23
+ IS_TRUE = "IS_TRUE",
24
+ IS_FALSE = "IS_FALSE",
25
+ IS_EMPTY = "IS_EMPTY",
26
+ IS_NOT_EMPTY = "IS_NOT_EMPTY"
27
+ }
28
+ /**
29
+ * Binary predicate operators that compare against an expected value
30
+ */
31
+ export declare enum BinaryPredicateOperator {
32
+ EQUAL = "EQUAL",
33
+ NOT_EQUAL = "NOT_EQUAL",
34
+ GREATER_THAN = "GREATER_THAN",
35
+ LESS_THAN = "LESS_THAN",
36
+ GREATER_THAN_OR_EQUAL = "GREATER_THAN_OR_EQUAL",
37
+ LESS_THAN_OR_EQUAL = "LESS_THAN_OR_EQUAL",
38
+ CONTAINS = "CONTAINS",
39
+ NOT_CONTAINS = "NOT_CONTAINS",
40
+ STARTS_WITH = "STARTS_WITH",
41
+ NOT_STARTS_WITH = "NOT_STARTS_WITH",
42
+ ENDS_WITH = "ENDS_WITH",
43
+ NOT_ENDS_WITH = "NOT_ENDS_WITH"
44
+ }
45
+ /**
46
+ * Binary predicate with operator and expected value
47
+ */
48
+ export interface BinaryPredicate {
49
+ operator: BinaryPredicateOperator;
50
+ expected: unknown;
51
+ }
52
+ /**
53
+ * Serialized assertion ready for execution
54
+ */
55
+ export interface SerializedAssertion {
56
+ nodeId: string;
57
+ accessor: "body" | "headers" | "status";
58
+ path: string[];
59
+ predicate: UnaryPredicate | BinaryPredicate;
60
+ }
61
+ /**
62
+ * Symbol used to store path metadata in proxy objects
63
+ */
64
+ declare const PATH_SYMBOL: unique symbol;
65
+ /**
66
+ * Internal interface for proxy objects that carry path information
67
+ */
68
+ interface ProxyWithPath {
69
+ [PATH_SYMBOL]: PathDescriptor;
70
+ }
71
+ /**
72
+ * Proxy for accessing nested properties within a node result accessor (body, headers, status)
73
+ * Note: The 'at' method is available at runtime but typed as NestedProxy for simplicity
74
+ */
75
+ export type NestedProxy = ProxyWithPath & {
76
+ [key: string]: NestedProxy;
77
+ };
78
+ /**
79
+ * Proxy for a node result with body, headers, and status accessors
80
+ */
81
+ export type NodeResultProxy = {
82
+ body: NestedProxy;
83
+ headers: NestedProxy;
84
+ status: NestedProxy;
85
+ };
86
+ /**
87
+ * State proxy that maps node names to their result proxies
88
+ */
89
+ export type StateProxy<NodeNames extends string = string> = {
90
+ [K in NodeNames]: NodeResultProxy;
91
+ };
92
+ /**
93
+ * Creates a state proxy for the given node names
94
+ */
95
+ export declare function createStateProxy<NodeNames extends string>(nodeNames: NodeNames[]): StateProxy<NodeNames>;
96
+ export declare class AssertBuilder {
97
+ private descriptor;
98
+ private negated;
99
+ constructor(descriptor: PathDescriptor);
100
+ /**
101
+ * Negation modifier - flips the meaning of the subsequent predicate
102
+ *
103
+ * @example
104
+ * Assert(state["node"].body["id"]).not.isNull() // IS_NOT_NULL
105
+ * Assert(state["node"].body["name"]).not.equals("") // NOT_EQUAL
106
+ */
107
+ get not(): this;
108
+ isNull(): SerializedAssertion;
109
+ isDefined(): SerializedAssertion;
110
+ isTrue(): SerializedAssertion;
111
+ isFalse(): SerializedAssertion;
112
+ isEmpty(): SerializedAssertion;
113
+ equals(expected: unknown): SerializedAssertion;
114
+ greaterThan(expected: number): SerializedAssertion;
115
+ lessThan(expected: number): SerializedAssertion;
116
+ greaterThanOrEqual(expected: number): SerializedAssertion;
117
+ lessThanOrEqual(expected: number): SerializedAssertion;
118
+ contains(expected: string): SerializedAssertion;
119
+ startsWith(expected: string): SerializedAssertion;
120
+ endsWith(expected: string): SerializedAssertion;
121
+ private createAssertion;
122
+ }
123
+ /**
124
+ * Creates an assertion builder from a state proxy reference
125
+ *
126
+ * @param proxyRef - A reference obtained from the state proxy (e.g., state["node"].body["id"])
127
+ * @returns An AssertBuilder for constructing the assertion
128
+ *
129
+ * @example
130
+ * Assert(state["create_user"].body["data"]["id"]).not.isNull()
131
+ * Assert(state["create_user"].status).equals(201)
132
+ * Assert(state["create_user"].headers["content-type"]).contains("application/json")
133
+ */
134
+ export declare function Assert(proxyRef: NestedProxy): AssertBuilder;
135
+ export {};
136
+ //# sourceMappingURL=assertions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assertions.d.ts","sourceRoot":"","sources":["../src/assertions.ts"],"names":[],"mappings":"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"}