sw/qa/core/fields/data/styleref-flags.docx         |binary
 sw/qa/core/fields/data/styleref.odt                |binary
 sw/qa/core/fields/data/suppress-non-numerical.docx |binary
 sw/qa/core/fields/fields.cxx                       |  215 ++++++++++++++++-----
 4 files changed, 169 insertions(+), 46 deletions(-)

New commits:
commit fd5c75750f5c5448eec840033bce16375774a707
Author:     Skyler Grey <skyler.g...@collabora.com>
AuthorDate: Mon Oct 23 09:17:23 2023 +0000
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Thu Nov 2 10:27:52 2023 +0100

    Improve and extend STYLEREF tests
    
    - I7d8f455ffe90cface4f3b1acf6b9bef6a045ed19,
      Ib664fec059aa1f7f130acc76c253d5d298fa59f7 and
      Iad8e8001807f5ceeaedc9665838672695174a936 added STYLEREF flags. This
      commit adds tests for them
    - The tests in I35dc36197b62fa53def4745da1d4755ece79ed22 were partly
      broken due to the fields occasionally being inserted in the wrong
      place (i.e. at the end of the document), this commit makes sure to
      move the cursor before inserting a field
    - The tests in I35dc36197b62fa53def4745da1d4755ece79ed22 were not
      separated into sections which made it difficult to tell what was being
      tested. All STYLEREF tests that create documents are now clearly split
      into arrange/act/assert steps with comments denoting the sections
    - The tests in I35dc36197b62fa53def4745da1d4755ece79ed22 had a lot of
      repetition, particularly in creating the document, adding headings,
      etc. This has been refactored into some helper functions
    - I35dc36197b62fa53def4745da1d4755ece79ed22 was missing an ODF import
      test. This commit adds one
    
    Follow-Up-To: I25dd7a6940abee5651a784b9059fe23b32547d6c
    Follow-Up-To: I35dc36197b62fa53def4745da1d4755ece79ed22
    Follow-Up-To: I7d8f455ffe90cface4f3b1acf6b9bef6a045ed19
    Follow-Up-To: Ib664fec059aa1f7f130acc76c253d5d298fa59f7
    Follow-Up-To: Iad8e8001807f5ceeaedc9665838672695174a936
    Follow-Up-To: Iecd3e83a6bd3f8c2c6adba5c7eba9ee55b773510
    Follow-Up-To: Ifaa67fbc2d53b0d4fb85e7305b2dbdf78cf0a1ad
    Follow-Up-To: Id991c92b9aeaa054b136f7a3d9c7c8ea0026e514
    Change-Id: I941b477c8e860270a400869cb9ea15e5561e402a
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/158352
    Tested-by: Jenkins
    Tested-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>

diff --git a/sw/qa/core/fields/data/styleref-flags.docx 
b/sw/qa/core/fields/data/styleref-flags.docx
new file mode 100644
index 000000000000..443624a575e0
Binary files /dev/null and b/sw/qa/core/fields/data/styleref-flags.docx differ
diff --git a/sw/qa/core/fields/data/styleref.odt 
b/sw/qa/core/fields/data/styleref.odt
new file mode 100644
index 000000000000..27af5aae1f06
Binary files /dev/null and b/sw/qa/core/fields/data/styleref.odt differ
diff --git a/sw/qa/core/fields/data/suppress-non-numerical.docx 
b/sw/qa/core/fields/data/suppress-non-numerical.docx
new file mode 100644
index 000000000000..439e048b9f93
Binary files /dev/null and b/sw/qa/core/fields/data/suppress-non-numerical.docx 
differ
diff --git a/sw/qa/core/fields/fields.cxx b/sw/qa/core/fields/fields.cxx
index 9fae9cafef13..8e6a1488fa3a 100644
--- a/sw/qa/core/fields/fields.cxx
+++ b/sw/qa/core/fields/fields.cxx
@@ -7,8 +7,9 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
+#include <com/sun/star/text/XParagraphCursor.hpp>
+#include <reffld.hxx>
 #include <com/sun/star/beans/PropertyValue.hpp>
