1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
use std::process::Stdio;
use tempfile::TempDir;
use tokio::process::Command;
fn witryna_bin() -> std::path::PathBuf {
let mut path = std::path::PathBuf::from(env!("CARGO_BIN_EXE_witryna"));
if !path.exists() {
path = std::path::PathBuf::from("target/debug/witryna");
}
path
}
async fn write_validate_config(dir: &std::path::Path, content: &str) -> std::path::PathBuf {
let config_path = dir.join("witryna.toml");
tokio::fs::write(&config_path, content).await.unwrap();
config_path
}
// ---------------------------------------------------------------------------
// Tier 1: no container runtime / git needed
// ---------------------------------------------------------------------------
#[tokio::test]
async fn cli_validate_valid_config() {
let tempdir = TempDir::new().unwrap();
let base_dir = tempdir.path().join("data");
tokio::fs::create_dir_all(&base_dir).await.unwrap();
let config = format!(
r#"listen_address = "127.0.0.1:8080"
container_runtime = "podman"
base_dir = "{base_dir}"
log_level = "info"
[[sites]]
name = "site-a"
repo_url = "https://example.com/a.git"
branch = "main"
[[sites]]
name = "site-b"
repo_url = "https://example.com/b.git"
branch = "main"
"#,
base_dir = base_dir.display(),
);
let config_path = write_validate_config(tempdir.path(), &config).await;
let output = Command::new(witryna_bin())
.args(["validate", "--config", config_path.to_str().unwrap()])
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.output()
.await
.unwrap();
assert!(
output.status.success(),
"should exit 0, stderr: {}",
String::from_utf8_lossy(&output.stderr)
);
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(
stderr.contains("Configuration valid:"),
"should say 'Configuration valid:', got: {stderr}"
);
assert!(
stderr.contains("127.0.0.1:8080"),
"should show listen address, got: {stderr}"
);
assert!(
stderr.contains("podman"),
"should show runtime, got: {stderr}"
);
assert!(
stderr.contains("Sites: 2"),
"should show site count, got: {stderr}"
);
assert!(
stderr.contains("site-a"),
"should list site-a, got: {stderr}"
);
assert!(
stderr.contains("site-b"),
"should list site-b, got: {stderr}"
);
}
#[tokio::test]
async fn cli_validate_missing_config_file() {
let output = Command::new(witryna_bin())
.args(["validate", "--config", "/nonexistent/witryna.toml"])
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.output()
.await
.unwrap();
assert!(!output.status.success(), "should exit non-zero");
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(
stderr.contains("config file not found"),
"should mention 'config file not found', got: {stderr}"
);
}
#[tokio::test]
async fn cli_validate_invalid_config() {
let tempdir = TempDir::new().unwrap();
// listen_address = "" is invalid — config validation rejects it
let config = r#"listen_address = ""
container_runtime = "podman"
base_dir = "/tmp/witryna"
log_level = "info"
[[sites]]
name = "test"
repo_url = "https://example.com/test.git"
branch = "main"
"#;
let config_path = write_validate_config(tempdir.path(), config).await;
let output = Command::new(witryna_bin())
.args(["validate", "--config", config_path.to_str().unwrap()])
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.output()
.await
.unwrap();
assert!(
!output.status.success(),
"should exit non-zero for invalid config"
);
}
|