use crate::cli::{Cli, Commands, DeployCommand, ServiceCommand};
use crate::service::{CreateServiceSpec, create_service_from_template, parse_exposes};
use crate::service_local::{find_service_root_from, service_dev_command};
use crate::util::make_vars;
use clap::Parser;
use std::fs;
#[test]
fn clap_parses_service_create() {
let cli = Cli::try_parse_from([
"exe",
"service",
"create",
"--name",
"orders",
"--domain",
"commerce",
"--template",
"rust",
])
.unwrap();
match cli.command {
Commands::Service {
command: ServiceCommand::Create(args),
} => {
assert_eq!(args.name, "orders");
assert_eq!(args.domain, "commerce");
assert_eq!(args.template_lang, "rust");
}
_ => panic!("unexpected command"),
}
}
#[test]
fn maps_make_vars() {
let vars = make_vars(&[
"tag=latest".into(),
"--image-tag=v1".into(),
"--ignored".into(),
]);
assert_eq!(vars, vec!["tag=latest", "IMAGE_TAG=v1"]);
}
#[test]
fn clap_parses_service_local_setup_and_dev() {
let setup = Cli::try_parse_from(["exe", "setup", "SKIP_DOCKER=1"]).unwrap();
match setup.command {
Commands::Setup(args) => assert_eq!(args.vars, vec!["SKIP_DOCKER=1"]),
_ => panic!("unexpected command"),
}
let dev = Cli::try_parse_from(["exe", "dev"]).unwrap();
match dev.command {
Commands::Dev { command } => assert!(command.is_none()),
_ => panic!("unexpected command"),
}
}
#[test]
fn clap_parses_release_sync_deploy_command() {
let cli = Cli::try_parse_from(["exe", "deploy", "release-sync"]).unwrap();
match cli.command {
Commands::Deploy {
command: DeployCommand::ReleaseSync(args),
} => assert!(args.vars.is_empty()),
_ => panic!("unexpected command"),
}
}
#[test]
fn finds_service_root_from_nested_directory() {
let dir = tempfile::tempdir().unwrap();
let service_root = dir.path().join("services/core/auth");
let nested = service_root.join("src/bootstrap");
fs::create_dir_all(&nested).unwrap();
fs::write(
service_root.join("service.yaml"),
"name: auth\nruntime: rust\n",
)
.unwrap();
assert_eq!(
find_service_root_from(&nested).unwrap(),
service_root.to_path_buf()
);
}
#[test]
fn chooses_dev_command_from_service_runtime() {
let dir = tempfile::tempdir().unwrap();
fs::write(dir.path().join("service.yaml"), "name: auth\nruntime: go\n").unwrap();
fs::create_dir_all(dir.path().join("cmd/server")).unwrap();
fs::write(dir.path().join("cmd/server/main.go"), "package main\n").unwrap();
assert_eq!(
service_dev_command(dir.path()).unwrap(),
vec!["go", "run", "./cmd/server"]
);
}
#[test]
fn parses_exposes() {
let dir = tempfile::tempdir().unwrap();
let path = dir.path().join("service.yaml");
fs::write(&path, "name: auth\nexposes:\n - protobuf: api/auth.proto\n - openapi: api/openapi.yaml\nruntime: rust\n").unwrap();
let exposes = parse_exposes(&path);
assert_eq!(exposes.get("protobuf").unwrap(), "api/auth.proto");
assert_eq!(exposes.get("openapi").unwrap(), "api/openapi.yaml");
}
#[test]
fn help_describes_commands() {
let mut command = <Cli as clap::CommandFactory>::command();
let mut help = Vec::new();
command.write_long_help(&mut help).unwrap();
let help = String::from_utf8(help).unwrap();
assert!(help.contains("Create, validate, build, test, and run services"));
assert!(help.contains("Generate and validate public gateway route artifacts"));
assert!(help.contains("Examples:"));
let mut service = <Cli as clap::CommandFactory>::command()
.find_subcommand_mut("service")
.unwrap()
.clone();
let mut service_help = Vec::new();
service.write_long_help(&mut service_help).unwrap();
let service_help = String::from_utf8(service_help).unwrap();
assert!(service_help.contains("Validate all service roots"));
assert!(service_help.contains("Create a service from a certified template"));
}
#[test]
fn creates_service_from_template() {
let dir = tempfile::tempdir().unwrap();
let root = dir.path();
let template = root.join("tools/templates/template-go-grpc");
let skeleton = template.join("skeleton");
fs::create_dir_all(skeleton.join("api")).unwrap();
fs::write(
skeleton.join("service.yaml"),
"name: __SERVICE_NAME__\ndomain: __DOMAIN__\nowner_team: __OWNER_TEAM__\n",
)
.unwrap();
fs::write(
skeleton.join("api/service.proto"),
"package __PROTO_PACKAGE__;\nservice __SERVICE_CLASS__Service {}\n",
)
.unwrap();
let output = root.join("services/commerce/order-service");
create_service_from_template(CreateServiceSpec {
root,
template_dir: &template,
output_dir: &output,
service_name: "order-service",
domain: "commerce",
owner_team: "team-orders",
framework: "native",
template_name: "template-go-grpc",
proto_package: "executesoft.commerce.order.service.v1",
service_class: "OrderService",
})
.unwrap();
let metadata = fs::read_to_string(output.join("service.yaml")).unwrap();
assert!(metadata.contains("name: order-service"));
assert!(metadata.contains("domain: commerce"));
assert!(metadata.contains("owner_team: team-orders"));
let shared =
fs::read_to_string(root.join("contracts/protobuf/commerce-order-service.proto")).unwrap();
assert!(shared.contains("package executesoft.commerce.order.service.v1;"));
assert!(shared.contains("service OrderServiceService {}"));
}