From 05f10ee42f79e6097d01bfedfdaec5379a450770 Mon Sep 17 00:00:00 2001 From: Brandon Corbett Date: Mon, 20 Jul 2026 10:13:52 -0400 Subject: [PATCH] chore: fix the misspelled apigateway module and drop a magic row count The API Gateway model lived in apigatway.rs while its fetcher and view used the correct spelling, and the view's render function carried the same typo. The account overview reported a hardcoded row count of 10. Nothing read it: the view free-scrolls a fixed layout and clamps its own offset while rendering, and both callers of the count return early for free-scroll views. It happened to match the ten inventory rows today, which is exactly the kind of number that drifts the moment a service is added. It now reports no selectable rows, which is what the view actually has. The third item on the issue, EC2 passing table widths twice, is already gone: the shared list-table helper removed it. --- .changeset/small-cleanups.md | 5 ++++ src/app/findings.rs | 2 +- src/app/mod.rs | 2 +- src/app/refresh.rs | 2 +- src/app/services.rs | 34 ++++++++++++++++++---- src/aws/apigateway.rs | 2 +- src/models/{apigatway.rs => apigateway.rs} | 0 src/models/mod.rs | 2 +- src/ui/mod.rs | 4 +-- src/ui/views/apigateway.rs | 2 +- 10 files changed, 42 insertions(+), 13 deletions(-) create mode 100644 .changeset/small-cleanups.md rename src/models/{apigatway.rs => apigateway.rs} (100%) diff --git a/.changeset/small-cleanups.md b/.changeset/small-cleanups.md new file mode 100644 index 0000000..64b95b3 --- /dev/null +++ b/.changeset/small-cleanups.md @@ -0,0 +1,5 @@ +--- +"seamless-glance": patch +--- + +Rename the misspelled API Gateway model module and render function to match the rest of the codebase, and stop the account overview from reporting a hardcoded row count. That count was never read, because the account overview free-scrolls a fixed layout and clamps its own offset while rendering, so it was a number that could only drift from the rows actually drawn. diff --git a/src/app/findings.rs b/src/app/findings.rs index 5b6d849..6a820db 100644 --- a/src/app/findings.rs +++ b/src/app/findings.rs @@ -1,7 +1,7 @@ use std::collections::BTreeSet; use crate::aws::pricing::{LoadBalancerKind, PriceBook, PriceKey}; -use crate::models::apigatway::ApiGatewayInfo; +use crate::models::apigateway::ApiGatewayInfo; use crate::models::cloudwatch::CloudWatchAlarm; use crate::models::ec2::Ec2InstanceInfo; use crate::models::elb::LoadBalancerInfo; diff --git a/src/app/mod.rs b/src/app/mod.rs index 6adc9c2..9c4b354 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -7,7 +7,7 @@ use crate::app::findings::{build_findings, FindingContext}; use crate::aws::clients::AwsClients; use crate::aws::pricing::PriceBook; use crate::cache::cost::{load_if_fresh, save, CostCache}; -use crate::models::apigatway::ApiGatewayInfo; +use crate::models::apigateway::ApiGatewayInfo; use crate::models::cloudwatch::{CloudWatchAlarm, CloudWatchSummary}; use crate::models::describable::DescribableResource; use crate::models::ec2::Ec2InstanceInfo; diff --git a/src/app/refresh.rs b/src/app/refresh.rs index 907a13c..514ed7a 100644 --- a/src/app/refresh.rs +++ b/src/app/refresh.rs @@ -9,7 +9,7 @@ use tokio::sync::mpsc::UnboundedSender; use crate::app::{ActiveView, App, RefreshPhase}; use crate::aws; use crate::aws::pricing::PriceBook; -use crate::models::apigatway::ApiGatewayInfo; +use crate::models::apigateway::ApiGatewayInfo; use crate::models::cloudwatch::{CloudWatchAlarm, CloudWatchSummary}; use crate::models::ec2::Ec2InstanceInfo; use crate::models::elb::LoadBalancerInfo; diff --git a/src/app/services.rs b/src/app/services.rs index a55d9aa..c0393df 100644 --- a/src/app/services.rs +++ b/src/app/services.rs @@ -61,10 +61,6 @@ macro_rules! row_text { }; } -/// Rows rendered by the account overview view. The view paints a fixed layout -/// rather than a list, so the count is not derived from a collection. -const ACCOUNT_OVERVIEW_ROWS: usize = 10; - pub const SERVICES: &[ServiceEntry] = &[ ServiceEntry { view: ActiveView::Findings, @@ -80,7 +76,10 @@ pub const SERVICES: &[ServiceEntry] = &[ }, ServiceEntry { view: ActiveView::AccountOverview, - row_text: |_| vec![String::new(); ACCOUNT_OVERVIEW_ROWS], + // The only view with no selectable rows: it paints a fixed layout and + // free-scrolls it, clamping its own offset as it renders. A row count + // here would be a number nothing reads and everything could drift from. + row_text: |_| Vec::new(), rows: ViewRows::Summary, }, ServiceEntry { @@ -387,6 +386,31 @@ mod tests { assert_eq!(app.total_row_count(), 3); } + /// The account overview free-scrolls a fixed layout and clamps its own + /// offset while rendering, so it has no selectable rows and nothing should + /// read a row count for it. + #[test] + fn the_account_overview_reports_no_selectable_rows() { + let mut app = test_app(); + app.active_view = ActiveView::AccountOverview; + + assert!(app.visible_indices().is_empty()); + assert_eq!(app.total_row_count(), 0); + } + + /// Moving the selection on a view with no rows must not underflow the + /// index or leave it somewhere a later render would index with. + #[test] + fn scrolling_a_view_with_no_rows_is_harmless() { + let mut app = test_app(); + app.active_view = ActiveView::AccountOverview; + + app.scroll_active_view_down(5); + app.scroll_active_view_to_bottom(); + + assert_eq!(app.selected_row, 0); + } + #[test] fn every_view_is_registered_exactly_once() { for view in ALL_VIEWS { diff --git a/src/aws/apigateway.rs b/src/aws/apigateway.rs index a99fa55..01203f5 100644 --- a/src/aws/apigateway.rs +++ b/src/aws/apigateway.rs @@ -2,7 +2,7 @@ use crate::{ app::App, aws::tags, models::{ - apigatway::{ApiGatewayInfo, ApiGatewaySummary}, + apigateway::{ApiGatewayInfo, ApiGatewaySummary}, service_status::ServiceStatus, }, }; diff --git a/src/models/apigatway.rs b/src/models/apigateway.rs similarity index 100% rename from src/models/apigatway.rs rename to src/models/apigateway.rs diff --git a/src/models/mod.rs b/src/models/mod.rs index 74ca51d..c8066f7 100644 --- a/src/models/mod.rs +++ b/src/models/mod.rs @@ -1,5 +1,5 @@ pub mod account_overview; -pub mod apigatway; +pub mod apigateway; pub mod cloudwatch; pub mod cost; pub mod cost_estimate; diff --git a/src/ui/mod.rs b/src/ui/mod.rs index 20911b9..0c8b852 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -19,7 +19,7 @@ use crate::ui::overlay::render::render_describe_overlay; use crate::ui::overlay::select_profile::render_select_profile_overlay; use crate::ui::overlay::select_ssh_key::render_select_ssh_key_overlay; use crate::ui::views::account_overview; -use crate::ui::views::apigateway::render_apigatway; +use crate::ui::views::apigateway::render_apigateway; use crate::ui::views::cloudwatch::render_cw; use crate::ui::views::command::command_for_view; use crate::ui::views::cost_overview::render_cost_overview; @@ -98,7 +98,7 @@ pub fn draw(frame: &mut Frame, app: &mut App) { render(frame, main_area, app); } ActiveView::Apigateway => { - render_apigatway(frame, main_area, app); + render_apigateway(frame, main_area, app); } ActiveView::Sqs => { render_sqs(frame, main_area, app); diff --git a/src/ui/views/apigateway.rs b/src/ui/views/apigateway.rs index 2d23653..a77eebf 100644 --- a/src/ui/views/apigateway.rs +++ b/src/ui/views/apigateway.rs @@ -5,7 +5,7 @@ use crate::ui::views::list_table::{ filter_query, render_list_table, visible_rows, ListSelection, ListTable, RowCells, }; -pub fn render_apigatway(frame: &mut Frame, area: ratatui::layout::Rect, app: &mut App) { +pub fn render_apigateway(frame: &mut Frame, area: ratatui::layout::Rect, app: &mut App) { if crate::ui::views::status::render_unavailable( frame, area,