@@ -336,13 +336,13 @@ describe('Recommendations Module', () => {
336336 // No selection: cards reflect the full visible set.
337337 ( state . getSelectedRecommendationIDs as jest . Mock ) . mockReturnValue ( new Set ( ) ) ;
338338 await loadRecommendations ( ) ;
339- expect ( cardValue ( / R e c o m m e n d a t i o n s / ) ) . toBe ( '2 ' ) ; // 2 cells, not 4 variants
339+ expect ( cardValue ( / R e c o m m e n d a t i o n s / ) ) . toBe ( '4 ' ) ; // 4 variants (closes #748: KPI now matches "Showing of")
340340 expect ( cardValue ( / M o n t h l y S a v i n g s / ) ) . toMatch ( / \$ 3 0 0 \b / ) ;
341341 expect ( cardValue ( / M o n t h l y S a v i n g s / ) ) . toMatch ( / \$ 4 0 0 \b / ) ;
342342 expect ( cardValue ( / U p f r o n t / ) ) . toMatch ( / \$ 0 \b / ) ;
343343 expect ( cardValue ( / U p f r o n t / ) ) . toMatch ( / \$ 3 , ? 0 0 0 \b / ) ;
344344 // Card titles reflect the "all visible" mode.
345- expect ( cardTitle ( / ^ 2 $ / ) ) . toBe ( 'Total Recommendations' ) ;
345+ expect ( cardTitle ( / ^ 4 $ / ) ) . toBe ( 'Total Recommendations' ) ;
346346
347347 // Tick one cell's pricey variant: cards narrow to that one rec.
348348 ( state . getSelectedRecommendationIDs as jest . Mock ) . mockReturnValue ( new Set ( [ 'cell1-pricey' ] ) ) ;
@@ -362,6 +362,48 @@ describe('Recommendations Module', () => {
362362 expect ( cardValue ( / U p f r o n t / ) ) . toMatch ( / ^ \$ 1 , ? 0 0 0 $ / ) ; // 1000 + 0
363363 } ) ;
364364
365+ test ( 'KPI "Total Recommendations" and "Showing X of X" agree on the same variant count (closes #748)' , async ( ) => {
366+ // 2 cells, 2 variants each = 4 total variants.
367+ // Before #748 the KPI showed 2 (cell count) while "Showing of" showed 4
368+ // (variant count). After the fix both display 4.
369+ const recs = [
370+ { id : 'cell1-v1' , provider : 'aws' , cloud_account_id : 'a1' , service : 'ec2' , resource_type : 't3.medium' , region : 'us-east-1' , count : 1 , term : 1 , payment_option : 'no-upfront' , savings : 100 , upfront_cost : 0 } ,
371+ { id : 'cell1-v2' , provider : 'aws' , cloud_account_id : 'a1' , service : 'ec2' , resource_type : 't3.medium' , region : 'us-east-1' , count : 1 , term : 1 , payment_option : 'all-upfront' , savings : 150 , upfront_cost : 1000 } ,
372+ { id : 'cell2-v1' , provider : 'aws' , cloud_account_id : 'a1' , service : 'rds' , resource_type : 'db.t3' , region : 'us-east-1' , count : 1 , term : 1 , payment_option : 'no-upfront' , savings : 200 , upfront_cost : 0 } ,
373+ { id : 'cell2-v2' , provider : 'aws' , cloud_account_id : 'a1' , service : 'rds' , resource_type : 'db.t3' , region : 'us-east-1' , count : 1 , term : 1 , payment_option : 'all-upfront' , savings : 250 , upfront_cost : 2000 } ,
374+ ] ;
375+ ( api . getRecommendations as jest . Mock ) . mockResolvedValue ( {
376+ summary : { total_count : 4 , total_monthly_savings : 700 , total_upfront_cost : 3000 , avg_payback_months : 2 } ,
377+ recommendations : recs ,
378+ regions : [ ] ,
379+ } ) ;
380+ ( state . getRecommendations as jest . Mock ) . mockReturnValue ( recs ) ;
381+ ( state . getVisibleRecommendations as jest . Mock ) . mockReturnValue ( recs ) ;
382+ ( state . getRecommendationsColumnFilters as jest . Mock ) . mockReturnValue ( { } ) ;
383+ ( state . getSelectedRecommendationIDs as jest . Mock ) . mockReturnValue ( new Set ( ) ) ;
384+
385+ await loadRecommendations ( ) ;
386+
387+ // KPI card value.
388+ const summary = document . getElementById ( 'recommendations-summary' ) ;
389+ const kpiCard = Array . from ( summary ?. querySelectorAll ( '.card' ) ?? [ ] )
390+ . find ( ( c ) => / R e c o m m e n d a t i o n s / . test ( c . querySelector ( 'h3' ) ?. textContent ?? '' ) ) ;
391+ const kpiValue = kpiCard ?. querySelector ( '.value' ) ?. textContent ?? '' ;
392+
393+ // "Showing X of X" live region value.
394+ const liveText = document . querySelector ( '.recommendations-filter-live' ) ?. textContent ?? '' ;
395+ const match = liveText . match ( / S h o w i n g ( \d + ) o f ( \d + ) / ) ;
396+ const showingVisible = match ?. [ 1 ] ?? '' ;
397+ const showingLoaded = match ?. [ 2 ] ?? '' ;
398+
399+ // Both KPI and "Showing of" must report the same variant count (4).
400+ expect ( kpiValue ) . toBe ( '4' ) ;
401+ expect ( showingLoaded ) . toBe ( '4' ) ;
402+ expect ( kpiValue ) . toBe ( showingLoaded ) ;
403+ // Parity between visible and loaded when no filter is active.
404+ expect ( showingVisible ) . toBe ( showingLoaded ) ;
405+ } ) ;
406+
365407 test ( 'row checkbox change event updates summary cards in place (PR #283 CR pass-2)' , async ( ) => {
366408 // Regression guard for the real DOM event path: verifies that dispatching
367409 // a `change` event on a row checkbox updates summary cards WITHOUT a
0 commit comments