[Libreoffice-commits] core.git: sw/qa

jmzambon jeanmarczambon at gmail.com
Tue Aug 29 08:51:37 UTC 2017


 sw/qa/complex/writer/TextPortionEnumerationTest.java |  788 -------------------
 sw/qa/python/text_portion_enumeration_test.py        |  774 ++++++++++++++++++
 2 files changed, 774 insertions(+), 788 deletions(-)

New commits:
commit 5a6ac13b7ccd121ede008238ee16a8c688910144
Author: jmzambon <jeanmarczambon at gmail.com>
Date:   Sat Aug 26 17:33:17 2017 +0200

    tdf#97362: TextPortionEnumerationTest partially migrated to python (part 7)
    
    Convert tests:
    - test_range2
    - test_range3
    - test_range4
    - test_range5
    - test_range6
    - test_range7
    - test_meta_xchild
    - test_meta_xtext
    - test_meta_xtextcursor
    - test_xtextcursor
    
    Change-Id: Iabfa51869611ee027565102f6658b045a182d66e
    Reviewed-on: https://gerrit.libreoffice.org/41589
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>

diff --git a/sw/qa/complex/writer/TextPortionEnumerationTest.java b/sw/qa/complex/writer/TextPortionEnumerationTest.java
index 0866ec897d51..255d39d619aa 100644
--- a/sw/qa/complex/writer/TextPortionEnumerationTest.java
+++ b/sw/qa/complex/writer/TextPortionEnumerationTest.java
@@ -1258,794 +1258,6 @@ public class TextPortionEnumerationTest
         util.DesktopTools.closeDoc(m_xDoc);
     }
 
