test_markupsafe.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. import pytest
  2. from markupsafe import Markup
  3. def test_adding(escape):
  4. unsafe = '<script type="application/x-some-script">alert("foo");</script>'
  5. safe = Markup("<em>username</em>")
  6. assert unsafe + safe == str(escape(unsafe)) + str(safe)
  7. @pytest.mark.parametrize(
  8. ("template", "data", "expect"),
  9. (
  10. ("<em>%s</em>", "<bad user>", "<em>&lt;bad user&gt;</em>"),
  11. (
  12. "<em>%(username)s</em>",
  13. {"username": "<bad user>"},
  14. "<em>&lt;bad user&gt;</em>",
  15. ),
  16. ("%i", 3.14, "3"),
  17. ("%.2f", 3.14, "3.14"),
  18. ),
  19. )
  20. def test_string_interpolation(template, data, expect):
  21. assert Markup(template) % data == expect
  22. def test_type_behavior():
  23. assert type(Markup("foo") + "bar") is Markup
  24. x = Markup("foo")
  25. assert x.__html__() is x
  26. def test_html_interop():
  27. class Foo:
  28. def __html__(self):
  29. return "<em>awesome</em>"
  30. def __str__(self):
  31. return "awesome"
  32. assert Markup(Foo()) == "<em>awesome</em>"
  33. result = Markup("<strong>%s</strong>") % Foo()
  34. assert result == "<strong><em>awesome</em></strong>"
  35. @pytest.mark.parametrize("args", ["foo", 42, ("foo", 42)])
  36. def test_missing_interpol(args):
  37. with pytest.raises(TypeError):
  38. Markup("<em></em>") % args
  39. def test_tuple_interpol():
  40. result = Markup("<em>%s:%s</em>") % ("<foo>", "<bar>")
  41. expect = Markup("<em>&lt;foo&gt;:&lt;bar&gt;</em>")
  42. assert result == expect
  43. def test_dict_interpol():
  44. result = Markup("<em>%(foo)s</em>") % {"foo": "<foo>"}
  45. expect = Markup("<em>&lt;foo&gt;</em>")
  46. assert result == expect
  47. result = Markup("<em>%(foo)s:%(bar)s</em>") % {"foo": "<foo>", "bar": "<bar>"}
  48. expect = Markup("<em>&lt;foo&gt;:&lt;bar&gt;</em>")
  49. assert result == expect
  50. def test_escaping(escape):
  51. assert escape("\"<>&'") == "&#34;&lt;&gt;&amp;&#39;"
  52. assert (
  53. Markup(
  54. "<!-- outer comment -->"
  55. "<em>Foo &amp; Bar"
  56. "<!-- inner comment about <em> -->"
  57. "</em>"
  58. ).striptags()
  59. == "Foo & Bar"
  60. )
  61. def test_unescape():
  62. assert Markup("&lt;test&gt;").unescape() == "<test>"
  63. result = Markup("jack & tavi are cooler than mike &amp; russ").unescape()
  64. expect = "jack & tavi are cooler than mike & russ"
  65. assert result == expect
  66. original = "&foo&#x3b;"
  67. once = Markup(original).unescape()
  68. twice = Markup(once).unescape()
  69. expect = "&foo;"
  70. assert once == expect
  71. assert twice == expect
  72. def test_format():
  73. result = Markup("<em>{awesome}</em>").format(awesome="<awesome>")
  74. assert result == "<em>&lt;awesome&gt;</em>"
  75. result = Markup("{0[1][bar]}").format([0, {"bar": "<bar/>"}])
  76. assert result == "&lt;bar/&gt;"
  77. result = Markup("{0[1][bar]}").format([0, {"bar": Markup("<bar/>")}])
  78. assert result == "<bar/>"
  79. def test_formatting_empty():
  80. formatted = Markup("{}").format(0)
  81. assert formatted == Markup("0")
  82. def test_custom_formatting():
  83. class HasHTMLOnly:
  84. def __html__(self):
  85. return Markup("<foo>")
  86. class HasHTMLAndFormat:
  87. def __html__(self):
  88. return Markup("<foo>")
  89. def __html_format__(self, spec):
  90. return Markup("<FORMAT>")
  91. assert Markup("{0}").format(HasHTMLOnly()) == Markup("<foo>")
  92. assert Markup("{0}").format(HasHTMLAndFormat()) == Markup("<FORMAT>")
  93. def test_complex_custom_formatting():
  94. class User:
  95. def __init__(self, id, username):
  96. self.id = id
  97. self.username = username
  98. def __html_format__(self, format_spec):
  99. if format_spec == "link":
  100. return Markup('<a href="/user/{0}">{1}</a>').format(
  101. self.id, self.__html__()
  102. )
  103. elif format_spec:
  104. raise ValueError("Invalid format spec")
  105. return self.__html__()
  106. def __html__(self):
  107. return Markup("<span class=user>{0}</span>").format(self.username)
  108. user = User(1, "foo")
  109. result = Markup("<p>User: {0:link}").format(user)
  110. expect = Markup('<p>User: <a href="/user/1"><span class=user>foo</span></a>')
  111. assert result == expect
  112. def test_formatting_with_objects():
  113. class Stringable:
  114. def __str__(self):
  115. return "строка"
  116. assert Markup("{s}").format(s=Stringable()) == Markup("строка")
  117. def test_escape_silent(escape, escape_silent):
  118. assert escape_silent(None) == Markup()
  119. assert escape(None) == Markup(None)
  120. assert escape_silent("<foo>") == Markup("&lt;foo&gt;")
  121. def test_splitting():
  122. expect = [Markup("a"), Markup("b")]
  123. assert Markup("a b").split() == expect
  124. assert Markup("a b").rsplit() == expect
  125. assert Markup("a\nb").splitlines() == expect
  126. def test_mul():
  127. assert Markup("a") * 3 == Markup("aaa")
  128. def test_escape_return_type(escape):
  129. assert isinstance(escape("a"), Markup)
  130. assert isinstance(escape(Markup("a")), Markup)
  131. class Foo:
  132. def __html__(self):
  133. return "<strong>Foo</strong>"
  134. assert isinstance(escape(Foo()), Markup)
  135. def test_soft_str(soft_str):
  136. assert type(soft_str("")) is str
  137. assert type(soft_str(Markup())) is Markup
  138. assert type(soft_str(15)) is str