use std::{sync::mpsc, time::Duration};
use chrono::{DateTime, Utc};
use serde_json::json;
use crate::{
client::{
config::{ClientConfig, PollingConfig},
service::GitlabService,
},
domain::{CommitDto, JobDto, PipelineDto, ProjectDto, StatisticsDto},
id::{JobId, PipelineId, ProjectId},
};
#[allow(dead_code)]
pub fn test_config() -> ClientConfig {
ClientConfig::new("https://gitlab.example.com", "test-token").with_debug_logging(false)
}
#[allow(dead_code)]
pub fn test_service() -> GitlabService {
let config = test_config();
let (sender, _receiver) = mpsc::channel();
GitlabService::new(config, sender).unwrap()
}
#[allow(dead_code)]
pub fn test_polling_config() -> PollingConfig {
PollingConfig {
projects_interval: Duration::from_millis(100),
jobs_interval: Duration::from_millis(50),
}
}
pub fn sample_project_dto() -> ProjectDto {
ProjectDto {
id: ProjectId::new(123),
path_with_namespace: "group/project".into(),
description: Some("Test project".into()),
default_branch: "main".into(),
ssh_url_to_repo: "git@gitlab.example.com:group/project.git".into(),
web_url: "https://gitlab.example.com/group/project".into(),
last_activity_at: DateTime::parse_from_rfc3339("2023-01-01T00:00:00Z")
.unwrap()
.with_timezone(&Utc),
statistics: StatisticsDto {
commit_count: 42,
job_artifacts_size: 1024 * 1024,
repository_size: 10 * 1024 * 1024,
},
}
}
pub fn sample_pipeline_dto() -> PipelineDto {
PipelineDto {
id: PipelineId::new(456),
project_id: ProjectId::new(123),
status: crate::domain::PipelineStatus::Success,
source: crate::domain::PipelineSource::Push,
branch: "main".into(),
web_url: "https://gitlab.example.com/group/project/-/pipelines/456".into(),
created_at: DateTime::parse_from_rfc3339("2023-01-01T00:00:00Z")
.unwrap()
.with_timezone(&Utc),
updated_at: DateTime::parse_from_rfc3339("2023-01-01T01:00:00Z")
.unwrap()
.with_timezone(&Utc),
}
}
pub fn sample_job_dto() -> JobDto {
JobDto {
id: JobId::new(789),
name: "test-job".into(),
stage: "test".into(),
commit: CommitDto {
title: "Test commit".into(),
author_name: "Test Author".into(),
},
status: crate::domain::PipelineStatus::Success,
created_at: DateTime::parse_from_rfc3339("2023-01-01T00:00:00Z")
.unwrap()
.with_timezone(&Utc),
started_at: Some(
DateTime::parse_from_rfc3339("2023-01-01T00:01:00Z")
.unwrap()
.with_timezone(&Utc),
),
finished_at: Some(
DateTime::parse_from_rfc3339("2023-01-01T00:05:00Z")
.unwrap()
.with_timezone(&Utc),
),
web_url: "https://gitlab.example.com/group/project/-/jobs/789".into(),
}
}
#[allow(dead_code)]
pub fn projects_json_response() -> serde_json::Value {
json!([sample_project_dto_json()])
}
pub fn sample_project_dto_json() -> serde_json::Value {
json!({
"id": 123,
"path_with_namespace": "group/project",
"description": "Test project",
"default_branch": "main",
"ssh_url_to_repo": "git@gitlab.example.com:group/project.git",
"web_url": "https://gitlab.example.com/group/project",
"last_activity_at": "2023-01-01T00:00:00Z",
"statistics": {
"commit_count": 42,
"job_artifacts_size": 1048576,
"repository_size": 10485760
}
})
}
#[allow(dead_code)]
pub fn pipelines_json_response() -> serde_json::Value {
json!([sample_pipeline_dto_json()])
}
pub fn sample_pipeline_dto_json() -> serde_json::Value {
json!({
"id": 456,
"project_id": 123,
"status": "success",
"source": "push",
"ref": "main",
"web_url": "https://gitlab.example.com/group/project/-/pipelines/456",
"created_at": "2023-01-01T00:00:00Z",
"updated_at": "2023-01-01T01:00:00Z"
})
}
#[allow(dead_code)]
pub fn jobs_json_response() -> serde_json::Value {
json!([sample_job_dto_json()])
}
pub fn sample_job_dto_json() -> serde_json::Value {
json!({
"id": 789,
"name": "test-job",
"stage": "test",
"commit": {
"title": "Test commit",
"author_name": "Test Author"
},
"status": "success",
"created_at": "2023-01-01T00:00:00Z",
"started_at": "2023-01-01T00:01:00Z",
"finished_at": "2023-01-01T00:05:00Z",
"web_url": "https://gitlab.example.com/group/project/-/jobs/789"
})
}
pub fn gitlab_error_response(error: &str, description: Option<&str>) -> serde_json::Value {
let mut json = json!({
"error": error
});
if let Some(desc) = description {
json["error_description"] = json!(desc);
}
json
}
pub fn gitlab_error_response_2(message: &str) -> serde_json::Value {
json!({
"message": message
})
}
#[cfg(test)]
#[allow(dead_code)]
pub struct MockServer {
pub server: wiremock::MockServer,
}
#[cfg(test)]
#[allow(dead_code)]
impl MockServer {
pub async fn start() -> Self {
let server = wiremock::MockServer::start().await;
Self { server }
}
pub fn base_url(&self) -> String {
self.server.uri()
}
pub fn test_config(&self) -> crate::client::config::ClientConfig {
crate::client::config::ClientConfig::new(self.base_url(), "test-token")
}
}
#[cfg(test)]
#[allow(clippy::module_inception)]
mod tests {
use super::*;
#[test]
fn test_sample_data_creation() {
let project = sample_project_dto();
assert_eq!(project.id, ProjectId::new(123));
assert_eq!(project.path_with_namespace, "group/project");
let pipeline = sample_pipeline_dto();
assert_eq!(pipeline.id, PipelineId::new(456));
assert_eq!(pipeline.project_id, ProjectId::new(123));
let job = sample_job_dto();
assert_eq!(job.id, JobId::new(789));
assert_eq!(job.name, "test-job");
}
#[test]
fn test_json_serialization() {
let project_json = sample_project_dto_json();
assert_eq!(project_json["id"], 123);
assert_eq!(project_json["path_with_namespace"], "group/project");
let pipeline_json = sample_pipeline_dto_json();
assert_eq!(pipeline_json["id"], 456);
assert_eq!(pipeline_json["project_id"], 123);
let job_json = sample_job_dto_json();
assert_eq!(job_json["id"], 789);
assert_eq!(job_json["name"], "test-job");
}
#[test]
fn test_error_responses() {
let error1 = gitlab_error_response("invalid_token", Some("Token is invalid"));
assert_eq!(error1["error"], "invalid_token");
assert_eq!(error1["error_description"], "Token is invalid");
let error2 = gitlab_error_response_2("Project not found");
assert_eq!(error2["message"], "Project not found");
}
}