-    @Test public void testRange2() throws Exception
-    {
-        RangeInserter inserter = new RangeInserter(m_xDoc);
-        TreeNode text = new TextNode("123456789");
-        inserter.insertRange( new Range(0, 0, text) );
-        TreeNode met1 = new MetaNode( mkId("id") );
-        inserter.insertRange( new Range(1, 8, met1) );
-        TreeNode met2 = new MetaNode( mkId("id") );
-        inserter.insertRange( new Range(3/*-1*/, 8/*-1*/, met2) );
-        TreeNode met3 = new MetaNode( mkId("id") );
-        inserter.insertRange( new Range(5/*-2*/, 8/*-2*/, met3) );
-        TreeNode root = new TreeNode()
-            .appendChild( new TextNode("1") )
-            .appendChild( met1.dup()
-                .appendChild( new TextNode("2") )
-                .appendChild( met2.dup()
-                    .appendChild( new TextNode("3") )
-                    .appendChild( met3.dup()
-                        .appendChild( new TextNode("456") ) )
-                    .appendChild( new TextNode("7") ) )
-                .appendChild( new TextNode("8") ) )
-            .appendChild( new TextNode("9") );
-        doTest(root, false);
-        // split ruby at every meta start!
-        TreeNode rby4 = new RubyNode( mkName("ruby") );
-        inserter.insertRange( new Range(0, 7/*-3*/, rby4) );
-        root = new TreeNode()
-            .appendChild( rby4.dup()
-                .appendChild( new TextNode("1") ) )
-            .appendChild( met1.dup()
-                .appendChild( rby4.dup()
-                    .appendChild( new TextNode("2") ) )
-                .appendChild( met2.dup()
-                    .appendChild( rby4.dup()
-                        .appendChild( new TextNode("3") ) )
-                    .appendChild( met3.dup()
-                        .appendChild( rby4.dup()
-                            .appendChild( new TextNode("4") ) )
-                        .appendChild( new TextNode("56") ) )
-                    .appendChild( new TextNode("7") ) )
-                .appendChild( new TextNode("8") ) )
-            .appendChild( new TextNode("9") );
-        doTest(root, false);
-        // split ruby at every meta end!
-        TreeNode rby5 = new RubyNode( mkName("ruby") );
-        inserter.insertRange( new Range(8/*-3*/, 12/*-3*/, rby5) );
-        root = new TreeNode()
-            .appendChild( rby4.dup()
-                .appendChild( new TextNode("1") ) )
-            .appendChild( met1.dup()
-                .appendChild( rby4.dup()
-                    .appendChild( new TextNode("2") ) )
-                .appendChild( met2.dup()
-                    .appendChild( rby4.dup()
-                        .appendChild( new TextNode("3") ) )
-                    .appendChild( met3.dup()
-                        .appendChild( rby4.dup()
-                            .appendChild( new TextNode("4") ) )
-                        .appendChild( new TextNode("5") )
-                        .appendChild( rby5.dup()
-                            .appendChild( new TextNode("6") ) ) )
-                    .appendChild( rby5.dup()
-                        .appendChild( new TextNode("7") ) ) )
-                .appendChild( rby5.dup()
-                    .appendChild( new TextNode("8") ) ) )
-            .appendChild( rby5.dup()
-                .appendChild( new TextNode("9") ) );
-        doTest(root, false);
-    }
-
-    @Test public void testRange3() throws Exception
-    {
-        RangeInserter inserter = new RangeInserter(m_xDoc);
-        TreeNode text = new TextNode("123456789");
-        inserter.insertRange( new Range(0, 0, text) );
-        TreeNode rby1 = new RubyNode( mkName("ruby") );
-        inserter.insertRange( new Range(0, 9, rby1) );
-        TreeNode met2 = new MetaNode( mkId("id") );
-        inserter.insertRange( new Range(2, 7, met2) );
-        TreeNode root = new TreeNode()
-            .appendChild( rby1.dup()
-                .appendChild( new TextNode("12") )
-                .appendChild( met2.dup()
-                    .appendChild( new TextNode("34567") ) )
-                .appendChild( new TextNode("89") ) );
-        doTest(root, false);
-        // overwrite outer ruby, split remains at inner meta!
-        TreeNode rby3 = new RubyNode( mkName("ruby") );
-        inserter.insertRange( new Range(5/*-1*/, 6/*-1*/, rby3) );
-        root = new TreeNode()
-            .appendChild( rby1.dup()
-                .appendChild( new TextNode("12") ) )
-            .appendChild( met2.dup()
-                .appendChild( rby1.dup()
-                    .appendChild( new TextNode("34") ) )
-                .appendChild( rby3.dup()
-                    .appendChild( new TextNode("5") ) )
-                .appendChild( rby1.dup()
-                    .appendChild( new TextNode("67") ) ) )
-            .appendChild( rby1.dup()
-                .appendChild( new TextNode("89") ) );
-        doTest(root, false);
-    }
-
-    @Test public void testRange4() throws Exception
-    {
-        RangeInserter inserter = new RangeInserter(m_xDoc);
-        TreeNode text = new TextNode("123456789");
-        inserter.insertRange( new Range(0, 0, text) );
-        TreeNode rby1 = new RubyNode( mkName("ruby") );
-        inserter.insertRange( new Range(0, 9, rby1) );
-        TreeNode met2 = new MetaNode( mkId("id") );
-        inserter.insertRange( new Range(1, 8, met2) );
-        TreeNode met3 = new MetaNode( mkId("id") );
-        inserter.insertRange( new Range(3/*-1*/, 8/*-1*/, met3) );
-        TreeNode met4 = new MetaNode( mkId("id") );
-        inserter.insertRange( new Range(5/*-2*/, 8/*-2*/, met4) );
-        TreeNode root = new TreeNode()
-            .appendChild( rby1.dup()
-                .appendChild( new TextNode("1") )
-                .appendChild( met2.dup()
-                    .appendChild( new TextNode("2") )
-                    .appendChild( met3.dup()
-                        .appendChild( new TextNode("3") )
-                        .appendChild( met4.dup()
-                            .appendChild( new TextNode("456") ) )
-                        .appendChild( new TextNode("7") ) )
-                    .appendChild( new TextNode("8") ) )
-                .appendChild( new TextNode("9") ) );
-        doTest(root, false);
-        // overwrite outer ruby, split remains at every inner meta!
-        TreeNode rby5 = new RubyNode( mkName("ruby") );
-        inserter.insertRange( new Range(7/*-3*/, 8/*-3*/, rby5) );
-        root = new TreeNode()
-            .appendChild( rby1.dup()
-                .appendChild( new TextNode("1") ) )
-            .appendChild( met2.dup()
-                .appendChild( rby1.dup()
-                    .appendChild( new TextNode("2") ) )
-                .appendChild( met3.dup()
-                    .appendChild( rby1.dup()
-                        .appendChild( new TextNode("3") ) )
-                    .appendChild( met4.dup()
-                        .appendChild( rby1.dup()
-                            .appendChild( new TextNode("4") ) )
-                        .appendChild( rby5.dup()
-                            .appendChild( new TextNode("5") ) )
-                        .appendChild( rby1.dup()
-                            .appendChild( new TextNode("6") ) ) )
-                    .appendChild( rby1.dup()
-                        .appendChild( new TextNode("7") ) ) )
-                .appendChild( rby1.dup()
-                    .appendChild( new TextNode("8") ) ) )
-            .appendChild( rby1.dup()
-                .appendChild( new TextNode("9") ) );
-        doTest(root, false);
-    }
-
-    @Test public void testRange5() throws Exception
-    {
-        RangeInserter inserter = new RangeInserter(m_xDoc);
-        TreeNode text = new TextNode("123456789");
-        inserter.insertRange( new Range(0, 0, text) );
-        TreeNode rby1 = new RubyNode( mkName("ruby") );
-        inserter.insertRange( new Range(0, 9, rby1) );
-        TreeNode met2 = new MetaNode( mkId("id") );
-        inserter.insertRange( new Range(1, 3, met2) );
-        TreeNode met3 = new MetaNode( mkId("id") );
-        inserter.insertRange( new Range(5/*-1*/, 6/*-1*/, met3) );
-        TreeNode met4 = new MetaNode( mkId("id") );
-        inserter.insertRange( new Range(8/*-2*/, 10/*-2*/, met4) );
-        TreeNode root = new TreeNode()
-            .appendChild( rby1.dup()
-                .appendChild( new TextNode("1") )
-                .appendChild( met2.dup().appendChild( new TextNode("23") ) )
-                .appendChild( new TextNode("4") )
-                .appendChild( met3.dup().appendChild( new TextNode("5") ) )
-                .appendChild( new TextNode("6") )
-                .appendChild( met4.dup().appendChild( new TextNode("78") ) )
-                .appendChild( new TextNode("9") ) );
-        doTest(root, false);
-        // overwrite outer ruby, but split at inner metas!
-        TreeNode rby5 = new RubyNode( mkName("ruby") );
-        inserter.insertRange( new Range(3/*-1*/, 10/*-3*/, rby5) );
-        root = new TreeNode()
-            .appendChild( rby1.dup()
-                .appendChild( new TextNode("1") ) )
-            .appendChild( met2.dup()
-                .appendChild( rby1.dup()
-                    .appendChild( new TextNode("2") ) )
-                .appendChild( rby5.dup()
-                    .appendChild( new TextNode("3") ) ) )
-            .appendChild( rby5.dup()
-                .appendChild( new TextNode("4") )
-                .appendChild( met3.dup()
-                    .appendChild( new TextNode("5") ) )
-                .appendChild( new TextNode("6") ) )
-            .appendChild( met4.dup()
-                .appendChild( rby5.dup()
-                    .appendChild( new TextNode("7") ) )
-                .appendChild( rby1.dup()
-                    .appendChild( new TextNode("8") ) ) )
-            .appendChild( rby1.dup()
-                .appendChild( new TextNode("9") ) );
-        doTest(root, false);
-    }
-
-    @Test public void testRange6() throws Exception
-    {
-        RangeInserter inserter = new RangeInserter(m_xDoc);
-        TreeNode text = new TextNode("123456789");
-        inserter.insertRange( new Range(0, 0, text) );
-        TreeNode met1 = new MetaNode( mkId("id") );
-        inserter.insertRange( new Range(1, 5, met1) );
-        TreeNode met2 = new MetaNode( mkId("id") );
-        inserter.insertRange( new Range(3/*-1*/, 6/*-1*/, met2) );
-        TreeNode met3 = new MetaNode( mkId("id") );
-        inserter.insertRange( new Range(5/*-2*/, 7/*-2*/, met3) );
-        TreeNode root = new TreeNode()
-            .appendChild( new TextNode("1") )
-            .appendChild( met1.dup()
-                .appendChild( new TextNode("2") )
-                .appendChild( met2.dup()
-                    .appendChild( new TextNode("3") )
-                    .appendChild( met3.dup()
-                        .appendChild( new TextNode("45") ) ) ) )
-            .appendChild( new TextNode("6789") );
-        doTest(root, false);
-        // split at 3 metas, all at same position
-        TreeNode rby4 = new RubyNode( mkName("ruby") );
-        inserter.insertRange( new Range(7/*-3*/, 10/*-3*/, rby4) );
-        root = new TreeNode()
-            .appendChild( new TextNode("1") )
-            .appendChild( met1.dup()
-                .appendChild( new TextNode("2") )
-                .appendChild( met2.dup()
-                    .appendChild( new TextNode("3") )
-                    .appendChild( met3.dup()
-                        .appendChild( new TextNode("4") )
-                        .appendChild( rby4.dup()
-                            .appendChild( new TextNode("5") ) ) ) ) )
-            .appendChild( rby4.dup()
-                .appendChild( new TextNode("67") ) )
-            .appendChild( new TextNode("89") );
-        doTest(root, false);
-    }
-
-    @Test public void testRange7() throws Exception
-    {
-        RangeInserter inserter = new RangeInserter(m_xDoc);
-        TreeNode text = new TextNode("123456789");
-        inserter.insertRange( new Range(0, 0, text) );
-        TreeNode url1 = new HyperlinkNode( mkName("url") );
-        inserter.insertRange( new Range(1, 5, url1) );
-        TreeNode met2 = new MetaNode( mkId("id") );
-        inserter.insertRange( new Range(3, 5, met2) );
-        TreeNode root = new TreeNode()
-            .appendChild( new TextNode("1") )
-            .appendChild( url1.dup()
-                .appendChild( new TextNode("23") ) )
-            .appendChild( met2.dup()
-                .appendChild( url1.dup()
-                    .appendChild( new TextNode("45") ) ) )
-            .appendChild( new TextNode("6789") );
-        doTest(root, false);
-        // this should result in not splitting the hyperlink, but due to API
-        // we can't tell :(
-        TreeNode rby3 = new RubyNode( mkName("ruby") );
-        inserter.insertRange( new Range(5/*-1*/, 8/*-1*/, rby3) );
-        root = new TreeNode()
-            .appendChild( new TextNode("1") )
-            .appendChild( url1.dup()
-                .appendChild( new TextNode("23") ) )
-            .appendChild( met2.dup()
-                .appendChild( url1.dup()
-                    .appendChild( new TextNode("4") ) )
-                .appendChild( rby3.dup()
-                    .appendChild( url1.dup()
-                        .appendChild( new TextNode("5") ) ) ) )
-            .appendChild( rby3.dup()
-                .appendChild( new TextNode("67") ) )
-            .appendChild( new TextNode("89") );
-        doTest(root, false);
-    }
-
-    /* TODO: test partial selection, test UNDO/REDO */
-
-    // #i109601# NestedTextContent and XChild
-    @Test public void testMetaXChild() throws Exception
-    {
-        StringPair id1 = new StringPair("content.xml", mkName("id"));
-        StringPair id2 = new StringPair("content.xml", mkName("id"));
-        StringPair id3 = new StringPair("content.xml", mkName("id"));
-        StringPair id4 = new StringPair("content.xml", mkName("id"));
-        StringPair id5 = new StringPair("content.xml", mkName("id"));
-        StringPair id6 = new StringPair("content.xml", mkName("id"));
-        TreeNode meta1 = new MetaNode(id1);
-        TreeNode meta2 = new MetaNode(id2);
-        TreeNode meta3 = new MetaFieldNode(id3);
-        TreeNode meta4 = new MetaNode(id4);
-        TreeNode meta5 = new MetaNode(id5);
-        TreeNode meta6 = new MetaFieldNode(id6);
-        TreeNode root = new TreeNode()
-            .appendChild( meta1.dup()
-                .appendChild( new TextNode("1") ) )
-            .appendChild( new TextNode("2") )
-            .appendChild( meta2.dup()
-                .appendChild( meta3.dup()
-                    .appendChild( new TextNode("34") )
-                    .appendChild( meta4.dup()
-                        .appendChild( new TextNode("56") ) )
-                    .appendChild( meta5.dup() )
-                    .appendChild( new TextNode("7") ) ) )
-            .appendChild( new TextNode("8") )
-            .appendChild( meta6.dup()
-                .appendChild( new TextNode("9") ) );
-
-        RangeInserter inserter = new RangeInserter(m_xDoc);
-        TreeNode text = new TextNode("123456789");
-        inserter.insertRange( new Range(0, 0, text) );
-        XTextContent xMeta1 = inserter.insertRange( new Range(0, 1, meta1) );
-        XTextContent xMeta2 = inserter.insertRange( new Range(3, 8, meta2) );
-        XTextContent xMeta3 = inserter.insertRange( new Range(4, 9, meta3) );
-        XTextContent xMeta4 = inserter.insertRange( new Range(7, 9, meta4) );
-        XTextContent xMeta5 = inserter.insertRange( new Range(10, 10, meta5) );
-        XTextContent xMeta6 = inserter.insertRange( new Range(13, 14, meta6) );
-
-        doTest(root, false);
-
-        XText xDocText = m_xDoc.getText();
-        XTextCursor xDocTextCursor = xDocText.createTextCursor();
-        XParagraphCursor xParagraphCursor = UnoRuntime.queryInterface(XParagraphCursor.class, xDocTextCursor);
-        xParagraphCursor.gotoNextParagraph(false); // second paragraph
-        // X12XX34X56X78X9
-        // 1  23  4  5  6
-        //  1       452  6
-        //            3
-        StringPair [] nestedTextContent = new StringPair[] {
-            null,
-            id1,
-            id1,
-            null,
-            id2,
-            id3,
-            id3,
-            id3,
-            id4,
-            id4,
-            id4,
-            id5,
-            id3,
-            null,
-            id6,
-            id6,
-        };
-        XPropertySet xPropertySet = UnoRuntime.queryInterface(XPropertySet.class, xDocTextCursor);
-        for (int i = 0; i < nestedTextContent.length; ++i) {
-            Object oNTC = xPropertySet.getPropertyValue("NestedTextContent");
-            XTextContent xNTC = UnoRuntime.queryInterface(XTextContent.class, oNTC);
-            if (null == nestedTextContent[i]) {
-                assertNull("unexpected NestedTextContent at: " + i, xNTC);
-            } else {
-                XMetadatable xMetadatable = UnoRuntime.queryInterface(XMetadatable.class, xNTC);
-                StringPair xmlid = xMetadatable.getMetadataReference();
-                assertTrue("wrong NestedTextContent at: " + i,
-                    MetaNode.eq(nestedTextContent[i], xmlid));
-            }
-            xDocTextCursor.goRight((short)1, false);
-        }
-
-        XChild xChild1 = UnoRuntime.queryInterface(XChild.class, xMeta1);
-        XChild xChild2 = UnoRuntime.queryInterface(XChild.class, xMeta2);
-        XChild xChild3 = UnoRuntime.queryInterface(XChild.class, xMeta3);
-        XChild xChild4 = UnoRuntime.queryInterface(XChild.class, xMeta4);
-        XChild xChild5 = UnoRuntime.queryInterface(XChild.class, xMeta5);
-        XChild xChild6 = UnoRuntime.queryInterface(XChild.class, xMeta6);
-        try {
-            xChild1.setParent(xChild4);
-            fail("setParent(): allowed?");
-        } catch (NoSupportException e) { /* expected */ }
-        assertNull("getParent(): not null", xChild1.getParent());
-        assertNull("getParent(): not null", xChild2.getParent());
-        assertNull("getParent(): not null", xChild6.getParent());
-        {
-            Object xParent3 = xChild3.getParent();
-            assertNotNull("getParent(): null", xParent3);
-            XMetadatable xMetadatable = UnoRuntime.queryInterface(XMetadatable.class, xParent3);
-            StringPair xmlid = xMetadatable.getMetadataReference();
-            assertTrue("getParent(): wrong", MetaNode.eq(xmlid, id2));
-        }{
-            Object xParent4 = xChild4.getParent();
-            assertNotNull("getParent(): null", xParent4);
-            XMetadatable xMetadatable = UnoRuntime.queryInterface(XMetadatable.class, xParent4);
-            StringPair xmlid = xMetadatable.getMetadataReference();
-            assertTrue("getParent(): wrong", MetaNode.eq(xmlid, id3));
-        }{
-            Object xParent5 = xChild5.getParent();
-            assertNotNull("getParent(): null", xParent5);
-            XMetadatable xMetadatable = UnoRuntime.queryInterface(XMetadatable.class, xParent5);
-            StringPair xmlid = xMetadatable.getMetadataReference();
-            assertTrue("getParent(): wrong", MetaNode.eq(xmlid, id3));
-        }
-    }
-
-    /** test SwXMeta XText interface */
-    @Test public void testMetaXText() throws Exception
-    {
-        RangeInserter inserter = new RangeInserter(m_xDoc);
-        TreeNode text = new TextNode("12AB6789");
-        inserter.insertRange( new Range(0, 0, text) );
-        MetaNode meta = new MetaNode( mkId("id") );
-        XTextContent xMeta = inserter.makeMeta();
-
-        XText xDocText = m_xDoc.getText();
-        XTextCursor xDocTextCursor = xDocText.createTextCursor();
-        xDocTextCursor.goRight((short)3, false);
-        xDocTextCursor.goRight((short)2, true);
-        xDocText.insertTextContent(xDocTextCursor, xMeta, true);
-
-        XMetadatable xMetadatable = UnoRuntime.queryInterface(XMetadatable.class, xMeta);
-        xMetadatable.setMetadataReference(meta.getXmlId());
-        XText xText = UnoRuntime.queryInterface(XText.class, xMeta);
-
-        XText xParentText = xText.getText();
-        assertNotNull("getText(): no parent", xParentText);
-
-        XTextRange xStart = xText.getStart();
-        assertNotNull("getStart(): no start", xStart);
-
-        XTextRange xEnd = xText.getEnd();
-        assertNotNull("getEnd(): no end", xEnd);
-
-        xText.setString("45");
-
-        {
-            String string = xText.getString();
-            assertEquals("getString(): invalid string returned",
-                         "45", string);
-        }
-
-        XTextCursor xTextCursor = xText.createTextCursor();
-        assertNotNull("createTextCursor(): failed", xTextCursor);
-
-        try {
-            xText.createTextCursorByRange(null);
-            fail("createTextCursorByRange(): null allowed?");
-        } catch (RuntimeException e) { /* expected */ }
-
-        XTextCursor xTextCursorStart = xText.createTextCursorByRange(xStart);
-        assertNotNull("createTextCursorByRange(): failed for start",
-                      xTextCursorStart);
-
-        XTextCursor xTextCursorEnd = xText.createTextCursorByRange(xEnd);
-        assertNotNull("createTextCursorByRange(): failed for end",
-                      xTextCursorEnd);
-
-        // move outside meta
-        xDocTextCursor.gotoStart(false);
-
-        try {
-            xText.insertString(null, "foo", false);
-            fail("insertString(): null allowed?");
-        } catch (RuntimeException e) { /* expected */ }
-
-        try {
-            xText.insertString(xDocTextCursor, "foo", false);
-            fail("insertString(): cursor outside allowed?");
-        } catch (RuntimeException e) { /* expected */ }
-
-        xStart = xText.getStart();
-        xText.insertString(xStart, "A", false);
-        {
-            String string = xText.getString();
-            assertEquals("getString(): invalid string returned",
-                         "A45", string);
-        }
-
-        xText.insertString(xEnd, "B", false);
-        {
-            String string = xText.getString();
-            assertEquals("getString(): invalid string returned",
-                         "A45B", string);
-        }
-
-        try {
-            xText.insertControlCharacter(null, HARD_HYPHEN, false);
-            fail("insertControlCharacter(): null allowed?");
-        } catch (com.sun.star.lang.IllegalArgumentException e) { /* ignore */ }
-
-        xStart = xText.getStart();
-        try {
-            xText.insertControlCharacter(xDocTextCursor, HARD_HYPHEN, false);
-            fail("insertControlCharacter(): cursor outside allowed?");
-        } catch (com.sun.star.lang.IllegalArgumentException e) { /* ignore */ }
-
-        xText.insertControlCharacter(xStart, HARD_HYPHEN, false);
-        {
-            String string = xText.getString();
-            assertEquals("getString(): invalid string returned",
-                         '\u2011' + "A45B", string);
-        }
-
-        xText.insertControlCharacter(xEnd, HARD_HYPHEN, false);
-        {
-            String string = xText.getString();
-            assertEquals("getString(): invalid string returned",
-                         '\u2011' + "A45B" + '\u2011', string);
-        }
-
-        xText.setString("45");
-
-        try {
-            xText.insertTextContent(null, xMeta, false);
-            fail("insertTextContent(): null range allowed?");
-        } catch (com.sun.star.lang.IllegalArgumentException e) { /* ignore */ }
-
-        try {
-            xText.insertTextContent(xStart, null, false);
-            fail("insertTextContent(): null content allowed?");
-        } catch (com.sun.star.lang.IllegalArgumentException e) { /* ignore */ }
-
-        try {
-            xText.insertTextContent(xDocTextCursor, xMeta, false);
-            fail("insertTextContent(): cursor outside allowed?");
-        } catch (com.sun.star.lang.IllegalArgumentException e) { /* ignore */ }
-
-        TextFieldNode field1 = new TextFieldNode( "f1" );
-        TextFieldNode field2 = new TextFieldNode( "f2" );
-        XTextContent xField1 = inserter.makeTextField(field1.getContent());
-        XTextContent xField2 = inserter.makeTextField(field2.getContent());
-
-        xStart = xText.getStart();
-        xText.insertTextContent(xStart, xField1, false);
-
-        TreeNode root = new TreeNode()
-            .appendChild( new TextNode("12") )
-            .appendChild( meta.dup()
-                .appendChild( field1.dup() )
-                .appendChild( new TextNode("45") ) )
-            .appendChild( new TextNode("6789") );
-        doTest(root, false);
-
-        xText.insertTextContent(xEnd, xField2, false);
-
-        root = new TreeNode()
-            .appendChild( new TextNode("12") )
-            .appendChild( meta.dup()
-                .appendChild( field1.dup() )
-                .appendChild( new TextNode("45") )
-                .appendChild( field2.dup() ) )
-            .appendChild( new TextNode("6789") );
-        doTest(root, false);
-
-        try {
-            xText.removeTextContent(null);
-            fail("removeTextContent(): null content allowed?");
-        } catch (RuntimeException e) { /* expected */ }
-
-        xText.removeTextContent(xField1);
-
-        XTextRange xAnchor = xMeta.getAnchor();
-        assertNotNull("getAnchor(): null", xAnchor);
-
-        // evil test case: insert ruby around meta
-        RubyNode ruby = new RubyNode( mkName("ruby") );
-        inserter.insertRange( new Range(2, 6, ruby) );
-
-        /* prevent caching...
-        root = new TreeNode()
-            .appendChild( new TextNode("12") )
-            .appendChild( ruby.dup()
-                .appendChild( meta.dup()
-                    .appendChild( new TextNode("45") )
-                    .appendChild( field2.dup() ) ) )
-            .appendChild( new TextNode("6789") );
-        doTest(root, false);
-        */
-
-        XEnumerationAccess xEA = UnoRuntime.queryInterface(XEnumerationAccess.class, xMeta);
-        XEnumeration xEnum = xEA.createEnumeration();
-        assertNotNull("createEnumeration(): returns null", xEnum);
-        {
-            assertTrue("hasNext(): first missing", xEnum.hasMoreElements());
-            Object xElement = xEnum.nextElement();
-            XTextRange xPortion = UnoRuntime.queryInterface(XTextRange.class, xElement);
-            XPropertySet xPropSet = UnoRuntime.queryInterface(XPropertySet.class, xPortion);
-            String type = (String) xPropSet.getPropertyValue("TextPortionType");
-            assertEquals("first: not text", "Text", type);
-            String txt = xPortion.getString();
-            assertEquals("first: text differs", "45", txt);
-        }
-        {
-            assertTrue("hasNext(): second missing", xEnum.hasMoreElements());
-            Object xElement = xEnum.nextElement();
-            XTextRange xPortion = UnoRuntime.queryInterface(XTextRange.class, xElement);
-            XPropertySet xPropSet = UnoRuntime.queryInterface(XPropertySet.class, xPortion);
-            String type = (String) xPropSet.getPropertyValue("TextPortionType");
-            assertEquals("second: not text", "TextField", type);
-        }
-        // no ruby end here!!!
-        assertFalse("hasNext(): more elements?", xEnum.hasMoreElements());
-
-        XComponent xComponent = UnoRuntime.queryInterface(XComponent.class, xMeta);
-        xComponent.dispose();
-
-        try {
-            XTextCursor xCursor = xText.createTextCursor();
-            assertNull("createTextCursor(): succeeds on disposed object?",
-                       xCursor);
-        } catch (RuntimeException e) { /* expected */ }
-    }
-
-    /** check that cursor move methods move to positions in the meta,
-        but do not move to positions outside the meta. */
-    @Test public void testMetaXTextCursor() throws Exception
-    {
-        RangeInserter inserter = new RangeInserter(m_xDoc);
-        TreeNode text = new TextNode("Text. 12 More text here.");
-        inserter.insertRange( new Range(0, 0, text) );
-        MetaNode met1 = new MetaNode( mkId("id") );
-        XTextContent xMeta = inserter.makeMeta();
-
-        XText xDocText = m_xDoc.getText();
-        XTextCursor xDocTextCursor = xDocText.createTextCursor();
-        xDocTextCursor.goRight((short)7, false);
-        xDocTextCursor.goRight((short)2, true);
-        xDocText.insertTextContent(xDocTextCursor, xMeta, true);
-        xDocTextCursor.gotoStart(true);
-
-        XMetadatable xMetadatable = UnoRuntime.queryInterface(XMetadatable.class, xMeta);
-        xMetadatable.setMetadataReference(met1.getXmlId());
-        XText xText = UnoRuntime.queryInterface(XText.class, xMeta);
-
-        XTextRange xStart = xText.getStart();
-        assertNotNull("getStart(): no start", xStart);
-        XTextRange xEnd = xText.getEnd();
-        assertNotNull("getEnd(): no end", xEnd);
-
-        XTextCursor xTextCursor = xText.createTextCursor();
-        assertNotNull("createTextCursor(): no cursor", xTextCursor);
-
-        // XTextCursor
-        boolean bSuccess = false;
-        xTextCursor.gotoStart(false);
-        xTextCursor.gotoEnd(false);
-        bSuccess = xTextCursor.goLeft((short)1, false);
-        assertTrue("goLeft(): failed", bSuccess);
-        bSuccess = xTextCursor.goLeft((short)1000, false);
-        assertFalse("goLeft(): succeeded", bSuccess);
-        bSuccess = xTextCursor.goRight((short)1, false);
-        assertTrue("goRight(): failed", bSuccess);
-        bSuccess = xTextCursor.goRight((short)1000, false);
-        assertFalse("goRight(): succeeded", bSuccess);
-        xTextCursor.gotoRange(xStart, false);
-        xTextCursor.gotoRange(xEnd, false);
-        try {
-            xTextCursor.gotoRange(xDocTextCursor, false);
-            fail("gotoRange(): succeeded");
-        } catch (RuntimeException e) { /* expected */ }
-
-        // XWordCursor
-        xText.setString("Two words");
-        xTextCursor.gotoStart(false);
-        XWordCursor xWordCursor = UnoRuntime.queryInterface(XWordCursor.class, xTextCursor);
-
-        bSuccess = xWordCursor.gotoNextWord(true);              //at start of "words"
-        assertTrue("gotoNextWord(): failed", bSuccess);
-        {
-            String string = xTextCursor.getString();
-            assertEquals("gotoNextWord(): wrong string",
-                         "Two ", string);
-        }
-        bSuccess = xWordCursor.gotoNextWord(false);             //at end of "words", cannot leave metafield
-        assertFalse("gotoNextWord(): succeeded", bSuccess);
-        xTextCursor.collapseToEnd();
-        bSuccess = xWordCursor.gotoPreviousWord(true);          //at start of "words"
-        assertTrue("gotoPreviousWord(): failed", bSuccess);
-        {
-            String string = xTextCursor.getString();
-            assertEquals("gotoPreviousWord(): wrong string",
-                         "words", string);
-        }
-        bSuccess = xWordCursor.gotoPreviousWord(false);         //at start of "Two"
-        assertTrue("gotoPreviousWord(): failed", bSuccess);
-
-        bSuccess = xWordCursor.gotoPreviousWord(false);         //cannot leave metafield
-        assertFalse("gotoPreviousWord(): succeeded", bSuccess);
-
-        bSuccess = xWordCursor.gotoEndOfWord(true);             //at end of "Two"
-        assertTrue("gotoEndOfWord(): failed", bSuccess);
-        {
-            String string = xTextCursor.getString();
-            assertEquals("gotoEndOfWord(): wrong string",
-                         "Two", string);
-        }
-        xTextCursor.gotoEnd(false);
-        bSuccess = xWordCursor.gotoStartOfWord(true);
-        assertTrue("gotoStartOfWord(): failed", bSuccess);
-        {
-            String string = xTextCursor.getString();
-            assertEquals("gotoStartOfWord(): wrong string",
-                         "words", string);
-        }
-        xText.setString("");
-        bSuccess = xWordCursor.gotoEndOfWord(false);
-        assertFalse("gotoEndOfWord(): succeeded", bSuccess);
-        bSuccess = xWordCursor.gotoStartOfWord(false);
-        assertFalse("gotoStartOfWord(): succeeded", bSuccess);
-
-        // XSentenceCursor
-        xText.setString("This is a sentence. Another sentence.");
-        xTextCursor.gotoStart(false);
-        XSentenceCursor xSentenceCursor = UnoRuntime.queryInterface(XSentenceCursor.class, xTextCursor);
-
-        bSuccess = xSentenceCursor.gotoNextSentence(true);
-        assertTrue("gotoNextSentence(): failed", bSuccess);
-        {
-            String string = xTextCursor.getString();
-            assertEquals("gotoNextSentence(): wrong string",
-                         "This is a sentence. ", string);
-        }
-        bSuccess = xSentenceCursor.gotoNextSentence(false);
-        assertFalse("gotoNextSentence(): succeeded", bSuccess);
-        // FIXME:
-        // the sentence cursor seems to work differently than the word cursor
-        xText.setString("This is a sentence. Another sentence. Sentence 3.");
-        xTextCursor.gotoEnd(false);
-        bSuccess = xSentenceCursor.gotoPreviousSentence(true);
-        assertTrue("gotoPreviousSentence(): failed", bSuccess);
-        {
-            String string = xTextCursor.getString();
-            assertEquals("gotoPreviousSentence(): wrong string",
-                         "Another sentence. Sentence 3.", string);
-        }
-        bSuccess = xSentenceCursor.gotoPreviousSentence(false);
-        assertFalse("gotoPreviousSentence(): succeeded", bSuccess);
-        bSuccess = xSentenceCursor.gotoEndOfSentence(true);
-        assertTrue("gotoEndOfSentence(): failed", bSuccess);
-        {
-            String string = xTextCursor.getString();
-            assertEquals("gotoEndOfSentence(): wrong string",
-                         "This is a sentence.", string);
-        }
-        xTextCursor.gotoEnd(false);
-        bSuccess = xSentenceCursor.gotoStartOfSentence(true);
-        assertTrue("gotoStartOfSentence(): failed", bSuccess);
-        {
-            String string = xTextCursor.getString();
-            assertEquals("gotoStartOfSentence(): wrong string",
-                         "Sentence 3.", string);
-        }
-        xText.setString("");
-        bSuccess = xSentenceCursor.gotoEndOfSentence(false);
-        assertFalse("gotoEndOfSentence(): succeeded", bSuccess);
-        bSuccess = xSentenceCursor.gotoStartOfSentence(false);
-        assertFalse("gotoStartOfSentence(): succeeded", bSuccess);
-
-        XParagraphCursor xParagraphCursor = UnoRuntime.queryInterface(XParagraphCursor.class, xTextCursor);
-
-        // XParagraphCursor (does not make sense)
-        bSuccess = xParagraphCursor.gotoNextParagraph(false);
-        assertFalse("gotoNextParagraph(): succeeded", bSuccess);
-        bSuccess = xParagraphCursor.gotoPreviousParagraph(false);
-        assertFalse("gotoPreviousParagraph(): succeeded", bSuccess);
-        bSuccess = xParagraphCursor.gotoStartOfParagraph(false);
-        assertFalse("gotoStartOfParagraph(): succeeded", bSuccess);
-        bSuccess = xParagraphCursor.gotoEndOfParagraph(false);
-        assertFalse("gotoEndOfParagraph(): succeeded", bSuccess);
-    }
-
-    /** See https://bugs.libreoffice.org/show_bug.cgi?id=49629
-        ensure that gotoEndOfWord does not fail when footnote is at word end*/
-    @Test public void testXTextCursor() throws Exception
-    {
-        RangeInserter inserter = new RangeInserter(m_xDoc);
-        XText xDocText = m_xDoc.getText();
-        XTextCursor xDocTextCursor = xDocText.createTextCursor();
-        inserter.insertText(xDocTextCursor, "Text");
-        XWordCursor xWordCursor = UnoRuntime.queryInterface(XWordCursor.class, xDocTextCursor);
-        xWordCursor.gotoEndOfWord(false);
-        inserter.insertFootnote(xDocTextCursor, "footnote");
-        xDocTextCursor.gotoStart(false);
-        boolean bSuccess = xWordCursor.gotoEndOfWord(true);
-        assertTrue("gotoEndOfWord(): failed", bSuccess);
-        String string = xWordCursor.getString();
-        assertEquals("gotoEndOfWord(): wrong string", "Text", string);
-    }
-
     private abstract class AttachHelper
     {
         abstract boolean isAttribute();
diff --git a/sw/qa/python/text_portion_enumeration_test.py b/sw/qa/python/text_portion_enumeration_test.py
index e6bec7230020..857eeee78b68 100644
--- a/sw/qa/python/text_portion_enumeration_test.py
+++ b/sw/qa/python/text_portion_enumeration_test.py
@@ -634,6 +634,33 @@ class RangeInserter(Inserter):
         elif nodetype == "MetadataField":
             meta = node
             return self.insertmetafield(xParaCursor, meta.xmlid)
+        elif nodetype == "Bookmark":
+            bkmk = node
+            if bkmk.ispoint:
+                raise RuntimeError("range only")
+            self.insertbookmark(xParaCursor, bkmk.name, bkmk.xmlid)
+        elif nodetype == "ReferenceMark":
+            mark = node
+            if mark.ispoint:
+                raise RuntimeError("range only")
+            self.insertreferencemark(xParaCursor, mark.name)
+        elif nodetype == "DocumentIndexMark":
+            mark = node
+            if mark.ispoint:
+                raise RuntimeError("range only")
+            self.insertdocumentindexmark(xParaCursor, mark.name)
+        elif nodetype == "TextField":
+            field = node
+            self.inserttextfield(self.xCursor, field.content)
+        elif nodetype == "Footnote":
+            note = node
+            self.insertfootnote(self.xCursor, note.label)
+        elif nodetype == "Frame":
+            frame = node
+            self.insertframe(xParaCursor, frame.name, frame.anchor)
+        elif nodetype == "ControlCharacter":
+            cchar = node
+            self.insertcontrolcharacter(self.xCursor, cchar.char)
         elif nodetype == "SoftPageBreak":
             raise RuntimeError("sorry, cannot test SoftPageBreak")
         else:
@@ -2129,6 +2156,753 @@ class TextPortionEnumerationTest(unittest.TestCase):
         root.appendchild(TextNode("789"))
         self.dotest(root, False)
 
+    def test_range2(self):
+        inserter = RangeInserter(self.__class__.xDoc)
+        text = TextNode("123456789")
+        inserter.insertrange(Range(0, 0, text))
+        met1 = MetaNode(self.mkid("id"))
+        inserter.insertrange(Range(1, 8, met1))
+        met2 = MetaNode(self.mkid("id"))
+        # inserter.insertrange(Range(3-1, 8-1, met2))
+        inserter.insertrange(Range(3, 8, met2))
+        met3 = MetaNode(self.mkid("id"))
+        # inserter.insertrange(Range(5-2, 8-2, met3))
+        inserter.insertrange(Range(5, 8, met3))
+        root = TreeNode()
+        root.appendchild(TextNode("1"))
+        root.appendchild(met1.dup()
+                .appendchild(TextNode("2"))
+                .appendchild(met2.dup()
+                    .appendchild(TextNode("3"))
+                    .appendchild(met3.dup()
+                        .appendchild(TextNode("456")))
+                    .appendchild(TextNode("7")))
+                .appendchild(TextNode("8")))
+        root.appendchild(TextNode("9"))
+        self.dotest(root, False)
+        ## split ruby at every meta start!
+        rby4 = RubyNode(self.mkname("ruby"))
+        # inserter.insertrange(Range(0, 7-3, rby4))
+        inserter.insertrange(Range(0, 7, rby4))
+        root = TreeNode()
+        root.appendchild(rby4.dup()
+                .appendchild(TextNode("1")))
+        root.appendchild(met1.dup()
+                .appendchild(rby4.dup()
+                    .appendchild(TextNode("2")))
+                .appendchild(met2.dup()
+                    .appendchild(rby4.dup()
+                        .appendchild(TextNode("3")))
+                    .appendchild(met3.dup()
+                        .appendchild(rby4.dup()
+                            .appendchild(TextNode("4")))
+                        .appendchild(TextNode("56")))
+                    .appendchild(TextNode("7")))
+                .appendchild(TextNode("8")))
+        root.appendchild(TextNode("9"))
+        self.dotest(root, False)
+        ## split ruby at every meta end!
+        rby5 = RubyNode(self.mkname("ruby"))
+        # inserter.insertrange(Range(8-3, 12-3, rby5))
+        inserter.insertrange(Range(8, 12, rby5))
+        root = TreeNode()
+        root.appendchild(rby4.dup()
+                .appendchild(TextNode("1")))
+        root.appendchild(met1.dup()
+                .appendchild(rby4.dup()
+                    .appendchild(TextNode("2")))
+                .appendchild(met2.dup()
+                    .appendchild(rby4.dup()
+                        .appendchild(TextNode("3")))
+                    .appendchild(met3.dup()
+                        .appendchild(rby4.dup()
+                            .appendchild(TextNode("4")))
+                        .appendchild(TextNode("5"))
+                        .appendchild(rby5.dup()
+                            .appendchild(TextNode("6"))))
+                    .appendchild(rby5.dup()
+                        .appendchild(TextNode("7"))))
+                .appendchild(rby5.dup()
+                    .appendchild(TextNode("8"))))
+        root.appendchild(rby5.dup()
+                .appendchild(TextNode("9")))
+        self.dotest(root, False)
+
+    def test_range3(self):
+        inserter = RangeInserter(self.__class__.xDoc)
+        text = TextNode("123456789")
+        inserter.insertrange(Range(0, 0, text))
+        rby1 = RubyNode(self.mkname("ruby"))
+        inserter.insertrange(Range(0, 9, rby1))
+        met2 = MetaNode(self.mkid("id"))
+        inserter.insertrange(Range(2, 7, met2))
+        root = TreeNode()
+        root.appendchild(rby1.dup()
+                .appendchild(TextNode("12"))
+                .appendchild(met2.dup()
+                    .appendchild(TextNode("34567")))
+                .appendchild(TextNode("89")))
+        self.dotest(root, False)
+        ## overwrite outer ruby, split remains at inner meta!
+        rby3 = RubyNode(self.mkname("ruby"))
+        # inserter.insertrange(Range(5-1, 6-1, rby3))
+        inserter.insertrange(Range(5, 6, rby3))
+        root = TreeNode()
+        root.appendchild(rby1.dup()
+                .appendchild(TextNode("12")))
+        root.appendchild(met2.dup()
+                .appendchild(rby1.dup()
+                    .appendchild(TextNode("34")))
+                .appendchild(rby3.dup()
+                    .appendchild(TextNode("5")))
+                .appendchild(rby1.dup()
+                    .appendchild(TextNode("67"))))
+        root.appendchild(rby1.dup()
+                .appendchild(TextNode("89")))
+        self.dotest(root, False)
+
+    def test_range4(self):
+        inserter = RangeInserter(self.__class__.xDoc)
+        text = TextNode("123456789")
+        inserter.insertrange(Range(0, 0, text))
+        rby1 = RubyNode(self.mkname("ruby"))
+        inserter.insertrange(Range(0, 9, rby1))
+        met2 = MetaNode(self.mkid("id"))
+        inserter.insertrange(Range(1, 8, met2))
+        met3 = MetaNode(self.mkid("id"))
+        # inserter.insertrange(Range(3-1, 8-1, met3))
+        inserter.insertrange(Range(3, 8, met3))
+        met4 = MetaNode(self.mkid("id"))
+        # inserter.insertrange(Range(5-2, 8-2, met4))
+        inserter.insertrange(Range(5, 8, met4))
+        root = TreeNode()
+        root.appendchild(rby1.dup()
+                .appendchild(TextNode("1"))
+                .appendchild(met2.dup()
+                    .appendchild(TextNode("2"))
+                    .appendchild(met3.dup()
+                        .appendchild(TextNode("3"))
+                        .appendchild(met4.dup()
+                            .appendchild(TextNode("456")))
+                        .appendchild(TextNode("7")))
+                    .appendchild(TextNode("8")))
+                .appendchild(TextNode("9")))
+        self.dotest(root, False)
+        ## overwrite outer ruby, split remains at every inner meta!
+        rby5 = RubyNode(self.mkname("ruby"))
+        # inserter.insertrange(Range(7-3, 8-3, rby5))
+        inserter.insertrange(Range(7, 8, rby5))
+        root = TreeNode()
+        root.appendchild(rby1.dup()
+                .appendchild(TextNode("1")))
+        root.appendchild(met2.dup()
+                .appendchild(rby1.dup()
+                    .appendchild(TextNode("2")))
+                .appendchild(met3.dup()
+                    .appendchild(rby1.dup()
+                        .appendchild(TextNode("3")))
+                    .appendchild(met4.dup()
+                        .appendchild(rby1.dup()
+                            .appendchild(TextNode("4")))
+                        .appendchild(rby5.dup()
+                            .appendchild(TextNode("5")))
+                        .appendchild(rby1.dup()
+                            .appendchild(TextNode("6"))))
+                    .appendchild(rby1.dup()
+                        .appendchild(TextNode("7"))))
+                .appendchild(rby1.dup()
+                    .appendchild(TextNode("8"))))
+        root.appendchild(rby1.dup()
+                .appendchild(TextNode("9")))
+        self.dotest(root, False)
+
+    def test_range5(self):
+        inserter = RangeInserter(self.__class__.xDoc)
+        text = TextNode("123456789")
+        inserter.insertrange(Range(0, 0, text))
+        rby1 = RubyNode(self.mkname("ruby"))
+        inserter.insertrange(Range(0, 9, rby1))
+        met2 = MetaNode(self.mkid("id"))
+        inserter.insertrange(Range(1, 3, met2))
+        met3 = MetaNode(self.mkid("id"))
+        # inserter.insertrange(Range(5-1, 6-1, met3))
+        inserter.insertrange(Range(5, 6, met3))
+        met4 = MetaNode(self.mkid("id"))
+        # inserter.insertrange(Range(8-2, 10-2, met4))
+        inserter.insertrange(Range(8, 10, met4))
+        root = TreeNode()
+        root.appendchild(rby1.dup()
+                .appendchild(TextNode("1"))
+                .appendchild(met2.dup().appendchild(TextNode("23")))
+                .appendchild(TextNode("4"))
+                .appendchild(met3.dup().appendchild(TextNode("5")))
+                .appendchild(TextNode("6"))
+                .appendchild(met4.dup().appendchild(TextNode("78")))
+                .appendchild(TextNode("9")))
+        self.dotest(root, False)
+        ## overwrite outer ruby, but split at inner metas!
+        rby5 = RubyNode(self.mkname("ruby"))
+        # inserter.insertrange(Range(3-1, 10-3, rby5))
+        inserter.insertrange(Range(3, 10, rby5))
+        root = TreeNode()
+        root.appendchild(rby1.dup()
+                .appendchild(TextNode("1")))
+        root.appendchild(met2.dup()
+                .appendchild(rby1.dup()
+                    .appendchild(TextNode("2")))
+                .appendchild(rby5.dup()
+                    .appendchild(TextNode("3"))))
+        root.appendchild(rby5.dup()
+                .appendchild(TextNode("4"))
+                .appendchild(met3.dup()
+                    .appendchild(TextNode("5")))
+                .appendchild(TextNode("6")))
+        root.appendchild(met4.dup()
+                .appendchild(rby5.dup()
+                    .appendchild(TextNode("7")))
+                .appendchild(rby1.dup()
+                    .appendchild(TextNode("8"))))
+        root.appendchild(rby1.dup()
+                .appendchild(TextNode("9")))
+        self.dotest(root, False)
+
+    def test_range6(self):
+        inserter = RangeInserter(self.__class__.xDoc)
+        text = TextNode("123456789")
+        inserter.insertrange(Range(0, 0, text))
+        met1 = MetaNode(self.mkid("id"))
+        inserter.insertrange(Range(1, 5, met1))
+        met2 = MetaNode(self.mkid("id"))
+        # inserter.insertrange(Range(3-1, 6-1, met2))
+        inserter.insertrange(Range(3, 6, met2))
+        met3 = MetaNode(self.mkid("id"))
+        # inserter.insertrange(Range(5-2, 7-2, met3))
+        inserter.insertrange(Range(5, 7, met3))
+        root = TreeNode()
+        root.appendchild(TextNode("1"))
+        root.appendchild(met1.dup()
+                .appendchild(TextNode("2"))
+                .appendchild(met2.dup()
+                    .appendchild(TextNode("3"))
+                    .appendchild(met3.dup()
+                        .appendchild(TextNode("45")))))
+        root.appendchild(TextNode("6789"))
+        self.dotest(root, False)
+        ## split at 3 metas, all at same position
+        rby4 = RubyNode(self.mkname("ruby"))
+        # inserter.insertrange(Range(7-3, 10-3, rby4))
+        inserter.insertrange(Range(7, 10, rby4))
+        root = TreeNode()
+        root.appendchild(TextNode("1"))
+        root.appendchild(met1.dup()
+                .appendchild(TextNode("2"))
+                .appendchild(met2.dup()
+                    .appendchild(TextNode("3"))
+                    .appendchild(met3.dup()
+                        .appendchild(TextNode("4"))
+                        .appendchild(rby4.dup()
+                            .appendchild(TextNode("5"))))))
+        root.appendchild(rby4.dup()
+                .appendchild(TextNode("67")))
+        root.appendchild(TextNode("89"))
+        self.dotest(root, False)
+
+    def test_range7(self):
+        inserter = RangeInserter(self.__class__.xDoc)
+        text = TextNode("123456789")
+        inserter.insertrange(Range(0, 0, text))
+        url1 = HyperlinkNode(self.mkname("url"))
+        inserter.insertrange(Range(1, 5, url1))
+        met2 = MetaNode(self.mkid("id"))
+        inserter.insertrange(Range(3, 5, met2))
+        root = TreeNode()
+        root.appendchild(TextNode("1"))
+        root.appendchild(url1.dup()
+                .appendchild(TextNode("23")))
+        root.appendchild(met2.dup()
+                .appendchild(url1.dup()
+                    .appendchild(TextNode("45"))))
+        root.appendchild(TextNode("6789"))
+        self.dotest(root, False)
+        ## this should result in not splitting the hyperlink, but due to API
+        ## we can't tell :(
+        rby3 = RubyNode(self.mkname("ruby"))
+        # inserter.insertrange(Range(5-1, 8-1, rby3))
+        inserter.insertrange(Range(5, 8, rby3))
+        root = TreeNode()
+        root.appendchild(TextNode("1"))
+        root.appendchild(url1.dup()
+                .appendchild(TextNode("23")))
+        root.appendchild(met2.dup()
+                .appendchild(url1.dup()
+                    .appendchild(TextNode("4")))
+                .appendchild(rby3.dup()
+                    .appendchild(url1.dup()
+                        .appendchild(TextNode("5")))))
+        root.appendchild(rby3.dup()
+                .appendchild(TextNode("67")))
+        root.appendchild(TextNode("89"))
+        self.dotest(root, False)
+
+    # TODO: test partial selection, test UNDO/REDO
+
+    ##i109601# NestedTextContent and XChild
+    def test_meta_xchild(self):
+        xDoc = self.__class__.xDoc
+        id1 = StringPair("content.xml", self.mkname("id"))
+        id2 = StringPair("content.xml", self.mkname("id"))
+        id3 = StringPair("content.xml", self.mkname("id"))
+        id4 = StringPair("content.xml", self.mkname("id"))
+        id5 = StringPair("content.xml", self.mkname("id"))
+        id6 = StringPair("content.xml", self.mkname("id"))
+        meta1 = MetaNode(id1)
+        meta2 = MetaNode(id2)
+        meta3 = MetaFieldNode(id3)
+        meta4 = MetaNode(id4)
+        meta5 = MetaNode(id5)
+        meta6 = MetaFieldNode(id6)
+        root = TreeNode()
+        root.appendchild(meta1.dup()
+                .appendchild(TextNode("1")))
+        root.appendchild(TextNode("2"))
+        root.appendchild(meta2.dup()
+                .appendchild(meta3.dup()
+                    .appendchild(TextNode("34"))
+                    .appendchild(meta4.dup()
+                        .appendchild(TextNode("56")))
+                    .appendchild(meta5.dup())
+                    .appendchild(TextNode("7"))))
+        root.appendchild(TextNode("8"))
+        root.appendchild(meta6.dup()
+                .appendchild(TextNode("9")))
+
+        inserter = RangeInserter(xDoc)
+        text = TextNode("123456789")
+        inserter.insertrange(Range(0, 0, text))
+        xMeta1 = inserter.insertrange(Range(0, 1, meta1))
+        xMeta2 = inserter.insertrange(Range(3, 8, meta2))
+        xMeta3 = inserter.insertrange(Range(4, 9, meta3))
+        xMeta4 = inserter.insertrange(Range(7, 9, meta4))
+        xMeta5 = inserter.insertrange(Range(10, 10, meta5))
+        xMeta6 = inserter.insertrange(Range(13, 14, meta6))
+
+        self.dotest(root, False)
+
+        xDocText = xDoc.getText()
+        xDocTextCursor = xDocText.createTextCursor()
+        xDocTextCursor.gotoNextParagraph(False) # second paragraph
+        #  X12XX34X56X78X9
+        #  1  23  4  5  6
+        #   1       452  6
+        #             3
+        nestedTextContent = (
+            None,
+            id1,
+            id1,
+            None,
+            id2,
+            id3,
+            id3,
+            id3,
+            id4,
+            id4,
+            id4,
+            id5,
+            id3,
+            None,
+            id6,
+            id6)
+        for i, ntc in enumerate(nestedTextContent):
+            oNTC = xDocTextCursor.NestedTextContent
+            if ntc is None:
+                self.assertIsNone(oNTC,
+                            "unexpected NestedTextContent at: {}".format(i))
+            else:
+                xmlid = oNTC.MetadataReference
+                self.assertTrue(MetaNode.eq(ntc, xmlid),
+                            "wrong NestedTextContent at: {}".format(i))
+            xDocTextCursor.goRight(1, False)
+
+        try:
+            xMeta1.setParent(xMeta4)
+            fail("setParent(): allowed?")
+        except NoSupportException:
+            pass
+        self.assertIsNone(xMeta1.getParent(), "getParent(): not None")
+        self.assertIsNone(xMeta2.getParent(), "getParent(): not None")
+        self.assertIsNone(xMeta6.getParent(), "getParent(): not None")
+
+        xParent3 = xMeta3.getParent()
+        self.assertIsNotNone(xParent3, "getParent(): None")
+        xmlid = xParent3.MetadataReference
+        self.assertTrue(MetaNode.eq(xmlid, id2), "getParent(): wrong")
+
+        xParent4 = xMeta4.getParent()
+        self.assertIsNotNone(xParent4, "getParent(): None")
+        xmlid = xParent4.MetadataReference
+        self. assertTrue(MetaNode.eq(xmlid, id3), "getParent(): wrong")
+
+        xParent5 = xMeta5.getParent()
+        self.assertIsNotNone(xParent5, "getParent(): None")
+        xmlid = xParent5.MetadataReference
+        self.assertTrue(MetaNode.eq(xmlid, id3), "getParent(): wrong")
+
+    # test SwXMeta XText interface
+    def test_meta_xtext(self):
+        xDoc = self.__class__.xDoc
+        inserter = RangeInserter(xDoc)
+        text = TextNode("12AB6789")
+        inserter.insertrange(Range(0, 0, text))
+        meta = MetaNode(self.mkid("id"))
+        xMeta = inserter.makemeta()
+
+        xDocText = xDoc.getText()
+        xDocTextCursor = xDocText.createTextCursor()
+        xDocTextCursor.goRight(3, False)
+        xDocTextCursor.goRight(2, True)
+        xDocText.insertTextContent(xDocTextCursor, xMeta, True)
+
+        xMeta.MetadataReference = meta.xmlid
+        xParentText = xMeta.getText()
+        self.assertIsNotNone(xParentText, "getText(): no parent")
+
+        xStart = xMeta.getStart()
+        self.assertIsNotNone(xStart, "getStart(): no start")
+
+        xEnd = xMeta.getEnd()
+        self.assertIsNotNone(xEnd, "getEnd(): no end")
+
+        xMeta.setString("45")
+
+        string = xMeta.getString()
+        self.assertEqual("45", string, "getString(): invalid string returned")
+
+        xTextCursor = xMeta.createTextCursor()
+        self.assertIsNotNone(xTextCursor, "createTextCursor(): failed")
+
+        try:
+            xMeta.createTextCursorByRange(None)
+            fail("createTextCursorByRange(): None allowed?")
+        except RuntimeException:
+            pass
+
+        xTextCursorStart = xMeta.createTextCursorByRange(xStart)
+        self.assertIsNotNone(xTextCursorStart,
+                    "createTextCursorByRange(): failed for start")
+
+        xTextCursorEnd = xMeta.createTextCursorByRange(xEnd)
+        self.assertIsNotNone(xTextCursorEnd,
+                             "createTextCursorByRange(): failed for end")
+
+        ## move outside meta
+        xDocTextCursor.gotoStart(False)
+
+        try:
+            xMeta.insertString(None, "foo", False)
+            fail("insertString(): None allowed?")
+        except RuntimeException:
+            pass
+
+        try:
+            xMeta.insertString(xDocTextCursor, "foo", False)
+            fail("insertString(): cursor outside allowed?")
+        except RuntimeException:
+            pass
+
+        xStart = xMeta.getStart()
+        xMeta.insertString(xStart, "A", False)
+        string = xMeta.getString()
+        self.assertEqual("A45", string, "getString(): invalid string returned")
+
+        xMeta.insertString(xEnd, "B", False)
+        string = xMeta.getString()
+        self.assertEqual("A45B", string, "getString(): invalid string returned")
+
+        try:
+            xMeta.insertControlCharacter(None, HARD_HYPHEN, False)
+            fail("insertControlCharacter(): None allowed?")
+        except IllegalArgumentException:
+            pass
+
+        xStart = xMeta.getStart()
+        try:
+            xMeta.insertControlCharacter(xDocTextCursor, HARD_HYPHEN, False)
+            fail("insertControlCharacter(): cursor outside allowed?")
+        except IllegalArgumentException:
+            pass
+
+        xMeta.insertControlCharacter(xStart, HARD_HYPHEN, False)
+        string = xMeta.getString()
+        self.assertEqual('\u2011' + 'A45B', string,
+                                "getString(): invalid string returned")
+
+        xMeta.insertControlCharacter(xEnd, HARD_HYPHEN, False)
+        string = xMeta.getString()
+        self.assertEqual('\u2011' + 'A45B' + '\u2011', string,
+                                "getString(): invalid string returned")
+
+        xMeta.setString("45")
+        try:
+            xMeta.insertTextContent(None, xMeta, False)
+            fail("insertTextContent(): None range allowed?")
+        except IllegalArgumentException:
+            pass
+
+        try:
+            xMeta.insertTextContent(xStart, None, False)
+            fail("insertTextContent(): None content allowed?")
+        except IllegalArgumentException:
+            pass
+
+        try:
+            xMeta.insertTextContent(xDocTextCursor, xMeta, False)
+            fail("insertTextContent(): cursor outside allowed?")
+        except IllegalArgumentException:
+            pass
+
+        field1 = TextFieldNode("f1")
+        field2 = TextFieldNode("f2")
+        xField1 = inserter.maketextfield(field1.content)
+        xField2 = inserter.maketextfield(field2.content)
+
+        xStart = xMeta.getStart()
+        xMeta.insertTextContent(xStart, xField1, False)
+
+        root = TreeNode()
+        root.appendchild(TextNode("12"))
+        root.appendchild(meta.dup()
+                .appendchild(field1.dup())
+                .appendchild(TextNode("45")))
+        root.appendchild(TextNode("6789"))
+        self.dotest(root, False)
+
+        xMeta.insertTextContent(xEnd, xField2, False)
+
+        root = TreeNode()
+        root.appendchild(TextNode("12"))
+        root.appendchild(meta.dup()
+                .appendchild(field1.dup())
+                .appendchild(TextNode("45"))
+                .appendchild(field2.dup()))
+        root.appendchild(TextNode("6789"))
+        self.dotest(root, False)
+
+        try:
+            xMeta.removeTextContent(None)
+            fail("removeTextContent(): None content allowed?")
+        except RuntimeException:
+            pass
+
+        xMeta.removeTextContent(xField1)
+
+        xAnchor = xMeta.getAnchor()
+        self.assertIsNotNone(xAnchor, "getAnchor(): None")
+
+        ## evil test case: insert ruby around meta
+        ruby = RubyNode(self.mkname("ruby"))
+        inserter.insertrange(Range(2, 6, ruby))
+
+        ## prevent caching...
+        # root = TreeNode()
+        # root.appendchild(TextNode("12"))
+        # root.appendchild(ruby.dup()
+                # .appendchild(meta.dup()
+                    # .appendchild(TextNode("45"))
+                    # .appendchild(field2.dup())))
+        # root.appendchild(TextNode("6789"))
+        # self.dotest(root, False)
+
+        xEnum = xMeta.createEnumeration()
+        self.assertIsNotNone("createEnumeration(): returns None", xEnum)
+
+        self.assertTrue(xEnum.hasMoreElements(),"hasNext(): first missing")
+        xPortion = xEnum.nextElement()
+        type_ = xPortion.TextPortionType
+        self.assertEqual("Text", type_, "first: not text")
+        txt = xPortion.getString()
+        self.assertEqual("45", txt, "first: text differs")
+
+        self.assertTrue(xEnum.hasMoreElements(),"hasNext(): second missing")
+        xPortion = xEnum.nextElement()
+        type_ = xPortion.TextPortionType
+        self.assertEqual("TextField", type_, "second: not text")
+
+        ## no ruby end here!!!
+        self.assertFalse(xEnum.hasMoreElements(), "hasNext(): more elements?")
+
+        xMeta.dispose()
+
+        try:
+            xCursor = xMeta.createTextCursor()
+            self.assertIsNone(xCursor,
+                        "createTextCursor(): succeeds on disposed object?")
+        except RuntimeException:
+            pass
+
+    # check that cursor move methods move to positions in the meta,
+    # but do not move to positions outside the meta.
+    def test_meta_xtextcursor(self):
+        xDoc = self.__class__.xDoc
+        inserter = RangeInserter(xDoc)
+        text = TextNode("Text. 12 More text here.")
+        inserter.insertrange(Range(0, 0, text))
+        met1 = MetaNode(self.mkid("id"))
+        xMeta = inserter.makemeta()
+
+        xDocText = xDoc.getText()
+        xDocTextCursor = xDocText.createTextCursor()
+        xDocTextCursor.goRight(7, False)
+        xDocTextCursor.goRight(2, True)
+        xDocText.insertTextContent(xDocTextCursor, xMeta, True)
+        xDocTextCursor.gotoStart(True)
+
+        xMeta.MetadataReference = met1.xmlid
+        xStart = xMeta.getStart()
+        self.assertIsNotNone(xStart, "getStart(): no start")
+        xEnd = xMeta.getEnd()
+        self.assertIsNotNone(xEnd, "getEnd(): no end")
+
+        ## XTextCursor
+        xMetaCursor = xMeta.createTextCursor()
+        self.assertIsNotNone(xMetaCursor, "createTextCursor(): no cursor")
+        bSuccess = False
+        xMetaCursor.gotoStart(False)
+        xMetaCursor.gotoEnd(False)
+        bSuccess = xMetaCursor.goLeft(1, False)
+        self.assertTrue(bSuccess, "goLeft(): failed")
+        bSuccess = xMetaCursor.goLeft(1000, False)
+        self.assertFalse(bSuccess, "goLeft(): succeeded")
+        bSuccess = xMetaCursor.goRight(1, False)
+        self.assertTrue(bSuccess, "goRight(): failed")
+        bSuccess = xMetaCursor.goRight(1000, False)
+        self.assertFalse(bSuccess, "goRight(): succeeded")
+        xMetaCursor.gotoRange(xStart, False)
+        xMetaCursor.gotoRange(xEnd, False)
+        try:
+            xMetaCursor.gotoRange(xDocTextCursor, False)
+            fail("gotoRange(): succeeded")
+        except RuntimeException:
+            pass
+
+        ## XWordCursor
+        xMeta.setString("Two words")
+        xMetaCursor.gotoStart(False)
+
+        bSuccess = xMetaCursor.gotoNextWord(True)  # at start of "words"
+        self.assertTrue(bSuccess, "gotoNextWord(): failed")
+
+        string = xMetaCursor.getString()
+        self.assertEqual("Two ", string, "gotoNextWord(): wrong string")
+
+        bSuccess = xMetaCursor.gotoNextWord(False)  # at end of "words", cannot leave metafield
+        self.assertFalse(bSuccess,"gotoNextWord(): succeeded")
+        xMetaCursor.collapseToEnd()
+        bSuccess = xMetaCursor.gotoPreviousWord(True)  # at start of "words"
+        self.assertTrue(bSuccess, "gotoPreviousWord(): failed")
+
+        string = xMetaCursor.getString()
+        self.assertEqual("words", string, "gotoPreviousWord(): wrong string")
+
+        bSuccess = xMetaCursor.gotoPreviousWord(False)  # at start of "Two"
+        self.assertTrue(bSuccess, "gotoPreviousWord(): failed")
+
+        bSuccess = xMetaCursor.gotoPreviousWord(False)  # cannot leave metafield
+        self.assertFalse(bSuccess, "gotoPreviousWord(): succeeded")
+
+        bSuccess = xMetaCursor.gotoEndOfWord(True)  # at end of "Two"
+        self.assertTrue(bSuccess, "gotoEndOfWord(): failed")
+
+        string = xMetaCursor.getString()
+        self.assertEqual("Two", string, "gotoEndOfWord(): wrong string")
+
+        xMetaCursor.gotoEnd(False)
+        bSuccess = xMetaCursor.gotoStartOfWord(True)
+        self.assertTrue(bSuccess, "gotoStartOfWord(): failed")
+
+        string = xMetaCursor.getString()
+        self.assertEqual("words", string, "gotoStartOfWord(): wrong string")
+
+        xMeta.setString("")
+        bSuccess = xMetaCursor.gotoEndOfWord(False)
+        self.assertFalse(bSuccess, "gotoEndOfWord(): succeeded")
+        bSuccess = xMetaCursor.gotoStartOfWord(False)
+        self.assertFalse(bSuccess, "gotoStartOfWord(): succeeded")
+
+        ## XSentenceCursor
+        xMeta.setString("This is a sentence. Another sentence.")
+        xMetaCursor.gotoStart(False)
+
+        bSuccess = xMetaCursor.gotoNextSentence(True)
+        self.assertTrue(bSuccess,"gotoNextSentence(): failed")
+
+        string = xMetaCursor.getString()
+        self.assertEqual("This is a sentence. ", string,
+                            "gotoNextSentence(): wrong string")
+
+        bSuccess = xMetaCursor.gotoNextSentence(False)
+        self.assertFalse(bSuccess, "gotoNextSentence(): succeeded")
+        ## FIXME:
+        ## the sentence cursor seems to work differently than the word cursor
+        xMeta.setString("This is a sentence. Another sentence. Sentence 3.")
+        xMetaCursor.gotoEnd(False)
+        bSuccess = xMetaCursor.gotoPreviousSentence(True)
+        self.assertTrue(bSuccess, "gotoPreviousSentence(): failed")
+
+        string = xMetaCursor.getString()
+        self.assertEqual("Another sentence. Sentence 3.", string,
+                                "gotoPreviousSentence(): wrong string")
+
+        bSuccess = xMetaCursor.gotoPreviousSentence(False)
+        self.assertFalse(bSuccess, "gotoPreviousSentence(): succeeded")
+        bSuccess = xMetaCursor.gotoEndOfSentence(True)
+        self.assertTrue(bSuccess, "gotoEndOfSentence(): failed")
+
+        string = xMetaCursor.getString()
+        self.assertEqual("This is a sentence.", string,
+                            "gotoEndOfSentence(): wrong string")
+
+        xMetaCursor.gotoEnd(False)
+        bSuccess = xMetaCursor.gotoStartOfSentence(True)
+        self.assertTrue(bSuccess,"gotoStartOfSentence(): failed")
+
+        string = xMetaCursor.getString()
+        self.assertEqual("Sentence 3.", string,
+                         "gotoStartOfSentence(): wrong string")
+
+        xMeta.setString("")
+        bSuccess = xMetaCursor.gotoEndOfSentence(False)
+        self.assertFalse(bSuccess, "gotoEndOfSentence(): succeeded")
+        bSuccess = xMetaCursor.gotoStartOfSentence(False)
+        self.assertFalse(bSuccess, "gotoStartOfSentence(): succeeded")
+
+        ## XParagraphCursor (does not make sense)
+        bSuccess = xMetaCursor.gotoNextParagraph(False)
+        self.assertFalse(bSuccess, "gotoNextParagraph(): succeeded")
+        bSuccess = xMetaCursor.gotoPreviousParagraph(False)
+        self.assertFalse(bSuccess, "gotoPreviousParagraph(): succeeded")
+        bSuccess = xMetaCursor.gotoStartOfParagraph(False)
+        self.assertFalse(bSuccess, "gotoStartOfParagraph(): succeeded")
+        bSuccess = xMetaCursor.gotoEndOfParagraph(False)
+        self.assertFalse(bSuccess, "gotoEndOfParagraph(): succeeded")
+
+    # See https://bugs.libreoffice.org/show_bug.cgi?id=49629
+    # ensure that gotoEndOfWord does not fail when footnote is at word end
+    def test_xtextcursor(self):
+        xDoc = self.__class__.xDoc
+        inserter = RangeInserter(xDoc)
+        xDocText = xDoc.getText()
+        xDocTextCursor = xDocText.createTextCursor()
+        xDocTextCursor.gotoNextParagraph(False)
+        inserter.inserttext(xDocTextCursor, "Text")
+        xDocTextCursor.gotoEndOfWord(False)
+        inserter.insertfootnote(xDocTextCursor, "footnote")
+        xDocTextCursor.gotoStartOfParagraph(False)
+        bSuccess = xDocTextCursor.gotoEndOfWord(True)
+        self.assertTrue(bSuccess, "gotoEndOfWord(): failed")
+        string = xDocTextCursor.getString()
+        self.assertEqual("Text", string, "gotoEndOfWord(): wrong string")
+        self.assertNotEqual("a","b")
+
     def dotest(self, intree, insert=True):
         xDoc = self.__class__.xDoc
         self._dotest(xDoc, intree, insert)


More information about the Libreoffice-commits mailing list