Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sw / qa / extras / odfexport / odfexport2.cxx
blob103892a7723ab16a3881a03c4d1204d6865dd752
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>
12 #include <com/sun/star/drawing/BarCode.hpp>
13 #include <com/sun/star/drawing/BarCodeErrorCorrection.hpp>
14 #include <com/sun/star/drawing/GraphicExportFilter.hpp>
15 #include <com/sun/star/drawing/XGraphicExportFilter.hpp>
16 #include <com/sun/star/io/XOutputStream.hpp>
17 #include <com/sun/star/style/VerticalAlignment.hpp>
18 #include <com/sun/star/text/ColumnSeparatorStyle.hpp>
19 #include <com/sun/star/text/XBookmarksSupplier.hpp>
20 #include <com/sun/star/text/XChapterNumberingSupplier.hpp>
21 #include <com/sun/star/text/XDocumentIndex.hpp>
22 #include <com/sun/star/text/XDocumentIndexesSupplier.hpp>
23 #include <com/sun/star/text/XTextColumns.hpp>
24 #include <com/sun/star/text/XTextFieldsSupplier.hpp>
25 #include <com/sun/star/text/XTextTable.hpp>
26 #include <com/sun/star/text/XTextTablesSupplier.hpp>
27 #include <com/sun/star/util/XRefreshable.hpp>
28 #include <unotools/localedatawrapper.hxx>
29 #include <unotools/streamwrap.hxx>
30 #include <comphelper/processfactory.hxx>
31 #include <comphelper/propertysequence.hxx>
32 #include <comphelper/sequenceashashmap.hxx>
33 #include <unoprnms.hxx>
34 #include <unotxdoc.hxx>
35 #include <docsh.hxx>
37 class Test : public SwModelTestBase
39 public:
40 Test() : SwModelTestBase("/sw/qa/extras/odfexport/data/", "writer8") {}
43 CPPUNIT_TEST_FIXTURE(Test, testEmbeddedFontProps)
45 loadAndReload("embedded-font-props.odt");
46 CPPUNIT_ASSERT_EQUAL(1, getPages());
47 #if !defined(MACOSX)
48 // Test that font style/weight of embedded fonts is exposed.
49 // Test file is a normal ODT, except EmbedFonts is set to true in settings.xml.
50 xmlDocUniquePtr pXmlDoc = parseExport("content.xml");
51 // These failed, the attributes were missing.
52 assertXPath(pXmlDoc, "//style:font-face[@style:name='Liberation Serif']/svg:font-face-src/svg:font-face-uri[1]", "font-style", "normal");
53 assertXPath(pXmlDoc, "//style:font-face[@style:name='Liberation Serif']/svg:font-face-src/svg:font-face-uri[1]", "font-weight", "normal");
54 assertXPath(pXmlDoc, "//style:font-face[@style:name='Liberation Serif']/svg:font-face-src/svg:font-face-uri[2]", "font-style", "normal");
55 assertXPath(pXmlDoc, "//style:font-face[@style:name='Liberation Serif']/svg:font-face-src/svg:font-face-uri[2]", "font-weight", "bold");
56 assertXPath(pXmlDoc, "//style:font-face[@style:name='Liberation Serif']/svg:font-face-src/svg:font-face-uri[3]", "font-style", "italic");
57 assertXPath(pXmlDoc, "//style:font-face[@style:name='Liberation Serif']/svg:font-face-src/svg:font-face-uri[3]", "font-weight", "normal");
58 assertXPath(pXmlDoc, "//style:font-face[@style:name='Liberation Serif']/svg:font-face-src/svg:font-face-uri[4]", "font-style", "italic");
59 assertXPath(pXmlDoc, "//style:font-face[@style:name='Liberation Serif']/svg:font-face-src/svg:font-face-uri[4]", "font-weight", "bold");
60 #endif
63 DECLARE_ODFEXPORT_TEST(testTdf100492, "tdf100492.odt")
65 CPPUNIT_ASSERT_EQUAL(2, getShapes());
66 CPPUNIT_ASSERT_EQUAL(1, getPages());
67 uno::Reference<drawing::XShape> xShape = getShape(1);
68 CPPUNIT_ASSERT(xShape.is());
70 // Save the first shape to a SVG
71 uno::Reference<drawing::XGraphicExportFilter> xGraphicExporter = drawing::GraphicExportFilter::create(comphelper::getProcessComponentContext());
72 uno::Reference<lang::XComponent> xSourceDoc(xShape, uno::UNO_QUERY);
73 xGraphicExporter->setSourceDocument(xSourceDoc);
75 SvMemoryStream aStream;
76 uno::Reference<io::XOutputStream> xOutputStream(new utl::OStreamWrapper(aStream));
77 uno::Sequence<beans::PropertyValue> aDescriptor( comphelper::InitPropertySequence({
78 { "OutputStream", uno::Any(xOutputStream) },
79 { "FilterName", uno::Any(OUString("SVG")) }
80 }));
81 xGraphicExporter->filter(aDescriptor);
82 aStream.Seek(STREAM_SEEK_TO_BEGIN);
84 // TODO: Disabled. Parsing of SVG gives just root node without any children.
85 // Reason of such behavior unclear. So XPATH assert fails.
87 // Parse resulting SVG as XML file.
88 // xmlDocUniquePtr pXmlDoc = parseXmlStream(&aStream);
90 // Check amount of paths required to draw an arrow.
91 // Since there are still some empty paths in output test can fail later. There are just two
92 // really used and visible paths.
93 //assertXPath(pXmlDoc, "/svg/path", 4);
96 DECLARE_ODFEXPORT_TEST(testTdf77961, "tdf77961.odt")
98 CPPUNIT_ASSERT_EQUAL(1, getPages());
99 uno::Reference<container::XNameAccess> xStyles(getStyles("PageStyles"));
100 uno::Reference<beans::XPropertySet> xStyle(xStyles->getByName("Standard"), uno::UNO_QUERY);
101 CPPUNIT_ASSERT_EQUAL( false , getProperty<bool>(xStyle, "GridDisplay"));
102 CPPUNIT_ASSERT_EQUAL( false , getProperty<bool>(xStyle, "GridPrint"));
105 DECLARE_ODFEXPORT_TEST(testReferenceLanguage, "referencelanguage.odt")
107 CPPUNIT_ASSERT_EQUAL(2, getPages());
108 // Test loext:reference-language attribute of reference fields
109 // (used from LibreOffice 6.1, and proposed for next ODF)
110 OUString const aFieldTexts[] = { "A 2", "Az Isten", "Az 50-esek",
111 "A 2018-asok", "Az egyebek", "A fejezetek",
112 u"Az „Őseinket...”", "a 2",
113 "Az v", "az 1", "Az e)", "az 1",
114 "Az (5)", "az 1", "A 2", "az 1" };
115 uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(mxComponent, uno::UNO_QUERY);
116 // update "A (4)" to "Az (5)"
117 uno::Reference<util::XRefreshable>(xTextFieldsSupplier->getTextFields(), uno::UNO_QUERY_THROW)->refresh();
119 uno::Reference<container::XEnumerationAccess> xFieldsAccess(xTextFieldsSupplier->getTextFields());
120 uno::Reference<container::XEnumeration> xFields(xFieldsAccess->createEnumeration());
122 uno::Any aHu(OUString("Hu"));
123 uno::Any ahu(OUString("hu"));
124 for (auto const& sFieldText : aFieldTexts)
126 uno::Any aField = xFields->nextElement();
127 uno::Reference<lang::XServiceInfo> xServiceInfo(aField, uno::UNO_QUERY);
128 if (xServiceInfo->supportsService("com.sun.star.text.textfield.GetReference"))
130 uno::Reference<beans::XPropertySet> xPropertySet(aField, uno::UNO_QUERY);
131 uno::Any aLang = xPropertySet->getPropertyValue("ReferenceFieldLanguage");
132 CPPUNIT_ASSERT_EQUAL(true, aLang == aHu || aLang == ahu);
133 uno::Reference<text::XTextContent> xField(aField, uno::UNO_QUERY);
134 CPPUNIT_ASSERT_EQUAL(sFieldText, xField->getAnchor()->getString());
139 CPPUNIT_TEST_FIXTURE(Test, testRubyPosition)
141 loadAndReload("ruby-position.odt");
142 CPPUNIT_ASSERT_EQUAL(1, getPages());
143 xmlDocUniquePtr pXmlDoc = parseExport("content.xml");
145 assertXPath(pXmlDoc, "//style:style[@style:family='ruby']/style:ruby-properties[@loext:ruby-position='inter-character']", 1);
146 assertXPath(pXmlDoc, "//style:style[@style:family='ruby']/style:ruby-properties[@style:ruby-position='below']", 1);
149 DECLARE_ODFEXPORT_TEST(testAllowOverlap, "allow-overlap.odt")
151 CPPUNIT_ASSERT_EQUAL(2, getShapes());
152 CPPUNIT_ASSERT_EQUAL(1, getPages());
153 uno::Reference<drawing::XShape> xShape = getShape(1);
154 // Without the accompanying fix in place, this test would have failed with:
155 // - Expression: !getProperty<bool>(xShape, "AllowOverlap")
156 // i.e. the custom AllowOverlap=false shape property was lost on import/export.
157 CPPUNIT_ASSERT(!getProperty<bool>(xShape, "AllowOverlap"));
158 xShape = getShape(2);
159 CPPUNIT_ASSERT(!getProperty<bool>(xShape, "AllowOverlap"));
162 CPPUNIT_TEST_FIXTURE(Test, testSignatureLineProperties)
164 loadAndReload("signatureline-properties.fodt");
165 uno::Reference<drawing::XShape> xShape = getShape(1);
166 CPPUNIT_ASSERT(xShape.is());
168 CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(xShape, "IsSignatureLine"));
169 CPPUNIT_ASSERT_EQUAL(OUString("{3C24159B-3B98-4F60-AB52-00E7721758E9}"),
170 getProperty<OUString>(xShape, "SignatureLineId"));
171 CPPUNIT_ASSERT_EQUAL(OUString("John Doe"),
172 getProperty<OUString>(xShape, "SignatureLineSuggestedSignerName"));
173 CPPUNIT_ASSERT_EQUAL(OUString("Farmer"),
174 getProperty<OUString>(xShape, "SignatureLineSuggestedSignerTitle"));
175 CPPUNIT_ASSERT_EQUAL(OUString("john@farmers.org"),
176 getProperty<OUString>(xShape, "SignatureLineSuggestedSignerEmail"));
177 CPPUNIT_ASSERT_EQUAL(OUString("Please farm here."),
178 getProperty<OUString>(xShape, "SignatureLineSigningInstructions"));
179 CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(xShape, "SignatureLineCanAddComment"));
180 CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(xShape, "SignatureLineShowSignDate"));
182 // tdf#130917 This needs to be always set when importing a doc, ooxml export expects it.
183 uno::Reference<graphic::XGraphic> xUnsignedGraphic;
184 uno::Reference<beans::XPropertySet> xProps(xShape, uno::UNO_QUERY);
185 xProps->getPropertyValue("SignatureLineUnsignedImage") >>= xUnsignedGraphic;
186 CPPUNIT_ASSERT_EQUAL(true, xUnsignedGraphic.is());
189 DECLARE_ODFEXPORT_TEST(testQrCodeGenProperties, "qrcode-properties.odt")
191 CPPUNIT_ASSERT_EQUAL(1, getShapes());
192 CPPUNIT_ASSERT_EQUAL(1, getPages());
193 uno::Reference<drawing::XShape> xShape = getShape(1);
194 CPPUNIT_ASSERT(xShape.is());
196 css::drawing::BarCode aBarCode = getProperty<css::drawing::BarCode>(xShape, "BarCodeProperties");
198 CPPUNIT_ASSERT_EQUAL(OUString("www.libreoffice.org"),
199 aBarCode.Payload);
200 CPPUNIT_ASSERT_EQUAL(css::drawing::BarCodeErrorCorrection::LOW,
201 aBarCode.ErrorCorrection);
202 CPPUNIT_ASSERT_EQUAL(sal_Int32(5),
203 aBarCode.Border);
206 DECLARE_ODFEXPORT_TEST(testChapterNumberingNewLine, "chapter-number-new-line.odt")
208 CPPUNIT_ASSERT_EQUAL(1, getPages());
209 uno::Reference<text::XChapterNumberingSupplier> xNumberingSupplier(mxComponent, uno::UNO_QUERY);
210 uno::Reference<container::XIndexAccess> xNumberingRules = xNumberingSupplier->getChapterNumberingRules();
211 comphelper::SequenceAsHashMap hashMap(xNumberingRules->getByIndex(0));
213 //This failed Actual Value was LISTTAB instead of NEWLINE
214 CPPUNIT_ASSERT_EQUAL(
215 sal_Int16(SvxNumberFormat::NEWLINE), hashMap["LabelFollowedBy"].get<sal_Int16>());
218 DECLARE_ODFEXPORT_TEST(testSpellOutNumberingTypes, "spellout-numberingtypes.odt")
220 CPPUNIT_ASSERT_EQUAL(1, getPages());
221 // ordinal indicator, ordinal and cardinal number numbering styles (from LibreOffice 6.1)
222 OUString const aFieldTexts[] = { "1st", "Erste", "Eins", "1.", "Premier", "Un", u"1ᵉʳ", "First", "One" };
223 // fallback for old platforms without std::codecvt and std::regex supports
224 OUString const aFieldTextFallbacks[] = { "Ordinal-number 1", "Ordinal 1", "1" };
225 uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(mxComponent, uno::UNO_QUERY);
226 // update text field content
227 uno::Reference<util::XRefreshable>(xTextFieldsSupplier->getTextFields(), uno::UNO_QUERY_THROW)->refresh();
229 uno::Reference<container::XEnumerationAccess> xFieldsAccess(xTextFieldsSupplier->getTextFields());
230 uno::Reference<container::XEnumeration> xFields(xFieldsAccess->createEnumeration());
232 for (size_t i = 0; i < SAL_N_ELEMENTS(aFieldTexts); i++)
234 uno::Any aField = xFields->nextElement();
235 uno::Reference<lang::XServiceInfo> xServiceInfo(aField, uno::UNO_QUERY);
236 if (xServiceInfo->supportsService("com.sun.star.text.textfield.PageNumber"))
238 uno::Reference<text::XTextContent> xField(aField, uno::UNO_QUERY);
239 CPPUNIT_ASSERT_EQUAL(true, aFieldTexts[i].equals(xField->getAnchor()->getString()) ||
240 aFieldTextFallbacks[i%3].equals(xField->getAnchor()->getString()));
245 // MAILMERGE Add conditional to expand / collapse bookmarks
246 DECLARE_ODFEXPORT_TEST(tdf101856_overlapped, "tdf101856_overlapped.odt")
248 CPPUNIT_ASSERT_EQUAL(1, getPages());
249 // get bookmark interface
250 uno::Reference<text::XBookmarksSupplier> xBookmarksSupplier(mxComponent, uno::UNO_QUERY);
251 uno::Reference<container::XIndexAccess> xBookmarksByIdx(xBookmarksSupplier->getBookmarks(), uno::UNO_QUERY);
252 uno::Reference<container::XNameAccess> xBookmarksByName = xBookmarksSupplier->getBookmarks();
254 // check: we have 2 bookmarks
255 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), xBookmarksByIdx->getCount());
256 CPPUNIT_ASSERT(xBookmarksByName->hasByName("BookmarkNonHidden"));
257 CPPUNIT_ASSERT(xBookmarksByName->hasByName("BookmarkHidden"));
259 // <text:bookmark-start text:name="BookmarkNonHidden"/>
260 uno::Reference<beans::XPropertySet> xBookmark1(xBookmarksByName->getByName("BookmarkNonHidden"), uno::UNO_QUERY);
261 CPPUNIT_ASSERT_EQUAL(OUString(""), getProperty<OUString>(xBookmark1, UNO_NAME_BOOKMARK_CONDITION));
262 CPPUNIT_ASSERT_EQUAL(false, getProperty<bool>(xBookmark1, UNO_NAME_BOOKMARK_HIDDEN));
264 // <text:bookmark-start text:name="BookmarkHidden"/>
265 uno::Reference<beans::XPropertySet> xBookmark2(xBookmarksByName->getByName("BookmarkHidden"), uno::UNO_QUERY);
266 CPPUNIT_ASSERT_EQUAL(OUString(""), getProperty<OUString>(xBookmark2, UNO_NAME_BOOKMARK_CONDITION));
267 CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(xBookmark2, UNO_NAME_BOOKMARK_HIDDEN));
270 // MAILMERGE Add conditional to expand / collapse bookmarks
271 DECLARE_ODFEXPORT_TEST(tdf101856, "tdf101856.odt")
273 CPPUNIT_ASSERT_EQUAL(1, getPages());
274 // get bookmark interface
275 uno::Reference<text::XBookmarksSupplier> xBookmarksSupplier(mxComponent, uno::UNO_QUERY);
276 uno::Reference<container::XIndexAccess> xBookmarksByIdx(xBookmarksSupplier->getBookmarks(), uno::UNO_QUERY);
277 uno::Reference<container::XNameAccess> xBookmarksByName = xBookmarksSupplier->getBookmarks();
279 // check: we have 2 bookmarks
280 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(5), xBookmarksByIdx->getCount());
281 CPPUNIT_ASSERT(xBookmarksByName->hasByName("BookmarkVisible"));
282 CPPUNIT_ASSERT(xBookmarksByName->hasByName("BookmarkHidden"));
283 CPPUNIT_ASSERT(xBookmarksByName->hasByName("BookmarkVisibleWithCondition"));
284 CPPUNIT_ASSERT(xBookmarksByName->hasByName("BookmarkNotHiddenWithCondition"));
285 CPPUNIT_ASSERT(xBookmarksByName->hasByName("BookmarkHiddenWithCondition"));
287 // <text:bookmark-start text:name="BookmarkVisible"/>
288 uno::Reference<beans::XPropertySet> xBookmark1(xBookmarksByName->getByName("BookmarkVisible"), uno::UNO_QUERY);
289 CPPUNIT_ASSERT_EQUAL(OUString(""), getProperty<OUString>(xBookmark1, UNO_NAME_BOOKMARK_CONDITION));
290 CPPUNIT_ASSERT_EQUAL(false, getProperty<bool>(xBookmark1, UNO_NAME_BOOKMARK_HIDDEN));
292 // <text:bookmark-start text:name="BookmarkHidden" loext:condition="" loext:hidden="true"/>
293 uno::Reference<beans::XPropertySet> xBookmark2(xBookmarksByName->getByName("BookmarkHidden"), uno::UNO_QUERY);
294 CPPUNIT_ASSERT_EQUAL(OUString(""), getProperty<OUString>(xBookmark2, UNO_NAME_BOOKMARK_CONDITION));
295 CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(xBookmark2, UNO_NAME_BOOKMARK_HIDDEN));
297 // <text:bookmark-start text:name="BookmarkVisibleWithCondition" loext:condition="0==1" loext:hidden="true"/>
298 uno::Reference<beans::XPropertySet> xBookmark3(xBookmarksByName->getByName("BookmarkVisibleWithCondition"), uno::UNO_QUERY);
299 CPPUNIT_ASSERT_EQUAL(OUString("0==1"), getProperty<OUString>(xBookmark3, UNO_NAME_BOOKMARK_CONDITION));
300 CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(xBookmark3, UNO_NAME_BOOKMARK_HIDDEN));
302 // <text:bookmark-start text:name="BookmarkNotHiddenWithCondition" loext:condition="1==1" loext:hidden="false"/>
304 // The following test doesn't work, while during output in the case of loext:hidden="false".
305 // no additional parameters are written. Implementation should be reviewed.
307 // uno::Reference<beans::XPropertySet> xBookmark4(xBookmarksByName->getByName("BookmarkNotHiddenWithCondition"), uno::UNO_QUERY);
308 // CPPUNIT_ASSERT_EQUAL(OUString("1==1"), getProperty<OUString>(xBookmark4, UNO_NAME_BOOKMARK_CONDITION));
309 // CPPUNIT_ASSERT_EQUAL(false, getProperty<bool>(xBookmark4, UNO_NAME_BOOKMARK_HIDDEN));
311 // <text:bookmark-start text:name="BookmarkHiddenWithCondition" loext:condition="1==1" loext:hidden="true"/>
312 uno::Reference<beans::XPropertySet> xBookmark5(xBookmarksByName->getByName("BookmarkHiddenWithCondition"), uno::UNO_QUERY);
313 CPPUNIT_ASSERT_EQUAL(OUString("1==1"), getProperty<OUString>(xBookmark5, UNO_NAME_BOOKMARK_CONDITION));
314 CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(xBookmark5, UNO_NAME_BOOKMARK_HIDDEN));
317 DECLARE_ODFEXPORT_TEST(tdf118502, "tdf118502.odt")
319 CPPUNIT_ASSERT_EQUAL(1, getShapes());
320 CPPUNIT_ASSERT_EQUAL(1, getPages());
321 uno::Reference<drawing::XShape> xShape = getShape(1);
322 // Make sure the replacement graphic is still there
323 // (was gone because the original graphic was not recognized during load)
324 auto xReplacementGraphic
325 = getProperty<uno::Reference<graphic::XGraphic>>(xShape, "ReplacementGraphic");
326 CPPUNIT_ASSERT(xReplacementGraphic.is());
329 CPPUNIT_TEST_FIXTURE(Test, tdf99631)
331 loadAndReload("tdf99631.docx");
332 // check import of VisualArea settings of the embedded XLSX OLE objects
333 xmlDocUniquePtr pXmlDoc = parseExport("Object 1/settings.xml");
334 assertXPathContent(pXmlDoc, "//config:config-item[@config:name='VisibleAreaWidth']", "4516");
335 assertXPathContent(pXmlDoc, "//config:config-item[@config:name='VisibleAreaHeight']", "903");
337 xmlDocUniquePtr pXmlDoc2 = parseExport("Object 2/settings.xml");
338 assertXPathContent(pXmlDoc2, "//config:config-item[@config:name='VisibleAreaWidth']", "4516");
339 assertXPathContent(pXmlDoc2, "//config:config-item[@config:name='VisibleAreaHeight']", "1355");
342 CPPUNIT_TEST_FIXTURE(Test, tdf145871)
344 loadAndReload("tdf145871.odt");
345 uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
346 uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables( ), uno::UNO_QUERY);
347 uno::Reference<text::XTextTable> xTextTable(xTables->getByIndex(0), uno::UNO_QUERY);
348 uno::Reference<table::XTableRows> xTableRows = xTextTable->getRows();
350 // Without the fix in place, this test would have failed with
351 // - Expected: 3150
352 // - Actual : 5851
353 CPPUNIT_ASSERT_EQUAL(sal_Int64(3150) , getProperty<sal_Int64>(xTableRows->getByIndex(0), "Height"));
356 CPPUNIT_TEST_FIXTURE(Test, tdf128504)
358 loadAndReload("tdf128504.docx");
359 uno::Reference<text::XTextRange> xPara = getParagraph(6);
360 uno::Reference<beans::XPropertySet> xRun(getRun(xPara,1), uno::UNO_QUERY);
361 OUString unVisitedStyleName = getProperty<OUString>(xRun, "UnvisitedCharStyleName");
362 CPPUNIT_ASSERT(!unVisitedStyleName.equalsIgnoreAsciiCase("Internet Link"));
363 OUString visitedStyleName = getProperty<OUString>(xRun, "VisitedCharStyleName");
364 CPPUNIT_ASSERT(!visitedStyleName.equalsIgnoreAsciiCase("Visited Internet Link"));
367 DECLARE_ODFEXPORT_TEST(tdf121658, "tdf121658.odt")
369 CPPUNIT_ASSERT_EQUAL(1, getPages());
370 uno::Reference<container::XNameAccess> xParaStyles(getStyles("ParagraphStyles"));
371 uno::Reference<beans::XPropertySet> xStyle1(xParaStyles->getByName(
372 "Standard"), uno::UNO_QUERY);
373 CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(xStyle1, "ParaHyphenationNoCaps"));
376 DECLARE_ODFEXPORT_TEST(tdf149248, "tdf149248.odt")
378 CPPUNIT_ASSERT_EQUAL(1, getPages());
379 CPPUNIT_ASSERT_EQUAL(false, getProperty<bool>(getParagraph(2), "ParaHyphenationNoLastWord"));
380 CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(getParagraph(4), "ParaHyphenationNoLastWord"));
383 DECLARE_ODFEXPORT_TEST(testTdf150394, "tdf150394.odt")
385 // crashes at import time
386 CPPUNIT_ASSERT_EQUAL(1, getPages());
389 DECLARE_ODFEXPORT_TEST(tdf149324, "tdf149324.odt")
391 CPPUNIT_ASSERT_EQUAL(1, getPages());
392 CPPUNIT_ASSERT_EQUAL(sal_uInt16(0), getProperty<sal_uInt16>(getParagraph(2), "ParaHyphenationMinWordLength"));
393 CPPUNIT_ASSERT_EQUAL(sal_uInt16(7), getProperty<sal_uInt16>(getParagraph(4), "ParaHyphenationMinWordLength"));
396 DECLARE_ODFEXPORT_TEST(tdf149420, "tdf149420.odt")
398 CPPUNIT_ASSERT_EQUAL(1, getPages());
399 CPPUNIT_ASSERT_EQUAL(sal_uInt16(0), getProperty<sal_uInt16>(getParagraph(2), "ParaHyphenationZone"));
400 CPPUNIT_ASSERT_EQUAL(sal_uInt16(567), getProperty<sal_uInt16>(getParagraph(4), "ParaHyphenationZone"));
403 DECLARE_ODFEXPORT_TEST(testArabicZeroNumbering, "arabic-zero-numbering.odt")
405 CPPUNIT_ASSERT_EQUAL(1, getPages());
406 auto xNumberingRules
407 = getProperty<uno::Reference<container::XIndexAccess>>(getParagraph(1), "NumberingRules");
408 comphelper::SequenceAsHashMap aMap(xNumberingRules->getByIndex(0));
409 // Without the accompanying fix in place, this test would have failed with:
410 // - Expected: 64
411 // - Actual : 4
412 // i.e. numbering type was ARABIC, not ARABIC_ZERO.
413 CPPUNIT_ASSERT_EQUAL(o3tl::narrowing<sal_uInt16>(style::NumberingType::ARABIC_ZERO),
414 aMap["NumberingType"].get<sal_uInt16>());
417 DECLARE_ODFEXPORT_TEST(testArabicZero3Numbering, "arabic-zero3-numbering.odt")
419 CPPUNIT_ASSERT_EQUAL(1, getPages());
420 auto xNumberingRules
421 = getProperty<uno::Reference<container::XIndexAccess>>(getParagraph(1), "NumberingRules");
422 comphelper::SequenceAsHashMap aMap(xNumberingRules->getByIndex(0));
423 // Without the accompanying fix in place, this test would have failed with:
424 // - Expected: 65
425 // - Actual : 4
426 // i.e. numbering type was ARABIC, not ARABIC_ZERO3.
427 CPPUNIT_ASSERT_EQUAL(o3tl::narrowing<sal_uInt16>(style::NumberingType::ARABIC_ZERO3),
428 aMap["NumberingType"].get<sal_uInt16>());
431 DECLARE_ODFEXPORT_TEST(testArabicZero4Numbering, "arabic-zero4-numbering.odt")
433 CPPUNIT_ASSERT_EQUAL(1, getPages());
434 auto xNumberingRules
435 = getProperty<uno::Reference<container::XIndexAccess>>(getParagraph(1), "NumberingRules");
436 comphelper::SequenceAsHashMap aMap(xNumberingRules->getByIndex(0));
437 // Without the accompanying fix in place, this test would have failed with:
438 // - Expected: 66
439 // - Actual : 4
440 // i.e. numbering type was ARABIC, not ARABIC_ZERO4.
441 CPPUNIT_ASSERT_EQUAL(o3tl::narrowing<sal_uInt16>(style::NumberingType::ARABIC_ZERO4),
442 aMap["NumberingType"].get<sal_uInt16>());
445 DECLARE_ODFEXPORT_TEST(testArabicZero5Numbering, "arabic-zero5-numbering.odt")
447 CPPUNIT_ASSERT_EQUAL(1, getPages());
448 auto xNumberingRules
449 = getProperty<uno::Reference<container::XIndexAccess>>(getParagraph(1), "NumberingRules");
450 comphelper::SequenceAsHashMap aMap(xNumberingRules->getByIndex(0));
451 // Without the accompanying fix in place, this test would have failed with:
452 // - Expected: 67
453 // - Actual : 4
454 // i.e. numbering type was ARABIC, not ARABIC_ZERO5.
455 CPPUNIT_ASSERT_EQUAL(o3tl::narrowing<sal_uInt16>(style::NumberingType::ARABIC_ZERO5),
456 aMap["NumberingType"].get<sal_uInt16>());
459 DECLARE_ODFEXPORT_TEST(testRovasNumbering, "rovas-numbering.odt")
461 CPPUNIT_ASSERT_EQUAL(1, getPages());
462 auto xNumberingRules
463 = getProperty<uno::Reference<container::XIndexAccess>>(getParagraph(1), "NumberingRules");
464 comphelper::SequenceAsHashMap aMap(xNumberingRules->getByIndex(0));
465 // Without the accompanying fix in place, this test would have failed with:
466 // - Expected: 68
467 // - Actual : 4
468 // i.e. numbering type was ARABIC, not SZEKELY_ROVAS.
469 CPPUNIT_ASSERT_EQUAL(o3tl::narrowing<sal_uInt16>(style::NumberingType::SZEKELY_ROVAS),
470 aMap["NumberingType"].get<sal_uInt16>());
473 DECLARE_ODFEXPORT_TEST(testPageContentTop, "page-content-top.odt")
475 CPPUNIT_ASSERT_EQUAL(1, getShapes());
476 CPPUNIT_ASSERT_EQUAL(1, getPages());
477 uno::Reference<beans::XPropertySet> xShape(getShape(1), uno::UNO_QUERY);
478 sal_Int16 nExpected = text::RelOrientation::PAGE_PRINT_AREA_TOP;
479 CPPUNIT_ASSERT_EQUAL(nExpected, getProperty<sal_Int16>(xShape, "VertOrientRelation"));
482 DECLARE_ODFEXPORT_TEST(testPageContentBottom, "page-content-bottom.odt")
484 CPPUNIT_ASSERT_EQUAL(1, getShapes());
485 CPPUNIT_ASSERT_EQUAL(1, getPages());
486 uno::Reference<beans::XPropertySet> xShape(getShape(1), uno::UNO_QUERY);
487 sal_Int16 nExpected = text::RelOrientation::PAGE_PRINT_AREA_BOTTOM;
488 CPPUNIT_ASSERT_EQUAL(nExpected, getProperty<sal_Int16>(xShape, "VertOrientRelation"));
491 CPPUNIT_TEST_FIXTURE(Test, tdf124470)
493 loadAndReload("tdf124470TableAndEmbeddedUsedFonts.odt");
494 // Table styles were exported out of place, inside font-face-decls.
495 // Without the fix in place, this will fail already in ODF validation:
496 // "content.xml[2,2150]: Error: tag name "style:style" is not allowed. Possible tag names are: <font-face>"
498 CPPUNIT_ASSERT_EQUAL(1, getPages());
500 xmlDocUniquePtr pXmlDoc = parseExport("content.xml");
502 assertXPath(pXmlDoc, "/office:document-content/office:font-face-decls/style:style", 0);
503 assertXPath(pXmlDoc, "/office:document-content/office:automatic-styles/style:style[@style:family='table']", 1);
504 assertXPath(pXmlDoc, "/office:document-content/office:automatic-styles/style:style[@style:family='table-column']", 2);
505 assertXPath(pXmlDoc, "/office:document-content/office:automatic-styles/style:style[@style:family='paragraph']", 1);
508 CPPUNIT_TEST_FIXTURE(Test, tdf135942)
510 loadAndReload("nestedTableInFooter.odt");
511 // All table autostyles should be collected, including nested, and must not crash.
513 CPPUNIT_ASSERT_EQUAL(1, getPages());
515 xmlDocUniquePtr pXmlDoc = parseExport("styles.xml");
517 assertXPath(pXmlDoc, "/office:document-styles/office:automatic-styles/style:style[@style:family='table']", 2);
520 CPPUNIT_TEST_FIXTURE(Test, tdf150927)
522 // Similar to tdf135942
524 loadAndReload("table-in-frame-in-table-in-header-base.odt");
525 // All table autostyles should be collected, including nested, and must not crash.
527 CPPUNIT_ASSERT_EQUAL(1, getPages());
529 xmlDocUniquePtr pXmlDoc = parseExport("styles.xml");
531 assertXPath(pXmlDoc, "/office:document-styles/office:automatic-styles/style:style[@style:family='table']", 2);
534 CPPUNIT_TEST_FIXTURE(Test, tdf151100)
536 // Similar to tdf135942
538 loadAndReload("tdf151100.docx");
539 // All table autostyles should be collected, including nested, and must not crash.
541 CPPUNIT_ASSERT_EQUAL(1, getPages());
543 xmlDocUniquePtr pXmlDoc = parseExport("styles.xml");
545 assertXPath(pXmlDoc, "/office:document-styles/office:automatic-styles/style:style[@style:family='table']", 1);
548 DECLARE_ODFEXPORT_TEST(testGutterLeft, "gutter-left.odt")
550 CPPUNIT_ASSERT_EQUAL(1, getPages());
551 uno::Reference<beans::XPropertySet> xPageStyle;
552 getStyles("PageStyles")->getByName("Standard") >>= xPageStyle;
553 sal_Int32 nGutterMargin{};
554 xPageStyle->getPropertyValue("GutterMargin") >>= nGutterMargin;
555 // Without the accompanying fix in place, this test would have failed with:
556 // - Expected: 1270
557 // - Actual : 0
558 // i.e. gutter margin was lost.
559 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1270), nGutterMargin);
562 DECLARE_ODFEXPORT_TEST(testTdf52065_centerTabs, "testTdf52065_centerTabs.odt")
564 CPPUNIT_ASSERT_EQUAL(1, getPages());
565 sal_Int32 nTabStop = parseDump("//body/txt[4]/SwParaPortion/SwLineLayout/child::*[3]", "width").toInt32();
566 // Without the fix, the text was unseen, with a tabstop width of 64057. It should be 3057
567 CPPUNIT_ASSERT(nTabStop < 4000);
568 CPPUNIT_ASSERT(3000 < nTabStop);
569 CPPUNIT_ASSERT_EQUAL(OUString(u"Pečiatka zamestnávateľa"), parseDump("//body/txt[4]/SwParaPortion/SwLineLayout/child::*[4]", "portion"));
571 // tdf#149547: __XXX___invalid CharacterStyles should not be imported/exported
572 CPPUNIT_ASSERT(!getStyles("CharacterStyles")->hasByName("__XXX___invalid"));
575 DECLARE_ODFEXPORT_TEST(testTdf104254_noHeaderWrapping, "tdf104254_noHeaderWrapping.odt")
577 CPPUNIT_ASSERT_EQUAL(1, getShapes());
578 CPPUNIT_ASSERT_EQUAL(1, getPages());
579 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
581 sal_Int32 nParaHeight = getXPath(pXmlDoc, "//header/txt[1]/infos/bounds", "height").toInt32();
582 // The wrapping on header images is supposed to be ignored (since OOo for MS compat reasons),
583 // thus making the text run underneath the image. Before, height was 1104. Now it is 552.
584 CPPUNIT_ASSERT_MESSAGE("Paragraph should fit on a single line", nParaHeight < 600);
587 DECLARE_ODFEXPORT_TEST(testTdf131025_noZerosInTable, "tdf131025_noZerosInTable.odt")
589 uno::Reference<text::XTextTablesSupplier> xSupplier(mxComponent, uno::UNO_QUERY);
590 uno::Reference<container::XNameAccess> xTables = xSupplier->getTextTables();
591 uno::Reference<text::XTextTable> xTable(xTables->getByName("Table1"), uno::UNO_QUERY);
593 uno::Reference<text::XTextRange> xCell(xTable->getCellByName("C3"), uno::UNO_QUERY);
594 CPPUNIT_ASSERT_EQUAL(OUString("5 gp"), xCell->getString());
597 DECLARE_ODFEXPORT_TEST(testTdf153090, "Custom-Style-TOC.docx")
599 uno::Reference<text::XDocumentIndexesSupplier> xIndexSupplier(mxComponent, uno::UNO_QUERY);
600 uno::Reference<container::XIndexAccess> xIndexes(xIndexSupplier->getDocumentIndexes());
601 uno::Reference<text::XDocumentIndex> xTOC(xIndexes->getByIndex(0), uno::UNO_QUERY);
602 CPPUNIT_ASSERT_EQUAL(OUString("_CustomImageCaption"), getProperty<OUString>(xTOC, "CreateFromParagraphStyle"));
603 // tdf#153659 this was imported as "table of figures" instead of "Figure Index 1"
604 // thus custom settings were not retained after ToF update
605 CPPUNIT_ASSERT_EQUAL(OUString("Figure Index 1"), getProperty<OUString>(getParagraph(1), "ParaStyleName"));
607 xTOC->update();
608 OUString const tocContent(xTOC->getAnchor()->getString());
609 CPPUNIT_ASSERT(tocContent.indexOf("1. Abb. Ein Haus") != -1);
610 CPPUNIT_ASSERT(tocContent.indexOf("2. Abb.Ein Schiff!") != -1);
611 CPPUNIT_ASSERT(tocContent.indexOf(u"1. ábra Small house with Hungarian description category") != -1);
614 DECLARE_ODFEXPORT_TEST(testTdf143793_noBodyWrapping, "tdf143793_noBodyWrapping.odt")
616 CPPUNIT_ASSERT_EQUAL(2, getShapes());
617 // Preserve old document wrapping. Compat "Use OOo 1.1 text wrapping around objects"
618 // Originally, the body text did not wrap around spill-over header images
619 CPPUNIT_ASSERT_EQUAL_MESSAGE( "Fits on one page", 1, getPages() );
621 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
623 sal_Int32 nParaHeight = getXPath(pXmlDoc, "//page[1]/header/txt[1]/infos/bounds", "height").toInt32();
624 // The header text should wrap around the header image in OOo 1.1 and prior,
625 // thus taking up two lines instead of one. One line is 276. It should be 552.
626 CPPUNIT_ASSERT_MESSAGE("Header text should fill two lines", nParaHeight > 400);
629 CPPUNIT_TEST_FIXTURE(Test, testTdf137199)
631 loadAndReload("tdf137199.docx");
632 CPPUNIT_ASSERT_EQUAL(OUString(">1<"), getProperty<OUString>(getParagraph(1), "ListLabelString"));
634 CPPUNIT_ASSERT_EQUAL(OUString("1)"), getProperty<OUString>(getParagraph(2), "ListLabelString"));
636 CPPUNIT_ASSERT_EQUAL(OUString("HELLO1WORLD!"), getProperty<OUString>(getParagraph(3), "ListLabelString"));
638 CPPUNIT_ASSERT_EQUAL(OUString("HELLO2WORLD!"), getProperty<OUString>(getParagraph(4), "ListLabelString"));
641 DECLARE_ODFEXPORT_TEST(testTdf143605, "tdf143605.odt")
643 CPPUNIT_ASSERT_EQUAL(1, getPages());
644 // With numbering type "none" there should be just prefix & suffix
645 CPPUNIT_ASSERT_EQUAL(OUString("."), getProperty<OUString>(getParagraph(1), "ListLabelString"));
648 CPPUNIT_TEST_FIXTURE(Test, testTdf57317_autoListName)
650 createSwDoc("tdf57317_autoListName.odt");
651 // The list style (from styles.xml) overrides a duplicate named auto-style
652 //uno::Any aNumStyle = getStyles("NumberingStyles")->getByName("L1");
653 //CPPUNIT_ASSERT(aNumStyle.hasValue());
654 uno::Reference<beans::XPropertySet> xPara(getParagraph(1), uno::UNO_QUERY);
655 CPPUNIT_ASSERT_EQUAL(OUString(">1<"), getProperty<OUString>(xPara, "ListLabelString"));
656 CPPUNIT_ASSERT_EQUAL(OUString("L1"), getProperty<OUString>(xPara, "NumberingStyleName"));
658 dispatchCommand(mxComponent, ".uno:SelectAll", {});
659 dispatchCommand(mxComponent, ".uno:DefaultBullet", {});
661 // This was failing with a duplicate auto numbering style name of L1 instead of a unique name,
662 // thus it was showing the same info as before the bullet modification.
663 saveAndReload("writer8");
664 xPara.set(getParagraph(1), uno::UNO_QUERY);
665 CPPUNIT_ASSERT_EQUAL(OUString(""), getProperty<OUString>(xPara, "ListLabelString"));
667 uno::Reference<container::XIndexAccess> xLevels(xPara->getPropertyValue("NumberingRules"),
668 uno::UNO_QUERY);
669 uno::Sequence<beans::PropertyValue> aProps;
670 xLevels->getByIndex(0) >>= aProps;
671 for (beans::PropertyValue const& rProp : std::as_const(aProps))
673 if (rProp.Name == "BulletChar")
674 return;
676 CPPUNIT_FAIL("no BulletChar property");
679 CPPUNIT_TEST_FIXTURE(Test, testListFormatDocx)
681 loadAndReload("listformat.docx");
682 // Ensure in resulting ODT we also have not just prefix/suffix, but custom delimiters
683 CPPUNIT_ASSERT_EQUAL(OUString(">1<"), getProperty<OUString>(getParagraph(1), "ListLabelString"));
684 CPPUNIT_ASSERT_EQUAL(OUString(">>1/1<<"), getProperty<OUString>(getParagraph(2), "ListLabelString"));
685 CPPUNIT_ASSERT_EQUAL(OUString(">>1/1/1<<"), getProperty<OUString>(getParagraph(3), "ListLabelString"));
686 CPPUNIT_ASSERT_EQUAL(OUString(">>1/1/2<<"), getProperty<OUString>(getParagraph(4), "ListLabelString"));
688 // Check also that in numbering styles we have num-list-format defined
689 xmlDocUniquePtr pXmlDoc = parseExport("styles.xml");
690 assertXPath(pXmlDoc, "/office:document-styles/office:styles/text:list-style[@style:name='WWNum1']/"
691 "text:list-level-style-number[@text:level='1']", "num-list-format", ">%1%<");
692 assertXPath(pXmlDoc, "/office:document-styles/office:styles/text:list-style[@style:name='WWNum1']/"
693 "text:list-level-style-number[@text:level='2']", "num-list-format", ">>%1%/%2%<<");
694 assertXPath(pXmlDoc, "/office:document-styles/office:styles/text:list-style[@style:name='WWNum1']/"
695 "text:list-level-style-number[@text:level='3']", "num-list-format", ">>%1%/%2%/%3%<<");
697 // But for compatibility there are still prefix/suffix
698 assertXPath(pXmlDoc, "/office:document-styles/office:styles/text:list-style[@style:name='WWNum1']/"
699 "text:list-level-style-number[@text:level='1']", "num-prefix", ">");
700 assertXPath(pXmlDoc, "/office:document-styles/office:styles/text:list-style[@style:name='WWNum1']/"
701 "text:list-level-style-number[@text:level='1']", "num-suffix", "<");
702 assertXPath(pXmlDoc, "/office:document-styles/office:styles/text:list-style[@style:name='WWNum1']/"
703 "text:list-level-style-number[@text:level='2']", "num-prefix", ">>");
704 assertXPath(pXmlDoc, "/office:document-styles/office:styles/text:list-style[@style:name='WWNum1']/"
705 "text:list-level-style-number[@text:level='2']", "num-suffix", "<<");
706 assertXPath(pXmlDoc, "/office:document-styles/office:styles/text:list-style[@style:name='WWNum1']/"
707 "text:list-level-style-number[@text:level='3']", "num-prefix", ">>");
708 assertXPath(pXmlDoc, "/office:document-styles/office:styles/text:list-style[@style:name='WWNum1']/"
709 "text:list-level-style-number[@text:level='3']", "num-suffix", "<<");
712 DECLARE_ODFEXPORT_TEST(testShapeWithHyperlink, "shape-with-hyperlink.odt")
714 CPPUNIT_ASSERT_EQUAL(1, getShapes());
715 CPPUNIT_ASSERT_EQUAL(1, getPages());
716 if (isExported())
718 xmlDocUniquePtr pXmlDoc = parseExport("content.xml");
719 // Check how conversion from prefix/suffix to list format did work
720 assertXPath(pXmlDoc, "/office:document-content/office:body/office:text/text:p/draw:a",
721 "href", "http://shape.com/");
725 DECLARE_ODFEXPORT_TEST(testShapesHyperlink, "shapes-hyperlink.odt")
727 CPPUNIT_ASSERT_EQUAL(1, getPages());
728 CPPUNIT_ASSERT_EQUAL(5, getShapes());
729 uno::Reference<beans::XPropertySet> const xPropSet1(getShape(1), uno::UNO_QUERY);
730 CPPUNIT_ASSERT_EQUAL(OUString("http://libreoffice.org/"), getProperty<OUString>(xPropSet1, "Hyperlink"));
732 uno::Reference<beans::XPropertySet> const xPropSet2(getShape(2), uno::UNO_QUERY);
733 CPPUNIT_ASSERT_EQUAL(OUString("http://libreoffice2.org/"), getProperty<OUString>(xPropSet2, "Hyperlink"));
735 uno::Reference<beans::XPropertySet> const xPropSet3(getShape(3), uno::UNO_QUERY);
736 CPPUNIT_ASSERT_EQUAL(OUString("http://libreoffice3.org/"), getProperty<OUString>(xPropSet3, "Hyperlink"));
738 uno::Reference<beans::XPropertySet> const xPropSet4(getShape(4), uno::UNO_QUERY);
739 CPPUNIT_ASSERT_EQUAL(OUString("http://libreoffice4.org/"), getProperty<OUString>(xPropSet4, "Hyperlink"));
741 uno::Reference<beans::XPropertySet> const xPropSet5(getShape(5), uno::UNO_QUERY);
742 CPPUNIT_ASSERT_EQUAL(OUString("http://libreoffice5.org/"), getProperty<OUString>(xPropSet5, "Hyperlink"));
745 DECLARE_ODFEXPORT_TEST(testListFormatOdt, "listformat.odt")
747 CPPUNIT_ASSERT_EQUAL(1, getPages());
748 // Ensure in resulting ODT we also have not just prefix/suffix, but custom delimiters
749 CPPUNIT_ASSERT_EQUAL(OUString(">1<"), getProperty<OUString>(getParagraph(1), "ListLabelString"));
750 CPPUNIT_ASSERT_EQUAL(OUString(">>1.1<<"), getProperty<OUString>(getParagraph(2), "ListLabelString"));
751 CPPUNIT_ASSERT_EQUAL(OUString(">>1.1.1<<"), getProperty<OUString>(getParagraph(3), "ListLabelString"));
752 CPPUNIT_ASSERT_EQUAL(OUString(">>1.1.2<<"), getProperty<OUString>(getParagraph(4), "ListLabelString"));
754 if (isExported())
756 xmlDocUniquePtr pXmlDoc = parseExport("content.xml");
757 // Check how conversion from prefix/suffix to list format did work
758 assertXPath(pXmlDoc, "/office:document-content/office:automatic-styles/text:list-style[@style:name='L1']/"
759 "text:list-level-style-number[@text:level='1']", "num-list-format", ">%1%<");
760 assertXPath(pXmlDoc, "/office:document-content/office:automatic-styles/text:list-style[@style:name='L1']/"
761 "text:list-level-style-number[@text:level='2']", "num-list-format", ">>%1%.%2%<<");
762 assertXPath(pXmlDoc, "/office:document-content/office:automatic-styles/text:list-style[@style:name='L1']/"
763 "text:list-level-style-number[@text:level='3']", "num-list-format", ">>%1%.%2%.%3%<<");
765 // But for compatibility there are still prefix/suffix as they were before
766 assertXPath(pXmlDoc, "/office:document-content/office:automatic-styles/text:list-style[@style:name='L1']/"
767 "text:list-level-style-number[@text:level='1']", "num-prefix", ">");
768 assertXPath(pXmlDoc, "/office:document-content/office:automatic-styles/text:list-style[@style:name='L1']/"
769 "text:list-level-style-number[@text:level='1']", "num-suffix", "<");
770 assertXPath(pXmlDoc, "/office:document-content/office:automatic-styles/text:list-style[@style:name='L1']/"
771 "text:list-level-style-number[@text:level='2']", "num-prefix", ">>");
772 assertXPath(pXmlDoc, "/office:document-content/office:automatic-styles/text:list-style[@style:name='L1']/"
773 "text:list-level-style-number[@text:level='2']", "num-suffix", "<<");
774 assertXPath(pXmlDoc, "/office:document-content/office:automatic-styles/text:list-style[@style:name='L1']/"
775 "text:list-level-style-number[@text:level='3']", "num-prefix", ">>");
776 assertXPath(pXmlDoc, "/office:document-content/office:automatic-styles/text:list-style[@style:name='L1']/"
777 "text:list-level-style-number[@text:level='3']", "num-suffix", "<<");
781 CPPUNIT_TEST_FIXTURE(Test, testStyleLink)
783 // Given a document with a para and a char style that links each other, when loading that
784 // document:
785 createSwDoc("style-link.fodt");
787 // Then make sure the char style links the para one:
788 uno::Any aCharStyle = getStyles("CharacterStyles")->getByName("List Paragraph Char");
789 // Without the accompanying fix in place, this test would have failed with:
790 // - Expected: List Paragraph
791 // - Actual :
792 // i.e. the linked style was lost on import.
793 CPPUNIT_ASSERT_EQUAL(OUString("List Paragraph"), getProperty<OUString>(aCharStyle, "LinkStyle"));
794 uno::Any aParaStyle = getStyles("ParagraphStyles")->getByName("List Paragraph");
795 // Without the accompanying fix in place, this test would have failed with:
796 // - Expected: List Paragraph Char
797 // - Actual :
798 // i.e. the linked style was lost on import.
799 CPPUNIT_ASSERT_EQUAL(OUString("List Paragraph Char"), getProperty<OUString>(aParaStyle, "LinkStyle"));
802 CPPUNIT_TEST_FIXTURE(Test, tdf120972)
804 loadAndReload("table_number_format_3.docx");
806 xmlDocUniquePtr pXmlDoc = parseExport("content.xml");
807 OUString cDecimal(SvtSysLocale().GetLocaleData().getNumDecimalSep()[0]);
808 assertXPath(
809 pXmlDoc,
810 "//style:style[@style:name='P1']/style:paragraph-properties/style:tab-stops/style:tab-stop",
811 "char", cDecimal);
812 assertXPath(
813 pXmlDoc,
814 "//style:style[@style:name='P2']/style:paragraph-properties/style:tab-stops/style:tab-stop",
815 "char", cDecimal);
818 DECLARE_ODFEXPORT_TEST(testTdf114287, "tdf114287.odt")
820 uno::Reference<container::XIndexAccess> const xLevels1(
821 getProperty<uno::Reference<container::XIndexAccess>>(getParagraph(2), "NumberingRules"));
822 uno::Reference<container::XNamed> const xNum1(xLevels1, uno::UNO_QUERY);
823 ::comphelper::SequenceAsHashMap props1(xLevels1->getByIndex(0));
824 CPPUNIT_ASSERT_EQUAL(sal_Int32(-700), props1["FirstLineIndent"].get<sal_Int32>());
825 CPPUNIT_ASSERT_EQUAL(sal_Int32(1330), props1["IndentAt"].get<sal_Int32>());
827 // 1: automatic style applies list-style-name and margin-left
828 CPPUNIT_ASSERT_EQUAL(sal_Int32(-1000), getProperty<sal_Int32>(getParagraph(2), "ParaFirstLineIndent"));
829 CPPUNIT_ASSERT_EQUAL(sal_Int32(5001), getProperty<sal_Int32>(getParagraph(2), "ParaLeftMargin"));
830 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(getParagraph(2), "ParaRightMargin"));
832 // list is continued
833 uno::Reference<container::XNamed> const xNum2(
834 getProperty<uno::Reference<container::XNamed>>(getParagraph(9), "NumberingRules"));
835 CPPUNIT_ASSERT_EQUAL(xNum1->getName(), xNum2->getName());
837 // 2: style applies list-style-name and margin-left, list applies list-style-name
838 CPPUNIT_ASSERT_EQUAL(sal_Int32(-1000), getProperty<sal_Int32>(getParagraph(9), "ParaFirstLineIndent"));
839 CPPUNIT_ASSERT_EQUAL(sal_Int32(5001), getProperty<sal_Int32>(getParagraph(9), "ParaLeftMargin"));
840 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(getParagraph(9), "ParaRightMargin"));
842 // list is continued
843 uno::Reference<container::XNamed> const xNum3(
844 getProperty<uno::Reference<container::XNamed>>(getParagraph(16), "NumberingRules"));
845 CPPUNIT_ASSERT_EQUAL(xNum1->getName(), xNum3->getName());
847 // 3: style applies margin-left, automatic style applies list-style-name
848 CPPUNIT_ASSERT_EQUAL(sal_Int32(-1000), getProperty<sal_Int32>(getParagraph(16), "ParaFirstLineIndent"));
849 CPPUNIT_ASSERT_EQUAL(sal_Int32(5001), getProperty<sal_Int32>(getParagraph(16), "ParaLeftMargin"));
850 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(getParagraph(16), "ParaRightMargin"));
852 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
853 assertXPath(pXmlDoc, "/root/page[1]/body/txt[2]/infos/prtBounds", "left", "2268");
854 assertXPath(pXmlDoc, "/root/page[1]/body/txt[2]/infos/prtBounds", "right", "11339");
855 // the problem was that the list style name of the list must override the
856 // paragraph style even though it's the same list style
857 assertXPath(pXmlDoc, "/root/page[1]/body/txt[9]/infos/prtBounds", "left", "357");
858 assertXPath(pXmlDoc, "/root/page[1]/body/txt[9]/infos/prtBounds", "right", "11339");
859 assertXPath(pXmlDoc, "/root/page[1]/body/txt[16]/infos/prtBounds", "left", "357");
860 assertXPath(pXmlDoc, "/root/page[1]/body/txt[16]/infos/prtBounds", "right", "11339");
863 DECLARE_ODFEXPORT_TEST(testSectionColumnSeparator, "section-columns-separator.fodt")
865 // tdf#150235: due to wrong types used in column export, 'style:height' and 'style:style'
866 // attributes were exported incorrectly for 'style:column-sep' element
867 auto xSection = getProperty<uno::Reference<uno::XInterface>>(getParagraph(1), "TextSection");
868 auto xColumns = getProperty<uno::Reference<text::XTextColumns>>(xSection, "TextColumns");
869 CPPUNIT_ASSERT(xColumns);
870 CPPUNIT_ASSERT_EQUAL(sal_Int16(2), xColumns->getColumnCount());
872 // Without the accompanying fix in place, this test would have failed with:
873 // - Expected: 50
874 // - Actual : 100
875 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(50),
876 getProperty<sal_Int32>(xColumns, "SeparatorLineRelativeHeight"));
877 // Without the accompanying fix in place, this test would have failed with:
878 // - Expected: 2
879 // - Actual : 0
880 CPPUNIT_ASSERT_EQUAL(css::text::ColumnSeparatorStyle::DOTTED,
881 getProperty<sal_Int16>(xColumns, "SeparatorLineStyle"));
883 // Check the rest of the properties, too
884 CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(xColumns, "IsAutomatic"));
885 CPPUNIT_ASSERT_EQUAL(sal_Int32(600), getProperty<sal_Int32>(xColumns, "AutomaticDistance"));
886 CPPUNIT_ASSERT_EQUAL(sal_Int32(9), getProperty<sal_Int32>(xColumns, "SeparatorLineWidth"));
887 CPPUNIT_ASSERT_EQUAL(Color(0x99, 0xAA, 0xBB),
888 getProperty<Color>(xColumns, "SeparatorLineColor"));
889 CPPUNIT_ASSERT_EQUAL(
890 css::style::VerticalAlignment_BOTTOM,
891 getProperty<css::style::VerticalAlignment>(xColumns, "SeparatorLineVerticalAlignment"));
892 CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(xColumns, "SeparatorLineIsOn"));
895 DECLARE_ODFEXPORT_TEST(testTdf78510, "WordTest_edit.odt")
897 uno::Reference<container::XIndexAccess> const xLevels1(
898 getProperty<uno::Reference<container::XIndexAccess>>(getParagraph(1), "NumberingRules"));
899 ::comphelper::SequenceAsHashMap props1(xLevels1->getByIndex(0));
900 CPPUNIT_ASSERT_EQUAL(sal_Int32(-1000), props1["FirstLineIndent"].get<sal_Int32>());
901 CPPUNIT_ASSERT_EQUAL(sal_Int32(2000), props1["IndentAt"].get<sal_Int32>());
903 // 1: inherited from paragraph style and overridden by list
904 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(getParagraph(1), "ParaFirstLineIndent"));
905 CPPUNIT_ASSERT_EQUAL(sal_Int32(1270), getProperty<sal_Int32>(getParagraph(1), "ParaLeftMargin"));
906 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(getParagraph(1), "ParaRightMargin"));
907 // 2: as 1 + paragraph sets firstline
908 CPPUNIT_ASSERT_EQUAL(sal_Int32(1000), getProperty<sal_Int32>(getParagraph(2), "ParaFirstLineIndent"));
909 CPPUNIT_ASSERT_EQUAL(sal_Int32(1270), getProperty<sal_Int32>(getParagraph(2), "ParaLeftMargin"));
910 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(getParagraph(2), "ParaRightMargin"));
911 // 3: as 1 + paragraph sets textleft
912 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(getParagraph(3), "ParaFirstLineIndent"));
913 CPPUNIT_ASSERT_EQUAL(sal_Int32(3000), getProperty<sal_Int32>(getParagraph(3), "ParaLeftMargin"));
914 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(getParagraph(3), "ParaRightMargin"));
915 // 4: as 1 + paragraph sets firstline, textleft
916 CPPUNIT_ASSERT_EQUAL(sal_Int32(-2000), getProperty<sal_Int32>(getParagraph(4), "ParaFirstLineIndent"));
917 CPPUNIT_ASSERT_EQUAL(sal_Int32(3000), getProperty<sal_Int32>(getParagraph(4), "ParaLeftMargin"));
918 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(getParagraph(4), "ParaRightMargin"));
919 // 5: as 1 + paragraph sets firstline
920 CPPUNIT_ASSERT_EQUAL(sal_Int32(-2000), getProperty<sal_Int32>(getParagraph(5), "ParaFirstLineIndent"));
921 CPPUNIT_ASSERT_EQUAL(sal_Int32(1270), getProperty<sal_Int32>(getParagraph(5), "ParaLeftMargin"));
922 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(getParagraph(5), "ParaRightMargin"));
923 // 6: as 1
924 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(getParagraph(6), "ParaFirstLineIndent"));
925 CPPUNIT_ASSERT_EQUAL(sal_Int32(1270), getProperty<sal_Int32>(getParagraph(6), "ParaLeftMargin"));
926 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(getParagraph(6), "ParaRightMargin"));
928 uno::Reference<container::XIndexAccess> const xLevels8(
929 getProperty<uno::Reference<container::XIndexAccess>>(getParagraph(8), "NumberingRules"));
930 ::comphelper::SequenceAsHashMap props8(xLevels8->getByIndex(0));
931 CPPUNIT_ASSERT_EQUAL(sal_Int32(1000), props8["FirstLineIndent"].get<sal_Int32>());
932 CPPUNIT_ASSERT_EQUAL(sal_Int32(1000), props8["IndentAt"].get<sal_Int32>());
934 // 8: inherited from paragraph style and overridden by list
935 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(getParagraph(8), "ParaFirstLineIndent"));
936 CPPUNIT_ASSERT_EQUAL(sal_Int32(1270), getProperty<sal_Int32>(getParagraph(8), "ParaLeftMargin"));
937 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(getParagraph(8), "ParaRightMargin"));
938 // 9: as 8 + paragraph sets firstline
939 CPPUNIT_ASSERT_EQUAL(sal_Int32(2000), getProperty<sal_Int32>(getParagraph(9), "ParaFirstLineIndent"));
940 CPPUNIT_ASSERT_EQUAL(sal_Int32(1270), getProperty<sal_Int32>(getParagraph(9), "ParaLeftMargin"));
941 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(getParagraph(9), "ParaRightMargin"));
942 // 10: as 8 + paragraph sets textleft
943 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(getParagraph(10), "ParaFirstLineIndent"));
944 CPPUNIT_ASSERT_EQUAL(sal_Int32(3000), getProperty<sal_Int32>(getParagraph(10), "ParaLeftMargin"));
945 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(getParagraph(10), "ParaRightMargin"));
946 // 11: as 8 + paragraph sets firstline, textleft
947 CPPUNIT_ASSERT_EQUAL(sal_Int32(-2000), getProperty<sal_Int32>(getParagraph(11), "ParaFirstLineIndent"));
948 CPPUNIT_ASSERT_EQUAL(sal_Int32(3000), getProperty<sal_Int32>(getParagraph(11), "ParaLeftMargin"));
949 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(getParagraph(11), "ParaRightMargin"));
950 // 12: as 8 + paragraph sets firstline
951 CPPUNIT_ASSERT_EQUAL(sal_Int32(-2000), getProperty<sal_Int32>(getParagraph(12), "ParaFirstLineIndent"));
952 CPPUNIT_ASSERT_EQUAL(sal_Int32(1270), getProperty<sal_Int32>(getParagraph(12), "ParaLeftMargin"));
953 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(getParagraph(12), "ParaRightMargin"));
954 // 13: as 8
955 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(getParagraph(13), "ParaFirstLineIndent"));
956 CPPUNIT_ASSERT_EQUAL(sal_Int32(1270), getProperty<sal_Int32>(getParagraph(13), "ParaLeftMargin"));
957 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(getParagraph(13), "ParaRightMargin"));
959 // unfortunately it appears that the portions don't have a position
960 // so it's not possible to check the first-line-offset that's applied
961 // (the first-line-indent is computed on the fly in SwTextMargin when
962 // painting)
964 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
965 assertXPath(pXmlDoc, "/root/page[1]/body/txt[1]/infos/prtBounds", "left", "567");
966 assertXPath(pXmlDoc, "/root/page[1]/body/txt[1]/infos/prtBounds", "right", "9359");
967 assertXPath(pXmlDoc, "/root/page[1]/body/txt[2]/infos/prtBounds", "left", "1134");
968 assertXPath(pXmlDoc, "/root/page[1]/body/txt[2]/infos/prtBounds", "right", "9359");
969 assertXPath(pXmlDoc, "/root/page[1]/body/txt[3]/infos/prtBounds", "left", "1134");
970 assertXPath(pXmlDoc, "/root/page[1]/body/txt[3]/infos/prtBounds", "right", "9359");
971 assertXPath(pXmlDoc, "/root/page[1]/body/txt[4]/infos/prtBounds", "left", "567");
972 assertXPath(pXmlDoc, "/root/page[1]/body/txt[4]/infos/prtBounds", "right", "9359");
973 assertXPath(pXmlDoc, "/root/page[1]/body/txt[5]/infos/prtBounds", "left", "0");
974 assertXPath(pXmlDoc, "/root/page[1]/body/txt[5]/infos/prtBounds", "right", "9359");
975 assertXPath(pXmlDoc, "/root/page[1]/body/txt[6]/infos/prtBounds", "left", "567");
976 assertXPath(pXmlDoc, "/root/page[1]/body/txt[6]/infos/prtBounds", "right", "9359");
978 assertXPath(pXmlDoc, "/root/page[1]/body/txt[8]/infos/prtBounds", "left", "567");
979 assertXPath(pXmlDoc, "/root/page[1]/body/txt[8]/infos/prtBounds", "right", "9359");
980 assertXPath(pXmlDoc, "/root/page[1]/body/txt[9]/infos/prtBounds", "left", "567");
981 assertXPath(pXmlDoc, "/root/page[1]/body/txt[9]/infos/prtBounds", "right", "9359");
982 assertXPath(pXmlDoc, "/root/page[1]/body/txt[10]/infos/prtBounds", "left", "1701");
983 assertXPath(pXmlDoc, "/root/page[1]/body/txt[10]/infos/prtBounds", "right", "9359");
984 assertXPath(pXmlDoc, "/root/page[1]/body/txt[11]/infos/prtBounds", "left", "567");
985 assertXPath(pXmlDoc, "/root/page[1]/body/txt[11]/infos/prtBounds", "right", "9359");
986 assertXPath(pXmlDoc, "/root/page[1]/body/txt[12]/infos/prtBounds", "left", "-567");
987 assertXPath(pXmlDoc, "/root/page[1]/body/txt[12]/infos/prtBounds", "right", "9359");
988 assertXPath(pXmlDoc, "/root/page[1]/body/txt[13]/infos/prtBounds", "left", "567");
989 assertXPath(pXmlDoc, "/root/page[1]/body/txt[13]/infos/prtBounds", "right", "9359");
992 // now check the positions where text is actually painted -
993 // wonder how fragile this is...
994 // FIXME some platform difference, 1st one is 2306 on Linux, 3087 on WNT ?
995 // some Mac has 3110
996 #if !defined(WNT) && !defined(MACOSX)
998 SwDocShell *const pShell(dynamic_cast<SwXTextDocument&>(*mxComponent).GetDocShell());
999 std::shared_ptr<GDIMetaFile> pMetaFile = pShell->GetPreviewMetaFile();
1000 MetafileXmlDump aDumper;
1001 xmlDocUniquePtr pXmlDoc = dumpAndParse(aDumper, *pMetaFile);
1003 // 1: inherited from paragraph style and overridden by list
1004 // bullet char is extra
1006 assertXPath(pXmlDoc, "//textarray[1]", "x", "2306");
1007 // text is after a tab from list - haven't checked if that is correct?
1008 assertXPath(pXmlDoc, "//textarray[2]", "x", "2873");
1009 // second line
1010 assertXPath(pXmlDoc, "//textarray[3]", "x", "2873");
1011 // 2: as 1 + paragraph sets firstline
1012 assertXPath(pXmlDoc, "//textarray[4]", "x", "3440");
1013 assertXPath(pXmlDoc, "//textarray[5]", "x", "3593");
1014 assertXPath(pXmlDoc, "//textarray[6]", "x", "2873");
1015 // 3: as 1 + paragraph sets textleft
1016 assertXPath(pXmlDoc, "//textarray[7]", "x", "2873");
1017 assertXPath(pXmlDoc, "//textarray[8]", "x", "3440");
1018 assertXPath(pXmlDoc, "//textarray[9]", "x", "3440");
1019 // 4: as 1 + paragraph sets firstline, textleft
1020 assertXPath(pXmlDoc, "//textarray[10]", "x", "2306");
1021 assertXPath(pXmlDoc, "//textarray[11]", "x", "3440");
1022 assertXPath(pXmlDoc, "//textarray[12]", "x", "3440");
1023 // 5: as 1 + paragraph sets firstline
1024 assertXPath(pXmlDoc, "//textarray[13]", "x", "1739");
1025 assertXPath(pXmlDoc, "//textarray[14]", "x", "2873");
1026 assertXPath(pXmlDoc, "//textarray[15]", "x", "2873");
1027 // 6: as 1
1028 assertXPath(pXmlDoc, "//textarray[16]", "x", "2306");
1029 assertXPath(pXmlDoc, "//textarray[17]", "x", "2873");
1031 // 8: inherited from paragraph style and overridden by list
1032 assertXPath(pXmlDoc, "//textarray[18]", "x", "2873");
1033 assertXPath(pXmlDoc, "//textarray[19]", "x", "3746");
1034 assertXPath(pXmlDoc, "//textarray[20]", "x", "2306");
1035 // 9: as 8 + paragraph sets firstline
1036 assertXPath(pXmlDoc, "//textarray[21]", "x", "3440");
1037 assertXPath(pXmlDoc, "//textarray[22]", "x", "3746");
1038 assertXPath(pXmlDoc, "//textarray[23]", "x", "2306");
1039 // 10: as 8 + paragraph sets textleft
1040 assertXPath(pXmlDoc, "//textarray[24]", "x", "4007");
1041 assertXPath(pXmlDoc, "//textarray[25]", "x", "4880");
1042 assertXPath(pXmlDoc, "//textarray[26]", "x", "3440");
1043 // 11: as 8 + paragraph sets firstline, textleft
1044 assertXPath(pXmlDoc, "//textarray[27]", "x", "2306");
1045 assertXPath(pXmlDoc, "//textarray[28]", "x", "3440");
1046 assertXPath(pXmlDoc, "//textarray[29]", "x", "3440");
1047 // 12: as 8 + paragraph sets firstline
1048 assertXPath(pXmlDoc, "//textarray[30]", "x", "1172");
1049 assertXPath(pXmlDoc, "//textarray[31]", "x", "1739");
1050 assertXPath(pXmlDoc, "//textarray[32]", "x", "2306");
1051 // 13: as 8
1052 assertXPath(pXmlDoc, "//textarray[33]", "x", "2873");
1053 assertXPath(pXmlDoc, "//textarray[34]", "x", "3746");
1055 #endif
1058 CPPUNIT_TEST_FIXTURE(Test, testParagraphMarkerMarkupRoundtrip)
1060 loadAndReload("ParagraphMarkerMarkup.fodt");
1061 // Test that the markup stays at save-and-reload
1062 xmlDocUniquePtr pXmlDoc = parseExport("content.xml");
1063 assertXPath(pXmlDoc, "/office:document-content/office:body/office:text/text:p", "marker-style-name", "T2");
1064 assertXPath(pXmlDoc, "/office:document-content/office:automatic-styles/style:style[@style:name='T2']/style:text-properties", "font-size", "9pt");
1065 assertXPath(pXmlDoc, "/office:document-content/office:automatic-styles/style:style[@style:name='T2']/style:text-properties", "color", "#ff0000");
1068 CPPUNIT_PLUGIN_IMPLEMENT();
1070 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */