Public Access
initial-commit
This commit is contained in:
@@ -0,0 +1,607 @@
|
||||
//! Integration tests for DefectDojo plugin using wiremock
|
||||
//!
|
||||
//! These tests require a running PostgreSQL instance.
|
||||
//! Set DATABASE_URL environment variable to run them.
|
||||
//! They are ignored by default in CI unless DATABASE_URL is set.
|
||||
|
||||
use charybdis::charybdis::entities::entity::{Metadata, Spec};
|
||||
use charybdis::charybdis::entities::Entity;
|
||||
use charybdis::database::{ensure_schema, EntityRepository};
|
||||
use charybdis::plugins::ResourceHandler;
|
||||
use charybdis_defectdojo::{DefectDojoClient, DefectDojoConfig, EngagementConfig, OwnerResolutionConfig};
|
||||
use serde_json::json;
|
||||
use sqlx::PgPool;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use wiremock::matchers::{method, path, query_param};
|
||||
use wiremock::{Mock, MockServer, ResponseTemplate};
|
||||
|
||||
async fn setup_db() -> PgPool {
|
||||
let url = std::env::var("DATABASE_URL")
|
||||
.expect("DATABASE_URL must be set for integration tests");
|
||||
let pool = PgPool::connect(&url).await.expect("Failed to connect to test database");
|
||||
ensure_schema(&pool).await.expect("Failed to create schema");
|
||||
|
||||
// Clean up from previous test runs
|
||||
sqlx::query("DELETE FROM entities")
|
||||
.execute(&pool)
|
||||
.await
|
||||
.expect("Failed to clean entities table");
|
||||
|
||||
pool
|
||||
}
|
||||
|
||||
fn make_component_entity(id: &str, name: &str, owner: &str) -> Entity {
|
||||
Entity {
|
||||
id: id.to_string(),
|
||||
kind: "Component".to_string(),
|
||||
annotations: HashMap::new(),
|
||||
created_at: None,
|
||||
updated_at: None,
|
||||
metadata: Some(Metadata::ComponentMetadata(
|
||||
charybdis::charybdis::core::ComponentMetadata {
|
||||
name: name.to_string(),
|
||||
namespace: "default".to_string(),
|
||||
description: format!("{} service", name),
|
||||
labels: HashMap::new(),
|
||||
tags: vec![],
|
||||
links: vec![],
|
||||
},
|
||||
)),
|
||||
spec: Some(Spec::ComponentSpec(
|
||||
charybdis::charybdis::core::ComponentSpec {
|
||||
r#type: "service".to_string(),
|
||||
lifecycle: "production".to_string(),
|
||||
owner: owner.to_string(),
|
||||
system: String::new(),
|
||||
subcomponent_of: String::new(),
|
||||
depends_on: vec![],
|
||||
provides_apis: vec![],
|
||||
consumes_apis: vec![],
|
||||
},
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
fn make_config(base_url: &str) -> DefectDojoConfig {
|
||||
DefectDojoConfig {
|
||||
base_url: base_url.to_string(),
|
||||
api_token: "test-token".to_string(),
|
||||
default_product_type_id: Some(1),
|
||||
auto_create_users: false,
|
||||
auto_create_product_types: false,
|
||||
default_engagement: EngagementConfig::default(),
|
||||
owner_resolution: OwnerResolutionConfig::default(),
|
||||
field_mappings: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────────────────────
|
||||
// Product creation
|
||||
// ──────────────────────────────────────────────────────────────
|
||||
|
||||
#[tokio::test]
|
||||
#[ignore] // Requires DATABASE_URL
|
||||
async fn test_product_creation_on_component_create() {
|
||||
let pool = setup_db().await;
|
||||
let repository = Arc::new(EntityRepository::new(pool.clone()));
|
||||
let mock_server = MockServer::start().await;
|
||||
|
||||
// Mock: POST /api/v2/products/ → returns product with id=42
|
||||
Mock::given(method("POST"))
|
||||
.and(path("/api/v2/products/"))
|
||||
.respond_with(ResponseTemplate::new(201).set_body_json(json!({
|
||||
"id": 42,
|
||||
"name": "payment-api",
|
||||
"description": "payment-api service",
|
||||
"prod_type": 1
|
||||
})))
|
||||
.expect(1)
|
||||
.mount(&mock_server)
|
||||
.await;
|
||||
|
||||
// Mock: POST /api/v2/engagements/ → returns engagement with id=100
|
||||
Mock::given(method("POST"))
|
||||
.and(path("/api/v2/engagements/"))
|
||||
.respond_with(ResponseTemplate::new(201).set_body_json(json!({
|
||||
"id": 100,
|
||||
"name": "CI/CD Scans",
|
||||
"product": 42
|
||||
})))
|
||||
.expect(1)
|
||||
.mount(&mock_server)
|
||||
.await;
|
||||
|
||||
let mut config = make_config(&mock_server.uri());
|
||||
config.default_engagement.auto_create = true;
|
||||
// Disable owner resolution for this test (no owner group exists)
|
||||
config.owner_resolution.assign_all_members = false;
|
||||
|
||||
let client = DefectDojoClient::new(mock_server.uri(), "test-token".to_string()).unwrap();
|
||||
let engagement_handler = Arc::new(
|
||||
charybdis_defectdojo::handlers::EngagementHandler::new(
|
||||
client.clone(),
|
||||
repository.clone(),
|
||||
HashMap::new(),
|
||||
),
|
||||
);
|
||||
|
||||
let handler = charybdis_defectdojo::handlers::ProductHandler::new(
|
||||
client,
|
||||
repository.clone(),
|
||||
HashMap::new(),
|
||||
config,
|
||||
engagement_handler,
|
||||
);
|
||||
|
||||
// Create the entity in the database first (returns entity with real UUID)
|
||||
let entity = make_component_entity("", "payment-api", "team-payments");
|
||||
let entity = repository.create(&entity).await.expect("Failed to create entity");
|
||||
|
||||
// Trigger handler
|
||||
let result = handler.handle_create(&entity).await;
|
||||
assert!(result.is_ok(), "handle_create failed: {:?}", result.err());
|
||||
|
||||
// Verify annotations were saved
|
||||
let updated = repository.get_by_id(&entity.id).await.unwrap().unwrap();
|
||||
assert_eq!(
|
||||
updated.annotations.get("defectdojo.com/product-id"),
|
||||
Some(&"42".to_string())
|
||||
);
|
||||
assert_eq!(
|
||||
updated.annotations.get("defectdojo.com/engagement-id"),
|
||||
Some(&"100".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────────────────────
|
||||
// Product update
|
||||
// ──────────────────────────────────────────────────────────────
|
||||
|
||||
#[tokio::test]
|
||||
#[ignore] // Requires DATABASE_URL
|
||||
async fn test_product_update_with_existing_product_id() {
|
||||
let pool = setup_db().await;
|
||||
let repository = Arc::new(EntityRepository::new(pool.clone()));
|
||||
let mock_server = MockServer::start().await;
|
||||
|
||||
// Mock: PUT /api/v2/products/42/ → success
|
||||
Mock::given(method("PUT"))
|
||||
.and(path("/api/v2/products/42/"))
|
||||
.respond_with(ResponseTemplate::new(200).set_body_json(json!({
|
||||
"id": 42,
|
||||
"name": "payment-api-updated"
|
||||
})))
|
||||
.expect(1)
|
||||
.mount(&mock_server)
|
||||
.await;
|
||||
|
||||
let config = make_config(&mock_server.uri());
|
||||
let client = DefectDojoClient::new(mock_server.uri(), "test-token".to_string()).unwrap();
|
||||
let engagement_handler = Arc::new(
|
||||
charybdis_defectdojo::handlers::EngagementHandler::new(
|
||||
client.clone(),
|
||||
repository.clone(),
|
||||
HashMap::new(),
|
||||
),
|
||||
);
|
||||
|
||||
let handler = charybdis_defectdojo::handlers::ProductHandler::new(
|
||||
client,
|
||||
repository.clone(),
|
||||
HashMap::new(),
|
||||
config,
|
||||
engagement_handler,
|
||||
);
|
||||
|
||||
// Create entity with existing product-id annotation
|
||||
let mut entity = make_component_entity("", "payment-api", "team-payments");
|
||||
entity.annotations.insert(
|
||||
"defectdojo.com/product-id".to_string(),
|
||||
"42".to_string(),
|
||||
);
|
||||
let entity = repository.create(&entity).await.expect("Failed to create entity");
|
||||
|
||||
// Trigger update handler
|
||||
let result = handler.handle_update(&entity).await;
|
||||
assert!(result.is_ok(), "handle_update failed: {:?}", result.err());
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────────────────────
|
||||
// Product deletion
|
||||
// ──────────────────────────────────────────────────────────────
|
||||
|
||||
#[tokio::test]
|
||||
#[ignore] // Requires DATABASE_URL
|
||||
async fn test_product_deletion() {
|
||||
let pool = setup_db().await;
|
||||
let repository = Arc::new(EntityRepository::new(pool.clone()));
|
||||
let mock_server = MockServer::start().await;
|
||||
|
||||
// Mock: DELETE /api/v2/products/42/ → 204 No Content
|
||||
Mock::given(method("DELETE"))
|
||||
.and(path("/api/v2/products/42/"))
|
||||
.respond_with(ResponseTemplate::new(204))
|
||||
.expect(1)
|
||||
.mount(&mock_server)
|
||||
.await;
|
||||
|
||||
let config = make_config(&mock_server.uri());
|
||||
let client = DefectDojoClient::new(mock_server.uri(), "test-token".to_string()).unwrap();
|
||||
let engagement_handler = Arc::new(
|
||||
charybdis_defectdojo::handlers::EngagementHandler::new(
|
||||
client.clone(),
|
||||
repository.clone(),
|
||||
HashMap::new(),
|
||||
),
|
||||
);
|
||||
|
||||
let handler = charybdis_defectdojo::handlers::ProductHandler::new(
|
||||
client,
|
||||
repository.clone(),
|
||||
HashMap::new(),
|
||||
config,
|
||||
engagement_handler,
|
||||
);
|
||||
|
||||
// Entity with product-id annotation
|
||||
let mut entity = make_component_entity("", "payment-api", "team-payments");
|
||||
entity.annotations.insert(
|
||||
"defectdojo.com/product-id".to_string(),
|
||||
"42".to_string(),
|
||||
);
|
||||
let entity = repository.create(&entity).await.expect("Failed to create entity");
|
||||
|
||||
// Trigger delete handler
|
||||
let result = handler.handle_delete(&entity).await;
|
||||
assert!(result.is_ok(), "handle_delete failed: {:?}", result.err());
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────────────────────
|
||||
// Owner resolution with product member assignment
|
||||
// ──────────────────────────────────────────────────────────────
|
||||
|
||||
#[tokio::test]
|
||||
#[ignore] // Requires DATABASE_URL
|
||||
async fn test_owner_resolution_assigns_product_members() {
|
||||
let pool = setup_db().await;
|
||||
let repository = Arc::new(EntityRepository::new(pool.clone()));
|
||||
let mock_server = MockServer::start().await;
|
||||
|
||||
// Mock: POST /api/v2/products/ → product id=10
|
||||
Mock::given(method("POST"))
|
||||
.and(path("/api/v2/products/"))
|
||||
.respond_with(ResponseTemplate::new(201).set_body_json(json!({
|
||||
"id": 10,
|
||||
"name": "orders-api",
|
||||
"prod_type": 1
|
||||
})))
|
||||
.expect(1)
|
||||
.mount(&mock_server)
|
||||
.await;
|
||||
|
||||
// Mock: POST /api/v2/engagements/ → engagement id=20
|
||||
Mock::given(method("POST"))
|
||||
.and(path("/api/v2/engagements/"))
|
||||
.respond_with(ResponseTemplate::new(201).set_body_json(json!({
|
||||
"id": 20,
|
||||
"name": "CI/CD Scans",
|
||||
"product": 10
|
||||
})))
|
||||
.expect(1)
|
||||
.mount(&mock_server)
|
||||
.await;
|
||||
|
||||
// Mock: GET /api/v2/users/?email=alice@example.com → found user id=5
|
||||
Mock::given(method("GET"))
|
||||
.and(path("/api/v2/users/"))
|
||||
.and(query_param("email", "alice@example.com"))
|
||||
.respond_with(ResponseTemplate::new(200).set_body_json(json!({
|
||||
"count": 1,
|
||||
"results": [{"id": 5, "username": "alice@example.com"}]
|
||||
})))
|
||||
.expect(1)
|
||||
.mount(&mock_server)
|
||||
.await;
|
||||
|
||||
// Mock: GET /api/v2/users/?email=bob@example.com → found user id=7
|
||||
Mock::given(method("GET"))
|
||||
.and(path("/api/v2/users/"))
|
||||
.and(query_param("email", "bob@example.com"))
|
||||
.respond_with(ResponseTemplate::new(200).set_body_json(json!({
|
||||
"count": 1,
|
||||
"results": [{"id": 7, "username": "bob@example.com"}]
|
||||
})))
|
||||
.expect(1)
|
||||
.mount(&mock_server)
|
||||
.await;
|
||||
|
||||
// Mock: GET /api/v2/roles/?name=Owner → role id=4
|
||||
Mock::given(method("GET"))
|
||||
.and(path("/api/v2/roles/"))
|
||||
.and(query_param("name", "Owner"))
|
||||
.respond_with(ResponseTemplate::new(200).set_body_json(json!({
|
||||
"count": 1,
|
||||
"results": [{"id": 4, "name": "Owner"}]
|
||||
})))
|
||||
.expect(1)
|
||||
.mount(&mock_server)
|
||||
.await;
|
||||
|
||||
// Mock: GET /api/v2/product_members/?product=10&user=5 → not yet a member
|
||||
Mock::given(method("GET"))
|
||||
.and(path("/api/v2/product_members/"))
|
||||
.and(query_param("product", "10"))
|
||||
.and(query_param("user", "5"))
|
||||
.respond_with(ResponseTemplate::new(200).set_body_json(json!({
|
||||
"count": 0,
|
||||
"results": []
|
||||
})))
|
||||
.expect(1)
|
||||
.mount(&mock_server)
|
||||
.await;
|
||||
|
||||
// Mock: GET /api/v2/product_members/?product=10&user=7 → not yet a member
|
||||
Mock::given(method("GET"))
|
||||
.and(path("/api/v2/product_members/"))
|
||||
.and(query_param("product", "10"))
|
||||
.and(query_param("user", "7"))
|
||||
.respond_with(ResponseTemplate::new(200).set_body_json(json!({
|
||||
"count": 0,
|
||||
"results": []
|
||||
})))
|
||||
.expect(1)
|
||||
.mount(&mock_server)
|
||||
.await;
|
||||
|
||||
// Mock: POST /api/v2/product_members/ → member created (called twice)
|
||||
Mock::given(method("POST"))
|
||||
.and(path("/api/v2/product_members/"))
|
||||
.respond_with(ResponseTemplate::new(201).set_body_json(json!({
|
||||
"id": 99,
|
||||
"product": 10,
|
||||
"user": 5,
|
||||
"role": 4
|
||||
})))
|
||||
.expect(2)
|
||||
.mount(&mock_server)
|
||||
.await;
|
||||
|
||||
// Set up config with owner resolution enabled
|
||||
let mut config = make_config(&mock_server.uri());
|
||||
config.default_engagement.auto_create = true;
|
||||
config.owner_resolution.user_email_annotation = "keycloak.com/email".to_string();
|
||||
config.owner_resolution.defectdojo_lookup_field = "email".to_string();
|
||||
config.owner_resolution.assign_all_members = true;
|
||||
|
||||
// Create Group "backend-team" with members alice and bob
|
||||
let group_entity = Entity {
|
||||
id: "group-backend".to_string(),
|
||||
kind: "Group".to_string(),
|
||||
annotations: HashMap::new(),
|
||||
created_at: None,
|
||||
updated_at: None,
|
||||
metadata: Some(Metadata::GroupMetadata(
|
||||
charybdis::charybdis::core::GroupMetadata {
|
||||
name: "backend-team".to_string(),
|
||||
namespace: "default".to_string(),
|
||||
description: "Backend team".to_string(),
|
||||
labels: HashMap::new(),
|
||||
tags: vec![],
|
||||
links: vec![],
|
||||
},
|
||||
)),
|
||||
spec: Some(Spec::GroupSpec(charybdis::charybdis::core::GroupSpec {
|
||||
r#type: "team".to_string(),
|
||||
profile: None,
|
||||
parent: String::new(),
|
||||
children: vec![],
|
||||
members: vec!["alice".to_string(), "bob".to_string()],
|
||||
})),
|
||||
};
|
||||
repository.create(&group_entity).await.unwrap();
|
||||
|
||||
// Create User "alice" with keycloak email annotation
|
||||
let mut alice = Entity {
|
||||
id: "user-alice".to_string(),
|
||||
kind: "User".to_string(),
|
||||
annotations: HashMap::new(),
|
||||
created_at: None,
|
||||
updated_at: None,
|
||||
metadata: Some(Metadata::UserMetadata(
|
||||
charybdis::charybdis::core::UserMetadata {
|
||||
name: "alice".to_string(),
|
||||
namespace: "default".to_string(),
|
||||
description: "Alice".to_string(),
|
||||
labels: HashMap::new(),
|
||||
tags: vec![],
|
||||
links: vec![],
|
||||
},
|
||||
)),
|
||||
spec: Some(Spec::UserSpec(charybdis::charybdis::core::UserSpec {
|
||||
profile: None,
|
||||
member_of: vec!["backend-team".to_string()],
|
||||
})),
|
||||
};
|
||||
alice.annotations.insert("keycloak.com/email".to_string(), "alice@example.com".to_string());
|
||||
repository.create(&alice).await.unwrap();
|
||||
|
||||
// Create User "bob" with keycloak email annotation
|
||||
let mut bob = Entity {
|
||||
id: "user-bob".to_string(),
|
||||
kind: "User".to_string(),
|
||||
annotations: HashMap::new(),
|
||||
created_at: None,
|
||||
updated_at: None,
|
||||
metadata: Some(Metadata::UserMetadata(
|
||||
charybdis::charybdis::core::UserMetadata {
|
||||
name: "bob".to_string(),
|
||||
namespace: "default".to_string(),
|
||||
description: "Bob".to_string(),
|
||||
labels: HashMap::new(),
|
||||
tags: vec![],
|
||||
links: vec![],
|
||||
},
|
||||
)),
|
||||
spec: Some(Spec::UserSpec(charybdis::charybdis::core::UserSpec {
|
||||
profile: None,
|
||||
member_of: vec!["backend-team".to_string()],
|
||||
})),
|
||||
};
|
||||
bob.annotations.insert("keycloak.com/email".to_string(), "bob@example.com".to_string());
|
||||
repository.create(&bob).await.unwrap();
|
||||
|
||||
// Create handlers
|
||||
let client = DefectDojoClient::new(mock_server.uri(), "test-token".to_string()).unwrap();
|
||||
let engagement_handler = Arc::new(
|
||||
charybdis_defectdojo::handlers::EngagementHandler::new(
|
||||
client.clone(),
|
||||
repository.clone(),
|
||||
HashMap::new(),
|
||||
),
|
||||
);
|
||||
|
||||
let handler = charybdis_defectdojo::handlers::ProductHandler::new(
|
||||
client,
|
||||
repository.clone(),
|
||||
HashMap::new(),
|
||||
config,
|
||||
engagement_handler,
|
||||
);
|
||||
|
||||
// Create component owned by "backend-team"
|
||||
let component = make_component_entity("", "orders-api", "backend-team");
|
||||
let component = repository.create(&component).await.unwrap();
|
||||
|
||||
// Trigger handler
|
||||
let result = handler.handle_create(&component).await;
|
||||
assert!(result.is_ok(), "handle_create failed: {:?}", result.err());
|
||||
|
||||
// Verify annotations
|
||||
let updated = repository.get_by_id(&component.id).await.unwrap().unwrap();
|
||||
assert_eq!(
|
||||
updated.annotations.get("defectdojo.com/product-id"),
|
||||
Some(&"10".to_string())
|
||||
);
|
||||
assert_eq!(
|
||||
updated.annotations.get("defectdojo.com/engagement-id"),
|
||||
Some(&"20".to_string())
|
||||
);
|
||||
// Owner member IDs should be set
|
||||
assert!(
|
||||
updated.annotations.contains_key("defectdojo.com/owner-member-ids"),
|
||||
"Expected owner-member-ids annotation"
|
||||
);
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────────────────────
|
||||
// Engagement auto-creation disabled
|
||||
// ──────────────────────────────────────────────────────────────
|
||||
|
||||
#[tokio::test]
|
||||
#[ignore] // Requires DATABASE_URL
|
||||
async fn test_product_creation_without_engagement() {
|
||||
let pool = setup_db().await;
|
||||
let repository = Arc::new(EntityRepository::new(pool.clone()));
|
||||
let mock_server = MockServer::start().await;
|
||||
|
||||
// Mock: POST /api/v2/products/ → product id=55
|
||||
Mock::given(method("POST"))
|
||||
.and(path("/api/v2/products/"))
|
||||
.respond_with(ResponseTemplate::new(201).set_body_json(json!({
|
||||
"id": 55,
|
||||
"name": "simple-service",
|
||||
"prod_type": 1
|
||||
})))
|
||||
.expect(1)
|
||||
.mount(&mock_server)
|
||||
.await;
|
||||
|
||||
// No engagement mock — should NOT be called
|
||||
Mock::given(method("POST"))
|
||||
.and(path("/api/v2/engagements/"))
|
||||
.respond_with(ResponseTemplate::new(201).set_body_json(json!({"id": 999})))
|
||||
.expect(0) // MUST NOT be called
|
||||
.mount(&mock_server)
|
||||
.await;
|
||||
|
||||
let mut config = make_config(&mock_server.uri());
|
||||
config.default_engagement.auto_create = false;
|
||||
|
||||
let client = DefectDojoClient::new(mock_server.uri(), "test-token".to_string()).unwrap();
|
||||
let engagement_handler = Arc::new(
|
||||
charybdis_defectdojo::handlers::EngagementHandler::new(
|
||||
client.clone(),
|
||||
repository.clone(),
|
||||
HashMap::new(),
|
||||
),
|
||||
);
|
||||
|
||||
let handler = charybdis_defectdojo::handlers::ProductHandler::new(
|
||||
client,
|
||||
repository.clone(),
|
||||
HashMap::new(),
|
||||
config,
|
||||
engagement_handler,
|
||||
);
|
||||
|
||||
let entity = make_component_entity("", "simple-service", "");
|
||||
let entity = repository.create(&entity).await.unwrap();
|
||||
|
||||
let result = handler.handle_create(&entity).await;
|
||||
assert!(result.is_ok(), "handle_create failed: {:?}", result.err());
|
||||
|
||||
// Verify only product-id annotation (no engagement-id)
|
||||
let updated = repository.get_by_id(&entity.id).await.unwrap().unwrap();
|
||||
assert_eq!(
|
||||
updated.annotations.get("defectdojo.com/product-id"),
|
||||
Some(&"55".to_string())
|
||||
);
|
||||
assert!(!updated.annotations.contains_key("defectdojo.com/engagement-id"));
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────────────────────
|
||||
// DefectDojo API error handling
|
||||
// ──────────────────────────────────────────────────────────────
|
||||
|
||||
#[tokio::test]
|
||||
#[ignore] // Requires DATABASE_URL
|
||||
async fn test_product_creation_handles_api_error() {
|
||||
let pool = setup_db().await;
|
||||
let repository = Arc::new(EntityRepository::new(pool.clone()));
|
||||
let mock_server = MockServer::start().await;
|
||||
|
||||
// Mock: POST /api/v2/products/ → 400 Bad Request
|
||||
Mock::given(method("POST"))
|
||||
.and(path("/api/v2/products/"))
|
||||
.respond_with(
|
||||
ResponseTemplate::new(400)
|
||||
.set_body_json(json!({"name": ["This field may not be blank."]})),
|
||||
)
|
||||
.mount(&mock_server)
|
||||
.await;
|
||||
|
||||
let config = make_config(&mock_server.uri());
|
||||
let client = DefectDojoClient::new(mock_server.uri(), "test-token".to_string()).unwrap();
|
||||
let engagement_handler = Arc::new(
|
||||
charybdis_defectdojo::handlers::EngagementHandler::new(
|
||||
client.clone(),
|
||||
repository.clone(),
|
||||
HashMap::new(),
|
||||
),
|
||||
);
|
||||
|
||||
let handler = charybdis_defectdojo::handlers::ProductHandler::new(
|
||||
client,
|
||||
repository.clone(),
|
||||
HashMap::new(),
|
||||
config,
|
||||
engagement_handler,
|
||||
);
|
||||
|
||||
let entity = make_component_entity("", "bad-entity", "team-x");
|
||||
let entity = repository.create(&entity).await.unwrap();
|
||||
|
||||
let result = handler.handle_create(&entity).await;
|
||||
assert!(result.is_err(), "Expected error on 400 response");
|
||||
}
|
||||
Reference in New Issue
Block a user