@@ -1090,14 +1090,60 @@ describe("PostgreSQL version compatibility (PG13-PG18)", () => {
10901090 }
10911091 } ) ;
10921092
1093+ describe ( "generateD004 (pg_stat_statements) works for each PG version" , ( ) => {
1094+ for ( const { major, minor } of pgVersions ) {
1095+ test ( `PG ${ major } .${ minor } ` , async ( ) => {
1096+ const mockClient = createMockClient ( createVersionMockData ( major , minor ) ) ;
1097+ const report = await checkup . REPORT_GENERATORS . D004 ( mockClient as any , "test-node" ) ;
1098+
1099+ expect ( report . checkId ) . toBe ( "D004" ) ;
1100+ expect ( report . checkTitle ) . toBe ( "pg_stat_statements and pg_stat_kcache settings" ) ;
1101+ expect ( "test-node" in report . results ) . toBe ( true ) ;
1102+ // D004 should include settings and extension info
1103+ expect ( "settings" in report . results [ "test-node" ] . data ) . toBe ( true ) ;
1104+ } ) ;
1105+ }
1106+ } ) ;
1107+
1108+ describe ( "generateF001 (autovacuum settings) works for each PG version" , ( ) => {
1109+ for ( const { major, minor } of pgVersions ) {
1110+ test ( `PG ${ major } .${ minor } ` , async ( ) => {
1111+ const mockClient = createMockClient ( createVersionMockData ( major , minor ) ) ;
1112+ const report = await checkup . REPORT_GENERATORS . F001 ( mockClient as any , "test-node" ) ;
1113+
1114+ expect ( report . checkId ) . toBe ( "F001" ) ;
1115+ expect ( report . checkTitle ) . toBe ( "Autovacuum: current settings" ) ;
1116+ expect ( "test-node" in report . results ) . toBe ( true ) ;
1117+ expect ( report . results [ "test-node" ] . postgres_version ?. version ) . toBe ( `${ major } .${ minor } ` ) ;
1118+ } ) ;
1119+ }
1120+ } ) ;
1121+
1122+ describe ( "generateG001 (memory settings) works for each PG version" , ( ) => {
1123+ for ( const { major, minor } of pgVersions ) {
1124+ test ( `PG ${ major } .${ minor } ` , async ( ) => {
1125+ const mockClient = createMockClient ( createVersionMockData ( major , minor ) ) ;
1126+ const report = await checkup . REPORT_GENERATORS . G001 ( mockClient as any , "test-node" ) ;
1127+
1128+ expect ( report . checkId ) . toBe ( "G001" ) ;
1129+ expect ( report . checkTitle ) . toBe ( "Memory-related settings" ) ;
1130+ expect ( "test-node" in report . results ) . toBe ( true ) ;
1131+ // G001 should include settings and analysis sections
1132+ expect ( "settings" in report . results [ "test-node" ] . data ) . toBe ( true ) ;
1133+ expect ( "analysis" in report . results [ "test-node" ] . data ) . toBe ( true ) ;
1134+ expect ( report . results [ "test-node" ] . postgres_version ?. version ) . toBe ( `${ major } .${ minor } ` ) ;
1135+ } ) ;
1136+ }
1137+ } ) ;
1138+
10931139 describe ( "generateAllReports works for each PG version" , ( ) => {
10941140 for ( const { major, minor } of pgVersions ) {
10951141 test ( `PG ${ major } .${ minor } ` , async ( ) => {
10961142 const mockClient = createMockClient ( createVersionMockData ( major , minor ) ) ;
10971143 const reports = await checkup . generateAllReports ( mockClient as any , "test-node" ) ;
10981144
1099- // Verify all expected checks are generated
1100- const expectedChecks = [ "A002" , "A003" , "A004" , "A007" , "A013" , "H001" , "H002" , "H004" ] ;
1145+ // Verify all expected checks are generated (includes D004, F001, G001)
1146+ const expectedChecks = [ "A002" , "A003" , "A004" , "A007" , "A013" , "D004" , "F001" , "G001" , " H001", "H002" , "H004" ] ;
11011147 for ( const checkId of expectedChecks ) {
11021148 expect ( checkId in reports ) . toBe ( true ) ;
11031149 expect ( reports [ checkId ] . checkId ) . toBe ( checkId ) ;
@@ -1119,58 +1165,54 @@ describe("PostgreSQL version compatibility (PG13-PG18)", () => {
11191165describe ( "Version-aware SQL query selection (PG13-PG18)" , ( ) => {
11201166 const pgVersions = [ 13 , 14 , 15 , 16 , 17 , 18 ] ;
11211167
1122- // Core metrics that should be available for all versions
1123- const coreMetrics = [
1124- "settings" ,
1125- "db_stats" ,
1126- "db_size" ,
1127- "stats_reset" ,
1128- "pg_invalid_indexes" ,
1129- "unused_indexes" ,
1130- "redundant_indexes" ,
1131- ] ;
1168+ // All metrics from metrics.yml that are used by checkup
1169+ const allMetrics = metricsLoader . listMetricNames ( ) ;
11321170
1133- describe ( "getMetricSql returns SQL for all PG versions " , ( ) => {
1171+ describe ( "All metrics from metrics.yml return valid SQL for each PG version " , ( ) => {
11341172 for ( const pgVersion of pgVersions ) {
1135- for ( const metric of coreMetrics ) {
1136- test ( `${ metric } for PG${ pgVersion } ` , ( ) => {
1137- const sql = metricsLoader . getMetricSql ( metric , pgVersion ) ;
1138- expect ( typeof sql ) . toBe ( "string" ) ;
1139- expect ( sql . length ) . toBeGreaterThan ( 0 ) ;
1140- // Verify it's actually SQL
1141- expect ( sql . toLowerCase ( ) ) . toMatch ( / s e l e c t / ) ;
1142- } ) ;
1143- }
1144- }
1145- } ) ;
1146-
1147- describe ( "getMetricSql selects appropriate version for each PG major version" , ( ) => {
1148- for ( const pgVersion of pgVersions ) {
1149- test ( `PG${ pgVersion } gets compatible SQL version` , ( ) => {
1150- // Settings metric should return SQL for all supported versions
1151- const sql = metricsLoader . getMetricSql ( "settings" , pgVersion ) ;
1152- expect ( sql ) . toBeTruthy ( ) ;
1153- // SQL should be valid (not throw an error)
1154- expect ( ( ) => metricsLoader . getMetricSql ( "settings" , pgVersion ) ) . not . toThrow ( ) ;
1173+ describe ( `PG${ pgVersion } ` , ( ) => {
1174+ for ( const metric of allMetrics ) {
1175+ test ( `${ metric } ` , ( ) => {
1176+ // Should not throw an error
1177+ expect ( ( ) => metricsLoader . getMetricSql ( metric , pgVersion ) ) . not . toThrow ( ) ;
1178+
1179+ const sql = metricsLoader . getMetricSql ( metric , pgVersion ) ;
1180+ expect ( typeof sql ) . toBe ( "string" ) ;
1181+ expect ( sql . length ) . toBeGreaterThan ( 0 ) ;
1182+ // Verify it's actually SQL (contains SELECT)
1183+ expect ( sql . toLowerCase ( ) ) . toMatch ( / s e l e c t / ) ;
1184+ } ) ;
1185+ }
11551186 } ) ;
11561187 }
11571188 } ) ;
11581189
11591190 describe ( "getMetricDefinition returns metadata for all metrics" , ( ) => {
1160- for ( const metric of coreMetrics ) {
1161- test ( `${ metric } has definition` , ( ) => {
1191+ for ( const metric of allMetrics ) {
1192+ test ( `${ metric } has definition with versioned SQL ` , ( ) => {
11621193 const definition = metricsLoader . getMetricDefinition ( metric ) ;
11631194 expect ( definition ) . toBeTruthy ( ) ;
11641195 expect ( definition ?. sqls ) . toBeTruthy ( ) ;
11651196 expect ( typeof definition ?. sqls ) . toBe ( "object" ) ;
1197+ // Should have at least one version defined
1198+ expect ( Object . keys ( definition ! . sqls ) . length ) . toBeGreaterThan ( 0 ) ;
11661199 } ) ;
11671200 }
11681201 } ) ;
11691202
1170- test ( "listMetricNames returns all expected metrics" , ( ) => {
1203+ test ( "listMetricNames returns all expected core metrics" , ( ) => {
11711204 const names = metricsLoader . listMetricNames ( ) ;
11721205 expect ( Array . isArray ( names ) ) . toBe ( true ) ;
1173- // Should include core metrics
1206+ // Core metrics used by checkup reports
1207+ const coreMetrics = [
1208+ "settings" ,
1209+ "db_stats" ,
1210+ "db_size" ,
1211+ "stats_reset" ,
1212+ "pg_invalid_indexes" ,
1213+ "unused_indexes" ,
1214+ "redundant_indexes" ,
1215+ ] ;
11741216 for ( const metric of coreMetrics ) {
11751217 expect ( names ) . toContain ( metric ) ;
11761218 }
@@ -1192,6 +1234,40 @@ describe("Version-aware SQL query selection (PG13-PG18)", () => {
11921234 test ( "settings metric exists" , ( ) => {
11931235 expect ( metricsLoader . METRIC_NAMES . settings ) . toBe ( "settings" ) ;
11941236 } ) ;
1237+
1238+ test ( "dbStats metric exists" , ( ) => {
1239+ expect ( metricsLoader . METRIC_NAMES . dbStats ) . toBe ( "db_stats" ) ;
1240+ } ) ;
1241+
1242+ test ( "dbSize metric exists" , ( ) => {
1243+ expect ( metricsLoader . METRIC_NAMES . dbSize ) . toBe ( "db_size" ) ;
1244+ } ) ;
1245+
1246+ test ( "statsReset metric exists" , ( ) => {
1247+ expect ( metricsLoader . METRIC_NAMES . statsReset ) . toBe ( "stats_reset" ) ;
1248+ } ) ;
1249+ } ) ;
1250+
1251+ describe ( "SQL queries are syntactically valid for version edge cases" , ( ) => {
1252+ // Test boundary versions
1253+ const boundaryVersions = [
1254+ { version : 13 , description : "minimum supported" } ,
1255+ { version : 18 , description : "maximum supported" } ,
1256+ ] ;
1257+
1258+ for ( const { version, description } of boundaryVersions ) {
1259+ test ( `PG${ version } (${ description } ) returns valid SQL for all metrics` , ( ) => {
1260+ for ( const metric of allMetrics ) {
1261+ const sql = metricsLoader . getMetricSql ( metric , version ) ;
1262+ // Basic SQL validation
1263+ expect ( sql . toLowerCase ( ) ) . toMatch ( / s e l e c t / ) ;
1264+ expect ( sql . toLowerCase ( ) ) . toMatch ( / f r o m / ) ;
1265+ // Should not contain unresolved template variables
1266+ expect ( sql ) . not . toMatch ( / \{ \{ .* \} \} / ) ;
1267+ expect ( sql ) . not . toMatch ( / \$ \{ .* \} / ) ;
1268+ }
1269+ } ) ;
1270+ }
11951271 } ) ;
11961272} ) ;
11971273
0 commit comments