Wave 6: Integration tests, golden tests, index invariant tests, diff command (bd-rex, bd-2gp, bd-1ck)
This commit is contained in:
@@ -104,3 +104,521 @@ fn test_fetch_minimal_fixture() {
|
||||
assert_eq!(json["ok"], true);
|
||||
assert_eq!(json["data"]["total"], 3);
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// Fetch tests
|
||||
// ===========================================================================
|
||||
|
||||
#[test]
|
||||
fn test_fetch_success_robot() {
|
||||
let env = helpers::TestEnv::new();
|
||||
let fixture = helpers::fixture_path("petstore.json");
|
||||
|
||||
let assert = helpers::run_cmd(
|
||||
&env,
|
||||
&[
|
||||
"fetch",
|
||||
fixture.to_str().unwrap(),
|
||||
"--alias",
|
||||
"ps",
|
||||
"--robot",
|
||||
],
|
||||
)
|
||||
.success();
|
||||
|
||||
let json = helpers::parse_robot_json(&assert.get_output().stdout);
|
||||
assert_eq!(json["ok"], true);
|
||||
assert_eq!(json["data"]["alias"], "ps");
|
||||
assert!(json["data"]["endpoint_count"].as_u64().unwrap() > 0);
|
||||
assert!(json["data"]["schema_count"].as_u64().unwrap() > 0);
|
||||
assert!(
|
||||
json["data"]["content_hash"]
|
||||
.as_str()
|
||||
.unwrap()
|
||||
.starts_with("sha256:")
|
||||
);
|
||||
assert_eq!(json["data"]["source_format"], "json");
|
||||
assert_eq!(json["meta"]["command"], "fetch");
|
||||
assert!(json["meta"]["schema_version"].as_u64().is_some());
|
||||
assert!(json["meta"]["duration_ms"].as_u64().is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fetch_invalid_json() {
|
||||
let env = helpers::TestEnv::new();
|
||||
|
||||
// Create a non-JSON, non-YAML file that is not a valid OpenAPI spec
|
||||
let bad_file = env.home_dir.join("not-a-spec.json");
|
||||
std::fs::write(&bad_file, b"this is not json or yaml").unwrap();
|
||||
|
||||
let assert = helpers::run_cmd(
|
||||
&env,
|
||||
&[
|
||||
"fetch",
|
||||
bad_file.to_str().unwrap(),
|
||||
"--alias",
|
||||
"bad",
|
||||
"--robot",
|
||||
],
|
||||
);
|
||||
|
||||
// Should fail -- the file is not valid JSON or YAML
|
||||
let output = assert.get_output();
|
||||
assert!(!output.status.success());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fetch_alias_exists_error() {
|
||||
let env = helpers::TestEnv::new();
|
||||
helpers::fetch_fixture(&env, "petstore.json", "dupe");
|
||||
|
||||
let fixture = helpers::fixture_path("petstore.json");
|
||||
let assert = helpers::run_cmd(
|
||||
&env,
|
||||
&[
|
||||
"fetch",
|
||||
fixture.to_str().unwrap(),
|
||||
"--alias",
|
||||
"dupe",
|
||||
"--robot",
|
||||
],
|
||||
);
|
||||
|
||||
let output = assert.get_output();
|
||||
assert!(!output.status.success());
|
||||
|
||||
// Exit code 6 = ALIAS_EXISTS
|
||||
let stderr_json = helpers::parse_robot_json(&output.stderr);
|
||||
assert_eq!(stderr_json["ok"], false);
|
||||
assert_eq!(stderr_json["error"]["code"], "ALIAS_EXISTS");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fetch_force_overwrite() {
|
||||
let env = helpers::TestEnv::new();
|
||||
helpers::fetch_fixture(&env, "petstore.json", "overwrite-me");
|
||||
|
||||
let fixture = helpers::fixture_path("minimal.json");
|
||||
let assert = helpers::run_cmd(
|
||||
&env,
|
||||
&[
|
||||
"fetch",
|
||||
fixture.to_str().unwrap(),
|
||||
"--alias",
|
||||
"overwrite-me",
|
||||
"--force",
|
||||
"--robot",
|
||||
],
|
||||
)
|
||||
.success();
|
||||
|
||||
let json = helpers::parse_robot_json(&assert.get_output().stdout);
|
||||
assert_eq!(json["ok"], true);
|
||||
assert_eq!(json["data"]["alias"], "overwrite-me");
|
||||
// After force overwrite, the title should be from minimal.json
|
||||
assert_eq!(json["data"]["title"], "Minimal API");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fetch_yaml_success() {
|
||||
let env = helpers::TestEnv::new();
|
||||
let fixture = helpers::fixture_path("petstore.yaml");
|
||||
|
||||
let assert = helpers::run_cmd(
|
||||
&env,
|
||||
&[
|
||||
"fetch",
|
||||
fixture.to_str().unwrap(),
|
||||
"--alias",
|
||||
"yaml-test",
|
||||
"--robot",
|
||||
],
|
||||
)
|
||||
.success();
|
||||
|
||||
let json = helpers::parse_robot_json(&assert.get_output().stdout);
|
||||
assert_eq!(json["ok"], true);
|
||||
assert_eq!(json["data"]["source_format"], "yaml");
|
||||
assert!(json["data"]["endpoint_count"].as_u64().unwrap() > 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fetch_stdin() {
|
||||
let env = helpers::TestEnv::new();
|
||||
let fixture = helpers::fixture_path("petstore.json");
|
||||
let content = std::fs::read(&fixture).unwrap();
|
||||
|
||||
#[allow(deprecated)]
|
||||
let assert = assert_cmd::Command::cargo_bin("swagger-cli")
|
||||
.expect("binary not found")
|
||||
.env("SWAGGER_CLI_HOME", &env.home_dir)
|
||||
.args(["fetch", "-", "--alias", "stdin-test", "--robot"])
|
||||
.write_stdin(content)
|
||||
.assert()
|
||||
.success();
|
||||
|
||||
let json = helpers::parse_robot_json(&assert.get_output().stdout);
|
||||
assert_eq!(json["ok"], true);
|
||||
assert_eq!(json["data"]["alias"], "stdin-test");
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// List tests
|
||||
// ===========================================================================
|
||||
|
||||
#[test]
|
||||
fn test_list_filter_by_method() {
|
||||
let env = helpers::TestEnv::new();
|
||||
helpers::fetch_fixture(&env, "petstore.json", "petstore");
|
||||
|
||||
let assert =
|
||||
helpers::run_cmd(&env, &["list", "petstore", "--method", "GET", "--robot"]).success();
|
||||
|
||||
let json = helpers::parse_robot_json(&assert.get_output().stdout);
|
||||
assert_eq!(json["ok"], true);
|
||||
|
||||
let endpoints = json["data"]["endpoints"].as_array().unwrap();
|
||||
assert!(!endpoints.is_empty());
|
||||
for ep in endpoints {
|
||||
assert_eq!(ep["method"], "GET");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_list_filter_by_tag() {
|
||||
let env = helpers::TestEnv::new();
|
||||
helpers::fetch_fixture(&env, "petstore.json", "petstore");
|
||||
|
||||
let assert =
|
||||
helpers::run_cmd(&env, &["list", "petstore", "--tag", "store", "--robot"]).success();
|
||||
|
||||
let json = helpers::parse_robot_json(&assert.get_output().stdout);
|
||||
assert_eq!(json["ok"], true);
|
||||
|
||||
let endpoints = json["data"]["endpoints"].as_array().unwrap();
|
||||
assert!(!endpoints.is_empty());
|
||||
for ep in endpoints {
|
||||
let tags = ep["tags"].as_array().unwrap();
|
||||
let tag_strings: Vec<&str> = tags.iter().filter_map(|t| t.as_str()).collect();
|
||||
assert!(
|
||||
tag_strings
|
||||
.iter()
|
||||
.any(|t| t.to_lowercase().contains("store")),
|
||||
"Expected 'store' tag in {tag_strings:?}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_list_path_regex() {
|
||||
let env = helpers::TestEnv::new();
|
||||
helpers::fetch_fixture(&env, "petstore.json", "petstore");
|
||||
|
||||
let assert =
|
||||
helpers::run_cmd(&env, &["list", "petstore", "--path", "pet.*", "--robot"]).success();
|
||||
|
||||
let json = helpers::parse_robot_json(&assert.get_output().stdout);
|
||||
assert_eq!(json["ok"], true);
|
||||
|
||||
let endpoints = json["data"]["endpoints"].as_array().unwrap();
|
||||
assert!(!endpoints.is_empty());
|
||||
for ep in endpoints {
|
||||
let path = ep["path"].as_str().unwrap();
|
||||
assert!(
|
||||
path.contains("pet"),
|
||||
"Expected path to match 'pet.*', got: {path}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_list_invalid_regex_error() {
|
||||
let env = helpers::TestEnv::new();
|
||||
helpers::fetch_fixture(&env, "petstore.json", "petstore");
|
||||
|
||||
let assert = helpers::run_cmd(&env, &["list", "petstore", "--path", "[invalid", "--robot"]);
|
||||
|
||||
let output = assert.get_output();
|
||||
assert!(!output.status.success());
|
||||
|
||||
let stderr_json = helpers::parse_robot_json(&output.stderr);
|
||||
assert_eq!(stderr_json["ok"], false);
|
||||
assert_eq!(stderr_json["error"]["code"], "USAGE_ERROR");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_list_limit() {
|
||||
let env = helpers::TestEnv::new();
|
||||
helpers::fetch_fixture(&env, "petstore.json", "petstore");
|
||||
|
||||
let assert = helpers::run_cmd(&env, &["list", "petstore", "--limit", "2", "--robot"]).success();
|
||||
|
||||
let json = helpers::parse_robot_json(&assert.get_output().stdout);
|
||||
assert_eq!(json["ok"], true);
|
||||
|
||||
let endpoints = json["data"]["endpoints"].as_array().unwrap();
|
||||
assert!(endpoints.len() <= 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_list_all_flag() {
|
||||
let env = helpers::TestEnv::new();
|
||||
helpers::fetch_fixture(&env, "petstore.json", "petstore");
|
||||
|
||||
let assert = helpers::run_cmd(&env, &["list", "petstore", "--all", "--robot"]).success();
|
||||
|
||||
let json = helpers::parse_robot_json(&assert.get_output().stdout);
|
||||
assert_eq!(json["ok"], true);
|
||||
|
||||
let endpoints = json["data"]["endpoints"].as_array().unwrap();
|
||||
let total = json["data"]["total"].as_u64().unwrap() as usize;
|
||||
// With --all, endpoints shown should equal total (no truncation)
|
||||
assert_eq!(endpoints.len(), total);
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// Show tests
|
||||
// ===========================================================================
|
||||
|
||||
#[test]
|
||||
fn test_show_endpoint_details() {
|
||||
let env = helpers::TestEnv::new();
|
||||
helpers::fetch_fixture(&env, "petstore.json", "petstore");
|
||||
|
||||
let assert = helpers::run_cmd(
|
||||
&env,
|
||||
&["show", "petstore", "/pets", "--method", "GET", "--robot"],
|
||||
)
|
||||
.success();
|
||||
|
||||
let json = helpers::parse_robot_json(&assert.get_output().stdout);
|
||||
assert_eq!(json["ok"], true);
|
||||
assert_eq!(json["data"]["path"], "/pets");
|
||||
assert_eq!(json["data"]["method"], "GET");
|
||||
assert!(json["data"]["summary"].as_str().is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_show_method_disambiguation() {
|
||||
let env = helpers::TestEnv::new();
|
||||
helpers::fetch_fixture(&env, "petstore.json", "petstore");
|
||||
|
||||
// /pets has both GET and POST -- omitting --method should error
|
||||
let assert = helpers::run_cmd(&env, &["show", "petstore", "/pets", "--robot"]);
|
||||
|
||||
let output = assert.get_output();
|
||||
assert!(!output.status.success());
|
||||
|
||||
let stderr_json = helpers::parse_robot_json(&output.stderr);
|
||||
assert_eq!(stderr_json["ok"], false);
|
||||
assert_eq!(stderr_json["error"]["code"], "USAGE_ERROR");
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// Search tests
|
||||
// ===========================================================================
|
||||
|
||||
#[test]
|
||||
fn test_search_basic() {
|
||||
let env = helpers::TestEnv::new();
|
||||
helpers::fetch_fixture(&env, "petstore.json", "petstore");
|
||||
|
||||
let assert = helpers::run_cmd(&env, &["search", "petstore", "pet", "--robot"]).success();
|
||||
|
||||
let json = helpers::parse_robot_json(&assert.get_output().stdout);
|
||||
assert_eq!(json["ok"], true);
|
||||
|
||||
let total = json["data"]["total"].as_u64().unwrap();
|
||||
assert!(total > 0, "Expected search results for 'pet'");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_search_no_results() {
|
||||
let env = helpers::TestEnv::new();
|
||||
helpers::fetch_fixture(&env, "petstore.json", "petstore");
|
||||
|
||||
let assert = helpers::run_cmd(
|
||||
&env,
|
||||
&["search", "petstore", "zzzznonexistent99999", "--robot"],
|
||||
)
|
||||
.success();
|
||||
|
||||
let json = helpers::parse_robot_json(&assert.get_output().stdout);
|
||||
assert_eq!(json["ok"], true);
|
||||
assert_eq!(json["data"]["total"], 0);
|
||||
assert!(json["data"]["results"].as_array().unwrap().is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_search_case_insensitive() {
|
||||
let env = helpers::TestEnv::new();
|
||||
helpers::fetch_fixture(&env, "petstore.json", "petstore");
|
||||
|
||||
// Default search is case-insensitive; "PET" should match "pet" paths
|
||||
let assert = helpers::run_cmd(&env, &["search", "petstore", "PET", "--robot"]).success();
|
||||
|
||||
let json = helpers::parse_robot_json(&assert.get_output().stdout);
|
||||
assert_eq!(json["ok"], true);
|
||||
|
||||
let total = json["data"]["total"].as_u64().unwrap();
|
||||
assert!(
|
||||
total > 0,
|
||||
"Expected case-insensitive search for 'PET' to find results"
|
||||
);
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// Schemas tests
|
||||
// ===========================================================================
|
||||
|
||||
#[test]
|
||||
fn test_schemas_list() {
|
||||
let env = helpers::TestEnv::new();
|
||||
helpers::fetch_fixture(&env, "petstore.json", "petstore");
|
||||
|
||||
let assert = helpers::run_cmd(&env, &["schemas", "petstore", "--robot"]).success();
|
||||
|
||||
let json = helpers::parse_robot_json(&assert.get_output().stdout);
|
||||
assert_eq!(json["ok"], true);
|
||||
|
||||
let schemas = json["data"]["schemas"].as_array().unwrap();
|
||||
assert!(!schemas.is_empty());
|
||||
|
||||
let names: Vec<&str> = schemas.iter().filter_map(|s| s["name"].as_str()).collect();
|
||||
assert!(
|
||||
names.contains(&"Pet"),
|
||||
"Expected 'Pet' schema, got: {names:?}"
|
||||
);
|
||||
assert!(
|
||||
names.contains(&"Error"),
|
||||
"Expected 'Error' schema, got: {names:?}"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_schemas_show() {
|
||||
let env = helpers::TestEnv::new();
|
||||
helpers::fetch_fixture(&env, "petstore.json", "petstore");
|
||||
|
||||
let assert =
|
||||
helpers::run_cmd(&env, &["schemas", "petstore", "--show", "Pet", "--robot"]).success();
|
||||
|
||||
let json = helpers::parse_robot_json(&assert.get_output().stdout);
|
||||
assert_eq!(json["ok"], true);
|
||||
assert_eq!(json["data"]["name"], "Pet");
|
||||
assert!(json["data"]["schema"].is_object());
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// Tags tests
|
||||
// ===========================================================================
|
||||
|
||||
#[test]
|
||||
fn test_tags_list() {
|
||||
let env = helpers::TestEnv::new();
|
||||
helpers::fetch_fixture(&env, "petstore.json", "petstore");
|
||||
|
||||
let assert = helpers::run_cmd(&env, &["tags", "petstore", "--robot"]).success();
|
||||
|
||||
let json = helpers::parse_robot_json(&assert.get_output().stdout);
|
||||
assert_eq!(json["ok"], true);
|
||||
|
||||
let tags = json["data"]["tags"].as_array().unwrap();
|
||||
assert!(!tags.is_empty());
|
||||
|
||||
let names: Vec<&str> = tags.iter().filter_map(|t| t["name"].as_str()).collect();
|
||||
assert!(
|
||||
names.contains(&"pets"),
|
||||
"Expected 'pets' tag, got: {names:?}"
|
||||
);
|
||||
assert!(
|
||||
names.contains(&"store"),
|
||||
"Expected 'store' tag, got: {names:?}"
|
||||
);
|
||||
|
||||
// Each tag should have an endpoint_count
|
||||
for tag in tags {
|
||||
assert!(
|
||||
tag["endpoint_count"].as_u64().is_some(),
|
||||
"Expected endpoint_count on tag: {tag}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// Aliases tests
|
||||
// ===========================================================================
|
||||
|
||||
#[test]
|
||||
fn test_aliases_list() {
|
||||
let env = helpers::TestEnv::new();
|
||||
helpers::fetch_fixture(&env, "petstore.json", "alias-one");
|
||||
helpers::fetch_fixture(&env, "minimal.json", "alias-two");
|
||||
|
||||
let assert = helpers::run_cmd(&env, &["aliases", "--list", "--robot"]).success();
|
||||
|
||||
let json = helpers::parse_robot_json(&assert.get_output().stdout);
|
||||
assert_eq!(json["ok"], true);
|
||||
|
||||
let aliases = json["data"]["aliases"].as_array().unwrap();
|
||||
let names: Vec<&str> = aliases.iter().filter_map(|a| a["name"].as_str()).collect();
|
||||
assert!(
|
||||
names.contains(&"alias-one"),
|
||||
"Expected 'alias-one', got: {names:?}"
|
||||
);
|
||||
assert!(
|
||||
names.contains(&"alias-two"),
|
||||
"Expected 'alias-two', got: {names:?}"
|
||||
);
|
||||
assert_eq!(json["data"]["count"].as_u64().unwrap(), 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_aliases_set_default() {
|
||||
let env = helpers::TestEnv::new();
|
||||
helpers::fetch_fixture(&env, "petstore.json", "my-default");
|
||||
|
||||
let assert =
|
||||
helpers::run_cmd(&env, &["aliases", "--set-default", "my-default", "--robot"]).success();
|
||||
|
||||
let json = helpers::parse_robot_json(&assert.get_output().stdout);
|
||||
assert_eq!(json["ok"], true);
|
||||
assert_eq!(json["data"]["name"], "my-default");
|
||||
|
||||
// Verify by listing
|
||||
let list_assert = helpers::run_cmd(&env, &["aliases", "--list", "--robot"]).success();
|
||||
let list_json = helpers::parse_robot_json(&list_assert.get_output().stdout);
|
||||
assert_eq!(list_json["data"]["default_alias"], "my-default");
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
// Doctor tests
|
||||
// ===========================================================================
|
||||
|
||||
#[test]
|
||||
fn test_doctor_healthy() {
|
||||
let env = helpers::TestEnv::new();
|
||||
helpers::fetch_fixture(&env, "petstore.json", "healthy-spec");
|
||||
|
||||
let assert = helpers::run_cmd(&env, &["doctor", "--robot"]).success();
|
||||
|
||||
let json = helpers::parse_robot_json(&assert.get_output().stdout);
|
||||
assert_eq!(json["ok"], true);
|
||||
|
||||
// health should be "healthy" or "warning" (warning is ok if stale threshold is very low)
|
||||
let health = json["data"]["health"].as_str().unwrap();
|
||||
assert!(
|
||||
health == "healthy" || health == "warning",
|
||||
"Expected healthy or warning, got: {health}"
|
||||
);
|
||||
|
||||
let aliases = json["data"]["aliases"].as_array().unwrap();
|
||||
assert!(!aliases.is_empty());
|
||||
|
||||
let spec_report = aliases
|
||||
.iter()
|
||||
.find(|a| a["name"] == "healthy-spec")
|
||||
.unwrap();
|
||||
assert_eq!(spec_report["status"], "healthy");
|
||||
assert!(spec_report["endpoint_count"].as_u64().unwrap() > 0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user