codeflash/experiments/code_replacement/test_cases.py

648 lines
15 KiB
Python
Raw Normal View History

2026-01-29 10:05:44 +00:00
"""Test cases for evaluating JavaScript/TypeScript code replacement strategies.
2026-01-15 02:29:20 +00:00
Each test case includes:
- original_source: The original JS/TS code
- function_name: Name of the function to replace
- start_line, end_line: Line numbers of the function (1-indexed)
- new_function: The replacement function code
- expected_result: What the output should look like
- description: What edge case this tests
"""
2026-01-29 11:08:46 +00:00
from __future__ import annotations
2026-01-15 02:29:20 +00:00
from dataclasses import dataclass
@dataclass
class ReplacementTestCase:
name: str
description: str
original_source: str
function_name: str
start_line: int
end_line: int
new_function: str
expected_result: str
# Test cases covering various JavaScript/TypeScript patterns
TEST_CASES = [
# ===========================================
# BASIC CASES
# ===========================================
ReplacementTestCase(
name="simple_function",
description="Basic named function declaration",
2026-01-29 10:05:44 +00:00
original_source="""function add(a, b) {
2026-01-15 02:29:20 +00:00
return a + b;
}
function multiply(a, b) {
return a * b;
}
2026-01-29 10:05:44 +00:00
""",
2026-01-15 02:29:20 +00:00
function_name="add",
start_line=1,
end_line=3,
2026-01-29 10:05:44 +00:00
new_function="""function add(a, b) {
2026-01-15 02:29:20 +00:00
// Optimized version
return a + b | 0;
2026-01-29 10:05:44 +00:00
}""",
expected_result="""function add(a, b) {
2026-01-15 02:29:20 +00:00
// Optimized version
return a + b | 0;
}
function multiply(a, b) {
return a * b;
}
2026-01-29 10:05:44 +00:00
""",
2026-01-15 02:29:20 +00:00
),
ReplacementTestCase(
name="arrow_function_const",
description="Arrow function assigned to const",
2026-01-29 10:05:44 +00:00
original_source="""const square = (x) => {
2026-01-15 02:29:20 +00:00
return x * x;
};
const cube = (x) => x * x * x;
2026-01-29 10:05:44 +00:00
""",
2026-01-15 02:29:20 +00:00
function_name="square",
start_line=1,
end_line=3,
2026-01-29 10:05:44 +00:00
new_function="""const square = (x) => {
2026-01-15 02:29:20 +00:00
return x ** 2;
2026-01-29 10:05:44 +00:00
};""",
expected_result="""const square = (x) => {
2026-01-15 02:29:20 +00:00
return x ** 2;
};
const cube = (x) => x * x * x;
2026-01-29 10:05:44 +00:00
""",
2026-01-15 02:29:20 +00:00
),
ReplacementTestCase(
name="arrow_function_oneliner",
description="Single-line arrow function",
2026-01-29 10:05:44 +00:00
original_source="""const double = x => x * 2;
2026-01-15 02:29:20 +00:00
const triple = x => x * 3;
2026-01-29 10:05:44 +00:00
""",
2026-01-15 02:29:20 +00:00
function_name="double",
start_line=1,
end_line=1,
2026-01-29 10:05:44 +00:00
new_function="""const double = x => x << 1;""",
expected_result="""const double = x => x << 1;
2026-01-15 02:29:20 +00:00
const triple = x => x * 3;
2026-01-29 10:05:44 +00:00
""",
2026-01-15 02:29:20 +00:00
),
# ===========================================
# CLASS METHODS
# ===========================================
ReplacementTestCase(
name="class_method",
description="Method inside a class",
2026-01-29 10:05:44 +00:00
original_source="""class Calculator {
2026-01-15 02:29:20 +00:00
constructor(value) {
this.value = value;
}
add(n) {
return this.value + n;
}
multiply(n) {
return this.value * n;
}
}
2026-01-29 10:05:44 +00:00
""",
2026-01-15 02:29:20 +00:00
function_name="add",
start_line=6,
end_line=8,
2026-01-29 10:05:44 +00:00
new_function=""" add(n) {
2026-01-15 02:29:20 +00:00
// Optimized addition
return (this.value + n) | 0;
2026-01-29 10:05:44 +00:00
}""",
expected_result="""class Calculator {
2026-01-15 02:29:20 +00:00
constructor(value) {
this.value = value;
}
add(n) {
// Optimized addition
return (this.value + n) | 0;
}
multiply(n) {
return this.value * n;
}
}
2026-01-29 10:05:44 +00:00
""",
2026-01-15 02:29:20 +00:00
),
ReplacementTestCase(
name="static_method",
description="Static method in class",
2026-01-29 10:05:44 +00:00
original_source="""class MathUtils {
2026-01-15 02:29:20 +00:00
static fibonacci(n) {
if (n <= 1) return n;
return MathUtils.fibonacci(n - 1) + MathUtils.fibonacci(n - 2);
}
static factorial(n) {
if (n <= 1) return 1;
return n * MathUtils.factorial(n - 1);
}
}
2026-01-29 10:05:44 +00:00
""",
2026-01-15 02:29:20 +00:00
function_name="fibonacci",
start_line=2,
end_line=5,
2026-01-29 10:05:44 +00:00
new_function=""" static fibonacci(n) {
2026-01-15 02:29:20 +00:00
// Memoized version
const memo = [0, 1];
for (let i = 2; i <= n; i++) {
memo[i] = memo[i-1] + memo[i-2];
}
return memo[n];
2026-01-29 10:05:44 +00:00
}""",
expected_result="""class MathUtils {
2026-01-15 02:29:20 +00:00
static fibonacci(n) {
// Memoized version
const memo = [0, 1];
for (let i = 2; i <= n; i++) {
memo[i] = memo[i-1] + memo[i-2];
}
return memo[n];
}
static factorial(n) {
if (n <= 1) return 1;
return n * MathUtils.factorial(n - 1);
}
}
2026-01-29 10:05:44 +00:00
""",
2026-01-15 02:29:20 +00:00
),
# ===========================================
# ASYNC FUNCTIONS
# ===========================================
ReplacementTestCase(
name="async_function",
description="Async function declaration",
2026-01-29 10:05:44 +00:00
original_source="""async function fetchData(url) {
2026-01-15 02:29:20 +00:00
const response = await fetch(url);
return response.json();
}
async function postData(url, data) {
const response = await fetch(url, { method: 'POST', body: JSON.stringify(data) });
return response.json();
}
2026-01-29 10:05:44 +00:00
""",
2026-01-15 02:29:20 +00:00
function_name="fetchData",
start_line=1,
end_line=4,
2026-01-29 10:05:44 +00:00
new_function="""async function fetchData(url) {
2026-01-15 02:29:20 +00:00
// With caching
const cached = cache.get(url);
if (cached) return cached;
const response = await fetch(url);
const data = await response.json();
cache.set(url, data);
return data;
2026-01-29 10:05:44 +00:00
}""",
expected_result="""async function fetchData(url) {
2026-01-15 02:29:20 +00:00
// With caching
const cached = cache.get(url);
if (cached) return cached;
const response = await fetch(url);
const data = await response.json();
cache.set(url, data);
return data;
}
async function postData(url, data) {
const response = await fetch(url, { method: 'POST', body: JSON.stringify(data) });
return response.json();
}
2026-01-29 10:05:44 +00:00
""",
2026-01-15 02:29:20 +00:00
),
# ===========================================
# EDGE CASES: COMMENTS & WHITESPACE
# ===========================================
ReplacementTestCase(
name="function_with_jsdoc",
description="Function with JSDoc comment above it",
2026-01-29 10:05:44 +00:00
original_source="""/**
2026-01-15 02:29:20 +00:00
* Calculates the sum of two numbers.
* @param {number} a - First number
* @param {number} b - Second number
* @returns {number} The sum
*/
function sum(a, b) {
return a + b;
}
function diff(a, b) {
return a - b;
}
2026-01-29 10:05:44 +00:00
""",
2026-01-15 02:29:20 +00:00
function_name="sum",
start_line=7, # Function starts after JSDoc
end_line=9,
2026-01-29 10:05:44 +00:00
new_function="""function sum(a, b) {
2026-01-15 02:29:20 +00:00
return (a + b) | 0;
2026-01-29 10:05:44 +00:00
}""",
expected_result="""/**
2026-01-15 02:29:20 +00:00
* Calculates the sum of two numbers.
* @param {number} a - First number
* @param {number} b - Second number
* @returns {number} The sum
*/
function sum(a, b) {
return (a + b) | 0;
}
function diff(a, b) {
return a - b;
}
2026-01-29 10:05:44 +00:00
""",
2026-01-15 02:29:20 +00:00
),
ReplacementTestCase(
name="inline_comments",
description="Function with inline comments",
2026-01-29 10:05:44 +00:00
original_source="""function process(data) {
2026-01-15 02:29:20 +00:00
// Validate input
if (!data) return null;
// Transform data
const result = data.map(x => x * 2); // double each value
return result;
}
2026-01-29 10:05:44 +00:00
""",
2026-01-15 02:29:20 +00:00
function_name="process",
start_line=1,
end_line=9,
2026-01-29 10:05:44 +00:00
new_function="""function process(data) {
2026-01-15 02:29:20 +00:00
if (!data) return null;
return data.map(x => x << 1);
2026-01-29 10:05:44 +00:00
}""",
expected_result="""function process(data) {
2026-01-15 02:29:20 +00:00
if (!data) return null;
return data.map(x => x << 1);
}
2026-01-29 10:05:44 +00:00
""",
2026-01-15 02:29:20 +00:00
),
# ===========================================
# NESTED FUNCTIONS
# ===========================================
ReplacementTestCase(
name="function_with_nested",
description="Function containing nested functions",
2026-01-29 10:05:44 +00:00
original_source="""function outer(x) {
2026-01-15 02:29:20 +00:00
function inner(y) {
return y * 2;
}
return inner(x) + 1;
}
function other() {
return 42;
}
2026-01-29 10:05:44 +00:00
""",
2026-01-15 02:29:20 +00:00
function_name="outer",
start_line=1,
end_line=6,
2026-01-29 10:05:44 +00:00
new_function="""function outer(x) {
2026-01-15 02:29:20 +00:00
const inner = y => y << 1;
return inner(x) + 1;
2026-01-29 10:05:44 +00:00
}""",
expected_result="""function outer(x) {
2026-01-15 02:29:20 +00:00
const inner = y => y << 1;
return inner(x) + 1;
}
function other() {
return 42;
}
2026-01-29 10:05:44 +00:00
""",
2026-01-15 02:29:20 +00:00
),
# ===========================================
# TYPESCRIPT SPECIFIC
# ===========================================
ReplacementTestCase(
name="typescript_typed_function",
description="TypeScript function with type annotations",
2026-01-29 10:05:44 +00:00
original_source="""function greet(name: string): string {
2026-01-15 02:29:20 +00:00
return `Hello, ${name}!`;
}
function farewell(name: string): string {
return `Goodbye, ${name}!`;
}
2026-01-29 10:05:44 +00:00
""",
2026-01-15 02:29:20 +00:00
function_name="greet",
start_line=1,
end_line=3,
2026-01-29 10:05:44 +00:00
new_function="""function greet(name: string): string {
2026-01-15 02:29:20 +00:00
return 'Hello, ' + name + '!';
2026-01-29 10:05:44 +00:00
}""",
expected_result="""function greet(name: string): string {
2026-01-15 02:29:20 +00:00
return 'Hello, ' + name + '!';
}
function farewell(name: string): string {
return `Goodbye, ${name}!`;
}
2026-01-29 10:05:44 +00:00
""",
2026-01-15 02:29:20 +00:00
),
ReplacementTestCase(
name="typescript_generic",
description="TypeScript generic function",
2026-01-29 10:05:44 +00:00
original_source="""function identity<T>(arg: T): T {
2026-01-15 02:29:20 +00:00
return arg;
}
function first<T>(arr: T[]): T | undefined {
return arr[0];
}
2026-01-29 10:05:44 +00:00
""",
2026-01-15 02:29:20 +00:00
function_name="identity",
start_line=1,
end_line=3,
2026-01-29 10:05:44 +00:00
new_function="""function identity<T>(arg: T): T {
2026-01-15 02:29:20 +00:00
// Direct return
return arg;
2026-01-29 10:05:44 +00:00
}""",
expected_result="""function identity<T>(arg: T): T {
2026-01-15 02:29:20 +00:00
// Direct return
return arg;
}
function first<T>(arr: T[]): T | undefined {
return arr[0];
}
2026-01-29 10:05:44 +00:00
""",
2026-01-15 02:29:20 +00:00
),
ReplacementTestCase(
name="typescript_interface_method",
description="TypeScript class implementing interface",
2026-01-29 10:05:44 +00:00
original_source="""interface Processor {
2026-01-15 02:29:20 +00:00
process(data: number[]): number[];
}
class ArrayProcessor implements Processor {
process(data: number[]): number[] {
return data.map(x => x * 2);
}
transform(data: number[]): number[] {
return data.filter(x => x > 0);
}
}
2026-01-29 10:05:44 +00:00
""",
2026-01-15 02:29:20 +00:00
function_name="process",
start_line=6,
end_line=8,
2026-01-29 10:05:44 +00:00
new_function=""" process(data: number[]): number[] {
2026-01-15 02:29:20 +00:00
const result = new Array(data.length);
for (let i = 0; i < data.length; i++) {
result[i] = data[i] << 1;
}
return result;
2026-01-29 10:05:44 +00:00
}""",
expected_result="""interface Processor {
2026-01-15 02:29:20 +00:00
process(data: number[]): number[];
}
class ArrayProcessor implements Processor {
process(data: number[]): number[] {
const result = new Array(data.length);
for (let i = 0; i < data.length; i++) {
result[i] = data[i] << 1;
}
return result;
}
transform(data: number[]): number[] {
return data.filter(x => x > 0);
}
}
2026-01-29 10:05:44 +00:00
""",
2026-01-15 02:29:20 +00:00
),
# ===========================================
# EXPORT PATTERNS
# ===========================================
ReplacementTestCase(
name="exported_function",
description="Exported function declaration",
2026-01-29 10:05:44 +00:00
original_source="""export function calculate(a, b) {
2026-01-15 02:29:20 +00:00
return a + b;
}
export function subtract(a, b) {
return a - b;
}
2026-01-29 10:05:44 +00:00
""",
2026-01-15 02:29:20 +00:00
function_name="calculate",
start_line=1,
end_line=3,
2026-01-29 10:05:44 +00:00
new_function="""export function calculate(a, b) {
2026-01-15 02:29:20 +00:00
return (a + b) | 0;
2026-01-29 10:05:44 +00:00
}""",
expected_result="""export function calculate(a, b) {
2026-01-15 02:29:20 +00:00
return (a + b) | 0;
}
export function subtract(a, b) {
return a - b;
}
2026-01-29 10:05:44 +00:00
""",
2026-01-15 02:29:20 +00:00
),
ReplacementTestCase(
name="default_export",
description="Default exported function",
2026-01-29 10:05:44 +00:00
original_source="""export default function main(args) {
2026-01-15 02:29:20 +00:00
return args.reduce((a, b) => a + b, 0);
}
function helper(x) {
return x * 2;
}
2026-01-29 10:05:44 +00:00
""",
2026-01-15 02:29:20 +00:00
function_name="main",
start_line=1,
end_line=3,
2026-01-29 10:05:44 +00:00
new_function="""export default function main(args) {
2026-01-15 02:29:20 +00:00
let sum = 0;
for (const arg of args) sum += arg;
return sum;
2026-01-29 10:05:44 +00:00
}""",
expected_result="""export default function main(args) {
2026-01-15 02:29:20 +00:00
let sum = 0;
for (const arg of args) sum += arg;
return sum;
}
function helper(x) {
return x * 2;
}
2026-01-29 10:05:44 +00:00
""",
2026-01-15 02:29:20 +00:00
),
# ===========================================
# DECORATORS (TypeScript/Experimental JS)
# ===========================================
ReplacementTestCase(
name="decorated_method",
description="Method with decorators",
2026-01-29 10:05:44 +00:00
original_source="""class Service {
2026-01-15 02:29:20 +00:00
@log
@memoize
compute(x: number): number {
return x * x;
}
other(): void {
console.log('other');
}
}
2026-01-29 10:05:44 +00:00
""",
2026-01-15 02:29:20 +00:00
function_name="compute",
start_line=4, # Method starts after decorators
end_line=6,
2026-01-29 10:05:44 +00:00
new_function=""" compute(x: number): number {
2026-01-15 02:29:20 +00:00
return x ** 2;
2026-01-29 10:05:44 +00:00
}""",
expected_result="""class Service {
2026-01-15 02:29:20 +00:00
@log
@memoize
compute(x: number): number {
return x ** 2;
}
other(): void {
console.log('other');
}
}
2026-01-29 10:05:44 +00:00
""",
2026-01-15 02:29:20 +00:00
),
# ===========================================
# FIRST/LAST FUNCTION EDGE CASES
# ===========================================
ReplacementTestCase(
name="first_function_in_file",
description="Replacing the very first function in file",
2026-01-29 10:05:44 +00:00
original_source="""function first() {
2026-01-15 02:29:20 +00:00
return 1;
}
function second() {
return 2;
}
2026-01-29 10:05:44 +00:00
""",
2026-01-15 02:29:20 +00:00
function_name="first",
start_line=1,
end_line=3,
2026-01-29 10:05:44 +00:00
new_function="""function first() {
2026-01-15 02:29:20 +00:00
return 1 | 0;
2026-01-29 10:05:44 +00:00
}""",
expected_result="""function first() {
2026-01-15 02:29:20 +00:00
return 1 | 0;
}
function second() {
return 2;
}
2026-01-29 10:05:44 +00:00
""",
2026-01-15 02:29:20 +00:00
),
ReplacementTestCase(
name="last_function_in_file",
description="Replacing the last function in file",
2026-01-29 10:05:44 +00:00
original_source="""function first() {
2026-01-15 02:29:20 +00:00
return 1;
}
function last() {
return 999;
}
2026-01-29 10:05:44 +00:00
""",
2026-01-15 02:29:20 +00:00
function_name="last",
start_line=5,
end_line=7,
2026-01-29 10:05:44 +00:00
new_function="""function last() {
2026-01-15 02:29:20 +00:00
return 1000;
2026-01-29 10:05:44 +00:00
}""",
expected_result="""function first() {
2026-01-15 02:29:20 +00:00
return 1;
}
function last() {
return 1000;
}
2026-01-29 10:05:44 +00:00
""",
2026-01-15 02:29:20 +00:00
),
ReplacementTestCase(
name="only_function_in_file",
description="Replacing the only function in file",
2026-01-29 10:05:44 +00:00
original_source="""function only() {
2026-01-15 02:29:20 +00:00
return 42;
}
2026-01-29 10:05:44 +00:00
""",
2026-01-15 02:29:20 +00:00
function_name="only",
start_line=1,
end_line=3,
2026-01-29 10:05:44 +00:00
new_function="""function only() {
2026-01-15 02:29:20 +00:00
return 42 | 0;
2026-01-29 10:05:44 +00:00
}""",
expected_result="""function only() {
2026-01-15 02:29:20 +00:00
return 42 | 0;
}
2026-01-29 10:05:44 +00:00
""",
2026-01-15 02:29:20 +00:00
),
# ===========================================
# INDENTATION PRESERVATION
# ===========================================
ReplacementTestCase(
name="deeply_nested_method",
description="Method with deep indentation",
2026-01-29 10:05:44 +00:00
original_source="""const module = {
2026-01-15 02:29:20 +00:00
submodule: {
handler: {
process(data) {
return data.map(x => x * 2);
}
}
}
};
2026-01-29 10:05:44 +00:00
""",
2026-01-15 02:29:20 +00:00
function_name="process",
start_line=4,
end_line=6,
2026-01-29 10:05:44 +00:00
new_function=""" process(data) {
2026-01-15 02:29:20 +00:00
return data.map(x => x << 1);
2026-01-29 10:05:44 +00:00
}""",
expected_result="""const module = {
2026-01-15 02:29:20 +00:00
submodule: {
handler: {
process(data) {
return data.map(x => x << 1);
}
}
}
};
2026-01-29 10:05:44 +00:00
""",
2026-01-15 02:29:20 +00:00
),
]
def get_test_cases() -> list[ReplacementTestCase]:
2026-01-15 02:29:20 +00:00
"""Return all test cases."""
return TEST_CASES
def get_test_case_by_name(name: str) -> ReplacementTestCase | None:
"""Get a specific test case by name."""
for tc in TEST_CASES:
if tc.name == name:
return tc
return None