Fixed warnings and patched some files, working on testing

This commit is contained in:
Eric Ratliff
2026-02-02 22:45:53 -06:00
parent 60679e097f
commit 38f1e0f3ed
3 changed files with 317 additions and 6 deletions

View File

@@ -1,5 +1,5 @@
[project] [project]
name = "{{PROJECT_NAME}}" project_name = "{{PROJECT_NAME}}"
created = "{{CREATION_DATE}}" created = "{{CREATION_DATE}}"
weevil_version = "{{WEEVIL_VERSION}}" weevil_version = "{{WEEVIL_VERSION}}"
template = "{{TEMPLATE_NAME}}" template = "{{TEMPLATE_NAME}}"

View File

@@ -1,5 +1,11 @@
project_name = "my-robot" [project]
weevil_version = "1.1.0-beta.2" project_name = "{{PROJECT_NAME}}"
ftc_sdk_path = 'C:\Users\Eric\.weevil\ftc-sdk' created = "{{CREATION_DATE}}"
ftc_sdk_version = "v10.1.1" weevil_version = "{{WEEVIL_VERSION}}"
android_sdk_path = 'C:\Users\Eric\.weevil\android-sdk' template = "{{TEMPLATE_NAME}}"
[ftc]
sdk_version = "10.1.1"
[build]
gradle_version = "8.5"

305
tests/template_tests.rs Normal file
View File

