@outputai/core 0.14.0 → 0.14.1-next.1ec4416.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 (100) hide show
  1. package/dist/credentials/credentials.d.ts +6 -0
  2. package/dist/credentials/credentials.js +87 -0
  3. package/dist/credentials/encrypted_yaml_provider.d.ts +2 -0
  4. package/dist/credentials/encrypted_yaml_provider.js +77 -0
  5. package/dist/credentials/encryption.d.ts +3 -0
  6. package/dist/credentials/encryption.js +6 -0
  7. package/dist/credentials/errors.d.ts +13 -0
  8. package/dist/credentials/errors.js +39 -0
  9. package/dist/credentials/index.d.ts +6 -0
  10. package/dist/credentials/index.js +5 -0
  11. package/dist/credentials/init.d.ts +1 -0
  12. package/dist/credentials/init.js +7 -0
  13. package/dist/credentials/paths.d.ts +7 -0
  14. package/dist/credentials/paths.js +14 -0
  15. package/dist/credentials/provider_registry.d.ts +3 -0
  16. package/dist/credentials/provider_registry.js +6 -0
  17. package/dist/credentials/types.d.ts +12 -0
  18. package/dist/credentials/types.js +1 -0
  19. package/package.json +25 -14
  20. package/src/async_storage.d.ts +4 -0
  21. package/src/consts.js +0 -2
  22. package/src/helpers/object.d.ts +2 -0
  23. package/src/hooks/index.d.ts +0 -8
  24. package/src/hooks/index.js +0 -3
  25. package/src/logger/index.d.ts +4 -0
  26. package/src/worker/index.js +3 -1
  27. package/bin/healthcheck.spec.js +0 -90
  28. package/src/bus.spec.js +0 -196
  29. package/src/errors.spec.js +0 -19
  30. package/src/helpers/activity_options.spec.js +0 -55
  31. package/src/helpers/component.spec.js +0 -54
  32. package/src/helpers/error_serializer.spec.js +0 -479
  33. package/src/helpers/errors.spec.js +0 -189
  34. package/src/helpers/fetch.spec.js +0 -292
  35. package/src/helpers/function.spec.js +0 -24
  36. package/src/helpers/object.spec.js +0 -425
  37. package/src/helpers/promise.spec.js +0 -62
  38. package/src/helpers/redact.spec.js +0 -66
  39. package/src/helpers/string.spec.js +0 -99
  40. package/src/helpers/temporal_context.spec.ts +0 -83
  41. package/src/helpers/trace_info.spec.js +0 -45
  42. package/src/helpers/workflow_context.spec.js +0 -46
  43. package/src/hooks/index.spec.js +0 -265
  44. package/src/hooks/pending_hooks.spec.js +0 -62
  45. package/src/interface/evaluator.spec.js +0 -685
  46. package/src/interface/logger.spec.js +0 -172
  47. package/src/interface/step.spec.js +0 -128
  48. package/src/interface/validations/index.spec.js +0 -197
  49. package/src/interface/validations/schemas.spec.js +0 -229
  50. package/src/interface/webhook.spec.js +0 -170
  51. package/src/interface/workflow.spec.js +0 -710
  52. package/src/interface/workflow_utils.spec.js +0 -271
  53. package/src/interface/zod_integration.spec.js +0 -646
  54. package/src/internal_activities/index.spec.js +0 -186
  55. package/src/logger/development.spec.js +0 -87
  56. package/src/logger/index.spec.js +0 -27
  57. package/src/logger/production.spec.js +0 -71
  58. package/src/sdk/helpers/component_metadata.spec.js +0 -30
  59. package/src/sdk/helpers/objects.spec.js +0 -16
  60. package/src/sdk/helpers/path.spec.js +0 -102
  61. package/src/sdk/runtime/context.spec.js +0 -37
  62. package/src/sdk/runtime/events.spec.js +0 -40
  63. package/src/temporal/client.spec.js +0 -124
  64. package/src/tracing/processors/local/index.spec.js +0 -204
  65. package/src/tracing/processors/s3/configs.spec.js +0 -64
  66. package/src/tracing/processors/s3/index.spec.js +0 -185
  67. package/src/tracing/processors/s3/redis_client.spec.js +0 -179
  68. package/src/tracing/processors/s3/s3_client.spec.js +0 -68
  69. package/src/tracing/tools/build_trace_tree.spec.js +0 -216
  70. package/src/tracing/trace_engine.spec.js +0 -299
  71. package/src/worker/bundle.spec.js +0 -53
  72. package/src/worker/bundler_options.spec.js +0 -62
  73. package/src/worker/catalog_workflow/catalog_publisher.spec.js +0 -317
  74. package/src/worker/catalog_workflow/index.spec.js +0 -222
  75. package/src/worker/configs.spec.js +0 -213
  76. package/src/worker/configs_tuner_schema.spec.js +0 -127
  77. package/src/worker/connection_monitor.spec.js +0 -328
  78. package/src/worker/global_functions.spec.js +0 -55
  79. package/src/worker/index.spec.js +0 -526
  80. package/src/worker/interceptors/activity.spec.js +0 -369
  81. package/src/worker/interceptors/headers.spec.js +0 -73
  82. package/src/worker/interceptors/workflow.spec.js +0 -357
  83. package/src/worker/interruption.spec.js +0 -177
  84. package/src/worker/loader/activities.spec.js +0 -212
  85. package/src/worker/loader/hooks.spec.js +0 -64
  86. package/src/worker/loader/matchers.spec.js +0 -140
  87. package/src/worker/loader/tools.spec.js +0 -595
  88. package/src/worker/loader/workflows.spec.js +0 -287
  89. package/src/worker/log_hooks.spec.js +0 -303
  90. package/src/worker/shutdown.spec.js +0 -197
  91. package/src/worker/sinks.spec.js +0 -220
  92. package/src/worker/telemetry.spec.js +0 -80
  93. package/src/worker/temporal_logger.spec.js +0 -90
  94. package/src/worker/webpack_loaders/tools.spec.js +0 -314
  95. package/src/worker/webpack_loaders/workflow_rewriter/collect_target_imports.spec.js +0 -134
  96. package/src/worker/webpack_loaders/workflow_rewriter/index.spec.js +0 -154
  97. package/src/worker/webpack_loaders/workflow_rewriter/rewrite_activity_calls.spec.js +0 -165
  98. package/src/worker/webpack_loaders/workflow_validator/index.spec.js +0 -202
  99. package/src/worker/webpack_loaders/workflow_validator/npm_workflow_export_resolve.spec.js +0 -374
  100. package/src/worker/worker_runner.spec.js +0 -220
