feat: add generated scene skill platform hardening
This commit is contained in:
@@ -31,7 +31,8 @@ fn make_test_mode(
|
||||
description: None,
|
||||
}),
|
||||
column_defs: vec![("id".to_string(), "ID".to_string())],
|
||||
request_template: serde_json::json!({}),
|
||||
request_template: serde_json::json!({ "mode": name }),
|
||||
request_field_mappings: Vec::new(),
|
||||
normalize_rules: Some(NormalizeRulesIr {
|
||||
rules_type: "validate_required".to_string(),
|
||||
required_fields: vec!["id".to_string()],
|
||||
@@ -43,6 +44,10 @@ fn make_test_mode(
|
||||
|
||||
fn make_test_scene_ir(modes: Vec<ModeIr>) -> SceneIr {
|
||||
let is_multi = modes.len() > 1;
|
||||
let api_endpoints = modes
|
||||
.iter()
|
||||
.filter_map(|mode| mode.api_endpoint.clone())
|
||||
.collect::<Vec<_>>();
|
||||
SceneIr {
|
||||
scene_id: "test-scene".to_string(),
|
||||
scene_id_diagnostics: SceneIdDiagnosticsIr::default(),
|
||||
@@ -71,6 +76,13 @@ fn make_test_scene_ir(modes: Vec<ModeIr>) -> SceneIr {
|
||||
},
|
||||
],
|
||||
workflow_evidence: Default::default(),
|
||||
main_request: None,
|
||||
pagination_plan: None,
|
||||
enrichment_requests: Vec::new(),
|
||||
join_keys: Vec::new(),
|
||||
merge_or_dedupe_rules: Vec::new(),
|
||||
export_plan: None,
|
||||
merge_plan: None,
|
||||
request_template: serde_json::Value::Null,
|
||||
response_path: "".to_string(),
|
||||
normalize_rules: None,
|
||||
@@ -78,7 +90,8 @@ fn make_test_scene_ir(modes: Vec<ModeIr>) -> SceneIr {
|
||||
validation_hints: Default::default(),
|
||||
evidence: Vec::new(),
|
||||
readiness: Default::default(),
|
||||
api_endpoints: Vec::new(),
|
||||
api_endpoints,
|
||||
runtime_dependencies: Vec::new(),
|
||||
static_params: Default::default(),
|
||||
column_defs: Vec::new(),
|
||||
confidence: 0.0,
|
||||
@@ -96,9 +109,9 @@ fn temp_workspace(prefix: &str) -> PathBuf {
|
||||
path
|
||||
}
|
||||
|
||||
/// Test 1: Single mode generates MODES array (routes through compile_multi_mode_request)
|
||||
/// Test 1: Single request table uses dedicated simple-request path instead of MODES fallback.
|
||||
#[test]
|
||||
fn test_single_mode_generates_modes_array() {
|
||||
fn test_single_request_table_uses_dedicated_path() {
|
||||
let output_root = temp_workspace("sgclaw-single-mode-test");
|
||||
let modes = vec![make_test_mode(
|
||||
"month",
|
||||
@@ -108,10 +121,9 @@ fn test_single_mode_generates_modes_array() {
|
||||
)];
|
||||
let scene_ir = make_test_scene_ir(modes);
|
||||
|
||||
// Use SingleRequestTable archetype - the compile path should auto-wrap into multi-mode
|
||||
// Use SingleRequestTable archetype - the compile path should stay on the dedicated single-request route.
|
||||
let mut scene_ir = scene_ir;
|
||||
scene_ir.workflow_archetype = Some(WorkflowArchetype::SingleRequestTable);
|
||||
// Provide one api_endpoint so ensure_modes_populated works
|
||||
scene_ir.api_endpoints = vec![ApiEndpointIr {
|
||||
name: "default_endpoint".to_string(),
|
||||
url: "http://example.com/api/data".to_string(),
|
||||
@@ -138,8 +150,12 @@ fn test_single_mode_generates_modes_array() {
|
||||
fs::read_to_string(skill_root.join("scripts/collect_single_mode_scene.js")).unwrap();
|
||||
|
||||
assert!(
|
||||
generated_script.contains("const MODES ="),
|
||||
"Generated JS should contain 'const MODES =' since SingleRequestTable routes through compile_multi_mode_request"
|
||||
generated_script.contains("const REQUEST_TEMPLATE ="),
|
||||
"Generated JS should contain REQUEST_TEMPLATE on the dedicated single-request path"
|
||||
);
|
||||
assert!(
|
||||
!generated_script.contains("const MODES ="),
|
||||
"Generated JS should no longer route SingleRequestTable through MODES fallback"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -148,18 +164,8 @@ fn test_single_mode_generates_modes_array() {
|
||||
fn test_multi_mode_generates_mode_routing() {
|
||||
let output_root = temp_workspace("sgclaw-multi-mode-test");
|
||||
let modes = vec![
|
||||
make_test_mode(
|
||||
"month",
|
||||
"http://example.com/api/month",
|
||||
None,
|
||||
"data",
|
||||
),
|
||||
make_test_mode(
|
||||
"week",
|
||||
"http://example.com/api/week",
|
||||
None,
|
||||
"data",
|
||||
),
|
||||
make_test_mode("month", "http://example.com/api/month", None, "data"),
|
||||
make_test_mode("week", "http://example.com/api/week", None, "data"),
|
||||
];
|
||||
let scene_ir = make_test_scene_ir(modes);
|
||||
|
||||
@@ -200,7 +206,8 @@ fn test_form_urlencoded_request_body() {
|
||||
Some("application/x-www-form-urlencoded"),
|
||||
"data",
|
||||
)];
|
||||
let scene_ir = make_test_scene_ir(modes);
|
||||
let mut scene_ir = make_test_scene_ir(modes);
|
||||
scene_ir.workflow_archetype = Some(WorkflowArchetype::MultiModeRequest);
|
||||
|
||||
generate_scene_package(GenerateSceneRequest {
|
||||
source_dir: PathBuf::from("tests/fixtures/generated_scene/report_collection"),
|
||||
@@ -245,7 +252,8 @@ fn test_response_path_extraction_in_template() {
|
||||
None,
|
||||
"data.list",
|
||||
)];
|
||||
let scene_ir = make_test_scene_ir(modes);
|
||||
let mut scene_ir = make_test_scene_ir(modes);
|
||||
scene_ir.workflow_archetype = Some(WorkflowArchetype::MultiModeRequest);
|
||||
|
||||
generate_scene_package(GenerateSceneRequest {
|
||||
source_dir: PathBuf::from("tests/fixtures/generated_scene/report_collection"),
|
||||
@@ -312,7 +320,9 @@ fn test_process_data_flag_in_ajax() {
|
||||
);
|
||||
// processData should be false for form-urlencoded (negated condition)
|
||||
assert!(
|
||||
generated_script.contains("processData: request.headers['Content-Type'] !== 'application/x-www-form-urlencoded'"),
|
||||
generated_script.contains(
|
||||
"processData: request.headers['Content-Type'] !== 'application/x-www-form-urlencoded'"
|
||||
),
|
||||
"Generated JS should set processData to false for form-urlencoded content type"
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user