Ejemplo n.º 1
0
class TestTag(TestCase):
    '''Test for Basic Dom implementation'''
    def setUp(self):
        customElements.clear()
        self.tag = Tag()
        self.c1 = Tag(c="1")
        self.c2 = Tag(c="2")

    def test_name(self):
        self.assertEqual(self.tag.tag, 'tag')
        self.assertEqual(self.tag.tagName, 'TAG')
        self.assertEqual(self.tag.localName, 'tag')

        class A(Tag):
            tag = 'Atag'
        a = A()
        self.assertEqual(a.tag, 'Atag')
        self.assertEqual(a.tagName, 'ATAG')
        self.assertEqual(a.localName, 'atag')

    def test_tag_string(self):
        self.assertRegex(self.tag.html, '<tag rimo_id="\d+"></tag>')

    def test_attr_init(self):
        tag = Tag(attrs={'src': 'a'})
        self.assertRegex(tag.html, '<tag src="a" rimo_id="\d+"></tag>')
        tag.removeAttribute('src')
        self.assertRegex(tag.html, '<tag rimo_id="\d+"></tag>')

    def test_attr_atomic(self):
        # test add tag-attr
        self.tag['a'] = 'b'
        self.assertEqual(self.tag['a'], 'b')
        self.assertIn('a="b"', self.tag.html)
        self.assertRegex(self.tag.start_tag, '<tag rimo_id="\d+" a="b">')
        self.assertRegex(self.tag.html, '<tag rimo_id="\d+" a="b"></tag>')
        del self.tag['a']
        self.assertRegex(self.tag.html, '<tag rimo_id="\d+"></tag>')

    def test_attr_addremove(self):
        self.assertTrue(self.tag.hasAttributes())  # has id
        self.assertFalse(self.tag.hasAttribute('a'))
        self.tag.setAttribute('a', 'b')
        self.assertTrue(self.tag.hasAttributes())
        self.assertTrue(self.tag.hasAttribute('a'))
        self.assertIsFalse(self.tag.hasAttribute('b'))
        self.assertEqual('b', self.tag.getAttribute('a'))
        self.assertRegex(self.tag.html, r'<tag rimo_id="\d+" a="b"></tag>')
        self.assertEqual(self.tag.getAttribute('a'), 'b')
        self.tag.removeAttribute('a')
        self.assertTrue(self.tag.hasAttributes())
        self.assertFalse(self.tag.hasAttribute('a'))
        self.assertRegex(self.tag.html, '<tag rimo_id="\d+"></tag>')
        self.assertIsNone(self.tag.getAttribute('aaaa'))

    def test_attr_multi(self):
        self.tag.setAttribute('c', 'd')
        self.tag.setAttribute('e', 'f')
        self.assertIn('c="d" e="f"', self.tag.html)

    def test_attr_overwrite(self):
        self.tag.setAttribute('c', 'd')
        self.tag.setAttribute('e', 'f')
        self.tag.setAttribute('c', 'new_d')
        self.assertNotIn('c="d"', self.tag.html)
        self.assertIn('c="new_d"', self.tag.html)
        self.assertIn('e="f"', self.tag.html)

    def test_child_addremove(self):
        self.assertIsFalse(self.tag.hasChildNodes())
        self.tag.appendChild(self.c1)
        self.assertIsTrue(self.tag.hasChildNodes())
        self.assertRegex(
            self.tag.html,
            '<tag rimo_id="\d+"><tag c="1" rimo_id="\d+"></tag></tag>',
        )
        self.assertIn(self.c1, self.tag)
        self.tag.removeChild(self.c1)
        self.assertIsFalse(self.tag.hasChildNodes())
        self.assertNotIn(self.c1, self.tag)
        self.assertRegex(self.tag.html, '<tag rimo_id="\d+"></tag>')

    def test_child_exception(self) -> None:
        with self.assertRaises(ValueError):
            self.tag.removeChild(Tag())
        with self.assertRaises(ValueError):
            self.tag.replaceChild(Tag(), Tag())

    def test_first_last_child(self):
        self.assertIsNone(self.tag.firstChild)
        self.assertIsNone(self.tag.lastChild)
        self.tag.appendChild(self.c1)
        self.assertIs(self.tag.firstChild, self.c1)
        self.assertIs(self.tag.lastChild, self.c1)
        self.tag.appendChild(self.c2)
        self.assertIs(self.tag.firstChild, self.c1)
        self.assertIs(self.tag.lastChild, self.c2)

    def test_child_deep(self):
        self.tag.appendChild(self.c1)
        self.c1.appendChild(self.c2)
        self.assertNotIn(self.c2, self.tag)
        self.assertIn(self.c2, self.c1)
        self.assertRegex(
            self.tag.html,
            '<tag rimo_id="\d+"><tag c="1" rimo_id="\d+">'
            '<tag c="2" rimo_id="\d+"></tag></tag></tag>',
        )

    def test_child_nodes(self):
        self.tag.appendChild(self.c1)
        self.tag.appendChild(self.c2)
        self.assertEqual(len(self.tag.childNodes), 2)
        self.assertIs(self.tag.childNodes[0], self.c1)
        self.assertIs(self.tag.childNodes[1], self.c2)

    def test_child_replace(self):
        self.tag.append(self.c1)
        self.assertIn(self.c1, self.tag)
        self.assertNotIn(self.c2, self.tag)
        self.assertRegex(
            self.tag.html,
            '<tag rimo_id="\d+"><tag c="1" rimo_id="\d+"></tag></tag>',
        )

        self.tag.replaceChild(self.c2, self.c1)
        self.assertNotIn(self.c1, self.tag)
        self.assertIn(self.c2, self.tag)
        self.assertRegex(
            self.tag.html,
            '<tag rimo_id="\d+"><tag c="2" rimo_id="\d+"></tag></tag>',
        )

    def test_text_addremove(self):
        self.tag.textContent = 'text'
        self.assertIsTrue(self.tag.hasChildNodes())
        self.assertRegex(self.tag.html, '<tag rimo_id="\d+">text</tag>')
        # self.assertIn('text', self.tag)
        self.assertEqual(self.tag[0].parentNode, self.tag)

        self.tag.textContent = ''
        self.assertIsFalse(self.tag.hasChildNodes())
        self.assertRegex(self.tag.html, '<tag rimo_id="\d+"></tag>')

    def test_textcontent(self):
        self.assertEqual(self.tag.textContent, '')
        self.tag.textContent = 'a'
        self.assertEqual(self.tag.textContent, 'a')
        self.assertRegex(self.tag.html, '<tag rimo_id="\d+">a</tag>')
        self.tag.textContent = 'b'
        self.assertEqual(self.tag.textContent, 'b')
        self.assertRegex(self.tag.html, '<tag rimo_id="\d+">b</tag>')

    def test_textcontent_child(self):
        self.tag.textContent = 'a'
        self.tag.appendChild(self.c1)
        self.assertRegex(
            self.tag.html,
            '<tag rimo_id="\d+">a<tag c="1" rimo_id="\d+"></tag></tag>',
        )
        self.c1.textContent = 'c1'
        self.assertRegex(
            self.tag.html,
            '<tag rimo_id="\d+">a<tag c="1" rimo_id="\d+">c1</tag></tag>',
        )
        self.assertEqual('ac1', self.tag.textContent)
        self.tag.textContent = 'b'
        self.assertEqual(self.tag.length, 1)
        self.assertRegex(self.tag.html, '<tag rimo_id="\d+">b</tag>')
        self.assertIsNone(self.c1.parentNode)

    def test_closing_tag(self):
        class Img(Tag):
            tag = 'img'
        img = Img()
        self.assertRegex(img.html, '<img rimo_id="\d+">')
        img.setAttribute('src', 'a')
        self.assertRegex(img.html, '<img rimo_id="\d+" src="a">')

    def _test_shallow_copy(self, clone):
        self.assertIsTrue(self.tag.hasChildNodes())
        self.assertIsFalse(clone.hasChildNodes())
        self.assertEqual(len(clone), 0)
        self.assertRegex(
            clone.html,
            '<tag rimo_id="\d+" src="a" class="b"></tag>',
        )

        self.assertIsTrue(clone.hasAttributes())
        self.assertEqual(clone.getAttribute('src'), 'a')
        clone.setAttribute('src', 'b')
        self.assertEqual(clone.getAttribute('src'), 'b')
        self.assertEqual(self.tag.getAttribute('src'), 'a')

        self.assertIsTrue(clone.hasClass('b'))
        self.assertEqual(clone.getAttribute('class'), 'b')
        clone.setAttribute('class', 'c')
        self.assertEqual(clone.getAttribute('class'), 'c')
        self.assertEqual(self.tag.getAttribute('class'), 'b')

        clone.append(self.c2)
        self.assertIsTrue(clone.hasChildNodes())
        self.assertIn(self.c2, clone)
        self.assertNotIn(self.c2, self.tag)

    def test_copy(self):
        from copy import copy
        self.tag.appendChild(self.c1)
        self.tag.setAttribute('src', 'a')
        self.tag.setAttribute('class', 'b')
        clone = copy(self.tag)
        self._test_shallow_copy(clone)

    def test_clone_node_sharrow(self):
        self.tag.appendChild(self.c1)
        self.tag.setAttribute('src', 'a')
        self.tag.setAttribute('class', 'b')
        clone = self.tag.cloneNode()
        self._test_shallow_copy(clone)

        clone2 = self.tag.cloneNode(deep=False)
        self._test_shallow_copy(clone2)

    def _test_deep_copy(self, clone):
        self.assertIsTrue(clone.hasChildNodes())
        self.assertEqual(len(clone), 1)
        self.assertIn(self.c1, self.tag)
        self.assertNotIn(self.c1, clone)

        self.c1.setAttribute('src', 'b')
        self.assertEqual(self.c1.getAttribute('src'), 'b')
        self.assertIsNone(clone[0].getAttribute('src'))

        self.c1.setAttribute('class', 'c')
        self.assertEqual(self.c1.getAttribute('class'), 'c')
        self.assertIsNone(clone[0].getAttribute('class'))

        clone.append(self.c2)
        self.assertEqual(len(clone), 2)
        self.assertEqual(len(self.tag), 1)

    def test_deepcopy(self):
        from copy import deepcopy
        self.tag.append(self.c1)
        self.tag.setAttribute('src', 'a')
        self.tag.setAttribute('class', 'b')
        clone = deepcopy(self.tag)
        self._test_deep_copy(clone)

    def test_clone_node_deep(self):
        self.tag.append(self.c1)
        self.tag.setAttribute('src', 'a')
        self.tag.setAttribute('class', 'b')
        clone = self.tag.cloneNode(deep=True)
        self._test_deep_copy(clone)

    def test_siblings(self):
        self.tag.appendChild(self.c1)
        self.tag.appendChild(self.c2)
        self.assertIsNone(self.tag.previousSibling)
        self.assertIsNone(self.tag.nextSibling)
        self.assertIsNone(self.c1.previousSibling)
        self.assertIs(self.c2.previousSibling, self.c1)
        self.assertIs(self.c1.nextSibling, self.c2)
        self.assertIsNone(self.c2.nextSibling)

    def test_get_elements_by_tagname(self):
        A = NewTagClass('A', 'a')
        B = NewTagClass('B', 'b')
        a1 = A(src='a1')
        a2 = A(src='a2')
        b1 = B(src='b1')
        b2 = B(src='b2')
        self.tag.appendChild(a1)
        self.tag.appendChild(a2)
        self.tag.appendChild(b1)
        b1.appendChild(b2)

        a_list = self.tag.getElementsByTagName('a')
        self.assertEqual(len(a_list), 2)
        self.assertIs(a_list[0], a1)
        self.assertIs(a_list[1], a2)

        b_list = self.tag.getElementsByTagName('b')
        self.assertEqual(len(b_list), 2)
        self.assertIs(b_list[0], b1)
        self.assertIs(b_list[1], b2)

        b_sub_list = b1.getElementsByTagName('b')
        self.assertEqual(len(b_sub_list), 1)
        self.assertIs(b_sub_list[0], b2)

    class NewTag(Tag):
        tag = 'new-tag'

    def test_custom_tag(self):
        self.tag.innerHTML = '<new-tag></new-tag>'
        self.assertEqual(type(self.tag.firstChild), HTMLElement)
        self.assertFalse(self.tag.firstChild._registered)
        customElements.define('new-tag', self.NewTag)
        self.assertEqual(type(self.tag.firstChild), self.NewTag)
        self.assertTrue(self.tag.firstChild._registered)

    def test_custom_tag_registered(self):
        customElements.define('new-tag', self.NewTag)
        self.c1.innerHTML = '<new-tag></new-tag>'
        self.assertTrue(isinstance(self.c1.firstChild, self.NewTag))
        self.assertTrue(self.c1.firstChild._registered)

    class ExtendTag(Tag):
        tag = 'a'
        is_ = 'new-a'

    def test_custom_tag_is(self):
        self.tag.innerHTML = '<a is="new-a"></a>'
        self.assertEqual(type(self.tag.firstChild), HTMLElement)
        self.assertFalse(self.tag.firstChild._registered)
        customElements.define('new-a', self.NewTag, {'extends': 'a'})
        self.assertEqual(type(self.tag.firstChild), self.NewTag)
        self.assertTrue(self.tag.firstChild._registered)

    def test_custom_tag_is_registered(self):
        customElements.define('new-a', self.ExtendTag, {'extends': 'a'})
        self.tag.innerHTML = '<a is="new-a"></a>'
        self.assertEqual(type(self.tag.firstChild), self.ExtendTag)
        self.assertTrue(self.tag.firstChild._registered)

        # test unregistered `is`
        self.tag.innerHTML = '<a is="new-b"></a>'
        self.assertEqual(type(self.tag.firstChild), HTMLElement)
        self.assertFalse(self.tag.firstChild._registered)

    def test_custom_tag_define_by_class(self):
        customElements.define(self.NewTag)
        self.tag.innerHTML = '<new-tag></new-tag>'
        self.assertEqual(type(self.tag.firstChild), self.NewTag)

    def test_custom_tag_define_by_class_is(self):
        customElements.define(self.ExtendTag)
        self.tag.innerHTML = '<a is="new-a"></a>'
        self.assertEqual(type(self.tag.firstChild), self.ExtendTag)
