use super::common::*;
use crate::embed::build_embedding_text;
use crate::parser::Language;
#[test]
fn test_basic_function() {
let source = r#"function greet(name) {
return `Hello, ${name}!`;
}"#;
let units = parse(source, Language::JavaScript, "test.js");
let func = get_unit_by_name(&units, "greet").unwrap();
let text = build_embedding_text(func);
let expected = r#"Function: greet
Signature: function greet(name) {
Parameters: name
File: test test.js
Code:
function greet(name) {
return `Hello, ${name}!`;
}"#;
assert_eq!(text, expected);
}
#[test]
fn test_arrow_function() {
let source = r#"const add = (a, b) => {
return a + b;
};"#;
let units = parse(source, Language::JavaScript, "test.js");
let func = get_unit_by_name(&units, "add").unwrap();
let text = build_embedding_text(func);
let expected = r#"Function: add
Signature: const add = (a, b) => {
Parameters: a, b
File: test test.js
Code:
const add = (a, b) => {
return a + b;
};"#;
assert_eq!(text, expected);
}
#[test]
fn test_function_with_jsdoc() {
let source = r#"/**
* Calculates the sum of two numbers.
* @param {number} a - First number
* @param {number} b - Second number
* @returns {number} Sum of a and b
*/
function add(a, b) {
return a + b;
}"#;
let units = parse(source, Language::JavaScript, "test.js");
let func = get_unit_by_name(&units, "add").unwrap();
let text = build_embedding_text(func);
let expected = r#"Function: add
Signature: function add(a, b) {
Description: Calculates the sum of two numbers. @param {number} a - First number @param {number} b - Second number @returns {number} Sum of a and b /
Parameters: a, b
File: test test.js
Code:
/**
* Calculates the sum of two numbers.
* @param {number} a - First number
* @param {number} b - Second number
* @returns {number} Sum of a and b
*/
function add(a, b) {
return a + b;
}"#;
assert_eq!(text, expected);
}
#[test]
fn test_class_definition() {
let source = r#"class Calculator {
constructor(value) {
this.value = value;
}
add(x) {
this.value += x;
return this.value;
}
}"#;
let units = parse(source, Language::JavaScript, "test.js");
let class = get_unit_by_name(&units, "Calculator").unwrap();
let class_text = build_embedding_text(class);
let expected_class = r#"Class: Calculator
Signature: class Calculator {
File: test test.js
Code:
class Calculator {
constructor(value) {
this.value = value;
}
add(x) {
this.value += x;
return this.value;
}
}"#;
assert_eq!(class_text, expected_class);
assert!(
get_unit_by_name(&units, "add").is_some(),
"Methods are extracted as separate units alongside their parent classes"
);
assert!(
get_unit_by_name(&units, "constructor").is_some(),
"Constructors are extracted as separate units alongside their parent classes"
);
}
#[test]
fn test_async_function() {
let source = r#"async function fetchData(url) {
const response = await fetch(url);
return response.json();
}"#;
let units = parse(source, Language::JavaScript, "test.js");
let func = get_unit_by_name(&units, "fetchData").unwrap();
let text = build_embedding_text(func);
let expected = r#"Function: fetchData
Signature: async function fetchData(url) {
Parameters: url
Calls: fetch, json
Variables: const, response
File: test test.js
Code:
async function fetchData(url) {
const response = await fetch(url);
return response.json();
}"#;
assert_eq!(text, expected);
}
#[test]
fn test_function_with_default_params() {
let source = r#"function greet(name = "World", greeting = "Hello") {
return `${greeting}, ${name}!`;
}"#;
let units = parse(source, Language::JavaScript, "test.js");
let func = get_unit_by_name(&units, "greet").unwrap();
let text = build_embedding_text(func);
let expected = r#"Function: greet
Signature: function greet(name = "World", greeting = "Hello") {
File: test test.js
Code:
function greet(name = "World", greeting = "Hello") {
return `${greeting}, ${name}!`;
}"#;
assert_eq!(text, expected);
}
#[test]
fn test_function_with_rest_params() {
let source = r#"function sum(...numbers) {
return numbers.reduce((a, b) => a + b, 0);
}"#;
let units = parse(source, Language::JavaScript, "test.js");
let func = get_unit_by_name(&units, "sum").unwrap();
let text = build_embedding_text(func);
let expected = r#"Function: sum
Signature: function sum(...numbers) {
Calls: reduce
File: test test.js
Code:
function sum(...numbers) {
return numbers.reduce((a, b) => a + b, 0);
}"#;
assert_eq!(text, expected);
}
#[test]
fn test_exported_function() {
let source = r#"export function publicFunc() {
return "public";
}
export default function defaultFunc() {
return "default";
}"#;
let units = parse(source, Language::JavaScript, "test.js");
let public_func = get_unit_by_name(&units, "publicFunc").unwrap();
let public_text = build_embedding_text(public_func);
let expected_public = r#"Function: publicFunc
Signature: export function publicFunc() {
File: test test.js
Code:
export function publicFunc() {
return "public";
}"#;
assert_eq!(public_text, expected_public);
let default_func = get_unit_by_name(&units, "defaultFunc").unwrap();
let default_text = build_embedding_text(default_func);
let expected_default = r#"Function: defaultFunc
Signature: export default function defaultFunc() {
File: test test.js
Code:
export default function defaultFunc() {
return "default";
}"#;
assert_eq!(default_text, expected_default);
}
#[test]
fn test_constants() {
let source = r#"const API_URL = "https://api.example.com";
const MAX_RETRIES = 3;
function fetchData() {
return fetch(API_URL);
}"#;
let units = parse(source, Language::JavaScript, "test.js");
let api_url = get_unit_by_name(&units, "API_URL").unwrap();
let api_text = build_embedding_text(api_url);
let expected_api = r#"const API_URL = "https://api.example.com";"#;
assert_eq!(api_text, expected_api);
let max_retries = get_unit_by_name(&units, "MAX_RETRIES").unwrap();
let max_text = build_embedding_text(max_retries);
let expected_max = r#"const MAX_RETRIES = 3;"#;
assert_eq!(max_text, expected_max);
}
#[test]
fn test_method_shorthand() {
let source = r#"const obj = {
method() {
return "method";
},
async asyncMethod() {
return "async";
}
};"#;
let units = parse(source, Language::JavaScript, "test.js");
assert!(!units.is_empty(), "Should extract something from the file");
}
#[test]
fn test_generator_function() {
let source = r#"function* generateNumbers(max) {
for (let i = 0; i < max; i++) {
yield i;
}
}"#;
let units = parse(source, Language::JavaScript, "test.js");
assert!(!units.is_empty(), "Should extract generator function");
}
#[test]
fn test_class_inheritance() {
let source = r#"class Animal {
speak() {
return "...";
}
}
class Dog extends Animal {
speak() {
return "Woof!";
}
}"#;
let units = parse(source, Language::JavaScript, "test.js");
let animal = get_unit_by_name(&units, "Animal").unwrap();
let animal_text = build_embedding_text(animal);
assert!(!animal_text.contains("Extends:"));
let dog = get_unit_by_name(&units, "Dog").unwrap();
let dog_text = build_embedding_text(dog);
let expected_dog = r#"Class: Dog
Signature: class Dog extends Animal {
Extends: Animal
File: test test.js
Code:
class Dog extends Animal {
speak() {
return "Woof!";
}
}"#;
assert_eq!(dog_text, expected_dog);
}
#[test]
fn test_function_with_imports() {
let source = r#"import axios from 'axios';
import { format } from 'date-fns';
function fetchData(url) {
return axios.get(url);
}"#;
let units = parse(source, Language::JavaScript, "test.js");
let func = get_unit_by_name(&units, "fetchData").unwrap();
let text = build_embedding_text(func);
let expected = r#"Function: fetchData
Signature: function fetchData(url) {
Parameters: url
Calls: get
Uses: axios
File: test test.js
Code:
function fetchData(url) {
return axios.get(url);
}"#;
assert_eq!(text, expected);
}