@frontmcp/sdk 0.3.0 → 0.4.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 (169) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +192 -164
  3. package/package.json +7 -4
  4. package/src/__test-utils__/fixtures/hook.fixtures.d.ts +46 -0
  5. package/src/__test-utils__/fixtures/hook.fixtures.js +114 -0
  6. package/src/__test-utils__/fixtures/hook.fixtures.js.map +1 -0
  7. package/src/__test-utils__/fixtures/index.d.ts +7 -0
  8. package/src/__test-utils__/fixtures/index.js +11 -0
  9. package/src/__test-utils__/fixtures/index.js.map +1 -0
  10. package/src/__test-utils__/fixtures/plugin.fixtures.d.ts +46 -0
  11. package/src/__test-utils__/fixtures/plugin.fixtures.js +127 -0
  12. package/src/__test-utils__/fixtures/plugin.fixtures.js.map +1 -0
  13. package/src/__test-utils__/fixtures/provider.fixtures.d.ts +69 -0
  14. package/src/__test-utils__/fixtures/provider.fixtures.js +131 -0
  15. package/src/__test-utils__/fixtures/provider.fixtures.js.map +1 -0
  16. package/src/__test-utils__/fixtures/scope.fixtures.d.ts +14 -0
  17. package/src/__test-utils__/fixtures/scope.fixtures.js +59 -0
  18. package/src/__test-utils__/fixtures/scope.fixtures.js.map +1 -0
  19. package/src/__test-utils__/fixtures/tool.fixtures.d.ts +36 -0
  20. package/src/__test-utils__/fixtures/tool.fixtures.js +91 -0
  21. package/src/__test-utils__/fixtures/tool.fixtures.js.map +1 -0
  22. package/src/__test-utils__/helpers/assertion.helpers.d.ts +45 -0
  23. package/src/__test-utils__/helpers/assertion.helpers.js +153 -0
  24. package/src/__test-utils__/helpers/assertion.helpers.js.map +1 -0
  25. package/src/__test-utils__/helpers/async.helpers.d.ts +48 -0
  26. package/src/__test-utils__/helpers/async.helpers.js +112 -0
  27. package/src/__test-utils__/helpers/async.helpers.js.map +1 -0
  28. package/src/__test-utils__/helpers/index.d.ts +6 -0
  29. package/src/__test-utils__/helpers/index.js +10 -0
  30. package/src/__test-utils__/helpers/index.js.map +1 -0
  31. package/src/__test-utils__/helpers/setup.helpers.d.ts +54 -0
  32. package/src/__test-utils__/helpers/setup.helpers.js +106 -0
  33. package/src/__test-utils__/helpers/setup.helpers.js.map +1 -0
  34. package/src/__test-utils__/index.d.ts +9 -0
  35. package/src/__test-utils__/index.js +14 -0
  36. package/src/__test-utils__/index.js.map +1 -0
  37. package/src/__test-utils__/mocks/flow-instance.mock.d.ts +50 -0
  38. package/src/__test-utils__/mocks/flow-instance.mock.js +72 -0
  39. package/src/__test-utils__/mocks/flow-instance.mock.js.map +1 -0
  40. package/src/__test-utils__/mocks/hook-registry.mock.d.ts +25 -0
  41. package/src/__test-utils__/mocks/hook-registry.mock.js +65 -0
  42. package/src/__test-utils__/mocks/hook-registry.mock.js.map +1 -0
  43. package/src/__test-utils__/mocks/index.d.ts +8 -0
  44. package/src/__test-utils__/mocks/index.js +12 -0
  45. package/src/__test-utils__/mocks/index.js.map +1 -0
  46. package/src/__test-utils__/mocks/plugin-registry.mock.d.ts +43 -0
  47. package/src/__test-utils__/mocks/plugin-registry.mock.js +70 -0
  48. package/src/__test-utils__/mocks/plugin-registry.mock.js.map +1 -0
  49. package/src/__test-utils__/mocks/provider-registry.mock.d.ts +39 -0
  50. package/src/__test-utils__/mocks/provider-registry.mock.js +72 -0
  51. package/src/__test-utils__/mocks/provider-registry.mock.js.map +1 -0
  52. package/src/__test-utils__/mocks/tool-registry.mock.d.ts +43 -0
  53. package/src/__test-utils__/mocks/tool-registry.mock.js +79 -0
  54. package/src/__test-utils__/mocks/tool-registry.mock.js.map +1 -0
  55. package/src/app/app.utils.js.map +1 -1
  56. package/src/app/instances/app.local.instance.js +8 -11
  57. package/src/app/instances/app.local.instance.js.map +1 -1
  58. package/src/auth/auth.registry.d.ts +2 -2
  59. package/src/auth/auth.registry.js +3 -3
  60. package/src/auth/auth.registry.js.map +1 -1
  61. package/src/auth/flows/oauth.authorize.flow.d.ts +8 -8
  62. package/src/auth/flows/oauth.register.flow.d.ts +4 -4
  63. package/src/auth/flows/oauth.token.flow.d.ts +4 -4
  64. package/src/auth/flows/well-known.jwks.flow.d.ts +12 -12
  65. package/src/auth/flows/well-known.oauth-authorization-server.flow.d.ts +8 -8
  66. package/src/auth/flows/well-known.prm.flow.d.ts +4 -4
  67. package/src/auth/instances/instance.local-primary-auth.d.ts +3 -2
  68. package/src/auth/instances/instance.local-primary-auth.js +4 -2
  69. package/src/auth/instances/instance.local-primary-auth.js.map +1 -1
  70. package/src/auth/instances/instance.remote-primary-auth.d.ts +3 -2
  71. package/src/auth/instances/instance.remote-primary-auth.js +3 -1
  72. package/src/auth/instances/instance.remote-primary-auth.js.map +1 -1
  73. package/src/auth/jwks/jwks.service.js +0 -1
  74. package/src/auth/jwks/jwks.service.js.map +1 -1
  75. package/src/common/decorators/tool.decorator.d.ts +97 -36
  76. package/src/common/decorators/tool.decorator.js +0 -1
  77. package/src/common/decorators/tool.decorator.js.map +1 -1
  78. package/src/common/entries/scope.entry.d.ts +1 -0
  79. package/src/common/entries/scope.entry.js +6 -0
  80. package/src/common/entries/scope.entry.js.map +1 -1
  81. package/src/common/entries/tool.entry.d.ts +54 -11
  82. package/src/common/entries/tool.entry.js +19 -0
  83. package/src/common/entries/tool.entry.js.map +1 -1
  84. package/src/common/interfaces/internal/registry.interface.d.ts +10 -2
  85. package/src/common/interfaces/internal/registry.interface.js.map +1 -1
  86. package/src/common/interfaces/plugin.interface.d.ts +1 -1
  87. package/src/common/interfaces/plugin.interface.js.map +1 -1
  88. package/src/common/interfaces/tool.interface.d.ts +12 -7
  89. package/src/common/interfaces/tool.interface.js +1 -1
  90. package/src/common/interfaces/tool.interface.js.map +1 -1
  91. package/src/common/metadata/front-mcp.metadata.d.ts +145 -145
  92. package/src/common/metadata/hook.metadata.d.ts +4 -2
  93. package/src/common/metadata/hook.metadata.js.map +1 -1
  94. package/src/common/metadata/prompt.metadata.d.ts +28 -28
  95. package/src/common/metadata/prompt.metadata.js.map +1 -1
  96. package/src/common/metadata/resource.metadata.d.ts +54 -54
  97. package/src/common/metadata/tool.metadata.d.ts +190 -7
  98. package/src/common/metadata/tool.metadata.js +41 -6
  99. package/src/common/metadata/tool.metadata.js.map +1 -1
  100. package/src/common/records/scope.record.d.ts +2 -2
  101. package/src/common/records/scope.record.js.map +1 -1
  102. package/src/common/schemas/http-output.schema.d.ts +106 -106
  103. package/src/common/tokens/tool.tokens.js.map +1 -1
  104. package/src/common/types/options/logging.options.d.ts +1 -2
  105. package/src/common/types/options/logging.options.js +1 -9
  106. package/src/common/types/options/logging.options.js.map +1 -1
  107. package/src/common/types/options/server-info.options.d.ts +19 -19
  108. package/src/errors/error-handler.d.ts +65 -0
  109. package/src/errors/error-handler.js +107 -0
  110. package/src/errors/error-handler.js.map +1 -0
  111. package/src/errors/index.d.ts +2 -0
  112. package/src/errors/index.js +26 -0
  113. package/src/errors/index.js.map +1 -0
  114. package/src/errors/mcp.error.d.ts +156 -0
  115. package/src/errors/mcp.error.js +243 -0
  116. package/src/errors/mcp.error.js.map +1 -0
  117. package/src/flows/flow.instance.js +7 -6
  118. package/src/flows/flow.instance.js.map +1 -1
  119. package/src/flows/flow.registry.js +1 -1
  120. package/src/flows/flow.registry.js.map +1 -1
  121. package/src/front-mcp/front-mcp.providers.d.ts +20 -20
  122. package/src/hooks/hook.registry.d.ts +5 -3
  123. package/src/hooks/hook.registry.js +13 -1
  124. package/src/hooks/hook.registry.js.map +1 -1
  125. package/src/plugin/plugin.registry.d.ts +7 -2
  126. package/src/plugin/plugin.registry.js +23 -11
  127. package/src/plugin/plugin.registry.js.map +1 -1
  128. package/src/prompt/prompt.registry.js +1 -0
  129. package/src/prompt/prompt.registry.js.map +1 -1
  130. package/src/resource/resource.registry.js +1 -0
  131. package/src/resource/resource.registry.js.map +1 -1
  132. package/src/scope/scope.instance.js +8 -2
  133. package/src/scope/scope.instance.js.map +1 -1
  134. package/src/scope/scope.registry.js +3 -2
  135. package/src/scope/scope.registry.js.map +1 -1
  136. package/src/scope/scope.utils.js +6 -4
  137. package/src/scope/scope.utils.js.map +1 -1
  138. package/src/store/adapters/store.memory.adapter.js +3 -1
  139. package/src/store/adapters/store.memory.adapter.js.map +1 -1
  140. package/src/tool/flows/call-tool.flow.d.ts +1012 -676
  141. package/src/tool/flows/call-tool.flow.js +94 -61
  142. package/src/tool/flows/call-tool.flow.js.map +1 -1
  143. package/src/tool/flows/tools-list.flow.d.ts +347 -590
  144. package/src/tool/flows/tools-list.flow.js +76 -49
  145. package/src/tool/flows/tools-list.flow.js.map +1 -1
  146. package/src/tool/tool.instance.d.ts +27 -8
  147. package/src/tool/tool.instance.js +40 -5
  148. package/src/tool/tool.instance.js.map +1 -1
  149. package/src/tool/tool.registry.js +19 -21
  150. package/src/tool/tool.registry.js.map +1 -1
  151. package/src/tool/tool.utils.d.ts +3 -2
  152. package/src/tool/tool.utils.js +377 -14
  153. package/src/tool/tool.utils.js.map +1 -1
  154. package/src/transport/adapters/transport.sse.adapter.js +2 -1
  155. package/src/transport/adapters/transport.sse.adapter.js.map +1 -1
  156. package/src/transport/adapters/transport.streamable-http.adapter.js.map +1 -1
  157. package/src/transport/flows/handle.sse.flow.js +6 -13
  158. package/src/transport/flows/handle.sse.flow.js.map +1 -1
  159. package/src/transport/flows/handle.streamable-http.flow.js +1 -0
  160. package/src/transport/flows/handle.streamable-http.flow.js.map +1 -1
  161. package/src/transport/mcp-handlers/call-tool-request.handler.d.ts +1 -1
  162. package/src/transport/mcp-handlers/call-tool-request.handler.js +10 -5
  163. package/src/transport/mcp-handlers/call-tool-request.handler.js.map +1 -1
  164. package/src/transport/mcp-handlers/index.d.ts +151 -268
  165. package/src/transport/mcp-handlers/list-tools-request.handler.d.ts +124 -216
  166. package/src/transport/transport.local.js +1 -0
  167. package/src/transport/transport.local.js.map +1 -1
  168. package/src/utils/string.utils.js +1 -1
  169. package/src/utils/string.utils.js.map +1 -1
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ /// <reference types="jest" />
3
+ /**
4
+ * Test fixtures for tools
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.MockToolClass = void 0;
8
+ exports.createToolMetadata = createToolMetadata;
9
+ exports.createEchoToolMetadata = createEchoToolMetadata;
10
+ exports.createCalculatorToolMetadata = createCalculatorToolMetadata;
11
+ exports.createStructuredOutputToolMetadata = createStructuredOutputToolMetadata;
12
+ exports.createMockToolInstance = createMockToolInstance;
13
+ const zod_1 = require("zod");
14
+ /**
15
+ * Simple test tool metadata
16
+ */
17
+ function createToolMetadata(overrides = {}) {
18
+ return {
19
+ name: 'test_tool',
20
+ description: 'A test tool',
21
+ inputSchema: {
22
+ text: zod_1.z.string(),
23
+ },
24
+ outputSchema: 'string',
25
+ ...overrides,
26
+ };
27
+ }
28
+ /**
29
+ * Creates a simple echo tool metadata
30
+ */
31
+ function createEchoToolMetadata() {
32
+ return {
33
+ name: 'echo',
34
+ description: 'Echoes back the input',
35
+ inputSchema: {
36
+ message: zod_1.z.string().describe('Message to echo'),
37
+ },
38
+ outputSchema: 'string',
39
+ };
40
+ }
41
+ /**
42
+ * Creates a calculator tool metadata
43
+ */
44
+ function createCalculatorToolMetadata() {
45
+ return {
46
+ name: 'calculator',
47
+ description: 'Performs basic arithmetic',
48
+ inputSchema: {
49
+ operation: zod_1.z.enum(['add', 'subtract', 'multiply', 'divide']),
50
+ a: zod_1.z.number(),
51
+ b: zod_1.z.number(),
52
+ },
53
+ outputSchema: 'number',
54
+ };
55
+ }
56
+ /**
57
+ * Creates a tool with structured output
58
+ */
59
+ function createStructuredOutputToolMetadata() {
60
+ return {
61
+ name: 'get_user',
62
+ description: 'Gets user information',
63
+ inputSchema: {
64
+ userId: zod_1.z.string(),
65
+ },
66
+ outputSchema: zod_1.z.object({
67
+ id: zod_1.z.string(),
68
+ name: zod_1.z.string(),
69
+ email: zod_1.z.string().email(),
70
+ }),
71
+ };
72
+ }
73
+ /**
74
+ * Mock tool class for testing
75
+ */
76
+ class MockToolClass {
77
+ async execute(input) {
78
+ return `Echo: ${input.text}`;
79
+ }
80
+ }
81
+ exports.MockToolClass = MockToolClass;
82
+ /**
83
+ * Mock tool instance for testing
84
+ */
85
+ function createMockToolInstance(metadata) {
86
+ return {
87
+ metadata: createToolMetadata(metadata),
88
+ execute: jest.fn(async (input) => `Result: ${JSON.stringify(input)}`),
89
+ };
90
+ }
91
+ //# sourceMappingURL=tool.fixtures.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool.fixtures.js","sourceRoot":"","sources":["../../../../src/__test-utils__/fixtures/tool.fixtures.ts"],"names":[],"mappings":";AAAA,8BAA8B;AAC9B;;GAEG;;;AAQH,gDAUC;AAKD,wDASC;AAKD,oEAWC;AAKD,gFAaC;AAcD,wDAKC;AAnFD,6BAAwB;AAGxB;;GAEG;AACH,SAAgB,kBAAkB,CAAC,YAAmC,EAAE;IACtE,OAAO;QACL,IAAI,EAAE,WAAW;QACjB,WAAW,EAAE,aAAa;QAC1B,WAAW,EAAE;YACX,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE;SACjB;QACD,YAAY,EAAE,QAAQ;QACtB,GAAG,SAAS;KACb,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAgB,sBAAsB;IACpC,OAAO;QACL,IAAI,EAAE,MAAM;QACZ,WAAW,EAAE,uBAAuB;QACpC,WAAW,EAAE;YACX,OAAO,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,iBAAiB,CAAC;SAChD;QACD,YAAY,EAAE,QAAQ;KACvB,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAgB,4BAA4B;IAC1C,OAAO;QACL,IAAI,EAAE,YAAY;QAClB,WAAW,EAAE,2BAA2B;QACxC,WAAW,EAAE;YACX,SAAS,EAAE,OAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC;YAC5D,CAAC,EAAE,OAAC,CAAC,MAAM,EAAE;YACb,CAAC,EAAE,OAAC,CAAC,MAAM,EAAE;SACd;QACD,YAAY,EAAE,QAAQ;KACvB,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAgB,kCAAkC;IAChD,OAAO;QACL,IAAI,EAAE,UAAU;QAChB,WAAW,EAAE,uBAAuB;QACpC,WAAW,EAAE;YACX,MAAM,EAAE,OAAC,CAAC,MAAM,EAAE;SACnB;QACD,YAAY,EAAE,OAAC,CAAC,MAAM,CAAC;YACrB,EAAE,EAAE,OAAC,CAAC,MAAM,EAAE;YACd,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE;YAChB,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE;SAC1B,CAAC;KACH,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAa,aAAa;IACxB,KAAK,CAAC,OAAO,CAAC,KAAuB;QACnC,OAAO,SAAS,KAAK,CAAC,IAAI,EAAE,CAAC;IAC/B,CAAC;CACF;AAJD,sCAIC;AAED;;GAEG;AACH,SAAgB,sBAAsB,CAAC,QAAgC;IACrE,OAAO;QACL,QAAQ,EAAE,kBAAkB,CAAC,QAAQ,CAAC;QACtC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,KAAU,EAAE,EAAE,CAAC,WAAW,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;KAC3E,CAAC;AACJ,CAAC","sourcesContent":["/// <reference types=\"jest\" />\n/**\n * Test fixtures for tools\n */\n\nimport { z } from 'zod';\nimport { ToolMetadata } from '../../common/metadata';\n\n/**\n * Simple test tool metadata\n */\nexport function createToolMetadata(overrides: Partial<ToolMetadata> = {}): ToolMetadata {\n return {\n name: 'test_tool',\n description: 'A test tool',\n inputSchema: {\n text: z.string(),\n },\n outputSchema: 'string',\n ...overrides,\n };\n}\n\n/**\n * Creates a simple echo tool metadata\n */\nexport function createEchoToolMetadata(): ToolMetadata {\n return {\n name: 'echo',\n description: 'Echoes back the input',\n inputSchema: {\n message: z.string().describe('Message to echo'),\n },\n outputSchema: 'string',\n };\n}\n\n/**\n * Creates a calculator tool metadata\n */\nexport function createCalculatorToolMetadata(): ToolMetadata {\n return {\n name: 'calculator',\n description: 'Performs basic arithmetic',\n inputSchema: {\n operation: z.enum(['add', 'subtract', 'multiply', 'divide']),\n a: z.number(),\n b: z.number(),\n },\n outputSchema: 'number',\n };\n}\n\n/**\n * Creates a tool with structured output\n */\nexport function createStructuredOutputToolMetadata(): ToolMetadata {\n return {\n name: 'get_user',\n description: 'Gets user information',\n inputSchema: {\n userId: z.string(),\n },\n outputSchema: z.object({\n id: z.string(),\n name: z.string(),\n email: z.string().email(),\n }),\n };\n}\n\n/**\n * Mock tool class for testing\n */\nexport class MockToolClass {\n async execute(input: { text: string }): Promise<string> {\n return `Echo: ${input.text}`;\n }\n}\n\n/**\n * Mock tool instance for testing\n */\nexport function createMockToolInstance(metadata?: Partial<ToolMetadata>) {\n return {\n metadata: createToolMetadata(metadata),\n execute: jest.fn(async (input: any) => `Result: ${JSON.stringify(input)}`),\n };\n}\n"]}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Custom assertion helpers for testing SDK components
3
+ */
4
+ /**
5
+ * Asserts that a value is defined (not null or undefined)
6
+ */
7
+ export declare function assertDefined<T>(value: T | null | undefined, message?: string): asserts value is T;
8
+ /**
9
+ * Asserts that a value is an instance of a class
10
+ */
11
+ export declare function assertInstanceOf<T>(value: any, Ctor: new (...args: any[]) => T, message?: string): asserts value is T;
12
+ /**
13
+ * Asserts that an array contains a specific item
14
+ */
15
+ export declare function assertContains<T>(array: T[], item: T, message?: string): void;
16
+ /**
17
+ * Asserts that two arrays have the same elements with the same counts (order doesn't matter)
18
+ */
19
+ export declare function assertSameElements<T>(actual: T[], expected: T[], message?: string): void;
20
+ /**
21
+ * Asserts that a map has a specific key
22
+ */
23
+ export declare function assertHasKey<K, V>(map: Map<K, V>, key: K, message?: string): void;
24
+ /**
25
+ * Asserts that a promise rejects with a specific error
26
+ */
27
+ export declare function assertRejects(promise: Promise<any>, expectedError?: string | RegExp | (new (...args: any[]) => Error)): Promise<Error>;
28
+ /**
29
+ * Asserts that a promise resolves to a specific value
30
+ */
31
+ export declare function assertResolves<T>(promise: Promise<T>, expectedValue?: T): Promise<T>;
32
+ /**
33
+ * Creates a spy that captures console output
34
+ */
35
+ export declare function spyConsole(): {
36
+ logs: string[];
37
+ warns: string[];
38
+ errors: string[];
39
+ infos: string[];
40
+ restore: () => void;
41
+ };
42
+ /**
43
+ * Suppresses console output during test execution
44
+ */
45
+ export declare function suppressConsole(): () => void;
@@ -0,0 +1,153 @@
1
+ "use strict";
2
+ /// <reference types="jest" />
3
+ /**
4
+ * Custom assertion helpers for testing SDK components
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.assertDefined = assertDefined;
8
+ exports.assertInstanceOf = assertInstanceOf;
9
+ exports.assertContains = assertContains;
10
+ exports.assertSameElements = assertSameElements;
11
+ exports.assertHasKey = assertHasKey;
12
+ exports.assertRejects = assertRejects;
13
+ exports.assertResolves = assertResolves;
14
+ exports.spyConsole = spyConsole;
15
+ exports.suppressConsole = suppressConsole;
16
+ const NO_EXPECTED = Symbol('assertResolves.noExpected');
17
+ /**
18
+ * Asserts that a value is defined (not null or undefined)
19
+ */
20
+ function assertDefined(value, message) {
21
+ if (value === null || value === undefined) {
22
+ throw new Error(message || 'Expected value to be defined');
23
+ }
24
+ }
25
+ /**
26
+ * Asserts that a value is an instance of a class
27
+ */
28
+ function assertInstanceOf(value, Ctor, message) {
29
+ if (!(value instanceof Ctor)) {
30
+ throw new Error(message ||
31
+ `Expected value to be an instance of ${Ctor.name}, but got ${value?.constructor?.name || typeof value}`);
32
+ }
33
+ }
34
+ /**
35
+ * Asserts that an array contains a specific item
36
+ */
37
+ function assertContains(array, item, message) {
38
+ if (!array.includes(item)) {
39
+ throw new Error(message || `Expected array to contain item`);
40
+ }
41
+ }
42
+ /**
43
+ * Asserts that two arrays have the same elements with the same counts (order doesn't matter)
44
+ */
45
+ function assertSameElements(actual, expected, message) {
46
+ if (actual.length !== expected.length) {
47
+ throw new Error(message || `Expected arrays to have same length: ${actual.length} vs ${expected.length}`);
48
+ }
49
+ // Count occurrences of each element in both arrays
50
+ const actualCounts = new Map();
51
+ const expectedCounts = new Map();
52
+ for (const item of actual) {
53
+ actualCounts.set(item, (actualCounts.get(item) || 0) + 1);
54
+ }
55
+ for (const item of expected) {
56
+ expectedCounts.set(item, (expectedCounts.get(item) || 0) + 1);
57
+ }
58
+ // Check that all expected items exist with the correct counts
59
+ for (const [item, count] of expectedCounts) {
60
+ const actualCount = actualCounts.get(item) || 0;
61
+ if (actualCount !== count) {
62
+ throw new Error(message || `Expected array to contain ${count} occurrence(s) of ${item}, but found ${actualCount}`);
63
+ }
64
+ }
65
+ // Check that actual doesn't have extra items
66
+ for (const [item, count] of actualCounts) {
67
+ const expectedCount = expectedCounts.get(item) || 0;
68
+ if (expectedCount !== count) {
69
+ throw new Error(message || `Expected array to contain ${expectedCount} occurrence(s) of ${item}, but found ${count}`);
70
+ }
71
+ }
72
+ }
73
+ /**
74
+ * Asserts that a map has a specific key
75
+ */
76
+ function assertHasKey(map, key, message) {
77
+ if (!map.has(key)) {
78
+ throw new Error(message || `Expected map to have key`);
79
+ }
80
+ }
81
+ /**
82
+ * Asserts that a promise rejects with a specific error
83
+ */
84
+ async function assertRejects(promise, expectedError) {
85
+ try {
86
+ await promise;
87
+ throw new Error('Expected promise to reject, but it resolved');
88
+ }
89
+ catch (error) {
90
+ if (expectedError) {
91
+ if (typeof expectedError === 'string') {
92
+ expect(error.message).toContain(expectedError);
93
+ }
94
+ else if (expectedError instanceof RegExp) {
95
+ expect(error.message).toMatch(expectedError);
96
+ }
97
+ else {
98
+ expect(error).toBeInstanceOf(expectedError);
99
+ }
100
+ }
101
+ return error;
102
+ }
103
+ }
104
+ /**
105
+ * Asserts that a promise resolves to a specific value
106
+ */
107
+ async function assertResolves(promise, expectedValue) {
108
+ const value = await promise;
109
+ const finalExpected = arguments.length > 1 ? expectedValue : NO_EXPECTED;
110
+ if (finalExpected !== NO_EXPECTED) {
111
+ expect(value).toEqual(finalExpected);
112
+ }
113
+ return value;
114
+ }
115
+ /**
116
+ * Creates a spy that captures console output
117
+ */
118
+ function spyConsole() {
119
+ const originalConsole = {
120
+ log: console.log,
121
+ warn: console.warn,
122
+ error: console.error,
123
+ info: console.info,
124
+ };
125
+ const logs = [];
126
+ const warns = [];
127
+ const errors = [];
128
+ const infos = [];
129
+ console.log = jest.fn((...args) => logs.push(args.join(' ')));
130
+ console.warn = jest.fn((...args) => warns.push(args.join(' ')));
131
+ console.error = jest.fn((...args) => errors.push(args.join(' ')));
132
+ console.info = jest.fn((...args) => infos.push(args.join(' ')));
133
+ return {
134
+ logs,
135
+ warns,
136
+ errors,
137
+ infos,
138
+ restore: () => {
139
+ console.log = originalConsole.log;
140
+ console.warn = originalConsole.warn;
141
+ console.error = originalConsole.error;
142
+ console.info = originalConsole.info;
143
+ },
144
+ };
145
+ }
146
+ /**
147
+ * Suppresses console output during test execution
148
+ */
149
+ function suppressConsole() {
150
+ const spy = spyConsole();
151
+ return spy.restore;
152
+ }
153
+ //# sourceMappingURL=assertion.helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assertion.helpers.js","sourceRoot":"","sources":["../../../../src/__test-utils__/helpers/assertion.helpers.ts"],"names":[],"mappings":"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","sourcesContent":["/// <reference types=\"jest\" />\n/**\n * Custom assertion helpers for testing SDK components\n */\n\nconst NO_EXPECTED = Symbol('assertResolves.noExpected');\n\n/**\n * Asserts that a value is defined (not null or undefined)\n */\nexport function assertDefined<T>(value: T | null | undefined, message?: string): asserts value is T {\n if (value === null || value === undefined) {\n throw new Error(message || 'Expected value to be defined');\n }\n}\n\n/**\n * Asserts that a value is an instance of a class\n */\nexport function assertInstanceOf<T>(value: any, Ctor: new (...args: any[]) => T, message?: string): asserts value is T {\n if (!(value instanceof Ctor)) {\n throw new Error(\n message ||\n `Expected value to be an instance of ${Ctor.name}, but got ${value?.constructor?.name || typeof value}`,\n );\n }\n}\n\n/**\n * Asserts that an array contains a specific item\n */\nexport function assertContains<T>(array: T[], item: T, message?: string): void {\n if (!array.includes(item)) {\n throw new Error(message || `Expected array to contain item`);\n }\n}\n\n/**\n * Asserts that two arrays have the same elements with the same counts (order doesn't matter)\n */\nexport function assertSameElements<T>(actual: T[], expected: T[], message?: string): void {\n if (actual.length !== expected.length) {\n throw new Error(message || `Expected arrays to have same length: ${actual.length} vs ${expected.length}`);\n }\n\n // Count occurrences of each element in both arrays\n const actualCounts = new Map<T, number>();\n const expectedCounts = new Map<T, number>();\n\n for (const item of actual) {\n actualCounts.set(item, (actualCounts.get(item) || 0) + 1);\n }\n\n for (const item of expected) {\n expectedCounts.set(item, (expectedCounts.get(item) || 0) + 1);\n }\n\n // Check that all expected items exist with the correct counts\n for (const [item, count] of expectedCounts) {\n const actualCount = actualCounts.get(item) || 0;\n if (actualCount !== count) {\n throw new Error(\n message || `Expected array to contain ${count} occurrence(s) of ${item}, but found ${actualCount}`,\n );\n }\n }\n\n // Check that actual doesn't have extra items\n for (const [item, count] of actualCounts) {\n const expectedCount = expectedCounts.get(item) || 0;\n if (expectedCount !== count) {\n throw new Error(\n message || `Expected array to contain ${expectedCount} occurrence(s) of ${item}, but found ${count}`,\n );\n }\n }\n}\n\n/**\n * Asserts that a map has a specific key\n */\nexport function assertHasKey<K, V>(map: Map<K, V>, key: K, message?: string): void {\n if (!map.has(key)) {\n throw new Error(message || `Expected map to have key`);\n }\n}\n\n/**\n * Asserts that a promise rejects with a specific error\n */\nexport async function assertRejects(\n promise: Promise<any>,\n expectedError?: string | RegExp | (new (...args: any[]) => Error),\n): Promise<Error> {\n try {\n await promise;\n throw new Error('Expected promise to reject, but it resolved');\n } catch (error) {\n if (expectedError) {\n if (typeof expectedError === 'string') {\n expect((error as Error).message).toContain(expectedError);\n } else if (expectedError instanceof RegExp) {\n expect((error as Error).message).toMatch(expectedError);\n } else {\n expect(error).toBeInstanceOf(expectedError);\n }\n }\n return error as Error;\n }\n}\n\n/**\n * Asserts that a promise resolves to a specific value\n */\nexport async function assertResolves<T>(promise: Promise<T>, expectedValue?: T): Promise<T> {\n const value = await promise;\n const finalExpected: T | typeof NO_EXPECTED = arguments.length > 1 ? (expectedValue as T) : NO_EXPECTED;\n\n if (finalExpected !== NO_EXPECTED) {\n expect(value).toEqual(finalExpected as T);\n }\n return value;\n}\n\n/**\n * Creates a spy that captures console output\n */\nexport function spyConsole() {\n const originalConsole = {\n log: console.log,\n warn: console.warn,\n error: console.error,\n info: console.info,\n };\n\n const logs: string[] = [];\n const warns: string[] = [];\n const errors: string[] = [];\n const infos: string[] = [];\n\n console.log = jest.fn((...args) => logs.push(args.join(' ')));\n console.warn = jest.fn((...args) => warns.push(args.join(' ')));\n console.error = jest.fn((...args) => errors.push(args.join(' ')));\n console.info = jest.fn((...args) => infos.push(args.join(' ')));\n\n return {\n logs,\n warns,\n errors,\n infos,\n restore: () => {\n console.log = originalConsole.log;\n console.warn = originalConsole.warn;\n console.error = originalConsole.error;\n console.info = originalConsole.info;\n },\n };\n}\n\n/**\n * Suppresses console output during test execution\n */\nexport function suppressConsole() {\n const spy = spyConsole();\n return spy.restore;\n}\n"]}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Helper utilities for testing asynchronous operations
3
+ */
4
+ /**
5
+ * Waits for a promise to settle and returns the result or error
6
+ */
7
+ export declare function settled<T>(promise: Promise<T>): Promise<{
8
+ status: 'fulfilled';
9
+ value: T;
10
+ } | {
11
+ status: 'rejected';
12
+ reason: any;
13
+ }>;
14
+ /**
15
+ * Waits for a condition to be true with a timeout
16
+ */
17
+ export declare function waitFor(condition: () => boolean | Promise<boolean>, options?: {
18
+ timeout?: number;
19
+ interval?: number;
20
+ }): Promise<void>;
21
+ /**
22
+ * Flushes all pending promises (useful for testing async flows)
23
+ */
24
+ export declare function flushPromises(): Promise<void>;
25
+ /**
26
+ * Creates a deferred promise that can be resolved/rejected externally
27
+ */
28
+ export declare function createDeferred<T>(): {
29
+ promise: Promise<T>;
30
+ resolve: (value: T) => void;
31
+ reject: (reason: any) => void;
32
+ };
33
+ /**
34
+ * Runs a function and expects it to throw an error
35
+ */
36
+ export declare function expectToThrow<T>(fn: () => T | Promise<T>, expectedError?: string | RegExp | (new (...args: any[]) => Error)): Promise<Error>;
37
+ /**
38
+ * Creates a mock function that tracks calls
39
+ */
40
+ export declare function createMockFn<T extends (...args: any[]) => any>(): {
41
+ fn: jest.Mock<ReturnType<T>, Parameters<T>, any>;
42
+ calls: {
43
+ args: Parameters<T>;
44
+ result?: ReturnType<T>;
45
+ error?: any;
46
+ }[];
47
+ reset: () => void;
48
+ };
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ /// <reference types="jest" />
3
+ /**
4
+ * Helper utilities for testing asynchronous operations
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.settled = settled;
8
+ exports.waitFor = waitFor;
9
+ exports.flushPromises = flushPromises;
10
+ exports.createDeferred = createDeferred;
11
+ exports.expectToThrow = expectToThrow;
12
+ exports.createMockFn = createMockFn;
13
+ /**
14
+ * Waits for a promise to settle and returns the result or error
15
+ */
16
+ async function settled(promise) {
17
+ try {
18
+ const value = await promise;
19
+ return { status: 'fulfilled', value };
20
+ }
21
+ catch (reason) {
22
+ return { status: 'rejected', reason };
23
+ }
24
+ }
25
+ /**
26
+ * Waits for a condition to be true with a timeout
27
+ */
28
+ async function waitFor(condition, options = {}) {
29
+ const { timeout = 5000, interval = 50 } = options;
30
+ const start = Date.now();
31
+ while (Date.now() - start < timeout) {
32
+ if (await condition()) {
33
+ return;
34
+ }
35
+ await new Promise((resolve) => setTimeout(resolve, interval));
36
+ }
37
+ throw new Error(`Timeout waiting for condition after ${timeout}ms`);
38
+ }
39
+ /**
40
+ * Flushes all pending promises (useful for testing async flows)
41
+ */
42
+ async function flushPromises() {
43
+ await new Promise((resolve) => setImmediate(resolve));
44
+ }
45
+ /**
46
+ * Creates a deferred promise that can be resolved/rejected externally
47
+ */
48
+ function createDeferred() {
49
+ let resolve;
50
+ let reject;
51
+ const promise = new Promise((res, rej) => {
52
+ resolve = res;
53
+ reject = rej;
54
+ });
55
+ return {
56
+ promise,
57
+ resolve: resolve,
58
+ reject: reject,
59
+ };
60
+ }
61
+ /**
62
+ * Runs a function and expects it to throw an error
63
+ */
64
+ async function expectToThrow(fn, expectedError) {
65
+ try {
66
+ await fn();
67
+ }
68
+ catch (error) {
69
+ if (expectedError) {
70
+ if (typeof expectedError === 'string') {
71
+ expect(error.message).toContain(expectedError);
72
+ }
73
+ else if (expectedError instanceof RegExp) {
74
+ expect(error.message).toMatch(expectedError);
75
+ }
76
+ else {
77
+ expect(error).toBeInstanceOf(expectedError);
78
+ }
79
+ }
80
+ return error;
81
+ }
82
+ throw new Error('Expected function to throw an error, but it did not');
83
+ }
84
+ /**
85
+ * Creates a mock function that tracks calls
86
+ */
87
+ function createMockFn() {
88
+ const calls = [];
89
+ const fn = jest.fn((...args) => {
90
+ const call = { args };
91
+ try {
92
+ const result = undefined;
93
+ call.result = result;
94
+ calls.push(call);
95
+ return result;
96
+ }
97
+ catch (error) {
98
+ call.error = error;
99
+ calls.push(call);
100
+ throw error;
101
+ }
102
+ });
103
+ return {
104
+ fn,
105
+ calls,
106
+ reset: () => {
107
+ calls.length = 0;
108
+ fn.mockReset();
109
+ },
110
+ };
111
+ }
112
+ //# sourceMappingURL=async.helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"async.helpers.js","sourceRoot":"","sources":["../../../../src/__test-utils__/helpers/async.helpers.ts"],"names":[],"mappings":";AAAA,8BAA8B;AAC9B;;GAEG;;AAKH,0BASC;AAKD,0BAeC;AAKD,sCAEC;AAKD,wCAcC;AAKD,sCAoBC;AAKD,oCAyBC;AAjHD;;GAEG;AACI,KAAK,UAAU,OAAO,CAC3B,OAAmB;IAEnB,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC;QAC5B,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC;IACxC,CAAC;IAAC,OAAO,MAAM,EAAE,CAAC;QAChB,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC;IACxC,CAAC;AACH,CAAC;AAED;;GAEG;AACI,KAAK,UAAU,OAAO,CAC3B,SAA2C,EAC3C,UAAmD,EAAE;IAErD,MAAM,EAAE,OAAO,GAAG,IAAI,EAAE,QAAQ,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC;IAClD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAEzB,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,OAAO,EAAE,CAAC;QACpC,IAAI,MAAM,SAAS,EAAE,EAAE,CAAC;YACtB,OAAO;QACT,CAAC;QACD,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;IAChE,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,uCAAuC,OAAO,IAAI,CAAC,CAAC;AACtE,CAAC;AAED;;GAEG;AACI,KAAK,UAAU,aAAa;IACjC,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC;AACxD,CAAC;AAED;;GAEG;AACH,SAAgB,cAAc;IAC5B,IAAI,OAA2B,CAAC;IAChC,IAAI,MAA6B,CAAC;IAElC,MAAM,OAAO,GAAG,IAAI,OAAO,CAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QAC1C,OAAO,GAAG,GAAG,CAAC;QACd,MAAM,GAAG,GAAG,CAAC;IACf,CAAC,CAAC,CAAC;IAEH,OAAO;QACL,OAAO;QACP,OAAO,EAAE,OAAQ;QACjB,MAAM,EAAE,MAAO;KAChB,CAAC;AACJ,CAAC;AAED;;GAEG;AACI,KAAK,UAAU,aAAa,CACjC,EAAwB,EACxB,aAAiE;IAEjE,IAAI,CAAC;QACH,MAAM,EAAE,EAAE,CAAC;IACb,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,aAAa,EAAE,CAAC;YAClB,IAAI,OAAO,aAAa,KAAK,QAAQ,EAAE,CAAC;gBACtC,MAAM,CAAE,KAAe,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;YAC5D,CAAC;iBAAM,IAAI,aAAa,YAAY,MAAM,EAAE,CAAC;gBAC3C,MAAM,CAAE,KAAe,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;YAC1D,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,KAAK,CAAC,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC;YAC9C,CAAC;QACH,CAAC;QACD,OAAO,KAAc,CAAC;IACxB,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;AACzE,CAAC;AAED;;GAEG;AACH,SAAgB,YAAY;IAC1B,MAAM,KAAK,GAAwE,EAAE,CAAC;IAEtF,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,GAAG,IAAmB,EAAiB,EAAE;QAC3D,MAAM,IAAI,GAAQ,EAAE,IAAI,EAAE,CAAC;QAC3B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,SAA0B,CAAC;YAC1C,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;YACrB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACjB,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;YACnB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACjB,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO;QACL,EAAE;QACF,KAAK;QACL,KAAK,EAAE,GAAG,EAAE;YACV,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;YACjB,EAAE,CAAC,SAAS,EAAE,CAAC;QACjB,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["/// <reference types=\"jest\" />\n/**\n * Helper utilities for testing asynchronous operations\n */\n\n/**\n * Waits for a promise to settle and returns the result or error\n */\nexport async function settled<T>(\n promise: Promise<T>,\n): Promise<{ status: 'fulfilled'; value: T } | { status: 'rejected'; reason: any }> {\n try {\n const value = await promise;\n return { status: 'fulfilled', value };\n } catch (reason) {\n return { status: 'rejected', reason };\n }\n}\n\n/**\n * Waits for a condition to be true with a timeout\n */\nexport async function waitFor(\n condition: () => boolean | Promise<boolean>,\n options: { timeout?: number; interval?: number } = {},\n): Promise<void> {\n const { timeout = 5000, interval = 50 } = options;\n const start = Date.now();\n\n while (Date.now() - start < timeout) {\n if (await condition()) {\n return;\n }\n await new Promise((resolve) => setTimeout(resolve, interval));\n }\n\n throw new Error(`Timeout waiting for condition after ${timeout}ms`);\n}\n\n/**\n * Flushes all pending promises (useful for testing async flows)\n */\nexport async function flushPromises(): Promise<void> {\n await new Promise((resolve) => setImmediate(resolve));\n}\n\n/**\n * Creates a deferred promise that can be resolved/rejected externally\n */\nexport function createDeferred<T>() {\n let resolve: (value: T) => void;\n let reject: (reason: any) => void;\n\n const promise = new Promise<T>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n\n return {\n promise,\n resolve: resolve!,\n reject: reject!,\n };\n}\n\n/**\n * Runs a function and expects it to throw an error\n */\nexport async function expectToThrow<T>(\n fn: () => T | Promise<T>,\n expectedError?: string | RegExp | (new (...args: any[]) => Error),\n): Promise<Error> {\n try {\n await fn();\n } catch (error) {\n if (expectedError) {\n if (typeof expectedError === 'string') {\n expect((error as Error).message).toContain(expectedError);\n } else if (expectedError instanceof RegExp) {\n expect((error as Error).message).toMatch(expectedError);\n } else {\n expect(error).toBeInstanceOf(expectedError);\n }\n }\n return error as Error;\n }\n\n throw new Error('Expected function to throw an error, but it did not');\n}\n\n/**\n * Creates a mock function that tracks calls\n */\nexport function createMockFn<T extends (...args: any[]) => any>() {\n const calls: Array<{ args: Parameters<T>; result?: ReturnType<T>; error?: any }> = [];\n\n const fn = jest.fn((...args: Parameters<T>): ReturnType<T> => {\n const call: any = { args };\n try {\n const result = undefined as ReturnType<T>;\n call.result = result;\n calls.push(call);\n return result;\n } catch (error) {\n call.error = error;\n calls.push(call);\n throw error;\n }\n });\n\n return {\n fn,\n calls,\n reset: () => {\n calls.length = 0;\n fn.mockReset();\n },\n };\n}\n"]}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Helper utilities for testing
3
+ */
4
+ export * from './async.helpers';
5
+ export * from './assertion.helpers';
6
+ export * from './setup.helpers';
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ /**
3
+ * Helper utilities for testing
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const tslib_1 = require("tslib");
7
+ tslib_1.__exportStar(require("./async.helpers"), exports);
8
+ tslib_1.__exportStar(require("./assertion.helpers"), exports);
9
+ tslib_1.__exportStar(require("./setup.helpers"), exports);
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/__test-utils__/helpers/index.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAEH,0DAAgC;AAChC,8DAAoC;AACpC,0DAAgC","sourcesContent":["/**\n * Helper utilities for testing\n */\n\nexport * from './async.helpers';\nexport * from './assertion.helpers';\nexport * from './setup.helpers';\n"]}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Helper utilities for test setup and teardown
3
+ */
4
+ import 'reflect-metadata';
5
+ /**
6
+ * Creates a clean test environment with automatic cleanup
7
+ */
8
+ export declare function createTestEnvironment(): {
9
+ /**
10
+ * Registers a cleanup function to be called after the test
11
+ */
12
+ onCleanup(fn: () => void | Promise<void>): void;
13
+ /**
14
+ * Cleans up all registered resources
15
+ */
16
+ cleanup(): Promise<void>;
17
+ };
18
+ /**
19
+ * Wraps a test function with automatic environment setup and cleanup
20
+ */
21
+ export declare function withTestEnvironment<T extends any[]>(testFn: (env: ReturnType<typeof createTestEnvironment>, ...args: T) => Promise<void> | void): (...args: T) => Promise<void>;
22
+ /**
23
+ * Creates a mock timer for testing time-based operations
24
+ */
25
+ export declare function useFakeTimers(): {
26
+ advance: (ms: number) => void;
27
+ runAll: () => void;
28
+ runPending: () => void;
29
+ };
30
+ /**
31
+ * Creates a test-specific logger that can be inspected
32
+ */
33
+ export declare function createTestLogger(): {
34
+ log: (message: string, data?: any) => number;
35
+ warn: (message: string, data?: any) => number;
36
+ error: (message: string, data?: any) => number;
37
+ info: (message: string, data?: any) => number;
38
+ debug: (message: string, data?: any) => number;
39
+ getLogs: () => {
40
+ level: string;
41
+ message: string;
42
+ data?: any;
43
+ }[];
44
+ clear: () => number;
45
+ hasLog: (level: string, message: string) => boolean;
46
+ };
47
+ /**
48
+ * Ensures reflect-metadata is loaded for decorator tests
49
+ */
50
+ export declare function setupReflectMetadata(): void;
51
+ /**
52
+ * Clears all mocks between tests
53
+ */
54
+ export declare function setupMockClearing(): void;
@@ -0,0 +1,106 @@
1
+ "use strict";
2
+ /// <reference types="jest" />
3
+ /**
4
+ * Helper utilities for test setup and teardown
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.createTestEnvironment = createTestEnvironment;
8
+ exports.withTestEnvironment = withTestEnvironment;
9
+ exports.useFakeTimers = useFakeTimers;
10
+ exports.createTestLogger = createTestLogger;
11
+ exports.setupReflectMetadata = setupReflectMetadata;
12
+ exports.setupMockClearing = setupMockClearing;
13
+ require("reflect-metadata");
14
+ /**
15
+ * Creates a clean test environment with automatic cleanup
16
+ */
17
+ function createTestEnvironment() {
18
+ const cleanupFns = [];
19
+ return {
20
+ /**
21
+ * Registers a cleanup function to be called after the test
22
+ */
23
+ onCleanup(fn) {
24
+ cleanupFns.push(fn);
25
+ },
26
+ /**
27
+ * Cleans up all registered resources
28
+ */
29
+ async cleanup() {
30
+ for (const fn of cleanupFns.reverse()) {
31
+ await fn();
32
+ }
33
+ cleanupFns.length = 0;
34
+ },
35
+ };
36
+ }
37
+ /**
38
+ * Wraps a test function with automatic environment setup and cleanup
39
+ */
40
+ function withTestEnvironment(testFn) {
41
+ return async (...args) => {
42
+ const env = createTestEnvironment();
43
+ try {
44
+ await testFn(env, ...args);
45
+ }
46
+ finally {
47
+ await env.cleanup();
48
+ }
49
+ };
50
+ }
51
+ /**
52
+ * Creates a mock timer for testing time-based operations
53
+ */
54
+ function useFakeTimers() {
55
+ beforeEach(() => {
56
+ jest.useFakeTimers();
57
+ });
58
+ afterEach(() => {
59
+ jest.runOnlyPendingTimers();
60
+ jest.useRealTimers();
61
+ });
62
+ return {
63
+ advance: (ms) => jest.advanceTimersByTime(ms),
64
+ runAll: () => jest.runAllTimers(),
65
+ runPending: () => jest.runOnlyPendingTimers(),
66
+ };
67
+ }
68
+ /**
69
+ * Creates a test-specific logger that can be inspected
70
+ */
71
+ function createTestLogger() {
72
+ const logs = [];
73
+ return {
74
+ log: (message, data) => logs.push({ level: 'log', message, data }),
75
+ warn: (message, data) => logs.push({ level: 'warn', message, data }),
76
+ error: (message, data) => logs.push({ level: 'error', message, data }),
77
+ info: (message, data) => logs.push({ level: 'info', message, data }),
78
+ debug: (message, data) => logs.push({ level: 'debug', message, data }),
79
+ getLogs: () => logs,
80
+ clear: () => (logs.length = 0),
81
+ hasLog: (level, message) => logs.some((log) => log.level === level && log.message.includes(message)),
82
+ };
83
+ }
84
+ /**
85
+ * Ensures reflect-metadata is loaded for decorator tests
86
+ */
87
+ function setupReflectMetadata() {
88
+ beforeAll(() => {
89
+ // Ensure reflect-metadata is loaded
90
+ if (typeof Reflect === 'undefined' || !Reflect.getMetadata) {
91
+ throw new Error('reflect-metadata is not loaded');
92
+ }
93
+ });
94
+ }
95
+ /**
96
+ * Clears all mocks between tests
97
+ */
98
+ function setupMockClearing() {
99
+ beforeEach(() => {
100
+ jest.clearAllMocks();
101
+ });
102
+ afterEach(() => {
103
+ jest.restoreAllMocks();
104
+ });
105
+ }
106
+ //# sourceMappingURL=setup.helpers.js.map