// File: tests/project_lifecycle.rs // Integration tests - full project lifecycle use tempfile::TempDir; use std::fs; use weevil::project::{ProjectBuilder, ProjectConfig}; use weevil::sdk::SdkConfig; // Note: These tests use the actual FTC SDK if available, or skip if not // For true unit testing with mocks, we'd need to refactor to use dependency injection #[test] fn test_config_create_and_save() { let temp_dir = TempDir::new().unwrap(); let sdk_path = temp_dir.path().join("mock-sdk"); let android_sdk_path = temp_dir.path().join("android-sdk"); // Create minimal SDK structure fs::create_dir_all(sdk_path.join("TeamCode/src/main/java")).unwrap(); fs::create_dir_all(sdk_path.join("FtcRobotController")).unwrap(); fs::write(sdk_path.join("build.gradle"), "// test").unwrap(); fs::write(sdk_path.join(".version"), "v10.1.1").unwrap(); let config = ProjectConfig::new("test-robot", sdk_path.clone(), android_sdk_path.clone()).unwrap(); assert_eq!(config.project_name, "test-robot"); assert_eq!(config.ftc_sdk_path, sdk_path); assert_eq!(config.android_sdk_path, android_sdk_path); assert_eq!(config.weevil_version, "1.0.0"); // Save and reload let project_path = temp_dir.path().join("project"); fs::create_dir_all(&project_path).unwrap(); config.save(&project_path).unwrap(); let loaded = ProjectConfig::load(&project_path).unwrap(); assert_eq!(loaded.project_name, config.project_name); assert_eq!(loaded.ftc_sdk_path, config.ftc_sdk_path); assert_eq!(loaded.android_sdk_path, config.android_sdk_path); } #[test] fn test_config_toml_format() { let temp_dir = TempDir::new().unwrap(); let sdk_path = temp_dir.path().join("sdk"); let android_sdk_path = temp_dir.path().join("android-sdk"); // Create minimal SDK fs::create_dir_all(sdk_path.join("TeamCode/src/main/java")).unwrap(); fs::create_dir_all(sdk_path.join("FtcRobotController")).unwrap(); fs::write(sdk_path.join("build.gradle"), "// test").unwrap(); fs::write(sdk_path.join(".version"), "v10.1.1").unwrap(); let config = ProjectConfig::new("my-robot", sdk_path, android_sdk_path).unwrap(); let project_path = temp_dir.path().join("project"); fs::create_dir_all(&project_path).unwrap(); config.save(&project_path).unwrap(); let content = fs::read_to_string(project_path.join(".weevil.toml")).unwrap(); assert!(content.contains("project_name = \"my-robot\"")); assert!(content.contains("weevil_version = \"1.0.0\"")); assert!(content.contains("ftc_sdk_path")); assert!(content.contains("ftc_sdk_version")); assert!(content.contains("android_sdk_path")); } #[test] fn test_project_structure_creation() { let temp_dir = TempDir::new().unwrap(); let sdk_path = temp_dir.path().join("sdk"); // Create minimal SDK fs::create_dir_all(sdk_path.join("TeamCode/src/main/java")).unwrap(); fs::create_dir_all(sdk_path.join("FtcRobotController")).unwrap(); fs::write(sdk_path.join("build.gradle"), "// test").unwrap(); fs::write(sdk_path.join(".version"), "v10.1.1").unwrap(); let sdk_config = SdkConfig { ftc_sdk_path: sdk_path.clone(), android_sdk_path: temp_dir.path().join("android-sdk"), cache_dir: temp_dir.path().join("cache"), }; let builder = ProjectBuilder::new("test-robot", &sdk_config).unwrap(); let project_path = temp_dir.path().join("test-robot"); builder.create(&project_path, &sdk_config).unwrap(); // Verify structure assert!(project_path.join("README.md").exists()); assert!(project_path.join("build.gradle.kts").exists()); assert!(project_path.join("gradlew").exists()); assert!(project_path.join(".weevil.toml").exists()); assert!(project_path.join("src/main/java/robot").exists()); assert!(project_path.join("src/test/java/robot").exists()); } #[test] fn test_build_scripts_contain_config_reading() { let temp_dir = TempDir::new().unwrap(); let sdk_path = temp_dir.path().join("sdk"); // Create minimal SDK fs::create_dir_all(sdk_path.join("TeamCode/src/main/java")).unwrap(); fs::create_dir_all(sdk_path.join("FtcRobotController")).unwrap(); fs::write(sdk_path.join("build.gradle"), "// test").unwrap(); fs::write(sdk_path.join(".version"), "v10.1.1").unwrap(); let sdk_config = SdkConfig { ftc_sdk_path: sdk_path, android_sdk_path: temp_dir.path().join("android-sdk"), cache_dir: temp_dir.path().join("cache"), }; let builder = ProjectBuilder::new("test", &sdk_config).unwrap(); let project_path = temp_dir.path().join("test"); builder.create(&project_path, &sdk_config).unwrap(); // Check build.sh reads from config let build_sh = fs::read_to_string(project_path.join("build.sh")).unwrap(); assert!(build_sh.contains(".weevil.toml")); assert!(build_sh.contains("ftc_sdk_path")); // Check build.bat reads from config let build_bat = fs::read_to_string(project_path.join("build.bat")).unwrap(); assert!(build_bat.contains(".weevil.toml")); assert!(build_bat.contains("ftc_sdk_path")); } #[test] fn test_config_persistence_across_operations() { let temp_dir = TempDir::new().unwrap(); let sdk_path = temp_dir.path().join("sdk"); // Create minimal SDK fs::create_dir_all(sdk_path.join("TeamCode/src/main/java")).unwrap(); fs::create_dir_all(sdk_path.join("FtcRobotController")).unwrap(); fs::write(sdk_path.join("build.gradle"), "// test").unwrap(); fs::write(sdk_path.join(".version"), "v10.1.1").unwrap(); let sdk_config = SdkConfig { ftc_sdk_path: sdk_path.clone(), android_sdk_path: temp_dir.path().join("android-sdk"), cache_dir: temp_dir.path().join("cache"), }; let builder = ProjectBuilder::new("persist-test", &sdk_config).unwrap(); let project_path = temp_dir.path().join("persist-test"); builder.create(&project_path, &sdk_config).unwrap(); // Load config let config = ProjectConfig::load(&project_path).unwrap(); assert_eq!(config.project_name, "persist-test"); assert_eq!(config.ftc_sdk_path, sdk_path); // Version may be "unknown" if SDK isn't a git repo, which is fine for mock SDKs assert!(config.ftc_sdk_version == "v10.1.1" || config.ftc_sdk_version == "unknown" || config.ftc_sdk_version.starts_with("commit-")); }