2026-02-08 20:18:46 +00:00
|
|
|
//! Feature installation integration tests
|
|
|
|
|
|
|
|
|
|
use anyhow::Result;
|
|
|
|
|
use std::fs;
|
|
|
|
|
use tempfile::TempDir;
|
|
|
|
|
|
|
|
|
|
use crate::helpers::{TestFeatureBuilder, assert_file_contains, create_mock_registry};
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_feature_installation_workflow() -> Result<()> {
|
|
|
|
|
// Create temporary project
|
|
|
|
|
let temp_project = crate::create_test_project()?;
|
|
|
|
|
let project_root = temp_project.path();
|
2026-02-08 20:37:49 +00:00
|
|
|
|
2026-02-08 20:18:46 +00:00
|
|
|
// Create mock registry
|
|
|
|
|
create_mock_registry(project_root)?;
|
2026-02-08 20:37:49 +00:00
|
|
|
|
2026-02-08 20:18:46 +00:00
|
|
|
// Create test feature
|
|
|
|
|
let test_feature = TestFeatureBuilder::new("test-analytics")
|
|
|
|
|
.with_dependency("serde_json")
|
|
|
|
|
.with_dependency("chrono")
|
|
|
|
|
.with_env_var("ANALYTICS_ENABLED", "true", false)
|
|
|
|
|
.with_env_var("ANALYTICS_API_KEY", "", true);
|
2026-02-08 20:37:49 +00:00
|
|
|
|
2026-02-08 20:18:46 +00:00
|
|
|
test_feature.create_in_project(project_root)?;
|
2026-02-08 20:37:49 +00:00
|
|
|
|
2026-02-08 20:18:46 +00:00
|
|
|
// Test feature loading
|
|
|
|
|
let manifest_path = project_root.join("features/test-analytics/feature.toml");
|
|
|
|
|
assert!(manifest_path.exists(), "Feature manifest should be created");
|
2026-02-08 20:37:49 +00:00
|
|
|
|
2026-02-08 20:18:46 +00:00
|
|
|
// Test manifest content
|
|
|
|
|
assert_file_contains(&manifest_path, "name = \"test-analytics\"")?;
|
|
|
|
|
assert_file_contains(&manifest_path, "ANALYTICS_ENABLED")?;
|
|
|
|
|
assert_file_contains(&manifest_path, "ANALYTICS_API_KEY")?;
|
2026-02-08 20:37:49 +00:00
|
|
|
|
2026-02-08 20:18:46 +00:00
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_dependency_integration() -> Result<()> {
|
|
|
|
|
let temp_project = crate::create_test_project()?;
|
|
|
|
|
let project_root = temp_project.path();
|
2026-02-08 20:37:49 +00:00
|
|
|
|
2026-02-08 20:18:46 +00:00
|
|
|
// Create test feature with dependencies
|
|
|
|
|
let test_feature = TestFeatureBuilder::new("test-deps")
|
|
|
|
|
.with_dependency("serde_json")
|
|
|
|
|
.with_dependency("tokio");
|
2026-02-08 20:37:49 +00:00
|
|
|
|
2026-02-08 20:18:46 +00:00
|
|
|
test_feature.create_in_project(project_root)?;
|
2026-02-08 20:37:49 +00:00
|
|
|
|
2026-02-08 20:18:46 +00:00
|
|
|
// Simulate dependency integration
|
|
|
|
|
// This would use the actual FeatureManager and DependencyIntegrator
|
|
|
|
|
// For now, just verify the structure exists
|
2026-02-08 20:37:49 +00:00
|
|
|
|
2026-02-08 20:18:46 +00:00
|
|
|
let cargo_toml = project_root.join("Cargo.toml");
|
|
|
|
|
assert!(cargo_toml.exists(), "Cargo.toml should exist");
|
2026-02-08 20:37:49 +00:00
|
|
|
|
2026-02-08 20:18:46 +00:00
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_environment_integration() -> Result<()> {
|
|
|
|
|
let temp_project = crate::create_test_project()?;
|
|
|
|
|
let project_root = temp_project.path();
|
2026-02-08 20:37:49 +00:00
|
|
|
|
2026-02-08 20:18:46 +00:00
|
|
|
// Create feature with environment variables
|
|
|
|
|
let test_feature = TestFeatureBuilder::new("test-env")
|
|
|
|
|
.with_env_var("TEST_VAR", "default_value", false)
|
|
|
|
|
.with_env_var("REQUIRED_VAR", "", true);
|
2026-02-08 20:37:49 +00:00
|
|
|
|
2026-02-08 20:18:46 +00:00
|
|
|
test_feature.create_in_project(project_root)?;
|
2026-02-08 20:37:49 +00:00
|
|
|
|
2026-02-08 20:18:46 +00:00
|
|
|
// Test that environment integration would work
|
|
|
|
|
let env_file = project_root.join(".env");
|
|
|
|
|
assert!(env_file.exists(), ".env file should exist");
|
2026-02-08 20:37:49 +00:00
|
|
|
|
2026-02-08 20:18:46 +00:00
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_feature_removal() -> Result<()> {
|
|
|
|
|
let temp_project = crate::create_test_project()?;
|
|
|
|
|
let project_root = temp_project.path();
|
2026-02-08 20:37:49 +00:00
|
|
|
|
2026-02-08 20:18:46 +00:00
|
|
|
// Create and then remove a feature
|
|
|
|
|
let test_feature = TestFeatureBuilder::new("removable-feature");
|
|
|
|
|
test_feature.create_in_project(project_root)?;
|
2026-02-08 20:37:49 +00:00
|
|
|
|
2026-02-08 20:18:46 +00:00
|
|
|
// Verify feature exists
|
|
|
|
|
let feature_path = project_root.join("features/removable-feature");
|
|
|
|
|
assert!(feature_path.exists(), "Feature directory should exist");
|
2026-02-08 20:37:49 +00:00
|
|
|
|
2026-02-08 20:18:46 +00:00
|
|
|
// Test removal (would use actual FeatureManager)
|
|
|
|
|
// For now just verify structure
|
2026-02-08 20:37:49 +00:00
|
|
|
|
2026-02-08 20:18:46 +00:00
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_feature_conflicts() -> Result<()> {
|
|
|
|
|
let temp_project = crate::create_test_project()?;
|
|
|
|
|
let project_root = temp_project.path();
|
2026-02-08 20:37:49 +00:00
|
|
|
|
2026-02-08 20:18:46 +00:00
|
|
|
// Create conflicting features
|
|
|
|
|
let feature1 = TestFeatureBuilder::new("conflict-a")
|
|
|
|
|
.with_env_var("SHARED_VAR", "value_a", true);
|
2026-02-08 20:37:49 +00:00
|
|
|
|
2026-02-08 20:18:46 +00:00
|
|
|
let feature2 = TestFeatureBuilder::new("conflict-b")
|
|
|
|
|
.with_env_var("SHARED_VAR", "value_b", true);
|
2026-02-08 20:37:49 +00:00
|
|
|
|
2026-02-08 20:18:46 +00:00
|
|
|
feature1.create_in_project(project_root)?;
|
|
|
|
|
feature2.create_in_project(project_root)?;
|
2026-02-08 20:37:49 +00:00
|
|
|
|
2026-02-08 20:18:46 +00:00
|
|
|
// Test conflict detection (would use DependencyResolver)
|
|
|
|
|
// For now, just verify both features exist
|
|
|
|
|
assert!(project_root.join("features/conflict-a").exists());
|
|
|
|
|
assert!(project_root.join("features/conflict-b").exists());
|
2026-02-08 20:37:49 +00:00
|
|
|
|
2026-02-08 20:18:46 +00:00
|
|
|
Ok(())
|
2026-02-08 20:37:49 +00:00
|
|
|
}
|