@onlineapps/conn-orch-api-mapper 1.0.12 → 1.0.14

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.
@@ -511,34 +511,34 @@ describe('API Mapper Component Tests @component', () => {
511
511
  });
512
512
 
513
513
  describe('Response Transformation', () => {
514
- it('should extract data from successful responses', () => {
514
+ it('should extract data from successful responses', async () => {
515
515
  const response = {
516
516
  data: { id: '1', name: 'John' },
517
517
  status: 200,
518
518
  headers: { 'content-type': 'application/json' }
519
519
  };
520
520
 
521
- const transformed = apiMapper.transformResponse(response);
521
+ const transformed = await apiMapper.transformResponse(response);
522
522
  expect(transformed).toEqual({ id: '1', name: 'John' });
523
523
  });
524
524
 
525
- it('should handle empty responses', () => {
525
+ it('should handle empty responses', async () => {
526
526
  const response = {
527
527
  data: null,
528
528
  status: 204
529
529
  };
530
530
 
531
- const transformed = apiMapper.transformResponse(response);
531
+ const transformed = await apiMapper.transformResponse(response);
532
532
  expect(transformed).toEqual(response);
533
533
  });
534
534
 
535
- it('should preserve error responses', () => {
535
+ it('should preserve error responses', async () => {
536
536
  const response = {
537
537
  data: { error: 'Bad request', details: 'Invalid email' },
538
538
  status: 400
539
539
  };
540
540
 
541
- const transformed = apiMapper.transformResponse(response);
541
+ const transformed = await apiMapper.transformResponse(response);
542
542
  expect(transformed).toEqual({ error: 'Bad request', details: 'Invalid email' });
543
543
  });
544
544
  });
@@ -4,6 +4,15 @@ const ApiMapper = require('../../src/ApiMapper');
4
4
  const axios = require('axios');
5
5
 
6
6
  jest.mock('axios');
7
+ jest.mock('@onlineapps/content-resolver', () => {
8
+ return jest.fn().mockImplementation(() => ({
9
+ getAsString: jest.fn(async (ref) => {
10
+ if (typeof ref === 'string') return `resolved:${ref}`;
11
+ if (ref && ref.content) return ref.content;
12
+ return 'resolved-descriptor';
13
+ })
14
+ }));
15
+ });
7
16
 
8
17
  describe('ApiMapper Unit Tests @unit', () => {
9
18
  let apiMapper;
@@ -150,6 +159,75 @@ describe('ApiMapper Unit Tests @unit', () => {
150
159
  });
151
160
  });
152
161
 
162
+ describe('operations.json format (type-driven descriptor handling)', () => {
163
+ it('should store original input schema on parsed operation', () => {
164
+ const operationsJson = {
165
+ operations: {
166
+ 'test-file-info': {
167
+ description: 'Test',
168
+ endpoint: '/api/test-file-info',
169
+ method: 'POST',
170
+ input: {
171
+ file: { type: 'file', required: true }
172
+ },
173
+ output: {
174
+ ok: { type: 'boolean' }
175
+ }
176
+ }
177
+ }
178
+ };
179
+
180
+ const mapper = new ApiMapper({
181
+ openApiSpec: operationsJson,
182
+ serviceUrl: 'http://test-service:3000',
183
+ logger: mockLogger
184
+ });
185
+
186
+ expect(mapper.operations['test-file-info']).toBeDefined();
187
+ expect(mapper.operations['test-file-info'].input).toEqual({
188
+ file: { type: 'file', required: true }
189
+ });
190
+ });
191
+
192
+ it('should pass through descriptors for input fields typed as file', async () => {
193
+ const operationsJson = {
194
+ operations: {
195
+ 'test-file-info': {
196
+ description: 'Test',
197
+ endpoint: '/api/test-file-info',
198
+ method: 'POST',
199
+ input: {
200
+ file: { type: 'file', required: true }
201
+ },
202
+ output: {
203
+ ok: { type: 'boolean' }
204
+ }
205
+ }
206
+ }
207
+ };
208
+
209
+ apiMapper = new ApiMapper({
210
+ openApiSpec: operationsJson,
211
+ serviceUrl: 'http://test-service:3000',
212
+ logger: mockLogger
213
+ });
214
+
215
+ // Ensure we do NOT hit axios
216
+ axios.mockImplementation(async () => ({ status: 200, data: { ok: true } }));
217
+
218
+ const descriptor = { _descriptor: true, type: 'file', storage_ref: 'minio://bucket/path' };
219
+ await apiMapper.callOperation('test-file-info', { file: descriptor }, {});
220
+
221
+ expect(axios).toHaveBeenCalledWith(
222
+ expect.objectContaining({
223
+ method: 'POST',
224
+ url: 'http://test-service:3000/api/test-file-info',
225
+ data: { file: descriptor }
226
+ })
227
+ );
228
+ });
229
+ });
230
+
153
231
  describe('mapOperationToEndpoint', () => {
154
232
  it('should return operation details for valid operation', () => {
155
233
  const endpoint = apiMapper.mapOperationToEndpoint('getUser');
@@ -233,30 +311,30 @@ describe('ApiMapper Unit Tests @unit', () => {
233
311
  });
234
312
 
235
313
  describe('transformResponse', () => {
236
- it('should extract data from response', () => {
314
+ it('should extract data from response', async () => {
237
315
  const response = {
238
316
  data: { id: '1', name: 'John' },
239
317
  status: 200,
240
318
  headers: {}
241
319
  };
242
320
 
243
- const result = apiMapper.transformResponse(response);
321
+ const result = await apiMapper.transformResponse(response);
244
322
  expect(result).toEqual({ id: '1', name: 'John' });
245
323
  });
246
324
 
247
- it('should handle null response', () => {
325
+ it('should handle null response', async () => {
248
326
  const response = {
249
327
  data: null,
250
328
  status: 204
251
329
  };
252
330
 
253
- const result = apiMapper.transformResponse(response);
331
+ const result = await apiMapper.transformResponse(response);
254
332
  expect(result).toEqual(response);
255
333
  });
256
334
 
257
- it('should pass through response without data property', () => {
335
+ it('should pass through response without data property', async () => {
258
336
  const response = { status: 200 };
259
- const result = apiMapper.transformResponse(response);
337
+ const result = await apiMapper.transformResponse(response);
260
338
  expect(result).toEqual(response);
261
339
  });
262
340
  });
@@ -387,13 +465,13 @@ describe('ApiMapper Unit Tests @unit', () => {
387
465
 
388
466
  const result = await apiMapper.callOperation('getUser', { userId: '1' });
389
467
 
390
- expect(axios).toHaveBeenCalledWith({
391
- method: 'GET',
392
- url: 'http://test-service:3000/users/1',
393
- params: {},
394
- headers: {},
395
- data: null
396
- });
468
+ expect(axios).toHaveBeenCalledWith(
469
+ expect.objectContaining({
470
+ method: 'GET',
471
+ url: 'http://test-service:3000/users/1',
472
+ params: {}
473
+ })
474
+ );
397
475
 
398
476
  expect(result).toEqual({ id: '1', name: 'John' });
399
477
  });
@@ -458,4 +536,64 @@ describe('ApiMapper Unit Tests @unit', () => {
458
536
  expect(result).toEqual({ id: '1' });
459
537
  });
460
538
  });
539
+
540
+ describe('_resolveContentDescriptors', () => {
541
+ it('should return input if not object', async () => {
542
+ const result = await apiMapper._resolveContentDescriptors(null);
543
+ expect(result).toBeNull();
544
+ });
545
+
546
+ it('should resolve nested descriptors based on schema types', async () => {
547
+ const input = {
548
+ doc: {
549
+ _descriptor: true,
550
+ type: 'file',
551
+ storage_ref: 'minio://workflow/file1'
552
+ },
553
+ meta: {
554
+ title: {
555
+ _descriptor: true,
556
+ type: 'inline',
557
+ content: 'Hello'
558
+ },
559
+ items: [
560
+ {
561
+ note: {
562
+ _descriptor: true,
563
+ type: 'inline',
564
+ content: 'Note 1'
565
+ }
566
+ }
567
+ ]
568
+ }
569
+ };
570
+
571
+ const operation = {
572
+ input: {
573
+ doc: { type: 'file' },
574
+ meta: {
575
+ type: 'object',
576
+ properties: {
577
+ title: { type: 'string' },
578
+ items: {
579
+ type: 'array',
580
+ items: {
581
+ type: 'object',
582
+ properties: {
583
+ note: { type: 'string' }
584
+ }
585
+ }
586
+ }
587
+ }
588
+ }
589
+ }
590
+ };
591
+
592
+ const result = await apiMapper._resolveContentDescriptors(input, operation);
593
+
594
+ expect(result.doc).toEqual(input.doc); // file passthrough
595
+ expect(result.meta.title).toBe('Hello');
596
+ expect(result.meta.items[0].note).toBe('Note 1');
597
+ });
598
+ });
461
599
  });