from app.inspector_projection import project_artifact_detail def test_script_table_projection_normalizes_facets_links_and_element_references(): artifact = { "sourceOrigin": "database", "paragraphs": [ { "id": 1, "rowId": 1, "effectiveId": 1, "paragraph_index": 2, "level": 1, "name": "机制拆解", "content_range": {"图片": ["1", "2"], "标题": True, "正文": "第二段"}, "theme": "通过[元素:10]解释机制", "theme_elements": [{"维度类型": "主", "维度": "核心竞争力", "原子点": "份额换订单"}], "form": "案例拆解", "form_elements": [], "function": "承接上文", "function_elements": [], "feeling": "建立可信度", "feeling_elements": [], "full_description": "通过[元素:10]解释机制,并保留[元素:999]。", } ], "elements": [ {"id": 10, "rowId": 10, "effectiveId": 10, "name": "份额换订单", "dimension_primary": "核心竞争力", "dimension_secondary": "商业模式"} ], "paragraphElements": [{"id": 100, "paragraph_id": 1, "element_id": 10}], } payload = project_artifact_detail(431, "artifact:base:current", artifact) table = payload["scriptTable"] assert table["counts"] == {"paragraphs": 1, "elements": 1, "links": 1} assert table["paragraphs"][0]["contentRange"] == ["图1-2", "标题", "正文: 第二段"] assert table["paragraphs"][0]["sections"]["theme"]["dimensions"][0] == { "type": "主", "name": "核心竞争力", "value": "份额换订单", } parts = table["paragraphs"][0]["fullDescriptionParts"] assert parts[1] == {"type": "element", "id": 10, "name": "份额换订单", "resolved": True, "text": "[元素:10]"} assert parts[3]["resolved"] is False assert table["paragraphs"][0]["sections"]["theme"]["descriptionParts"][1] == { "type": "element", "id": 10, "name": "份额换订单", "resolved": True, "text": "[元素:10]", } assert table["elements"][0]["paragraphs"] == [{"id": 1, "index": 2, "name": "机制拆解"}] assert payload["changes"]["sections"][0]["content"] == "1 个段落、1 个元素、1 条关联" assert "artifact" not in payload["technical"] def test_script_table_keeps_children_beside_their_real_parent(): def paragraph(row_id, index, name, parent_id=None, level=1): return { "id": row_id, "rowId": row_id, "effectiveId": row_id, "paragraph_index": index, "parent_id": parent_id, "level": level, "name": name, } artifact = { "sourceOrigin": "database", "paragraphs": [ paragraph(1, 1, "第一章"), paragraph(2, 1, "第一章子段", parent_id=1, level=2), paragraph(3, 2, "第二章"), paragraph(4, 1, "第二章子段", parent_id=3, level=2), ], "elements": [], "paragraphElements": [], } table = project_artifact_detail(1, "artifact:base:current", artifact)["scriptTable"] assert [row["name"] for row in table["paragraphs"]] == [ "第一章", "第一章子段", "第二章", "第二章子段", ] assert [row["depth"] for row in table["paragraphs"]] == [0, 1, 0, 1] assert table["maxDepth"] == 2 def test_frozen_candidate_snapshot_restores_nested_paragraphs_and_embedded_links(): artifact = { "sourceOrigin": "database", "historicalAccuracy": "exact", "artifactContext": {"type": "candidate", "branchStatus": "merged"}, "snapshot": { "stats": {"paragraph_count": 2, "element_count": 1, "link_count": 2}, "paragraphs": [ { "id": 1, "paragraph_index": 1, "level": 1, "name": "主段落", "linked_elements": [{"link_id": 10, "element_id": 100}], "sub_paragraphs": [ { "id": 2, "paragraph_index": 1, "level": 2, "name": "子段落", "linked_elements": [], "linked_element_ids": [100], } ], } ], "elements": [{"id": 100, "name": "候选元素"}], }, } payload = project_artifact_detail(1, "artifact:branch:7", artifact) table = payload["scriptTable"] assert table["counts"] == {"paragraphs": 2, "elements": 1, "links": 2} assert [row["name"] for row in table["paragraphs"]] == ["主段落", "子段落"] assert [row["depth"] for row in table["paragraphs"]] == [0, 1] assert table["elements"][0]["paragraphs"] == [ {"id": 1, "index": 1, "name": "主段落"}, {"id": 2, "index": 1, "name": "子段落"}, ] assert payload["businessSections"][0]["title"] == "候选脚本规模" assert payload["changes"]["summary"] == "候选脚本内容"