sw/CppunitTest_sw_core_accessibilitycheck.mk             |    3 
 sw/qa/core/accessibilitycheck/AccessibilityCheckTest.cxx |  170 +++++++++++++++
 sw/qa/core/accessibilitycheck/data/OnlineCheck.odt       |binary
 sw/source/core/inc/AccessibilityIssue.hxx                |    6 
 4 files changed, 177 insertions(+), 2 deletions(-)

New commits:
commit 02d1163dc8d769ae65baadaedc2a254a8e909d66
Author:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
AuthorDate: Sun Nov 13 22:27:54 2022 +0900
Commit:     Tomaž Vajngerl <qui...@gmail.com>
CommitDate: Fri Feb 17 05:16:09 2023 +0000

    sw: test online a11y check - splitting and joining nodes
    
    Change-Id: I9be3df3a4c00e7f1bbfc4f2462c8cf9a0f813f9d
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/142656
    Tested-by: Jenkins
    Reviewed-by: Tomaž Vajngerl <qui...@gmail.com>
    (cherry picked from commit e7f78c3123c7bb7b8c830fa11241c357d89bad6a)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/144498
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>

diff --git a/sw/CppunitTest_sw_core_accessibilitycheck.mk 
b/sw/CppunitTest_sw_core_accessibilitycheck.mk
index 1780c7c4bfc9..91b455dda736 100644
--- a/sw/CppunitTest_sw_core_accessibilitycheck.mk
+++ b/sw/CppunitTest_sw_core_accessibilitycheck.mk
@@ -25,11 +25,12 @@ $(eval $(call 
gb_CppunitTest_use_libraries,sw_core_accessibilitycheck, \
     svx \
     sfx \
     sw \
-       swqahelper \
+    swqahelper \
     test \
     unotest \
     utl \
     tl \
+    vcl \
 ))
 
 $(eval $(call gb_CppunitTest_use_externals,sw_core_accessibilitycheck,\
diff --git a/sw/qa/core/accessibilitycheck/AccessibilityCheckTest.cxx 
b/sw/qa/core/accessibilitycheck/AccessibilityCheckTest.cxx
index 3a7ea285efbf..713537422f8c 100644
--- a/sw/qa/core/accessibilitycheck/AccessibilityCheckTest.cxx
+++ b/sw/qa/core/accessibilitycheck/AccessibilityCheckTest.cxx
@@ -11,6 +11,14 @@
 #include <AccessibilityCheck.hxx>
 #include <unotxdoc.hxx>
 #include <docsh.hxx>
+#include <AccessibilityIssue.hxx>
+#include <OnlineAccessibilityCheck.hxx>
+#include <wrtsh.hxx>
+#include <vcl/scheduler.hxx>
+#include <comphelper/propertysequence.hxx>
+
+#include <comphelper/scopeguard.hxx>
+#include <officecfg/Office/Common.hxx>
 
 constexpr OUStringLiteral DATA_DIRECTORY = 
u"/sw/qa/core/accessibilitycheck/data/";
 
@@ -181,6 +189,168 @@ CPPUNIT_TEST_FIXTURE(AccessibilityCheckTest, 
testNumberingCheck)
     CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::MANUAL_NUMBERING, 
aIssues[4]->m_eIssueID);
 }
 
