@olane/o-node 0.7.13-alpha.0 → 0.7.13-alpha.2

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 (60) hide show
  1. package/dist/src/connection/interfaces/o-node-connection-manager.config.d.ts +1 -0
  2. package/dist/src/connection/interfaces/o-node-connection-manager.config.d.ts.map +1 -1
  3. package/dist/src/connection/o-node-connection.d.ts +0 -1
  4. package/dist/src/connection/o-node-connection.d.ts.map +1 -1
  5. package/dist/src/connection/o-node-connection.js +0 -8
  6. package/dist/src/connection/o-node-connection.manager.d.ts +41 -4
  7. package/dist/src/connection/o-node-connection.manager.d.ts.map +1 -1
  8. package/dist/src/connection/o-node-connection.manager.js +187 -45
  9. package/dist/src/connection/stream-handler.d.ts.map +1 -1
  10. package/dist/src/connection/stream-handler.js +0 -2
  11. package/dist/src/managers/o-connection-heartbeat.manager.d.ts.map +1 -1
  12. package/dist/src/managers/o-connection-heartbeat.manager.js +15 -1
  13. package/dist/src/managers/o-reconnection.manager.d.ts.map +1 -1
  14. package/dist/src/managers/o-reconnection.manager.js +12 -7
  15. package/dist/src/o-node.d.ts +19 -0
  16. package/dist/src/o-node.d.ts.map +1 -1
  17. package/dist/src/o-node.js +89 -11
  18. package/dist/src/o-node.tool.d.ts.map +1 -1
  19. package/dist/src/o-node.tool.js +5 -0
  20. package/dist/src/router/o-node.router.d.ts.map +1 -1
  21. package/dist/src/router/o-node.router.js +16 -6
  22. package/dist/src/router/o-node.routing-policy.d.ts.map +1 -1
  23. package/dist/src/router/o-node.routing-policy.js +4 -0
  24. package/dist/test/connection-management.spec.d.ts +2 -0
  25. package/dist/test/connection-management.spec.d.ts.map +1 -0
  26. package/dist/test/connection-management.spec.js +370 -0
  27. package/dist/test/helpers/connection-spy.d.ts +124 -0
  28. package/dist/test/helpers/connection-spy.d.ts.map +1 -0
  29. package/dist/test/helpers/connection-spy.js +229 -0
  30. package/dist/test/helpers/index.d.ts +6 -0
  31. package/dist/test/helpers/index.d.ts.map +1 -0
  32. package/dist/test/helpers/index.js +12 -0
  33. package/dist/test/helpers/network-builder.d.ts +109 -0
  34. package/dist/test/helpers/network-builder.d.ts.map +1 -0
  35. package/dist/test/helpers/network-builder.js +309 -0
  36. package/dist/test/helpers/simple-node-builder.d.ts +50 -0
  37. package/dist/test/helpers/simple-node-builder.d.ts.map +1 -0
  38. package/dist/test/helpers/simple-node-builder.js +66 -0
  39. package/dist/test/helpers/test-environment.d.ts +140 -0
  40. package/dist/test/helpers/test-environment.d.ts.map +1 -0
  41. package/dist/test/helpers/test-environment.js +184 -0
  42. package/dist/test/helpers/test-node.tool.d.ts +31 -0
  43. package/dist/test/helpers/test-node.tool.d.ts.map +1 -1
  44. package/dist/test/helpers/test-node.tool.js +49 -0
  45. package/dist/test/leader-transport-validation.spec.d.ts +2 -0
  46. package/dist/test/leader-transport-validation.spec.d.ts.map +1 -0
  47. package/dist/test/leader-transport-validation.spec.js +177 -0
  48. package/dist/test/network-communication.spec.d.ts +2 -0
  49. package/dist/test/network-communication.spec.d.ts.map +1 -0
  50. package/dist/test/network-communication.spec.js +256 -0
  51. package/dist/test/o-node.spec.d.ts +2 -0
  52. package/dist/test/o-node.spec.d.ts.map +1 -0
  53. package/dist/test/o-node.spec.js +247 -0
  54. package/dist/test/parent-child-registration.spec.d.ts +2 -0
  55. package/dist/test/parent-child-registration.spec.d.ts.map +1 -0
  56. package/dist/test/parent-child-registration.spec.js +177 -0
  57. package/dist/test/search-resolver.spec.d.ts +2 -0
  58. package/dist/test/search-resolver.spec.d.ts.map +1 -0
  59. package/dist/test/search-resolver.spec.js +648 -0
  60. package/package.json +12 -7
