use std::env;
use torrust_index::config::ApiToken;
use torrust_index::web::api::Version;
use url::Url;
use super::config::{initialize_configuration, ENV_VAR_DB_CONNECT_URL, ENV_VAR_INDEX_SHARED};
use crate::common::contexts::settings::Settings;
use crate::environments::{isolated, shared};
enum State {
Stopped,
RunningShared,
RunningIsolated,
}
#[derive(Default)]
pub struct TestEnv {
starting_settings: Option<Settings>,
shared: Option<shared::TestEnv>,
isolated: Option<isolated::TestEnv>,
}
impl TestEnv {
pub fn new() -> Self {
Self::default()
}
pub fn is_shared(&self) -> bool {
self.shared.is_some()
}
pub fn is_isolated(&self) -> bool {
self.isolated.is_some()
}
pub async fn start(&mut self, api_version: Version) {
let e2e_shared = ENV_VAR_INDEX_SHARED;
if let Ok(_e2e_test_env_is_shared) = env::var(e2e_shared) {
let shared_env = shared::TestEnv::running().await;
self.shared = Some(shared_env);
self.starting_settings = self.server_settings_for_shared_env().await;
} else {
let isolated_env = isolated::TestEnv::running(api_version).await;
self.isolated = Some(isolated_env);
self.starting_settings = self.server_settings_for_isolated_env();
}
}
pub fn provides_a_tracker(&self) -> bool {
self.is_shared() && self.server_settings().is_some()
}
pub fn provides_a_private_tracker(&self) -> bool {
if !self.is_shared() {
return false;
};
match self.server_settings() {
Some(settings) => settings.tracker.private,
None => false,
}
}
pub fn server_settings(&self) -> Option<Settings> {
self.starting_settings.clone()
}
pub fn server_settings_masking_secrets(&self) -> Option<Settings> {
match self.starting_settings.clone() {
Some(mut settings) => {
let mut connect_url = Url::parse(&settings.database.connect_url).expect("valid database connect URL");
if let Some(_password) = connect_url.password() {
let _ = connect_url.set_password(Some("***"));
settings.database.connect_url = connect_url.to_string();
}
settings.tracker.token = ApiToken::new("***");
"***".clone_into(&mut settings.mail.smtp.credentials.password);
"***".clone_into(&mut settings.auth.user_claim_token_pepper);
Some(settings)
}
None => None,
}
}
pub fn server_socket_addr(&self) -> Option<String> {
match self.state() {
State::RunningShared => self.shared.as_ref().unwrap().server_socket_addr(),
State::RunningIsolated => self.isolated.as_ref().unwrap().server_socket_addr(),
State::Stopped => None,
}
}
pub fn database_connect_url(&self) -> Option<String> {
let internal_connect_url = self
.starting_settings
.as_ref()
.map(|settings| settings.database.connect_url.clone());
match self.state() {
State::RunningShared => {
let connect_url_env_var = ENV_VAR_DB_CONNECT_URL;
if let Ok(connect_url) = env::var(connect_url_env_var) {
Some(connect_url)
} else {
None
}
}
State::RunningIsolated => internal_connect_url,
State::Stopped => None,
}
}
fn state(&self) -> State {
if self.is_shared() {
return State::RunningShared;
}
if self.is_isolated() {
return State::RunningIsolated;
}
State::Stopped
}
fn server_settings_for_isolated_env(&self) -> Option<Settings> {
self.isolated
.as_ref()
.map(|env| Settings::from(env.app_starter.server_configuration()))
}
async fn server_settings_for_shared_env(&self) -> Option<Settings> {
let configuration = initialize_configuration();
let settings = configuration.settings.read().await;
Some(Settings::from(settings.clone()))
}
}