A Python parser for MediaWiki wikicode https://mwparserfromhell.readthedocs.io/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

test_tag.py 14 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  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. """
  21. Test cases for the Tag node.
  22. """
  23. import pytest
  24. from mwparserfromhell.nodes import Tag, Template, Text
  25. from mwparserfromhell.nodes.extras import Attribute
  26. from .conftest import assert_wikicode_equal, wrap, wraptext
  27. agen = lambda name, value: Attribute(wraptext(name), wraptext(value))
  28. agennv = lambda name: Attribute(wraptext(name))
  29. agennq = lambda name, value: Attribute(wraptext(name), wraptext(value), None)
  30. agenp = lambda name, v, a, b, c: Attribute(wraptext(name), v, '"', a, b, c)
  31. agenpnv = lambda name, a, b, c: Attribute(wraptext(name), None, '"', a, b, c)
  32. def test_str():
  33. """test Tag.__str__()"""
  34. node1 = Tag(wraptext("ref"))
  35. node2 = Tag(wraptext("span"), wraptext("foo"), [agen("style", "color: red;")])
  36. node3 = Tag(
  37. wraptext("ref"),
  38. attrs=[agennq("name", "foo"), agenpnv("some_attr", " ", "", "")],
  39. self_closing=True,
  40. )
  41. node4 = Tag(wraptext("br"), self_closing=True, padding=" ")
  42. node5 = Tag(wraptext("br"), self_closing=True, implicit=True)
  43. node6 = Tag(wraptext("br"), self_closing=True, invalid=True, implicit=True)
  44. node7 = Tag(wraptext("br"), self_closing=True, invalid=True, padding=" ")
  45. node8 = Tag(wraptext("hr"), wiki_markup="----", self_closing=True)
  46. node9 = Tag(wraptext("i"), wraptext("italics!"), wiki_markup="''")
  47. assert "<ref></ref>" == str(node1)
  48. assert '<span style="color: red;">foo</span>' == str(node2)
  49. assert "<ref name=foo some_attr/>" == str(node3)
  50. assert "<br />" == str(node4)
  51. assert "<br>" == str(node5)
  52. assert "</br>" == str(node6)
  53. assert "</br />" == str(node7)
  54. assert "----" == str(node8)
  55. assert "''italics!''" == str(node9)
  56. def test_children():
  57. """test Tag.__children__()"""
  58. # <ref>foobar</ref>
  59. node1 = Tag(wraptext("ref"), wraptext("foobar"))
  60. # '''bold text'''
  61. node2 = Tag(wraptext("b"), wraptext("bold text"), wiki_markup="'''")
  62. # <img id="foo" class="bar" selected />
  63. node3 = Tag(
  64. wraptext("img"),
  65. attrs=[agen("id", "foo"), agen("class", "bar"), agennv("selected")],
  66. self_closing=True,
  67. padding=" ",
  68. )
  69. gen1 = node1.__children__()
  70. gen2 = node2.__children__()
  71. gen3 = node3.__children__()
  72. assert node1.tag == next(gen1)
  73. assert node3.tag == next(gen3)
  74. assert node3.attributes[0].name == next(gen3)
  75. assert node3.attributes[0].value == next(gen3)
  76. assert node3.attributes[1].name == next(gen3)
  77. assert node3.attributes[1].value == next(gen3)
  78. assert node3.attributes[2].name == next(gen3)
  79. assert node1.contents == next(gen1)
  80. assert node2.contents == next(gen2)
  81. assert node1.closing_tag == next(gen1)
  82. with pytest.raises(StopIteration):
  83. next(gen1)
  84. with pytest.raises(StopIteration):
  85. next(gen2)
  86. with pytest.raises(StopIteration):
  87. next(gen3)
  88. def test_strip():
  89. """test Tag.__strip__()"""
  90. node1 = Tag(wraptext("i"), wraptext("foobar"))
  91. node2 = Tag(wraptext("math"), wraptext("foobar"))
  92. node3 = Tag(wraptext("br"), self_closing=True)
  93. assert "foobar" == node1.__strip__()
  94. assert node2.__strip__() is None
  95. assert node3.__strip__() is None
  96. def test_showtree():
  97. """test Tag.__showtree__()"""
  98. output = []
  99. getter, marker = object(), object()
  100. get = lambda code: output.append((getter, code))
  101. mark = lambda: output.append(marker)
  102. node1 = Tag(
  103. wraptext("ref"), wraptext("text"), [agen("name", "foo"), agennv("selected")]
  104. )
  105. node2 = Tag(wraptext("br"), self_closing=True, padding=" ")
  106. node3 = Tag(
  107. wraptext("br"), self_closing=True, invalid=True, implicit=True, padding=" "
  108. )
  109. node1.__showtree__(output.append, get, mark)
  110. node2.__showtree__(output.append, get, mark)
  111. node3.__showtree__(output.append, get, mark)
  112. valid = [
  113. "<",
  114. (getter, node1.tag),
  115. (getter, node1.attributes[0].name),
  116. " = ",
  117. marker,
  118. (getter, node1.attributes[0].value),
  119. (getter, node1.attributes[1].name),
  120. ">",
  121. (getter, node1.contents),
  122. "</",
  123. (getter, node1.closing_tag),
  124. ">",
  125. "<",
  126. (getter, node2.tag),
  127. "/>",
  128. "</",
  129. (getter, node3.tag),
  130. ">",
  131. ]
  132. assert valid == output
  133. def test_tag():
  134. """test getter/setter for the tag attribute"""
  135. tag = wraptext("ref")
  136. node = Tag(tag, wraptext("text"))
  137. assert tag is node.tag
  138. assert tag is node.closing_tag
  139. node.tag = "span"
  140. assert_wikicode_equal(wraptext("span"), node.tag)
  141. assert_wikicode_equal(wraptext("span"), node.closing_tag)
  142. assert "<span>text</span>" == node
  143. def test_contents():
  144. """test getter/setter for the contents attribute"""
  145. contents = wraptext("text")
  146. node = Tag(wraptext("ref"), contents)
  147. assert contents is node.contents
  148. node.contents = "text and a {{template}}"
  149. parsed = wrap([Text("text and a "), Template(wraptext("template"))])
  150. assert_wikicode_equal(parsed, node.contents)
  151. assert "<ref>text and a {{template}}</ref>" == node
  152. def test_attributes():
  153. """test getter for the attributes attribute"""
  154. attrs = [agen("name", "bar")]
  155. node1 = Tag(wraptext("ref"), wraptext("foo"))
  156. node2 = Tag(wraptext("ref"), wraptext("foo"), attrs)
  157. assert [] == node1.attributes
  158. assert attrs is node2.attributes
  159. def test_wiki_markup():
  160. """test getter/setter for the wiki_markup attribute"""
  161. node = Tag(wraptext("i"), wraptext("italic text"))
  162. assert None is node.wiki_markup
  163. node.wiki_markup = "''"
  164. assert "''" == node.wiki_markup
  165. assert "''italic text''" == node
  166. node.wiki_markup = False
  167. assert node.wiki_markup is None
  168. assert "<i>italic text</i>" == node
  169. def test_self_closing():
  170. """test getter/setter for the self_closing attribute"""
  171. node = Tag(wraptext("ref"), wraptext("foobar"))
  172. assert node.self_closing is False
  173. node.self_closing = True
  174. assert node.self_closing is True
  175. assert "<ref/>" == node
  176. node.self_closing = 0
  177. assert node.self_closing is False
  178. assert "<ref>foobar</ref>" == node
  179. def test_invalid():
  180. """test getter/setter for the invalid attribute"""
  181. node = Tag(wraptext("br"), self_closing=True, implicit=True)
  182. assert node.invalid is False
  183. node.invalid = True
  184. assert node.invalid is True
  185. assert "</br>" == node
  186. node.invalid = 0
  187. assert node.invalid is False
  188. assert "<br>" == node
  189. def test_implicit():
  190. """test getter/setter for the implicit attribute"""
  191. node = Tag(wraptext("br"), self_closing=True)
  192. assert node.implicit is False
  193. node.implicit = True
  194. assert node.implicit is True
  195. assert "<br>" == node
  196. node.implicit = 0
  197. assert node.implicit is False
  198. assert "<br/>" == node
  199. def test_padding():
  200. """test getter/setter for the padding attribute"""
  201. node = Tag(wraptext("ref"), wraptext("foobar"))
  202. assert "" == node.padding
  203. node.padding = " "
  204. assert " " == node.padding
  205. assert "<ref >foobar</ref>" == node
  206. node.padding = None
  207. assert "" == node.padding
  208. assert "<ref>foobar</ref>" == node
  209. with pytest.raises(ValueError):
  210. node.__setattr__("padding", True)
  211. def test_closing_tag():
  212. """test getter/setter for the closing_tag attribute"""
  213. tag = wraptext("ref")
  214. node = Tag(tag, wraptext("foobar"))
  215. assert tag is node.closing_tag
  216. node.closing_tag = "ref {{ignore me}}"
  217. parsed = wrap([Text("ref "), Template(wraptext("ignore me"))])
  218. assert_wikicode_equal(parsed, node.closing_tag)
  219. assert "<ref>foobar</ref {{ignore me}}>" == node
  220. def test_wiki_style_separator():
  221. """test getter/setter for wiki_style_separator attribute"""
  222. node = Tag(wraptext("table"), wraptext("\n"))
  223. assert None is node.wiki_style_separator
  224. node.wiki_style_separator = "|"
  225. assert "|" == node.wiki_style_separator
  226. node.wiki_markup = "{"
  227. assert "{|\n{" == node
  228. node2 = Tag(wraptext("table"), wraptext("\n"), wiki_style_separator="|")
  229. assert "|" == node2.wiki_style_separator
  230. def test_closing_wiki_markup():
  231. """test getter/setter for closing_wiki_markup attribute"""
  232. node = Tag(wraptext("table"), wraptext("\n"))
  233. assert None is node.closing_wiki_markup
  234. node.wiki_markup = "{|"
  235. assert "{|" == node.closing_wiki_markup
  236. node.closing_wiki_markup = "|}"
  237. assert "|}" == node.closing_wiki_markup
  238. assert "{|\n|}" == node
  239. node.wiki_markup = "!!"
  240. assert "|}" == node.closing_wiki_markup
  241. assert "!!\n|}" == node
  242. node.wiki_markup = False
  243. assert node.closing_wiki_markup is None
  244. assert "<table>\n</table>" == node
  245. node2 = Tag(
  246. wraptext("table"),
  247. wraptext("\n"),
  248. attrs=[agen("id", "foo")],
  249. wiki_markup="{|",
  250. closing_wiki_markup="|}",
  251. )
  252. assert "|}" == node2.closing_wiki_markup
  253. assert '{| id="foo"\n|}' == node2
  254. def test_has():
  255. """test Tag.has()"""
  256. node = Tag(wraptext("ref"), wraptext("cite"), [agen("name", "foo")])
  257. assert node.has("name") is True
  258. assert node.has(" name ") is True
  259. assert node.has(wraptext("name")) is True
  260. assert node.has("Name") is False
  261. assert node.has("foo") is False
  262. attrs = [
  263. agen("id", "foo"),
  264. agenp("class", "bar", " ", "\n", "\n"),
  265. agen("foo", "bar"),
  266. agenpnv("foo", " ", " \n ", " \t"),
  267. ]
  268. node2 = Tag(wraptext("div"), attrs=attrs, self_closing=True)
  269. assert node2.has("id") is True
  270. assert node2.has("class") is True
  271. assert (
  272. node2.has(attrs[1].pad_first + str(attrs[1].name) + attrs[1].pad_before_eq)
  273. is True
  274. )
  275. assert node2.has(attrs[3]) is True
  276. assert node2.has(str(attrs[3])) is True
  277. assert node2.has("idclass") is False
  278. assert node2.has("id class") is False
  279. assert node2.has("id=foo") is False
  280. def test_get():
  281. """test Tag.get()"""
  282. attrs = [agen("name", "foo")]
  283. node = Tag(wraptext("ref"), wraptext("cite"), attrs)
  284. assert attrs[0] is node.get("name")
  285. assert attrs[0] is node.get(" name ")
  286. assert attrs[0] is node.get(wraptext("name"))
  287. with pytest.raises(ValueError):
  288. node.get("Name")
  289. with pytest.raises(ValueError):
  290. node.get("foo")
  291. attrs = [
  292. agen("id", "foo"),
  293. agenp("class", "bar", " ", "\n", "\n"),
  294. agen("foo", "bar"),
  295. agenpnv("foo", " ", " \n ", " \t"),
  296. ]
  297. node2 = Tag(wraptext("div"), attrs=attrs, self_closing=True)
  298. assert attrs[0] is node2.get("id")
  299. assert attrs[1] is node2.get("class")
  300. assert attrs[1] is node2.get(
  301. attrs[1].pad_first + str(attrs[1].name) + attrs[1].pad_before_eq
  302. )
  303. assert attrs[3] is node2.get(attrs[3])
  304. assert attrs[3] is node2.get(str(attrs[3]))
  305. assert attrs[3] is node2.get(" foo")
  306. with pytest.raises(ValueError):
  307. node2.get("idclass")
  308. with pytest.raises(ValueError):
  309. node2.get("id class")
  310. with pytest.raises(ValueError):
  311. node2.get("id=foo")
  312. def test_add():
  313. """test Tag.add()"""
  314. node = Tag(wraptext("ref"), wraptext("cite"))
  315. node.add("name", "value")
  316. node.add("name", "value", quotes=None)
  317. node.add("name", "value", quotes="'")
  318. node.add("name")
  319. node.add(1, False)
  320. node.add("style", "{{foobar}}")
  321. node.add("name", "value", '"', "\n", " ", " ")
  322. attr1 = ' name="value"'
  323. attr2 = " name=value"
  324. attr3 = " name='value'"
  325. attr4 = " name"
  326. attr5 = ' 1="False"'
  327. attr6 = ' style="{{foobar}}"'
  328. attr7 = '\nname = "value"'
  329. assert attr1 == node.attributes[0]
  330. assert attr2 == node.attributes[1]
  331. assert attr3 == node.attributes[2]
  332. assert attr4 == node.attributes[3]
  333. assert attr5 == node.attributes[4]
  334. assert attr6 == node.attributes[5]
  335. assert attr7 == node.attributes[6]
  336. assert attr7 == node.get("name")
  337. assert_wikicode_equal(
  338. wrap([Template(wraptext("foobar"))]), node.attributes[5].value
  339. )
  340. assert (
  341. "".join(
  342. ("<ref", attr1, attr2, attr3, attr4, attr5, attr6, attr7, ">cite</ref>")
  343. )
  344. == node
  345. )
  346. with pytest.raises(ValueError):
  347. node.add("name", "foo", quotes="bar")
  348. with pytest.raises(ValueError):
  349. node.add("name", "a bc d", quotes=None)
  350. def test_remove():
  351. """test Tag.remove()"""
  352. attrs = [
  353. agen("id", "foo"),
  354. agenp("class", "bar", " ", "\n", "\n"),
  355. agen("foo", "bar"),
  356. agenpnv("foo", " ", " \n ", " \t"),
  357. ]
  358. node = Tag(wraptext("div"), attrs=attrs, self_closing=True)
  359. node.remove("class")
  360. assert '<div id="foo" foo="bar" foo \n />' == node
  361. node.remove("foo")
  362. assert '<div id="foo"/>' == node
  363. with pytest.raises(ValueError):
  364. node.remove("foo")
  365. node.remove("id")
  366. assert "<div/>" == node