+namespace
+{
+std::vector<std::shared_ptr<sfx::AccessibilityIssue>>
+scanAccessibilityIssuesOnNodes(SwDoc* pDocument)
+{
+    std::vector<std::shared_ptr<sfx::AccessibilityIssue>> aIssues;
+    auto const& pNodes = pDocument->GetNodes();
+    for (SwNodeOffset n(0); n < pNodes.Count(); ++n)
+    {
+        SwNode* pNode = pNodes[n];
+        auto& pCollection = pNode->getAccessibilityCheckStatus().pCollection;
+        if (pCollection)
+        {
+            for (auto& pIssue : pCollection->getIssues())
+            {
+                aIssues.push_back(pIssue);
+            }
+        }
+    }
+    return aIssues;
+}
+
+void checkIssuePosition(std::shared_ptr<sfx::AccessibilityIssue> const& 
pIssue, int nLine,
+                        sal_Int32 nStart, sal_Int32 nEnd, SwNodeOffset nIndex)
+{
+    auto* pSwIssue = static_cast<sw::AccessibilityIssue*>(pIssue.get());
+
+    OString sFailMessage = OString::Concat("Start doesn't match at line: ")
+                           + OString::Concat(OString::number(nLine));
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailMessage.getStr(), nStart, 
pSwIssue->getStart());
+
+    sFailMessage
+        = OString::Concat("End doesn't match at line: ") + 
OString::Concat(OString::number(nLine));
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailMessage.getStr(), nEnd, 
pSwIssue->getEnd());
+
+    sFailMessage = OString::Concat("Offset doesn't match at line: ")
+                   + OString::Concat(OString::number(nLine));
+    CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailMessage.getStr(), nIndex, 
pSwIssue->getNode()->GetIndex());
+}
+
+} // end anonymous ns
+
+CPPUNIT_TEST_FIXTURE(AccessibilityCheckTest, testOnlineNodeSplitAppend)
+{
+    // Checks the a11y checker is setting the a11y issues to the nodes
+    // correctly when splitting and appending nodes (through undo), which
+    // happen on editing all the time.
+    // When a node is split, it can happen that both nodes get a11y issues
+    // if the node splits the area of direct formatting.
+
+    SwDoc* pDoc = createSwDoc(DATA_DIRECTORY, "OnlineCheck.odt");
+    CPPUNIT_ASSERT(pDoc);
+    SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+    CPPUNIT_ASSERT(pWrtShell);
+
+    // Enable online a11y checker
+    {
+        auto pBatch(comphelper::ConfigurationChanges::create());
+        
officecfg::Office::Common::Accessibility::OnlineAccessibilityCheck::set(true, 
pBatch);
+        pBatch->commit();
+    }
+    comphelper::ScopeGuard g([] {
+        auto pBatch(comphelper::ConfigurationChanges::create());
+        
officecfg::Office::Common::Accessibility::OnlineAccessibilityCheck::set(false, 
pBatch);
+        pBatch->commit();
+    });
+
+    Scheduler::ProcessEventsToIdle();
+
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(0),
+                         
pDoc->getOnlineAccessibilityCheck()->getNumberOfAccessibilityIssues());
+    // Trigger a11y checker
+    pWrtShell->Down(/*bSelect*/ false, /*nCount*/ 0);
+
+    // Check we have 1 a11y issue
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(2),
+                         
pDoc->getOnlineAccessibilityCheck()->getNumberOfAccessibilityIssues());
+    auto aIssues = scanAccessibilityIssuesOnNodes(pDoc);
+    CPPUNIT_ASSERT_EQUAL(size_t(2), aIssues.size());
+    CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TEXT_FORMATTING, 
aIssues[0]->m_eIssueID);
+    CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TEXT_FORMATTING, 
aIssues[1]->m_eIssueID);
+    checkIssuePosition(aIssues[0], __LINE__, 0, 32, SwNodeOffset(9));
+    checkIssuePosition(aIssues[1], __LINE__, 33, 136, SwNodeOffset(9));
+
+    // Position the cursor and hit "enter" (trigger split-node action)
+    pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/false, 33, 
/*bBasicCall=*/false);
+    pWrtShell->SplitNode();
+
+    // Check the result
+    CPPUNIT_ASSERT_EQUAL(OUString("He heard quiet steps behind him. "),
+                         getParagraph(1)->getString());
+    CPPUNIT_ASSERT_EQUAL(OUString("That didn't bode well. Who could be 
following him this late at "
+                                  "night and in this deadbeat part of town?"),
+                         getParagraph(2)->getString());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(2),
+                         
pDoc->getOnlineAccessibilityCheck()->getNumberOfAccessibilityIssues());
+
+    aIssues = scanAccessibilityIssuesOnNodes(pDoc);
+    CPPUNIT_ASSERT_EQUAL(size_t(2), aIssues.size());
+    CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TEXT_FORMATTING, 
aIssues[0]->m_eIssueID);
+    CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TEXT_FORMATTING, 
aIssues[1]->m_eIssueID);
+    checkIssuePosition(aIssues[0], __LINE__, 0, 32, SwNodeOffset(9));
+    checkIssuePosition(aIssues[1], __LINE__, 0, 103, SwNodeOffset(10));
+
+    // Position cursor and split again
+    pWrtShell->Down(/*bSelect*/ false, /*nCount*/ 0);
+    pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/false, 23, 
/*bBasicCall=*/false);
+    pWrtShell->SplitNode();
+
+    // Check the result
+    CPPUNIT_ASSERT_EQUAL(OUString("He heard quiet steps behind him. "),
+                         getParagraph(1)->getString());
+    CPPUNIT_ASSERT_EQUAL(OUString("That didn't bode well. "), 
getParagraph(2)->getString());
+    CPPUNIT_ASSERT_EQUAL(
+        OUString(
+            "Who could be following him this late at night and in this 
deadbeat part of town?"),
+        getParagraph(3)->getString());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(3),
+                         
pDoc->getOnlineAccessibilityCheck()->getNumberOfAccessibilityIssues());
+    aIssues = scanAccessibilityIssuesOnNodes(pDoc);
+    CPPUNIT_ASSERT_EQUAL(size_t(3), aIssues.size());
+    CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TEXT_FORMATTING, 
aIssues[0]->m_eIssueID);
+    CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TEXT_FORMATTING, 
aIssues[1]->m_eIssueID);
+    CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TEXT_FORMATTING, 
aIssues[2]->m_eIssueID);
+    checkIssuePosition(aIssues[0], __LINE__, 0, 32, SwNodeOffset(9));
+    checkIssuePosition(aIssues[1], __LINE__, 0, 23, SwNodeOffset(10));
+    checkIssuePosition(aIssues[2], __LINE__, 0, 80, SwNodeOffset(11));
+
+    // Undo second change
+    dispatchCommand(mxComponent, ".uno:Undo", {});
+    Scheduler::ProcessEventsToIdle();
+    CPPUNIT_ASSERT_EQUAL(OUString("He heard quiet steps behind him. "),
+                         getParagraph(1)->getString());
+    CPPUNIT_ASSERT_EQUAL(OUString("That didn't bode well. Who could be 
following him this late at "
+                                  "night and in this deadbeat part of town?"),
+                         getParagraph(2)->getString());
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(2),
+                         
pDoc->getOnlineAccessibilityCheck()->getNumberOfAccessibilityIssues());
+    aIssues = scanAccessibilityIssuesOnNodes(pDoc);
+    CPPUNIT_ASSERT_EQUAL(size_t(2), aIssues.size());
+    CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TEXT_FORMATTING, 
aIssues[0]->m_eIssueID);
+    CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TEXT_FORMATTING, 
aIssues[1]->m_eIssueID);
+    checkIssuePosition(aIssues[0], __LINE__, 0, 32, SwNodeOffset(9));
+    checkIssuePosition(aIssues[1], __LINE__, 0, 103, SwNodeOffset(10));
+
+    // Undo first change
+    dispatchCommand(mxComponent, ".uno:Undo", {});
+    Scheduler::ProcessEventsToIdle();
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(2),
+                         
pDoc->getOnlineAccessibilityCheck()->getNumberOfAccessibilityIssues());
+    CPPUNIT_ASSERT_EQUAL(
+        OUString("He heard quiet steps behind him. That didn't bode well. Who 
could be following "
+                 "him this late at night and in this deadbeat part of town?"),
+        getParagraph(1)->getString());
+    aIssues = scanAccessibilityIssuesOnNodes(pDoc);
+    CPPUNIT_ASSERT_EQUAL(size_t(2), aIssues.size());
+    CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TEXT_FORMATTING, 
aIssues[0]->m_eIssueID);
+    CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TEXT_FORMATTING, 
aIssues[1]->m_eIssueID);
+    checkIssuePosition(aIssues[0], __LINE__, 0, 32, SwNodeOffset(9));
+    checkIssuePosition(aIssues[1], __LINE__, 33, 136, SwNodeOffset(9));
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/qa/core/accessibilitycheck/data/OnlineCheck.odt 
b/sw/qa/core/accessibilitycheck/data/OnlineCheck.odt
new file mode 100644
index 000000000000..d24fb4ff1abf
Binary files /dev/null and b/sw/qa/core/accessibilitycheck/data/OnlineCheck.odt 
differ
diff --git a/sw/source/core/inc/AccessibilityIssue.hxx 
b/sw/source/core/inc/AccessibilityIssue.hxx
index 8823303057a1..870ad2364692 100644
--- a/sw/source/core/inc/AccessibilityIssue.hxx
+++ b/sw/source/core/inc/AccessibilityIssue.hxx
@@ -25,7 +25,7 @@ enum class IssueObject
     TEXT,
 };
 
-class AccessibilityIssue final : public sfx::AccessibilityIssue
+class SW_DLLPUBLIC AccessibilityIssue final : public sfx::AccessibilityIssue
 {
 private:
     IssueObject m_eIssueObject;
@@ -58,6 +58,10 @@ public:
 
     bool canGotoIssue() const override;
     void gotoIssue() const override;
+
+    sal_Int32 getStart() { return m_nStart; }
+    sal_Int32 getEnd() { return m_nEnd; }
+    SwNode* getNode() { return m_pNode; }
 };
 
 } // end sw namespace

Reply via email to