From 54e93ca5c6a0da93ad12f4b7cfb1bb0fa0efa8fb Mon Sep 17 00:00:00 2001 From: JK Date: Tue, 7 Apr 2026 04:25:11 +0900 Subject: [PATCH] =?UTF-8?q?confluence-mdx:=20preserved=20anchor=20?= =?UTF-8?q?=EB=A6=AC=EC=8A=A4=ED=8A=B8=20=EB=A7=88=EC=BB=A4=20=EA=B3=B5?= =?UTF-8?q?=EB=B0=B1=20=EB=B3=80=EA=B2=BD=EC=9D=98=20E2E=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=EB=A5=BC=20=EC=B6=94=EA=B0=80=ED=95=A9?= =?UTF-8?q?=EB=8B=88=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit build_patches() → has_content_change → replace_fragment 경로를 검증하는 통합 테스트를 추가합니다. 기존 단위 테스트는 _normalize_list_for_content_compare() 반환값만 확인하여 실제 회귀를 감지하지 못했습니다. 이 테스트는 동반 PR (#988)의 수정이 적용되어야 통과합니다. Co-Authored-By: Claude Opus 4.6 --- .../tests/test_reverse_sync_patch_builder.py | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/confluence-mdx/tests/test_reverse_sync_patch_builder.py b/confluence-mdx/tests/test_reverse_sync_patch_builder.py index ef32f8ac6..e07645279 100644 --- a/confluence-mdx/tests/test_reverse_sync_patch_builder.py +++ b/confluence-mdx/tests/test_reverse_sync_patch_builder.py @@ -2967,6 +2967,57 @@ def test_image_anchor_list_keeps_collapsed_text_diff(self): ) assert patches[0]['new_plain_text'] == '목록 좌측 상단에서 Delete 버튼을 클릭합니다.' + def test_image_anchor_list_marker_ws_change_produces_patch(self): + """이미지 preserved anchor 리스트의 마커 뒤 공백 변경도 패치를 생성한다.""" + xhtml = ( + '
  1. 목록 좌측 상단에서 Delete 버튼을 클릭합니다.

    ' + '' + '' + '

' + ) + old_content = ( + '4. 목록 좌측 상단에서 Delete 버튼을 클릭합니다.
\n' + '
\n' + ' img\n' + '
\n' + ) + new_content = ( + '4. 목록 좌측 상단에서 Delete 버튼을 클릭합니다.
\n' + '
\n' + ' img\n' + '
\n' + ) + change = _make_change(0, old_content, new_content, type_='list') + mapping = BlockMapping( + block_id='list-image-ws-1', + type='list', + xhtml_xpath='ol[1]', + xhtml_text=xhtml, + xhtml_plain_text='목록 좌측 상단에서 Delete 버튼을 클릭합니다.', + xhtml_element_index=0, + children=[], + ) + roundtrip_sidecar = _make_roundtrip_sidecar([ + SidecarBlock(0, 'ol[1]', xhtml, sha256_text(old_content), (1, 4)) + ]) + + patches, _, skipped = build_patches( + [change], [change.old_block], [change.new_block], + mappings=[mapping], + roundtrip_sidecar=roundtrip_sidecar, + ) + + assert len(patches) == 1, ( + f"마커 공백만 변경된 이미지 preserved anchor 리스트도 패치를 생성해야 합니다. skipped={skipped}" + ) + assert patches[0].get('action') == 'replace_fragment', ( + f"preserved anchor 리스트는 replace_fragment 패치여야 합니다: {patches[0]}" + ) + new_xhtml = patches[0].get('new_element_xhtml', '') + assert '