use super::*;
#[test]
fn workspace_member_config_merge() {
use std::io::Write;
let tmp = std::env::temp_dir().join("seam-test-workspace-merge");
let _ = std::fs::remove_dir_all(&tmp);
std::fs::create_dir_all(tmp.join("backends/ts-hono")).unwrap();
let mut f = std::fs::File::create(tmp.join("backends/ts-hono/seam.toml")).unwrap();
writeln!(
f,
r#"[project]
name = "ignored"
[backend]
lang = "typescript"
dev_command = "bun --watch src/index.ts"
port = 4000
[build]
backend_build_command = "bun build src/index.ts"
router_file = "src/router.ts"
"#
)
.unwrap();
let root: SeamConfig = toml::from_str(
r#"
[project]
name = "github-dashboard"
[frontend]
entry = "frontend/src/client/main.tsx"
[build]
routes = "frontend/src/client/routes.ts"
out_dir = ".seam/output"
[workspace]
members = ["backends/ts-hono"]
"#,
)
.unwrap();
let merged = resolve_member_config(&root, &tmp.join("backends/ts-hono")).unwrap();
assert_eq!(merged.project_name(), "github-dashboard");
assert_eq!(merged.backend.lang, "typescript");
assert_eq!(merged.backend.port, 4000);
assert_eq!(
merged.backend.dev_command.as_ref().map(crate::config::CommandConfig::command),
Some("bun --watch src/index.ts")
);
assert_eq!(merged.build.routes.as_deref(), Some("frontend/src/client/routes.ts"));
assert_eq!(
merged.build.backend_build_command.as_ref().map(crate::config::CommandConfig::command),
Some("bun build src/index.ts")
);
assert_eq!(merged.build.router_file.as_deref(), Some("src/router.ts"));
assert!(!merged.is_workspace());
let _ = std::fs::remove_dir_all(&tmp);
}
#[test]
fn workspace_validation_missing_dir() {
let tmp = std::env::temp_dir().join("seam-test-ws-missing-dir");
let _ = std::fs::remove_dir_all(&tmp);
std::fs::create_dir_all(&tmp).unwrap();
let config: SeamConfig = toml::from_str(
r#"
[project]
name = "test"
[workspace]
members = ["nonexistent"]
"#,
)
.unwrap();
let err = validate_workspace(&config, &tmp).unwrap_err();
assert!(err.to_string().contains("not found"));
let _ = std::fs::remove_dir_all(&tmp);
}
#[test]
fn workspace_validation_missing_config() {
let tmp = std::env::temp_dir().join("seam-test-ws-missing-config");
let _ = std::fs::remove_dir_all(&tmp);
std::fs::create_dir_all(tmp.join("member-a")).unwrap();
let config: SeamConfig = toml::from_str(
r#"
[project]
name = "test"
[workspace]
members = ["member-a"]
"#,
)
.unwrap();
let err = validate_workspace(&config, &tmp).unwrap_err();
assert!(err.to_string().contains("missing config file"));
let _ = std::fs::remove_dir_all(&tmp);
}
#[test]
fn workspace_validation_duplicate_names() {
use std::io::Write;
let tmp = std::env::temp_dir().join("seam-test-ws-dup-names");
let _ = std::fs::remove_dir_all(&tmp);
std::fs::create_dir_all(tmp.join("a/hono")).unwrap();
std::fs::create_dir_all(tmp.join("b/hono")).unwrap();
for dir in ["a/hono", "b/hono"] {
let mut f = std::fs::File::create(tmp.join(dir).join("seam.toml")).unwrap();
writeln!(
f,
r#"[project]
name = "x"
[build]
router_file = "src/router.ts"
"#
)
.unwrap();
}
let config: SeamConfig = toml::from_str(
r#"
[project]
name = "test"
[frontend]
entry = "src/main.tsx"
[build]
routes = "routes.ts"
[workspace]
members = ["a/hono", "b/hono"]
"#,
)
.unwrap();
let err = validate_workspace(&config, &tmp).unwrap_err();
assert!(err.to_string().contains("duplicate"));
let _ = std::fs::remove_dir_all(&tmp);
}
#[test]
fn workspace_validation_no_manifest_method() {
use std::io::Write;
let tmp = std::env::temp_dir().join("seam-test-ws-no-manifest");
let _ = std::fs::remove_dir_all(&tmp);
std::fs::create_dir_all(tmp.join("member")).unwrap();
let mut f = std::fs::File::create(tmp.join("member/seam.toml")).unwrap();
writeln!(
f,
r#"[project]
name = "x"
[backend]
lang = "rust"
"#
)
.unwrap();
let config: SeamConfig = toml::from_str(
r#"
[project]
name = "test"
[frontend]
entry = "src/main.tsx"
[build]
routes = "routes.ts"
[workspace]
members = ["member"]
"#,
)
.unwrap();
let err = validate_workspace(&config, &tmp).unwrap_err();
assert!(err.to_string().contains("router_file or build.manifest_command"));
let _ = std::fs::remove_dir_all(&tmp);
}