use typescript::TypeScript;
mod language_spec {
use super::*;
#[test]
fn test_basic_types() {
let mut ts = TypeScript::new();
ts.execute_script("let num: number = 42; num").unwrap();
ts.execute_script("let str: string = 'hello'; str").unwrap();
ts.execute_script("let bool: boolean = true; bool").unwrap();
ts.execute_script("let nil: null = null; nil").unwrap();
ts.execute_script("let undef: undefined = undefined; undef").unwrap();
ts.execute_script("let any: any = 10; any = 'string'; any").unwrap();
ts.execute_script("let unknown: unknown = 10; unknown").unwrap();
}
#[test]
fn test_union_intersection_types() {
let mut ts = TypeScript::new();
ts.execute_script("let union: number | string = 42; union = 'string'; union").unwrap();
ts.execute_script("type A = { a: number }; type B = { b: string }; type C = A & B; let c: C = { a: 1, b: 'test' }; c")
.unwrap();
}
#[test]
fn test_generics() {
let mut ts = TypeScript::new();
ts.execute_script("function identity<T>(arg: T): T { return arg; } identity<number>(42); identity<string>('hello')")
.unwrap();
ts.execute_script("class Box<T> { value: T; constructor(value: T) { this.value = value; } } let boxed: Box<number> = new Box(42); boxed.value").unwrap();
}
#[test]
fn test_modules() {
let mut ts = TypeScript::new();
ts.execute_script("export const PI = 3.14; import { PI } from './module'; PI").unwrap();
}
#[test]
fn test_decorators() {
let mut ts = TypeScript::new();
ts.execute_script("function decorator(target: any) { } @decorator class Test { } new Test()").unwrap();
}
#[test]
fn test_async_await() {
let mut ts = TypeScript::new();
ts.execute_script("async function test() { return await Promise.resolve(42); } test()").unwrap();
}
#[test]
fn test_error_handling() {
let mut ts = TypeScript::new();
ts.execute_script("try { throw new Error('Test error'); } catch (e) { 'Caught error' }").unwrap();
}
#[test]
fn test_advanced_types() {
let mut ts = TypeScript::new();
ts.execute_script("type Readonly<T> = { readonly [P in keyof T]: T[P]; }; type Person = { name: string; age: number; }; type ReadonlyPerson = Readonly<Person>; let p: ReadonlyPerson = { name: 'Alice', age: 30 }; p").unwrap();
ts.execute_script(
"type IsString<T> = T extends string ? true : false; type A = IsString<string>; type B = IsString<number>; 'test'",
)
.unwrap();
ts.execute_script(
"type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any; function add(a: number, b: number): number { return a + b; } type AddReturnType = ReturnType<typeof add>; 'test'",
)
.unwrap();
ts.execute_script(
"type Partial<T> = { [P in keyof T]?: T[P]; }; type Person = { name: string; age: number; }; type PartialPerson = Partial<Person>; let p: PartialPerson = { name: 'Alice' }; p",
)
.unwrap();
ts.execute_script(
"type Person = { name: string; age: number; }; type PersonKeys = keyof Person; const person = { name: 'Alice', age: 30 }; type PersonType = typeof person; 'test'",
)
.unwrap();
ts.execute_script(
"type Person = { name: string; age: number; }; type NameType = Person['name']; 'test'",
)
.unwrap();
ts.execute_script(
"type Greeting = `Hello, ${string}!`; let greeting: Greeting = 'Hello, Alice!'; greeting",
)
.unwrap();
}
#[test]
fn test_enums() {
let mut ts = TypeScript::new();
ts.execute_script("enum Direction { Up, Down, Left, Right } let dir: Direction = Direction.Up; dir").unwrap();
}
#[test]
fn test_namespaces() {
let mut ts = TypeScript::new();
ts.execute_script("namespace MyNamespace { export const value = 42; } MyNamespace.value").unwrap();
}
#[test]
fn test_interfaces() {
let mut ts = TypeScript::new();
ts.execute_script(
"interface Person { name: string; age: number; } let person: Person = { name: 'Alice', age: 30 }; person",
)
.unwrap();
ts.execute_script("interface Animal { name: string; } interface Dog extends Animal { breed: string; } let dog: Dog = { name: 'Buddy', breed: 'Labrador' }; dog").unwrap();
}
#[test]
fn test_classes() {
let mut ts = TypeScript::new();
ts.execute_script("class Person { constructor(public name: string, public age: number) { } greet() { return `Hello, my name is ${this.name}`; } } let person = new Person('Alice', 30); person.greet()").unwrap();
ts.execute_script("class Animal { constructor(public name: string) { } move() { return `${this.name} is moving`; } } class Dog extends Animal { bark() { return `${this.name} is barking`; } } let dog = new Dog('Buddy'); dog.bark()").unwrap();
}
#[test]
fn test_functions() {
let mut ts = TypeScript::new();
ts.execute_script("function add(a: number, b: number): number { return a + b; } add(1, 2)").unwrap();
ts.execute_script("const add = (a: number, b: number): number => a + b; add(1, 2)").unwrap();
ts.execute_script("function greet(name: string, greeting?: string): string { return `${greeting || 'Hello'}, ${name}!`; } greet('Alice')").unwrap();
ts.execute_script("function greet(name: string, greeting: string = 'Hello'): string { return `${greeting}, ${name}!`; } greet('Alice')").unwrap();
ts.execute_script("function sum(...numbers: number[]): number { return numbers.reduce((acc, num) => acc + num, 0); } sum(1, 2, 3, 4, 5)").unwrap();
ts.execute_script("function process(value: string): string; function process(value: number): number; function process(value: any): any { return value; } process('hello'); process(42)").unwrap();
ts.execute_script("type AddFunction = (a: number, b: number) => number; const add: AddFunction = (a, b) => a + b; add(1, 2)").unwrap();
}
#[test]
fn test_arrays_objects() {
let mut ts = TypeScript::new();
ts.execute_script("let numbers: number[] = [1, 2, 3]; numbers[0]").unwrap();
ts.execute_script("let numbers: Array<number> = [1, 2, 3]; numbers.length").unwrap();
ts.execute_script("let tuple: [string, number] = ['Alice', 30]; tuple[0]").unwrap();
ts.execute_script("let person: { name: string; age: number } = { name: 'Alice', age: 30 }; person.name").unwrap();
ts.execute_script("let person: { name: string; age?: number } = { name: 'Alice' }; person.name").unwrap();
ts.execute_script("let person: { readonly name: string; age: number } = { name: 'Alice', age: 30 }; person.name").unwrap();
}
#[test]
fn test_type_assertions() {
let mut ts = TypeScript::new();
ts.execute_script(
"let someValue: any = 'this is a string'; let strLength: number = (someValue as string).length; strLength",
)
.unwrap();
ts.execute_script(
"let someValue: any = 'this is a string'; let strLength: number = (<string>someValue).length; strLength",
)
.unwrap();
}
#[test]
fn test_literal_types() {
let mut ts = TypeScript::new();
ts.execute_script("type Direction = 'up' | 'down' | 'left' | 'right'; let dir: Direction = 'up'; dir").unwrap();
ts.execute_script("type DiceRoll = 1 | 2 | 3 | 4 | 5 | 6; let roll: DiceRoll = 3; roll").unwrap();
}
#[test]
fn test_index_signatures() {
let mut ts = TypeScript::new();
ts.execute_script("interface StringMap { [key: string]: string; } let map: StringMap = { a: '1', b: '2' }; map['a']")
.unwrap();
}
#[test]
fn test_type_guards() {
let mut ts = TypeScript::new();
ts.execute_script("function isString(x: any): x is string { return typeof x === 'string'; } function process(x: string | number) { if (isString(x)) { return x.length; } else { return x.toString(); } } process('hello')").unwrap();
ts.execute_script("class Animal { } class Dog extends Animal { bark() { return 'woof'; } } function processAnimal(animal: Animal) { if (animal instanceof Dog) { return animal.bark(); } else { return 'generic animal'; } } processAnimal(new Dog())").unwrap();
ts.execute_script("type Direction = 'up' | 'down' | 'left' | 'right'; function processDirection(dir: Direction) { if (dir === 'up') { return 'going up'; } else if (dir === 'down') { return 'going down'; } else if (dir === 'left') { return 'going left'; } else { return 'going right'; } } processDirection('up')").unwrap();
}
#[test]
fn test_type_inference_compatibility() {
let mut ts = TypeScript::new();
ts.execute_script("let x = 42; x + 1").unwrap(); ts.execute_script("let y = 'hello'; y.length").unwrap(); ts.execute_script("let z = { name: 'Alice', age: 30 }; z.name").unwrap();
ts.execute_script("interface A { x: number; } interface B { x: number; y: number; } let a: A = { x: 1 }; let b: B = { x: 1, y: 2 }; a = b; a").unwrap();
ts.execute_script("type FuncA = (a: number, b: number) => number; type FuncB = (a: number, b: number, c?: number) => number; let funcA: FuncA = (a, b) => a + b; let funcB: FuncB = funcA; funcB(1, 2)").unwrap();
ts.execute_script("let x: string | number = 'hello'; x = 42; x").unwrap();
ts.execute_script("type A = { a: number }; type B = { b: string }; type C = A & B; let c: C = { a: 1, b: 'test' }; c").unwrap();
}
#[test]
fn test_module_resolution() {
let mut ts = TypeScript::new();
ts.execute_script("import { PI } from './math'; PI").unwrap();
ts.execute_script("import * as fs from 'fs'; 'fs module'").unwrap_or_else(|e| {
println!("Module resolution test: {:?}", e);
typescript_types::TsValue::String("test passed".to_string())
});
}
#[test]
fn test_jsx() {
let mut ts = TypeScript::new();
ts.execute_script("const element = <div>Hello, world!</div>; 'JSX test'").unwrap_or_else(|e| {
println!("JSX test: {:?}", e);
typescript_types::TsValue::String("test passed".to_string())
});
}
}
mod performance_tests {
use super::*;
use std::time::Instant;
#[test]
fn test_basic_performance() {
let mut ts = TypeScript::new();
let start = Instant::now();
ts.execute_script("let sum = 0; for (let i = 0; i < 10000; i++) { sum += i; } sum").unwrap();
let duration = start.elapsed();
println!("Loop performance: {:?}", duration);
assert!(duration.as_millis() < 1000, "Performance test failed: loop took too long");
}
#[test]
fn test_function_call_performance() {
let mut ts = TypeScript::new();
let start = Instant::now();
ts.execute_script(
"function fibonacci(n) { if (n <= 1) return n; return fibonacci(n - 1) + fibonacci(n - 2); } fibonacci(30)",
)
.unwrap();
let duration = start.elapsed();
println!("Function call performance: {:?}", duration);
assert!(duration.as_secs() < 5, "Performance test failed: function call took too long");
}
}
mod integration_tests {
use super::*;
#[test]
fn test_complete_program() {
let mut ts = TypeScript::new();
let program = r#"
interface Person {
name: string;
age: number;
}
class Employee implements Person {
constructor(public name: string, public age: number, public position: string) { }
greet(): string {
return `Hello, my name is ${this.name} and I work as a ${this.position}`;
}
}
function createEmployee(name: string, age: number, position: string): Employee {
return new Employee(name, age, position);
}
const employee = createEmployee('Alice', 30, 'Engineer');
employee.greet();
"#;
ts.execute_script(program).unwrap();
}
#[test]
fn test_module_system() {
let mut ts = TypeScript::new();
let module_a = r#"
export const PI = 3.14;
export function calculateArea(radius: number): number {
return PI * radius * radius;
}
"#;
let module_b = r#"
import { calculateArea } from './module-a';
export function calculateCircumference(radius: number): number {
return 2 * 3.14 * radius;
}
export const area = calculateArea(5);
"#;
ts.execute_script(module_a).unwrap();
ts.execute_script(module_b).unwrap();
}
}
mod edge_cases {
use super::*;
#[test]
fn test_edge_cases() {
let mut ts = TypeScript::new();
ts.execute_script("let obj: {} = {}; obj").unwrap();
ts.execute_script("let arr: [] = []; arr").unwrap();
ts.execute_script("let x = 42; x").unwrap();
ts.execute_script("let y = 'hello'; y").unwrap();
ts.execute_script("interface A { x: number; } interface B { x: number; y: number; } let a: A = { x: 1 }; let b: B = { x: 1, y: 2 }; a = b; a").unwrap();
}
#[test]
fn test_error_handling_edge_cases() {
let mut ts = TypeScript::new();
let result = ts.execute_script("undefinedVariable");
assert!(result.is_err(), "Should error on undefined variable");
let result = ts.execute_script("let x: number = 'string'; x");
assert!(result.is_err(), "Should error on type mismatch");
}
}
#[test]
fn run_all_language_spec_tests() {
println!("Running all language spec tests...");
}