Files
tuono/crates/tuono_lib/tests/utils/mock_server.rs
T
2025-03-29 11:15:45 +01:00

116 lines
3.7 KiB
Rust

use fs_extra::dir::create_all;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;
use std::{env, fs};
use tempfile::{TempDir, tempdir};
use tuono_lib::axum::routing::{get, post};
use tuono_lib::{Mode, Server, axum::Router, tuono_internal_init_v8_platform};
use crate::utils::catch_all::get_tuono_internal_api as catch_all;
use crate::utils::dynamic_parameter::get_tuono_internal_api as dynamic_parameter;
use crate::utils::env::get_tuono_internal_api as test_env;
use crate::utils::health_check::get_tuono_internal_api as health_check;
use crate::utils::post_api::post_tuono_internal_api as post_api;
use crate::utils::route as html_route;
use crate::utils::route::tuono_internal_api as route_api;
use std::sync::Once;
static INIT: Once = Once::new();
fn init_v8() {
INIT.call_once(|| {
tuono_internal_init_v8_platform();
})
}
fn add_file_with_content<'a>(path: &'a str, content: &'a str) {
let path = PathBuf::from(path);
create_all(
path.parent().expect("File path does not have any parent"),
false,
)
.unwrap_or_else(|_| {
panic!(
"Failed to create parent file directories: {}",
path.display()
)
});
let mut file = File::create(path).expect("Failed to create the file");
file.write_all(content.as_bytes())
.expect("Failed to write into the file");
}
#[derive(Debug)]
pub struct MockTuonoServer {
pub address: String,
pub port: u16,
original_dir: PathBuf,
#[allow(dead_code)]
// Required for dropping the temp_dir when this struct drops
temp_dir: TempDir,
}
impl MockTuonoServer {
pub async fn spawn() -> Self {
init_v8();
let original_dir = env::current_dir().expect("Failed to read current_dir");
let temp_dir = tempdir().expect("Failed to create temp_dir");
let react_prod_build = fs::read_to_string("./tests/assets/fake_react_build.js")
.expect("Failed to read fake_react_build.js");
env::set_current_dir(temp_dir.path()).expect("Failed to change current dir into temp_dir");
add_file_with_content(
"./.tuono/config/config.json",
r#"{"server": {"host": "127.0.0.1", "port": 0}}"#,
);
add_file_with_content("./out/server/prod-server.js", react_prod_build.as_str());
add_file_with_content(
"./out/client/.vite/manifest.json",
r#"{"client-main.tsx": { "file": "assets/index.js", "name": "index", "src": "index.tsx", "isEntry": true,"dynamicImports": [],"css": []}}"#,
);
add_file_with_content("./.env", r#"MY_TEST_KEY="foobar""#);
let router = Router::new()
.route("/", get(html_route::tuono_internal_route))
.route("/tuono/data", get(html_route::tuono_internal_api))
.route("/health_check", get(health_check))
.route("/route-api", get(route_api))
.route("/catch_all/{*catch_all}", get(catch_all))
.route("/dynamic/{parameter}", get(dynamic_parameter))
.route("/api/post", post(post_api))
.route("/env", get(test_env));
let server = Server::init(router, Mode::Prod).await;
let socket = server
.listener
.local_addr()
.expect("Failed to extract test server socket");
_ = tokio::spawn(server.start());
MockTuonoServer {
address: socket.ip().to_string(),
port: socket.port(),
original_dir,
temp_dir,
}
}
}
impl Drop for MockTuonoServer {
fn drop(&mut self) {
// Set back the current dir in the previous state
env::set_current_dir(&self.original_dir)
.expect("Failed to restore the original directory.");
}
}