use macroforge_ts::macros::ts_template;
#[test]
fn test_for_in_stmt_object() {
let stream = ts_template! {
for (const key in object) {
console.log(key);
}
};
let source = stream.source();
assert!(source.contains("for"), "Expected 'for'. Got:\n{}", source);
assert!(
source.contains("in object") || source.contains("in object"),
"Expected 'in object'. Got:\n{}",
source
);
}
#[test]
fn test_for_in_stmt_with_index() {
let stream = ts_template! {
for (const index in array) {
console.log(index, array[index]);
}
};
let source = stream.source();
assert!(
source.contains("for") && source.contains("in array"),
"Expected for-in. Got:\n{}",
source
);
}
#[test]
fn test_for_in_stmt_let() {
let stream = ts_template! {
for (let prop in obj) {
if (obj.hasOwnProperty(prop)) {
process(prop);
}
}
};
let source = stream.source();
assert!(
source.contains("let prop") || source.contains("let prop"),
"Expected 'let prop'. Got:\n{}",
source
);
assert!(
source.contains("in obj") || source.contains("in obj"),
"Expected 'in obj'. Got:\n{}",
source
);
}
#[test]
fn test_for_in_stmt_var() {
let stream = ts_template! {
for (var key in config) {
settings[key] = config[key];
}
};
let source = stream.source();
assert!(
source.contains("var key") || source.contains("var key"),
"Expected 'var key'. Got:\n{}",
source
);
}
#[test]
fn test_for_of_stmt_array() {
let stream = ts_template! {
for (const item of items) {
process(item);
}
};
let source = stream.source();
assert!(source.contains("for"), "Expected 'for'. Got:\n{}", source);
assert!(
source.contains("of items") || source.contains("of items"),
"Expected 'of items'. Got:\n{}",
source
);
}
#[test]
fn test_for_of_stmt_destructure_array() {
let stream = ts_template! {
for (const [key, value] of entries) {
map.set(key, value);
}
};
let source = stream.source();
assert!(
source.contains("of entries") || source.contains("of entries"),
"Expected 'of entries'. Got:\n{}",
source
);
}
#[test]
fn test_for_of_stmt_destructure_object() {
let stream = ts_template! {
for (const { name, age } of users) {
console.log(name, age);
}
};
let source = stream.source();
assert!(
source.contains("of users") || source.contains("of users"),
"Expected 'of users'. Got:\n{}",
source
);
}
#[test]
fn test_for_of_stmt_string() {
let stream = ts_template! {
for (const char of text) {
chars.push(char);
}
};
let source = stream.source();
assert!(
source.contains("of text") || source.contains("of text"),
"Expected 'of text'. Got:\n{}",
source
);
}
#[test]
fn test_for_of_stmt_set() {
let stream = ts_template! {
for (const value of uniqueSet) {
results.push(value);
}
};
let source = stream.source();
assert!(
source.contains("of uniqueSet") || source.contains("of uniqueSet"),
"Expected 'of uniqueSet'. Got:\n{}",
source
);
}
#[test]
fn test_for_of_stmt_map() {
let stream = ts_template! {
for (const [k, v] of myMap) {
console.log(k, v);
}
};
let source = stream.source();
assert!(
source.contains("of myMap") || source.contains("of myMap"),
"Expected 'of myMap'. Got:\n{}",
source
);
}
#[test]
fn test_for_await_of_stmt() {
let stream = ts_template! {
async function consume() {
for await (const chunk of stream) {
process(chunk);
}
}
};
let source = stream.source();
assert!(
source.contains("for await") || source.contains("for await"),
"Expected 'for await'. Got:\n{}",
source
);
}
#[test]
fn test_for_await_of_stmt_async_generator() {
let stream = ts_template! {
async function* generate() {
yield 1;
yield 2;
}
async function process() {
for await (const num of generate()) {
console.log(num);
}
}
};
let source = stream.source();
assert!(
source.contains("for await") || source.contains("for await"),
"Expected 'for await'. Got:\n{}",
source
);
}
#[test]
fn test_empty_stmt_standalone() {
let stream = ts_template! {
;
};
let source = stream.source();
assert!(
source.contains(";") || source.trim().is_empty() || source.is_empty(),
"Expected empty statement. Got:\n{}",
source
);
}
#[test]
fn test_empty_stmt_in_for() {
let stream = ts_template! {
for (;;) {
if (shouldBreak) break;
}
};
let source = stream.source();
assert!(
source.contains("for") && source.contains(";;"),
"Expected infinite for loop. Got:\n{}",
source
);
}
#[test]
fn test_empty_stmt_after_label() {
let stream = ts_template! {
outer:
for (let i = 0; i < 10; i++) {
continue outer;
}
};
let source = stream.source();
assert!(
source.contains("outer") && source.contains("continue"),
"Expected labeled statement. Got:\n{}",
source
);
}
#[test]
fn test_throw_stmt_error() {
let stream = ts_template! {
throw new Error("Something went wrong");
};
let source = stream.source();
assert!(
source.contains("throw"),
"Expected 'throw'. Got:\n{}",
source
);
assert!(
source.contains("new Error") || source.contains("new Error"),
"Expected 'new Error'. Got:\n{}",
source
);
}
#[test]
fn test_throw_stmt_custom_error() {
let stream = ts_template! {
throw new ValidationError("Invalid input", { field: "email" });
};
let source = stream.source();
assert!(
source.contains("throw"),
"Expected 'throw'. Got:\n{}",
source
);
assert!(
source.contains("ValidationError"),
"Expected 'ValidationError'. Got:\n{}",
source
);
}
#[test]
fn test_throw_stmt_type_error() {
let stream = ts_template! {
throw new TypeError("Expected a string");
};
let source = stream.source();
assert!(
source.contains("throw") && source.contains("TypeError"),
"Expected throw TypeError. Got:\n{}",
source
);
}
#[test]
fn test_throw_stmt_range_error() {
let stream = ts_template! {
throw new RangeError("Value out of range");
};
let source = stream.source();
assert!(
source.contains("throw") && source.contains("RangeError"),
"Expected throw RangeError. Got:\n{}",
source
);
}
#[test]
fn test_throw_stmt_string() {
let stream = ts_template! {
throw "An error occurred";
};
let source = stream.source();
assert!(
source.contains("throw"),
"Expected 'throw'. Got:\n{}",
source
);
}
#[test]
fn test_throw_stmt_in_function() {
let stream = ts_template! {
function validate(value: unknown): asserts value is string {
if (typeof value !== "string") {
throw new Error("Expected string");
}
}
};
let source = stream.source();
assert!(
source.contains("throw"),
"Expected 'throw'. Got:\n{}",
source
);
}
#[test]
fn test_throw_stmt_rethrow() {
let stream = ts_template! {
try {
riskyOperation();
} catch (e) {
console.error(e);
throw e;
}
};
let source = stream.source();
assert!(
source.contains("throw e") || source.contains("throw e"),
"Expected rethrow. Got:\n{}",
source
);
}
#[test]
fn test_throw_stmt_conditional() {
let stream = ts_template! {
function assertNotNull<T>(value: T | null): T {
if (value === null) {
throw new Error("Value cannot be null");
}
return value;
}
};
let source = stream.source();
assert!(
source.contains("throw") && source.contains("null"),
"Expected conditional throw. Got:\n{}",
source
);
}
#[test]
fn test_for_in_with_throw() {
let stream = ts_template! {
for (const key in required) {
if (!(key in obj)) {
throw new Error("Missing required key: " + key);
}
}
};
let source = stream.source();
assert!(
source.contains("for") && source.contains("in required"),
"Expected for-in. Got:\n{}",
source
);
assert!(source.contains("throw"), "Expected throw. Got:\n{}", source);
}
#[test]
fn test_for_of_with_throw() {
let stream = ts_template! {
for (const item of items) {
if (!isValid(item)) {
throw new Error("Invalid item");
}
process(item);
}
};
let source = stream.source();
assert!(
source.contains("for") && source.contains("of items"),
"Expected for-of. Got:\n{}",
source
);
assert!(source.contains("throw"), "Expected throw. Got:\n{}", source);
}
#[test]
fn test_nested_for_loops() {
let stream = ts_template! {
for (const row of matrix) {
for (const cell of row) {
console.log(cell);
}
}
};
let source = stream.source();
let for_count = source.matches("for").count();
assert!(
for_count >= 2,
"Expected at least 2 'for'. Got {} in:\n{}",
for_count,
source
);
}