@@ -1,172 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
2
- import { ACTIVITY_LOGGER_SYMBOL } from '#consts';
3
-
4
- const workflowLogMock = vi.fn();
5
- const proxySinksMock = vi.fn( () => ( {
6
- workflow: {
7
- log: workflowLogMock
8
- }
9
- } ) );
10
- const inWorkflowContextMock = vi.fn( () => false );
11
-
12
- vi.mock( '@temporalio/workflow', () => ( {
13
- inWorkflowContext: inWorkflowContextMock,
14
- proxySinks: proxySinksMock
15
- } ) );
16
-
17
- const logLevels = [
18
- 'error',
19
- 'warn',
20
- 'info',
21
- 'http',
22
- 'verbose',
23
- 'debug',
24
- 'silly'
25
- ];
26
-
27
- const consoleMethodsByLevel = {
28
- error: 'error',
29
- warn: 'warn',
30
- info: 'info',
31
- http: 'log',
32
- verbose: 'log',
33
- debug: 'debug',
34
- silly: 'log'
35
- };
36
-
37
- const loadLogger = async () => ( await import( './logger.js' ) ).Logger;
38
-
39
- describe( 'interface/logger', () => {
40
- beforeEach( () => {
41
- vi.clearAllMocks();
42
- inWorkflowContextMock.mockReturnValue( false );
43
- delete globalThis[ACTIVITY_LOGGER_SYMBOL];
44
- } );
45
-
46
- afterEach( () => {
47
- delete globalThis[ACTIVITY_LOGGER_SYMBOL];
48
- vi.restoreAllMocks();
49
- } );
50
-
51
- it( 'proxies sinks once when the module is loaded', async () => {
52
- await loadLogger();
53
-
54
- expect( proxySinksMock ).toHaveBeenCalledTimes( 1 );
55
- } );
56
-
57
- it( 'logs every level through workflow sinks inside workflow context', async () => {
58
- const logger = await loadLogger();
59
- inWorkflowContextMock.mockReturnValue( true );
60
-
61
- logLevels.forEach( level => {
62
- logger[level]( `${level} message`, { requestId: level } );
63
- } );
64
-
65
- logLevels.forEach( ( level, index ) => {
66
- const payload = {
67
- level,
68
- message: `${level} message`,
69
- metadata: { requestId: level }
70
- };
71
-
72
- expect( workflowLogMock ).toHaveBeenNthCalledWith( index + 1, payload );
73
- } );
74
- } );
75
-
76
- it( 'sanitizes messages and metadata before logging', async () => {
77
- const logger = await loadLogger();
78
- inWorkflowContextMock.mockReturnValue( true );
79
-
80
- logger.info( 123, {
81
- requestId: 'req-1',
82
- level: 'error',
83
- message: 'metadata message'
84
- } );
85
-
86
- expect( workflowLogMock ).toHaveBeenCalledWith( {
87
- level: 'info',
88
- message: '123',
89
- metadata: { requestId: 'req-1' }
90
- } );
91
- } );
92
-
93
- it( 'logs every level through the activity global logger when it is set outside workflow context', async () => {
94
- const logger = await loadLogger();
95
- const activityLoggerMock = vi.fn();
96
- globalThis[ACTIVITY_LOGGER_SYMBOL] = activityLoggerMock;
97
-
98
- logLevels.forEach( level => {
99
- logger[level]( `${level} message`, { requestId: level } );
100
- } );
101
-
102
- logLevels.forEach( ( level, index ) => {
103
- expect( activityLoggerMock ).toHaveBeenNthCalledWith( index + 1, {
104
- level,
105
- message: `${level} message`,
106
- metadata: { requestId: level }
107
- } );
108
- } );
109
- expect( workflowLogMock ).not.toHaveBeenCalled();
110
- } );
111
-
112
- it( 'logs every level to its native console method when no workflow or activity logger is available', async () => {
113
- const logger = await loadLogger();
114
- const consoleMocks = Object.fromEntries(
115
- [ 'debug', 'error', 'info', 'log', 'warn' ].map( method => [
116
- method,
117
- vi.spyOn( console, method ).mockImplementation( () => {} )
118
- ] )
119
- );
120
-
121
- logLevels.forEach( level => {
122
- logger[level]( `${level} message`, { requestId: level } );
123
- } );
124
-
125
- logLevels.forEach( level => {
126
- expect( consoleMocks[consoleMethodsByLevel[level]] ).toHaveBeenCalledWith(
127
- `${level} message`,
128
- { requestId: level }
129
- );
130
- } );
131
- expect( consoleMocks.error ).toHaveBeenCalledTimes( 1 );
132
- expect( consoleMocks.warn ).toHaveBeenCalledTimes( 1 );
133
- expect( consoleMocks.info ).toHaveBeenCalledTimes( 1 );
134
- expect( consoleMocks.debug ).toHaveBeenCalledTimes( 1 );
135
- expect( consoleMocks.log ).toHaveBeenCalledTimes( 3 );
136
- expect( workflowLogMock ).not.toHaveBeenCalled();
137
- } );
138
-
139
- it( 'creates a logger with a default namespace for every level', async () => {
140
- const logger = await loadLogger();
141
- inWorkflowContextMock.mockReturnValue( true );
142
-
143
- const namespacedLogger = logger.createLogger( 'Namespace' );
144
- logLevels.forEach( level => {
145
- namespacedLogger[level]( `${level} message`, { requestId: level } );
146
- } );
147
-
148
- logLevels.forEach( ( level, index ) => {
149
- expect( workflowLogMock ).toHaveBeenNthCalledWith( index + 1, {
150
- level,
151
- message: `${level} message`,
152
- metadata: {
153
- namespace: 'Namespace',
154
- requestId: level
155
- }
156
- } );
157
- } );
158
- } );
159
-
160
- it( 'lets log metadata override the default namespace', async () => {
161
- const logger = await loadLogger();
162
- inWorkflowContextMock.mockReturnValue( true );
163
-
164
- logger.createLogger( 'Default namespace' ).info( 'message', { namespace: 'Inline namespace' } );
165
-
166
- expect( workflowLogMock ).toHaveBeenCalledWith( {
167
- level: 'info',
168
- message: 'message',
169
- metadata: { namespace: 'Inline namespace' }
170
- } );
171
- } );
172
- } );
@@ -1,128 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach } from 'vitest';
2
- import { ValidationError } from '#errors';
3
-
4
- const validateDefinitionMock = vi.hoisted( () => vi.fn() );
5
- const parseInputMock = vi.hoisted( () => vi.fn( input => input ) );
6
- const parseOutputMock = vi.hoisted( () => vi.fn( output => output ) );
7
- const validatorConstructorMock = vi.hoisted( () => vi.fn() );
8
- const createStepMock = vi.hoisted( () => vi.fn( ( { handler } ) => handler ) );
9
-
10
- vi.mock( './validations/index.js', () => {
11
- class StepValidator {
12
- static validateDefinition( ...args ) {
13
- return validateDefinitionMock( ...args );
14
- }
15
-
16
- constructor( ...args ) {
17
- validatorConstructorMock( ...args );
18
- this.parseInput = parseInputMock;
19
- this.parseOutput = parseOutputMock;
20
- }
21
- }
22
-
23
- return { StepValidator };
24
- } );
25
-
26
- vi.mock( '#helpers/component', () => ( {
27
- createStep: createStepMock
28
- } ) );
29
-
30
- describe( 'step()', () => {
31
- beforeEach( () => {
32
- vi.clearAllMocks();
33
- } );
34
-
35
- it( 'validates the definition, creates a runtime validator, and creates a step component', async () => {
36
- const { step } = await import( './step.js' );
37
- const inputSchema = { safeParse: vi.fn() };
38
- const outputSchema = { safeParse: vi.fn() };
39
- const fn = vi.fn().mockResolvedValue( { ok: true } );
40
- const options = { activityOptions: { startToCloseTimeout: '1m' } };
41
-
42
- const wrapper = step( {
43
- name: 'test_step',
44
- description: 'Test step',
45
- inputSchema,
46
- outputSchema,
47
- fn,
48
- options
49
- } );
50
-
51
- expect( validateDefinitionMock ).toHaveBeenCalledWith( {
52
- name: 'test_step',
53
- description: 'Test step',
54
- inputSchema,
55
- outputSchema,
56
- fn,
57
- options
58
- } );
59
- expect( validatorConstructorMock ).toHaveBeenCalledWith( {
60
- name: 'test_step',
61
- inputSchema,
62
- outputSchema
63
- } );
64
-
65
- expect( createStepMock ).toHaveBeenCalledWith( {
66
- name: 'test_step',
67
- description: 'Test step',
68
- inputSchema,
69
- outputSchema,
70
- options,
71
- handler: expect.any( Function )
72
- } );
73
- expect( wrapper ).toBe( createStepMock.mock.calls[0][0].handler );
74
- } );
75
-
76
- it( 'validates input and output around the step function', async () => {
77
- const { step } = await import( './step.js' );
78
- const output = { ok: true };
79
- const fn = vi.fn().mockResolvedValue( output );
80
- const wrapper = step( {
81
- name: 'runtime_step',
82
- inputSchema: undefined,
83
- outputSchema: undefined,
84
- fn
85
- } );
86
-
87
- await expect( wrapper( { value: 'input' } ) ).resolves.toBe( output );
88
-
89
- expect( parseInputMock ).toHaveBeenCalledWith( { value: 'input' } );
90
- expect( fn ).toHaveBeenCalledWith( { value: 'input' } );
91
- expect( parseOutputMock ).toHaveBeenCalledWith( output );
92
- } );
93
-
94
- it( 'does not call the step function when input validation throws', async () => {
95
- const { step } = await import( './step.js' );
96
- const error = new ValidationError( 'invalid input' );
97
- parseInputMock.mockImplementationOnce( () => {
98
- throw error;
99
- } );
100
- const fn = vi.fn();
101
- const wrapper = step( {
102
- name: 'invalid_input_step',
103
- fn
104
- } );
105
-
106
- await expect( wrapper( { value: 'bad' } ) ).rejects.toBe( error );
107
- expect( fn ).not.toHaveBeenCalled();
108
- expect( parseOutputMock ).not.toHaveBeenCalled();
109
- } );
110
-
111
- it( 'propagates output validation errors after the step function runs', async () => {
112
- const { step } = await import( './step.js' );
113
- const error = new ValidationError( 'invalid output' );
114
- parseOutputMock.mockImplementationOnce( () => {
115
- throw error;
116
- } );
117
- const output = { ok: false };
118
- const fn = vi.fn().mockResolvedValue( output );
119
- const wrapper = step( {
120
- name: 'invalid_output_step',
121
- fn
122
- } );
123
-
124
- await expect( wrapper( { value: 'input' } ) ).rejects.toBe( error );
125
- expect( fn ).toHaveBeenCalledOnce();
126
- expect( parseOutputMock ).toHaveBeenCalledWith( output );
127
- } );
128
- } );
@@ -1,197 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { z } from 'zod';
3
- import { ValidationError } from '#errors';
4
- import { EvaluationResult } from '../evaluation_result.js';
5
- import {
6
- EvaluatorValidator,
7
- StepValidator,
8
- WorkflowValidator,
9
- validateExecuteInParallel,
10
- validateRequestPayload
11
- } from './index.js';
12
-
13
- const fn = async () => {};
14
-
15
- const workflowArgs = {
16
- name: 'valid_workflow',
17
- description: 'Valid workflow',
18
- inputSchema: z.object( { value: z.string() } ),
19
- outputSchema: z.object( { result: z.string() } ),
20
- fn,
21
- options: {
22
- activityOptions: {
23
- startToCloseTimeout: '5m',
24
- retry: { maximumAttempts: 2 }
25
- },
26
- disableTrace: true
27
- },
28
- aliases: [ 'old_workflow' ]
29
- };
30
-
31
- const stepArgs = {
32
- name: 'valid_step',
33
- description: 'Valid step',
34
- inputSchema: z.object( { value: z.string() } ),
35
- outputSchema: z.object( { result: z.string() } ),
36
- fn,
37
- options: {
38
- activityOptions: {
39
- heartbeatTimeout: '30s'
40
- }
41
- }
42
- };
43
-
44
- const evaluatorArgs = {
45
- name: 'valid_evaluator',
46
- description: 'Valid evaluator',
47
- inputSchema: z.object( { value: z.string() } ),
48
- fn
49
- };
50
-
51
- describe( 'interface validators', () => {
52
- describe( 'WorkflowValidator', () => {
53
- it( 'validates workflow definitions, input, output, and invocation options', () => {
54
- expect( () => WorkflowValidator.validateDefinition( workflowArgs ) ).not.toThrow();
55
- const validator = new WorkflowValidator( workflowArgs );
56
- const input = { value: 'ok' };
57
- const output = { result: 'ok' };
58
-
59
- expect( validator.parseInput( input ) ).toEqual( input );
60
- expect( validator.parseOutput( output ) ).toEqual( output );
61
- expect( () => validator.parseInvocationOptions( {
62
- detached: true,
63
- activityOptions: { retry: { maximumAttempts: 1 } },
64
- context: { info: { workflowId: 'test-workflow' } }
65
- } ) ).not.toThrow();
66
- } );
67
-
68
- it( 'throws ValidationError with useful prefixes for invalid workflow data', () => {
69
- expect( () => WorkflowValidator.validateDefinition( { ...workflowArgs, name: 'bad-name' } ) ).toThrow( ValidationError );
70
- expect( () => WorkflowValidator.validateDefinition( { ...workflowArgs, name: 'bad-name' } ) ).toThrow(
71
- /Workflow validation failed/
72
- );
73
-
74
- const validator = new WorkflowValidator( workflowArgs );
75
-
76
- expect( () => validator.parseInput( { value: 1 } ) ).toThrow( ValidationError );
77
- expect( () => validator.parseInput( { value: 1 } ) ).toThrow( /Workflow "valid_workflow" input validation failed/ );
78
- expect( () => validator.parseOutput( { result: 1 } ) ).toThrow( /Workflow "valid_workflow" output validation failed/ );
79
- expect( () => validator.parseInvocationOptions( {
80
- options: { activityOptions: { retry: { maximumAttempts: 1 } } }
81
- } ) ).toThrow( /Workflow "valid_workflow" invocation options validation failed/ );
82
- } );
83
-
84
- it( 'skips input and output validation when schemas are omitted', () => {
85
- const validator = new WorkflowValidator( {
86
- name: 'schema_less_workflow',
87
- fn
88
- } );
89
- const input = { anything: true };
90
- const output = { anything: true };
91
-
92
- expect( validator.parseInput( input ) ).toBe( input );
93
- expect( validator.parseOutput( output ) ).toBe( output );
94
- } );
95
- } );
96
-
97
- describe( 'StepValidator', () => {
98
- it( 'validates step definitions, input, and output', () => {
99
- expect( () => StepValidator.validateDefinition( stepArgs ) ).not.toThrow();
100
- const validator = new StepValidator( stepArgs );
101
- const input = { value: 'ok' };
102
- const output = { result: 'ok' };
103
-
104
- expect( validator.parseInput( input ) ).toEqual( input );
105
- expect( validator.parseOutput( output ) ).toEqual( output );
106
- } );
107
-
108
- it( 'throws ValidationError with useful prefixes for invalid step data', () => {
109
- expect( () => StepValidator.validateDefinition( { ...stepArgs, fn: 'not-a-function' } ) ).toThrow(
110
- /Step validation failed/
111
- );
112
-
113
- const validator = new StepValidator( stepArgs );
114
-
115
- expect( () => validator.parseInput( { value: 1 } ) ).toThrow( /Step "valid_step" input validation failed/ );
116
- expect( () => validator.parseOutput( { result: 1 } ) ).toThrow( /Step "valid_step" output validation failed/ );
117
- } );
118
- } );
119
-
120
- describe( 'EvaluatorValidator', () => {
121
- it( 'validates evaluator definitions, input, and EvaluationResult output', () => {
122
- expect( () => EvaluatorValidator.validateDefinition( evaluatorArgs ) ).not.toThrow();
123
- const validator = new EvaluatorValidator( evaluatorArgs );
124
- const input = { value: 'ok' };
125
- const output = new EvaluationResult( { value: 'pass', confidence: 1 } );
126
-
127
- expect( validator.parseInput( input ) ).toEqual( input );
128
- expect( validator.parseOutput( output ) ).toEqual( output );
129
- } );
130
-
131
- it( 'throws ValidationError for output schemas and invalid evaluator output', () => {
132
- expect( () => EvaluatorValidator.validateDefinition( {
133
- ...evaluatorArgs,
134
- outputSchema: z.string()
135
- } ) ).toThrow( /Evaluator validation failed/ );
136
-
137
- const validator = new EvaluatorValidator( evaluatorArgs );
138
-
139
- expect( () => validator.parseInput( { value: 1 } ) ).toThrow( /Evaluator "valid_evaluator" input validation failed/ );
140
- expect( () => validator.parseOutput( { value: 'pass', confidence: 1 } ) ).toThrow(
141
- /Evaluator "valid_evaluator" output validation failed/
142
- );
143
- } );
144
- } );
145
-
146
- describe( 'validateRequestPayload()', () => {
147
- it( 'accepts valid request payloads', () => {
148
- expect( () => validateRequestPayload( {
149
- url: 'https://example.com',
150
- method: 'POST',
151
- payload: { ok: true },
152
- headers: { authorization: 'Bearer token' },
153
- responseOptions: { includeHeaders: true, includeBody: true }
154
- } ) ).not.toThrow();
155
- } );
156
-
157
- it( 'throws ValidationError for invalid request payloads', () => {
158
- expect( () => validateRequestPayload( {
159
- url: 'ftp://example.com',
160
- method: 'POST'
161
- } ) ).toThrow( /Request payload validation failed/ );
162
-
163
- expect( () => validateRequestPayload( {
164
- url: 'https://example.com',
165
- method: 'OPTIONS'
166
- } ) ).toThrow( ValidationError );
167
-
168
- expect( () => validateRequestPayload( {
169
- url: 'https://example.com',
170
- method: 'GET',
171
- responseOptions: { includeHeaders: 'yes' }
172
- } ) ).toThrow( ValidationError );
173
- } );
174
- } );
175
-
176
- describe( 'validateExecuteInParallel()', () => {
177
- it( 'accepts valid parallel execution configs', () => {
178
- expect( () => validateExecuteInParallel( {
179
- jobs: [ () => 'ok' ],
180
- concurrency: Infinity,
181
- onJobCompleted: () => {}
182
- } ) ).not.toThrow();
183
- } );
184
-
185
- it( 'throws ValidationError for invalid parallel execution configs', () => {
186
- expect( () => validateExecuteInParallel( {
187
- jobs: [ () => 'ok' ],
188
- concurrency: 0
189
- } ) ).toThrow( /ExecuteInParallel validation failed/ );
190
-
191
- expect( () => validateExecuteInParallel( {
192
- jobs: [ 'not-a-function' ],
193
- concurrency: 1
194
- } ) ).toThrow( ValidationError );
195
- } );
196
- } );
197
- } );