use super::dsl::agent::Agent;
use super::dsl::assertion::expect_global;
use super::dsl::audio::{audio_file, audio_silence, audio_tone, verify_audio_connection_async};
use super::dsl::core::{
HostState, default_timeout_global, env_global, load_env_global, log_global, until_async,
uuid_global, wait_async,
};
use super::dsl::http::http_async;
use super::dsl::mock::{MockServer, json_response_global, regex_global, text_response_global};
use super::dsl::scenario::{register_scenario, setup_global, skip_global, teardown_global};
use super::host::{EnvVars, Registry};
use crate::engine::ctx::Ctx as EngineCtx;
use rquickjs::function::{Async, Opt};
use rquickjs::{Class, Ctx, Function, Object, Value};
use std::collections::HashMap;
use std::path::Path;
use std::sync::Arc;
pub fn install(
ctx: &Ctx<'_>,
engine: &Arc<EngineCtx>,
registry: &Arc<Registry>,
env: &EnvVars,
overrides: &HashMap<String, String>,
base_dir: &Path,
) -> rquickjs::Result<()> {
let g = ctx.globals();
let _ = ctx.store_userdata(HostState {
eng: engine.clone(),
reg: registry.clone(),
env: env.clone(),
base: base_dir.to_path_buf(),
});
macro_rules! set {
($name:literal, $f:expr) => {
g.set($name, Function::new(ctx.clone(), $f)?)?
};
}
for (key, value) in overrides {
g.set(key.as_str(), value.as_str())?;
}
set!("scenario", |name: String,
a: Value<'_>,
b: Opt<Function<'_>>|
-> rquickjs::Result<()> {
register_scenario(name, a, b)
});
ctx.eval::<(), _>(super::dsl::scenario::EACH_SHIM)?;
set!("skip", skip_global);
set!("setup", setup_global);
set!("teardown", teardown_global);
set!("tone", audio_tone);
set!("file", audio_file);
set!("silence", audio_silence);
set!("http", Async(http_async));
set!(
"verifyAudioConnection",
Async(verify_audio_connection_async)
);
set!("regex", regex_global);
set!("jsonResponse", json_response_global);
set!("textResponse", text_response_global);
Class::<MockServer>::define(&g)?;
Class::<Agent>::define(&g)?;
set!("expect", expect_global);
set!("until", Async(until_async));
set!("log", log_global);
set!("env", env_global);
set!("loadEnv", load_env_global);
set!("defaultTimeout", default_timeout_global);
set!("wait", Async(wait_async));
set!("uuid", uuid_global);
g.set("State", super::dsl::agent::State::object(ctx)?)?;
Ok(())
}
pub(super) fn reject_unknown_keys(
label: &str,
config: &Object<'_>,
allowed: &[&str],
) -> Result<(), String> {
for key in config.keys::<String>().flatten() {
if !allowed.contains(&key.as_str()) {
return Err(format!("{label}: unknown config key `{key}`"));
}
}
Ok(())
}