This is an automated email from the ASF dual-hosted git repository.

hubcio pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iggy.git


The following commit(s) were added to refs/heads/master by this push:
     new 5556d30a6 feat(cli): add context show and session status commands 
(#3096)
5556d30a6 is described below

commit 5556d30a6d7390bee89a60153c657aeeb0eb55a1
Author: Atharva Lade <[email protected]>
AuthorDate: Wed May 6 05:07:27 2026 -0500

    feat(cli): add context show and session status commands (#3096)
---
 core/cli/src/args/context.rs                       |  18 ++
 core/cli/src/args/mod.rs                           |  10 +
 .../cli/context/mod.rs => cli/src/args/session.rs} |  24 +-
 core/cli/src/commands/binary_context/mod.rs        |   1 +
 .../src/commands/binary_context/show_context.rs    | 252 +++++++++++++++++++
 core/cli/src/commands/binary_system/mod.rs         |   1 +
 .../src/commands/binary_system/session_status.rs   |  93 +++++++
 core/cli/src/main.rs                               |  12 +
 core/integration/tests/cli/context/mod.rs          |   1 +
 .../tests/cli/context/test_context_show_command.rs | 269 +++++++++++++++++++++
 .../tests/cli/general/test_help_command.rs         |   1 +
 .../tests/cli/general/test_overview_command.rs     |   1 +
 12 files changed, 677 insertions(+), 6 deletions(-)

diff --git a/core/cli/src/args/context.rs b/core/cli/src/args/context.rs
index 1c7d9089c..50ef254c8 100644
--- a/core/cli/src/args/context.rs
+++ b/core/cli/src/args/context.rs
@@ -60,6 +60,17 @@ pub(crate) enum ContextAction {
     ///  iggy context delete production
     #[clap(verbatim_doc_comment, visible_alias = "d")]
     Delete(ContextDeleteArgs),
+
+    /// Show details of a specific context
+    ///
+    /// Displays the full configuration of a named context including
+    /// transport, server addresses, TLS settings, and credentials.
+    ///
+    /// Examples
+    ///  iggy context show default
+    ///  iggy context show production
+    #[clap(verbatim_doc_comment, visible_alias = "s")]
+    Show(ContextShowArgs),
 }
 
 #[derive(Debug, Clone, Args)]
@@ -148,6 +159,13 @@ pub(crate) struct ContextDeleteArgs {
     pub(crate) context_name: String,
 }
 
+#[derive(Debug, Clone, Args)]
+pub(crate) struct ContextShowArgs {
+    /// Name of the context to show
+    #[arg(value_parser = clap::value_parser!(String))]
+    pub(crate) context_name: String,
+}
+
 #[cfg(test)]
 mod tests {
     use super::*;
diff --git a/core/cli/src/args/mod.rs b/core/cli/src/args/mod.rs
index 428d4d5e4..a9ed50160 100644
--- a/core/cli/src/args/mod.rs
+++ b/core/cli/src/args/mod.rs
@@ -45,6 +45,9 @@ use crate::args::{
 #[cfg(feature = "login-session")]
 use crate::args::system::LoginArgs;
 
+#[cfg(feature = "login-session")]
+use crate::args::session::SessionAction;
+
 use self::user::UserAction;
 
 pub(crate) mod client;
@@ -63,6 +66,9 @@ pub(crate) mod system;
 pub(crate) mod topic;
 pub(crate) mod user;
 
+#[cfg(feature = "login-session")]
+pub(crate) mod session;
+
 static CARGO_BIN_NAME: &str = env!("CARGO_BIN_NAME");
 static CARGO_PKG_HOMEPAGE: &str = env!("CARGO_PKG_HOMEPAGE");
 
@@ -206,6 +212,10 @@ pub(crate) enum Command {
     /// execute any command that requires authentication.
     #[clap(verbatim_doc_comment, visible_alias = "lo")]
     Logout,
+    #[cfg(feature = "login-session")]
+    /// login session operations
+    #[command(subcommand, visible_alias = "sess")]
+    Session(SessionAction),
 }
 
 impl IggyConsoleArgs {
diff --git a/core/integration/tests/cli/context/mod.rs 
b/core/cli/src/args/session.rs
similarity index 55%
copy from core/integration/tests/cli/context/mod.rs
copy to core/cli/src/args/session.rs
index 1bc857c6c..2243a225a 100644
--- a/core/integration/tests/cli/context/mod.rs
+++ b/core/cli/src/args/session.rs
@@ -16,10 +16,22 @@
  * under the License.
  */
 
-mod common;
+use clap::Subcommand;
 
-mod test_context_applied;
-mod test_context_create_command;
-mod test_context_delete_command;
-mod test_context_list_command;
-mod test_context_use_command;
+#[derive(Debug, Clone, Subcommand)]
+pub(crate) enum SessionAction {
+    /// Show current login session status
+    ///
+    /// Displays whether you have an active login session and which
+    /// server it is connected to. This checks the local credential
+    /// store without contacting the server.
+    ///
+    /// Note: only checks whether a token exists in the keyring.
+    /// A stale or expired token will still report as active.
+    /// Use 'iggy me' to verify the session is valid server-side.
+    ///
+    /// Examples
+    ///  iggy session status
+    #[clap(verbatim_doc_comment, visible_alias = "s")]
+    Status,
+}
diff --git a/core/cli/src/commands/binary_context/mod.rs 
b/core/cli/src/commands/binary_context/mod.rs
index bad021e21..8037ca566 100644
--- a/core/cli/src/commands/binary_context/mod.rs
+++ b/core/cli/src/commands/binary_context/mod.rs
@@ -21,4 +21,5 @@ pub mod common;
 pub mod create_context;
 pub mod delete_context;
 pub mod get_contexts;
+pub mod show_context;
 pub mod use_context;
diff --git a/core/cli/src/commands/binary_context/show_context.rs 
b/core/cli/src/commands/binary_context/show_context.rs
new file mode 100644
index 000000000..882caf116
--- /dev/null
+++ b/core/cli/src/commands/binary_context/show_context.rs
@@ -0,0 +1,252 @@
+/* Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+use anyhow::bail;
+use async_trait::async_trait;
+use comfy_table::Table;
+use tracing::{Level, event};
+
+use crate::commands::cli_command::{CliCommand, PRINT_TARGET};
+use iggy_common::Client;
+
+use super::common::{ContextConfig, ContextManager};
+
+const MASKED_VALUE: &str = "********";
+
+pub struct ShowContextCmd {
+    context_name: String,
+}
+
+impl ShowContextCmd {
+    pub fn new(context_name: String) -> Self {
+        Self { context_name }
+    }
+
+    fn add_opt_str(table: &mut Table, label: &str, value: &Option<String>) {
+        if let Some(ref v) = *value {
+            table.add_row(vec![label, v]);
+        }
+    }
+
+    fn add_opt_bool(table: &mut Table, label: &str, value: Option<bool>) {
+        if let Some(v) = value {
+            table.add_row(vec![label, &v.to_string()]);
+        }
+    }
+
+    fn add_opt_u16(table: &mut Table, label: &str, value: Option<u16>) {
+        if let Some(v) = value {
+            table.add_row(vec![label, &v.to_string()]);
+        }
+    }
+
+    fn add_opt_u32(table: &mut Table, label: &str, value: Option<u32>) {
+        if let Some(v) = value {
+            table.add_row(vec![label, &v.to_string()]);
+        }
+    }
+
+    fn add_opt_u64(table: &mut Table, label: &str, value: Option<u64>) {
+        if let Some(v) = value {
+            table.add_row(vec![label, &v.to_string()]);
+        }
+    }
+
+    fn add_masked(table: &mut Table, label: &str, value: &Option<String>) {
+        if value.is_some() {
+            table.add_row(vec![label, MASKED_VALUE]);
+        }
+    }
+
+    fn build_table(name: &str, is_active: bool, config: &ContextConfig) -> 
Table {
+        let mut table = Table::new();
+        table.set_header(vec!["Property", "Value"]);
+
+        let display_name = if is_active {
+            format!("{name}*")
+        } else {
+            name.to_string()
+        };
+        table.add_row(vec!["Name", &display_name]);
+
+        let iggy = &config.iggy;
+
+        Self::add_opt_str(&mut table, "Transport", &iggy.transport);
+        Self::add_masked(&mut table, "Encryption Key", &iggy.encryption_key);
+        Self::add_opt_str(
+            &mut table,
+            "Credentials Username",
+            &iggy.credentials_username,
+        );
+        Self::add_masked(
+            &mut table,
+            "Credentials Password",
+            &iggy.credentials_password,
+        );
+
+        Self::add_opt_str(&mut table, "HTTP API URL", &iggy.http_api_url);
+        Self::add_opt_u32(&mut table, "HTTP Retries", iggy.http_retries);
+
+        Self::add_opt_str(&mut table, "TCP Server Address", 
&iggy.tcp_server_address);
+        Self::add_opt_u32(
+            &mut table,
+            "TCP Reconnection Max Retries",
+            iggy.tcp_reconnection_max_retries,
+        );
+        Self::add_opt_str(
+            &mut table,
+            "TCP Reconnection Interval",
+            &iggy.tcp_reconnection_interval,
+        );
+        Self::add_opt_bool(&mut table, "TCP TLS Enabled", 
iggy.tcp_tls_enabled);
+        Self::add_opt_str(&mut table, "TCP TLS Domain", &iggy.tcp_tls_domain);
+
+        Self::add_opt_str(&mut table, "QUIC Client Address", 
&iggy.quic_client_address);
+        Self::add_opt_str(&mut table, "QUIC Server Address", 
&iggy.quic_server_address);
+        Self::add_opt_str(&mut table, "QUIC Server Name", 
&iggy.quic_server_name);
+        Self::add_opt_u32(
+            &mut table,
+            "QUIC Reconnection Max Retries",
+            iggy.quic_reconnection_max_retries,
+        );
+        Self::add_opt_str(
+            &mut table,
+            "QUIC Reconnection Interval",
+            &iggy.quic_reconnection_interval,
+        );
+        Self::add_opt_u64(
+            &mut table,
+            "QUIC Max Concurrent Bidi Streams",
+            iggy.quic_max_concurrent_bidi_streams,
+        );
+        Self::add_opt_u64(
+            &mut table,
+            "QUIC Datagram Send Buffer Size",
+            iggy.quic_datagram_send_buffer_size,
+        );
+        Self::add_opt_u16(&mut table, "QUIC Initial MTU", 
iggy.quic_initial_mtu);
+        Self::add_opt_u64(&mut table, "QUIC Send Window", 
iggy.quic_send_window);
+        Self::add_opt_u64(&mut table, "QUIC Receive Window", 
iggy.quic_receive_window);
+        Self::add_opt_u64(
+            &mut table,
+            "QUIC Response Buffer Size",
+            iggy.quic_response_buffer_size,
+        );
+        Self::add_opt_u64(
+            &mut table,
+            "QUIC Keep Alive Interval",
+            iggy.quic_keep_alive_interval,
+        );
+        Self::add_opt_u64(
+            &mut table,
+            "QUIC Max Idle Timeout",
+            iggy.quic_max_idle_timeout,
+        );
+        Self::add_opt_bool(
+            &mut table,
+            "QUIC Validate Certificate",
+            iggy.quic_validate_certificate,
+        );
+
+        Self::add_opt_str(
+            &mut table,
+            "WebSocket Server Address",
+            &iggy.websocket_server_address,
+        );
+        Self::add_opt_u32(
+            &mut table,
+            "WebSocket Reconnection Max Retries",
+            iggy.websocket_reconnection_max_retries,
+        );
+        Self::add_opt_str(
+            &mut table,
+            "WebSocket Reconnection Interval",
+            &iggy.websocket_reconnection_interval,
+        );
+
+        if let Some(ref username) = config.username {
+            table.add_row(vec!["Username", username]);
+        }
+        Self::add_masked(&mut table, "Password", &config.password);
+        Self::add_masked(&mut table, "Token", &config.token);
+        Self::add_opt_str(&mut table, "Token Name", &config.token_name);
+
+        for (key, value) in &config.extra {
+            table.add_row(vec![key.as_str(), &value.to_string()]);
+        }
+
+        table
+    }
+}
+
+#[async_trait]
+impl CliCommand for ShowContextCmd {
+    fn explain(&self) -> String {
+        let context_name = &self.context_name;
+        format!("show context {context_name}")
+    }
+
+    fn login_required(&self) -> bool {
+        false
+    }
+
+    fn connection_required(&self) -> bool {
+        false
+    }
+
+    async fn execute_cmd(&mut self, _client: &dyn Client) -> 
anyhow::Result<(), anyhow::Error> {
+        let mut context_mgr = ContextManager::default();
+        let contexts_map = context_mgr.get_contexts().await?;
+        let active_context_key = context_mgr.get_active_context_key().await?;
+
+        let config = match contexts_map.get(&self.context_name) {
+            Some(config) => config,
+            None => bail!("context '{}' not found", self.context_name),
+        };
+
+        let is_active = self.context_name == active_context_key;
+        let table = Self::build_table(&self.context_name, is_active, config);
+
+        event!(target: PRINT_TARGET, Level::INFO, "{table}");
+
+        Ok(())
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn should_return_explain_message() {
+        let cmd = ShowContextCmd::new("production".to_string());
+        assert_eq!(cmd.explain(), "show context production");
+    }
+
+    #[test]
+    fn should_not_require_login() {
+        let cmd = ShowContextCmd::new("test".to_string());
+        assert!(!cmd.login_required());
+    }
+
+    #[test]
+    fn should_not_require_connection() {
+        let cmd = ShowContextCmd::new("test".to_string());
+        assert!(!cmd.connection_required());
+    }
+}
diff --git a/core/cli/src/commands/binary_system/mod.rs 
b/core/cli/src/commands/binary_system/mod.rs
index 18e57b5c3..42c0bc1dc 100644
--- a/core/cli/src/commands/binary_system/mod.rs
+++ b/core/cli/src/commands/binary_system/mod.rs
@@ -21,5 +21,6 @@ pub mod logout;
 pub mod me;
 pub mod ping;
 pub mod session;
+pub mod session_status;
 pub mod snapshot;
 pub mod stats;
diff --git a/core/cli/src/commands/binary_system/session_status.rs 
b/core/cli/src/commands/binary_system/session_status.rs
new file mode 100644
index 000000000..94ee0ee16
--- /dev/null
+++ b/core/cli/src/commands/binary_system/session_status.rs
@@ -0,0 +1,93 @@
+/* Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+use crate::commands::binary_system::session::ServerSession;
+use crate::commands::cli_command::{CliCommand, PRINT_TARGET};
+use async_trait::async_trait;
+use comfy_table::Table;
+use iggy_common::Client;
+use tracing::{Level, event};
+
+pub struct SessionStatusCmd {
+    server_session: ServerSession,
+}
+
+impl SessionStatusCmd {
+    pub fn new(server_address: String) -> Self {
+        Self {
+            server_session: ServerSession::new(server_address),
+        }
+    }
+}
+
+#[async_trait]
+impl CliCommand for SessionStatusCmd {
+    fn explain(&self) -> String {
+        "session status command".to_owned()
+    }
+
+    fn login_required(&self) -> bool {
+        false
+    }
+
+    fn connection_required(&self) -> bool {
+        false
+    }
+
+    async fn execute_cmd(&mut self, _client: &dyn Client) -> 
anyhow::Result<(), anyhow::Error> {
+        let is_active = self.server_session.is_active();
+        let server_address = self.server_session.get_server_address();
+
+        let mut table = Table::new();
+        table.set_header(vec!["Property", "Value"]);
+        table.add_row(vec!["Server Address", server_address]);
+        let active = if is_active {
+            "Yes (token presence only, freshness not verified)"
+        } else {
+            "No"
+        };
+        table.add_row(vec!["Session Active", active]);
+
+        event!(target: PRINT_TARGET, Level::INFO, "{table}");
+
+        Ok(())
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn should_return_explain_message() {
+        let cmd = SessionStatusCmd::new("127.0.0.1:8090".to_string());
+        assert_eq!(cmd.explain(), "session status command");
+    }
+
+    #[test]
+    fn should_not_require_login() {
+        let cmd = SessionStatusCmd::new("127.0.0.1:8090".to_string());
+        assert!(!cmd.login_required());
+    }
+
+    #[test]
+    fn should_not_require_connection() {
+        let cmd = SessionStatusCmd::new("127.0.0.1:8090".to_string());
+        assert!(!cmd.connection_required());
+    }
+}
diff --git a/core/cli/src/main.rs b/core/cli/src/main.rs
index 98c300ada..543003dac 100644
--- a/core/cli/src/main.rs
+++ b/core/cli/src/main.rs
@@ -43,6 +43,7 @@ use iggy::prelude::{Aes256GcmEncryptor, Args, EncryptorKind, 
PersonalAccessToken
 use iggy_cli::commands::binary_context::common::ContextManager;
 use iggy_cli::commands::binary_context::create_context::CreateContextCmd;
 use iggy_cli::commands::binary_context::delete_context::DeleteContextCmd;
+use iggy_cli::commands::binary_context::show_context::ShowContextCmd;
 use iggy_cli::commands::binary_context::use_context::UseContextCmd;
 use iggy_cli::commands::binary_segments::delete_segments::DeleteSegmentsCmd;
 use iggy_cli::commands::binary_system::snapshot::GetSnapshotCmd;
@@ -95,6 +96,8 @@ use tracing::{Level, event};
 
 #[cfg(feature = "login-session")]
 mod main_login_session {
+    pub(crate) use crate::args::session::SessionAction;
+    pub(crate) use 
iggy_cli::commands::binary_system::session_status::SessionStatusCmd;
     pub(crate) use iggy_cli::commands::binary_system::{login::LoginCmd, 
logout::LogoutCmd};
     pub(crate) use 
iggy_cli::commands::utils::login_session_expiry::LoginSessionExpiry;
 }
@@ -337,6 +340,9 @@ fn get_command(
             ContextAction::Delete(delete_args) => {
                 
Box::new(DeleteContextCmd::new(delete_args.context_name.clone()))
             }
+            ContextAction::Show(show_args) => {
+                Box::new(ShowContextCmd::new(show_args.context_name.clone()))
+            }
         },
         #[cfg(feature = "login-session")]
         Command::Login(login_args) => Box::new(LoginCmd::new(
@@ -345,6 +351,12 @@ fn get_command(
         )),
         #[cfg(feature = "login-session")]
         Command::Logout => 
Box::new(LogoutCmd::new(iggy_args.get_server_address().unwrap())),
+        #[cfg(feature = "login-session")]
+        Command::Session(command) => match command {
+            SessionAction::Status => Box::new(SessionStatusCmd::new(
+                iggy_args.get_server_address().unwrap(),
+            )),
+        },
     }
 }
 
diff --git a/core/integration/tests/cli/context/mod.rs 
b/core/integration/tests/cli/context/mod.rs
index 1bc857c6c..01ca1a747 100644
--- a/core/integration/tests/cli/context/mod.rs
+++ b/core/integration/tests/cli/context/mod.rs
@@ -22,4 +22,5 @@ mod test_context_applied;
 mod test_context_create_command;
 mod test_context_delete_command;
 mod test_context_list_command;
+mod test_context_show_command;
 mod test_context_use_command;
diff --git a/core/integration/tests/cli/context/test_context_show_command.rs 
b/core/integration/tests/cli/context/test_context_show_command.rs
new file mode 100644
index 000000000..14fd72cb4
--- /dev/null
+++ b/core/integration/tests/cli/context/test_context_show_command.rs
@@ -0,0 +1,269 @@
+/* Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+use std::collections::BTreeMap;
+
+use crate::cli::common::{
+    CLAP_INDENT, IggyCmdCommand, IggyCmdTest, IggyCmdTestCase, TestHelpCmd, 
USAGE_PREFIX,
+};
+use assert_cmd::assert::Assert;
+use async_trait::async_trait;
+use iggy::prelude::Client;
+use iggy_cli::commands::binary_context::common::ContextConfig;
+use iggy_common::ArgsOptional;
+use predicates::str::contains;
+use serial_test::parallel;
+
+use super::common::TestIggyContext;
+
+struct TestContextShowCmd {
+    test_iggy_context: TestIggyContext,
+    context_to_show: String,
+    expected_rows: Vec<String>,
+}
+
+impl TestContextShowCmd {
+    fn new(
+        test_iggy_context: TestIggyContext,
+        context_to_show: String,
+        expected_rows: Vec<String>,
+    ) -> Self {
+        Self {
+            test_iggy_context,
+            context_to_show,
+            expected_rows,
+        }
+    }
+}
+
+#[async_trait]
+impl IggyCmdTestCase for TestContextShowCmd {
+    async fn prepare_server_state(&mut self, _client: &dyn Client) {
+        self.test_iggy_context.prepare().await;
+    }
+
+    fn get_command(&self) -> IggyCmdCommand {
+        IggyCmdCommand::new()
+            .env(
+                "IGGY_HOME",
+                self.test_iggy_context.get_iggy_home().to_str().unwrap(),
+            )
+            .arg("context")
+            .arg("show")
+            .arg(self.context_to_show.clone())
+            .with_env_credentials()
+    }
+
+    fn verify_command(&self, command_state: Assert) {
+        let mut command_state = command_state.success();
+
+        for row in &self.expected_rows {
+            command_state = command_state.stdout(contains(row.as_str()));
+        }
+    }
+
+    async fn verify_server_state(&self, _client: &dyn Client) {}
+}
+
+#[tokio::test]
+#[parallel]
+pub async fn should_show_context_with_all_fields() {
+    let mut iggy_cmd_test = IggyCmdTest::default();
+    iggy_cmd_test.setup().await;
+
+    let config = ContextConfig {
+        username: Some("admin".to_string()),
+        password: Some("secret".to_string()),
+        token: None,
+        token_name: None,
+        iggy: ArgsOptional {
+            transport: Some("tcp".to_string()),
+            tcp_server_address: Some("10.0.0.1:8090".to_string()),
+            tcp_tls_enabled: Some(true),
+            ..Default::default()
+        },
+        extra: Default::default(),
+    };
+
+    iggy_cmd_test
+        .execute_test(TestContextShowCmd::new(
+            TestIggyContext::new(
+                Some(BTreeMap::from([
+                    ("default".to_string(), ContextConfig::default()),
+                    ("production".to_string(), config),
+                ])),
+                None,
+            ),
+            "production".to_string(),
+            vec![
+                "production".to_string(),
+                "tcp".to_string(),
+                "10.0.0.1:8090".to_string(),
+                "true".to_string(),
+                "admin".to_string(),
+                "********".to_string(),
+            ],
+        ))
+        .await;
+}
+
+#[tokio::test]
+#[parallel]
+pub async fn should_show_default_context() {
+    let mut iggy_cmd_test = IggyCmdTest::default();
+    iggy_cmd_test.setup().await;
+
+    iggy_cmd_test
+        .execute_test(TestContextShowCmd::new(
+            TestIggyContext::new(None, None),
+            "default".to_string(),
+            vec!["default*".to_string()],
+        ))
+        .await;
+}
+
+#[tokio::test]
+#[parallel]
+pub async fn should_show_active_context_with_asterisk() {
+    let mut iggy_cmd_test = IggyCmdTest::default();
+    iggy_cmd_test.setup().await;
+
+    iggy_cmd_test
+        .execute_test(TestContextShowCmd::new(
+            TestIggyContext::new(
+                Some(BTreeMap::from([
+                    ("default".to_string(), ContextConfig::default()),
+                    ("dev".to_string(), ContextConfig::default()),
+                ])),
+                Some("dev".to_string()),
+            ),
+            "dev".to_string(),
+            vec!["dev*".to_string()],
+        ))
+        .await;
+}
+
+struct TestContextShowNotFoundCmd {
+    test_iggy_context: TestIggyContext,
+    context_to_show: String,
+}
+
+impl TestContextShowNotFoundCmd {
+    fn new(test_iggy_context: TestIggyContext, context_to_show: String) -> 
Self {
+        Self {
+            test_iggy_context,
+            context_to_show,
+        }
+    }
+}
+
+#[async_trait]
+impl IggyCmdTestCase for TestContextShowNotFoundCmd {
+    async fn prepare_server_state(&mut self, _client: &dyn Client) {
+        self.test_iggy_context.prepare().await;
+    }
+
+    fn get_command(&self) -> IggyCmdCommand {
+        IggyCmdCommand::new()
+            .env(
+                "IGGY_HOME",
+                self.test_iggy_context.get_iggy_home().to_str().unwrap(),
+            )
+            .arg("context")
+            .arg("show")
+            .arg(self.context_to_show.clone())
+            .with_env_credentials()
+    }
+
+    fn verify_command(&self, command_state: Assert) {
+        command_state.failure().stderr(contains("not found"));
+    }
+
+    async fn verify_server_state(&self, _client: &dyn Client) {}
+}
+
+#[tokio::test]
+#[parallel]
+pub async fn should_fail_for_nonexistent_context() {
+    let mut iggy_cmd_test = IggyCmdTest::default();
+    iggy_cmd_test.setup().await;
+
+    iggy_cmd_test
+        .execute_test(TestContextShowNotFoundCmd::new(
+            TestIggyContext::new(None, None),
+            "nonexistent".to_string(),
+        ))
+        .await;
+}
+
+#[tokio::test]
+#[parallel]
+pub async fn should_help_match() {
+    let mut iggy_cmd_test = IggyCmdTest::default();
+
+    iggy_cmd_test
+        .execute_test_for_help_command(TestHelpCmd::new(
+            vec!["context", "show", "--help"],
+            format!(
+                r#"Show details of a specific context
+
+Displays the full configuration of a named context including
+transport, server addresses, TLS settings, and credentials.
+
+Examples
+ iggy context show default
+ iggy context show production
+
+{USAGE_PREFIX} context show <CONTEXT_NAME>
+
+Arguments:
+  <CONTEXT_NAME>
+{CLAP_INDENT}Name of the context to show
+
+Options:
+  -h, --help
+{CLAP_INDENT}Print help (see a summary with '-h')
+"#,
+            ),
+        ))
+        .await;
+}
+
+#[tokio::test]
+#[parallel]
+pub async fn should_short_help_match() {
+    let mut iggy_cmd_test = IggyCmdTest::default();
+
+    iggy_cmd_test
+        .execute_test_for_help_command(TestHelpCmd::new(
+            vec!["context", "show", "-h"],
+            format!(
+                r#"Show details of a specific context
+
+{USAGE_PREFIX} context show <CONTEXT_NAME>
+
+Arguments:
+  <CONTEXT_NAME>  Name of the context to show
+
+Options:
+  -h, --help  Print help (see more with '--help')
+"#,
+            ),
+        ))
+        .await;
+}
diff --git a/core/integration/tests/cli/general/test_help_command.rs 
b/core/integration/tests/cli/general/test_help_command.rs
index 8cf0735b1..365345696 100644
--- a/core/integration/tests/cli/general/test_help_command.rs
+++ b/core/integration/tests/cli/general/test_help_command.rs
@@ -51,6 +51,7 @@ Commands:
   context          context operations [aliases: ctx]
   login            login to Iggy server [aliases: li]
   logout           logout from Iggy server [aliases: lo]
+  session          login session operations [aliases: sess]
   help             Print this message or the help of the given subcommand(s)
 
 Options:
diff --git a/core/integration/tests/cli/general/test_overview_command.rs 
b/core/integration/tests/cli/general/test_overview_command.rs
index a5a88d2e9..8a32f9dff 100644
--- a/core/integration/tests/cli/general/test_overview_command.rs
+++ b/core/integration/tests/cli/general/test_overview_command.rs
@@ -62,6 +62,7 @@ Commands:
   context          context operations [aliases: ctx]
   login            login to Iggy server [aliases: li]
   logout           logout from Iggy server [aliases: lo]
+  session          login session operations [aliases: sess]
   help             Print this message or the help of the given subcommand(s)
 
 

Reply via email to