A Python parser for MediaWiki wikicode https://mwparserfromhell.readthedocs.io/
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

test_tag.py 15 KiB

10 anos atrás
10 anos atrás
10 anos atrás
10 anos atrás
10 anos atrás
10 anos atrás
10 anos atrás
10 anos atrás
10 anos atrás
10 anos atrás
10 anos atrás
10 anos atrás
10 anos atrás
10 anos atrás
10 anos atrás
10 anos atrás
10 anos atrás
10 anos atrás
10 anos atrás
10 anos atrás
10 anos atrás
10 anos atrás
10 anos atrás
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. # Copyright (C) 2012-2020 Ben Kurtovic <ben.kurtovic@gmail.com>
  2. #
  3. # Permission is hereby granted, free of charge, to any person obtaining a copy
  4. # of this software and associated documentation files (the "Software"), to deal
  5. # in the Software without restriction, including without limitation the rights
  6. # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. # copies of the Software, and to permit persons to whom the Software is
  8. # furnished to do so, subject to the following conditions:
  9. #
  10. # The above copyright notice and this permission notice shall be included in
  11. # all copies or substantial portions of the Software.
  12. #
  13. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18. # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  19. # SOFTWARE.
  20. import pytest
  21. from mwparserfromhell.nodes import Tag, Template, Text
  22. from mwparserfromhell.nodes.extras import Attribute
  23. from ._test_tree_equality import TreeEqualityTestCase, wrap, wraptext
  24. agen = lambda name, value: Attribute(wraptext(name), wraptext(value))
  25. agennv = lambda name: Attribute(wraptext(name))
  26. agennq = lambda name, value: Attribute(wraptext(name), wraptext(value), None)
  27. agenp = lambda name, v, a, b, c: Attribute(wraptext(name), v, '"', a, b, c)
  28. agenpnv = lambda name, a, b, c: Attribute(wraptext(name), None, '"', a, b, c)
  29. class TestTag(TreeEqualityTestCase):
  30. """Test cases for the Tag node."""
  31. def test_str(self):
  32. """test Tag.__str__()"""
  33. node1 = Tag(wraptext("ref"))
  34. node2 = Tag(wraptext("span"), wraptext("foo"),
  35. [agen("style", "color: red;")])
  36. node3 = Tag(wraptext("ref"),
  37. attrs=[agennq("name", "foo"),
  38. agenpnv("some_attr", " ", "", "")],
  39. self_closing=True)
  40. node4 = Tag(wraptext("br"), self_closing=True, padding=" ")
  41. node5 = Tag(wraptext("br"), self_closing=True, implicit=True)
  42. node6 = Tag(wraptext("br"), self_closing=True, invalid=True,
  43. implicit=True)
  44. node7 = Tag(wraptext("br"), self_closing=True, invalid=True,
  45. padding=" ")
  46. node8 = Tag(wraptext("hr"), wiki_markup="----", self_closing=True)
  47. node9 = Tag(wraptext("i"), wraptext("italics!"), wiki_markup="''")
  48. assert "<ref></ref>" == str(node1)
  49. assert '<span style="color: red;">foo</span>' == str(node2)
  50. assert "<ref name=foo some_attr/>" == str(node3)
  51. assert "<br />" == str(node4)
  52. assert "<br>" == str(node5)
  53. assert "</br>" == str(node6)
  54. assert "</br />" == str(node7)
  55. assert "----" == str(node8)
  56. assert "''italics!''" == str(node9)
  57. def test_children(self):
  58. """test Tag.__children__()"""
  59. # <ref>foobar</ref>
  60. node1 = Tag(wraptext("ref"), wraptext("foobar"))
  61. # '''bold text'''
  62. node2 = Tag(wraptext("b"), wraptext("bold text"), wiki_markup="'''")
  63. # <img id="foo" class="bar" selected />
  64. node3 = Tag(wraptext("img"),
  65. attrs=[agen("id", "foo"), agen("class", "bar"),
  66. agennv("selected")],
  67. self_closing=True, padding=" ")
  68. gen1 = node1.__children__()
  69. gen2 = node2.__children__()
  70. gen3 = node3.__children__()
  71. assert node1.tag == next(gen1)
  72. assert node3.tag == next(gen3)
  73. assert node3.attributes[0].name == next(gen3)
  74. assert node3.attributes[0].value == next(gen3)
  75. assert node3.attributes[1].name == next(gen3)
  76. assert node3.attributes[1].value == next(gen3)
  77. assert node3.attributes[2].name == next(gen3)
  78. assert node1.contents == next(gen1)
  79. assert node2.contents == next(gen2)
  80. assert node1.closing_tag == next(gen1)
  81. with pytest.raises(StopIteration):
  82. next(gen1)
  83. with pytest.raises(StopIteration):
  84. next(gen2)
  85. with pytest.raises(StopIteration):
  86. next(gen3)
  87. def test_strip(self):
  88. """test Tag.__strip__()"""
  89. node1 = Tag(wraptext("i"), wraptext("foobar"))
  90. node2 = Tag(wraptext("math"), wraptext("foobar"))
  91. node3 = Tag(wraptext("br"), self_closing=True)
  92. assert "foobar" == node1.__strip__()
  93. assert None == node2.__strip__()
  94. assert None == node3.__strip__()
  95. def test_showtree(self):
  96. """test Tag.__showtree__()"""
  97. output = []
  98. getter, marker = object(), object()
  99. get = lambda code: output.append((getter, code))
  100. mark = lambda: output.append(marker)
  101. node1 = Tag(wraptext("ref"), wraptext("text"),
  102. [agen("name", "foo"), agennv("selected")])
  103. node2 = Tag(wraptext("br"), self_closing=True, padding=" ")
  104. node3 = Tag(wraptext("br"), self_closing=True, invalid=True,
  105. implicit=True, padding=" ")
  106. node1.__showtree__(output.append, get, mark)
  107. node2.__showtree__(output.append, get, mark)
  108. node3.__showtree__(output.append, get, mark)
  109. valid = [
  110. "<", (getter, node1.tag), (getter, node1.attributes[0].name),
  111. " = ", marker, (getter, node1.attributes[0].value),
  112. (getter, node1.attributes[1].name), ">", (getter, node1.contents),
  113. "</", (getter, node1.closing_tag), ">", "<", (getter, node2.tag),
  114. "/>", "</", (getter, node3.tag), ">"]
  115. assert valid == output
  116. def test_tag(self):
  117. """test getter/setter for the tag attribute"""
  118. tag = wraptext("ref")
  119. node = Tag(tag, wraptext("text"))
  120. assert tag is node.tag
  121. assert tag is node.closing_tag
  122. node.tag = "span"
  123. self.assertWikicodeEqual(wraptext("span"), node.tag)
  124. self.assertWikicodeEqual(wraptext("span"), node.closing_tag)
  125. assert "<span>text</span>" == node
  126. def test_contents(self):
  127. """test getter/setter for the contents attribute"""
  128. contents = wraptext("text")
  129. node = Tag(wraptext("ref"), contents)
  130. assert contents is node.contents
  131. node.contents = "text and a {{template}}"
  132. parsed = wrap([Text("text and a "), Template(wraptext("template"))])
  133. self.assertWikicodeEqual(parsed, node.contents)
  134. assert "<ref>text and a {{template}}</ref>" == node
  135. def test_attributes(self):
  136. """test getter for the attributes attribute"""
  137. attrs = [agen("name", "bar")]
  138. node1 = Tag(wraptext("ref"), wraptext("foo"))
  139. node2 = Tag(wraptext("ref"), wraptext("foo"), attrs)
  140. assert [] == node1.attributes
  141. assert attrs is node2.attributes
  142. def test_wiki_markup(self):
  143. """test getter/setter for the wiki_markup attribute"""
  144. node = Tag(wraptext("i"), wraptext("italic text"))
  145. assert None is node.wiki_markup
  146. node.wiki_markup = "''"
  147. assert "''" == node.wiki_markup
  148. assert "''italic text''" == node
  149. node.wiki_markup = False
  150. assert node.wiki_markup is None
  151. assert "<i>italic text</i>" == node
  152. def test_self_closing(self):
  153. """test getter/setter for the self_closing attribute"""
  154. node = Tag(wraptext("ref"), wraptext("foobar"))
  155. assert node.self_closing is False
  156. node.self_closing = True
  157. assert node.self_closing is True
  158. assert "<ref/>" == node
  159. node.self_closing = 0
  160. assert node.self_closing is False
  161. assert "<ref>foobar</ref>" == node
  162. def test_invalid(self):
  163. """test getter/setter for the invalid attribute"""
  164. node = Tag(wraptext("br"), self_closing=True, implicit=True)
  165. assert node.invalid is False
  166. node.invalid = True
  167. assert node.invalid is True
  168. assert "</br>" == node
  169. node.invalid = 0
  170. assert node.invalid is False
  171. assert "<br>" == node
  172. def test_implicit(self):
  173. """test getter/setter for the implicit attribute"""
  174. node = Tag(wraptext("br"), self_closing=True)
  175. assert node.implicit is False
  176. node.implicit = True
  177. assert node.implicit is True
  178. assert "<br>" == node
  179. node.implicit = 0
  180. assert node.implicit is False
  181. assert "<br/>" == node
  182. def test_padding(self):
  183. """test getter/setter for the padding attribute"""
  184. node = Tag(wraptext("ref"), wraptext("foobar"))
  185. assert "" == node.padding
  186. node.padding = " "
  187. assert " " == node.padding
  188. assert "<ref >foobar</ref>" == node
  189. node.padding = None
  190. assert "" == node.padding
  191. assert "<ref>foobar</ref>" == node
  192. with pytest.raises(ValueError):
  193. node.__setattr__("padding", True)
  194. def test_closing_tag(self):
  195. """test getter/setter for the closing_tag attribute"""
  196. tag = wraptext("ref")
  197. node = Tag(tag, wraptext("foobar"))
  198. assert tag is node.closing_tag
  199. node.closing_tag = "ref {{ignore me}}"
  200. parsed = wrap([Text("ref "), Template(wraptext("ignore me"))])
  201. self.assertWikicodeEqual(parsed, node.closing_tag)
  202. assert "<ref>foobar</ref {{ignore me}}>" == node
  203. def test_wiki_style_separator(self):
  204. """test getter/setter for wiki_style_separator attribute"""
  205. node = Tag(wraptext("table"), wraptext("\n"))
  206. assert None is node.wiki_style_separator
  207. node.wiki_style_separator = "|"
  208. assert "|" == node.wiki_style_separator
  209. node.wiki_markup = "{"
  210. assert "{|\n{" == node
  211. node2 = Tag(wraptext("table"), wraptext("\n"), wiki_style_separator="|")
  212. assert "|" == node2.wiki_style_separator
  213. def test_closing_wiki_markup(self):
  214. """test getter/setter for closing_wiki_markup attribute"""
  215. node = Tag(wraptext("table"), wraptext("\n"))
  216. assert None is node.closing_wiki_markup
  217. node.wiki_markup = "{|"
  218. assert "{|" == node.closing_wiki_markup
  219. node.closing_wiki_markup = "|}"
  220. assert "|}" == node.closing_wiki_markup
  221. assert "{|\n|}" == node
  222. node.wiki_markup = "!!"
  223. assert "|}" == node.closing_wiki_markup
  224. assert "!!\n|}" == node
  225. node.wiki_markup = False
  226. assert node.closing_wiki_markup is None
  227. assert "<table>\n</table>" == node
  228. node2 = Tag(wraptext("table"), wraptext("\n"),
  229. attrs=[agen("id", "foo")], wiki_markup="{|",
  230. closing_wiki_markup="|}")
  231. assert "|}" == node2.closing_wiki_markup
  232. assert '{| id="foo"\n|}' == node2
  233. def test_has(self):
  234. """test Tag.has()"""
  235. node = Tag(wraptext("ref"), wraptext("cite"), [agen("name", "foo")])
  236. assert node.has("name") is True
  237. assert node.has(" name ") is True
  238. assert node.has(wraptext("name")) is True
  239. assert node.has("Name") is False
  240. assert node.has("foo") is False
  241. attrs = [agen("id", "foo"), agenp("class", "bar", " ", "\n", "\n"),
  242. agen("foo", "bar"), agenpnv("foo", " ", " \n ", " \t")]
  243. node2 = Tag(wraptext("div"), attrs=attrs, self_closing=True)
  244. assert node2.has("id") is True
  245. assert node2.has("class") is True
  246. assert node2.has(attrs[1].pad_first + str(attrs[1].name) +
  247. attrs[1].pad_before_eq) is True
  248. assert node2.has(attrs[3]) is True
  249. assert node2.has(str(attrs[3])) is True
  250. assert node2.has("idclass") is False
  251. assert node2.has("id class") is False
  252. assert node2.has("id=foo") is False
  253. def test_get(self):
  254. """test Tag.get()"""
  255. attrs = [agen("name", "foo")]
  256. node = Tag(wraptext("ref"), wraptext("cite"), attrs)
  257. assert attrs[0] is node.get("name")
  258. assert attrs[0] is node.get(" name ")
  259. assert attrs[0] is node.get(wraptext("name"))
  260. with pytest.raises(ValueError):
  261. node.get("Name")
  262. with pytest.raises(ValueError):
  263. node.get("foo")
  264. attrs = [agen("id", "foo"), agenp("class", "bar", " ", "\n", "\n"),
  265. agen("foo", "bar"), agenpnv("foo", " ", " \n ", " \t")]
  266. node2 = Tag(wraptext("div"), attrs=attrs, self_closing=True)
  267. assert attrs[0] is node2.get("id")
  268. assert attrs[1] is node2.get("class")
  269. assert attrs[1] is node2.get(
  270. attrs[1].pad_first + str(attrs[1].name) + attrs[1].pad_before_eq)
  271. assert attrs[3] is node2.get(attrs[3])
  272. assert attrs[3] is node2.get(str(attrs[3]))
  273. assert attrs[3] is node2.get(" foo")
  274. with pytest.raises(ValueError):
  275. node2.get("idclass")
  276. with pytest.raises(ValueError):
  277. node2.get("id class")
  278. with pytest.raises(ValueError):
  279. node2.get("id=foo")
  280. def test_add(self):
  281. """test Tag.add()"""
  282. node = Tag(wraptext("ref"), wraptext("cite"))
  283. node.add("name", "value")
  284. node.add("name", "value", quotes=None)
  285. node.add("name", "value", quotes="'")
  286. node.add("name")
  287. node.add(1, False)
  288. node.add("style", "{{foobar}}")
  289. node.add("name", "value", '"', "\n", " ", " ")
  290. attr1 = ' name="value"'
  291. attr2 = " name=value"
  292. attr3 = " name='value'"
  293. attr4 = " name"
  294. attr5 = ' 1="False"'
  295. attr6 = ' style="{{foobar}}"'
  296. attr7 = '\nname = "value"'
  297. assert attr1 == node.attributes[0]
  298. assert attr2 == node.attributes[1]
  299. assert attr3 == node.attributes[2]
  300. assert attr4 == node.attributes[3]
  301. assert attr5 == node.attributes[4]
  302. assert attr6 == node.attributes[5]
  303. assert attr7 == node.attributes[6]
  304. assert attr7 == node.get("name")
  305. self.assertWikicodeEqual(wrap([Template(wraptext("foobar"))]),
  306. node.attributes[5].value)
  307. assert "".join(("<ref", attr1, attr2, attr3, attr4, attr5,
  308. attr6, attr7, ">cite</ref>")) == node
  309. with pytest.raises(ValueError):
  310. node.add("name", "foo", quotes="bar")
  311. with pytest.raises(ValueError):
  312. node.add("name", "a bc d", quotes=None)
  313. def test_remove(self):
  314. """test Tag.remove()"""
  315. attrs = [agen("id", "foo"), agenp("class", "bar", " ", "\n", "\n"),
  316. agen("foo", "bar"), agenpnv("foo", " ", " \n ", " \t")]
  317. node = Tag(wraptext("div"), attrs=attrs, self_closing=True)
  318. node.remove("class")
  319. assert '<div id="foo" foo="bar" foo \n />' == node
  320. node.remove("foo")
  321. assert '<div id="foo"/>' == node
  322. with pytest.raises(ValueError):
  323. node.remove("foo")
  324. node.remove("id")
  325. assert '<div/>' == node