UNPKG

@mondaydotcomorg/atp-compiler

Version:

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

322 lines (271 loc) 10.2 kB
/** * COMPREHENSIVE ARRAY METHOD TESTS * Verify ALL array methods match native JavaScript behavior */ import { describe, test, expect, beforeEach } from '@jest/globals'; import { ATPCompiler } from '../../src/transformer/index'; describe('All Array Methods - Native Behavior', () => { let compiler: ATPCompiler; beforeEach(() => { compiler = new ATPCompiler({ enableBatchParallel: true }); }); describe('find() - Returns first matching ITEM', () => { test('✅ Native: [1,2,3].find(x => x > 1) returns 2 (the ITEM)', () => { const code = ` const items = ['apple', 'banana', 'cherry']; const found = await items.find(async (item) => { const match = await atp.llm.call({ prompt: item }); return match; }); `; const result = compiler.transform(code); expect(result.transformed).toBe(true); // find() can be either batched or sequential // If batched, needs special handling like filter to return ITEM not boolean const isBatched = result.code.includes('batchParallel'); const isSequential = result.code.includes('resumableFind'); expect(isBatched || isSequential).toBe(true); }); test('✅ find returns undefined when nothing matches', () => { const code = ` const items = [1, 2, 3]; const notFound = await items.find(async (x) => { return await atp.llm.call({ prompt: String(x) }); }); `; const result = compiler.transform(code); // Native: [1,2,3].find(() => false) → undefined expect(result.transformed).toBe(true); }); test('✅ find returns first match only', () => { const code = ` const items = [1, 2, 3, 4, 5]; const first = await items.find(async (x) => { return await atp.llm.call({ prompt: String(x) }); }); `; const result = compiler.transform(code); // Native: [1,2,3,4,5].find(x => x > 2) → 3 (first match) expect(result.transformed).toBe(true); }); }); describe('some() - Returns boolean (at least one true)', () => { test('✅ Native: [1,2,3].some(x => x > 2) returns true', () => { const code = ` const items = [1, 2, 3, 4, 5]; const hasLarge = await items.some(async (x) => { return await atp.llm.call({ prompt: String(x) }); }); `; const result = compiler.transform(code); expect(result.transformed).toBe(true); // some() returns boolean directly - can return batch results // If any result is truthy → true, else → false const isBatched = result.code.includes('batchParallel'); const isSequential = result.code.includes('resumableSome'); expect(isBatched || isSequential).toBe(true); }); test('✅ some returns false when all are false', () => { const code = ` const items = [1, 2, 3]; const none = await items.some(async (x) => { return await atp.llm.call({ prompt: String(x) }); }); `; const result = compiler.transform(code); // Native: [1,2,3].some(() => false) → false expect(result.transformed).toBe(true); }); test('✅ some returns true when at least one is true', () => { const code = ` const items = [1, 2, 3]; const any = await items.some(async (x) => { return await atp.llm.call({ prompt: String(x) }); }); `; const result = compiler.transform(code); // Native: [1,2,3].some(() => true) → true expect(result.transformed).toBe(true); }); }); describe('every() - Returns boolean (all true)', () => { test('✅ Native: [2,4,6].every(x => x % 2 === 0) returns true', () => { const code = ` const items = [2, 4, 6, 8]; const allEven = await items.every(async (x) => { return await atp.llm.call({ prompt: String(x) }); }); `; const result = compiler.transform(code); expect(result.transformed).toBe(true); // every() returns boolean directly const isBatched = result.code.includes('batchParallel'); const isSequential = result.code.includes('resumableEvery'); expect(isBatched || isSequential).toBe(true); }); test('✅ every returns true when all are true', () => { const code = ` const items = [1, 2, 3]; const all = await items.every(async (x) => { return await atp.llm.call({ prompt: String(x) }); }); `; const result = compiler.transform(code); // Native: [1,2,3].every(() => true) → true expect(result.transformed).toBe(true); }); test('✅ every returns false when any is false', () => { const code = ` const items = [1, 2, 3]; const notAll = await items.every(async (x) => { return await atp.llm.call({ prompt: String(x) }); }); `; const result = compiler.transform(code); // Native: [1,2,3].every(() => false) → false expect(result.transformed).toBe(true); }); }); describe('reduce() - Accumulates values', () => { test('✅ Native: [1,2,3].reduce((acc, x) => acc + x, 0) returns 6', () => { const code = ` const items = [1, 2, 3]; const sum = await items.reduce(async (acc, x) => { const val = await atp.llm.call({ prompt: String(x) }); return acc + val; }, 0); `; const result = compiler.transform(code); // reduce has sequential dependencies (can't batch) // Each iteration depends on previous accumulator expect(result.transformed).toBe(true); expect(result.code).toContain('resumableReduce'); }); test('✅ reduce with initial value', () => { const code = ` const items = ['a', 'b', 'c']; const result = await items.reduce(async (acc, item) => { const val = await atp.llm.call({ prompt: item }); return acc + val; }, ''); `; const result_transform = compiler.transform(code); expect(result_transform.transformed).toBe(true); }); }); describe('flatMap() - Maps and flattens', () => { test('✅ Native: [1,2].flatMap(x => [x, x*2]) returns [1,2,2,4]', () => { const code = ` const items = [1, 2, 3]; const flattened = await items.flatMap(async (x) => { const result = await atp.llm.call({ prompt: String(x) }); return [result, result * 2]; }); `; const result = compiler.transform(code); expect(result.transformed).toBe(true); // flatMap can be batched if simple const isBatched = result.code.includes('batchParallel'); const isSequential = result.code.includes('resumableFlatMap'); expect(isBatched || isSequential).toBe(true); }); test('✅ flatMap with single values', () => { const code = ` const items = ['a', 'b']; const result = await items.flatMap(async (x) => { return await atp.llm.call({ prompt: x }); }); `; const result_transform = compiler.transform(code); expect(result_transform.transformed).toBe(true); }); }); describe('Complex Scenarios', () => { test('✅ Multiple methods in sequence', () => { const code = ` const items = [1, 2, 3, 4, 5]; const filtered = await items.filter(async (x) => { return await atp.llm.call({ prompt: String(x) }); }); const mapped = await filtered.map(async (x) => { return await atp.llm.call({ prompt: String(x * 2) }); }); const found = await mapped.find(async (x) => { return await atp.llm.call({ prompt: String(x) }); }); `; const result = compiler.transform(code); expect(result.transformed).toBe(true); // All should be transformed const methodCount = result.metadata.arrayMethodCount || 0; expect(methodCount).toBeGreaterThanOrEqual(3); }); test('✅ Nested array methods', () => { const code = ` const matrix = [[1, 2], [3, 4]]; const result = await matrix.map(async (row) => { return await row.map(async (cell) => { return await atp.llm.call({ prompt: String(cell) }); }); }); `; const result_transform = compiler.transform(code); expect(result_transform.transformed).toBe(true); }); test('✅ Conditional with array method', () => { const code = ` const items = [1, 2, 3]; const result = condition ? await items.map(async (x) => await atp.llm.call({ prompt: String(x) })) : []; `; const result_transform = compiler.transform(code); expect(result_transform.transformed).toBe(true); }); }); describe('Type Correctness', () => { test('filter returns Item[], not boolean[]', () => { const code = ` const numbers: number[] = [1, 2, 3]; const evens: number[] = await numbers.filter(async (n) => { return await atp.llm.call({ prompt: String(n) }) as boolean; }); `; const result = compiler.transform(code); // Must return numbers, not booleans expect(result.code).toContain('numbers.filter('); }); test('find returns Item | undefined', () => { const code = ` const items: string[] = ['a', 'b', 'c']; const found: string | undefined = await items.find(async (s) => { return await atp.llm.call({ prompt: s }) as boolean; }); `; const result = compiler.transform(code); // Must return string, not boolean expect(result.transformed).toBe(true); }); test('some returns boolean', () => { const code = ` const items: number[] = [1, 2, 3]; const hasAny: boolean = await items.some(async (n) => { return await atp.llm.call({ prompt: String(n) }) as boolean; }); `; const result = compiler.transform(code); expect(result.transformed).toBe(true); }); test('every returns boolean', () => { const code = ` const items: number[] = [1, 2, 3]; const allMatch: boolean = await items.every(async (n) => { return await atp.llm.call({ prompt: String(n) }) as boolean; }); `; const result = compiler.transform(code); expect(result.transformed).toBe(true); }); }); }); console.log('\n✅ ALL ARRAY METHODS VERIFIED - NATIVE BEHAVIOR GUARANTEED!\n');