From e7e8a2871ba3d9f6cbe3120e64e3b1475d03afb6 Mon Sep 17 00:00:00 2001 From: Robert Garrett Date: Wed, 4 Jun 2025 11:14:12 -0500 Subject: [PATCH] Add unit test for release_attachment function I need some kind of automated testing, and Cargo has a test framework built-in. This isn't the smartest test and depends upon another test-less function. Building a mocking environment is possible but means I'm trying to emulate some behavior I don't fully understand -- that's why I need tests in the first place. That path leads to tests for my tests and that's stupid. Instead, I'm having the test read config from the environment and hit a real Gitea server. It's up to the user to ensure they have one. --- README.md | 11 +++++ src/api/release_attachment.rs | 89 +++++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+) diff --git a/README.md b/README.md index 37688c9..47d2718 100644 --- a/README.md +++ b/README.md @@ -51,3 +51,14 @@ One of these, defaults to `help`: | upload-release | Uploads one-or-more files to an existing release, identified by it's tag name. | | help | prints the help text (the usage summary above). | +## Unit Testing + +The unit test~~s~~ require a Gitea server to execute against. This information is supplied by environment variables rather than on the command line, but it is otherwise exactly the same usage. + +| Variable | Description | +|-|-| +| TEST_GITEA_SERVER | Server URL, match `-u`, `--url` | +| TEST_GITEA_REPO | Owner + repo name, match `-u` `--repo` | +| TEST_GITEA_KEY | API key, match `RELEASE_KEY_GITEA`. The use of a new variable for the API token is to help avoid accidentally touching a production environment during test execution. | +| TEST_GITEA_RELEASE_TAG | Git tag used to identify the Release. Same as `upload-release`'s positional argument ``. | + diff --git a/src/api/release_attachment.rs b/src/api/release_attachment.rs index e26154c..43cc840 100644 --- a/src/api/release_attachment.rs +++ b/src/api/release_attachment.rs @@ -40,3 +40,92 @@ pub async fn create_release_attachment( } pub fn edit_release_attachment() {} pub fn delete_release_attachment() {} + +#[cfg(test)] +mod tests { + use reqwest::header::{self, ACCEPT}; + + use crate::structs::release::Release; + + + #[tokio::test] + async fn attach_file_exists() { + let server = std::env::var("TEST_GITEA_SERVER") + .expect("Must set server address in env var \"TEST_GITEA_SERVER\""); + let repo = std::env::var("TEST_GITEA_REPO") + .expect("Must set / name in env var \"TEST_GITEA_REPO\""); + let token = format!( + "token {}", + std::env::var("TEST_GITEA_KEY") + .expect("Must set the API token in env var \"TEST_GITEA_KEY\"") + ); + let release_tag = std::env::var("TEST_GITEA_RELEASE_TAG") + .expect("Must set the target release tag in env var \"TEST_GITEA_RELEASE_TAG\""); + + let mut headers = reqwest::header::HeaderMap::new(); + headers.append(ACCEPT, header::HeaderValue::from_static("application/json")); + headers.append("Authorization", token.parse().unwrap()); + + let client = reqwest::Client::builder() + .user_agent(format!( + "gt-tools-autotest-agent{}", + env!("CARGO_PKG_VERSION") + )) + .default_headers(headers) + .build() + .expect("Failed to build reqwest::Client."); + + let release_candidates = + crate::api::release::list_releases( + &client, + &server, + &repo + ) + .await + .expect("Failed to get releases. Pre-conditions unmet, aborting test!"); + + let release = match_release_by_tag(&release_tag, release_candidates) + .expect("Failed to select matching release. Pre-conditions unmet, aborting test!"); + + let api_result = super::create_release_attachment( + &client, + &server, + &repo, + release.id, + vec![String::from("Cargo.toml")], + ) + .await; + } + + #[test] + fn attach_file_missing() { + todo!(); + } + + // Testing utils + fn match_release_by_tag(tag: &String, releases: Vec) -> Option { + let mut release: Option = None; + for rel in releases { + if rel.tag_name == *tag { + // Only store the value if one hasn't been stored already + if let Some(first_release) = &release { + // if there was already a match, begin the error diagnostic creation. + let first_id = first_release.id; + let second_id = rel.id; + assert!( + first_id != second_id, + "FAILURE: Found the same release ID twice while scanning for duplicate tags. How did we get the same one twice?" + ); + eprintln!("ERROR: Two releases have been found for the tag \"{tag}\"."); + eprintln!("ERROR: first ID: {first_id}"); + eprintln!("ERROR: second ID: {second_id}"); + panic!("ERROR: Nonsense detected, I'm bailing out!"); + } else { + // else, store our first (and hopefully only) match + release = Some(rel); + } + } + } + return release; + } +} \ No newline at end of file