Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 5 additions & 16 deletions rust/src/hosting/app/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::scopes::HOSTING_APPLICATION_CREATE as APP_CREATE;

#[derive(Debug, Clone, clap::Args)]
struct AppCreateArgs {
/// Hosting product.
/// Application type (required).
#[arg(long = "app-type", value_name = "TYPE", ignore_case = true)]
app_type: HostingAppType,

Expand Down Expand Up @@ -122,9 +122,10 @@ fn create_err(e: ClientError, app_type: HostingAppType) -> cli_engine::CliCoreEr

#[cfg(test)]
mod tests {
use cli_engine::{Cli, CliConfig, Stage};
use cli_engine::Cli;

use super::*;
use crate::hosting::test_support::{cli, run_hosting};

fn fix_for(status: u16, issue: &str, app_type: HostingAppType) -> Option<String> {
let err = create_err(
Expand Down Expand Up @@ -216,22 +217,10 @@ mod tests {
assert!(poll_description(HostingAppType::Mhwp).contains("Coming Soon"));
}

fn cli(mhwp: bool) -> Cli {
let mut config = CliConfig::new("gddy", "GoDaddy developer CLI", "gddy")
.with_min_stage(Stage::Beta)
// Unregistered provider: commands that pass parsing stop at auth.
.with_default_auth_provider("godaddy")
.with_module(crate::hosting::module());
if mhwp {
config = config.with_feature_override("hosting-mhwp", Stage::Ga);
}
Cli::new(config)
}

async fn run(cli: &Cli, args: &[&str]) -> String {
let mut argv = vec!["gddy", "hosting", "app"];
let mut argv = vec!["app"];
argv.extend_from_slice(args);
cli.run(argv).await.rendered
run_hosting(cli, &argv).await
}

const REJECTED: &str = "invalid value 'MHWP'";
Expand Down
12 changes: 4 additions & 8 deletions rust/src/hosting/app/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@ use serde_json::{Value, json};

use crate::hosting::common::{
HostingAppSummary, HostingAppType, app_type_command, client_err, make_client, next_page_token,
supported_app_types,
};
use crate::next_action::next_action;
use crate::scopes::HOSTING_APPLICATION_READ as APP_READ;

#[derive(Debug, Clone, clap::Args)]
struct AppListArgs {
/// Hosting product.
/// Application type (required).
#[arg(long = "app-type", value_name = "TYPE", ignore_case = true)]
app_type: HostingAppType,

Expand All @@ -22,13 +21,10 @@ struct AppListArgs {
pub(super) fn command(mhwp: bool) -> RuntimeCommandSpec {
RuntimeCommandSpec::new_typed_with_context::<AppListArgs, _, _, _>(
app_type_command::<AppListArgs>("list", "List hosting applications", mhwp)
.with_long(format!(
.with_long(
"List all hosting applications of a given type. Results are autopaginated — \
all pages are fetched and combined. Use --limit to cap the total returned.\n\
\n\
--app-type is required. Currently supported: {}.",
supported_app_types(mhwp)
))
all pages are fetched and combined. Use --limit to cap the total returned.",
)
.with_system("hosting")
.with_tier(Tier::Read)
.with_scopes(&[APP_READ])
Expand Down
2 changes: 1 addition & 1 deletion rust/src/hosting/app/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pub(super) fn group(mhwp: bool) -> RuntimeGroupSpec {
.with_alias("apps")
.with_long(format!(
"Work with hosting applications. Use --app-type on list and create to \
specify the product type (currently {}).",
specify the application type (currently {}).",
supported_app_types(mhwp)
)),
)
Expand Down
2 changes: 2 additions & 0 deletions rust/src/hosting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ mod runtime;
mod secrets;
mod source;
mod subscription;
#[cfg(test)]
mod test_support;

use cli_engine::{GroupSpec, Module, RuntimeGroupSpec};

Expand Down
4 changes: 2 additions & 2 deletions rust/src/hosting/subscription/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::scopes::HOSTING_SUBSCRIPTION_READ as SUB_READ;

#[derive(Debug, Clone, clap::Args)]
struct SubscriptionListArgs {
/// Hosting product to list (WEB_HOSTING or MANAGED_WORDPRESS).
/// Hosting product (required).
#[arg(long, value_name = "PRODUCT", ignore_case = true)]
hosting_product: HostingProduct,

Expand All @@ -28,7 +28,7 @@ pub(super) fn command() -> RuntimeCommandSpec {
)
.with_long(
"List hosting plan subscriptions available to attach to applications. \
--hosting-product is required. Results are autopaginated.",
Results are autopaginated.",
)
.with_system("hosting")
.with_tier(Tier::Read)
Expand Down
57 changes: 57 additions & 0 deletions rust/src/hosting/test_support.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
use cli_engine::{Cli, CliConfig, Stage};

pub(crate) fn cli(mhwp: bool) -> Cli {
let mut config = CliConfig::new("gddy", "GoDaddy developer CLI", "gddy")
.with_min_stage(Stage::Beta)
// Unregistered provider: commands that pass parsing stop at auth.
.with_default_auth_provider("godaddy")
.with_module(crate::hosting::module());
if mhwp {
config = config.with_feature_override("hosting-mhwp", Stage::Ga);
}
Cli::new(config)
}

/// Runs `gddy hosting <args>` and returns the rendered output.
pub(crate) async fn run_hosting(cli: &Cli, args: &[&str]) -> String {
let mut argv = vec!["gddy", "hosting"];
argv.extend_from_slice(args);
cli.run(argv).await.rendered
}

#[tokio::test]
async fn required_flags_are_marked_in_help_and_enforced() {
let cli = cli(false);
let cases: [(&[&str], &str); 3] = [
(&["app", "list"], "--app-type"),
(&["app", "create", "--name", "x"], "--app-type"),
(&["subscription", "list"], "--hosting-product"),
];
for (command, flag) in cases {
let missing = run_hosting(&cli, command).await;
assert!(
missing.contains("required arguments were not provided") && missing.contains(flag),
"{command:?}: {missing}"
);

let mut help_args = command.to_vec();
help_args.push("--help");
let help = run_hosting(&cli, &help_args).await;
// The entry is the flag line plus its description, up to the next flag.
let entry: Vec<&str> = help
.lines()
.skip_while(|line| !line.trim_start().starts_with(flag))
.enumerate()
.take_while(|(i, line)| *i == 0 || !line.trim_start().starts_with("-"))
.map(|(_, line)| line)
.collect();
assert!(
!entry.is_empty(),
"{command:?}: no entry for {flag}: {help}"
);
assert!(
entry.iter().any(|line| line.contains("(required)")),
"{command:?}: {help}"
);
}
}
Loading