@@ -436,22 +436,31 @@ export function SuiteDetailPage() {
436436 return Array . from ( keys ) . sort ( )
437437 } , [ suiteRunsAll ] )
438438
439+ // Effective group-by: when groupBy is unset in the URL, auto-default to the
440+ // first available label key. The sentinel 'none' means the user explicitly
441+ // chose no grouping.
442+ const effectiveGroupBy = useMemo ( ( ) => {
443+ if ( groupBy === 'none' ) return undefined
444+ if ( groupBy !== undefined ) return groupBy
445+ return groupByLabelKeys [ 0 ]
446+ } , [ groupBy , groupByLabelKeys ] )
447+
439448 // Apply grouping: transforms client name to include the group suffix
440449 const applyGrouping = useCallback ( ( runs : IndexEntry [ ] ) : IndexEntry [ ] => {
441- if ( ! groupBy ) return runs
450+ if ( ! effectiveGroupBy ) return runs
442451 return runs . map ( ( run ) => {
443452 let suffix : string
444- if ( groupBy === 'instance_id' ) {
453+ if ( effectiveGroupBy === 'instance_id' ) {
445454 suffix = run . instance . id
446455 } else {
447- suffix = run . metadata ?. [ groupBy ] ?? '(none)'
456+ suffix = run . metadata ?. [ effectiveGroupBy ] ?? '(none)'
448457 }
449458 return {
450459 ...run ,
451460 instance : { ...run . instance , client : `${ run . instance . client } / ${ suffix } ` } ,
452461 }
453462 } )
454- } , [ groupBy ] )
463+ } , [ effectiveGroupBy ] )
455464
456465 const groupedRunsAll = useMemo ( ( ) => applyGrouping ( suiteRunsAll ) , [ suiteRunsAll , applyGrouping ] )
457466
@@ -961,9 +970,9 @@ export function SuiteDetailPage() {
961970 < span className = "text-xs/5 font-medium text-gray-700 sm:text-sm/6 dark:text-gray-300" > Group by:</ span >
962971 < div className = "flex items-center gap-1" >
963972 < button
964- onClick = { ( ) => handleGroupByChange ( undefined ) }
973+ onClick = { ( ) => handleGroupByChange ( 'none' ) }
965974 className = { `rounded-xs px-2 py-0.5 text-xs font-medium transition-colors sm:px-2.5 sm:py-1 ${
966- ! groupBy
975+ ! effectiveGroupBy
967976 ? 'bg-gray-800 text-white dark:bg-gray-200 dark:text-gray-900'
968977 : 'bg-gray-100 text-gray-500 hover:bg-gray-200 dark:bg-gray-700 dark:text-gray-400 dark:hover:bg-gray-600'
969978 } `}
@@ -975,7 +984,7 @@ export function SuiteDetailPage() {
975984 key = { key }
976985 onClick = { ( ) => handleGroupByChange ( key ) }
977986 className = { `rounded-xs px-2 py-0.5 text-xs font-medium transition-colors sm:px-2.5 sm:py-1 ${
978- groupBy === key
987+ effectiveGroupBy === key
979988 ? 'bg-gray-800 text-white dark:bg-gray-200 dark:text-gray-900'
980989 : 'bg-gray-100 text-gray-500 hover:bg-gray-200 dark:bg-gray-700 dark:text-gray-400 dark:hover:bg-gray-600'
981990 } `}
@@ -986,7 +995,7 @@ export function SuiteDetailPage() {
986995 < button
987996 onClick = { ( ) => handleGroupByChange ( 'instance_id' ) }
988997 className = { `rounded-xs px-2 py-0.5 text-xs font-medium transition-colors sm:px-2.5 sm:py-1 ${
989- groupBy === 'instance_id'
998+ effectiveGroupBy === 'instance_id'
990999 ? 'bg-gray-800 text-white dark:bg-gray-200 dark:text-gray-900'
9911000 : 'bg-gray-100 text-gray-500 hover:bg-gray-200 dark:bg-gray-700 dark:text-gray-400 dark:hover:bg-gray-600'
9921001 } `}
@@ -1046,8 +1055,8 @@ export function SuiteDetailPage() {
10461055 < div className = "border-t border-gray-200 p-3 sm:p-4 dark:border-gray-700" >
10471056 < RunsHeatmap
10481057 runs = { suiteRunsAll }
1049- groupBy = { groupBy }
1050- onCompareGroup = { groupBy ? ( groupRuns ) => {
1058+ groupBy = { effectiveGroupBy }
1059+ onCompareGroup = { effectiveGroupBy ? ( groupRuns ) => {
10511060 const sorted = [ ...groupRuns ] . sort ( ( a , b ) => b . timestamp - a . timestamp )
10521061 const seen = new Set < string > ( )
10531062 const ids : string [ ] = [ ]
@@ -1066,7 +1075,7 @@ export function SuiteDetailPage() {
10661075 navigate ( { to : '/compare' , search : { runs : ids . join ( ',' ) } } )
10671076 }
10681077 } : undefined }
1069- onCompareClientAcrossGroups = { groupBy ? ( client ) => {
1078+ onCompareClientAcrossGroups = { effectiveGroupBy ? ( client ) => {
10701079 // Find the latest successful run for this client in each group
10711080 const sorted = [ ...suiteRunsAll ]
10721081 . filter ( ( r ) => r . instance . client === client )
@@ -1076,9 +1085,9 @@ export function SuiteDetailPage() {
10761085 for ( const run of sorted ) {
10771086 // Skip live runs — can't compare in-progress runs.
10781087 if ( run . status === 'running' ) continue
1079- const groupValue = groupBy === 'instance_id'
1088+ const groupValue = effectiveGroupBy === 'instance_id'
10801089 ? run . instance . id
1081- : ( run . metadata ?. [ groupBy ] ?? '(none)' )
1090+ : ( run . metadata ?. [ effectiveGroupBy ] ?? '(none)' )
10821091 if ( seenGroups . has ( groupValue ) ) continue
10831092 if ( run . tests . tests_total > 0 && run . tests . tests_passed === run . tests . tests_total ) {
10841093 seenGroups . add ( groupValue )
@@ -1087,28 +1096,28 @@ export function SuiteDetailPage() {
10871096 if ( ids . length >= MAX_COMPARE_RUNS ) break
10881097 }
10891098 if ( ids . length >= MIN_COMPARE_RUNS ) {
1090- const labels = groupBy === 'instance_id' ? 'instance-id' : `label:${ groupBy } `
1099+ const labels = effectiveGroupBy === 'instance_id' ? 'instance-id' : `label:${ effectiveGroupBy } `
10911100 navigate ( { to : '/compare' , search : { runs : ids . join ( ',' ) , labels } } )
10921101 }
10931102 } : undefined }
1094- onGroupCompareGroup = { groupBy ? ( groupLabel , groupClients ) => {
1095- const labelFilter = groupBy !== 'instance_id' ? `${ groupBy } =${ groupLabel } ` : ''
1103+ onGroupCompareGroup = { effectiveGroupBy ? ( groupLabel , groupClients ) => {
1104+ const labelFilter = effectiveGroupBy !== 'instance_id' ? `${ effectiveGroupBy } =${ groupLabel } ` : ''
10961105 const groups = groupClients . map ( ( c ) => `${ c } :${ labelFilter } ` ) . join ( ';' )
10971106 navigate ( { to : '/compare/groups' , search : { suite : suiteHash , groups } as Record < string , string > } )
10981107 } : undefined }
1099- onGroupCompareClientAcrossGroups = { groupBy ? ( client ) => {
1108+ onGroupCompareClientAcrossGroups = { effectiveGroupBy ? ( client ) => {
11001109 // Build one group per label-value for this client.
11011110 const labelValues = new Set < string > ( )
11021111 for ( const run of suiteRunsAll ) {
11031112 if ( run . instance . client !== client ) continue
1104- const val = groupBy === 'instance_id'
1113+ const val = effectiveGroupBy === 'instance_id'
11051114 ? run . instance . id
1106- : ( run . metadata ?. [ groupBy ] ?? '' )
1115+ : ( run . metadata ?. [ effectiveGroupBy ] ?? '' )
11071116 if ( val ) labelValues . add ( val )
11081117 }
11091118 const groups = [ ...labelValues ] . sort ( ) . map ( ( val ) => {
1110- if ( groupBy === 'instance_id' ) return `${ client } :`
1111- return `${ client } :${ groupBy } =${ val } `
1119+ if ( effectiveGroupBy === 'instance_id' ) return `${ client } :`
1120+ return `${ client } :${ effectiveGroupBy } =${ val } `
11121121 } ) . join ( ';' )
11131122 navigate ( { to : '/compare/groups' , search : { suite : suiteHash , groups } as Record < string , string > } )
11141123 } : undefined }
0 commit comments