-#include <com/sun/star/frame/XStorable.hpp>
 #include <com/sun/star/beans/XPropertySet.hpp>
 #include <com/sun/star/container/XIndexAccess.hpp>
 #include <com/sun/star/text/ControlCharacter.hpp>
@@ -36,7 +37,6 @@
 
 #include <com/sun/star/text/XTextDocument.hpp>
 #include <com/sun/star/text/XTextFieldsSupplier.hpp>
-
 #include <comphelper/propertyvalue.hxx>
 
 #include <authfld.hxx>
@@ -182,27 +182,49 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf86790)
         CPPUNIT_ASSERT_EQUAL(sValue.first, xField->getPresentation(true));
         CPPUNIT_ASSERT_EQUAL(sValue.second, xField->getPresentation(false));
     }
+    CPPUNIT_ASSERT(!xFields->hasMoreElements());
+}
+
+void InsertParagraphBreak(const uno::Reference<text::XTextCursor>& xCursor)
+{
+    uno::Reference<text::XText> xText = xCursor->getText();
+    xText->insertControlCharacter(xCursor, 
text::ControlCharacter::PARAGRAPH_BREAK, false);
+}
+void InsertHeading(const uno::Reference<text::XTextCursor>& xCursor, const 
OUString& content)
+{
+    uno::Reference<beans::XPropertySet> xCursorPropertySet(xCursor, 
uno::UNO_QUERY);
+    uno::Reference<text::XText> xText = xCursor->getText();
+
+    xCursorPropertySet->setPropertyValue("ParaStyleName", 
uno::Any(OUString("Heading 1")));
+    xText->insertString(xCursor, content, false);
+    InsertParagraphBreak(xCursor);
 }
 
 /// If there is referenced text both above and below, STYLEREF searches up
 CPPUNIT_TEST_FIXTURE(Test, testStyleRefSearchUp)
 {
+    // Arrange
+    // Create a document with headings both above and below a cursor
     createSwDoc();
 
     uno::Reference<text::XTextDocument> xTextDocument(mxComponent, 
uno::UNO_QUERY);
     uno::Reference<text::XText> xText = xTextDocument->getText();
 
     uno::Reference<text::XTextCursor> xCursor = xText->createTextCursor();
-    uno::Reference<beans::XPropertySet> xCursorPropertySet(xCursor, 
uno::UNO_QUERY);
 
-    xCursorPropertySet->setPropertyValue("ParaStyleName", 
uno::Any(OUString("Heading 1")));
-    xText->insertString(xCursor, "Heading far above field", false);
-    xText->insertControlCharacter(xCursor, 
text::ControlCharacter::PARAGRAPH_BREAK, false);
+    InsertHeading(xCursor, "Heading far above field");
+    InsertHeading(xCursor, "Heading above field");
+    InsertParagraphBreak(xCursor);
+    InsertHeading(xCursor, "Heading below field");
+    InsertHeading(xCursor, "Heading far below field");
 
-    xCursorPropertySet->setPropertyValue("ParaStyleName", 
uno::Any(OUString("Heading 1")));
-    xText->insertString(xCursor, "Heading above field", false);
-    xText->insertControlCharacter(xCursor, 
text::ControlCharacter::PARAGRAPH_BREAK, false);
+    uno::Reference<text::XParagraphCursor> xParagraphCursor(xCursor, 
uno::UNO_QUERY);
+    xParagraphCursor->gotoPreviousParagraph(false); // Heading far below...
+    xParagraphCursor->gotoPreviousParagraph(false); // Heading below...
+    xParagraphCursor->gotoPreviousParagraph(false); // Blank space
 
+    // Act
+    // Insert a STYLEREF field which looks for "Heading 1"s
     uno::Reference<lang::XMultiServiceFactory> xFactory(mxComponent, 
uno::UNO_QUERY);
     uno::Reference<text::XTextField> xField(
         xFactory->createInstance("com.sun.star.text.TextField.GetReference"), 
uno::UNO_QUERY);
@@ -214,27 +236,36 @@ CPPUNIT_TEST_FIXTURE(Test, testStyleRefSearchUp)
                                         
uno::Any(sal_Int16(text::ReferenceFieldPart::TEXT)));
     xFieldPropertySet->setPropertyValue("SourceName", 
uno::Any(OUString("Heading 1")));
 
