sources_parser_tests.erl 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. -module(sources_parser_tests).
  2. -include_lib("eunit/include/eunit.hrl").
  3. -include("include/erlydtl_ext.hrl").
  4. all_sources_parser_test_() ->
  5. [{Title, [test_fun(Test) || Test <- Tests]}
  6. || {Title, Tests} <- test_defs()].
  7. test_fun({Name, Content, Output}) ->
  8. {Name, fun () ->
  9. Tokens = (catch sources_parser:process_content("dummy_path", Content)),
  10. ?assertMatch(Output, Tokens)
  11. end}.
  12. test_defs() ->
  13. [{"trans",
  14. [{"block with no trans",
  15. <<"<html>{% block main %} {% endblock %}</html>">>,
  16. []},
  17. {"block with trans",
  18. <<"<html>{% block main %} {% trans \"Hello\" %} {% endblock %}</html>">>,
  19. [{"Hello",{"dummy_path",1,33}}]},
  20. {"for with trans",
  21. <<"<html>{% block main %} {%for thing in things %}{% trans \"Hello inside a for\" %} {% endfor %} {% endblock %}</html>">>,
  22. [{"Hello inside a for",{"dummy_path",1,57}}]},
  23. {"if with trans",
  24. <<"<html>{% block content %}{% if thing %} {% trans \"Hello inside an if\" %} {% endif %} {% endblock %}</html>">>,
  25. [{"Hello inside an if",{"dummy_path",1,50}}]},
  26. {"if with trans inside a for",
  27. <<"<html>{% block content %}{%for thin in things %}{% if thing %} {% trans \"Hello inside an if inside a for\" %} {% endif %} {% endfor %}{% endblock %}</html>">>,
  28. [{"Hello inside an if inside a for",{"dummy_path",1,73}}]},
  29. {"if and else both with trans",
  30. <<"<html>{% block content %}{% if thing %} {% trans \"Hello inside an if\" %} {% else %} {% trans \"Hello inside an else\" %} {% endif %} {% endblock %}</html>">>,
  31. [{"Hello inside an else",{"dummy_path",1,94}}, {"Hello inside an if",{"dummy_path",1,50}}]},
  32. {"blocktrans with pretty format",
  33. <<"<html>{% blocktrans %}\n This is a multiline\n message... \n{% endblocktrans %}">>,
  34. [{"\n This is a multiline\n message... \n", {"dummy_path",1,10}}]},
  35. {"blocktrans with pretty format, trimmed",
  36. <<"<html>{% blocktrans trimmed %}\n This is a multiline\n message... \n{% endblocktrans %}">>,
  37. [{"This is a multiline message...", {"dummy_path",1,18}}]}
  38. ]}
  39. ].
  40. all_sources_parser_ext_test_() ->
  41. [test_ext_fun(Test) || Test <- ext_test_defs()].
  42. test_ext_fun({Name, Tpl, {Fields, Output}}) ->
  43. {Name, fun() ->
  44. Tokens = [sources_parser:phrase_info(Fields, P)
  45. || P <- sources_parser:parse_content("dummy_path", Tpl)],
  46. ?assertEqual(Output, Tokens)
  47. end}.
  48. ext_test_defs() ->
  49. [{"trans with inline comments",
  50. <<"{#TrAnSlATORs: hi!#}{%trans 'phrase'%}">>,
  51. {[msgid, comment], [["phrase", "TrAnSlATORs: hi!"]]}},
  52. {"trans with comments",
  53. <<"{%comment%}translators: com{{me}}nt{%endcomment%}{%trans 'phrase'%}">>,
  54. {[msgid, comment], [["phrase", "translators: com{{ me }}nt"]]}},
  55. {"blocktrans with comments",
  56. <<"{%comment%}translators: comment{%endcomment%}{%blocktrans with a=b%}B={{b}}{%endblocktrans%}">>,
  57. {[msgid, comment], [["B={{ b }}", "translators: comment"]]}},
  58. {"blocktrans with context",
  59. <<"{%blocktrans context 'ctxt'%}msg{%endblocktrans%}">>,
  60. {[msgid, context], [["msg", "ctxt"]]}},
  61. {"blocktrans with plural form",
  62. <<"{%blocktrans%}msg{%plural%}msgs{%endblocktrans%}">>,
  63. {[msgid, msgid_plural], [["msg", "msgs"]]}},
  64. {"trans with context",
  65. <<"{% trans 'msg' context 'ctxt' %}">>,
  66. {[msgid, context], [["msg", "ctxt"]]}},
  67. {"trans noop",
  68. <<"{% trans 'msg' noop %}">>,
  69. {[msgid], [["msg"]]}},
  70. {"trans noop with context",
  71. <<"{% trans 'msg' noop context 'ctxt' %}">>,
  72. {[msgid, context], [["msg", "ctxt"]]}}
  73. ].
  74. unparser_test_() ->
  75. [test_unparser_fun(Test) || Test <- unparser_test_defs()].
  76. test_unparser_fun({Name, Tpl}) ->
  77. {Name, fun() ->
  78. %% take input Tpl value, parse it, "unparse" it, then parse it again.
  79. %% both parsed values should be equvialent, even if the source versions
  80. %% are not an exact match (there can be whitespace differences)
  81. {ok, Dpt} = erlydtl_compiler:do_parse_template(
  82. Tpl, #dtl_context{}),
  83. Unparsed = erlydtl_unparser:unparse(Dpt),
  84. {ok, DptU} = erlydtl_compiler:do_parse_template(
  85. Unparsed, #dtl_context{}),
  86. compare_tree(Dpt, DptU)
  87. end}.
  88. unparser_test_defs() ->
  89. [{"comment tag", <<"here it is: {# this is my comment #} <-- it was right there.">>}
  90. ].
  91. compare_tree([], []) -> ok;
  92. compare_tree([H1|T1], [H2|T2]) ->
  93. compare_token(H1, H2),
  94. compare_tree(T1, T2).
  95. compare_token({'extends', Value1}, {'extends', Value2}) ->
  96. ?assertEqual(Value1, Value2);
  97. compare_token({'autoescape', OnOrOff1, Contents1}, {'autoescape', OnOrOff2, Contents2}) ->
  98. ?assertEqual(OnOrOff1, OnOrOff2),
  99. compare_tree(Contents1, Contents2);
  100. compare_token({'block', Identifier1, Contents1}, {'block', Identifier2, Contents2}) ->
  101. compare_identifier(Identifier1, Identifier2),
  102. compare_tree(Contents1, Contents2);
  103. compare_token({'blocktrans', Args1, Contents1}, {'blocktrans', Args2, Contents2}) ->
  104. compare_args(Args1, Args2),
  105. compare_tree(Contents1, Contents2);
  106. compare_token({'call', Identifier1}, {'call', Identifier2}) ->
  107. compare_identifier(Identifier1, Identifier2);
  108. compare_token({'call', Identifier1, With1}, {'call', Identifier2, With2}) ->
  109. ?assertEqual(With1, With2),
  110. compare_identifier(Identifier1, Identifier2);
  111. compare_token({'comment', Contents1}, {'comment', Contents2}) ->
  112. compare_tree(Contents1, Contents2);
  113. compare_token({'comment_tag', _Pos, Text1}, {'comment_tag', _Pos, Text2}) ->
  114. ?assertEqual(Text1, Text2);
  115. compare_token({'cycle', Names1}, {'cycle', Names2}) ->
  116. compare_tree(Names1, Names2);
  117. compare_token({'cycle_compat', Names1}, {'cycle_compat', Names2}) ->
  118. compare_cycle_compat_names(Names1, Names2);
  119. compare_token({'date', 'now', Value1}, {'date', 'now', Value2}) ->
  120. compare_value(Value1, Value2);
  121. compare_token({'filter', FilterList1, Contents1}, {'filter', FilterList2, Contents2}) ->
  122. compare_filters(FilterList1, FilterList2),
  123. compare_tree(Contents1, Contents2);
  124. compare_token({'firstof', Vars1}, {'firstof', Vars2}) ->
  125. compare_tree(Vars1, Vars2);
  126. %% TODO...
  127. %% compare_token({'for', {'in', IteratorList, Identifier}, Contents}, {'for', {'in', IteratorList, Identifier}, Contents}) -> ok;
  128. %% compare_token({'for', {'in', IteratorList, Identifier}, Contents, EmptyPartsContents}, {'for', {'in', IteratorList, Identifier}, Contents, EmptyPartsContents}) -> ok;
  129. compare_token({'if', Expression1, Contents1}, {'if', Expression2, Contents2}) ->
  130. compare_expression(Expression1, Expression2),
  131. compare_tree(Contents1, Contents2);
  132. %% compare_token({'ifchanged', Expression, IfContents}, {'ifchanged', Expression, IfContents}) -> ok;
  133. %% compare_token({'ifchangedelse', Expression, IfContents, ElseContents}, {'ifchangedelse', Expression, IfContents, ElseContents}) -> ok;
  134. %% compare_token({'ifelse', Expression, IfContents, ElseContents}, {'ifelse', Expression, IfContents, ElseContents}) -> ok;
  135. %% compare_token({'ifequal', [Arg1, Arg2], Contents}, {'ifequal', [Arg1, Arg2], Contents}) -> ok;
  136. %% compare_token({'ifequalelse', [Arg1, Arg2], IfContents, ElseContents}, {'ifequalelse', [Arg1, Arg2], IfContents, ElseContents}) -> ok;
  137. %% compare_token({'ifnotequal', [Arg1, Arg2], Contents}, {'ifnotequal', [Arg1, Arg2], Contents}) -> ok;
  138. %% compare_token({'ifnotequalelse', [Arg1, Arg2], IfContents, ElseContents}, {'ifnotequalelse', [Arg1, Arg2], IfContents, ElseContents}) -> ok;
  139. %% compare_token({'include', Value, []}, {'include', Value, []}) -> ok;
  140. %% compare_token({'include', Value, Args}, {'include', Value, Args}) -> ok;
  141. %% compare_token({'include_only', Value, []}, {'include_only', Value, []}) -> ok;
  142. %% compare_token({'include_only', Value, Args}, {'include_only', Value, Args}) -> ok;
  143. %% compare_token({'regroup', {Variable, Identifier1, Identifier2}, Contents}, {'regroup', {Variable, Identifier1, Identifier2}, Contents}) -> ok;
  144. %% compare_token({'spaceless', Contents}, {'spaceless', Contents}) -> ok;
  145. %% compare_token({'ssi', Arg}, {'ssi', Arg}) -> ok;
  146. %% compare_token({'ssi_parsed', Arg}, {'ssi_parsed', Arg}) -> ok;
  147. compare_token({'string', _, String1}, {'string', _, String2}) ->
  148. ?assertEqual(String1, String2);
  149. %% compare_token({'tag', Identifier, []}, {'tag', Identifier, []}) -> ok;
  150. %% compare_token({'tag', Identifier, Args}, {'tag', Identifier, Args}) -> ok;
  151. %% compare_token({'templatetag', Identifier}, {'templatetag', Identifier}) -> ok;
  152. %% compare_token({'trans', Value}, {'trans', Value}) -> ok;
  153. %% compare_token({'widthratio', Numerator, Denominator, Scale}, {'widthratio', Numerator, Denominator, Scale}) -> ok;
  154. %% compare_token({'with', Args, Contents}, {'with', Args, Contents}) -> ok;
  155. compare_token(ValueToken1, ValueToken2) ->
  156. compare_value(ValueToken1, ValueToken2).
  157. compare_identifier({identifier, _, Name1}, {identifier, _, Name2}) ->
  158. ?assertEqual(Name1, Name2).
  159. compare_filters(FilterList1, FilterList2) ->
  160. [compare_filter(F1, F2)
  161. || {F1, F2} <- lists:zip(FilterList1, FilterList2)].
  162. compare_filter([Identifier1], [Identifier2]) ->
  163. compare_identifier(Identifier1, Identifier2);
  164. compare_filter([Identifier1, Arg1], [Identifier2, Arg2]) ->
  165. compare_identifier(Identifier1, Identifier2),
  166. compare_value(Arg1, Arg2).
  167. compare_expression({'expr', _, Arg11, Arg12}, {'expr', _, Arg21, Arg22}) ->
  168. compare_value(Arg11, Arg21),
  169. compare_value(Arg12, Arg22);
  170. compare_expression({'expr', "not", Expr1}, {'expr', "not", Expr2}) ->
  171. compare_expression(Expr1, Expr2);
  172. compare_expression(Other1, Other2) ->
  173. compare_value(Other1, Other2).
  174. compare_value({'string_literal', _, Value1}, {'string_literal', _, Value2}) ->
  175. ?assertEqual(Value1, Value2);
  176. compare_value({'number_literal', _, Value1}, {'number_literal', _, Value2}) ->
  177. ?assertEqual(Value1, Value2);
  178. compare_value({'apply_filter', Variable1, Filter1}, {'apply_filter', Variable2, Filter2}) ->
  179. compare_value(Variable1, Variable2),
  180. compare_filter(Filter1, Filter2);
  181. compare_value({'attribute', {Variable1, Identifier1}}, {'attribute', {Variable2, Identifier2}}) ->
  182. compare_value(Variable1, Variable2),
  183. compare_identifier(Identifier1, Identifier2);
  184. compare_value({'variable', Identifier1}, {'variable', Identifier2}) ->
  185. compare_identifier(Identifier1, Identifier2).
  186. compare_args(Args1, Args2) ->
  187. [compare_arg(A1, A2)
  188. || {A1, A2} <- lists:zip(Args1, Args2)].
  189. compare_arg({{identifier, _, Name1}, Value1}, {{identifier, _, Name2}, Value2}) ->
  190. ?assertEqual(Name1, Name2),
  191. compare_value(Value1, Value2).
  192. compare_cycle_compat_names(Names1, Names2) ->
  193. [compare_identifier(N1, N2)
  194. || {N1, N2} <- lists:zip(Names1, Names2)].