@@ -77,6 +77,8 @@ def _check_threshold(expected: CatalogMetricAlert, actual_args: dict) -> bool:
7777
7878
7979def _check_trigger (expected : CatalogMetricAlert , actual_args : dict ) -> bool :
80+ if expected .operator == "ANOMALY" :
81+ return True
8082 exp_trigger = expected .trigger
8183 act_trigger = actual_args .get ("trigger" , actual_args .get ("triggerMode" , "ALWAYS" ))
8284 if exp_trigger in _ALWAYS_TRIGGER_VALUES :
@@ -235,27 +237,42 @@ class AgenticAlertSummary:
235237 best : AlertRunResult
236238
237239
240+ def _case_insensitive_get (d : dict , * keys : str ) -> Any :
241+ """Look up a value by key, preferring an exact match then a case-insensitive one."""
242+ for k in keys :
243+ if k in d :
244+ return d [k ]
245+ lowered = {str (k ).lower (): v for k , v in d .items ()}
246+ for k in keys :
247+ if k .lower () in lowered :
248+ return lowered [k .lower ()]
249+ return None
250+
251+
238252def _normalize_expected_output (expected : dict ) -> CatalogMetricAlert :
239253 """Parse expected_output dict into CatalogMetricAlert, accepting display-format or internal-format keys."""
240- operator = expected .get ("operator" ) or expected .get ("Operator" ) or "GREATER_THAN"
241- threshold = expected .get ("threshold" ) or expected .get ("Threshold" )
242- threshold_from = expected .get ("threshold_from" )
243- threshold_to = expected .get ("threshold_to" )
244- trigger = expected .get ("trigger" ) or expected .get ("Trigger" ) or "not specified"
245-
246- metric_id = expected .get ("metric_id" )
247- if not metric_id and "Metric" in expected :
248- m = re .search (r"\(([^)]+)\)\s*$" , str (expected ["Metric" ]))
249- if m :
250- metric_id = m .group (1 ).strip ()
251-
252- raw_recip = expected .get ("recipients" ) or expected .get ("Recipient(s)" ) or []
254+ operator = _case_insensitive_get (expected , "operator" ) or "GREATER_THAN"
255+ threshold = _case_insensitive_get (expected , "threshold" )
256+ threshold_from = _case_insensitive_get (expected , "threshold_from" )
257+ threshold_to = _case_insensitive_get (expected , "threshold_to" )
258+
259+ trigger = _case_insensitive_get (expected , "trigger" ) or "not specified"
260+ trigger = _TRIGGER_DISPLAY_TO_API .get (trigger , trigger )
261+
262+ metric_id = _case_insensitive_get (expected , "metric_id" )
263+ if not metric_id :
264+ metric_disp = _case_insensitive_get (expected , "metric" )
265+ if metric_disp :
266+ m = re .search (r"\(([^)]+)\)\s*$" , str (metric_disp ))
267+ metric_id = m .group (1 ).strip () if m else None
268+
269+ raw_recip = _case_insensitive_get (expected , "recipients" , "recipient(s)" ) or []
253270 if isinstance (raw_recip , str ):
254271 recipients = [r .strip () for r in raw_recip .replace (";" , "," ).split ("," ) if r .strip ()]
255272 else :
256273 recipients = list (raw_recip )
257274
258- filters = expected . get ( "filters" ) or expected . get ( "Time window/Filters " )
275+ filters = _case_insensitive_get ( expected , "filters " )
259276 if isinstance (filters , str ) and any (kw in filters for kw in ("None" , "All time" )):
260277 filters = None
261278
0 commit comments