use anyhow::Result;
use test_context::{test_context, AsyncTestContext};
struct TestContext {
tmp_dir: std::path::PathBuf,
}
impl TestContext {
pub async fn new() -> Result<Self> {
let tmp_dir = std::env::temp_dir();
let tmp_dir = tmp_dir.join(&format!("openapitor-{}", uuid::Uuid::new_v4()));
std::fs::create_dir_all(&tmp_dir)?;
let src_dir = tmp_dir.clone().join("src");
std::fs::create_dir_all(&src_dir)?;
Ok(TestContext { tmp_dir })
}
}
#[async_trait::async_trait]
impl AsyncTestContext for TestContext {
async fn setup() -> Self {
TestContext::new().await.unwrap()
}
async fn teardown(self) {
println!("Removing {}", self.tmp_dir.display());
std::fs::remove_dir_all(&self.tmp_dir).unwrap();
}
}
#[test_context(TestContext)]
#[tokio::test]
async fn test_kittycad_generation(ctx: &mut TestContext) {
let opts = crate::Opts {
debug: true,
json: false,
input: ctx.tmp_dir.clone(),
output: ctx.tmp_dir.clone(),
base_url: "https://api.kittycad.io".parse().unwrap(),
name: "kittycad".to_string(),
version: "1.0.0".to_string(),
description: "KittyCAD is a tool for generating 3D models of cats.".to_string(),
spec_url: Some("https://api.kittycad.io".to_string()),
repo_name: Some("kittycad/kittycad.rs".to_string()),
token_endpoint: None,
user_consent_endpoint: None,
};
let spec = crate::load_json_spec(include_str!("../../spec.json")).unwrap();
let test_file = include_str!("../tests/library/kittycad.tests.rs");
let test_file_path = ctx.tmp_dir.join("src").join("tests.rs");
std::fs::write(&test_file_path, test_file).unwrap();
let assets_dir = ctx.tmp_dir.join("assets");
std::fs::create_dir_all(&assets_dir).unwrap();
let mut assets_dir_contents =
std::fs::read_dir(&std::env::current_dir().unwrap().join("../assets")).unwrap();
while let Some(Ok(entry)) = assets_dir_contents.next() {
let dest = assets_dir.join(entry.file_name());
std::fs::copy(&entry.path(), &dest).unwrap();
}
crate::generate(&spec, &opts).await.unwrap();
let output_tests_dir = ctx.tmp_dir.join("tests");
std::fs::create_dir_all(&output_tests_dir).unwrap();
run_cargo_test(&opts).await.unwrap();
}
#[test_context(TestContext)]
#[tokio::test]
#[ignore]
async fn test_github_generation(ctx: &mut TestContext) {
let opts = crate::Opts {
debug: true,
json: false,
input: ctx.tmp_dir.clone(),
output: ctx.tmp_dir.clone(),
base_url: "https://api.github.com".parse().unwrap(),
name: "octorust".to_string(),
version: "1.0.0".to_string(),
description: "GitHub is where we push our code and you do too!".to_string(),
spec_url: Some("https://github.com/github/rest-api-description/raw/main/descriptions/api.github.com/api.github.com.json".to_string()),
repo_name: Some("kittycad/octorust.rs".to_string()),
token_endpoint:None,
user_consent_endpoint:None,
};
let spec = crate::load_json_spec(include_str!("../tests/api.github.com.json")).unwrap();
let test_file = include_str!("../tests/library/github.tests.rs");
let test_file_path = ctx.tmp_dir.join("src").join("tests.rs");
std::fs::write(&test_file_path, test_file).unwrap();
crate::generate(&spec, &opts).await.unwrap();
run_cargo_test(&opts).await.unwrap();
}
#[test_context(TestContext)]
#[tokio::test]
async fn test_oxide_generation(ctx: &mut TestContext) {
let opts = crate::Opts {
debug: true,
json: false,
input: ctx.tmp_dir.clone(),
output: ctx.tmp_dir.clone(),
base_url: "https://api.oxide.computer".parse().unwrap(),
name: "oxide".to_string(),
version: "1.0.0".to_string(),
description: "Oxide builds computers.".to_string(),
spec_url: Some(
"https://raw.githubusercontent.com/oxidecomputer/omicron/main/openapi/nexus.json"
.to_string(),
),
repo_name: Some("oxide/oxide.rs".to_string()),
token_endpoint: None,
user_consent_endpoint: None,
};
let spec = crate::load_json_spec(include_str!("../tests/oxide.json")).unwrap();
let test_file = include_str!("../tests/library/oxide.tests.rs");
let test_file_path = ctx.tmp_dir.join("src").join("tests.rs");
std::fs::write(&test_file_path, test_file).unwrap();
crate::generate(&spec, &opts).await.unwrap();
run_cargo_test(&opts).await.unwrap();
}
#[test_context(TestContext)]
#[tokio::test]
async fn test_front_generation(ctx: &mut TestContext) {
let opts = crate::Opts {
debug: true,
json: false,
input: ctx.tmp_dir.clone(),
output: ctx.tmp_dir.clone(),
base_url: "https://api.front.com".parse().unwrap(),
name: "front-api".to_string(),
version: "1.0.0".to_string(),
description: "CRM crap!".to_string(),
spec_url: Some("".to_string()),
repo_name: Some("kittycad/front.rs".to_string()),
token_endpoint: None,
user_consent_endpoint: None,
};
let spec = crate::load_json_spec(include_str!("../tests/front.json")).unwrap();
let test_file = include_str!("../tests/library/front.tests.rs");
let test_file_path = ctx.tmp_dir.join("src").join("tests.rs");
std::fs::write(&test_file_path, test_file).unwrap();
crate::generate(&spec, &opts).await.unwrap();
run_cargo_test(&opts).await.unwrap();
}
#[test_context(TestContext)]
#[tokio::test]
async fn test_gusto_generation(ctx: &mut TestContext) {
let opts = crate::Opts {
debug: true,
json: false,
input: ctx.tmp_dir.clone(),
output: ctx.tmp_dir.clone(),
base_url: "https://api.gusto.com".parse().unwrap(),
name: "gusto-api".to_string(),
version: "1.0.0".to_string(),
description: "HR crap!".to_string(),
spec_url: Some("".to_string()),
repo_name: Some("kittycad/gusto.rs".to_string()),
token_endpoint: Some("https://api.gusto.com/oauth/token".parse().unwrap()),
user_consent_endpoint: Some("https://api.gusto.com/oauth/authorize".parse().unwrap()),
};
let spec = crate::load_yaml_spec(include_str!("../tests/gusto.v1.yaml")).unwrap();
let test_file = include_str!("../tests/library/gusto.tests.rs");
let test_file_path = ctx.tmp_dir.join("src").join("tests.rs");
std::fs::write(&test_file_path, test_file).unwrap();
crate::generate(&spec, &opts).await.unwrap();
run_cargo_test(&opts).await.unwrap();
}
async fn run_cargo_test(opts: &crate::Opts) -> Result<()> {
log::info!("Running `cargo test`...");
let output = if opts.output.display().to_string() == "." {
"".to_string()
} else {
opts.output.display().to_string()
};
let mut cmd = tokio::process::Command::new("cargo");
cmd.args(["test"])
.current_dir(output)
.env("EXPECTORATE", "overwrite");
let output = cmd.output().await?;
if !output.status.success() {
anyhow::bail!(
"cargo test failed: {}",
String::from_utf8_lossy(&output.stderr)
);
}
Ok(())
}