-    uno::Reference<text::XTextCursor> xFieldCursor = xText->createTextCursor();
+    xField->attach(xCursor);
 
-    xText->insertControlCharacter(xCursor, 
text::ControlCharacter::PARAGRAPH_BREAK, false);
-    xCursorPropertySet->setPropertyValue("ParaStyleName", 
uno::Any(OUString("Heading 1")));
-    xText->insertString(xCursor, "Heading below field", false);
-
-    xField->attach(xFieldCursor);
+    // Assert
+    // Make sure the field has the right text
     CPPUNIT_ASSERT_EQUAL(OUString("Heading above field"), 
xField->getPresentation(false));
 }
 
-/// If there is referenced text both above and below, STYLEREF searches down
+/// If there is referenced text only below, STYLEREF searches down
 CPPUNIT_TEST_FIXTURE(Test, testStyleRefSearchDown)
 {
+    // Arrange
+    // Create a document with headings below a cursor
     createSwDoc();
 
     uno::Reference<text::XTextDocument> xTextDocument(mxComponent, 
uno::UNO_QUERY);
     uno::Reference<text::XText> xText = xTextDocument->getText();
 
     uno::Reference<text::XTextCursor> xCursor = xText->createTextCursor();
-    uno::Reference<beans::XPropertySet> xCursorPropertySet(xCursor, 
uno::UNO_QUERY);
 
+    InsertParagraphBreak(xCursor);
+    InsertHeading(xCursor, "Heading below field");
+    InsertHeading(xCursor, "Heading far below field");
+
+    uno::Reference<text::XParagraphCursor> xParagraphCursor(xCursor, 
uno::UNO_QUERY);
+    xParagraphCursor->gotoPreviousParagraph(false); // Heading far below...
+    xParagraphCursor->gotoPreviousParagraph(false); // Heading below...
+    xParagraphCursor->gotoPreviousParagraph(false); // Blank space
+
+    // Act
+    // Insert a STYLEREF field which looks for "Heading 1"s
     uno::Reference<lang::XMultiServiceFactory> xFactory(mxComponent, 
uno::UNO_QUERY);
     uno::Reference<text::XTextField> xField(
         xFactory->createInstance("com.sun.star.text.TextField.GetReference"), 
uno::UNO_QUERY);
@@ -246,39 +277,30 @@ CPPUNIT_TEST_FIXTURE(Test, testStyleRefSearchDown)
                                         
uno::Any(sal_Int16(text::ReferenceFieldPart::TEXT)));
     xFieldPropertySet->setPropertyValue("SourceName", 
uno::Any(OUString("Heading 1")));
 
-    uno::Reference<text::XTextCursor> xFieldCursor = xText->createTextCursor();
-
-    xText->insertControlCharacter(xCursor, 
text::ControlCharacter::PARAGRAPH_BREAK, false);
-    xCursorPropertySet->setPropertyValue("ParaStyleName", 
uno::Any(OUString("Heading 1")));
-    xText->insertString(xCursor, "Heading below field", false);
+    xField->attach(xCursor);
 
