amberjs 1.17.0

JavaScript/TypeScript runtime built with Rust and V8
Documentation
// V8 Bindings for Testing Framework
/// Registers test() / describe() / expect() functions in V8 context
use rusty_v8 as v8;
use crate::testing::{register_suite, get_all_suites};
use crate::testing::test_context::{TestSuite, TestCase};
use std::collections::{HashMap, BTreeMap};
use std::time::Duration;
/// Register all testing functions in the V8 global scope
pub fn register_testing_api(scope: &mut v8::PinScope, global: v8::Local<v8::Object>) {
    // Register test() function
    let test_func: _ = v8::FunctionTemplate::new(scope, test_callback);
    let test_key: _ = v8::String::new(scope, "test").unwrap();
    global.set(scope, test_key.into(), test_func.get_function(scope).unwrap().into());
    // Register describe() function
    let describe_func: _ = v8::FunctionTemplate::new(scope, describe_callback);
    let describe_key: _ = v8::String::new(scope, "describe").unwrap();
    global.set(scope, describe_key.into(), describe_func.get_function(scope).unwrap().into());
    // Register it() function (alias for test)
    let it_func: _ = v8::FunctionTemplate::new(scope, it_callback);
    let it_key: _ = v8::String::new(scope, "it").unwrap();
    global.set(scope, it_key.into(), it_func.get_function(scope).unwrap().into());
    // Register expect() function
    let expect_func: _ = v8::FunctionTemplate::new(scope, expect_callback);
    let expect_key: _ = v8::String::new(scope, "expect").unwrap();
    global.set(scope, expect_key.into(), expect_func.get_function(scope).unwrap().into());
    // Register lifecycle hooks
    let before_each_func: _ = v8::FunctionTemplate::new(scope, before_each_callback);
    let before_each_key: _ = v8::String::new(scope, "beforeEach").unwrap();
    global.set(scope, before_each_key.into(), before_each_func.get_function(scope).unwrap().into());
    let after_each_func: _ = v8::FunctionTemplate::new(scope, after_each_callback);
    let after_each_key: _ = v8::String::new(scope, "afterEach").unwrap();
    global.set(scope, after_each_key.into(), after_each_func.get_function(scope).unwrap().into());
    let before_all_func: _ = v8::FunctionTemplate::new(scope, before_all_callback);
    let before_all_key: _ = v8::String::new(scope, "beforeAll").unwrap();
    global.set(scope, before_all_key.into(), before_all_func.get_function(scope).unwrap().into());
    let after_all_func: _ = v8::FunctionTemplate::new(scope, after_all_callback);
    let after_all_key: _ = v8::String::new(scope, "afterAll").unwrap();
    global.set(scope, after_all_key.into(), after_all_func.get_function(scope).unwrap().into());
    // Register skip/only modifiers
    let skip_func: _ = v8::FunctionTemplate::new(scope, skip_callback);
    let skip_key: _ = v8::String::new(scope, "skip").unwrap();
    global.set(scope, skip_key.into(), skip_func.get_function(scope).unwrap().into());
    let only_func: _ = v8::FunctionTemplate::new(scope, only_callback);
    let only_key: _ = v8::String::new(scope, "only").unwrap();
    global.set(scope, only_key.into(), only_func.get_function(scope).unwrap().into());
    if cfg!(feature = "verbose_logging") {
        eprintln!("✅ Registered testing API in V8 context");
    }
}
/// test() callback - registers a test case
fn test_callback(
    scope: &mut v8::PinScope,
    args: v8::FunctionCallbackArguments,
    mut retval: v8::ReturnValue,
) {
    let name: _ = args.get(0).to_rust_string_lossy(scope);
    let function: _ = args.get(1);
    if !function.is_function() {
        let error: _ = v8::String::new(scope, "test() requires a function as second argument").unwrap();
        let exception: _ = v8::Exception::error(scope, error);
        scope.throw_exception(exception);
        return;
    }
    let func: _ = v8::Local::<v8::Function>::try_from(args.get(1)).unwrap();
    // Store function in the test registry
    let _test_case: _ = TestCase::new(name.clone(), v8::Global::new(scope, func), Duration::from_secs(5));
    // For now, we'll use a default suite name
    // In a real implementation, we'd track the current describe context
    let _suite_name: _ = "default".to_string();
    // Register the test case (this is a simplified approach)
    // In practice, we'd need a more sophisticated registry system
    if cfg!(feature = "verbose_logging") {
        eprintln!("📝 Registered test: {}", name);
    }
    // Return undefined
    retval.set(v8::undefined(scope).into());
}
/// describe() callback - creates a test suite
fn describe_callback(
    scope: &mut v8::PinScope,
    args: v8::FunctionCallbackArguments,
    mut retval: v8::ReturnValue,
) {
    let name: _ = args.get(0).to_rust_string_lossy(scope);
    let function: _ = args.get(1);
    if !function.is_function() {
        let error: _ = v8::String::new(scope, "describe() requires a function as second argument").unwrap();
        let exception: _ = v8::Exception::error(scope, error);
        scope.throw_exception(exception);
        return;
    }
    let func: _ = v8::Local::<v8::Function>::try_from(args.get(1)).unwrap();
    // Create a new suite
    let mut suite = TestSuite::new(name.clone(), None);
    // Execute the describe block to register nested tests
    let _: _ = func.call(scope, v8::undefined(scope).into(), &[]);
    // Register the suite
    register_suite(suite);
    if cfg!(feature = "verbose_logging") {
        eprintln!("📂 Registered suite: {}", name);
    }
    retval.set(v8::undefined(scope).into());
}
/// it() callback - alias for test()
fn it_callback(
    scope: &mut v8::PinScope,
    args: v8::FunctionCallbackArguments,
    mut retval: v8::ReturnValue,
) {
    test_callback(scope, args, retval);
}
/// expect() callback - creates an expectation
fn expect_callback(
    scope: &mut v8::PinScope,
    args: v8::FunctionCallbackArguments,
    mut retval: v8::ReturnValue,
) {
    let value: _ = args.get(0);
    // Create an expectation object
    let expect_obj: _ = v8::Object::new(scope);
    // Add toBe matcher
    let to_be_func: _ = v8::FunctionTemplate::new(scope, to_be_matcher);
    expect_obj.set(scope, "toBe".into(), to_be_func.get_function(scope).unwrap().into());
    // Add toEqual matcher
    let to_equal_func: _ = v8::FunctionTemplate::new(scope, to_equal_matcher);
    expect_obj.set(scope, "toEqual".into(), to_equal_func.get_function(scope).unwrap().into());
    // Add toBeTruthy matcher
    let to_be_truthy_func: _ = v8::FunctionTemplate::new(scope, to_be_truthy_matcher);
    expect_obj.set(scope, "toBeTruthy".into(), to_be_truthy_func.get_function(scope).unwrap().into());
    // Add toBeFalsy matcher
    let to_be_falsy_func: _ = v8::FunctionTemplate::new(scope, to_be_falsy_matcher);
    expect_obj.set(scope, "toBeFalsy".into(), to_be_falsy_func.get_function(scope).unwrap().into());
    // Add toContain matcher
    let to_contain_func: _ = v8::FunctionTemplate::new(scope, to_contain_matcher);
    expect_obj.set(scope, "toContain".into(), to_contain_func.get_function(scope).unwrap().into());
    retval.set(expect_obj.into());
}
/// beforeEach() callback
fn before_each_callback(
    scope: &mut v8::PinScope,
    args: v8::FunctionCallbackArguments,
    mut retval: v8::ReturnValue,
) {
    // Store beforeEach hook for the current suite
    if cfg!(feature = "verbose_logging") {
        eprintln!("🔧 Registered beforeEach hook");
    }
    retval.set(v8::undefined(scope).into());
}
/// afterEach() callback
fn after_each_callback(
    scope: &mut v8::PinScope,
    args: v8::FunctionCallbackArguments,
    mut retval: v8::ReturnValue,
) {
    // Store afterEach hook for the current suite
    if cfg!(feature = "verbose_logging") {
        eprintln!("🔧 Registered afterEach hook");
    }
    retval.set(v8::undefined(scope).into());
}
/// beforeAll() callback
fn before_all_callback(
    scope: &mut v8::PinScope,
    args: v8::FunctionCallbackArguments,
    mut retval: v8::ReturnValue,
) {
    // Store beforeAll hook for the current suite
    if cfg!(feature = "verbose_logging") {
        eprintln!("🔧 Registered beforeAll hook");
    }
    retval.set(v8::undefined(scope).into());
}
/// afterAll() callback
fn after_all_callback(
    scope: &mut v8::PinScope,
    args: v8::FunctionCallbackArguments,
    mut retval: v8::ReturnValue,
) {
    // Store afterAll hook for the current suite
    if cfg!(feature = "verbose_logging") {
        eprintln!("🔧 Registered afterAll hook");
    }
    retval.set(v8::undefined(scope).into());
}
/// skip() modifier
fn skip_callback(
    scope: &mut v8::PinScope,
    args: v8::FunctionCallbackArguments,
    mut retval: v8::ReturnValue,
) {
    // Mark test or suite as skipped
    if cfg!(feature = "verbose_logging") {
        eprintln!("⏭️  Marked as skipped");
    }
    retval.set(v8::undefined(scope).into());
}
/// only() modifier
fn only_callback(
    scope: &mut v8::PinScope,
    args: v8::FunctionCallbackArguments,
    mut retval: v8::ReturnValue,
) {
    // Mark test or suite as only
    if cfg!(feature = "verbose_logging") {
        eprintln!("🎯 Marked as only");
    }
    retval.set(v8::undefined(scope).into());
}
/// toBe matcher implementation
fn to_be_matcher(
    scope: &mut v8::PinScope,
    args: v8::FunctionCallbackArguments,
    mut retval: v8::ReturnValue,
) {
    let expected: _ = args.get(0);
    // Get the 'this' value (the expect object)
    let this: _ = args.this();
    // In a real implementation, we'd compare the values
    // For now, just return a simple result object
    let result_obj: _ = v8::Object::new(scope);
    result_obj.set(scope, "pass".into(), v8::Boolean::new(scope, true).into());
    retval.set(result_obj.into());
}
/// toEqual matcher implementation
fn to_equal_matcher(
    scope: &mut v8::PinScope,
    args: v8::FunctionCallbackArguments,
    mut retval: v8::ReturnValue,
) {
    let expected: _ = args.get(0);
    let result_obj: _ = v8::Object::new(scope);
    result_obj.set(scope, "pass".into(), v8::Boolean::new(scope, true).into());
    retval.set(result_obj.into());
}
/// toBeTruthy matcher implementation
fn to_be_truthy_matcher(
    scope: &mut v8::PinScope,
    args: v8::FunctionCallbackArguments,
    mut retval: v8::ReturnValue,
) {
    let result_obj: _ = v8::Object::new(scope);
    result_obj.set(scope, "pass".into(), v8::Boolean::new(scope, true).into());
    retval.set(result_obj.into());
}
/// toBeFalsy matcher implementation
fn to_be_falsy_matcher(
    scope: &mut v8::PinScope,
    args: v8::FunctionCallbackArguments,
    mut retval: v8::ReturnValue,
) {
    let result_obj: _ = v8::Object::new(scope);
    result_obj.set(scope, "pass".into(), v8::Boolean::new(scope, true).into());
    retval.set(result_obj.into());
}
/// toContain matcher implementation
fn to_contain_matcher(
    scope: &mut v8::PinScope,
    args: v8::FunctionCallbackArguments,
    mut retval: v8::ReturnValue,
) {
    let expected: _ = args.get(0);
    let result_obj: _ = v8::Object::new(scope);
    result_obj.set(scope, "pass".into(), v8::Boolean::new(scope, true).into());
    retval.set(result_obj.into());
}