Files
imphnen-backend-service/tests/src/hackathon/hackathon_controller_test.rs
T

808 lines
37 KiB
Rust
Raw Normal View History

#[cfg(test)]
mod tests {
use crate::{generate_unique_email, get_role_id, UsersRepository};
use axum::http::StatusCode;
use imphnen_hackathon::v1::hackathon::hackathon_dto::{
HackathonCreateRequestDto, HackathonSubmissionCreateRequestDto,
};
use imphnen_hackathon::v1::hackathon::HackathonRepository;
use imphnen_iam::v1::teams::teams_dto::{TeamsCreateRequestDto};
use imphnen_iam::v1::teams::teams_repository::TeamsRepository;
use imphnen_iam::v1::teams::teams_schema::TeamMembersSchema;
use chrono::{Utc, Duration};
use serde_json::json;
#[tokio::test]
async fn test_create_hackathon() {
let app = crate::get_full_test_app().await;
let users_repo = UsersRepository::new(&app.state);
// Create test organizer
let email = generate_unique_email("hackathon_organizer_controller");
let role_id = get_role_id("mentor", &app.state).await;
let user_data = crate::create_test_user(&email, "password123", true, &role_id);
let user_result = users_repo.query_create_user(user_data.clone()).await;
assert!(user_result.is_ok(), "Failed to create test user");
let user = users_repo.query_user_by_email(email.clone()).await.unwrap();
// Create hackathon request
let hackathon_request = HackathonCreateRequestDto {
name: "Test Hackathon Controller".to_string(),
description: "Hackathon created via controller test".to_string(),
start_date: Utc::now() + Duration::days(7),
end_date: Utc::now() + Duration::days(14),
registration_deadline: Utc::now() + Duration::days(10),
max_participants: None,
theme: None,
rules: None,
prizes: None,
previous_winners: None,
organizers: vec![user.id.id.to_raw()],
};
// Send create request
let response = app.service.post("/api/v1/hackathons")
.header("Authorization", format!("Bearer {}", crate::get_test_token(&user.id.id.to_raw()).await))
.json(&hackathon_request)
.await
.unwrap();
// For debugging: capture status then extract body so we can print server error details
let status = response.status();
let body = crate::get_response_body(response).await;
eprintln!("[DEBUG] create_hackathon status: {}", status);
eprintln!("[DEBUG] create_hackathon body: {}", body);
// Verify response
assert_eq!(status, StatusCode::CREATED);
assert_eq!(body["message"], "Success create hackathon");
assert_eq!(body["data"]["name"], "Test Hackathon Controller");
assert_eq!(body["data"]["description"], "Hackathon created via controller test");
// Clean up
let hackathon_id = body["data"]["id"].as_str().unwrap().to_string();
let repo = HackathonRepository::new(&app.state);
let _ = repo.delete_hackathon(hackathon_id).await;
let _ = users_repo.query_delete_user(user.id.id.to_raw()).await;
}
#[tokio::test]
async fn test_get_hackathon_by_id() {
let app = crate::get_full_test_app().await;
let users_repo = UsersRepository::new(&app.state);
let repo = HackathonRepository::new(&app.state);
// Create test organizer and hackathon
let email = generate_unique_email("hackathon_get_controller");
let role_id = get_role_id("mentor", &app.state).await;
let user_data = crate::create_test_user(&email, "password123", true, &role_id);
let user_result = users_repo.query_create_user(user_data.clone()).await;
assert!(user_result.is_ok(), "Failed to create test user");
let user = users_repo.query_user_by_email(email.clone()).await.unwrap();
let hackathon_request = HackathonCreateRequestDto {
name: "Get Hackathon Test".to_string(),
description: "Test hackathon for get by ID".to_string(),
start_date: Utc::now() + Duration::days(7),
end_date: Utc::now() + Duration::days(14),
registration_deadline: Utc::now() + Duration::days(10),
max_participants: None,
theme: None,
rules: None,
prizes: None,
previous_winners: None,
organizers: vec![user.id.id.to_raw()],
};
let created = repo.create_hackathon(hackathon_request.clone()).await.expect("Failed to create hackathon");
let hackathon_id = created.id.id.to_raw();
// Send get request
let response = app.service.get(format!("/api/v1/hackathons/{}", hackathon_id))
.await
.unwrap();
// Verify response
assert_eq!(response.status(), StatusCode::OK);
let body = crate::get_response_body(response).await;
assert_eq!(body["data"]["name"], "Get Hackathon Test");
assert_eq!(body["data"]["description"], "Test hackathon for get by ID");
// Clean up
let _ = repo.delete_hackathon(hackathon_id).await;
let _ = users_repo.query_delete_user(user.id.id.to_raw()).await;
}
#[tokio::test]
async fn test_update_hackathon() {
let app = crate::get_full_test_app().await;
let users_repo = UsersRepository::new(&app.state);
let repo = HackathonRepository::new(&app.state);
// Create test organizer and hackathon
let email = generate_unique_email("hackathon_update_controller");
let role_id = get_role_id("mentor", &app.state).await;
let user_data = crate::create_test_user(&email, "password123", true, &role_id);
let user_result = users_repo.query_create_user(user_data.clone()).await;
assert!(user_result.is_ok(), "Failed to create test user");
let user = users_repo.query_user_by_email(email.clone()).await.unwrap();
let hackathon_request = HackathonCreateRequestDto {
name: "Original Hackathon Controller".to_string(),
description: "Original description".to_string(),
start_date: Utc::now() + Duration::days(7),
end_date: Utc::now() + Duration::days(14),
registration_deadline: Utc::now() + Duration::days(10),
max_participants: None,
theme: None,
rules: None,
prizes: None,
previous_winners: None,
organizers: vec![user.id.id.to_raw()],
};
let create_result = repo.create_hackathon(hackathon_request.clone()).await.expect("Failed to create hackathon");
let hackathon_id = create_result.id.id.to_raw();
// Prepare update payload using the public update DTO
let update_payload = imphnen_hackathon::v1::hackathon::hackathon_dto::HackathonUpdateRequestDto {
name: Some("Updated Hackathon Controller".to_string()),
description: Some("Updated description via controller".to_string()),
start_date: None,
end_date: None,
registration_deadline: None,
max_participants: None,
theme: None,
rules: None,
prizes: None,
previous_winners: None,
organizers: None,
};
// Send update request
let response = app.service.put(format!("/api/v1/hackathons/{}", hackathon_id))
.header("Authorization", format!("Bearer {}", crate::get_test_token(&user.id.id.to_raw()).await))
.json(&update_payload)
.await
.unwrap();
// Verify response
assert_eq!(response.status(), StatusCode::OK);
let body = crate::get_response_body(response).await;
assert_eq!(body["message"], "Success update hackathon");
assert_eq!(body["data"]["name"], "Updated Hackathon Controller");
// Clean up
let _ = repo.delete_hackathon(hackathon_id).await;
let _ = users_repo.query_delete_user(user.id.id.to_raw()).await;
}
#[tokio::test]
async fn test_delete_hackathon() {
let app = crate::get_full_test_app().await;
let users_repo = UsersRepository::new(&app.state);
let repo = HackathonRepository::new(&app.state);
// Create test organizer and hackathon
let email = generate_unique_email("hackathon_delete_controller");
let role_id = get_role_id("mentor", &app.state).await;
let user_data = crate::create_test_user(&email, "password123", true, &role_id);
let user_result = users_repo.query_create_user(user_data.clone()).await;
assert!(user_result.is_ok(), "Failed to create test user");
let user = users_repo.query_user_by_email(email.clone()).await.unwrap();
let hackathon_request = HackathonCreateRequestDto {
name: "Hackathon to Delete Controller".to_string(),
description: "Hackathon for deletion test".to_string(),
start_date: Utc::now() + Duration::days(7),
end_date: Utc::now() + Duration::days(14),
registration_deadline: Utc::now() + Duration::days(10),
max_participants: None,
theme: None,
rules: None,
prizes: None,
previous_winners: None,
organizers: vec![user.id.id.to_raw()],
};
let create_result = repo.create_hackathon(hackathon_request.clone()).await.expect("Failed to create hackathon");
let hackathon_id = create_result.id.id.to_raw();
// Send delete request
let response = app.service.delete(format!("/api/v1/hackathons/{}", hackathon_id))
.header("Authorization", format!("Bearer {}", crate::get_test_token(&user.id.id.to_raw()).await))
.await
.unwrap();
// Verify response
assert_eq!(response.status(), StatusCode::OK);
let body = crate::get_response_body(response).await;
assert_eq!(body["message"], "Success delete hackathon");
// Verify hackathon is deleted
let get_response = app.service.get(format!("/api/v1/hackathons/{}", hackathon_id))
.await
.unwrap();
assert_eq!(get_response.status(), StatusCode::NOT_FOUND);
// Clean up
let _ = users_repo.query_delete_user(user.id.id.to_raw()).await;
}
#[tokio::test]
async fn test_submit_project_as_user() {
let app = crate::get_full_test_app().await;
let users_repo = UsersRepository::new(&app.state);
let repo = HackathonRepository::new(&app.state);
// Create test users and hackathon
let organizer_email = generate_unique_email("hackathon_submit_organizer_controller");
let participant_email = generate_unique_email("hackathon_submit_participant_controller");
let role_id = get_role_id("mentee", &app.state).await;
let organizer_data = crate::create_test_user(&organizer_email, "password123", true, &role_id);
let participant_data = crate::create_test_user(&participant_email, "password123", true, &role_id);
let organizer_result = users_repo.query_create_user(organizer_data.clone()).await;
let participant_result = users_repo.query_create_user(participant_data.clone()).await;
assert!(organizer_result.is_ok(), "Failed to create organizer");
assert!(participant_result.is_ok(), "Failed to create participant");
let organizer = users_repo.query_user_by_email(organizer_email.clone()).await.unwrap();
let participant = users_repo.query_user_by_email(participant_email.clone()).await.unwrap();
let hackathon_request = HackathonCreateRequestDto {
name: "User Submission Test Controller".to_string(),
description: "Test hackathon for user submissions".to_string(),
start_date: Utc::now() + Duration::days(7),
end_date: Utc::now() + Duration::days(14),
registration_deadline: Utc::now() + Duration::days(10),
max_participants: None,
theme: None,
rules: None,
prizes: None,
previous_winners: None,
organizers: vec![organizer.id.id.to_raw()],
};
let create_result = repo.create_hackathon(hackathon_request.clone()).await.expect("Failed to create hackathon");
let hackathon_id = create_result.id.id.to_raw();
// Submit project request
let submission_dto = HackathonSubmissionCreateRequestDto {
project_name: "My Rust Project Controller".to_string(),
description: "A cool Rust project for the hackathon".to_string(),
repository_url: Some("https://github.com/user/my-rust-project".to_string()),
demo_url: Some("https://my-rust-project.com".to_string()),
slides_url: None,
technologies: vec![],
};
// Send submission request (use team path; for single-user tests we pass participant id as team_id)
let response = app.service.post(format!("/api/v1/hackathons/{}/teams/{}/submissions", hackathon_id, participant.id.id.to_raw()))
.header("Authorization", format!("Bearer {}", crate::get_test_token(&participant.id.id.to_raw()).await))
.json(&submission_dto)
.await
.unwrap();
// Verify response
assert_eq!(response.status(), StatusCode::CREATED);
let body = crate::get_response_body(response).await;
assert_eq!(body["message"], "Success submit project");
assert_eq!(body["data"]["project_name"], "My Rust Project Controller");
assert_eq!(body["data"]["status"], "Draft");
// Clean up
let _ = repo.delete_hackathon(hackathon_id).await;
let _ = users_repo.query_delete_user(organizer.id.id.to_raw()).await;
let _ = users_repo.query_delete_user(participant.id.id.to_raw()).await;
}
#[tokio::test]
async fn test_submit_project_as_team() {
let app = crate::get_full_test_app().await;
let users_repo = UsersRepository::new(&app.state);
let teams_repo = TeamsRepository::new(&app.state);
let hackathon_repo = HackathonRepository::new(&app.state);
// Create test users, team, and hackathon
let organizer_email = generate_unique_email("hackathon_team_submit_organizer_controller");
let member1_email = generate_unique_email("team_member1_submit_controller");
let member2_email = generate_unique_email("team_member2_submit_controller");
let role_id = get_role_id("mentee", &app.state).await;
let organizer_data = crate::create_test_user(&organizer_email, "password123", true, &role_id);
let member1_data = crate::create_test_user(&member1_email, "password123", true, &role_id);
let member2_data = crate::create_test_user(&member2_email, "password123", true, &role_id);
let organizer_result = users_repo.query_create_user(organizer_data.clone()).await;
let member1_result = users_repo.query_create_user(member1_data.clone()).await;
let member2_result = users_repo.query_create_user(member2_data.clone()).await;
assert!(organizer_result.is_ok(), "Failed to create organizer");
assert!(member1_result.is_ok(), "Failed to create member1");
assert!(member2_result.is_ok(), "Failed to create member2");
let organizer = users_repo.query_user_by_email(organizer_email.clone()).await.unwrap();
let member1 = users_repo.query_user_by_email(member1_email.clone()).await.unwrap();
let member2 = users_repo.query_user_by_email(member2_email.clone()).await.unwrap();
// Create team
let team_request = TeamsCreateRequestDto {
name: "Hackathon Team Controller".to_string(),
description: Some("Team for hackathon submissions".to_string()),
is_open: Some(false),
max_members: Some(5),
skills_required: Some(vec!["Rust".to_string(), "Backend".to_string()]),
location: Some("Remote".to_string()),
website_url: None,
github_url: None,
avatar: None,
member_emails: vec![],
};
let team_schema = imphnen_iam::TeamsSchema::create(team_request, member1.id.id.to_raw());
let team_create_result = teams_repo.query_create_team(team_schema).await.unwrap();
let team_id = team_create_result.split_whitespace().last().unwrap().to_string();
// Add team members
let member2_schema = TeamMembersSchema::create(
team_id.clone(),
member2.id.id.to_raw(),
Some("member".to_string())
);
let add_member_result = teams_repo.query_add_team_member(member2_schema).await;
assert!(add_member_result.is_ok(), "Failed to add team member");
// Create hackathon
let hackathon_request = HackathonCreateRequestDto {
name: "Team Submission Test Controller".to_string(),
description: "Test hackathon for team submissions".to_string(),
start_date: Utc::now() + Duration::days(7),
end_date: Utc::now() + Duration::days(14),
registration_deadline: Utc::now() + Duration::days(10),
max_participants: None,
theme: None,
rules: None,
prizes: None,
previous_winners: None,
organizers: vec![organizer.id.id.to_raw()],
};
let create_result = hackathon_repo.create_hackathon(hackathon_request.clone()).await.expect("Failed to create hackathon");
let hackathon_id = create_result.id.id.to_raw();
// Submit team project request
let team_submission_dto = HackathonSubmissionCreateRequestDto {
project_name: "Our Team Rust Project Controller".to_string(),
description: "A collaborative Rust project by our team".to_string(),
repository_url: Some("https://github.com/team/our-rust-project".to_string()),
demo_url: Some("https://our-team-project.com".to_string()),
slides_url: Some("https://docs.google.com/presentation/d/12345".to_string()),
technologies: vec![],
};
// Send team submission request (use teams path)
let response = app.service.post(format!("/api/v1/hackathons/{}/teams/{}/submissions", hackathon_id, team_id))
.header("Authorization", format!("Bearer {}", crate::get_test_token(&member1.id.id.to_raw()).await))
.json(&team_submission_dto)
.await
.unwrap();
// Verify response
assert_eq!(response.status(), StatusCode::CREATED);
let body = crate::get_response_body(response).await;
assert_eq!(body["message"], "Success submit team project");
assert_eq!(body["data"]["project_name"], "Our Team Rust Project Controller");
assert_eq!(body["data"]["status"], "Draft");
assert_eq!(body["data"]["team_id"], team_id);
// Clean up
let _ = hackathon_repo.delete_hackathon(hackathon_id).await;
let _ = teams_repo.query_delete_team(team_id).await;
let _ = users_repo.query_delete_user(organizer.id.id.to_raw()).await;
let _ = users_repo.query_delete_user(member1.id.id.to_raw()).await;
let _ = users_repo.query_delete_user(member2.id.id.to_raw()).await;
}
#[tokio::test]
async fn test_get_hackathon_submissions() {
let app = crate::get_full_test_app().await;
let users_repo = UsersRepository::new(&app.state);
let repo = HackathonRepository::new(&app.state);
// Create test users and hackathon
let organizer_email = generate_unique_email("hackathon_submissions_organizer_controller");
let participant_email = generate_unique_email("hackathon_submissions_participant_controller");
let role_id = get_role_id("mentee", &app.state).await;
let organizer_data = crate::create_test_user(&organizer_email, "password123", true, &role_id);
let participant_data = crate::create_test_user(&participant_email, "password123", true, &role_id);
let organizer_result = users_repo.query_create_user(organizer_data.clone()).await;
let participant_result = users_repo.query_create_user(participant_data.clone()).await;
assert!(organizer_result.is_ok(), "Failed to create organizer");
assert!(participant_result.is_ok(), "Failed to create participant");
let organizer = users_repo.query_user_by_email(organizer_email.clone()).await.unwrap();
let participant = users_repo.query_user_by_email(participant_email.clone()).await.unwrap();
// Create hackathon
let hackathon_request = HackathonCreateRequestDto {
name: "Submissions Test Controller".to_string(),
description: "Test hackathon for retrieving submissions".to_string(),
start_date: Utc::now() + Duration::days(7),
end_date: Utc::now() + Duration::days(14),
registration_deadline: Utc::now() + Duration::days(10),
max_participants: None,
theme: None,
rules: None,
prizes: None,
previous_winners: None,
organizers: vec![organizer.id.id.to_raw()],
};
let create_result = repo.create_hackathon(hackathon_request.clone()).await.expect("Failed to create hackathon");
let hackathon_id = create_result.id.id.to_raw();
// Submit multiple projects
let submission_dtos = [
HackathonSubmissionCreateRequestDto {
project_name: "Project 1 Controller".to_string(),
description: "Description 1".to_string(),
repository_url: Some("https://github.com/user/project1".to_string()),
demo_url: None,
slides_url: None,
technologies: vec![],
},
HackathonSubmissionCreateRequestDto {
project_name: "Project 2 Controller".to_string(),
description: "Description 2".to_string(),
repository_url: Some("https://github.com/user/project2".to_string()),
demo_url: Some("https://project2.com".to_string()),
slides_url: None,
technologies: vec![],
}
];
for submission_dto in submission_dtos.iter() {
let response = app.service.post(format!("/api/v1/hackathons/{}/teams/{}/submissions", hackathon_id, participant.id.id.to_raw()))
.header("Authorization", format!("Bearer {}", crate::get_test_token(&participant.id.id.to_raw()).await))
.json(submission_dto)
.await
.unwrap();
assert_eq!(response.status(), StatusCode::CREATED);
}
// Get hackathon submissions
let response = app.service.get(format!("/api/v1/hackathons/{}/submissions", hackathon_id))
.await
.unwrap();
// Verify response
assert_eq!(response.status(), StatusCode::OK);
let body = crate::get_response_body(response).await;
assert_eq!(body["data"].as_array().unwrap().len(), 2);
assert_eq!(body["data"][0]["project_name"], "Project 1 Controller");
assert_eq!(body["data"][1]["project_name"], "Project 2 Controller");
assert_eq!(body["data"][0]["status"], "Draft");
assert_eq!(body["data"][1]["status"], "Draft");
// Clean up
let _ = repo.delete_hackathon(hackathon_id).await;
let _ = users_repo.query_delete_user(organizer.id.id.to_raw()).await;
let _ = users_repo.query_delete_user(participant.id.id.to_raw()).await;
}
#[tokio::test]
async fn test_get_user_hackathon_submissions() {
let app = crate::get_full_test_app().await;
let users_repo = UsersRepository::new(&app.state);
let repo = HackathonRepository::new(&app.state);
// Create test users and hackathons
let organizer_email = generate_unique_email("hackathon_user_submissions_organizer_controller");
let participant_email = generate_unique_email("hackathon_user_submissions_participant_controller");
let role_id = get_role_id("mentee", &app.state).await;
let organizer_data = crate::create_test_user(&organizer_email, "password123", true, &role_id);
let participant_data = crate::create_test_user(&participant_email, "password123", true, &role_id);
let organizer_result = users_repo.query_create_user(organizer_data.clone()).await;
let participant_result = users_repo.query_create_user(participant_data.clone()).await;
assert!(organizer_result.is_ok(), "Failed to create organizer");
assert!(participant_result.is_ok(), "Failed to create participant");
let organizer = users_repo.query_user_by_email(organizer_email.clone()).await.unwrap();
let participant = users_repo.query_user_by_email(participant_email.clone()).await.unwrap();
// Create multiple hackathons
let hackathon_requests = [
HackathonCreateRequestDto {
name: "Hackathon 1 Controller".to_string(),
description: "First hackathon".to_string(),
start_date: Utc::now() + Duration::days(7),
end_date: Utc::now() + Duration::days(14),
registration_deadline: Utc::now() + Duration::days(10),
max_participants: None,
theme: None,
rules: None,
prizes: None,
previous_winners: None,
organizers: vec![organizer.id.id.to_raw()],
},
HackathonCreateRequestDto {
name: "Hackathon 2 Controller".to_string(),
description: "Second hackathon".to_string(),
start_date: Utc::now() + Duration::days(14),
end_date: Utc::now() + Duration::days(21),
registration_deadline: Utc::now() + Duration::days(17),
max_participants: None,
theme: None,
rules: None,
prizes: None,
previous_winners: None,
organizers: vec![organizer.id.id.to_raw()],
}
];
let mut hackathon_ids = Vec::new();
for hackathon_request in hackathon_requests.iter() {
let create_result = repo.create_hackathon(hackathon_request.clone()).await.unwrap();
let hackathon_id = create_result.id.id.to_raw();
hackathon_ids.push(hackathon_id);
}
// Submit projects to different hackathons using team endpoint (single-user uses user id as team_id)
let submission_requests = [
HackathonSubmissionCreateRequestDto {
project_name: "Project for Hackathon 1 Controller".to_string(),
description: "Description for hackathon 1".to_string(),
repository_url: Some("https://github.com/user/hackathon1-project".to_string()),
demo_url: None,
slides_url: None,
technologies: vec![],
},
HackathonSubmissionCreateRequestDto {
project_name: "Project for Hackathon 2 Controller".to_string(),
description: "Description for hackathon 2".to_string(),
repository_url: Some("https://github.com/user/hackathon2-project".to_string()),
demo_url: Some("https://hackathon2-project.com".to_string()),
slides_url: None,
technologies: vec![],
}
];
for (i, create_req) in submission_requests.iter().enumerate() {
let response = app.service.post(format!("/api/v1/hackathons/{}/teams/{}/submissions", hackathon_ids[i], participant.id.id.to_raw()))
.header("Authorization", format!("Bearer {}", crate::get_test_token(&participant.id.id.to_raw()).await))
.json(create_req)
.await
.unwrap();
assert_eq!(response.status(), StatusCode::CREATED);
}
// Get user's hackathon submissions
let response = app.service.get(format!("/api/v1/users/{}/hackathon-submissions", participant.id.id.to_raw()))
.await
.unwrap();
// Verify response
assert_eq!(response.status(), StatusCode::OK);
let body = crate::get_response_body(response).await;
assert_eq!(body["data"].as_array().unwrap().len(), 2);
assert_eq!(body["data"][0]["project_name"], "Project for Hackathon 1 Controller");
assert_eq!(body["data"][1]["project_name"], "Project for Hackathon 2 Controller");
assert_eq!(body["data"][0]["status"], "Draft");
assert_eq!(body["data"][1]["status"], "Draft");
// Clean up
for hackathon_id in hackathon_ids {
let _ = repo.delete_hackathon(hackathon_id).await;
}
let _ = users_repo.query_delete_user(organizer.id.id.to_raw()).await;
let _ = users_repo.query_delete_user(participant.id.id.to_raw()).await;
}
#[tokio::test]
async fn test_search_hackathons() {
let app = crate::get_full_test_app().await;
let users_repo = UsersRepository::new(&app.state);
let repo = HackathonRepository::new(&app.state);
// Create test organizer and hackathons
let email = generate_unique_email("hackathon_search_controller");
let role_id = get_role_id("mentor", &app.state).await;
let user_data = crate::create_test_user(&email, "password123", true, &role_id);
let user_result = users_repo.query_create_user(user_data.clone()).await;
assert!(user_result.is_ok(), "Failed to create test user");
let user = users_repo.query_user_by_email(email.clone()).await.unwrap();
// Create test hackathons
let hackathon_requests = [
HackathonCreateRequestDto {
name: "Rust Backend Hackathon Controller".to_string(),
description: "Build Rust backend projects".to_string(),
start_date: Utc::now() + Duration::days(7),
end_date: Utc::now() + Duration::days(14),
registration_deadline: Utc::now() + Duration::days(10),
max_participants: None,
theme: Some("Backend".to_string()),
rules: None,
prizes: None,
previous_winners: None,
organizers: vec![user.id.id.to_raw()],
},
HackathonCreateRequestDto {
name: "TypeScript Frontend Hackathon Controller".to_string(),
description: "Build TypeScript frontend projects".to_string(),
start_date: Utc::now() + Duration::days(14),
end_date: Utc::now() + Duration::days(21),
registration_deadline: Utc::now() + Duration::days(17),
max_participants: None,
theme: Some("Frontend".to_string()),
rules: None,
prizes: None,
previous_winners: None,
organizers: vec![user.id.id.to_raw()],
},
HackathonCreateRequestDto {
name: "Rust Fullstack Hackathon Controller".to_string(),
description: "Build fullstack projects with Rust".to_string(),
start_date: Utc::now() + Duration::days(21),
end_date: Utc::now() + Duration::days(28),
registration_deadline: Utc::now() + Duration::days(24),
max_participants: None,
theme: Some("Fullstack".to_string()),
rules: None,
prizes: None,
previous_winners: None,
organizers: vec![user.id.id.to_raw()],
}
];
for hackathon_request in hackathon_requests.iter() {
let create_result = repo.create_hackathon(hackathon_request.clone()).await.unwrap();
// Store hackathon IDs for cleanup
let _ = create_result.id.id.to_raw();
}
// Test search with multiple parameters
let search_params = json!({
"query": "Rust",
"category": "Backend",
"location": "Remote",
"is_featured": true,
"page": 1,
"per_page": 10
});
let response = app.service.post("/api/v1/hackathons/search")
.json(&search_params)
.await
.unwrap();
// Verify response
assert_eq!(response.status(), StatusCode::OK);
let body = crate::get_response_body(response).await;
assert_eq!(body["data"].as_array().unwrap().len(), 1);
assert_eq!(body["data"][0]["name"], "Rust Backend Hackathon Controller");
assert!(body["data"][0]["description"].as_str().unwrap().contains("Rust"));
// Clean up - in a real test you would store and delete all created hackathons
let _ = users_repo.query_delete_user(user.id.id.to_raw()).await;
}
#[tokio::test]
async fn test_update_submission_status() {
let app = crate::get_full_test_app().await;
let users_repo = UsersRepository::new(&app.state);
let repo = HackathonRepository::new(&app.state);
// Create test users and hackathon
let organizer_email = generate_unique_email("hackathon_status_organizer_controller");
let participant_email = generate_unique_email("hackathon_status_participant_controller");
let role_id = get_role_id("mentee", &app.state).await;
let organizer_data = crate::create_test_user(&organizer_email, "password123", true, &role_id);
let participant_data = crate::create_test_user(&participant_email, "password123", true, &role_id);
let organizer_result = users_repo.query_create_user(organizer_data.clone()).await;
let participant_result = users_repo.query_create_user(participant_data.clone()).await;
assert!(organizer_result.is_ok(), "Failed to create organizer");
assert!(participant_result.is_ok(), "Failed to create participant");
let organizer = users_repo.query_user_by_email(organizer_email.clone()).await.unwrap();
let participant = users_repo.query_user_by_email(participant_email.clone()).await.unwrap();
// Create hackathon and submission
let hackathon_request = HackathonCreateRequestDto {
name: "Submission Status Test Controller".to_string(),
description: "Test hackathon for submission status updates".to_string(),
start_date: Utc::now() + Duration::days(7),
end_date: Utc::now() + Duration::days(14),
registration_deadline: Utc::now() + Duration::days(10),
max_participants: None,
theme: None,
rules: None,
prizes: None,
previous_winners: None,
organizers: vec![organizer.id.id.to_raw()],
};
let create_result = repo.create_hackathon(hackathon_request).await.unwrap();
let hackathon_id = create_result.id.id.to_raw();
let submission_dto = HackathonSubmissionCreateRequestDto {
project_name: "Test Project Controller".to_string(),
description: "Test description".to_string(),
repository_url: Some("https://github.com/user/test-project".to_string()),
demo_url: None,
slides_url: None,
technologies: vec![],
};
let submit_response = app.service.post(format!("/api/v1/hackathons/{}/teams/{}/submissions", hackathon_id, participant.id.id.to_raw()))
.header("Authorization", format!("Bearer {}", crate::get_test_token(&participant.id.id.to_raw()).await))
.json(&submission_dto)
.await
.unwrap();
assert_eq!(submit_response.status(), StatusCode::CREATED);
let submission_id = crate::get_response_body(submit_response).await["data"]["id"]
.as_str()
.unwrap()
.to_string();
// Update submission status to "Accepted"
let update_status = json!({
"status": "Accepted",
"feedback": "Great project!"
});
let response = app.service.patch(format!("/api/v1/hackathons/submissions/{}/status", submission_id))
.header("Authorization", format!("Bearer {}", crate::get_test_token(&organizer.id.id.to_raw()).await))
.json(&update_status)
.await
.unwrap();
// Verify response
assert_eq!(response.status(), StatusCode::OK);
let body = crate::get_response_body(response).await;
assert_eq!(body["message"], "Success update submission status");
assert_eq!(body["data"]["status"], "Accepted");
assert_eq!(body["data"]["judge_feedback"], "Great project!");
// Update status again to "Rejected"
let update_status2 = json!({
"status": "Rejected",
"feedback": "Does not meet criteria"
});
let response2 = app.service.patch(format!("/api/v1/hackathons/submissions/{}/status", submission_id))
.header("Authorization", format!("Bearer {}", crate::get_test_token(&organizer.id.id.to_raw()).await))
.json(&update_status2)
.await
.unwrap();
// Verify second update
assert_eq!(response2.status(), StatusCode::OK);
let body2 = crate::get_response_body(response2).await;
assert_eq!(body2["message"], "Success update submission status");
assert_eq!(body2["data"]["status"], "Rejected");
assert_eq!(body2["data"]["judge_feedback"], "Does not meet criteria");
// Clean up
let _ = repo.delete_hackathon(hackathon_id).await;
let _ = users_repo.query_delete_user(organizer.id.id.to_raw()).await;
let _ = users_repo.query_delete_user(participant.id.id.to_raw()).await;
}
}