-    xText->insertControlCharacter(xCursor, 
text::ControlCharacter::PARAGRAPH_BREAK, false);
-    xCursorPropertySet->setPropertyValue("ParaStyleName", 
uno::Any(OUString("Heading 1")));
-    xText->insertString(xCursor, "Heading far below field", false);
-
-    xField->attach(xFieldCursor);
+    // Assert
+    // Make sure the field has the right text
     CPPUNIT_ASSERT_EQUAL(OUString("Heading below field"), 
xField->getPresentation(false));
 }
 
 /// STYLEREFs in marginals (headers or footers) should search in the page they 
are on first, regardless if there is anything above them
 CPPUNIT_TEST_FIXTURE(Test, testMarginalStyleRef)
 {
+    // Arrange
+    // Create a document with 2 headings
     createSwDoc();
 
     uno::Reference<text::XTextDocument> xTextDocument(mxComponent, 
uno::UNO_QUERY);
     uno::Reference<text::XText> xText = xTextDocument->getText();
 
     uno::Reference<text::XTextCursor> xCursor = xText->createTextCursor();
-    uno::Reference<beans::XPropertySet> xCursorPropertySet(xCursor, 
uno::UNO_QUERY);
 
-    xCursorPropertySet->setPropertyValue("ParaStyleName", 
uno::Any(OUString("Heading 1")));
-    xText->insertString(xCursor, "Top heading on page", false);
-    xText->insertControlCharacter(xCursor, 
text::ControlCharacter::PARAGRAPH_BREAK, false);
-
-    xCursorPropertySet->setPropertyValue("ParaStyleName", 
uno::Any(OUString("Heading 1")));
-    xText->insertString(xCursor, "Bottom heading on page", false);
-    xText->insertControlCharacter(xCursor, 
text::ControlCharacter::PARAGRAPH_BREAK, false);
+    InsertHeading(xCursor, "Top heading on page");
+    InsertHeading(xCursor, "Bottom heading on page");
 
+    // Act
+    // Insert a STYLEREF field which looks for "Heading 1"s into the footer
     uno::Reference<lang::XMultiServiceFactory> xFactory(mxComponent, 
uno::UNO_QUERY);
     uno::Reference<text::XTextField> xField(
         xFactory->createInstance("com.sun.star.text.TextField.GetReference"), 
uno::UNO_QUERY);
@@ -305,28 +327,36 @@ CPPUNIT_TEST_FIXTURE(Test, testMarginalStyleRef)
     uno::Reference<text::XTextRange> xFooterCursor = 
xFooterText->createTextCursor();
     xField->attach(xFooterCursor);
 
+    // Assert
+    // Make sure the field has the right text
     CPPUNIT_ASSERT_EQUAL(OUString("Top heading on page"), 
xField->getPresentation(false));
 }
 
 /// STYLEREFs in footnotes should search from the point of the reference mark
 CPPUNIT_TEST_FIXTURE(Test, testFootnoteStyleRef)
 {
+    // Arrange
+    // Create a document with headings both above and below a cursor
     createSwDoc();
 
     uno::Reference<text::XTextDocument> xTextDocument(mxComponent, 
uno::UNO_QUERY);
     uno::Reference<text::XText> xText = xTextDocument->getText();
 
     uno::Reference<text::XTextCursor> xCursor = xText->createTextCursor();
-    uno::Reference<beans::XPropertySet> xCursorPropertySet(xCursor, 
uno::UNO_QUERY);
 
-    xCursorPropertySet->setPropertyValue("ParaStyleName", 
uno::Any(OUString("Heading 1")));
-    xText->insertString(xCursor, "Heading far above reference mark", false);
-    xText->insertControlCharacter(xCursor, 
text::ControlCharacter::PARAGRAPH_BREAK, false);
+    InsertHeading(xCursor, "Heading far above reference mark");
+    InsertHeading(xCursor, "Heading above reference mark");
+    InsertParagraphBreak(xCursor);
+    InsertHeading(xCursor, "Heading below reference mark");
+    InsertHeading(xCursor, "Heading far below reference mark");
 
-    xCursorPropertySet->setPropertyValue("ParaStyleName", 
uno::Any(OUString("Heading 1")));
-    xText->insertString(xCursor, "Heading above reference mark", false);
-    xText->insertControlCharacter(xCursor, 
text::ControlCharacter::PARAGRAPH_BREAK, false);
+    uno::Reference<text::XParagraphCursor> xParagraphCursor(xCursor, 
uno::UNO_QUERY);
+    xParagraphCursor->gotoPreviousParagraph(false); // Heading far below...
+    xParagraphCursor->gotoPreviousParagraph(false); // Heading below...
+    xParagraphCursor->gotoPreviousParagraph(false); // Blank space
 
+    // Act
+    // Insert a STYLEREF field which looks for "Heading 1"s into a footnote
     uno::Reference<lang::XMultiServiceFactory> xFactory(mxComponent, 
uno::UNO_QUERY);
 
     uno::Reference<text::XFootnote> xFootnote(
@@ -334,10 +364,6 @@ CPPUNIT_TEST_FIXTURE(Test, testFootnoteStyleRef)
     xFootnote->setLabel("Style reference mark");
     xText->insertTextContent(xCursor, xFootnote, false);
 
-    xText->insertControlCharacter(xCursor, 
text::ControlCharacter::PARAGRAPH_BREAK, false);
-    xCursorPropertySet->setPropertyValue("ParaStyleName", 
uno::Any(OUString("Heading 1")));
-    xText->insertString(xCursor, "Heading below reference mark", false);
-
     uno::Reference<text::XTextField> xField(
         xFactory->createInstance("com.sun.star.text.TextField.GetReference"), 
uno::UNO_QUERY);
 
@@ -352,8 +378,105 @@ CPPUNIT_TEST_FIXTURE(Test, testFootnoteStyleRef)
     uno::Reference<text::XTextRange> xFootnoteCursor = 
xFootnoteText->createTextCursor();
     xField->attach(xFootnoteCursor);
 
+    // Assert
+    // Make sure the field has the right text
     CPPUNIT_ASSERT_EQUAL(OUString("Heading above reference mark"), 
xField->getPresentation(false));
 }
+
+/// STYLEREFs with the REFFLDFLAG_HIDE_NON_NUMERICAL flag should hide all 
characters that are not numerical or delimiters
+CPPUNIT_TEST_FIXTURE(Test, testNumericalStyleRef)
+{
+    loadFromURL(u"suppress-non-numerical.docx");
+
+    uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(mxComponent, 
uno::UNO_QUERY);
+    uno::Reference<container::XEnumerationAccess> xFieldsAccess(
+        xTextFieldsSupplier->getTextFields());
+    uno::Reference<container::XEnumeration> 
xFields(xFieldsAccess->createEnumeration());
+
+    // Similarly to testChapterFieldsFollowedBy, the fields are enumerated 
with #1 first and everything else in reverse order
+    std::vector<std::pair<OUString, OUString>> aFieldValues = {
+        { " Heading 1", "3" }, // #1
+        { " Heading 2", ".2\\@123^&~|a....." }, // #4
+        { " Heading 2", ".2\\|a....." }, // #3
+        { " Heading 1", "Chapter 3.!" }, // #2
+    };
+
+    for (const auto& sValue : aFieldValues)
+    {
+        CPPUNIT_ASSERT(xFields->hasMoreElements());
+        uno::Reference<text::XTextField> xField(xFields->nextElement(), 
uno::UNO_QUERY);
+        CPPUNIT_ASSERT_EQUAL(sValue.first, xField->getPresentation(true));
+        CPPUNIT_ASSERT_EQUAL(sValue.second, xField->getPresentation(false));
+    }
+    CPPUNIT_ASSERT(!xFields->hasMoreElements());
+}
+
+/// We should be able to import these flags from OOXML documents
+/// (Note: in Word, STYLEREF 'search bottom up' flag does nothing unless it's 
in a marginal, we place no such limitation but
+///        this docx only has such stylerefs to avoid confusion)
+CPPUNIT_TEST_FIXTURE(Test, testOOXMLStyleRefFlags)
+{
+    loadFromURL(u"styleref-flags.docx");
+
+    uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(mxComponent, 
uno::UNO_QUERY);
+    uno::Reference<container::XEnumerationAccess> xFieldsAccess(
+        xTextFieldsSupplier->getTextFields());
+    uno::Reference<container::XEnumeration> 
xFields(xFieldsAccess->createEnumeration());
+
+    // Similarly to testChapterFieldsFollowedBy, the fields are enumerated 
with #1 first and everything else in reverse order
+    std::vector<std::pair<OUString, OUString>> aFieldValues = {
+        { " Heading 2", "2.1" }, // #1
+        { " Heading 1", "3" }, // #5
+        { " Heading 1", "A top level heading at the top of the page" }, // #4
+        { " Heading 1", "The last top level heading" }, // #3
+        { " Heading 2", "Heading 2.1" }, // #2
+    };
+
+    for (const auto& sValue : aFieldValues)
+    {
+        CPPUNIT_ASSERT(xFields->hasMoreElements());
+        uno::Reference<text::XTextField> xField(xFields->nextElement(), 
uno::UNO_QUERY);
+        CPPUNIT_ASSERT_EQUAL(sValue.first, xField->getPresentation(true));
+        CPPUNIT_ASSERT_EQUAL(sValue.second, xField->getPresentation(false));
+    }
+    CPPUNIT_ASSERT(!xFields->hasMoreElements());
+}
+
+/// We should be able to import these flags from OOXML documents
+/// (Note: in Word, STYLEREF 'search bottom up' flag does nothing unless it's 
in a marginal, we place no such limitation but
+///        this docx only has such stylerefs to avoid confusion)
+CPPUNIT_TEST_FIXTURE(Test, testODFStyleRef)
+{
+    loadFromURL(u"styleref.odt");
+
+    uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(mxComponent, 
uno::UNO_QUERY);
+    uno::Reference<container::XEnumerationAccess> xFieldsAccess(
+        xTextFieldsSupplier->getTextFields());
+    uno::Reference<container::XEnumeration> 
xFields(xFieldsAccess->createEnumeration());
+
+    // Similarly to testChapterFieldsFollowedBy, the fields are enumerated 
with #1 first and everything else in reverse order
+    std::vector<std::pair<OUString, OUString>> aFieldValues = {
+        { " Heading 1", "1:" }, // #1
+        { " Heading 2", "In footnotes" }, // #10
+        { " Heading 2", "In document text" }, // #9
+        { " Heading 1", "STYLEREF in different locations" }, // #8
+        { " Heading 1", "2:" }, // #7
+        { " Heading 1", "With STYLEREF, many things are possible" }, // #6
+        { " Heading 1", "1:" }, // #5
+        { " Heading 1", "STYLEREF in different locations" }, // #4
+        { " Heading 1", "2:" }, // #3
+        { " Heading 1", "With STYLEREF, many things are possible" }, // #2
+    };
+
+    for (const auto& sValue : aFieldValues)
+    {
+        CPPUNIT_ASSERT(xFields->hasMoreElements());
+        uno::Reference<text::XTextField> xField(xFields->nextElement(), 
uno::UNO_QUERY);
+        CPPUNIT_ASSERT_EQUAL(sValue.first, xField->getPresentation(true));
+        CPPUNIT_ASSERT_EQUAL(sValue.second, xField->getPresentation(false));
+    }
+    CPPUNIT_ASSERT(!xFields->hasMoreElements());
+}
 }
 
 CPPUNIT_PLUGIN_IMPLEMENT();

Reply via email to