@@ -403,8 +403,10 @@ class TestDagDetails(TestDagEndpoint):
403403 ],
404404 )
405405 @pytest .mark .usefixtures ("configure_git_connection_for_dag_bundle" )
406+ @mock .patch ("airflow.api_fastapi.core_api.datamodels.dag_versions.hasattr" )
406407 def test_dag_details (
407408 self ,
409+ mock_hasattr ,
408410 test_client ,
409411 query_params ,
410412 dag_id ,
@@ -413,6 +415,7 @@ def test_dag_details(
413415 start_date ,
414416 owner_links ,
415417 ):
418+ mock_hasattr .return_value = False
416419 response = test_client .get (f"/dags/{ dag_id } /details" , params = query_params )
417420 assert response .status_code == expected_status_code
418421 if expected_status_code != 200 :
@@ -489,6 +492,100 @@ def test_dag_details(
489492 }
490493 assert res_json == expected
491494
495+ @pytest .mark .parametrize (
496+ "query_params, dag_id, expected_status_code, dag_display_name, start_date, owner_links" ,
497+ [
498+ ({}, "fake_dag_id" , 404 , "fake_dag" , "2023-12-31T00:00:00Z" , {}),
499+ ({}, DAG2_ID , 200 , DAG2_ID , "2021-06-15T00:00:00Z" , {}),
500+ ],
501+ )
502+ @pytest .mark .usefixtures ("configure_git_connection_for_dag_bundle" )
503+ def test_dag_details_with_view_url_template (
504+ self ,
505+ test_client ,
506+ query_params ,
507+ dag_id ,
508+ expected_status_code ,
509+ dag_display_name ,
510+ start_date ,
511+ owner_links ,
512+ ):
513+ response = test_client .get (f"/dags/{ dag_id } /details" , params = query_params )
514+ assert response .status_code == expected_status_code
515+ if expected_status_code != 200 :
516+ return
517+
518+ # Match expected and actual responses below.
519+ res_json = response .json ()
520+ last_parsed = res_json ["last_parsed" ]
521+ last_parsed_time = res_json ["last_parsed_time" ]
522+ file_token = res_json ["file_token" ]
523+ expected = {
524+ "bundle_name" : "dag_maker" ,
525+ "bundle_version" : None ,
526+ "asset_expression" : None ,
527+ "catchup" : False ,
528+ "concurrency" : 16 ,
529+ "dag_id" : dag_id ,
530+ "dag_display_name" : dag_display_name ,
531+ "dag_run_timeout" : None ,
532+ "default_args" : {
533+ "depends_on_past" : False ,
534+ "retries" : 1 ,
535+ "retry_delay" : "PT5M" ,
536+ },
537+ "description" : None ,
538+ "doc_md" : "details" ,
539+ "deadline" : None ,
540+ "end_date" : None ,
541+ "fileloc" : __file__ ,
542+ "file_token" : file_token ,
543+ "has_import_errors" : False ,
544+ "has_task_concurrency_limits" : True ,
545+ "is_stale" : False ,
546+ "is_paused" : False ,
547+ "is_paused_upon_creation" : None ,
548+ "latest_dag_version" : {
549+ "bundle_name" : "dag_maker" ,
550+ "bundle_url" : "http://test_host.github.com/tree/None/dags" ,
551+ "bundle_version" : None ,
552+ "created_at" : mock .ANY ,
553+ "dag_id" : "test_dag2" ,
554+ "id" : mock .ANY ,
555+ "version_number" : 1 ,
556+ "dag_display_name" : dag_display_name ,
557+ },
558+ "last_expired" : None ,
559+ "last_parsed" : last_parsed ,
560+ "last_parsed_time" : last_parsed_time ,
561+ "max_active_runs" : 16 ,
562+ "max_active_tasks" : 16 ,
563+ "max_consecutive_failed_dag_runs" : 0 ,
564+ "next_dagrun_data_interval_end" : None ,
565+ "next_dagrun_data_interval_start" : None ,
566+ "next_dagrun_logical_date" : None ,
567+ "next_dagrun_run_after" : None ,
568+ "owners" : ["airflow" ],
569+ "owner_links" : {},
570+ "params" : {
571+ "foo" : {
572+ "__class" : "airflow.sdk.definitions.param.Param" ,
573+ "description" : None ,
574+ "schema" : {},
575+ "value" : 1 ,
576+ }
577+ },
578+ "relative_fileloc" : "test_dags.py" ,
579+ "render_template_as_native_obj" : False ,
580+ "timetable_summary" : None ,
581+ "start_date" : start_date ,
582+ "tags" : [],
583+ "template_search_path" : None ,
584+ "timetable_description" : "Never, external triggers only" ,
585+ "timezone" : UTC_JSON_REPR ,
586+ }
587+ assert res_json == expected
588+
492589 def test_dag_details_should_response_401 (self , unauthenticated_test_client ):
493590 response = unauthenticated_test_client .get (f"/dags/{ DAG1_ID } /details" )
494591 assert response .status_code == 401
0 commit comments