WIP: test: add more tests to forge-forgejo crate
This commit is contained in:
parent
98839c8a00
commit
db965ba23e
3 changed files with 292 additions and 1 deletions
|
@ -1,4 +1,7 @@
|
||||||
//
|
//
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests;
|
||||||
|
|
||||||
mod webhook;
|
mod webhook;
|
||||||
|
|
||||||
use git::forge::commit::Status;
|
use git::forge::commit::Status;
|
||||||
|
|
288
crates/forge-forgejo/src/tests.rs
Normal file
288
crates/forge-forgejo/src/tests.rs
Normal file
|
@ -0,0 +1,288 @@
|
||||||
|
use git_next_config as config;
|
||||||
|
use git_next_git as git;
|
||||||
|
|
||||||
|
mod forgejo {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
use assert2::let_assert;
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
|
use crate::ForgeJo;
|
||||||
|
use config::{
|
||||||
|
webhook::message::Body, ForgeAlias, ForgeConfig, ForgeType, GitDir, RepoAlias,
|
||||||
|
RepoBranches, ServerRepoConfig, WebhookAuth, WebhookMessage,
|
||||||
|
};
|
||||||
|
use git::ForgeLike as _;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_return_name() {
|
||||||
|
let forge = given_forgejo_forge(given_repo_details(), given_net());
|
||||||
|
assert_eq!(forge.name(), "forgejo");
|
||||||
|
}
|
||||||
|
|
||||||
|
mod is_message_authorised {
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_return_true_with_valid_header() {
|
||||||
|
let forge = given_forgejo_forge(given_repo_details(), given_net());
|
||||||
|
let auth = given_auth();
|
||||||
|
let message = given_message(Header::Valid(auth.clone()));
|
||||||
|
assert!(forge.is_message_authorised(&message, &auth));
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn should_return_false_with_missing_header() {
|
||||||
|
let forge = given_forgejo_forge(given_repo_details(), given_net());
|
||||||
|
let auth = given_auth();
|
||||||
|
let message = given_message(Header::Missing);
|
||||||
|
assert!(!forge.is_message_authorised(&message, &auth));
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn should_return_false_with_non_basic_prefix() {
|
||||||
|
let forge = given_forgejo_forge(given_repo_details(), given_net());
|
||||||
|
let auth = given_auth();
|
||||||
|
let message = given_message(Header::NonBasic);
|
||||||
|
assert!(!forge.is_message_authorised(&message, &auth));
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn should_return_false_with_non_ulid_value() {
|
||||||
|
let forge = given_forgejo_forge(given_repo_details(), given_net());
|
||||||
|
let auth = given_auth();
|
||||||
|
let message = given_message(Header::NonUlid);
|
||||||
|
assert!(!forge.is_message_authorised(&message, &auth));
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn should_return_false_with_wrong_ulid_value() {
|
||||||
|
let forge = given_forgejo_forge(given_repo_details(), given_net());
|
||||||
|
let auth = given_auth();
|
||||||
|
let message = given_message(Header::WrongUlid);
|
||||||
|
assert!(!forge.is_message_authorised(&message, &auth));
|
||||||
|
}
|
||||||
|
fn given_auth() -> WebhookAuth {
|
||||||
|
WebhookAuth::generate()
|
||||||
|
}
|
||||||
|
enum Header {
|
||||||
|
Valid(WebhookAuth),
|
||||||
|
Missing,
|
||||||
|
NonBasic,
|
||||||
|
NonUlid,
|
||||||
|
WrongUlid,
|
||||||
|
}
|
||||||
|
fn given_message(header: Header) -> WebhookMessage {
|
||||||
|
WebhookMessage::new(
|
||||||
|
given_forge_alias(),
|
||||||
|
given_repo_alias(),
|
||||||
|
given_headers(header),
|
||||||
|
given_body(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
fn given_headers(header: Header) -> HashMap<String, String> {
|
||||||
|
let mut headers = HashMap::new();
|
||||||
|
match header {
|
||||||
|
Header::Valid(auth) => {
|
||||||
|
headers.insert("authorization".to_string(), format!("Basic {auth}"));
|
||||||
|
}
|
||||||
|
Header::Missing => { /* don't add any header */ }
|
||||||
|
Header::NonBasic => {
|
||||||
|
headers.insert("authorization".to_string(), "Non-Basic".to_string());
|
||||||
|
}
|
||||||
|
Header::NonUlid => {
|
||||||
|
headers.insert("authorization".to_string(), "Basic 123456".to_string());
|
||||||
|
}
|
||||||
|
Header::WrongUlid => {
|
||||||
|
headers.insert(
|
||||||
|
"authorization".to_string(),
|
||||||
|
format!("Basic {}", WebhookAuth::generate()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
headers
|
||||||
|
}
|
||||||
|
fn given_body() -> Body {
|
||||||
|
Body::new("body".to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod parse_webhook_body {
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_parse_valid_body() {
|
||||||
|
let forge = given_forgejo_forge(given_repo_details(), given_net());
|
||||||
|
let repo_branches = given_repo_branches();
|
||||||
|
let body = Body::new(
|
||||||
|
r#"{"ref":"refs/heads/b-next","after":"a-sha","head_commit":{"message":"the-message"}}"#
|
||||||
|
.to_string(),
|
||||||
|
);
|
||||||
|
let_assert!(Ok(push) = forge.parse_webhook_body(&body));
|
||||||
|
assert_eq!(push.sha(), "a-sha");
|
||||||
|
assert_eq!(push.message(), "the-message");
|
||||||
|
assert_eq!(
|
||||||
|
push.branch(&repo_branches),
|
||||||
|
Some(config::webhook::push::Branch::Next)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_error_invalid_body() {
|
||||||
|
let forge = given_forgejo_forge(given_repo_details(), given_net());
|
||||||
|
let body = Body::new(r#"{"type":"invalid"}"#.to_string());
|
||||||
|
let_assert!(Err(_) = forge.parse_webhook_body(&body));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod commit_status {
|
||||||
|
use git_next_git::{forge::commit::Status, RepoDetails};
|
||||||
|
use kxio::network::{MockNetwork, StatusCode};
|
||||||
|
use serde_json::json;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn should_return_pass_for_success() {
|
||||||
|
let repo_details = given_repo_details();
|
||||||
|
let commit = given_a_commit();
|
||||||
|
let mut net = given_net();
|
||||||
|
given_state("success", &mut net, &repo_details, &commit);
|
||||||
|
let forge = given_forgejo_forge(repo_details, net);
|
||||||
|
assert_eq!(forge.commit_status(&commit).await, Status::Pass);
|
||||||
|
}
|
||||||
|
#[tokio::test]
|
||||||
|
async fn should_return_pending_for_pending() {
|
||||||
|
let repo_details = given_repo_details();
|
||||||
|
let commit = given_a_commit();
|
||||||
|
let mut net = given_net();
|
||||||
|
given_state("pending", &mut net, &repo_details, &commit);
|
||||||
|
let forge = given_forgejo_forge(given_repo_details(), net);
|
||||||
|
let commit = given_a_commit();
|
||||||
|
assert_eq!(forge.commit_status(&commit).await, Status::Pending);
|
||||||
|
}
|
||||||
|
#[tokio::test]
|
||||||
|
async fn should_return_fail_for_failure() {
|
||||||
|
let repo_details = given_repo_details();
|
||||||
|
let commit = given_a_commit();
|
||||||
|
let mut net = given_net();
|
||||||
|
given_state("failure", &mut net, &repo_details, &commit);
|
||||||
|
let forge = given_forgejo_forge(given_repo_details(), net);
|
||||||
|
let commit = given_a_commit();
|
||||||
|
assert_eq!(forge.commit_status(&commit).await, Status::Fail);
|
||||||
|
}
|
||||||
|
#[tokio::test]
|
||||||
|
async fn should_return_fail_for_error() {
|
||||||
|
let repo_details = given_repo_details();
|
||||||
|
let commit = given_a_commit();
|
||||||
|
let mut net = given_net();
|
||||||
|
given_state("error", &mut net, &repo_details, &commit);
|
||||||
|
let forge = given_forgejo_forge(given_repo_details(), net);
|
||||||
|
let commit = given_a_commit();
|
||||||
|
assert_eq!(forge.commit_status(&commit).await, Status::Fail);
|
||||||
|
}
|
||||||
|
#[tokio::test]
|
||||||
|
async fn should_return_pending_for_blank() {
|
||||||
|
let repo_details = given_repo_details();
|
||||||
|
let commit = given_a_commit();
|
||||||
|
let mut net = given_net();
|
||||||
|
given_state("", &mut net, &repo_details, &commit);
|
||||||
|
let forge = given_forgejo_forge(given_repo_details(), net);
|
||||||
|
let commit = given_a_commit();
|
||||||
|
assert_eq!(forge.commit_status(&commit).await, Status::Pending);
|
||||||
|
}
|
||||||
|
#[tokio::test]
|
||||||
|
async fn should_return_pending_for_no_statuses() {
|
||||||
|
let repo_details = given_repo_details();
|
||||||
|
let commit = given_a_commit();
|
||||||
|
let mut net = given_net();
|
||||||
|
net.add_get_response(&url(&repo_details, &commit), StatusCode::OK, "");
|
||||||
|
let forge = given_forgejo_forge(given_repo_details(), net);
|
||||||
|
let commit = given_a_commit();
|
||||||
|
assert_eq!(forge.commit_status(&commit).await, Status::Pending);
|
||||||
|
}
|
||||||
|
#[tokio::test]
|
||||||
|
async fn should_return_pending_for_network_error() {
|
||||||
|
let repo_details = given_repo_details();
|
||||||
|
let commit = given_a_commit();
|
||||||
|
let mut net = given_net();
|
||||||
|
net.add_get_error(&url(&repo_details, &commit), "boom today");
|
||||||
|
let forge = given_forgejo_forge(given_repo_details(), net);
|
||||||
|
let commit = given_a_commit();
|
||||||
|
|
||||||
|
assert_eq!(forge.commit_status(&commit).await, Status::Pending);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn url(repo_details: &RepoDetails, commit: &git::Commit) -> String {
|
||||||
|
let hostname = repo_details.forge.hostname();
|
||||||
|
let repo_path = &repo_details.repo_path;
|
||||||
|
use secrecy::ExposeSecret;
|
||||||
|
let token = repo_details.forge.token().expose_secret();
|
||||||
|
format!(
|
||||||
|
"https://{hostname}/api/v1/repos/{repo_path}/commits/{commit}/status?token={token}"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn given_state(
|
||||||
|
state: impl AsRef<str>,
|
||||||
|
net: &mut MockNetwork,
|
||||||
|
repo_details: &git::RepoDetails,
|
||||||
|
commit: &git::Commit,
|
||||||
|
) {
|
||||||
|
let response = json!({"state":state.as_ref()});
|
||||||
|
net.add_get_response(
|
||||||
|
url(repo_details, commit).as_str(),
|
||||||
|
StatusCode::OK,
|
||||||
|
response.to_string().as_str(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn given_a_commit() -> git::Commit {
|
||||||
|
git::Commit::new(
|
||||||
|
git::commit::Sha::new("a-sha".to_string()),
|
||||||
|
git::commit::Message::new("a-message".to_string()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn given_repo_branches() -> RepoBranches {
|
||||||
|
RepoBranches::new(
|
||||||
|
"a-main".to_string(),
|
||||||
|
"b-next".to_string(),
|
||||||
|
"c-dev".to_string(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn given_forgejo_forge(
|
||||||
|
repo_details: git::RepoDetails,
|
||||||
|
net: impl Into<kxio::network::Network>,
|
||||||
|
) -> ForgeJo {
|
||||||
|
ForgeJo::new(repo_details, net.into())
|
||||||
|
}
|
||||||
|
fn given_repo_details() -> git::RepoDetails {
|
||||||
|
git::RepoDetails::new(
|
||||||
|
git::Generation::new(),
|
||||||
|
&given_repo_alias(),
|
||||||
|
&ServerRepoConfig::new("b".to_string(), "c".to_string(), None, None, None, None),
|
||||||
|
&given_forge_alias(),
|
||||||
|
&ForgeConfig::new(
|
||||||
|
ForgeType::ForgeJo,
|
||||||
|
"git.forge.jo".to_string(),
|
||||||
|
"user".to_string(),
|
||||||
|
"token".to_string(),
|
||||||
|
BTreeMap::default(),
|
||||||
|
),
|
||||||
|
GitDir::default(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn given_forge_alias() -> ForgeAlias {
|
||||||
|
ForgeAlias::new("d".to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn given_repo_alias() -> RepoAlias {
|
||||||
|
RepoAlias::new("a")
|
||||||
|
}
|
||||||
|
fn given_net() -> kxio::network::MockNetwork {
|
||||||
|
kxio::network::MockNetwork::new()
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
#[derive(Debug)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub enum Status {
|
pub enum Status {
|
||||||
Pass,
|
Pass,
|
||||||
Fail,
|
Fail,
|
||||||
|
|
Loading…
Reference in a new issue