diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 269dbe7..08ff4f1 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -17,3 +17,5 @@ jobs: - uses: actions/checkout@v4 - name: Build run: cargo build --verbose + - name: Run tests + run: cargo test --verbose diff --git a/Cargo.lock b/Cargo.lock index b53058e..cdce842 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -261,6 +261,12 @@ version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c7a8fb8a9fbf66c1f703fe16184d10ca0ee9d23be5b4436400408ba54a95005" +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + [[package]] name = "fnv" version = "1.0.7" @@ -347,6 +353,12 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" +[[package]] +name = "futures-timer" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" + [[package]] name = "futures-util" version = "0.3.31" @@ -400,13 +412,27 @@ checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "github-cli" -version = "1.9.2" +version = "1.10.0" dependencies = [ "clap", "octorust", + "paste", + "rstest", "tokio", ] +[[package]] +name = "glob" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" + +[[package]] +name = "hashbrown" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" + [[package]] name = "heck" version = "0.5.0" @@ -631,6 +657,16 @@ dependencies = [ "icu_properties", ] +[[package]] +name = "indexmap" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" +dependencies = [ + "equivalent", + "hashbrown", +] + [[package]] name = "instant" version = "0.1.13" @@ -934,6 +970,12 @@ dependencies = [ "regex", ] +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + [[package]] name = "pem" version = "3.0.5" @@ -986,6 +1028,15 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "proc-macro-crate" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" +dependencies = [ + "toml_edit", +] + [[package]] name = "proc-macro2" version = "1.0.95" @@ -1171,6 +1222,12 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +[[package]] +name = "relative-path" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" + [[package]] name = "reqwest" version = "0.12.20" @@ -1299,6 +1356,36 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rstest" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fc39292f8613e913f7df8fa892b8944ceb47c247b78e1b1ae2f09e019be789d" +dependencies = [ + "futures-timer", + "futures-util", + "rstest_macros", + "rustc_version", +] + +[[package]] +name = "rstest_macros" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f168d99749d307be9de54d23fd226628d99768225ef08f6ffb52e0182a27746" +dependencies = [ + "cfg-if", + "glob", + "proc-macro-crate", + "proc-macro2", + "quote", + "regex", + "relative-path", + "rustc_version", + "syn", + "unicode-ident", +] + [[package]] name = "rustc-demangle" version = "0.1.25" @@ -1311,6 +1398,15 @@ version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + [[package]] name = "rustls" version = "0.23.27" @@ -1392,6 +1488,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "semver" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" + [[package]] name = "serde" version = "1.0.219" @@ -1683,6 +1785,23 @@ dependencies = [ "tokio", ] +[[package]] +name = "toml_datetime" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" + +[[package]] +name = "toml_edit" +version = "0.22.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + [[package]] name = "tower" version = "0.5.2" @@ -2062,6 +2181,15 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "winnow" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95" +dependencies = [ + "memchr", +] + [[package]] name = "wit-bindgen-rt" version = "0.39.0" diff --git a/Cargo.toml b/Cargo.toml index 37faf4b..d27a1fb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,9 +1,11 @@ [package] name = "github-cli" -version = "1.9.2" +version = "1.10.0" edition = "2021" [dependencies] octorust = "0.10.0" clap = { version = "4.5.39", features = ["derive"] } tokio = { version = "1.45.1", features = ["full"] } +rstest = "0.25.0" +paste = "1.0.15" diff --git a/Readme.md b/Readme.md index d9b0721..835a018 100644 --- a/Readme.md +++ b/Readme.md @@ -52,7 +52,7 @@ github-cli release --help ### comment - [x] Сделать создание комментария в issue/pull request -- [ ] Сделать получение комментариев для issue/pull request +- [x] Сделать получение комментариев для issue/pull request - [ ] Сделать редактирование комментария для issue/pull request - [ ] Сделать удаление комментария для issue/pull request diff --git a/src/cli_in/comment_command.rs b/src/cli_in/comment_command.rs index e5c7922..2b4a72a 100644 --- a/src/cli_in/comment_command.rs +++ b/src/cli_in/comment_command.rs @@ -1,4 +1,6 @@ -use clap::{Subcommand}; +use clap::Subcommand; + +use crate::cli_in::set_vars::CommentTarget; #[derive(Subcommand)] pub enum CommentCommand { @@ -11,4 +13,14 @@ pub enum CommentCommand { #[clap(long, short, default_value = "")] body: String, }, + + /// Get all comments from issue/pull request + GetAll { + /// Get all comments from issue/pull request with number + #[clap(long, short)] + number: i64, + /// Get from issue or from pull request (can be only 'issue' or 'pull-request') + #[clap(long, short)] + target: CommentTarget, + }, } diff --git a/src/cli_in/issue_command.rs b/src/cli_in/issue_command.rs index 7192b7d..a06a98e 100644 --- a/src/cli_in/issue_command.rs +++ b/src/cli_in/issue_command.rs @@ -1,4 +1,4 @@ -use clap::{Subcommand}; +use clap::Subcommand; use crate::cli_in::set_vars::{IssuesListStates, States}; diff --git a/src/cli_in/mod.rs b/src/cli_in/mod.rs index b0ea10e..015c4b0 100644 --- a/src/cli_in/mod.rs +++ b/src/cli_in/mod.rs @@ -1,6 +1,6 @@ -pub mod read_cli; -pub mod set_vars; -pub mod issue_command; pub mod comment_command; -pub mod repo_command; +pub mod issue_command; +pub mod read_cli; pub mod release_command; +pub mod repo_command; +pub mod set_vars; diff --git a/src/cli_in/release_command.rs b/src/cli_in/release_command.rs index e413a4b..8ba1c02 100644 --- a/src/cli_in/release_command.rs +++ b/src/cli_in/release_command.rs @@ -12,10 +12,10 @@ pub enum ReleaseCommand { /// Repo name #[clap(long, short)] repo: RepoName, - /// Tag name + /// Tag name #[clap(long)] tag_name: String, - /// Target commit hash (only long variant of commit hash) + /// Target commit hash (only long variant of commit hash) #[clap(long)] target_commitish: String, /// Release name @@ -27,10 +27,10 @@ pub enum ReleaseCommand { /// Name of discussion category (optional) #[clap(long, default_value = "")] discussion_category_name: String, - /// It's draft? (optional) + /// It's draft? (optional) #[clap(long, default_value = None)] draft: Option, - /// It's prerelease? (optional) + /// It's prerelease? (optional) #[clap(long, default_value = None)] prerelease: Option, }, diff --git a/src/cli_in/repo_command.rs b/src/cli_in/repo_command.rs index 66c6ba1..bb5c2fa 100644 --- a/src/cli_in/repo_command.rs +++ b/src/cli_in/repo_command.rs @@ -1,6 +1,11 @@ use clap::Subcommand; -use crate::{cli_in::set_vars::{Orders, ReposListOrgSorts, ReposListOrgTypes, ReposListUserTypes, Visibilities}, git_utils::repo_info::{RepoName, RepoOwner}}; +use crate::{ + cli_in::set_vars::{ + Orders, ReposListOrgSorts, ReposListOrgTypes, ReposListUserTypes, Visibilities, + }, + git_utils::repo_info::{RepoName, RepoOwner}, +}; #[derive(Subcommand)] pub enum RepoCommand { @@ -137,7 +142,7 @@ pub enum RepoCommand { /// Get all repos from user GetAllFromUser { - /// Owner name + /// Owner name #[clap(long)] owner: String, /// Order can be only 'asc' or 'desc' (optional) @@ -151,7 +156,7 @@ pub enum RepoCommand { #[clap(long, short, default_value = "all")] type_value: ReposListUserTypes, ///// NOT WORKING NOW BECAUSE OCTORUST BREAK THIS - ///// Can include: + ///// Can include: ///// - owner: Repositories that are owned by the authenticated user. ///// - collaborator: Repositories that the user has been added to as a collaborator. ///// - organization_member: Repositories that the user has access to through being a member of an organization. This includes every repository on every team that the user is on. diff --git a/src/cli_in/set_vars.rs b/src/cli_in/set_vars.rs index 2db7441..5832138 100644 --- a/src/cli_in/set_vars.rs +++ b/src/cli_in/set_vars.rs @@ -135,3 +135,21 @@ impl ToString for IssuesListStates { } } } + +#[derive(Debug, Clone)] +pub enum CommentTarget { + Issue, + PullRequest, +} + +impl FromStr for CommentTarget { + type Err = String; + + fn from_str(s: &str) -> Result { + match s { + "issue" => Ok(CommentTarget::Issue), + "pull-request" => Ok(CommentTarget::PullRequest), + _ => Err("Bad input. Comment target can be only 'issue' or 'pull-request'".to_string()), + } + } +} diff --git a/src/cli_out/print_in_cli.rs b/src/cli_out/print_in_cli.rs index d2553bb..7844d42 100644 --- a/src/cli_out/print_in_cli.rs +++ b/src/cli_out/print_in_cli.rs @@ -1,4 +1,8 @@ -use octorust::types::{IssueSimple, MinimalRepository, Release}; +use std::process; + +use octorust::types::{ + IssueComment, IssueSimple, MinimalRepository, PullRequestReviewComment, Release, +}; use crate::cli_in::set_vars::IssuesListStates; @@ -48,3 +52,47 @@ pub fn print_repos(repos: Vec, owner: String, owner_type: &st println!("╰────────────────────────────────────────────────────────────────────────────────────────────────"); } } + +pub fn print_comments(list_comments: Vec) { + println!("╭────────────────────────────────────────────────────────────────────────────────────────────────"); + println!("│Comments:"); + println!("╰────────────────────────────────────────────────────────────────────────────────────────────────"); + for comment in list_comments { + println!("╭────────────────────────────────────────────────────────────────────────────────────────────────"); + println!( + "│Who create: {}", + match comment.user { + Some(u) => u.login, + None => { + eprintln!("Bad response from github"); + process::exit(1); + } + } + ); + println!("│Body: {}", comment.body); + println!("╰────────────────────────────────────────────────────────────────────────────────────────────────"); + } +} + +pub fn print_review_comments(list_comments: Vec) { + println!("╭────────────────────────────────────────────────────────────────────────────────────────────────"); + println!("│Review comments:"); + println!("╰────────────────────────────────────────────────────────────────────────────────────────────────"); + for comment in list_comments { + println!("╭────────────────────────────────────────────────────────────────────────────────────────────────"); + println!( + "│Who create: {}", + match comment.user { + Some(u) => u.login, + None => { + eprintln!("Bad response from github"); + process::exit(1); + } + } + ); + println!("│Body: {}", comment.body); + println!("│For line: {}", comment.line); + println!("│In file: {}", comment.path); + println!("╰────────────────────────────────────────────────────────────────────────────────────────────────"); + } +} diff --git a/src/cli_parse/handle_cli.rs b/src/cli_parse/handle_cli.rs index 89c15d2..fcf9b5b 100644 --- a/src/cli_parse/handle_cli.rs +++ b/src/cli_parse/handle_cli.rs @@ -22,7 +22,7 @@ pub async fn handle_cli_command(args: Args, github_client: Client) { } CliCommand::Release { subcommand } => { - handle_release_command(github_client, subcommand).await; - } + handle_release_command(github_client, subcommand).await; + } } } diff --git a/src/cli_parse/handle_commands/handle_comment.rs b/src/cli_parse/handle_commands/handle_comment.rs index 7587b4b..8bc25e4 100644 --- a/src/cli_parse/handle_commands/handle_comment.rs +++ b/src/cli_parse/handle_commands/handle_comment.rs @@ -1,16 +1,23 @@ use octorust::{self, Client}; use std::process; +// use std::str::FromStr; use crate::cli_in::comment_command::CommentCommand; +use crate::cli_in::set_vars::CommentTarget; +use crate::cli_out::print_in_cli::{print_comments, print_review_comments}; use crate::git_utils::comments; -use crate::git_utils::repo_info::Repo; -use crate::git_utils::repo_info::RepoInfo; +use crate::git_utils::repo_info::{Repo, RepoInfo}; +// use crate::git_utils::repo_info::{RepoName, RepoOwner}; pub async fn handle_comment_command(github_client: Client, subcommand: CommentCommand) { match subcommand { CommentCommand::Create { number, body } => { handle_create(github_client, number, body).await; } + + CommentCommand::GetAll { number, target } => { + handle_get_all(github_client, number, target).await + } }; } @@ -27,3 +34,34 @@ async fn handle_create(github_client: Client, number: i64, body: String) { println!("{result}"); } + +async fn handle_get_all(github_client: Client, number: i64, target: CommentTarget) { + let repo_info: RepoInfo = match RepoInfo::new(Repo::Current, None, None) { + Ok(rep) => rep, + Err(message) => { + eprintln!("Error: {message}"); + process::exit(1); + } + }; + + let result = comments::get_all(&github_client, &repo_info, &number).await; + + print_comments(result); + + let review_comments = match target { + CommentTarget::PullRequest => { + comments::get_all_from_review( + &github_client, + &repo_info, + &number, + octorust::types::Sort::Created, + octorust::types::Order::Asc, + ) + .await + } + CommentTarget::Issue => Vec::new(), + }; + if !review_comments.is_empty() { + print_review_comments(review_comments); + } +} diff --git a/src/cli_parse/handle_commands/handle_release.rs b/src/cli_parse/handle_commands/handle_release.rs index 2e57d88..d32f4b2 100644 --- a/src/cli_parse/handle_commands/handle_release.rs +++ b/src/cli_parse/handle_commands/handle_release.rs @@ -10,7 +10,6 @@ use crate::git_utils::repo_info::RepoInfo; use crate::git_utils::repo_info::RepoName; use crate::git_utils::repo_info::RepoOwner; - pub async fn handle_release_command(github_client: Client, subcommand: ReleaseCommand) { match subcommand { ReleaseCommand::Create { diff --git a/src/cli_parse/handle_commands/mod.rs b/src/cli_parse/handle_commands/mod.rs index 7ede74b..197a4af 100644 --- a/src/cli_parse/handle_commands/mod.rs +++ b/src/cli_parse/handle_commands/mod.rs @@ -1,4 +1,4 @@ -pub mod handle_issue; pub mod handle_comment; -pub mod handle_repo; +pub mod handle_issue; pub mod handle_release; +pub mod handle_repo; diff --git a/src/git_utils/comments.rs b/src/git_utils/comments.rs index e8b4d44..8aeec4b 100644 --- a/src/git_utils/comments.rs +++ b/src/git_utils/comments.rs @@ -1,6 +1,8 @@ use std::process; -use octorust::types::PullsUpdateReviewRequest; +use octorust::types::{ + IssueComment, Order, PullRequestReviewComment, PullsUpdateReviewRequest, Sort, +}; use octorust::Client; use crate::git_utils::repo_info::RepoInfo; @@ -31,3 +33,55 @@ pub async fn create( } }; } + +// Get all Comments for issue/pull request without review comments +pub async fn get_all( + github_client: &Client, + repo_info: &RepoInfo, + number: &i64, +) -> Vec { + let list_comments = github_client + .issues() + .list_all_comments( + &repo_info.get_owner(), + &repo_info.get_name(), + number.clone(), + None, + ) + .await; + + return match list_comments { + Ok(c) => c.body, + Err(message) => { + eprintln!("Error: {message}"); + process::exit(1); + } + }; +} +pub async fn get_all_from_review( + github_client: &Client, + repo_info: &RepoInfo, + number: &i64, + sort: Sort, + direction: Order, +) -> Vec { + let list_comments = github_client + .pulls() + .list_all_review_comments( + &repo_info.get_owner(), + &repo_info.get_name(), + number.clone(), + sort, + direction, + None, + ) + .await; + + return match list_comments { + Ok(c) => c.body, + Err(message) => { + eprintln!("Error: {message}"); + process::exit(1); + } + }; +} diff --git a/src/git_utils/repo_info.rs b/src/git_utils/repo_info.rs index 6061296..4693151 100644 --- a/src/git_utils/repo_info.rs +++ b/src/git_utils/repo_info.rs @@ -66,6 +66,7 @@ impl FromStr for RepoName { } } +#[derive(Debug, Clone, PartialEq, Eq)] pub struct RepoInfo { owner: RepoOwner, name: RepoName, @@ -169,8 +170,8 @@ impl RepoInfo { )); } else { let mut new_repo = RepoInfo { - owner: RepoOwner(owner.unwrap().0.trim_start().trim_end().to_string()), - name: RepoName(name.unwrap().0.trim_start().trim_end().to_string()), + owner: RepoOwner(owner.unwrap().0.trim().to_string()), + name: RepoName(name.unwrap().0.trim().to_string()), url: RepoUrl(String::new()), ssh: RepoSsh(String::new()), }; @@ -186,21 +187,123 @@ impl RepoInfo { owner: Option, name: Option, ) -> Result { - match type_repo { Repo::Current => { - - let new_repo = RepoInfo { - owner: RepoOwner(String::new()), - name: RepoName(String::new()), - url: RepoUrl(String::new()), - ssh: RepoSsh(String::new()), - }; - return Self::get_current_repo(new_repo); - } + let new_repo = RepoInfo { + owner: RepoOwner(String::new()), + name: RepoName(String::new()), + url: RepoUrl(String::new()), + ssh: RepoSsh(String::new()), + }; + return Self::get_current_repo(new_repo); + } Repo::Input => { - return Self::create_repo_info(owner, name); - } + return Self::create_repo_info(owner, name); + } } } } + +#[cfg(test)] +mod repo_info_tests { + use super::*; + use paste::paste; + use rstest::rstest; + + // Macros for Repo owner and name tests + macro_rules! repo_main_field_valid_tests { + ($type: ident, $type_name: literal) => { + paste! { + // Tests valid cases + #[rstest] + #[case("aragami3070", "aragami3070")] + #[case("SE-legacy", "SE-legacy")] + #[case("The Drot Team", "The Drot Team")] + fn [](#[case] input: &str, #[case] expected: &str) { + assert_eq!( + $type::from_str(input).unwrap(), + $type(expected.to_string()) + ); + } + + // Tests invalid cases + #[rstest] + #[case("", concat!($type_name, " cannot be empty"))] + #[case("owner/repo", concat!($type_name, " cannot contain '/'"))] + #[case("/owner", concat!($type_name, " cannot contain '/'"))] + #[case("/owner/repo/", concat!($type_name, " cannot contain '/'"))] + fn [](#[case] input: &str, #[case] error: &str) { + assert_eq!($type::from_str(input).unwrap_err(), error); + } + } + }; + } + + // RepoOwner tests + repo_main_field_valid_tests!(RepoOwner, "Repo owner"); + // RepoName tests + repo_main_field_valid_tests!(RepoName, "Repo name"); + + macro_rules! repo_links_field_valid_test { + ($type: ident, $field_name: ident, $start_link: literal, $end_link: literal) => { + paste! { + // Tests valid cases + #[rstest] + #[case( + "aragami3070", + "github-cli", + concat!($start_link, "aragami3070/github-cli", $end_link) + )] + #[case( + " SE-legacy ", + "kg-exam-4sem", + concat!($start_link, "SE-legacy/kg-exam-4sem", $end_link) + )] + #[case( + "The Drot Team", + " Trash-Hack-Back-end", + concat!($start_link, "The-Drot-Team/Trash-Hack-Back-end", $end_link) + )] + fn [](#[case] owner: &str, #[case] name: &str, #[case] expected: &str) { + let repo = RepoInfo::new( + Repo::Input, + Some(RepoOwner(owner.to_string())), + Some(RepoName(name.to_string())), + ); + assert_eq!(repo.unwrap().$field_name.0.replace(" ", "-"), expected); + } + } + }; + } + + // RepoUrl valid test + repo_links_field_valid_test!(RepoUrl, url, "https://github.com/", "/"); + + // RepoSsh valid test + repo_links_field_valid_test!(RepoSsh, ssh, "git@github.com:", ".git"); + + // Tests valid case + #[test] + fn valid_new_repo_info() { + let repo_input = RepoInfo::new( + Repo::Input, + Some(RepoOwner("aragami3070".to_string())), + Some(RepoName("github-cli".to_string())), + ); + let repo_current = RepoInfo::new(Repo::Current, None, None); + assert_eq!(repo_input.unwrap(), repo_current.unwrap()); + } + + // Tests invalid case + #[rstest] + #[case(None, None)] + #[case(Some(RepoOwner("aragami3070".to_string())), None)] + #[case(None, Some(RepoName("github-cli".to_string())))] + fn invalid_new_input_repo_info( + #[case] owner: Option, + #[case] name: Option, + ) { + let repo_current = RepoInfo::new(Repo::Input, owner, name); + assert_eq!(repo_current.unwrap_err().kind(), io::ErrorKind::NotFound); + } +}