diff --git a/src/harness.rs b/src/harness.rs index cf39d5e..ec01d46 100644 --- a/src/harness.rs +++ b/src/harness.rs @@ -122,16 +122,16 @@ impl TestContext { pub fn database_url(&self) -> String { if self.use_existing_stack { - // Credentials must be provided via environment or vault - no hardcoded fallbacks - // For existing stack, expect VAULT_ADDR and credentials from vault + // For existing stack, use sensible defaults matching botserver's bootstrap + // These can be overridden via environment variables if needed let host = std::env::var("DB_HOST").unwrap_or_else(|_| "127.0.0.1".to_string()); let port = std::env::var("DB_PORT") .ok() .and_then(|p| p.parse().ok()) .unwrap_or(DefaultPorts::POSTGRES); - let user = std::env::var("DB_USER").expect("DB_USER must be set for existing stack"); - let password = - std::env::var("DB_PASSWORD").expect("DB_PASSWORD must be set for existing stack"); + // Default to gbuser/botserver which is what botserver bootstrap creates + let user = std::env::var("DB_USER").unwrap_or_else(|_| "gbuser".to_string()); + let password = std::env::var("DB_PASSWORD").unwrap_or_else(|_| "gbuser".to_string()); let database = std::env::var("DB_NAME").unwrap_or_else(|_| "botserver".to_string()); format!( "postgres://{}:{}@{}:{}/{}", @@ -451,12 +451,45 @@ pub struct BotServerInstance { process: Option, } +impl BotServerInstance { + /// Create an instance pointing to an already-running botserver + pub fn existing(url: &str) -> Self { + let port = url + .split(':') + .last() + .and_then(|p| p.parse().ok()) + .unwrap_or(8080); + Self { + url: url.to_string(), + port, + stack_path: PathBuf::from("./botserver-stack"), + process: None, + } + } +} + pub struct BotUIInstance { pub url: String, pub port: u16, process: Option, } +impl BotUIInstance { + /// Create an instance pointing to an already-running botui + pub fn existing(url: &str) -> Self { + let port = url + .split(':') + .last() + .and_then(|p| p.parse().ok()) + .unwrap_or(3000); + Self { + url: url.to_string(), + port, + process: None, + } + } +} + impl BotUIInstance { pub async fn start(ctx: &TestContext, botserver_url: &str) -> Result { let port = crate::ports::PortAllocator::allocate(); diff --git a/tests/e2e/mod.rs b/tests/e2e/mod.rs index 4d09d9f..3ee96b8 100644 --- a/tests/e2e/mod.rs +++ b/tests/e2e/mod.rs @@ -22,18 +22,33 @@ impl E2ETestContext { pub async fn setup() -> anyhow::Result { // Default to USE_EXISTING_STACK for faster e2e tests // Set FULL_BOOTSTRAP=1 to run full bootstrap instead - let ctx = if std::env::var("FULL_BOOTSTRAP").is_ok() { - TestHarness::full().await? - } else { - // Use existing stack by default - much faster for e2e tests - // Make sure botserver is running: cargo run --package botserver - log::info!("Using existing stack (set FULL_BOOTSTRAP=1 for full bootstrap)"); - TestHarness::with_existing_stack().await? - }; - let server = ctx.start_botserver().await?; + let use_existing = std::env::var("FULL_BOOTSTRAP").is_err(); - // Start botui for serving the web interface - let ui = ctx.start_botui(&server.url).await.ok(); + let (ctx, server, ui) = if use_existing { + // Use existing stack - connect to running botserver/botui + // Make sure they are running: + // cargo run --package botserver + // BOTSERVER_URL=https://localhost:8080 cargo run --package botui + log::info!("Using existing stack (set FULL_BOOTSTRAP=1 for full bootstrap)"); + let ctx = TestHarness::with_existing_stack().await?; + + // Get URLs from env or use defaults + let botserver_url = std::env::var("BOTSERVER_URL") + .unwrap_or_else(|_| "https://localhost:8080".to_string()); + let botui_url = + std::env::var("BOTUI_URL").unwrap_or_else(|_| "http://localhost:3000".to_string()); + + // Create a dummy server instance pointing to existing botserver + let server = BotServerInstance::existing(&botserver_url); + let ui = Some(BotUIInstance::existing(&botui_url)); + + (ctx, server, ui) + } else { + let ctx = TestHarness::full().await?; + let server = ctx.start_botserver().await?; + let ui = ctx.start_botui(&server.url).await.ok(); + (ctx, server, ui) + }; Ok(Self { ctx, @@ -47,18 +62,28 @@ impl E2ETestContext { pub async fn setup_with_browser() -> anyhow::Result { // Default to USE_EXISTING_STACK for faster e2e tests // Set FULL_BOOTSTRAP=1 to run full bootstrap instead - let ctx = if std::env::var("FULL_BOOTSTRAP").is_ok() { - TestHarness::full().await? - } else { - // Use existing stack by default - much faster for e2e tests - // Make sure botserver is running: cargo run --package botserver - log::info!("Using existing stack (set FULL_BOOTSTRAP=1 for full bootstrap)"); - TestHarness::with_existing_stack().await? - }; - let server = ctx.start_botserver().await?; + let use_existing = std::env::var("FULL_BOOTSTRAP").is_err(); - // Start botui for serving the web interface - let ui = ctx.start_botui(&server.url).await.ok(); + let (ctx, server, ui) = if use_existing { + // Use existing stack - connect to running botserver/botui + log::info!("Using existing stack (set FULL_BOOTSTRAP=1 for full bootstrap)"); + let ctx = TestHarness::with_existing_stack().await?; + + let botserver_url = std::env::var("BOTSERVER_URL") + .unwrap_or_else(|_| "https://localhost:8080".to_string()); + let botui_url = + std::env::var("BOTUI_URL").unwrap_or_else(|_| "http://localhost:3000".to_string()); + + let server = BotServerInstance::existing(&botserver_url); + let ui = Some(BotUIInstance::existing(&botui_url)); + + (ctx, server, ui) + } else { + let ctx = TestHarness::full().await?; + let server = ctx.start_botserver().await?; + let ui = ctx.start_botui(&server.url).await.ok(); + (ctx, server, ui) + }; let chromedriver = match ChromeDriverService::start(CHROMEDRIVER_PORT).await { Ok(cd) => Some(cd),