77from dayamlchecker .docx_accessibility import (
88 DocxAccessibilityOptions ,
99 check_docx_accessibility ,
10+ check_docx_review_markup ,
1011)
1112from dayamlchecker .messages import Severity
1213from dayamlchecker .yaml_structure import main
@@ -259,6 +260,71 @@ def test_unreadable_docx_reports_a_package_finding():
259260 assert strict [0 ].severity == ERROR
260261
261262
263+ # ---------------------------------------------------------------------------
264+ # Comments and tracked changes
265+ # ---------------------------------------------------------------------------
266+
267+
268+ def test_docx_comments_are_errors_by_default ():
269+ with TemporaryDirectory () as tmp :
270+ path = _build (
271+ tmp ,
272+ "commented" ,
273+ '<w:p><w:commentRangeStart w:id="0"/><w:r><w:t>Draft</w:t></w:r>'
274+ '<w:commentRangeEnd w:id="0"/><w:r><w:commentReference w:id="0"/>'
275+ "</w:p>" ,
276+ )
277+ with zipfile .ZipFile (path , "a" ) as package :
278+ package .writestr (
279+ "word/comments.xml" ,
280+ '<?xml version="1.0" encoding="UTF-8"?>'
281+ '<w:comments xmlns:w="http://schemas.openxmlformats.org/'
282+ 'wordprocessingml/2006/main"><w:comment w:id="0">'
283+ "<w:p><w:r><w:t>Do not publish this note</w:t></w:r></w:p>"
284+ "</w:comment></w:comments>" ,
285+ )
286+
287+ findings = check_docx_review_markup (path )
288+
289+ assert len (findings ) == 1
290+ assert findings [0 ].code == "EG130"
291+ assert findings [0 ].severity == ERROR
292+ assert findings [0 ].finding_class == "general"
293+ assert "embedded comments" in findings [0 ].message
294+ assert "word/comments.xml" in findings [0 ].message
295+
296+
297+ def test_docx_tracked_changes_are_errors_by_default ():
298+ with TemporaryDirectory () as tmp :
299+ path = _build (
300+ tmp ,
301+ "revisions" ,
302+ '<w:p><w:del w:id="1"><w:r><w:delText>Old</w:delText></w:r></w:del>'
303+ '<w:ins w:id="2"><w:r><w:t>New</w:t></w:r></w:ins></w:p>' ,
304+ )
305+
306+ findings = check_docx_review_markup (path )
307+
308+ assert len (findings ) == 1
309+ assert findings [0 ].code == "EG130"
310+ assert "tracked changes" in findings [0 ].message
311+ assert "word/document.xml" in findings [0 ].message
312+
313+
314+ def test_track_changes_setting_without_revision_markup_is_allowed ():
315+ with TemporaryDirectory () as tmp :
316+ path = _build (tmp , "tracking-on" , f"<w:p><w:r><w:t>{ PROSE } </w:t></w:r></w:p>" )
317+ with zipfile .ZipFile (path , "a" ) as package :
318+ package .writestr (
319+ "word/settings.xml" ,
320+ '<?xml version="1.0" encoding="UTF-8"?>'
321+ '<w:settings xmlns:w="http://schemas.openxmlformats.org/'
322+ 'wordprocessingml/2006/main"><w:trackRevisions/></w:settings>' ,
323+ )
324+
325+ assert check_docx_review_markup (path ) == []
326+
327+
262328# ---------------------------------------------------------------------------
263329# Regressions
264330# ---------------------------------------------------------------------------
@@ -553,7 +619,7 @@ def test_cli_checks_docx_by_default_without_failing():
553619 assert "WA541" in output , "image-alt-missing, demoted to a warning"
554620
555621
556- def test_cli_can_skip_docx_checks ():
622+ def test_cli_can_skip_all_docx_checks ():
557623 with TemporaryDirectory () as tmp :
558624 path = Path (tmp ) / "inaccessible.docx"
559625 _write_docx (path , _base_files (_inaccessible_document_xml ()))
@@ -562,7 +628,57 @@ def test_cli_can_skip_docx_checks():
562628 ["--no-docx-accessibility" , "--no-url-check" , str (path )]
563629 )
564630
565- assert exit_code == 1 , "nothing left to check"
631+ assert exit_code == 1 , "nothing is enabled to check the DOCX"
632+
633+
634+ def test_cli_review_markup_fails_independently_of_accessibility_severity ():
635+ with TemporaryDirectory () as tmp :
636+ path = _build (
637+ tmp ,
638+ "revisions" ,
639+ '<w:p><w:ins w:id="2"><w:r><w:t>New</w:t></w:r></w:ins></w:p>' ,
640+ )
641+
642+ exit_code , output = _run_cli (["--no-url-check" , str (path )])
643+
644+ assert exit_code == 1
645+ assert "EG130" in output
646+
647+
648+ def test_cli_can_disable_docx_review_markup_rule ():
649+ with TemporaryDirectory () as tmp :
650+ path = _build (
651+ tmp ,
652+ "revisions" ,
653+ '<w:p><w:ins w:id="2"><w:r><w:t>New</w:t></w:r></w:ins></w:p>' ,
654+ )
655+
656+ exit_code , output = _run_cli (
657+ [
658+ "--no-docx-review-markup" ,
659+ "--no-url-check" ,
660+ str (path ),
661+ ]
662+ )
663+
664+ assert exit_code == 0 , "warning-level accessibility findings do not fail"
665+ assert "EG130" not in output
666+
667+
668+ def test_cli_can_suppress_docx_review_markup_by_code ():
669+ with TemporaryDirectory () as tmp :
670+ path = _build (
671+ tmp ,
672+ "revisions" ,
673+ '<w:p><w:ins w:id="2"><w:r><w:t>New</w:t></w:r></w:ins></w:p>' ,
674+ )
675+
676+ exit_code , output = _run_cli (
677+ ["--suppress" , "EG130" , "--no-url-check" , str (path )]
678+ )
679+
680+ assert exit_code == 0
681+ assert "EG130" not in output
566682
567683
568684def test_cli_error_severity_fails_the_command ():
0 commit comments