diff --git a/editoast/src/views/train_schedule.rs b/editoast/src/views/train_schedule.rs index b6aa27a3ab3..e9e8d8fb3a0 100644 --- a/editoast/src/views/train_schedule.rs +++ b/editoast/src/views/train_schedule.rs @@ -796,6 +796,8 @@ async fn get_path( #[cfg(test)] mod tests { use axum::http::StatusCode; + use chrono::DateTime; + use chrono::Utc; use pretty_assertions::assert_eq; use rstest::rstest; use serde_json::json; @@ -920,8 +922,7 @@ mod tests { ) } - async fn app_infra_id_train_schedule_id_for_simulation_tests() -> (TestApp, i64, i64) { - let db_pool = DbConnectionPoolV2::for_tests(); + fn mocked_core_pathfinding_and_sim() -> MockingClient { let mut core = MockingClient::new(); core.stub("/v2/pathfinding/blocks") .method(reqwest::Method::POST) @@ -975,6 +976,19 @@ mod tests { } })) .finish(); + core.stub("/v2/signal_projection") + .method(reqwest::Method::POST) + .response(StatusCode::OK) + .json(json!({ + "signal_updates": {}, + })) + .finish(); + core + } + + async fn app_infra_id_train_schedule_id_for_simulation_tests() -> (TestApp, i64, i64) { + let db_pool = DbConnectionPoolV2::for_tests(); + let core = mocked_core_pathfinding_and_sim(); let app = TestAppBuilder::new() .db_pool(db_pool.clone()) .core_client(core.into()) @@ -1024,4 +1038,143 @@ mod tests { })); app.fetch(request).assert_status(StatusCode::OK); } + + #[derive(Deserialize)] + struct PartialProjectPathTrainResult { + departure_time: DateTime, + // Ignore the rest of the payload + } + + fn mocked_core_for_project_path(train_id: i64) -> MockingClient { + let mut core = MockingClient::new(); + core.stub("/v2/pathfinding/blocks") + .method(reqwest::Method::POST) + .response(StatusCode::OK) + .json(json!({ + "blocks":[], + "routes": [], + "track_section_ranges": [], + "path_item_positions": [0,1,2,3], + "length": 0, + "status": "success" + })) + .finish(); + core.stub("/v2/standalone_simulation") + .method(reqwest::Method::POST) + .response(StatusCode::OK) + .json(json!({ + "status": "success", + "base": { + "positions": [], + "times": [], + "speeds": [], + "energy_consumption": 0.0, + "path_item_times": [0, 1000, 2000, 3000] + }, + "provisional": { + "positions": [], + "times": [], + "speeds": [], + "energy_consumption": 0.0, + "path_item_times": [0, 1000, 2000, 3000] + }, + "final_output": { + "positions": [0], + "times": [0], + "speeds": [], + "energy_consumption": 0.0, + "path_item_times": [0, 1000, 2000, 3000], + "signal_critical_positions": [], + "zone_updates": [], + "spacing_requirements": [], + "routing_requirements": [] + }, + "mrsp": { + "boundaries": [], + "values": [] + }, + "electrical_profiles": { + "boundaries": [], + "values": [] + } + })) + .finish(); + core.stub("/v2/signal_projection") + .method(reqwest::Method::POST) + .response(StatusCode::OK) + .json(json!({ + "signal_updates": {train_id.to_string(): [] }, + })) + .finish(); + core + } + + #[rstest] + async fn train_schedule_project_path() { + // SETUP + let db_pool = DbConnectionPoolV2::for_tests(); + + let small_infra = create_small_infra(&mut db_pool.get_ok()).await; + let rolling_stock = + create_fast_rolling_stock(&mut db_pool.get_ok(), "simulation_rolling_stock").await; + let timetable = create_timetable(&mut db_pool.get_ok()).await; + let train_schedule_base: TrainScheduleBase = TrainScheduleBase { + rolling_stock_name: rolling_stock.name.clone(), + ..serde_json::from_str(include_str!("../tests/train_schedules/simple.json")) + .expect("Unable to parse") + }; + let train_schedule: Changeset = TrainScheduleForm { + timetable_id: Some(timetable.id), + train_schedule: train_schedule_base.clone(), + } + .into(); + let train_schedule_valid = train_schedule + .create(&mut db_pool.get_ok()) + .await + .expect("Failed to create train schedule"); + + let train_schedule_fail: Changeset = TrainScheduleForm { + timetable_id: Some(timetable.id), + train_schedule: TrainScheduleBase { + rolling_stock_name: "fail".to_string(), + start_time: DateTime::from_timestamp(0, 0).unwrap(), + ..train_schedule_base.clone() + }, + } + .into(); + + let train_schedule_fail = train_schedule_fail + .create(&mut db_pool.get_ok()) + .await + .expect("Failed to create train schedule"); + + let core = mocked_core_for_project_path(train_schedule_valid.id); + let app = TestAppBuilder::new() + .db_pool(db_pool.clone()) + .core_client(core.into()) + .build(); + + // TEST + let request = app.post("/train_schedule/project_path").json(&json!({ + "infra_id": small_infra.id, + "electrical_profile_set_id": null, + "ids": vec![train_schedule_fail.id, train_schedule_valid.id], + "path": { + "track_section_ranges": [ + {"track_section": "TA1", "begin": 0, "end": 100, "direction": "START_TO_STOP"} + ], + "routes": [], + "blocks": [] + } + })); + let response: HashMap = + app.fetch(request).assert_status(StatusCode::OK).json_into(); + + // EXPECT + assert_eq!(response.len(), 1); + assert_eq!( + response[&train_schedule_valid.id].departure_time, + train_schedule_base.start_time + ); + } }