Ejemplo n.º 2
0
class TestTag(TestCase):
    '''Test for Basic Dom implementation'''
    def setUp(self):
        customElements.clear()
        self.tag = Tag()
        self.c1 = Tag(c="1")
        self.c2 = Tag(c="2")

    def test_name(self):
        self.assertEqual(self.tag.tag, 'tag')
        self.assertEqual(self.tag.tagName, 'TAG')
        self.assertEqual(self.tag.localName, 'tag')

        class A(Tag):
            tag = 'Atag'

        a = A()
        self.assertEqual(a.tag, 'Atag')
        self.assertEqual(a.tagName, 'ATAG')
        self.assertEqual(a.localName, 'atag')

    def test_tag_string(self):
        self.assertRegex(self.tag.html, '<tag wdom_id="\d+"></tag>')

    def test_attr_init(self):
        tag = Tag(attrs={'src': 'a'})
        self.assertRegex(tag.html, '<tag wdom_id="\d+" src="a"></tag>')
        tag.removeAttribute('src')
        self.assertRegex(tag.html, '<tag wdom_id="\d+"></tag>')

    def test_attr_addremove(self):
        self.assertFalse(self.tag.hasAttributes())  # wdom_id is not attribute
        self.assertFalse(self.tag.hasAttribute('a'))
        self.tag.setAttribute('a', 'b')
        self.assertTrue(self.tag.hasAttributes())
        self.assertTrue(self.tag.hasAttribute('a'))
        self.assertIsFalse(self.tag.hasAttribute('b'))
        self.assertEqual('b', self.tag.getAttribute('a'))
        self.assertRegex(self.tag.html, r'<tag wdom_id="\d+" a="b"></tag>')
        self.assertEqual(self.tag.getAttribute('a'), 'b')
        self.tag.removeAttribute('a')
        self.assertFalse(self.tag.hasAttributes())  # wdom_id is not attribute
        self.assertFalse(self.tag.hasAttribute('a'))
        self.assertRegex(self.tag.html, '<tag wdom_id="\d+"></tag>')
        self.assertIsNone(self.tag.getAttribute('aaaa'))

    def test_attr_multi(self):
        self.tag.setAttribute('c', 'd')
        self.tag.setAttribute('e', 'f')
        self.assertIn('c="d" e="f"', self.tag.html)

    def test_attr_overwrite(self):
        self.tag.setAttribute('c', 'd')
        self.tag.setAttribute('e', 'f')
        self.tag.setAttribute('c', 'new_d')
        self.assertNotIn('c="d"', self.tag.html)
        self.assertIn('c="new_d"', self.tag.html)
        self.assertIn('e="f"', self.tag.html)

    def test_child_addremove(self):
        self.assertIsFalse(self.tag.hasChildNodes())
        self.tag.appendChild(self.c1)
        self.assertIsTrue(self.tag.hasChildNodes())
        self.assertRegex(
            self.tag.html,
            '<tag wdom_id="\d+"><tag wdom_id="\d+" c="1"></tag></tag>',
        )
        self.assertIn(self.c1, self.tag)
        self.tag.removeChild(self.c1)
        self.assertIsFalse(self.tag.hasChildNodes())
        self.assertNotIn(self.c1, self.tag)
        self.assertRegex(self.tag.html, '<tag wdom_id="\d+"></tag>')

    def test_child_exception(self) -> None:
        with self.assertRaises(ValueError):
            self.tag.removeChild(Tag())
        with self.assertRaises(ValueError):
            self.tag.replaceChild(Tag(), Tag())

    def test_first_last_child(self):
        self.assertIsNone(self.tag.firstChild)
        self.assertIsNone(self.tag.lastChild)
        self.tag.appendChild(self.c1)
        self.assertIs(self.tag.firstChild, self.c1)
        self.assertIs(self.tag.lastChild, self.c1)
        self.tag.appendChild(self.c2)
        self.assertIs(self.tag.firstChild, self.c1)
        self.assertIs(self.tag.lastChild, self.c2)

    def test_child_deep(self):
        self.tag.appendChild(self.c1)
        self.c1.appendChild(self.c2)
        self.assertNotIn(self.c2, self.tag)
        self.assertIn(self.c2, self.c1)
        self.assertRegex(
            self.tag.html,
            '<tag wdom_id="\d+"><tag wdom_id="\d+" c="1">'
            '<tag wdom_id="\d+" c="2"></tag></tag></tag>',
        )

    def test_child_nodes(self):
        self.tag.appendChild(self.c1)
        self.tag.appendChild(self.c2)
        self.assertEqual(len(self.tag.childNodes), 2)
        self.assertIs(self.tag.childNodes[0], self.c1)
        self.assertIs(self.tag.childNodes[1], self.c2)

    def test_child_replace(self):
        self.tag.append(self.c1)
        self.assertIn(self.c1, self.tag)
        self.assertNotIn(self.c2, self.tag)
        self.assertRegex(
            self.tag.html,
            '<tag wdom_id="\d+"><tag wdom_id="\d+" c="1"></tag></tag>',
        )

        self.tag.replaceChild(self.c2, self.c1)
        self.assertNotIn(self.c1, self.tag)
        self.assertIn(self.c2, self.tag)
        self.assertRegex(
            self.tag.html,
            '<tag wdom_id="\d+"><tag wdom_id="\d+" c="2"></tag></tag>',
        )

    def test_text_addremove(self):
        self.tag.textContent = 'text'
        self.assertIsTrue(self.tag.hasChildNodes())
        self.assertRegex(self.tag.html, '<tag wdom_id="\d+">text</tag>')
        # self.assertIn('text', self.tag)
        self.assertEqual(self.tag[0].parentNode, self.tag)

        self.tag.textContent = ''
        self.assertIsFalse(self.tag.hasChildNodes())
        self.assertRegex(self.tag.html, '<tag wdom_id="\d+"></tag>')

    def test_textcontent(self):
        self.assertEqual(self.tag.textContent, '')
        self.tag.textContent = 'a'
        self.assertEqual(self.tag.textContent, 'a')
        self.assertRegex(self.tag.html, '<tag wdom_id="\d+">a</tag>')
        self.tag.textContent = 'b'
        self.assertEqual(self.tag.textContent, 'b')
        self.assertRegex(self.tag.html, '<tag wdom_id="\d+">b</tag>')

    def test_textcontent_child(self):
        self.tag.textContent = 'a'
        self.tag.appendChild(self.c1)
        self.assertRegex(self.tag.html, 'wdom_id="\d+">a<tag .*wdom_id="\d+"')
        self.assertEqual(self.tag.html_noid, '<tag>a<tag c="1"></tag></tag>')
        self.c1.textContent = 'c1'
        self.assertRegex(self.tag.html_noid, '<tag>a<tag c="1">c1</tag></tag>')
        self.assertEqual('ac1', self.tag.textContent)
        self.tag.textContent = 'b'
        self.assertEqual(self.tag.length, 1)
        self.assertRegex(self.tag.html, '<tag wdom_id="\d+">b</tag>')
        self.assertIsNone(self.c1.parentNode)

    def test_closing_tag(self):
        class Img(Tag):
            tag = 'img'

        img = Img()
        self.assertRegex(img.html, '<img wdom_id="\d+">')
        img.setAttribute('src', 'a')
        self.assertRegex(img.html, 'wdom_id="\d+"')
        self.assertEqual(img.html_noid, '<img src="a">')

    def _test_shallow_copy(self, clone):
        self.assertIsTrue(self.tag.hasChildNodes())
        self.assertIsFalse(clone.hasChildNodes())
        self.assertEqual(len(clone), 0)
        self.assertRegex(clone.html, 'wdom_id="\d+"')
        self.assertEqual(clone.html_noid, '<tag src="a" class="b"></tag>')

        self.assertIsTrue(clone.hasAttributes())
        self.assertEqual(clone.getAttribute('src'), 'a')
        clone.setAttribute('src', 'b')
        self.assertEqual(clone.getAttribute('src'), 'b')
        self.assertEqual(self.tag.getAttribute('src'), 'a')

        self.assertIsTrue(clone.hasClass('b'))
        self.assertEqual(clone.getAttribute('class'), 'b')
        clone.setAttribute('class', 'c')
        self.assertEqual(clone.getAttribute('class'), 'c')
        self.assertEqual(self.tag.getAttribute('class'), 'b')

        clone.append(self.c2)
        self.assertIsTrue(clone.hasChildNodes())
        self.assertIn(self.c2, clone)
        self.assertNotIn(self.c2, self.tag)

    def test_copy(self):
        from copy import copy
        self.tag.appendChild(self.c1)
        self.tag.setAttribute('src', 'a')
        self.tag.setAttribute('class', 'b')
        clone = copy(self.tag)
        self._test_shallow_copy(clone)

    def test_clone_node_sharrow(self):
        self.tag.appendChild(self.c1)
        self.tag.setAttribute('src', 'a')
        self.tag.setAttribute('class', 'b')
        clone = self.tag.cloneNode()
        self._test_shallow_copy(clone)

        clone2 = self.tag.cloneNode(deep=False)
        self._test_shallow_copy(clone2)

    def _test_deep_copy(self, clone):
        self.assertIsTrue(clone.hasChildNodes())
        self.assertEqual(len(clone), 1)
        self.assertIn(self.c1, self.tag)
        self.assertNotIn(self.c1, clone)

        self.c1.setAttribute('src', 'b')
        self.assertEqual(self.c1.getAttribute('src'), 'b')
        self.assertIsNone(clone[0].getAttribute('src'))

        self.c1.setAttribute('class', 'c')
        self.assertEqual(self.c1.getAttribute('class'), 'c')
        self.assertIsNone(clone[0].getAttribute('class'))

        clone.append(self.c2)
        self.assertEqual(len(clone), 2)
        self.assertEqual(len(self.tag), 1)

    def test_deepcopy(self):
        from copy import deepcopy
        self.tag.append(self.c1)
        self.tag.setAttribute('src', 'a')
        self.tag.setAttribute('class', 'b')
        clone = deepcopy(self.tag)
        self._test_deep_copy(clone)

    def test_clone_node_deep(self):
        self.tag.append(self.c1)
        self.tag.setAttribute('src', 'a')
        self.tag.setAttribute('class', 'b')
        clone = self.tag.cloneNode(deep=True)
        self._test_deep_copy(clone)

    def test_clone_style(self):
        self.tag.style = 'color: red;'
        clone = self.tag.cloneNode()
        self.assertEqual(clone.html_noid, self.tag.html_noid)

    def test_siblings(self):
        self.tag.appendChild(self.c1)
        self.tag.appendChild(self.c2)
        self.assertIsNone(self.tag.previousSibling)
        self.assertIsNone(self.tag.nextSibling)
        self.assertIsNone(self.c1.previousSibling)
        self.assertIs(self.c2.previousSibling, self.c1)
        self.assertIs(self.c1.nextSibling, self.c2)
        self.assertIsNone(self.c2.nextSibling)

    def test_get_elements_by_tagname(self):
        A = NewTagClass('A', 'a')
        B = NewTagClass('B', 'b')
        a1 = A(src='a1')
        a2 = A(src='a2')
        b1 = B(src='b1')
        b2 = B(src='b2')
        self.tag.appendChild(a1)
        self.tag.appendChild(a2)
        self.tag.appendChild(b1)
        b1.appendChild(b2)

        a_list = self.tag.getElementsByTagName('a')
        self.assertEqual(len(a_list), 2)
        self.assertIs(a_list[0], a1)
        self.assertIs(a_list[1], a2)

        b_list = self.tag.getElementsByTagName('b')
        self.assertEqual(len(b_list), 2)
        self.assertIs(b_list[0], b1)
        self.assertIs(b_list[1], b2)

        b_sub_list = b1.getElementsByTagName('b')
        self.assertEqual(len(b_sub_list), 1)
        self.assertIs(b_sub_list[0], b2)

    class NewTag(Tag):
        tag = 'new-tag'

    def test_custom_tag(self):
        self.tag.innerHTML = '<new-tag></new-tag>'
        self.assertEqual(type(self.tag.firstChild), WdomElement)
        self.assertFalse(self.tag.firstChild._registered)
        customElements.define('new-tag', self.NewTag)
        self.assertEqual(type(self.tag.firstChild), self.NewTag)
        self.assertTrue(self.tag.firstChild._registered)

    def test_custom_tag_registered(self):
        customElements.define('new-tag', self.NewTag)
        self.c1.innerHTML = '<new-tag></new-tag>'
        self.assertTrue(isinstance(self.c1.firstChild, self.NewTag))
        self.assertTrue(self.c1.firstChild._registered)

    class ExtendTag(Tag):
        tag = 'a'
        is_ = 'new-a'

    def test_custom_tag_is(self):
        self.tag.innerHTML = '<a is="new-a"></a>'
        self.assertEqual(type(self.tag.firstChild), WdomElement)
        self.assertFalse(self.tag.firstChild._registered)
        customElements.define('new-a', self.NewTag, {'extends': 'a'})
        self.assertEqual(type(self.tag.firstChild), self.NewTag)
        self.assertTrue(self.tag.firstChild._registered)

    def test_custom_tag_is_registered(self):
        customElements.define('new-a', self.ExtendTag, {'extends': 'a'})
        self.tag.innerHTML = '<a is="new-a"></a>'
        self.assertEqual(type(self.tag.firstChild), self.ExtendTag)
        self.assertTrue(self.tag.firstChild._registered)

        # test unregistered `is`
        self.tag.innerHTML = '<a is="new-b"></a>'
        self.assertEqual(type(self.tag.firstChild), WdomElement)
        self.assertFalse(self.tag.firstChild._registered)

    def test_custom_tag_define_by_class(self):
        customElements.define(self.NewTag)
        self.tag.innerHTML = '<new-tag></new-tag>'
        self.assertEqual(type(self.tag.firstChild), self.NewTag)

    def test_custom_tag_define_by_class_is(self):
        customElements.define(self.ExtendTag)
        self.tag.innerHTML = '<a is="new-a"></a>'
        self.assertEqual(type(self.tag.firstChild), self.ExtendTag)