@@ -0,0 +1,305 @@
use anyhow::Result;
use std::fs;
use std::process::Command;
use tempfile::TempDir;
// Import the template system
use weevil::templates::{TemplateManager, TemplateContext};
/// Helper to create a test template context
fn test_context(project_name: &str) -> TemplateContext {
TemplateContext {
project_name: project_name.to_string(),
package_name: project_name.to_lowercase().replace("-", ""),
creation_date: "2026-02-02T12:00:00Z".to_string(),
weevil_version: "1.1.0-test".to_string(),
template_name: "basic".to_string(),
}
}
#[test]
fn test_template_manager_creation() {
let mgr = TemplateManager::new();
assert!(mgr.is_ok(), "TemplateManager should be created successfully");
}
#[test]
fn test_template_exists() {
let mgr = TemplateManager::new().unwrap();
assert!(mgr.template_exists("basic"), "basic template should exist");
assert!(mgr.template_exists("testing"), "testing template should exist");
assert!(!mgr.template_exists("nonexistent"), "nonexistent template should not exist");
}
#[test]
fn test_list_templates() {
let mgr = TemplateManager::new().unwrap();
let templates = mgr.list_templates();
assert_eq!(templates.len(), 2, "Should have exactly 2 templates");
assert!(templates.iter().any(|t| t.contains("basic")), "Should list basic template");
assert!(templates.iter().any(|t| t.contains("testing")), "Should list testing template");
}
#[test]
fn test_basic_template_extraction() -> Result<()> {
let mgr = TemplateManager::new()?;
let temp_dir = TempDir::new()?;
let project_dir = temp_dir.path().join("test-robot");
fs::create_dir(&project_dir)?;
let context = test_context("test-robot");
let file_count = mgr.extract_template("basic", &project_dir, &context)?;
assert!(file_count > 0, "Should extract at least one file from basic template");
// Verify key files exist
assert!(project_dir.join(".gitignore").exists(), ".gitignore should exist");
assert!(project_dir.join("README.md").exists(), "README.md should exist (processed from .template)");
assert!(project_dir.join(".weevil.toml").exists(), ".weevil.toml should exist (processed from .template)");
assert!(project_dir.join("build.gradle").exists(), "build.gradle should exist (processed from .template)");
assert!(project_dir.join("settings.gradle").exists(), "settings.gradle should exist");
// Verify OpMode exists
let opmode_path = project_dir.join("src/main/java/robot/opmodes/BasicOpMode.java");
assert!(opmode_path.exists(), "BasicOpMode.java should exist");
Ok(())
}
#[test]
fn test_testing_template_extraction() -> Result<()> {
let mgr = TemplateManager::new()?;
let temp_dir = TempDir::new()?;
let project_dir = temp_dir.path().join("test-showcase");
fs::create_dir(&project_dir)?;
let mut context = test_context("test-showcase");
context.template_name = "testing".to_string();
let file_count = mgr.extract_template("testing", &project_dir, &context)?;
assert!(file_count > 20, "Testing template should have 20+ files, got {}", file_count);
// Verify documentation files
assert!(project_dir.join("README.md").exists(), "README.md should exist");
assert!(project_dir.join("DESIGN_AND_TEST_PLAN.md").exists(), "DESIGN_AND_TEST_PLAN.md should exist");
assert!(project_dir.join("TESTING_GUIDE.md").exists(), "TESTING_GUIDE.md should exist");
// Verify subsystems
assert!(project_dir.join("src/main/java/robot/subsystems/MotorCycler.java").exists(), "MotorCycler.java should exist");
assert!(project_dir.join("src/main/java/robot/subsystems/WallApproach.java").exists(), "WallApproach.java should exist");
assert!(project_dir.join("src/main/java/robot/subsystems/TurnController.java").exists(), "TurnController.java should exist");
// Verify hardware interfaces and implementations
assert!(project_dir.join("src/main/java/robot/hardware/MotorController.java").exists(), "MotorController interface should exist");
assert!(project_dir.join("src/main/java/robot/hardware/FtcMotorController.java").exists(), "FtcMotorController should exist");
assert!(project_dir.join("src/main/java/robot/hardware/DistanceSensor.java").exists(), "DistanceSensor interface should exist");
assert!(project_dir.join("src/main/java/robot/hardware/FtcDistanceSensor.java").exists(), "FtcDistanceSensor should exist");
// Verify test files
assert!(project_dir.join("src/test/java/robot/subsystems/MotorCyclerTest.java").exists(), "MotorCyclerTest.java should exist");
assert!(project_dir.join("src/test/java/robot/subsystems/WallApproachTest.java").exists(), "WallApproachTest.java should exist");
assert!(project_dir.join("src/test/java/robot/subsystems/TurnControllerTest.java").exists(), "TurnControllerTest.java should exist");
// Verify mock implementations
assert!(project_dir.join("src/test/java/robot/hardware/MockMotorController.java").exists(), "MockMotorController should exist");
assert!(project_dir.join("src/test/java/robot/hardware/MockDistanceSensor.java").exists(), "MockDistanceSensor should exist");
Ok(())
}
#[test]
fn test_template_variable_substitution() -> Result<()> {
let mgr = TemplateManager::new()?;
let temp_dir = TempDir::new()?;
let project_dir = temp_dir.path().join("my-test-robot");
fs::create_dir(&project_dir)?;
let context = test_context("my-test-robot");
mgr.extract_template("basic", &project_dir, &context)?;
// Check README.md for variable substitution
let readme_path = project_dir.join("README.md");
let readme_content = fs::read_to_string(readme_path)?;
assert!(readme_content.contains("my-test-robot"), "README should contain project name");
assert!(readme_content.contains("1.1.0-test"), "README should contain weevil version");
assert!(!readme_content.contains("{{PROJECT_NAME}}"), "README should not contain template variable");
assert!(!readme_content.contains("{{WEEVIL_VERSION}}"), "README should not contain template variable");
// Check .weevil.toml for variable substitution
let weevil_toml = project_dir.join(".weevil.toml");
let toml_content = fs::read_to_string(weevil_toml)?;
assert!(toml_content.contains("my-test-robot"), ".weevil.toml should contain project name");
assert!(!toml_content.contains("{{PROJECT_NAME}}"), ".weevil.toml should not contain template variable");
Ok(())
}
#[test]
fn test_invalid_template_extraction() {
let mgr = TemplateManager::new().unwrap();
let temp_dir = TempDir::new().unwrap();
let project_dir = temp_dir.path().join("test-robot");
fs::create_dir(&project_dir).unwrap();
let context = test_context("test-robot");
let result = mgr.extract_template("nonexistent", &project_dir, &context);
assert!(result.is_err(), "Should fail for nonexistent template");
}
#[test]
fn test_package_name_sanitization() {
let context1 = test_context("my-robot");
assert_eq!(context1.package_name, "myrobot", "Hyphens should be removed");
let context2 = test_context("team_1234_bot");
assert_eq!(context2.package_name, "team1234bot", "Underscores should be removed");
}
/// Integration test: Create a project with testing template and run gradle tests
/// This is marked with #[ignore] by default since it requires:
/// - Java installed
/// - Network access (first time to download gradle wrapper)
/// - Takes ~1-2 minutes to run
///
/// Run with: cargo test test_testing_template_gradle_build -- --ignored --nocapture
#[test]
#[ignore]
fn test_testing_template_gradle_build() -> Result<()> {
println!("Testing complete gradle build and test execution...");
let mgr = TemplateManager::new()?;
let temp_dir = TempDir::new()?;
let project_dir = temp_dir.path().join("gradle-test-robot");
fs::create_dir(&project_dir)?;
// Extract testing template
let mut context = test_context("gradle-test-robot");
context.template_name = "testing".to_string();
let file_count = mgr.extract_template("testing", &project_dir, &context)?;
println!("Extracted {} files from testing template", file_count);
// Check if gradlew exists (should be in testing template)
let gradlew = if cfg!(windows) {
project_dir.join("gradlew.bat")
} else {
project_dir.join("gradlew")
};
if !gradlew.exists() {
println!("WARNING: gradlew not found in template, skipping gradle test");
return Ok(());
}
// Make gradlew executable on Unix
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
let mut perms = fs::metadata(&gradlew)?.permissions();
perms.set_mode(0o755);
fs::set_permissions(&gradlew, perms)?;
}
println!("Running gradle test...");
// Run gradlew test
let output = Command::new(&gradlew)
.arg("test")
.current_dir(&project_dir)
.output()?;
println!("=== Gradle Output ===");
println!("{}", String::from_utf8_lossy(&output.stdout));
if !output.status.success() {
println!("=== Gradle Errors ===");
println!("{}", String::from_utf8_lossy(&output.stderr));
panic!("Gradle tests failed with status: {}", output.status);
}
// Verify test output mentions 45 tests
let stdout = String::from_utf8_lossy(&output.stdout);
// Look for test success indicators
let has_success = stdout.contains("BUILD SUCCESSFUL") ||
stdout.contains("45 tests") ||
stdout.to_lowercase().contains("tests passed");
assert!(has_success, "Gradle test output should indicate success");
println!("✓ All 45 tests passed!");
Ok(())
}
/// Test that basic template creates a valid directory structure
#[test]
fn test_basic_template_directory_structure() -> Result<()> {
let mgr = TemplateManager::new()?;
let temp_dir = TempDir::new()?;
let project_dir = temp_dir.path().join("structure-test");
fs::create_dir(&project_dir)?;
let context = test_context("structure-test");
mgr.extract_template("basic", &project_dir, &context)?;
// Verify directory structure
assert!(project_dir.join("src").is_dir(), "src directory should exist");
assert!(project_dir.join("src/main").is_dir(), "src/main directory should exist");
assert!(project_dir.join("src/main/java").is_dir(), "src/main/java directory should exist");
assert!(project_dir.join("src/main/java/robot").is_dir(), "src/main/java/robot directory should exist");
assert!(project_dir.join("src/main/java/robot/opmodes").is_dir(), "opmodes directory should exist");
assert!(project_dir.join("src/test/java/robot").is_dir(), "test directory should exist");
Ok(())
}
/// Test that .gitignore is not named ".gitignore.template"
#[test]
fn test_gitignore_naming() -> Result<()> {
let mgr = TemplateManager::new()?;
let temp_dir = TempDir::new()?;
let project_dir = temp_dir.path().join("gitignore-test");
fs::create_dir(&project_dir)?;
let context = test_context("gitignore-test");
mgr.extract_template("basic", &project_dir, &context)?;
assert!(project_dir.join(".gitignore").exists(), ".gitignore should exist");
assert!(!project_dir.join(".gitignore.template").exists(), ".gitignore.template should NOT exist");
Ok(())
}
/// Test that template extraction doesn't fail with unusual project names
#[test]
fn test_unusual_project_names() -> Result<()> {
let mgr = TemplateManager::new()?;
let test_names = vec![
"robot-2024",
"team_1234",
"FTC_Bot",
"my-awesome-bot",
];
for name in test_names {
let temp_dir = TempDir::new()?;
let project_dir = temp_dir.path().join(name);
fs::create_dir(&project_dir)?;
let context = test_context(name);
let result = mgr.extract_template("basic", &project_dir, &context);
assert!(result.is_ok(), "Should handle project name: {}", name);
assert!(project_dir.join("README.md").exists(), "README should exist for {}", name);
}
Ok(())
}