UNPKG

@mondaydotcomorg/atp-compiler

Version:

Production-ready compiler for transforming async iteration patterns into resumable operations with checkpoint-based state management

347 lines (276 loc) 9.17 kB
import { AsyncIterationDetector } from '../../src/transformer/detector'; describe('AsyncIterationDetector', () => { let detector: AsyncIterationDetector; beforeEach(() => { detector = new AsyncIterationDetector(); }); describe('for-of loops with await', () => { it('should detect for-of loop with await inside', () => { const code = ` for (const item of items) { await atp.llm.call({ prompt: item }); } `; const result = detector.detect(code); expect(result.needsTransform).toBe(true); expect(result.patterns).toContain('for-of-await'); }); it('should not detect for-of loop without await', () => { const code = ` for (const item of items) { console.log(item); } `; const result = detector.detect(code); expect(result.needsTransform).toBe(false); expect(result.patterns).not.toContain('for-of-await'); }); it('should detect nested for-of with await', () => { const code = ` for (const outer of outerItems) { for (const inner of innerItems) { await api.process(outer, inner); } } `; const result = detector.detect(code); expect(result.needsTransform).toBe(true); expect(result.patterns).toContain('for-of-await'); }); }); describe('while loops with await', () => { it('should detect while loop with await inside', () => { const code = ` while (condition) { await atp.llm.call({ prompt: 'test' }); } `; const result = detector.detect(code); expect(result.needsTransform).toBe(true); expect(result.patterns).toContain('while-await'); }); it('should not detect while loop without await', () => { const code = ` while (condition) { console.log('test'); } `; const result = detector.detect(code); expect(result.needsTransform).toBe(false); expect(result.patterns).not.toContain('while-await'); }); }); describe('array.map with async callback', () => { it('should detect map with async callback', () => { const code = ` const results = items.map(async (item) => { return await atp.llm.call({ prompt: item }); }); `; const result = detector.detect(code); expect(result.needsTransform).toBe(true); expect(result.patterns).toContain('map-async'); }); it('should not detect map with sync callback', () => { const code = ` const results = items.map((item) => { return item * 2; }); `; const result = detector.detect(code); expect(result.needsTransform).toBe(false); expect(result.patterns).not.toContain('map-async'); }); }); describe('array.forEach with async callback', () => { it('should detect forEach with async callback', () => { const code = ` items.forEach(async (item) => { await atp.llm.call({ prompt: item }); }); `; const result = detector.detect(code); expect(result.needsTransform).toBe(true); expect(result.patterns).toContain('forEach-async'); }); }); describe('array.filter with async callback', () => { it('should detect filter with async callback', () => { const code = ` const filtered = items.filter(async (item) => { const result = await atp.llm.call({ prompt: item }); return result === 'yes'; }); `; const result = detector.detect(code); expect(result.needsTransform).toBe(true); expect(result.patterns).toContain('filter-async'); }); }); describe('array.reduce with async callback', () => { it('should detect reduce with async callback', () => { const code = ` const sum = items.reduce(async (acc, item) => { const result = await atp.llm.call({ prompt: item }); return acc + result; }, 0); `; const result = detector.detect(code); expect(result.needsTransform).toBe(true); expect(result.patterns).toContain('reduce-async'); }); }); describe('array.find with async callback', () => { it('should detect find with async callback', () => { const code = ` const found = items.find(async (item) => { const result = await atp.llm.call({ prompt: item }); return result === 'match'; }); `; const result = detector.detect(code); expect(result.needsTransform).toBe(true); expect(result.patterns).toContain('find-async'); }); }); describe('array.some with async callback', () => { it('should detect some with async callback', () => { const code = ` const hasMatch = items.some(async (item) => { const result = await atp.llm.call({ prompt: item }); return result === 'yes'; }); `; const result = detector.detect(code); expect(result.needsTransform).toBe(true); expect(result.patterns).toContain('some-async'); }); }); describe('array.every with async callback', () => { it('should detect every with async callback', () => { const code = ` const allMatch = items.every(async (item) => { const result = await atp.llm.call({ prompt: item }); return result === 'yes'; }); `; const result = detector.detect(code); expect(result.needsTransform).toBe(true); expect(result.patterns).toContain('every-async'); }); }); describe('array.flatMap with async callback', () => { it('should detect flatMap with async callback', () => { const code = ` const flattened = items.flatMap(async (item) => { const results = await atp.llm.call({ prompt: item }); return results.split(','); }); `; const result = detector.detect(code); expect(result.needsTransform).toBe(true); expect(result.patterns).toContain('flatMap-async'); }); }); describe('Promise.all', () => { it('should detect Promise.all', () => { const code = ` const results = await Promise.all([ fetch('url1'), fetch('url2'), ]); `; const result = detector.detect(code); expect(result.needsTransform).toBe(true); expect(result.patterns).toContain('promise-all'); }); it('should detect batchable Promise.all with direct pausable calls', () => { const code = ` const results = await Promise.all([ atp.llm.call({ prompt: 'Q1' }), atp.llm.call({ prompt: 'Q2' }), atp.llm.call({ prompt: 'Q3' }), ]); `; const result = detector.detect(code); expect(result.needsTransform).toBe(true); expect(result.patterns).toContain('promise-all'); expect(result.batchableParallel).toBe(true); }); it('should not mark Promise.all as batchable with complex logic', () => { const code = ` const results = await Promise.all( items.map(async (item) => { const step1 = await atp.llm.call({ prompt: item }); return await process(step1); }) ); `; const result = detector.detect(code); expect(result.needsTransform).toBe(true); expect(result.patterns).toContain('promise-all'); expect(result.batchableParallel).toBe(false); }); }); describe('Promise.allSettled', () => { it('should detect Promise.allSettled', () => { const code = ` const results = await Promise.allSettled([ fetch('url1'), fetch('url2'), ]); `; const result = detector.detect(code); expect(result.needsTransform).toBe(true); expect(result.patterns).toContain('promise-allSettled'); }); }); describe('multiple patterns', () => { it('should detect multiple patterns in same code', () => { const code = ` for (const item of items) { await atp.llm.call({ prompt: item }); } const results = items.map(async (item) => { return await atp.llm.call({ prompt: item }); }); const parallel = await Promise.all([ atp.llm.call({ prompt: 'Q1' }), atp.llm.call({ prompt: 'Q2' }), ]); `; const result = detector.detect(code); expect(result.needsTransform).toBe(true); expect(result.patterns).toContain('for-of-await'); expect(result.patterns).toContain('map-async'); expect(result.patterns).toContain('promise-all'); expect(result.batchableParallel).toBe(true); }); }); describe('edge cases', () => { it('should handle empty loops', () => { const code = ` for (const item of items) { } `; const result = detector.detect(code); expect(result.needsTransform).toBe(false); }); it('should handle malformed code gracefully', () => { const code = `this is not valid javascript`; const result = detector.detect(code); expect(result.needsTransform).toBe(false); expect(result.patterns).toEqual([]); }); it('should handle code with no async patterns', () => { const code = ` const x = 1; const y = 2; console.log(x + y); `; const result = detector.detect(code); expect(result.needsTransform).toBe(false); expect(result.patterns).toEqual([]); }); }); });