@@ -0,0 +1,309 @@
1
+ import { oNodeTool } from '../../src/o-node.tool.js';
2
+ import { oNodeAddress } from '../../src/router/o-node.address.js';
3
+ import { oAddress } from '@olane/o-core';
4
+ /**
5
+ * Simple test tool for network communication testing
6
+ */
7
+ export class TestTool extends oNodeTool {
8
+ constructor(config) {
9
+ super(config);
10
+ this.callCount = 0;
11
+ }
12
+ async configure() {
13
+ const config = await super.configure();
14
+ config.connectionGater = {
15
+ denyDialPeer: (peerId) => {
16
+ return false;
17
+ },
18
+ // who can call us?
19
+ denyInboundEncryptedConnection: (peerId, maConn) => {
20
+ return false;
21
+ },
22
+ };
23
+ return config;
24
+ }
25
+ // NEED TO OVERRIDE to ensure that we can test fully without a proper leader node
26
+ async registerParent() {
27
+ if (!this.parent) {
28
+ this.logger.warn('no parent, skipping registration');
29
+ return;
30
+ }
31
+ if (!this.parent?.libp2pTransports?.length) {
32
+ this.logger.debug('Parent has no transports, waiting for reconnection & leader ack');
33
+ if (this.parent?.toString() === oAddress.leader().toString()) {
34
+ this.parent.setTransports(this.leader?.libp2pTransports || []);
35
+ }
36
+ else {
37
+ this.logger.debug('Waiting for parent and reconnecting...');
38
+ await this.reconnectionManager?.waitForParentAndReconnect();
39
+ }
40
+ }
41
+ // if no parent transports, register with the parent to get them
42
+ // TODO: should we remove the transports check to make this more consistent?
43
+ if (this.config.parent) {
44
+ this.logger.debug('Registering node with parent...', this.config.parent?.toString());
45
+ // avoid transports to ensure we do not try direct connection, we need to route via the leader for proper access controls
46
+ await this.use(this.config.parent, {
47
+ method: 'child_register',
48
+ params: {
49
+ address: this.address.toString(),
50
+ transports: this.transports.map((t) => t.toString()),
51
+ peerId: this.peerId.toString(),
52
+ _token: this.config.joinToken,
53
+ },
54
+ });
55
+ this.setKeepAliveTag(this.parent);
56
+ }
57
+ }
58
+ async _tool_echo(request) {
59
+ this.callCount++;
60
+ return {
61
+ message: request.params.message || 'echo',
62
+ nodeAddress: this.address.toString(),
63
+ timestamp: Date.now(),
64
+ };
65
+ }
66
+ async _tool_get_info(request) {
67
+ return {
68
+ address: this.address.toString(),
69
+ parent: this.parent?.toString(),
70
+ children: this.getChildren().map((c) => c.toString()),
71
+ callCount: this.callCount,
72
+ };
73
+ }
74
+ async *_tool_stream(request) {
75
+ const count = request.params.count || 5;
76
+ for (let i = 0; i < count; i++) {
77
+ yield {
78
+ chunk: i + 1,
79
+ total: count,
80
+ nodeAddress: this.address.toString(),
81
+ timestamp: Date.now(),
82
+ };
83
+ await new Promise((resolve) => setTimeout(resolve, 10));
84
+ }
85
+ }
86
+ }
87
+ /**
88
+ * Simplified network topology builder for testing node-to-node communication
89
+ * Focuses on peer connections and parent-child relationships without leader abstractions
90
+ */
91
+ export class NetworkBuilder {
92
+ constructor() {
93
+ this.nodes = new Map();
94
+ this.startedNodes = new Set();
95
+ }
96
+ /**
97
+ * Add a node to the network
98
+ * If parentAddress is provided, the node will register as a child
99
+ */
100
+ async addNode(address, parentAddress, config = {}) {
101
+ const seed = config.seed || `node-seed-${address}-${Date.now()}`;
102
+ let parentNode;
103
+ let parentRef = null;
104
+ if (parentAddress) {
105
+ parentNode = this.nodes.get(parentAddress);
106
+ if (!parentNode) {
107
+ throw new Error(`Parent node not found: ${parentAddress}`);
108
+ }
109
+ // Wait for parent to have transports
110
+ // await this.waitForTransports(parentNode);
111
+ parentRef = new oNodeAddress(parentNode.address.toString(), parentNode.address.libp2pTransports);
112
+ }
113
+ const node = new TestTool({
114
+ address: new oNodeAddress(address),
115
+ parent: parentRef,
116
+ leader: null, // No leader abstraction in o-node tests
117
+ seed,
118
+ connectionHeartbeat: {
119
+ enabled: !config.disableHeartbeat,
120
+ checkChildren: parentAddress ? false : true, // Only root monitors children
121
+ },
122
+ });
123
+ this.nodes.set(address, node);
124
+ await this.startNode(address);
125
+ return node;
126
+ }
127
+ /**
128
+ * Start a specific node
129
+ */
130
+ async startNode(address) {
131
+ const node = this.nodes.get(address);
132
+ if (!node) {
133
+ throw new Error(`Node not found: ${address}`);
134
+ }
135
+ if (this.startedNodes.has(address)) {
136
+ return; // Already started
137
+ }
138
+ await node.start();
139
+ this.startedNodes.add(address);
140
+ // Wait for transports to be available
141
+ // await this.waitForTransports(node);
142
+ }
143
+ /**
144
+ * Stop a specific node
145
+ */
146
+ async stopNode(address) {
147
+ const node = this.nodes.get(address);
148
+ if (!node) {
149
+ throw new Error(`Node not found: ${address}`);
150
+ }
151
+ if (!this.startedNodes.has(address)) {
152
+ return; // Not started
153
+ }
154
+ await node.stop();
155
+ this.startedNodes.delete(address);
156
+ }
157
+ /**
158
+ * Stop all nodes in the network
159
+ * Stops in reverse dependency order: children first, then parents
160
+ */
161
+ async stopAll() {
162
+ const sortedNodes = this.getSortedNodesByDepth().reverse();
163
+ for (const address of sortedNodes) {
164
+ if (this.startedNodes.has(address)) {
165
+ await this.stopNode(address);
166
+ }
167
+ }
168
+ }
169
+ /**
170
+ * Get a node by address
171
+ */
172
+ getNode(address) {
173
+ return this.nodes.get(address);
174
+ }
175
+ /**
176
+ * Get all nodes
177
+ */
178
+ getAllNodes() {
179
+ return new Map(this.nodes);
180
+ }
181
+ /**
182
+ * Sort nodes by hierarchy depth (root nodes first)
183
+ */
184
+ getSortedNodesByDepth() {
185
+ const depths = new Map();
186
+ const addresses = Array.from(this.nodes.keys());
187
+ // Calculate depth for each node
188
+ const calculateDepth = (address) => {
189
+ if (depths.has(address)) {
190
+ return depths.get(address);
191
+ }
192
+ const node = this.nodes.get(address);
193
+ if (!node.parent) {
194
+ depths.set(address, 0);
195
+ return 0;
196
+ }
197
+ // Find parent address in our map
198
+ const parentAddress = Array.from(this.nodes.entries()).find(([_, n]) => n.address.toString() === node.parent?.toString())?.[0];
199
+ if (!parentAddress) {
200
+ depths.set(address, 0);
201
+ return 0;
202
+ }
203
+ const depth = calculateDepth(parentAddress) + 1;
204
+ depths.set(address, depth);
205
+ return depth;
206
+ };
207
+ addresses.forEach((addr) => calculateDepth(addr));
208
+ // Sort by depth (ascending)
209
+ return addresses.sort((a, b) => {
210
+ const depthA = depths.get(a) || 0;
211
+ const depthB = depths.get(b) || 0;
212
+ return depthA - depthB;
213
+ });
214
+ }
215
+ /**
216
+ * Wait for a node to have transports available
217
+ */
218
+ async waitForTransports(node, timeoutMs = 5000) {
219
+ const startTime = Date.now();
220
+ while (Date.now() - startTime < timeoutMs) {
221
+ if (node.address.libp2pTransports.length > 0) {
222
+ return;
223
+ }
224
+ await new Promise((resolve) => setTimeout(resolve, 50));
225
+ }
226
+ throw new Error(`Timeout waiting for transports on ${node.address.toString()}`);
227
+ }
228
+ /**
229
+ * Clean up all nodes
230
+ */
231
+ async cleanup() {
232
+ await this.stopAll();
233
+ this.nodes.clear();
234
+ this.startedNodes.clear();
235
+ }
236
+ }
237
+ /**
238
+ * Quick network topology builders for common test scenarios
239
+ * All topologies use simple parent-child relationships without leader abstractions
240
+ * Note: "leader" in address names is just a convention, not a special node type
241
+ */
242
+ export class NetworkTopologies {
243
+ /**
244
+ * Create a simple two-node network (parent-child)
245
+ * Addresses: o://leader (root), o://child
246
+ */
247
+ static async twoNode() {
248
+ const builder = new NetworkBuilder();
249
+ await builder.addNode('o://leader');
250
+ await builder.addNode('o://child', 'o://leader');
251
+ return builder;
252
+ }
253
+ /**
254
+ * Create a three-node hierarchy (leader → parent → child)
255
+ * Addresses: o://leader (root), o://parent, o://child
256
+ */
257
+ static async threeNode() {
258
+ const builder = new NetworkBuilder();
259
+ await builder.addNode('o://leader');
260
+ await builder.addNode('o://parent', 'o://leader');
261
+ await builder.addNode('o://child', 'o://parent');
262
+ return builder;
263
+ }
264
+ /**
265
+ * Create a five-node hierarchy with two branches
266
+ * Structure: leader → parent1 → child1, child2
267
+ * → parent2
268
+ */
269
+ static async fiveNode() {
270
+ const builder = new NetworkBuilder();
271
+ await builder.addNode('o://leader');
272
+ await builder.addNode('o://parent1', 'o://leader');
273
+ await builder.addNode('o://parent2', 'o://leader');
274
+ await builder.addNode('o://child1', 'o://parent1');
275
+ await builder.addNode('o://child2', 'o://parent1');
276
+ return builder;
277
+ }
278
+ /**
279
+ * Create two standalone nodes (peer-to-peer)
280
+ */
281
+ static async twoStandalone() {
282
+ const builder = new NetworkBuilder();
283
+ await builder.addNode('o://node1');
284
+ await builder.addNode('o://node2');
285
+ return builder;
286
+ }
287
+ /**
288
+ * Create a complex hierarchy for integration testing
289
+ * Structure: leader → parent1 → child1, child2
290
+ * → parent2 → child3, child4
291
+ * → parent3 → child5, child6
292
+ */
293
+ static async complex() {
294
+ const builder = new NetworkBuilder();
295
+ await builder.addNode('o://leader');
296
+ // Add three parent nodes
297
+ await builder.addNode('o://parent1', 'o://leader');
298
+ await builder.addNode('o://parent2', 'o://leader');
299
+ await builder.addNode('o://parent3', 'o://leader');
300
+ // Add children to each parent
301
+ await builder.addNode('o://parent1-child1', 'o://parent1');
302
+ await builder.addNode('o://parent1-child2', 'o://parent1');
303
+ await builder.addNode('o://parent2-child1', 'o://parent2');
304
+ await builder.addNode('o://parent2-child2', 'o://parent2');
305
+ await builder.addNode('o://parent3-child1', 'o://parent3');
306
+ await builder.addNode('o://parent3-child2', 'o://parent3');
307
+ return builder;
308
+ }
309
+ }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * SimpleNodeBuilder - Fluent API for creating single-node tests
3
+ *
4
+ * @example
5
+ * ```typescript
6
+ * const node = await new SimpleNodeBuilder(MyTool)
7
+ * .withConfig({ apiKey: 'test' })
8
+ * .withAddress('o://test-tool')
9
+ * .build(env);
10
+ * ```
11
+ */
12
+ import type { oNodeTool } from '../../src/o-node.tool.js';
13
+ import type { oNodeAddress } from '../../src/router/o-node.address.js';
14
+ import type { TestEnvironment } from './test-environment.js';
15
+ import type { TestNodeConfig } from './test-environment.js';
16
+ export declare class SimpleNodeBuilder<T extends oNodeTool = any> {
17
+ private nodeClass;
18
+ private config;
19
+ private autoStart;
20
+ constructor(NodeClass: new (config: any) => T);
21
+ /**
22
+ * Set node configuration
23
+ */
24
+ withConfig(config: TestNodeConfig): this;
25
+ /**
26
+ * Set node address
27
+ */
28
+ withAddress(address: oNodeAddress): this;
29
+ /**
30
+ * Set node description
31
+ */
32
+ withDescription(description: string): this;
33
+ /**
34
+ * Set leader reference
35
+ */
36
+ withLeader(leader: oNodeAddress | null): this;
37
+ /**
38
+ * Set parent reference
39
+ */
40
+ withParent(parent: oNodeAddress | null): this;
41
+ /**
42
+ * Control automatic start
43
+ */
44
+ withAutoStart(autoStart: boolean): this;
45
+ /**
46
+ * Build and create the node
47
+ */
48
+ build(env: TestEnvironment): Promise<T>;
49
+ }
50
+ //# sourceMappingURL=simple-node-builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"simple-node-builder.d.ts","sourceRoot":"","sources":["../../../test/helpers/simple-node-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AACvE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,qBAAa,iBAAiB,CAAC,CAAC,SAAS,SAAS,GAAG,GAAG;IACtD,OAAO,CAAC,SAAS,CAAyB;IAC1C,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,SAAS,CAAiB;gBAEtB,SAAS,EAAE,KAAK,MAAM,EAAE,GAAG,KAAK,CAAC;IAI7C;;OAEG;IACH,UAAU,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI;IAKxC;;OAEG;IACH,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI;IAKxC;;OAEG;IACH,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAK1C;;OAEG;IACH,UAAU,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,GAAG,IAAI;IAK7C;;OAEG;IACH,UAAU,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,GAAG,IAAI;IAK7C;;OAEG;IACH,aAAa,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI;IAKvC;;OAEG;IACG,KAAK,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,CAAC,CAAC;CAG9C"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * SimpleNodeBuilder - Fluent API for creating single-node tests
3
+ *
4
+ * @example
5
+ * ```typescript
6
+ * const node = await new SimpleNodeBuilder(MyTool)
7
+ * .withConfig({ apiKey: 'test' })
8
+ * .withAddress('o://test-tool')
9
+ * .build(env);
10
+ * ```
11
+ */
12
+ export class SimpleNodeBuilder {
13
+ constructor(NodeClass) {
14
+ this.config = {};
15
+ this.autoStart = true;
16
+ this.nodeClass = NodeClass;
17
+ }
18
+ /**
19
+ * Set node configuration
20
+ */
21
+ withConfig(config) {
22
+ this.config = { ...this.config, ...config };
23
+ return this;
24
+ }
25
+ /**
26
+ * Set node address
27
+ */
28
+ withAddress(address) {
29
+ this.config.address = address;
30
+ return this;
31
+ }
32
+ /**
33
+ * Set node description
34
+ */
35
+ withDescription(description) {
36
+ this.config.description = description;
37
+ return this;
38
+ }
39
+ /**
40
+ * Set leader reference
41
+ */
42
+ withLeader(leader) {
43
+ this.config.leader = leader;
44
+ return this;
45
+ }
46
+ /**
47
+ * Set parent reference
48
+ */
49
+ withParent(parent) {
50
+ this.config.parent = parent;
51
+ return this;
52
+ }
53
+ /**
54
+ * Control automatic start
55
+ */
56
+ withAutoStart(autoStart) {
57
+ this.autoStart = autoStart;
58
+ return this;
59
+ }
60
+ /**
61
+ * Build and create the node
62
+ */
63
+ async build(env) {
64
+ return await env.createNode(this.nodeClass, this.config, this.autoStart);
65
+ }
66
+ }
@@ -0,0 +1,140 @@
1
+ /**
2
+ * TestEnvironment - Core test setup and lifecycle management for O-Network nodes
3
+ *
4
+ * Provides automatic cleanup, node factories, and common test utilities
5
+ * to eliminate boilerplate in O-Network package tests.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * describe('MyTool', () => {
10
+ * const env = new TestEnvironment();
11
+ *
12
+ * afterEach(async () => {
13
+ * await env.cleanup();
14
+ * });
15
+ *
16
+ * it('should work', async () => {
17
+ * const node = await env.createNode(MyTool);
18
+ * expect(node.state).to.equal(NodeState.RUNNING);
19
+ * });
20
+ * });
21
+ * ```
22
+ */
23
+ import type { oNode } from '../../src/o-node.js';
24
+ import type { oNodeAddress } from '../../src/router/o-node.address.js';
25
+ /**
26
+ * Node configuration for test environment
27
+ */
28
+ export interface TestNodeConfig {
29
+ address?: oNodeAddress;
30
+ leader?: oNodeAddress | null;
31
+ parent?: oNodeAddress | null;
32
+ description?: string;
33
+ [key: string]: any;
34
+ }
35
+ /**
36
+ * Core test environment class for O-Network testing
37
+ *
38
+ * Manages node lifecycle, automatic cleanup, and provides
39
+ * factory methods for common test scenarios.
40
+ *
41
+ * Note: This class does not include leader-related utilities to avoid
42
+ * circular dependencies with @olane/o-leader. Packages that need leader
43
+ * functionality should implement their own test utilities.
44
+ */
45
+ export declare class TestEnvironment {
46
+ private nodes;
47
+ private cleanupCallbacks;
48
+ /**
49
+ * Create a node
50
+ *
51
+ * @param NodeClass - Node class to instantiate
52
+ * @param config - Node configuration
53
+ * @param autoStart - Whether to start node automatically (default: true)
54
+ * @returns Node instance
55
+ *
56
+ * @example
57
+ * ```typescript
58
+ * const node = await env.createNode(MyTool, {
59
+ * address: new oNodeAddress('o://test')
60
+ * });
61
+ * ```
62
+ */
63
+ createNode<T extends oNode>(NodeClass: new (config: any) => T, config?: TestNodeConfig, autoStart?: boolean): Promise<T>;
64
+ /**
65
+ * Track a node for automatic cleanup
66
+ *
67
+ * @param node - Node instance to track
68
+ *
69
+ * @example
70
+ * ```typescript
71
+ * const node = new MyNode({});
72
+ * env.track(node);
73
+ * await node.start();
74
+ * ```
75
+ */
76
+ track(node: oNode): void;
77
+ /**
78
+ * Register a cleanup callback
79
+ *
80
+ * Useful for cleaning up external resources (databases, files, etc.)
81
+ *
82
+ * @param callback - Async cleanup function
83
+ *
84
+ * @example
85
+ * ```typescript
86
+ * const db = await createTestDB();
87
+ * env.onCleanup(async () => {
88
+ * await db.close();
89
+ * });
90
+ * ```
91
+ */
92
+ onCleanup(callback: () => Promise<void>): void;
93
+ /**
94
+ * Stop all tracked nodes and execute cleanup callbacks
95
+ *
96
+ * Stops nodes in reverse order (children before parents)
97
+ * Call this in afterEach hooks.
98
+ *
99
+ * @example
100
+ * ```typescript
101
+ * afterEach(async () => {
102
+ * await env.cleanup();
103
+ * });
104
+ * ```
105
+ */
106
+ cleanup(): Promise<void>;
107
+ /**
108
+ * Get all tracked nodes
109
+ *
110
+ * @returns Array of tracked node instances
111
+ */
112
+ getNodes(): oNode[];
113
+ /**
114
+ * Get count of tracked nodes
115
+ *
116
+ * @returns Number of tracked nodes
117
+ */
118
+ getNodeCount(): number;
119
+ /**
120
+ * Check if all tracked nodes are stopped
121
+ *
122
+ * @returns True if all nodes are stopped
123
+ */
124
+ allNodesStopped(): boolean;
125
+ /**
126
+ * Wait for a condition to be true
127
+ *
128
+ * @param condition - Function that returns true when condition is met
129
+ * @param timeoutMs - Maximum time to wait in milliseconds (default: 5000)
130
+ * @param intervalMs - Check interval in milliseconds (default: 100)
131
+ * @returns Promise that resolves when condition is met or rejects on timeout
132
+ *
133
+ * @example
134
+ * ```typescript
135
+ * await env.waitFor(() => tool.isReady, 10000);
136
+ * ```
137
+ */
138
+ waitFor(condition: () => boolean, timeoutMs?: number, intervalMs?: number): Promise<void>;
139
+ }
140
+ //# sourceMappingURL=test-environment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-environment.d.ts","sourceRoot":"","sources":["../../../test/helpers/test-environment.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAEvE;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,MAAM,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IAC7B,MAAM,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED;;;;;;;;;GASG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,KAAK,CAAe;IAC5B,OAAO,CAAC,gBAAgB,CAAkC;IAE1D;;;;;;;;;;;;;;OAcG;IACG,UAAU,CAAC,CAAC,SAAS,KAAK,EAC9B,SAAS,EAAE,KAAK,MAAM,EAAE,GAAG,KAAK,CAAC,EACjC,MAAM,GAAE,cAAmB,EAC3B,SAAS,GAAE,OAAc,GACxB,OAAO,CAAC,CAAC,CAAC;IAgBb;;;;;;;;;;;OAWG;IACH,KAAK,CAAC,IAAI,EAAE,KAAK,GAAG,IAAI;IAIxB;;;;;;;;;;;;;;OAcG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAI9C;;;;;;;;;;;;OAYG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IA4B9B;;;;OAIG;IACH,QAAQ,IAAI,KAAK,EAAE;IAInB;;;;OAIG;IACH,YAAY,IAAI,MAAM;IAItB;;;;OAIG;IACH,eAAe,IAAI,OAAO;IAI1B;;;;;;;;;;;;OAYG;IACG,OAAO,CACX,SAAS,EAAE,MAAM,OAAO,EACxB,SAAS,GAAE,MAAa,EACxB,UAAU,GAAE,MAAY,GACvB,OAAO,CAAC,IAAI,CAAC;CAUjB"}