@@ -177,6 +177,19 @@ def _make_workflow_mock(run_return=None, executors=None):
177177sys .modules ['common.config.app_config' ] = Mock (config = mock_config )
178178sys .modules ['common.models' ] = Mock ()
179179
180+ # Register the real markdown_utils so the orchestrator uses genuine table logic, not a Mock (Bug 47810).
181+ import importlib .util as _ilu # noqa: E402
182+
183+ _md_path = os .path .join (
184+ os .path .dirname (__file__ ), ".." , ".." , ".." , "backend" ,
185+ "common" , "utils" , "markdown_utils.py" ,
186+ )
187+ _md_spec = _ilu .spec_from_file_location ("common.utils.markdown_utils" , _md_path )
188+ _markdown_utils = _ilu .module_from_spec (_md_spec )
189+ _md_spec .loader .exec_module (_markdown_utils )
190+ sys .modules ['common.utils' ] = Mock ()
191+ sys .modules ['common.utils.markdown_utils' ] = _markdown_utils
192+
180193
181194class MockTeamConfiguration :
182195 def __init__ (self , name = "TestTeam" , deployment_name = "test_deployment" ):
@@ -991,3 +1004,69 @@ def test_given_new_instance_when_init_then_logger_is_set(self):
9911004 manager = OrchestrationManager ()
9921005
9931006 assert isinstance (manager .logger , logging .Logger )
1007+
1008+
1009+ # _normalize_markdown_tables (Bug 47810)
1010+ from backend .orchestration .orchestration_manager import ( # noqa: E402
1011+ _normalize_markdown_tables ,
1012+ )
1013+ from common .utils .markdown_utils import ( # noqa: E402
1014+ reflow_collapsed_table_line as _reflow_collapsed_table_line ,
1015+ )
1016+
1017+
1018+ class TestNormalizeMarkdownTables :
1019+ """Test markdown table re-flow for collapsed orchestrator output (Bug 47810)."""
1020+
1021+ def test_given_collapsed_table_when_normalized_then_rows_split_to_lines (self ):
1022+ collapsed = (
1023+ "| Risk Type | Description | Rating | "
1024+ "|-------|-------|-------| "
1025+ "| Delivery | Undefined timeline | Medium | "
1026+ "| Financial | Fixed budget | High |"
1027+ )
1028+
1029+ result = _normalize_markdown_tables (collapsed )
1030+
1031+ lines = [ln for ln in result .split ("\n " ) if ln .strip ()]
1032+ assert lines == [
1033+ "| Risk Type | Description | Rating |" ,
1034+ "| ------- | ------- | ------- |" ,
1035+ "| Delivery | Undefined timeline | Medium |" ,
1036+ "| Financial | Fixed budget | High |" ,
1037+ ]
1038+
1039+ def test_given_collapsed_table_with_prefix_then_prefix_kept_on_own_line (self ):
1040+ collapsed = (
1041+ "Risk Analysis | A | B | |---|---| | 1 | 2 |"
1042+ )
1043+
1044+ result = _normalize_markdown_tables (collapsed )
1045+
1046+ # Prefix prose separated from the table by a blank line for GFM.
1047+ assert result .startswith ("Risk Analysis\n \n | A | B |" )
1048+
1049+ def test_given_wellformed_table_when_normalized_then_unchanged (self ):
1050+ good = "| A | B |\n | --- | --- |\n | 1 | 2 |\n | 3 | 4 |"
1051+
1052+ assert _normalize_markdown_tables (good ) == good
1053+
1054+ def test_given_plain_text_when_normalized_then_unchanged (self ):
1055+ text = "Just some text with a - dash and | a pipe."
1056+
1057+ assert _normalize_markdown_tables (text ) == text
1058+
1059+ def test_given_colon_aligned_delimiter_when_normalized_then_alignment_kept (self ):
1060+ collapsed = "| A | B | C | |:--|:-:|--:| | 1 | 2 | 3 |"
1061+
1062+ result = _normalize_markdown_tables (collapsed )
1063+
1064+ assert "| :-- | :-: | --: |" in result
1065+
1066+ def test_given_empty_or_none_when_normalized_then_returns_input (self ):
1067+ assert _normalize_markdown_tables ("" ) == ""
1068+ assert _normalize_markdown_tables (None ) is None
1069+
1070+ def test_given_non_table_pipe_line_when_reflowed_then_returns_none (self ):
1071+ assert _reflow_collapsed_table_line ("a | b | c" ) is None
1072+
0 commit comments