Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sw / qa / core / accessibilitycheck / AccessibilityCheckTest.cxx
blob2b99f49b0cb21ef676efd80493d87cdddf6278ba
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #include <swmodeltestbase.hxx>
11 #include <AccessibilityCheck.hxx>
12 #include <AccessibilityIssue.hxx>
13 #include <OnlineAccessibilityCheck.hxx>
14 #include <wrtsh.hxx>
15 #include <vcl/scheduler.hxx>
16 #include <comphelper/propertysequence.hxx>
18 #include <comphelper/scopeguard.hxx>
19 #include <officecfg/Office/Common.hxx>
21 class AccessibilityCheckTest : public SwModelTestBase
23 public:
24 AccessibilityCheckTest()
25 : SwModelTestBase("/sw/qa/core/accessibilitycheck/data/")
30 CPPUNIT_TEST_FIXTURE(AccessibilityCheckTest, testCheckDocumentIssues)
32 createSwDoc("DocumentTest.odt");
33 SwDoc* pDoc = getSwDoc();
34 CPPUNIT_ASSERT(pDoc);
35 sw::AccessibilityCheck aCheck(pDoc);
36 aCheck.check();
37 auto& aIssues = aCheck.getIssueCollection().getIssues();
38 CPPUNIT_ASSERT_EQUAL(size_t(2), aIssues.size());
39 CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::DOCUMENT_LANGUAGE, aIssues[0]->m_eIssueID);
40 CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::DOCUMENT_TITLE, aIssues[1]->m_eIssueID);
43 CPPUNIT_TEST_FIXTURE(AccessibilityCheckTest, testTableSplitMergeAndAltText)
45 createSwDoc("AccessibilityTests1.odt");
46 SwDoc* pDoc = getSwDoc();
47 CPPUNIT_ASSERT(pDoc);
48 sw::AccessibilityCheck aCheck(pDoc);
49 aCheck.check();
50 auto& aIssues = aCheck.getIssueCollection().getIssues();
51 CPPUNIT_ASSERT_EQUAL(size_t(6), aIssues.size());
53 CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::NO_ALT_GRAPHIC, aIssues[0]->m_eIssueID);
54 CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TABLE_MERGE_SPLIT, aIssues[1]->m_eIssueID);
55 CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TABLE_MERGE_SPLIT, aIssues[2]->m_eIssueID);
56 CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TABLE_MERGE_SPLIT, aIssues[3]->m_eIssueID);
57 CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TABLE_MERGE_SPLIT, aIssues[4]->m_eIssueID);
58 CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::NO_ALT_SHAPE, aIssues[5]->m_eIssueID);
61 CPPUNIT_TEST_FIXTURE(AccessibilityCheckTest, testCheckParagraphIssues)
63 // Tests whether formatting issues are detected when the whole paragraph has them instead of
64 // some text inside the paragraph
65 createSwDoc("ParagraphTest.odt");
66 SwDoc* pDoc = getSwDoc();
67 CPPUNIT_ASSERT(pDoc);
68 sw::AccessibilityCheck aCheck(pDoc);
69 aCheck.check();
70 auto& aIssues = aCheck.getIssueCollection().getIssues();
71 CPPUNIT_ASSERT_EQUAL(size_t(1), aIssues.size());
72 CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TEXT_FORMATTING, aIssues[0]->m_eIssueID);
75 CPPUNIT_TEST_FIXTURE(AccessibilityCheckTest, testCheckBackgroundImage)
77 createSwDoc("BackgroundImageTest.odt");
78 SwDoc* pDoc = getSwDoc();
79 CPPUNIT_ASSERT(pDoc);
80 sw::AccessibilityCheck aCheck(pDoc);
81 aCheck.check();
82 auto& aIssues = aCheck.getIssueCollection().getIssues();
83 CPPUNIT_ASSERT_EQUAL(size_t(1), aIssues.size());
84 CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::DOCUMENT_BACKGROUND, aIssues[0]->m_eIssueID);
87 CPPUNIT_TEST_FIXTURE(AccessibilityCheckTest, testCheckNewlineSpace)
89 createSwDoc("NewlineTest.odt");
90 SwDoc* pDoc = getSwDoc();
91 CPPUNIT_ASSERT(pDoc);
92 sw::AccessibilityCheck aCheck(pDoc);
93 aCheck.check();
94 auto& aIssues = aCheck.getIssueCollection().getIssues();
95 CPPUNIT_ASSERT_EQUAL(size_t(2), aIssues.size());
96 CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TEXT_FORMATTING, aIssues[0]->m_eIssueID);
97 CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TEXT_FORMATTING, aIssues[1]->m_eIssueID);
100 CPPUNIT_TEST_FIXTURE(AccessibilityCheckTest, testCheckSpacebarSpace)
102 createSwDoc("SpaceTest.odt");
103 SwDoc* pDoc = getSwDoc();
104 CPPUNIT_ASSERT(pDoc);
105 sw::AccessibilityCheck aCheck(pDoc);
106 aCheck.check();
107 auto& aIssues = aCheck.getIssueCollection().getIssues();
108 CPPUNIT_ASSERT_EQUAL(size_t(1), aIssues.size());
109 CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TEXT_FORMATTING, aIssues[0]->m_eIssueID);
112 CPPUNIT_TEST_FIXTURE(AccessibilityCheckTest, testHyperlinks)
114 createSwDoc("HyperlinkTest.odt");
115 SwDoc* pDoc = getSwDoc();
116 CPPUNIT_ASSERT(pDoc);
117 sw::AccessibilityCheck aCheck(pDoc);
118 aCheck.check();
119 auto& aIssues = aCheck.getIssueCollection().getIssues();
120 CPPUNIT_ASSERT_EQUAL(size_t(2), aIssues.size());
121 CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::HYPERLINK_SHORT, aIssues[0]->m_eIssueID);
122 CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::HYPERLINK_IS_TEXT, aIssues[1]->m_eIssueID);
125 CPPUNIT_TEST_FIXTURE(AccessibilityCheckTest, testCheckHighlightedText)
127 createSwDoc("HighlightTest.odt");
128 SwDoc* pDoc = getSwDoc();
129 CPPUNIT_ASSERT(pDoc);
130 sw::AccessibilityCheck aCheck(pDoc);
131 aCheck.check();
132 auto& aIssues = aCheck.getIssueCollection().getIssues();
133 CPPUNIT_ASSERT_EQUAL(size_t(1), aIssues.size());
134 CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TEXT_FORMATTING, aIssues[0]->m_eIssueID);
137 CPPUNIT_TEST_FIXTURE(AccessibilityCheckTest, testNumberingCheck)
139 createSwDoc("AccessibilityTests_NumberingCheck.odt");
140 SwDoc* pDoc = getSwDoc();
141 CPPUNIT_ASSERT(pDoc);
142 sw::AccessibilityCheck aCheck(pDoc);
143 aCheck.check();
144 auto& aIssues = aCheck.getIssueCollection().getIssues();
145 CPPUNIT_ASSERT_EQUAL(size_t(5), aIssues.size());
146 CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::MANUAL_NUMBERING, aIssues[0]->m_eIssueID);
147 CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::MANUAL_NUMBERING, aIssues[1]->m_eIssueID);
148 CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::MANUAL_NUMBERING, aIssues[2]->m_eIssueID);
149 CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::MANUAL_NUMBERING, aIssues[3]->m_eIssueID);
150 CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::MANUAL_NUMBERING, aIssues[4]->m_eIssueID);
153 CPPUNIT_TEST_FIXTURE(AccessibilityCheckTest, testCheckFakeFootnote)
155 createSwDoc("FakeFootnoteTest.odt");
156 SwDoc* pDoc = getSwDoc();
157 CPPUNIT_ASSERT(pDoc);
158 sw::AccessibilityCheck aCheck(pDoc);
159 aCheck.check();
160 auto& aIssues = aCheck.getIssueCollection().getIssues();
161 CPPUNIT_ASSERT_EQUAL(size_t(2), aIssues.size());
162 CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::FAKE_FOOTNOTE, aIssues[0]->m_eIssueID);
163 CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::FAKE_FOOTNOTE, aIssues[1]->m_eIssueID);
166 CPPUNIT_TEST_FIXTURE(AccessibilityCheckTest, testCheckFakeCaption)
168 createSwDoc("FakeCaptionTest.odt");
169 SwDoc* pDoc = getSwDoc();
170 CPPUNIT_ASSERT(pDoc);
171 sw::AccessibilityCheck aCheck(pDoc);
172 aCheck.check();
173 auto& aIssues = aCheck.getIssueCollection().getIssues();
174 CPPUNIT_ASSERT_EQUAL(size_t(1), aIssues.size());
175 CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::FAKE_CAPTION, aIssues[0]->m_eIssueID);
178 CPPUNIT_TEST_FIXTURE(AccessibilityCheckTest, testCheckTableFormatting)
180 createSwDoc("TableFormattingTest.odt");
181 SwDoc* pDoc = getSwDoc();
182 CPPUNIT_ASSERT(pDoc);
183 sw::AccessibilityCheck aCheck(pDoc);
184 aCheck.check();
185 auto& aIssues = aCheck.getIssueCollection().getIssues();
186 CPPUNIT_ASSERT_EQUAL(size_t(1), aIssues.size());
187 CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TABLE_FORMATTING, aIssues[0]->m_eIssueID);
190 CPPUNIT_TEST_FIXTURE(AccessibilityCheckTest, testCheckTabsFormatting)
192 createSwDoc("TabsTest.odt");
193 SwDoc* pDoc = getSwDoc();
194 CPPUNIT_ASSERT(pDoc);
195 sw::AccessibilityCheck aCheck(pDoc);
196 aCheck.check();
197 auto& aIssues = aCheck.getIssueCollection().getIssues();
198 CPPUNIT_ASSERT_EQUAL(size_t(4), aIssues.size());
199 CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TEXT_FORMATTING, aIssues[0]->m_eIssueID);
200 CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TEXT_FORMATTING, aIssues[1]->m_eIssueID);
201 CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TEXT_FORMATTING, aIssues[2]->m_eIssueID);
202 CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TEXT_FORMATTING, aIssues[3]->m_eIssueID);
205 namespace
207 std::vector<std::shared_ptr<sfx::AccessibilityIssue>>
208 scanAccessibilityIssuesOnNodes(SwDoc* pDocument)
210 std::vector<std::shared_ptr<sfx::AccessibilityIssue>> aIssues;
211 auto const& pNodes = pDocument->GetNodes();
212 for (SwNodeOffset n(0); n < pNodes.Count(); ++n)
214 SwNode* pNode = pNodes[n];
215 auto& pCollection = pNode->getAccessibilityCheckStatus().pCollection;
216 if (pCollection)
218 for (auto& pIssue : pCollection->getIssues())
220 aIssues.push_back(pIssue);
224 return aIssues;
227 void checkIssuePosition(std::shared_ptr<sfx::AccessibilityIssue> const& pIssue, int nLine,
228 sal_Int32 nStart, sal_Int32 nEnd, SwNodeOffset nIndex)
230 auto* pSwIssue = static_cast<sw::AccessibilityIssue*>(pIssue.get());
232 OString sFailMessage = OString::Concat("Start doesn't match at line: ")
233 + OString::Concat(OString::number(nLine));
234 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailMessage.getStr(), nStart, pSwIssue->getStart());
236 sFailMessage
237 = OString::Concat("End doesn't match at line: ") + OString::Concat(OString::number(nLine));
238 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailMessage.getStr(), nEnd, pSwIssue->getEnd());
240 sFailMessage = OString::Concat("Offset doesn't match at line: ")
241 + OString::Concat(OString::number(nLine));
242 CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailMessage.getStr(), nIndex, pSwIssue->getNode()->GetIndex());
245 } // end anonymous ns
247 CPPUNIT_TEST_FIXTURE(AccessibilityCheckTest, testOnlineNodeSplitAppend)
249 // Checks the a11y checker is setting the a11y issues to the nodes
250 // correctly when splitting and appending nodes (through undo), which
251 // happen on editing all the time.
252 // When a node is split, it can happen that both nodes get a11y issues
253 // if the node splits the area of direct formatting.
255 createSwDoc("OnlineCheck.odt");
256 SwDoc* pDoc = getSwDoc();
257 CPPUNIT_ASSERT(pDoc);
258 SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
259 CPPUNIT_ASSERT(pWrtShell);
261 // Enable online a11y checker
263 auto pBatch(comphelper::ConfigurationChanges::create());
264 officecfg::Office::Common::Accessibility::OnlineAccessibilityCheck::set(true, pBatch);
265 pBatch->commit();
267 comphelper::ScopeGuard g([] {
268 auto pBatch(comphelper::ConfigurationChanges::create());
269 officecfg::Office::Common::Accessibility::OnlineAccessibilityCheck::set(false, pBatch);
270 pBatch->commit();
273 Scheduler::ProcessEventsToIdle();
275 // Check we have 2 a11y issue
276 CPPUNIT_ASSERT_EQUAL(sal_Int32(2),
277 pDoc->getOnlineAccessibilityCheck()->getNumberOfAccessibilityIssues());
278 auto aIssues = scanAccessibilityIssuesOnNodes(pDoc);
279 CPPUNIT_ASSERT_EQUAL(size_t(2), aIssues.size());
280 CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TEXT_FORMATTING, aIssues[0]->m_eIssueID);
281 CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TEXT_FORMATTING, aIssues[1]->m_eIssueID);
282 checkIssuePosition(aIssues[0], __LINE__, 0, 32, SwNodeOffset(9));
283 checkIssuePosition(aIssues[1], __LINE__, 33, 136, SwNodeOffset(9));
285 // Position the cursor and hit "enter" (trigger split-node action)
286 pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 33, /*bBasicCall=*/false);
287 pWrtShell->SplitNode();
289 // Check the result
290 CPPUNIT_ASSERT_EQUAL(OUString("He heard quiet steps behind him. "),
291 getParagraph(1)->getString());
292 CPPUNIT_ASSERT_EQUAL(OUString("That didn't bode well. Who could be following him this late at "
293 "night and in this deadbeat part of town?"),
294 getParagraph(2)->getString());
295 CPPUNIT_ASSERT_EQUAL(sal_Int32(2),
296 pDoc->getOnlineAccessibilityCheck()->getNumberOfAccessibilityIssues());
298 aIssues = scanAccessibilityIssuesOnNodes(pDoc);
299 CPPUNIT_ASSERT_EQUAL(size_t(2), aIssues.size());
300 CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TEXT_FORMATTING, aIssues[0]->m_eIssueID);
301 CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TEXT_FORMATTING, aIssues[1]->m_eIssueID);
302 checkIssuePosition(aIssues[0], __LINE__, 0, 32, SwNodeOffset(9));
303 checkIssuePosition(aIssues[1], __LINE__, 0, 103, SwNodeOffset(10));
305 // Position cursor and split again
306 pWrtShell->Down(/*bSelect*/ false, /*nCount*/ 0);
307 pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 23, /*bBasicCall=*/false);
308 pWrtShell->SplitNode();
310 // Check the result
311 CPPUNIT_ASSERT_EQUAL(OUString("He heard quiet steps behind him. "),
312 getParagraph(1)->getString());
313 CPPUNIT_ASSERT_EQUAL(OUString("That didn't bode well. "), getParagraph(2)->getString());
314 CPPUNIT_ASSERT_EQUAL(
315 OUString(
316 "Who could be following him this late at night and in this deadbeat part of town?"),
317 getParagraph(3)->getString());
318 CPPUNIT_ASSERT_EQUAL(sal_Int32(3),
319 pDoc->getOnlineAccessibilityCheck()->getNumberOfAccessibilityIssues());
320 aIssues = scanAccessibilityIssuesOnNodes(pDoc);
321 CPPUNIT_ASSERT_EQUAL(size_t(3), aIssues.size());
322 CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TEXT_FORMATTING, aIssues[0]->m_eIssueID);
323 CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TEXT_FORMATTING, aIssues[1]->m_eIssueID);
324 CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TEXT_FORMATTING, aIssues[2]->m_eIssueID);
325 checkIssuePosition(aIssues[0], __LINE__, 0, 32, SwNodeOffset(9));
326 checkIssuePosition(aIssues[1], __LINE__, 0, 23, SwNodeOffset(10));
327 checkIssuePosition(aIssues[2], __LINE__, 0, 80, SwNodeOffset(11));
329 // Undo second change
330 dispatchCommand(mxComponent, ".uno:Undo", {});
331 CPPUNIT_ASSERT_EQUAL(OUString("He heard quiet steps behind him. "),
332 getParagraph(1)->getString());
333 CPPUNIT_ASSERT_EQUAL(OUString("That didn't bode well. Who could be following him this late at "
334 "night and in this deadbeat part of town?"),
335 getParagraph(2)->getString());
336 CPPUNIT_ASSERT_EQUAL(sal_Int32(2),
337 pDoc->getOnlineAccessibilityCheck()->getNumberOfAccessibilityIssues());
338 aIssues = scanAccessibilityIssuesOnNodes(pDoc);
339 CPPUNIT_ASSERT_EQUAL(size_t(2), aIssues.size());
340 CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TEXT_FORMATTING, aIssues[0]->m_eIssueID);
341 CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TEXT_FORMATTING, aIssues[1]->m_eIssueID);
342 checkIssuePosition(aIssues[0], __LINE__, 0, 32, SwNodeOffset(9));
343 checkIssuePosition(aIssues[1], __LINE__, 0, 103, SwNodeOffset(10));
345 // Undo first change
346 dispatchCommand(mxComponent, ".uno:Undo", {});
347 CPPUNIT_ASSERT_EQUAL(sal_Int32(2),
348 pDoc->getOnlineAccessibilityCheck()->getNumberOfAccessibilityIssues());
349 CPPUNIT_ASSERT_EQUAL(
350 OUString("He heard quiet steps behind him. That didn't bode well. Who could be following "
351 "him this late at night and in this deadbeat part of town?"),
352 getParagraph(1)->getString());
353 aIssues = scanAccessibilityIssuesOnNodes(pDoc);
354 CPPUNIT_ASSERT_EQUAL(size_t(2), aIssues.size());
355 CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TEXT_FORMATTING, aIssues[0]->m_eIssueID);
356 CPPUNIT_ASSERT_EQUAL(sfx::AccessibilityIssueID::TEXT_FORMATTING, aIssues[1]->m_eIssueID);
357 checkIssuePosition(aIssues[0], __LINE__, 0, 32, SwNodeOffset(9));
358 checkIssuePosition(aIssues[1], __LINE__, 33, 136, SwNodeOffset(9));
361 CPPUNIT_PLUGIN_IMPLEMENT();
363 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */