use crate::support::*;
use std::fs;
#[test]
fn test_dot_detects_python() {
let t = Test::init("alice");
fs::write(
t.dir.path().join("pyproject.toml"),
"[project]\nname = \"test\"\n",
)
.unwrap();
let set_output = t.set("TEST_VAR", "test_value");
assert_success(&set_output);
let output = t.cmd().arg(".").output().unwrap();
let combined = format!("{}{}", stdout(&output), stderr(&output));
assert!(
!combined.contains("couldn't detect project type"),
"should detect python project, got: {combined}"
);
}
#[test]
fn test_dot_detects_node() {
let t = Test::init("alice");
fs::write(t.dir.path().join("package.json"), "{}").unwrap();
let set_output = t.set("TEST_VAR", "test_value");
assert_success(&set_output);
let output = t.cmd().arg(".").output().unwrap();
let combined = format!("{}{}", stdout(&output), stderr(&output));
assert!(
!combined.contains("couldn't detect project type"),
"should detect node project, got: {combined}"
);
}
#[test]
fn test_dot_detects_rust() {
let t = Test::init("alice");
fs::write(
t.dir.path().join("Cargo.toml"),
"[package]\nname = \"test\"\n",
)
.unwrap();
let set_output = t.set("TEST_VAR", "test_value");
assert_success(&set_output);
let output = t.cmd().arg(".").output().unwrap();
let combined = format!("{}{}", stdout(&output), stderr(&output));
assert!(combined.contains("Cargo"));
}
#[test]
fn test_dot_priority_python_over_node() {
let t = Test::init("alice");
fs::write(
t.dir.path().join("pyproject.toml"),
"[project]\nname = \"test\"\n",
)
.unwrap();
fs::write(t.dir.path().join("package.json"), "{}").unwrap();
let set_output = t.set("TEST_VAR", "test_value");
assert_success(&set_output);
let output = t.cmd().arg(".").output().unwrap();
let combined = format!("{}{}", stdout(&output), stderr(&output));
assert!(
!combined.contains("couldn't detect project type"),
"should detect a project type, got: {combined}"
);
assert!(
!combined.contains("npm") && !combined.contains("bun"),
"should prefer python over node, got: {combined}"
);
}
#[test]
fn test_dot_no_project_detected() {
let t = Test::init("alice");
let output = t.cmd().arg(".").output().unwrap();
assert_failure(&output);
assert_stderr_contains(&output, "couldn't detect project type");
assert_stdout_contains(&output, "dugout run");
}
#[test]
fn test_dot_without_vault_fails() {
let t = Test::new();
fs::write(t.dir.path().join("Cargo.toml"), "[package]\n").unwrap();
let output = t.cmd().arg(".").output().unwrap();
assert_failure(&output);
assert_stderr_contains(&output, "no vault found");
}
#[test]
fn test_dot_without_access_suggests_knock() {
let t = Test::new();
let init_output = t.init_cmd("alice");
assert_success(&init_output);
fs::write(t.dir.path().join("Cargo.toml"), "[package]\n").unwrap();
let setup_output = t.cmd().arg("setup").output().unwrap();
assert_success(&setup_output);
let output = t.cmd().arg(".").output().unwrap();
assert_failure(&output);
let combined = format!("{}{}", stdout(&output), stderr(&output));
assert!(combined.contains("knock") || combined.contains("access"));
}
#[test]
fn test_dot_detects_docker_compose() {
let t = Test::init("alice");
fs::write(
t.dir.path().join("docker-compose.yml"),
"version: '3'\nservices:\n test:\n image: test\n",
)
.unwrap();
let set_output = t.set("TEST_VAR", "test_value");
assert_success(&set_output);
let output = t.cmd().arg(".").output().unwrap();
let combined = format!("{}{}", stdout(&output), stderr(&output));
assert!(combined.contains("docker"));
}
#[test]
fn test_dot_detects_makefile() {
let t = Test::init("alice");
fs::write(t.dir.path().join("Makefile"), "dev:\n\techo test\n").unwrap();
let set_output = t.set("TEST_VAR", "test_value");
assert_success(&set_output);
let output = t.cmd().arg(".").output().unwrap();
let combined = format!("{}{}", stdout(&output), stderr(&output));
assert!(combined.contains("test") || combined.contains("echo"));
}
#[test]
fn test_dot_detects_deno() {
let t = Test::init("alice");
fs::write(t.dir.path().join("deno.json"), "{}").unwrap();
let set_output = t.set("TEST_VAR", "test_value");
assert_success(&set_output);
let output = t.cmd().arg(".").output().unwrap();
let combined = format!("{}{}", stdout(&output), stderr(&output));
assert!(
!combined.contains("couldn't detect project type"),
"should detect deno project, got: {combined}"
);
}
#[test]
fn test_dot_detects_deno_jsonc() {
let t = Test::init("alice");
fs::write(t.dir.path().join("deno.jsonc"), "{}").unwrap();
let set_output = t.set("TEST_VAR", "test_value");
assert_success(&set_output);
let output = t.cmd().arg(".").output().unwrap();
let combined = format!("{}{}", stdout(&output), stderr(&output));
assert!(
!combined.contains("couldn't detect project type"),
"should detect deno project from deno.jsonc, got: {combined}"
);
}
#[test]
fn test_dot_deno_priority_over_node() {
let t = Test::init("alice");
fs::write(t.dir.path().join("deno.json"), "{}").unwrap();
fs::write(t.dir.path().join("package.json"), "{}").unwrap();
let set_output = t.set("TEST_VAR", "test_value");
assert_success(&set_output);
let output = t.cmd().arg(".").output().unwrap();
let combined = format!("{}{}", stdout(&output), stderr(&output));
assert!(
!combined.contains("npm") && !combined.contains("bun"),
"should prefer deno over node, got: {combined}"
);
}
#[test]
fn test_dot_detects_ruby() {
let t = Test::init("alice");
fs::write(
t.dir.path().join("Gemfile"),
"source 'https://rubygems.org'\n",
)
.unwrap();
let set_output = t.set("TEST_VAR", "test_value");
assert_success(&set_output);
let output = t.cmd().arg(".").output().unwrap();
let combined = format!("{}{}", stdout(&output), stderr(&output));
assert!(
!combined.contains("couldn't detect project type"),
"should detect ruby project, got: {combined}"
);
}
#[test]
fn test_dot_detects_elixir() {
let t = Test::init("alice");
fs::write(
t.dir.path().join("mix.exs"),
"defmodule MyApp.MixProject do\nend\n",
)
.unwrap();
let set_output = t.set("TEST_VAR", "test_value");
assert_success(&set_output);
let output = t.cmd().arg(".").output().unwrap();
let combined = format!("{}{}", stdout(&output), stderr(&output));
assert!(
!combined.contains("couldn't detect project type"),
"should detect elixir project, got: {combined}"
);
}
#[test]
fn test_dot_python_no_entry_shows_summary() {
let t = Test::init("alice");
fs::write(
t.dir.path().join("pyproject.toml"),
"[project]\nname = \"mylib\"\n",
)
.unwrap();
let set_output = t.set("DB_URL", "postgres://localhost");
assert_success(&set_output);
let output = t.cmd().arg(".").output().unwrap();
let combined = format!("{}{}", stdout(&output), stderr(&output));
assert!(
combined.contains("python") && combined.contains("secret"),
"should show summary with project type and secret count, got: {combined}"
);
}
#[test]
fn test_dot_python_with_main_py() {
let t = Test::init("alice");
fs::write(
t.dir.path().join("pyproject.toml"),
"[project]\nname = \"myapp\"\n",
)
.unwrap();
fs::write(
t.dir.path().join("main.py"),
"import os\nprint(os.environ.get('TEST_SECRET', 'missing'))\n",
)
.unwrap();
let set_output = t.set("TEST_SECRET", "hunter2");
assert_success(&set_output);
let output = t.cmd().arg(".").output().unwrap();
let combined = format!("{}{}", stdout(&output), stderr(&output));
assert!(
combined.contains("hunter2") || combined.contains("main.py"),
"should run main.py with injected secrets, got: {combined}"
);
}
#[test]
fn test_dot_detects_justfile() {
let t = Test::init("alice");
fs::write(t.dir.path().join("justfile"), "dev:\n echo test-just\n").unwrap();
let set_output = t.set("TEST_VAR", "test_value");
assert_success(&set_output);
let output = t.cmd().arg(".").output().unwrap();
let combined = format!("{}{}", stdout(&output), stderr(&output));
assert!(
!combined.contains("couldn't detect project type"),
"should detect justfile project, got: {combined}"
);
}