@@ -475,6 +475,177 @@ public void CompareStructureFindsNestedTableCellChanges() {
475475 Assert . Equal ( "table[1]/row[0]/cell[0]" , cell . Location ) ;
476476 }
477477
478+ [ Fact ]
479+ public void CompareStructureAlignsTablesAroundInsertedTables ( ) {
480+ string sourcePath = Path . Combine ( _directoryWithFiles , "compare_structure_source_table_insert_alignment.docx" ) ;
481+ using ( WordDocument doc = WordDocument . Create ( sourcePath ) ) {
482+ WordTable table = doc . AddTable ( 1 , 1 ) ;
483+ table . Rows [ 0 ] . Cells [ 0 ] . Paragraphs [ 0 ] . SetText ( "Existing terms" ) ;
484+ doc . Save ( false ) ;
485+ }
486+
487+ string targetPath = Path . Combine ( _directoryWithFiles , "compare_structure_target_table_insert_alignment.docx" ) ;
488+ using ( WordDocument doc = WordDocument . Create ( targetPath ) ) {
489+ WordTable inserted = doc . AddTable ( 1 , 1 ) ;
490+ inserted . Rows [ 0 ] . Cells [ 0 ] . Paragraphs [ 0 ] . SetText ( "New summary" ) ;
491+ WordTable table = doc . AddTable ( 1 , 1 ) ;
492+ table . Rows [ 0 ] . Cells [ 0 ] . Paragraphs [ 0 ] . SetText ( "Existing terms" ) ;
493+ doc . Save ( false ) ;
494+ }
495+
496+ WordComparisonResult result = WordDocumentComparer . CompareStructure ( sourcePath , targetPath ) ;
497+
498+ WordComparisonFinding tableFinding = Assert . Single ( result . Findings ) ;
499+ Assert . Equal ( WordComparisonScope . Table , tableFinding . Scope ) ;
500+ Assert . Equal ( WordComparisonChangeKind . Inserted , tableFinding . ChangeKind ) ;
501+ Assert . Equal ( "table[0]" , tableFinding . Location ) ;
502+ Assert . Equal ( "New summary" , tableFinding . TargetText ) ;
503+ }
504+
505+ [ Fact ]
506+ public void CompareStructurePreservesVisibleParagraphWhitespaceAndBlankParagraphs ( ) {
507+ string sourcePath = Path . Combine ( _directoryWithFiles , "compare_structure_source_visible_whitespace.docx" ) ;
508+ using ( WordDocument doc = WordDocument . Create ( sourcePath ) ) {
509+ WordParagraph paragraph = doc . AddParagraph ( "Column A" ) ;
510+ paragraph . AddTab ( ) ;
511+ paragraph . AddText ( "Column B" ) ;
512+ doc . AddParagraph ( "Closing" ) ;
513+ doc . Save ( false ) ;
514+ }
515+
516+ string targetPath = Path . Combine ( _directoryWithFiles , "compare_structure_target_visible_whitespace.docx" ) ;
517+ using ( WordDocument doc = WordDocument . Create ( targetPath ) ) {
518+ WordParagraph paragraph = doc . AddParagraph ( "Column A" ) ;
519+ paragraph . AddBreak ( ) ;
520+ paragraph . AddText ( "Column B" ) ;
521+ doc . AddParagraph ( ) ;
522+ doc . AddParagraph ( "Closing" ) ;
523+ doc . Save ( false ) ;
524+ }
525+
526+ WordComparisonResult result = WordDocumentComparer . CompareStructure ( sourcePath , targetPath ) ;
527+
528+ WordComparisonFinding modified = Assert . Single ( result . Findings , finding =>
529+ finding . Scope == WordComparisonScope . Paragraph &&
530+ finding . ChangeKind == WordComparisonChangeKind . Modified ) ;
531+ Assert . Equal ( "Column A\t Column B" , modified . SourceText ) ;
532+ Assert . Equal ( "Column A\n Column B" , modified . TargetText ) ;
533+
534+ WordComparisonFinding inserted = Assert . Single ( result . Findings , finding =>
535+ finding . Scope == WordComparisonScope . Paragraph &&
536+ finding . ChangeKind == WordComparisonChangeKind . Inserted ) ;
537+ Assert . Equal ( "paragraph[1]" , inserted . Location ) ;
538+ Assert . Equal ( string . Empty , inserted . TargetText ) ;
539+ }
540+
541+ [ Fact ]
542+ public void CompareStructureTreatsFormattedTableCellRunsAsOneLogicalParagraph ( ) {
543+ string sourcePath = Path . Combine ( _directoryWithFiles , "compare_structure_source_cell_formatted_runs.docx" ) ;
544+ using ( WordDocument doc = WordDocument . Create ( sourcePath ) ) {
545+ WordTable table = doc . AddTable ( 1 , 1 ) ;
546+ table . Rows [ 0 ] . Cells [ 0 ] . Paragraphs [ 0 ] . SetText ( "Project Alpha approved" ) ;
547+ doc . Save ( false ) ;
548+ }
549+
550+ string targetPath = Path . Combine ( _directoryWithFiles , "compare_structure_target_cell_formatted_runs.docx" ) ;
551+ using ( WordDocument doc = WordDocument . Create ( targetPath ) ) {
552+ WordTable table = doc . AddTable ( 1 , 1 ) ;
553+ WordParagraph paragraph = table . Rows [ 0 ] . Cells [ 0 ] . Paragraphs [ 0 ] ;
554+ paragraph . SetText ( "Project " ) ;
555+ paragraph . AddText ( "Alpha" ) . Bold = true ;
556+ paragraph . AddText ( " approved" ) ;
557+ doc . Save ( false ) ;
558+ }
559+
560+ WordComparisonResult result = WordDocumentComparer . CompareStructure ( sourcePath , targetPath ) ;
561+
562+ Assert . Empty ( result . Findings ) ;
563+ }
564+
565+ [ Fact ]
566+ public void CompareStructureIncludesHeaderFooterParagraphsAndTables ( ) {
567+ string sourcePath = Path . Combine ( _directoryWithFiles , "compare_structure_source_header_footer.docx" ) ;
568+ using ( WordDocument doc = WordDocument . Create ( sourcePath ) ) {
569+ doc . AddHeadersAndFooters ( ) ;
570+ doc . Header . Default ! . AddParagraph ( "Classification: Internal" ) ;
571+ WordTable footerTable = doc . Footer . Default ! . AddTable ( 1 , 2 ) ;
572+ footerTable . Rows [ 0 ] . Cells [ 0 ] . Paragraphs [ 0 ] . SetText ( "Owner" ) ;
573+ footerTable . Rows [ 0 ] . Cells [ 1 ] . Paragraphs [ 0 ] . SetText ( "Platform" ) ;
574+ doc . Save ( false ) ;
575+ }
576+
577+ string targetPath = Path . Combine ( _directoryWithFiles , "compare_structure_target_header_footer.docx" ) ;
578+ using ( WordDocument doc = WordDocument . Create ( targetPath ) ) {
579+ doc . AddHeadersAndFooters ( ) ;
580+ doc . Header . Default ! . AddParagraph ( "Classification: Confidential" ) ;
581+ WordTable footerTable = doc . Footer . Default ! . AddTable ( 1 , 2 ) ;
582+ footerTable . Rows [ 0 ] . Cells [ 0 ] . Paragraphs [ 0 ] . SetText ( "Owner" ) ;
583+ footerTable . Rows [ 0 ] . Cells [ 1 ] . Paragraphs [ 0 ] . SetText ( "Security" ) ;
584+ doc . Save ( false ) ;
585+ }
586+
587+ WordComparisonResult result = WordDocumentComparer . CompareStructure ( sourcePath , targetPath ) ;
588+
589+ WordComparisonFinding paragraph = Assert . Single ( result . Findings , finding =>
590+ finding . Scope == WordComparisonScope . Paragraph &&
591+ finding . ChangeKind == WordComparisonChangeKind . Modified ) ;
592+ Assert . Equal ( "Classification: Internal" , paragraph . SourceText ) ;
593+ Assert . Equal ( "Classification: Confidential" , paragraph . TargetText ) ;
594+
595+ WordComparisonFinding cell = Assert . Single ( result . Findings , finding =>
596+ finding . Scope == WordComparisonScope . TableCell &&
597+ finding . ChangeKind == WordComparisonChangeKind . Modified ) ;
598+ Assert . Equal ( "Platform" , cell . SourceText ) ;
599+ Assert . Equal ( "Security" , cell . TargetText ) ;
600+ }
601+
602+ [ Fact ]
603+ public void CompareStructureReportsExternalLinkedImageChanges ( ) {
604+ string sourcePath = Path . Combine ( _directoryWithFiles , "compare_structure_source_external_image.docx" ) ;
605+ using ( WordDocument doc = WordDocument . Create ( sourcePath ) ) {
606+ doc . AddParagraph ( ) . AddImage ( new Uri ( "https://example.com/logo-a.png" ) , 50 , 50 ) ;
607+ doc . Save ( false ) ;
608+ }
609+
610+ string targetPath = Path . Combine ( _directoryWithFiles , "compare_structure_target_external_image.docx" ) ;
611+ using ( WordDocument doc = WordDocument . Create ( targetPath ) ) {
612+ doc . AddParagraph ( ) . AddImage ( new Uri ( "https://example.com/logo-b.png" ) , 50 , 50 ) ;
613+ doc . Save ( false ) ;
614+ }
615+
616+ WordComparisonResult result = WordDocumentComparer . CompareStructure ( sourcePath , targetPath ) ;
617+
618+ WordComparisonFinding image = Assert . Single ( result . Findings , finding =>
619+ finding . Scope == WordComparisonScope . Image &&
620+ finding . ChangeKind == WordComparisonChangeKind . Modified ) ;
621+ Assert . Equal ( "[Image: https://example.com/logo-a.png]" , image . SourceText ) ;
622+ Assert . Equal ( "[Image: https://example.com/logo-b.png]" , image . TargetText ) ;
623+ }
624+
625+ [ Fact ]
626+ public void CompareStructureIncludesHeaderImages ( ) {
627+ string sourcePath = Path . Combine ( _directoryWithFiles , "compare_structure_source_header_image.docx" ) ;
628+ using ( WordDocument doc = WordDocument . Create ( sourcePath ) ) {
629+ doc . AddHeadersAndFooters ( ) ;
630+ doc . Header . Default ! . AddParagraph ( ) . AddImage ( Path . Combine ( _directoryWithImages , "EvotecLogo.png" ) ) ;
631+ doc . Save ( false ) ;
632+ }
633+
634+ string targetPath = Path . Combine ( _directoryWithFiles , "compare_structure_target_header_image.docx" ) ;
635+ using ( WordDocument doc = WordDocument . Create ( targetPath ) ) {
636+ doc . AddHeadersAndFooters ( ) ;
637+ doc . Header . Default ! . AddParagraph ( ) . AddImage ( Path . Combine ( _directoryWithImages , "Kulek.jpg" ) ) ;
638+ doc . Save ( false ) ;
639+ }
640+
641+ WordComparisonResult result = WordDocumentComparer . CompareStructure ( sourcePath , targetPath ) ;
642+
643+ WordComparisonFinding image = Assert . Single ( result . Findings , finding =>
644+ finding . Scope == WordComparisonScope . Image &&
645+ finding . ChangeKind == WordComparisonChangeKind . Modified ) ;
646+ Assert . Equal ( "image[0]" , image . Location ) ;
647+ }
648+
478649 private static void AssertNoTempArtifact ( WordDocument document ) {
479650 Assert . Equal ( string . Empty , document . FilePath ) ;
480651 }
0 commit comments