use super::*;
fn minimal_fixture(id: &str, assertions: Vec<crate::e2e::fixture::Assertion>) -> crate::e2e::fixture::Fixture {
crate::e2e::fixture::Fixture {
docs: None,
requirements: Vec::new(),
id: id.to_string(),
description: "Mock capture smoke test".to_string(),
input: serde_json::Value::Null,
http: None,
asyncapi: None,
websocket: None,
preserve_input_urls: false,
assertions,
call: None,
skip: None,
env: None,
setup: Vec::new(),
visitor: None,
args: vec![],
assertion_recipes: vec![],
mock_response: None,
source: String::new(),
category: None,
tags: Vec::new(),
}
}
fn mock_assertion(field: &str, assertion_type: &str, value: serde_json::Value) -> crate::e2e::fixture::Assertion {
crate::e2e::fixture::Assertion {
assertion_type: assertion_type.to_string(),
field: Some(field.to_string()),
value: Some(value),
..Default::default()
}
}
fn render(fixture: &crate::e2e::fixture::Fixture, e2e_config: &crate::e2e::config::E2eConfig) -> String {
let fixtures: Vec<&crate::e2e::fixture::Fixture> = vec![fixture];
let config = crate::core::config::ResolvedCrateConfig::default();
render_test_file(
"mock_capture",
&fixtures,
e2e_config,
&config,
&[],
&[],
&[],
&[],
false,
)
}
#[test]
fn a_sync_mock_assertion_gets_both_its_call_and_the_helper_definition() {
let fixture = minimal_fixture(
"mock_capture_sync",
vec![
mock_assertion("mock.requests.total", "equals", serde_json::json!(1)),
mock_assertion(
r#"mock.requests["POST /v1/chat"]"#,
"greater_than_or_equal",
serde_json::json!(1),
),
],
);
let out = render(&fixture, &crate::e2e::config::E2eConfig::default());
assert!(
out.contains(
" assert _alef_mock_request_count(os.environ[\"MOCK_SERVER_URL\"], \"/__alef/requests/total?prefix=\") == 1, \"expected mock.requests.total == 1\""
),
"expected the sync total-count call, got:\n{out}"
);
assert!(
out.contains(
" assert _alef_mock_request_count(os.environ[\"MOCK_SERVER_URL\"], \"/__alef/requests/one?key=POST%20%2Fv1%2Fchat\") >= 1, \"expected mock.requests[\\\"POST /v1/chat\\\"] >= 1\""
),
"expected the sync bracketed-key call, got:\n{out}"
);
assert!(
out.contains("def _alef_mock_request_count(base_url: str, path_and_query: str) -> int:"),
"expected the helper definition in the same file as the call, got:\n{out}"
);
assert!(
out.contains("\nimport os\n"),
"expected `import os` alongside the os.environ call, got:\n{out}"
);
}
#[test]
fn an_async_mock_assertion_gets_the_to_thread_call_and_the_asyncio_import_together() {
let mut e2e_config = crate::e2e::config::E2eConfig::default();
e2e_config.call.r#async = true;
let fixture = minimal_fixture(
"mock_capture_async",
vec![mock_assertion("mock.requests.total", "count_min", serde_json::json!(1))],
);
let out = render(&fixture, &e2e_config);
assert!(
out.contains(
" assert await asyncio.to_thread(_alef_mock_request_count, os.environ[\"MOCK_SERVER_URL\"], \"/__alef/requests/total?prefix=\") >= 1, \"expected mock.requests.total >= 1\""
),
"expected the asyncio.to_thread call, got:\n{out}"
);
assert!(
out.contains("import asyncio"),
"expected the `import asyncio` line alongside the to_thread call, got:\n{out}"
);
assert!(
out.contains("def _alef_mock_request_count(base_url: str, path_and_query: str) -> int:"),
"expected the helper definition too, got:\n{out}"
);
}
#[test]
fn a_file_with_no_mock_assertion_defines_no_helper() {
let fixture = minimal_fixture(
"mock_capture_absent",
vec![crate::e2e::fixture::Assertion {
assertion_type: "not_error".to_string(),
..Default::default()
}],
);
let out = render(&fixture, &crate::e2e::config::E2eConfig::default());
assert!(
!out.contains("_alef_mock_request_count"),
"a file with no mock.* assertion must not reference or define the helper, got:\n{out}"
);
}