1. from django.template import RequestContext, TemplateSyntaxError
    
  2. from django.template.defaulttags import URLNode
    
  3. from django.test import RequestFactory, SimpleTestCase, override_settings
    
  4. from django.urls import NoReverseMatch, resolve
    
  5. 
    
  6. from ..utils import setup
    
  7. 
    
  8. 
    
  9. @override_settings(ROOT_URLCONF="template_tests.urls")
    
  10. class UrlTagTests(SimpleTestCase):
    
  11.     request_factory = RequestFactory()
    
  12. 
    
  13.     # Successes
    
  14.     @setup({"url01": '{% url "client" client.id %}'})
    
  15.     def test_url01(self):
    
  16.         output = self.engine.render_to_string("url01", {"client": {"id": 1}})
    
  17.         self.assertEqual(output, "/client/1/")
    
  18. 
    
  19.     @setup({"url02": '{% url "client_action" id=client.id action="update" %}'})
    
  20.     def test_url02(self):
    
  21.         output = self.engine.render_to_string("url02", {"client": {"id": 1}})
    
  22.         self.assertEqual(output, "/client/1/update/")
    
  23. 
    
  24.     @setup({"url02a": '{% url "client_action" client.id "update" %}'})
    
  25.     def test_url02a(self):
    
  26.         output = self.engine.render_to_string("url02a", {"client": {"id": 1}})
    
  27.         self.assertEqual(output, "/client/1/update/")
    
  28. 
    
  29.     @setup({"url02b": "{% url 'client_action' id=client.id action='update' %}"})
    
  30.     def test_url02b(self):
    
  31.         output = self.engine.render_to_string("url02b", {"client": {"id": 1}})
    
  32.         self.assertEqual(output, "/client/1/update/")
    
  33. 
    
  34.     @setup({"url02c": "{% url 'client_action' client.id 'update' %}"})
    
  35.     def test_url02c(self):
    
  36.         output = self.engine.render_to_string("url02c", {"client": {"id": 1}})
    
  37.         self.assertEqual(output, "/client/1/update/")
    
  38. 
    
  39.     @setup({"url03": '{% url "index" %}'})
    
  40.     def test_url03(self):
    
  41.         output = self.engine.render_to_string("url03")
    
  42.         self.assertEqual(output, "/")
    
  43. 
    
  44.     @setup({"url04": '{% url "named.client" client.id %}'})
    
  45.     def test_url04(self):
    
  46.         output = self.engine.render_to_string("url04", {"client": {"id": 1}})
    
  47.         self.assertEqual(output, "/named-client/1/")
    
  48. 
    
  49.     @setup({"url05": '{% url "метка_оператора" v %}'})
    
  50.     def test_url05(self):
    
  51.         output = self.engine.render_to_string("url05", {"v": "Ω"})
    
  52.         self.assertEqual(output, "/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/")
    
  53. 
    
  54.     @setup({"url06": '{% url "метка_оператора_2" tag=v %}'})
    
  55.     def test_url06(self):
    
  56.         output = self.engine.render_to_string("url06", {"v": "Ω"})
    
  57.         self.assertEqual(output, "/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/")
    
  58. 
    
  59.     @setup({"url08": '{% url "метка_оператора" v %}'})
    
  60.     def test_url08(self):
    
  61.         output = self.engine.render_to_string("url08", {"v": "Ω"})
    
  62.         self.assertEqual(output, "/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/")
    
  63. 
    
  64.     @setup({"url09": '{% url "метка_оператора_2" tag=v %}'})
    
  65.     def test_url09(self):
    
  66.         output = self.engine.render_to_string("url09", {"v": "Ω"})
    
  67.         self.assertEqual(output, "/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/")
    
  68. 
    
  69.     @setup({"url10": '{% url "client_action" id=client.id action="two words" %}'})
    
  70.     def test_url10(self):
    
  71.         output = self.engine.render_to_string("url10", {"client": {"id": 1}})
    
  72.         self.assertEqual(output, "/client/1/two%20words/")
    
  73. 
    
  74.     @setup({"url11": '{% url "client_action" id=client.id action="==" %}'})
    
  75.     def test_url11(self):
    
  76.         output = self.engine.render_to_string("url11", {"client": {"id": 1}})
    
  77.         self.assertEqual(output, "/client/1/==/")
    
  78. 
    
  79.     @setup(
    
  80.         {"url12": '{% url "client_action" id=client.id action="!$&\'()*+,;=~:@," %}'}
    
  81.     )
    
  82.     def test_url12(self):
    
  83.         output = self.engine.render_to_string("url12", {"client": {"id": 1}})
    
  84.         self.assertEqual(output, "/client/1/!$&'()*+,;=~:@,/")
    
  85. 
    
  86.     @setup({"url13": '{% url "client_action" id=client.id action=arg|join:"-" %}'})
    
  87.     def test_url13(self):
    
  88.         output = self.engine.render_to_string(
    
  89.             "url13", {"client": {"id": 1}, "arg": ["a", "b"]}
    
  90.         )
    
  91.         self.assertEqual(output, "/client/1/a-b/")
    
  92. 
    
  93.     @setup({"url14": '{% url "client_action" client.id arg|join:"-" %}'})
    
  94.     def test_url14(self):
    
  95.         output = self.engine.render_to_string(
    
  96.             "url14", {"client": {"id": 1}, "arg": ["a", "b"]}
    
  97.         )
    
  98.         self.assertEqual(output, "/client/1/a-b/")
    
  99. 
    
  100.     @setup({"url15": '{% url "client_action" 12 "test" %}'})
    
  101.     def test_url15(self):
    
  102.         output = self.engine.render_to_string("url15")
    
  103.         self.assertEqual(output, "/client/12/test/")
    
  104. 
    
  105.     @setup({"url18": '{% url "client" "1,2" %}'})
    
  106.     def test_url18(self):
    
  107.         output = self.engine.render_to_string("url18")
    
  108.         self.assertEqual(output, "/client/1,2/")
    
  109. 
    
  110.     @setup({"url19": "{% url named_url client.id %}"})
    
  111.     def test_url19(self):
    
  112.         output = self.engine.render_to_string(
    
  113.             "url19", {"client": {"id": 1}, "named_url": "client"}
    
  114.         )
    
  115.         self.assertEqual(output, "/client/1/")
    
  116. 
    
  117.     @setup({"url20": "{% url url_name_in_var client.id %}"})
    
  118.     def test_url20(self):
    
  119.         output = self.engine.render_to_string(
    
  120.             "url20", {"client": {"id": 1}, "url_name_in_var": "named.client"}
    
  121.         )
    
  122.         self.assertEqual(output, "/named-client/1/")
    
  123. 
    
  124.     @setup(
    
  125.         {
    
  126.             "url21": "{% autoescape off %}"
    
  127.             '{% url "client_action" id=client.id action="!$&\'()*+,;=~:@," %}'
    
  128.             "{% endautoescape %}"
    
  129.         }
    
  130.     )
    
  131.     def test_url21(self):
    
  132.         output = self.engine.render_to_string("url21", {"client": {"id": 1}})
    
  133.         self.assertEqual(output, "/client/1/!$&'()*+,;=~:@,/")
    
  134. 
    
  135.     # Failures
    
  136.     @setup({"url-fail01": "{% url %}"})
    
  137.     def test_url_fail01(self):
    
  138.         with self.assertRaises(TemplateSyntaxError):
    
  139.             self.engine.get_template("url-fail01")
    
  140. 
    
  141.     @setup({"url-fail02": '{% url "no_such_view" %}'})
    
  142.     def test_url_fail02(self):
    
  143.         with self.assertRaises(NoReverseMatch):
    
  144.             self.engine.render_to_string("url-fail02")
    
  145. 
    
  146.     @setup({"url-fail03": '{% url "client" %}'})
    
  147.     def test_url_fail03(self):
    
  148.         with self.assertRaises(NoReverseMatch):
    
  149.             self.engine.render_to_string("url-fail03")
    
  150. 
    
  151.     @setup({"url-fail04": '{% url "view" id, %}'})
    
  152.     def test_url_fail04(self):
    
  153.         with self.assertRaises(TemplateSyntaxError):
    
  154.             self.engine.get_template("url-fail04")
    
  155. 
    
  156.     @setup({"url-fail05": '{% url "view" id= %}'})
    
  157.     def test_url_fail05(self):
    
  158.         with self.assertRaises(TemplateSyntaxError):
    
  159.             self.engine.get_template("url-fail05")
    
  160. 
    
  161.     @setup({"url-fail06": '{% url "view" a.id=id %}'})
    
  162.     def test_url_fail06(self):
    
  163.         with self.assertRaises(TemplateSyntaxError):
    
  164.             self.engine.get_template("url-fail06")
    
  165. 
    
  166.     @setup({"url-fail07": '{% url "view" a.id!id %}'})
    
  167.     def test_url_fail07(self):
    
  168.         with self.assertRaises(TemplateSyntaxError):
    
  169.             self.engine.get_template("url-fail07")
    
  170. 
    
  171.     @setup({"url-fail08": '{% url "view" id="unterminatedstring %}'})
    
  172.     def test_url_fail08(self):
    
  173.         with self.assertRaises(TemplateSyntaxError):
    
  174.             self.engine.get_template("url-fail08")
    
  175. 
    
  176.     @setup({"url-fail09": '{% url "view" id=", %}'})
    
  177.     def test_url_fail09(self):
    
  178.         with self.assertRaises(TemplateSyntaxError):
    
  179.             self.engine.get_template("url-fail09")
    
  180. 
    
  181.     @setup({"url-fail11": "{% url named_url %}"})
    
  182.     def test_url_fail11(self):
    
  183.         with self.assertRaises(NoReverseMatch):
    
  184.             self.engine.render_to_string("url-fail11")
    
  185. 
    
  186.     @setup({"url-fail12": "{% url named_url %}"})
    
  187.     def test_url_fail12(self):
    
  188.         with self.assertRaises(NoReverseMatch):
    
  189.             self.engine.render_to_string("url-fail12", {"named_url": "no_such_view"})
    
  190. 
    
  191.     @setup({"url-fail13": "{% url named_url %}"})
    
  192.     def test_url_fail13(self):
    
  193.         with self.assertRaises(NoReverseMatch):
    
  194.             self.engine.render_to_string(
    
  195.                 "url-fail13", {"named_url": "template_tests.views.client"}
    
  196.             )
    
  197. 
    
  198.     @setup({"url-fail14": "{% url named_url id, %}"})
    
  199.     def test_url_fail14(self):
    
  200.         with self.assertRaises(TemplateSyntaxError):
    
  201.             self.engine.render_to_string("url-fail14", {"named_url": "view"})
    
  202. 
    
  203.     @setup({"url-fail15": "{% url named_url id= %}"})
    
  204.     def test_url_fail15(self):
    
  205.         with self.assertRaises(TemplateSyntaxError):
    
  206.             self.engine.render_to_string("url-fail15", {"named_url": "view"})
    
  207. 
    
  208.     @setup({"url-fail16": "{% url named_url a.id=id %}"})
    
  209.     def test_url_fail16(self):
    
  210.         with self.assertRaises(TemplateSyntaxError):
    
  211.             self.engine.render_to_string("url-fail16", {"named_url": "view"})
    
  212. 
    
  213.     @setup({"url-fail17": "{% url named_url a.id!id %}"})
    
  214.     def test_url_fail17(self):
    
  215.         with self.assertRaises(TemplateSyntaxError):
    
  216.             self.engine.render_to_string("url-fail17", {"named_url": "view"})
    
  217. 
    
  218.     @setup({"url-fail18": '{% url named_url id="unterminatedstring %}'})
    
  219.     def test_url_fail18(self):
    
  220.         with self.assertRaises(TemplateSyntaxError):
    
  221.             self.engine.render_to_string("url-fail18", {"named_url": "view"})
    
  222. 
    
  223.     @setup({"url-fail19": '{% url named_url id=", %}'})
    
  224.     def test_url_fail19(self):
    
  225.         with self.assertRaises(TemplateSyntaxError):
    
  226.             self.engine.render_to_string("url-fail19", {"named_url": "view"})
    
  227. 
    
  228.     # {% url ... as var %}
    
  229.     @setup({"url-asvar01": '{% url "index" as url %}'})
    
  230.     def test_url_asvar01(self):
    
  231.         output = self.engine.render_to_string("url-asvar01")
    
  232.         self.assertEqual(output, "")
    
  233. 
    
  234.     @setup({"url-asvar02": '{% url "index" as url %}{{ url }}'})
    
  235.     def test_url_asvar02(self):
    
  236.         output = self.engine.render_to_string("url-asvar02")
    
  237.         self.assertEqual(output, "/")
    
  238. 
    
  239.     @setup({"url-asvar03": '{% url "no_such_view" as url %}{{ url }}'})
    
  240.     def test_url_asvar03(self):
    
  241.         output = self.engine.render_to_string("url-asvar03")
    
  242.         self.assertEqual(output, "")
    
  243. 
    
  244.     @setup({"url-namespace01": '{% url "app:named.client" 42 %}'})
    
  245.     def test_url_namespace01(self):
    
  246.         request = self.request_factory.get("/")
    
  247.         request.resolver_match = resolve("/ns1/")
    
  248.         template = self.engine.get_template("url-namespace01")
    
  249.         context = RequestContext(request)
    
  250.         output = template.render(context)
    
  251.         self.assertEqual(output, "/ns1/named-client/42/")
    
  252. 
    
  253.     @setup({"url-namespace02": '{% url "app:named.client" 42 %}'})
    
  254.     def test_url_namespace02(self):
    
  255.         request = self.request_factory.get("/")
    
  256.         request.resolver_match = resolve("/ns2/")
    
  257.         template = self.engine.get_template("url-namespace02")
    
  258.         context = RequestContext(request)
    
  259.         output = template.render(context)
    
  260.         self.assertEqual(output, "/ns2/named-client/42/")
    
  261. 
    
  262.     @setup({"url-namespace03": '{% url "app:named.client" 42 %}'})
    
  263.     def test_url_namespace03(self):
    
  264.         request = self.request_factory.get("/")
    
  265.         template = self.engine.get_template("url-namespace03")
    
  266.         context = RequestContext(request)
    
  267.         output = template.render(context)
    
  268.         self.assertEqual(output, "/ns2/named-client/42/")
    
  269. 
    
  270.     @setup({"url-namespace-no-current-app": '{% url "app:named.client" 42 %}'})
    
  271.     def test_url_namespace_no_current_app(self):
    
  272.         request = self.request_factory.get("/")
    
  273.         request.resolver_match = resolve("/ns1/")
    
  274.         request.current_app = None
    
  275.         template = self.engine.get_template("url-namespace-no-current-app")
    
  276.         context = RequestContext(request)
    
  277.         output = template.render(context)
    
  278.         self.assertEqual(output, "/ns2/named-client/42/")
    
  279. 
    
  280.     @setup({"url-namespace-explicit-current-app": '{% url "app:named.client" 42 %}'})
    
  281.     def test_url_namespace_explicit_current_app(self):
    
  282.         request = self.request_factory.get("/")
    
  283.         request.resolver_match = resolve("/ns1/")
    
  284.         request.current_app = "app"
    
  285.         template = self.engine.get_template("url-namespace-explicit-current-app")
    
  286.         context = RequestContext(request)
    
  287.         output = template.render(context)
    
  288.         self.assertEqual(output, "/ns2/named-client/42/")
    
  289. 
    
  290. 
    
  291. class URLNodeTest(SimpleTestCase):
    
  292.     def test_repr(self):
    
  293.         url_node = URLNode(view_name="named-view", args=[], kwargs={}, asvar=None)
    
  294.         self.assertEqual(
    
  295.             repr(url_node),
    
  296.             "<URLNode view_name='named-view' args=[] kwargs={} as=None>",
    
  297.         )
    
  298.         url_node = URLNode(
    
  299.             view_name="named-view",
    
  300.             args=[1, 2],
    
  301.             kwargs={"action": "update"},
    
  302.             asvar="my_url",
    
  303.         )
    
  304.         self.assertEqual(
    
  305.             repr(url_node),
    
  306.             "<URLNode view_name='named-view' args=[1, 2] "
    
  307.             "kwargs={'action': 'update'} as='my_url'>",
    
  308.         )