485 lines
14 KiB
Rust
485 lines
14 KiB
Rust
//! Integration tests for CLI pack commands
|
|
|
|
#![allow(deprecated)]
|
|
|
|
use assert_cmd::Command;
|
|
use predicates::prelude::*;
|
|
use serde_json::json;
|
|
use wiremock::{
|
|
matchers::{body_json, method, path},
|
|
Mock, ResponseTemplate,
|
|
};
|
|
|
|
mod common;
|
|
use common::*;
|
|
|
|
#[tokio::test]
|
|
async fn test_pack_list_authenticated() {
|
|
let fixture = TestFixture::new().await;
|
|
fixture.write_authenticated_config("valid_token", "refresh_token");
|
|
|
|
// Mock pack list endpoint
|
|
mock_pack_list(&fixture.mock_server).await;
|
|
|
|
let mut cmd = Command::cargo_bin("attune").unwrap();
|
|
cmd.env("XDG_CONFIG_HOME", fixture.config_dir_path())
|
|
.env("HOME", fixture.config_dir_path())
|
|
.arg("--api-url")
|
|
.arg(fixture.server_url())
|
|
.arg("pack")
|
|
.arg("list");
|
|
|
|
cmd.assert()
|
|
.success()
|
|
.stdout(predicate::str::contains("core"))
|
|
.stdout(predicate::str::contains("linux"));
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_pack_list_unauthenticated() {
|
|
let fixture = TestFixture::new().await;
|
|
fixture.write_default_config();
|
|
|
|
// Mock unauthorized response
|
|
mock_unauthorized(&fixture.mock_server, "/api/v1/packs").await;
|
|
|
|
let mut cmd = Command::cargo_bin("attune").unwrap();
|
|
cmd.env("XDG_CONFIG_HOME", fixture.config_dir_path())
|
|
.env("HOME", fixture.config_dir_path())
|
|
.arg("--api-url")
|
|
.arg(fixture.server_url())
|
|
.arg("pack")
|
|
.arg("list");
|
|
|
|
cmd.assert().failure();
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_pack_list_json_output() {
|
|
let fixture = TestFixture::new().await;
|
|
fixture.write_authenticated_config("valid_token", "refresh_token");
|
|
|
|
// Mock pack list endpoint
|
|
mock_pack_list(&fixture.mock_server).await;
|
|
|
|
let mut cmd = Command::cargo_bin("attune").unwrap();
|
|
cmd.env("XDG_CONFIG_HOME", fixture.config_dir_path())
|
|
.env("HOME", fixture.config_dir_path())
|
|
.arg("--api-url")
|
|
.arg(fixture.server_url())
|
|
.arg("--json")
|
|
.arg("pack")
|
|
.arg("list");
|
|
|
|
cmd.assert()
|
|
.success()
|
|
.stdout(predicate::str::contains(r#""ref": "core""#))
|
|
.stdout(predicate::str::contains(r#""ref": "linux""#));
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_pack_list_yaml_output() {
|
|
let fixture = TestFixture::new().await;
|
|
fixture.write_authenticated_config("valid_token", "refresh_token");
|
|
|
|
// Mock pack list endpoint
|
|
mock_pack_list(&fixture.mock_server).await;
|
|
|
|
let mut cmd = Command::cargo_bin("attune").unwrap();
|
|
cmd.env("XDG_CONFIG_HOME", fixture.config_dir_path())
|
|
.env("HOME", fixture.config_dir_path())
|
|
.arg("--api-url")
|
|
.arg(fixture.server_url())
|
|
.arg("--yaml")
|
|
.arg("pack")
|
|
.arg("list");
|
|
|
|
cmd.assert()
|
|
.success()
|
|
.stdout(predicate::str::contains("ref: core"))
|
|
.stdout(predicate::str::contains("ref: linux"));
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_pack_get_by_ref() {
|
|
let fixture = TestFixture::new().await;
|
|
fixture.write_authenticated_config("valid_token", "refresh_token");
|
|
|
|
// Mock pack get endpoint
|
|
mock_pack_get(&fixture.mock_server, "core").await;
|
|
|
|
let mut cmd = Command::cargo_bin("attune").unwrap();
|
|
cmd.env("XDG_CONFIG_HOME", fixture.config_dir_path())
|
|
.env("HOME", fixture.config_dir_path())
|
|
.arg("--api-url")
|
|
.arg(fixture.server_url())
|
|
.arg("pack")
|
|
.arg("show")
|
|
.arg("core");
|
|
|
|
cmd.assert()
|
|
.success()
|
|
.stdout(predicate::str::contains("core"))
|
|
.stdout(predicate::str::contains("core pack"));
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_pack_get_not_found() {
|
|
let fixture = TestFixture::new().await;
|
|
fixture.write_authenticated_config("valid_token", "refresh_token");
|
|
|
|
// Mock 404 response
|
|
mock_not_found(&fixture.mock_server, "/api/v1/packs/nonexistent").await;
|
|
|
|
let mut cmd = Command::cargo_bin("attune").unwrap();
|
|
cmd.env("XDG_CONFIG_HOME", fixture.config_dir_path())
|
|
.env("HOME", fixture.config_dir_path())
|
|
.arg("--api-url")
|
|
.arg(fixture.server_url())
|
|
.arg("pack")
|
|
.arg("show")
|
|
.arg("nonexistent");
|
|
|
|
cmd.assert()
|
|
.failure()
|
|
.stderr(predicate::str::contains("Error"));
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_pack_list_with_profile() {
|
|
let fixture = TestFixture::new().await;
|
|
|
|
// Create multi-profile config with authentication on default
|
|
let config = format!(
|
|
r#"
|
|
current_profile: staging
|
|
default_output_format: table
|
|
profiles:
|
|
default:
|
|
api_url: {}
|
|
auth_token: valid_token
|
|
refresh_token: refresh_token
|
|
description: Default server
|
|
staging:
|
|
api_url: {}
|
|
auth_token: staging_token
|
|
refresh_token: staging_refresh
|
|
description: Staging server
|
|
"#,
|
|
fixture.server_url(),
|
|
fixture.server_url()
|
|
);
|
|
fixture.write_config(&config);
|
|
|
|
// Mock pack list endpoint
|
|
mock_pack_list(&fixture.mock_server).await;
|
|
|
|
let mut cmd = Command::cargo_bin("attune").unwrap();
|
|
cmd.env("XDG_CONFIG_HOME", fixture.config_dir_path())
|
|
.env("HOME", fixture.config_dir_path())
|
|
.arg("--profile")
|
|
.arg("staging")
|
|
.arg("pack")
|
|
.arg("list");
|
|
|
|
cmd.assert().success();
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_pack_list_with_api_url_override() {
|
|
let fixture = TestFixture::new().await;
|
|
fixture.write_authenticated_config("valid_token", "refresh_token");
|
|
|
|
// Mock pack list endpoint
|
|
mock_pack_list(&fixture.mock_server).await;
|
|
|
|
let mut cmd = Command::cargo_bin("attune").unwrap();
|
|
cmd.env("XDG_CONFIG_HOME", fixture.config_dir_path())
|
|
.env("HOME", fixture.config_dir_path())
|
|
.arg("--api-url")
|
|
.arg(fixture.server_url())
|
|
.arg("pack")
|
|
.arg("list");
|
|
|
|
cmd.assert().success();
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_pack_get_json_output() {
|
|
let fixture = TestFixture::new().await;
|
|
fixture.write_authenticated_config("valid_token", "refresh_token");
|
|
|
|
// Mock pack get endpoint
|
|
mock_pack_get(&fixture.mock_server, "core").await;
|
|
|
|
let mut cmd = Command::cargo_bin("attune").unwrap();
|
|
cmd.env("XDG_CONFIG_HOME", fixture.config_dir_path())
|
|
.env("HOME", fixture.config_dir_path())
|
|
.arg("--api-url")
|
|
.arg(fixture.server_url())
|
|
.arg("-j")
|
|
.arg("pack")
|
|
.arg("show")
|
|
.arg("core");
|
|
|
|
cmd.assert()
|
|
.success()
|
|
.stdout(predicate::str::contains(r#""ref": "core""#));
|
|
}
|
|
|
|
// ── pack create tests ──────────────────────────────────────────────────
|
|
|
|
#[tokio::test]
|
|
async fn test_pack_create_non_interactive() {
|
|
let fixture = TestFixture::new().await;
|
|
fixture.write_authenticated_config("valid_token", "refresh_token");
|
|
|
|
mock_pack_create(&fixture.mock_server).await;
|
|
|
|
let mut cmd = Command::cargo_bin("attune").unwrap();
|
|
cmd.env("XDG_CONFIG_HOME", fixture.config_dir_path())
|
|
.env("HOME", fixture.config_dir_path())
|
|
.arg("--api-url")
|
|
.arg(fixture.server_url())
|
|
.arg("pack")
|
|
.arg("create")
|
|
.arg("--ref")
|
|
.arg("my_pack")
|
|
.arg("--label")
|
|
.arg("My Pack")
|
|
.arg("--description")
|
|
.arg("A test pack")
|
|
.arg("--pack-version")
|
|
.arg("0.1.0")
|
|
.arg("--tags")
|
|
.arg("test");
|
|
|
|
cmd.assert()
|
|
.success()
|
|
.stdout(predicate::str::contains("my_pack"))
|
|
.stdout(predicate::str::contains("created successfully"));
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_pack_create_json_output() {
|
|
let fixture = TestFixture::new().await;
|
|
fixture.write_authenticated_config("valid_token", "refresh_token");
|
|
|
|
mock_pack_create(&fixture.mock_server).await;
|
|
|
|
let mut cmd = Command::cargo_bin("attune").unwrap();
|
|
cmd.env("XDG_CONFIG_HOME", fixture.config_dir_path())
|
|
.env("HOME", fixture.config_dir_path())
|
|
.arg("--api-url")
|
|
.arg(fixture.server_url())
|
|
.arg("--json")
|
|
.arg("pack")
|
|
.arg("create")
|
|
.arg("--ref")
|
|
.arg("my_pack");
|
|
|
|
cmd.assert()
|
|
.success()
|
|
.stdout(predicate::str::contains(r#""ref": "my_pack""#))
|
|
.stdout(predicate::str::contains(r#""id": 42"#));
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_pack_create_conflict() {
|
|
let fixture = TestFixture::new().await;
|
|
fixture.write_authenticated_config("valid_token", "refresh_token");
|
|
|
|
mock_pack_create_conflict(&fixture.mock_server).await;
|
|
|
|
let mut cmd = Command::cargo_bin("attune").unwrap();
|
|
cmd.env("XDG_CONFIG_HOME", fixture.config_dir_path())
|
|
.env("HOME", fixture.config_dir_path())
|
|
.arg("--api-url")
|
|
.arg(fixture.server_url())
|
|
.arg("pack")
|
|
.arg("create")
|
|
.arg("--ref")
|
|
.arg("my_pack");
|
|
|
|
cmd.assert()
|
|
.failure()
|
|
.stderr(predicate::str::contains("already exists"));
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_pack_create_missing_ref() {
|
|
let fixture = TestFixture::new().await;
|
|
fixture.write_authenticated_config("valid_token", "refresh_token");
|
|
|
|
let mut cmd = Command::cargo_bin("attune").unwrap();
|
|
cmd.env("XDG_CONFIG_HOME", fixture.config_dir_path())
|
|
.env("HOME", fixture.config_dir_path())
|
|
.arg("--api-url")
|
|
.arg(fixture.server_url())
|
|
.arg("pack")
|
|
.arg("create");
|
|
|
|
cmd.assert()
|
|
.failure()
|
|
.stderr(predicate::str::contains("Pack ref is required"));
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_pack_create_default_label_from_ref() {
|
|
let fixture = TestFixture::new().await;
|
|
fixture.write_authenticated_config("valid_token", "refresh_token");
|
|
|
|
// Use a custom mock that validates the request body contains the derived label
|
|
Mock::given(method("POST"))
|
|
.and(path("/api/v1/packs"))
|
|
.and(body_json(json!({
|
|
"ref": "my_cool_pack",
|
|
"label": "My Cool Pack",
|
|
"version": "0.1.0",
|
|
"tags": []
|
|
})))
|
|
.respond_with(ResponseTemplate::new(201).set_body_json(json!({
|
|
"data": {
|
|
"id": 99,
|
|
"ref": "my_cool_pack",
|
|
"label": "My Cool Pack",
|
|
"version": "0.1.0",
|
|
"enabled": true,
|
|
"created": "2024-01-01T00:00:00Z",
|
|
"updated": "2024-01-01T00:00:00Z"
|
|
}
|
|
})))
|
|
.mount(&fixture.mock_server)
|
|
.await;
|
|
|
|
let mut cmd = Command::cargo_bin("attune").unwrap();
|
|
cmd.env("XDG_CONFIG_HOME", fixture.config_dir_path())
|
|
.env("HOME", fixture.config_dir_path())
|
|
.arg("--api-url")
|
|
.arg(fixture.server_url())
|
|
.arg("pack")
|
|
.arg("create")
|
|
.arg("--ref")
|
|
.arg("my_cool_pack");
|
|
|
|
cmd.assert()
|
|
.success()
|
|
.stdout(predicate::str::contains("my_cool_pack"))
|
|
.stdout(predicate::str::contains("created successfully"));
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_pack_create_default_version() {
|
|
let fixture = TestFixture::new().await;
|
|
fixture.write_authenticated_config("valid_token", "refresh_token");
|
|
|
|
// Verify the default version "0.1.0" is sent when --pack-version is not specified
|
|
Mock::given(method("POST"))
|
|
.and(path("/api/v1/packs"))
|
|
.and(body_json(json!({
|
|
"ref": "versioned_pack",
|
|
"label": "Versioned Pack",
|
|
"version": "0.1.0",
|
|
"tags": []
|
|
})))
|
|
.respond_with(ResponseTemplate::new(201).set_body_json(json!({
|
|
"data": {
|
|
"id": 7,
|
|
"ref": "versioned_pack",
|
|
"label": "Versioned Pack",
|
|
"version": "0.1.0",
|
|
"enabled": true,
|
|
"created": "2024-01-01T00:00:00Z",
|
|
"updated": "2024-01-01T00:00:00Z"
|
|
}
|
|
})))
|
|
.mount(&fixture.mock_server)
|
|
.await;
|
|
|
|
let mut cmd = Command::cargo_bin("attune").unwrap();
|
|
cmd.env("XDG_CONFIG_HOME", fixture.config_dir_path())
|
|
.env("HOME", fixture.config_dir_path())
|
|
.arg("--api-url")
|
|
.arg(fixture.server_url())
|
|
.arg("pack")
|
|
.arg("create")
|
|
.arg("--ref")
|
|
.arg("versioned_pack");
|
|
|
|
cmd.assert().success();
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_pack_create_with_tags() {
|
|
let fixture = TestFixture::new().await;
|
|
fixture.write_authenticated_config("valid_token", "refresh_token");
|
|
|
|
Mock::given(method("POST"))
|
|
.and(path("/api/v1/packs"))
|
|
.and(body_json(json!({
|
|
"ref": "tagged",
|
|
"label": "Tagged",
|
|
"version": "0.1.0",
|
|
"tags": ["networking", "monitoring"]
|
|
})))
|
|
.respond_with(ResponseTemplate::new(201).set_body_json(json!({
|
|
"data": {
|
|
"id": 10,
|
|
"ref": "tagged",
|
|
"label": "Tagged",
|
|
"version": "0.1.0",
|
|
"tags": ["networking", "monitoring"],
|
|
"enabled": true,
|
|
"created": "2024-01-01T00:00:00Z",
|
|
"updated": "2024-01-01T00:00:00Z"
|
|
}
|
|
})))
|
|
.mount(&fixture.mock_server)
|
|
.await;
|
|
|
|
let mut cmd = Command::cargo_bin("attune").unwrap();
|
|
cmd.env("XDG_CONFIG_HOME", fixture.config_dir_path())
|
|
.env("HOME", fixture.config_dir_path())
|
|
.arg("--api-url")
|
|
.arg(fixture.server_url())
|
|
.arg("pack")
|
|
.arg("create")
|
|
.arg("--ref")
|
|
.arg("tagged")
|
|
.arg("--tags")
|
|
.arg("networking,monitoring");
|
|
|
|
cmd.assert().success();
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_pack_list_empty_result() {
|
|
let fixture = TestFixture::new().await;
|
|
fixture.write_authenticated_config("valid_token", "refresh_token");
|
|
|
|
// Mock empty pack list
|
|
use serde_json::json;
|
|
use wiremock::{
|
|
matchers::{method, path},
|
|
Mock, ResponseTemplate,
|
|
};
|
|
|
|
Mock::given(method("GET"))
|
|
.and(path("/api/v1/packs"))
|
|
.respond_with(ResponseTemplate::new(200).set_body_json(json!({
|
|
"data": []
|
|
})))
|
|
.mount(&fixture.mock_server)
|
|
.await;
|
|
|
|
let mut cmd = Command::cargo_bin("attune").unwrap();
|
|
cmd.env("XDG_CONFIG_HOME", fixture.config_dir_path())
|
|
.env("HOME", fixture.config_dir_path())
|
|
.arg("--api-url")
|
|
.arg(fixture.server_url())
|
|
.arg("pack")
|
|
.arg("list");
|
|
|
|
cmd.assert().success();
|
|
}
|