123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305 |
- %%%-------------------------------------------------------------------
- %%% File: erlydtl_tests.erl
- %%% @author Roberto Saccon <rsaccon@gmail.com> [http://rsaccon.com]
- %%% @author Evan Miller <emmiller@gmail.com>
- %%% @copyright 2008 Roberto Saccon, Evan Miller
- %%% @doc ErlyDTL test suite
- %%% @end
- %%%
- %%% The MIT License
- %%%
- %%% Copyright (c) 2007 Roberto Saccon
- %%%
- %%% Permission is hereby granted, free of charge, to any person obtaining a copy
- %%% of this software and associated documentation files (the "Software"), to deal
- %%% in the Software without restriction, including without limitation the rights
- %%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- %%% copies of the Software, and to permit persons to whom the Software is
- %%% furnished to do so, subject to the following conditions:
- %%%
- %%% The above copyright notice and this permission notice shall be included in
- %%% all copies or substantial portions of the Software.
- %%%
- %%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- %%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- %%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- %%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- %%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- %%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- %%% THE SOFTWARE.
- %%%
- %%% @since 2008-02-11 by Roberto Saccon
- %%%-------------------------------------------------------------------
- -module(erlydtl_functional_tests).
- -author('rsaccon@gmail.com').
- -author('emmiller@gmail.com').
- %% API
- -export([run_tests/0, run_test/1]).
- test_list() ->
- % order is important.
- ["autoescape", "comment", "extends", "filters", "for", "for_list",
- "for_tuple", "for_list_preset", "for_preset", "for_records",
- "for_records_preset", "include", "if", "if_preset", "ifequal",
- "ifequal_preset", "ifnotequal", "ifnotequal_preset", "now",
- "var", "var_preset", "cycle",
- "custom_tag", "custom_tag1", "custom_tag2", "custom_tag3",
- "custom_call",
- "include_template", "include_path", "ssi",
- "extends_path", "extends_path2", "trans" ].
- setup_compile("for_list_preset") ->
- CompileVars = [{fruit_list, [["apple", "apples"], ["banana", "bananas"], ["coconut", "coconuts"]]}],
- {ok, CompileVars};
- setup_compile("for_preset") ->
- CompileVars = [{fruit_list, ["preset-apple", "preset-banana", "preset-coconut"]}],
- {ok, CompileVars};
- setup_compile("for_records_preset") ->
- Link1a = [{name, "Amazon (preset)"}, {url, "http://amazon.com"}],
- Link2a = [{name, "Google (preset)"}, {url, "http://google.com"}],
- Link3a = [{name, "Microsoft (preset)"}, {url, "http://microsoft.com"}],
- CompileVars = [{software_links, [Link1a, Link2a, Link3a]}],
- {ok, CompileVars};
- setup_compile("if_preset") ->
- CompileVars = [{var1, "something"}],
- {ok, CompileVars};
- setup_compile("ifequal_preset") ->
- CompileVars = [{var1, "foo"}, {var2, "foo"}],
- {ok, CompileVars};
- setup_compile("ifnotequal_preset") ->
- CompileVars = [{var1, "foo"}, {var2, "foo"}],
- {ok, CompileVars};
- setup_compile("var_preset") ->
- CompileVars = [{preset_var1, "preset-var1"}, {preset_var2, "preset-var2"}],
- {ok, CompileVars};
- setup_compile(_) ->
- {ok, []}.
- %% @spec (Name::string()) -> {CompileStatus::atom(), PresetVars::list(),
- %% RenderStatus::atom(), RenderVars::list()} | skip
- %% @doc
- %% @end
- %%--------------------------------------------------------------------
- setup("autoescape") ->
- RenderVars = [{var1, "<b>bold</b>"}],
- {ok, RenderVars};
- setup("extends") ->
- RenderVars = [{base_var, "base-barstring"}, {test_var, "test-barstring"}],
- {ok, RenderVars};
- setup("filters") ->
- RenderVars = [
- {date_var1, {1975,7,24}},
- {datetime_var1, {{1975,7,24}, {7,13,1}}},
- {'list', ["eins", "zwei", "drei"]}
- ],
- {ok, RenderVars};
- setup("for") ->
- RenderVars = [{fruit_list, ["apple", "banana", "coconut"]}],
- {ok, RenderVars};
- setup("for_list") ->
- RenderVars = [{fruit_list, [["apple", "apples", "$1"], ["banana", "bananas", "$2"], ["coconut", "coconuts", "$500"]]}],
- {ok, RenderVars};
- setup("for_tuple") ->
- RenderVars = [{fruit_list, [{"apple", "apples"}, {"banana", "bananas"}, {"coconut", "coconuts"}]}],
- {ok, RenderVars};
- setup("for_records") ->
- Link1 = [{name, "Amazon"}, {url, "http://amazon.com"}],
- Link2 = [{name, "Google"}, {url, "http://google.com"}],
- Link3 = [{name, "Microsoft"}, {url, "http://microsoft.com"}],
- RenderVars = [{link_list, [Link1, Link2, Link3]}],
- {ok, RenderVars};
- setup("for_records_preset") ->
- Link1b = [{name, "Canon"}, {url, "http://canon.com"}],
- Link2b = [{name, "Leica"}, {url, "http://leica.com"}],
- Link3b = [{name, "Nikon"}, {url, "http://nikon.com"}],
- RenderVars = [{photo_links, [Link1b, Link2b, Link3b]}],
- {ok, RenderVars};
- setup("include") ->
- RenderVars = [{var1, "foostring1"}, {var2, "foostring2"}],
- {ok, RenderVars};
- setup("if") ->
- RenderVars = [{var1, "something"}],
- {ok, RenderVars};
- setup("ifequal") ->
- RenderVars = [{var1, "foo"}, {var2, "foo"}, {var3, "bar"}],
- {ok, RenderVars};
- setup("ifequal_preset") ->
- RenderVars = [{var3, "bar"}],
- {ok, RenderVars};
- setup("ifnotequal") ->
- RenderVars = [{var1, "foo"}, {var2, "foo"}, {var3, "bar"}],
- {ok, RenderVars};
- setup("var") ->
- RenderVars = [{var1, "foostring1"}, {var2, "foostring2"}, {var_not_used, "foostring3"}],
- {ok, RenderVars};
- setup("var_preset") ->
- RenderVars = [{var1, "foostring1"}, {var2, "foostring2"}],
- {ok, RenderVars};
- setup("cycle") ->
- RenderVars = [{test, [integer_to_list(X) || X <- lists:seq(1, 20)]},
- {a, "Apple"}, {b, "Banana"}, {c, "Cherry"}],
- {ok, RenderVars};
- setup("include_template") ->
- RenderVars = [{base_var, "base-barstring"}, {test_var, "test-barstring"}],
- {ok, RenderVars};
- setup("include_path") ->
- RenderVars = [{base_var, "base-barstring"}, {test_var, "test-barstring"}],
- {ok, RenderVars};
- setup("extends_path") ->
- RenderVars = [{base_var, "base-barstring"}, {test_var, "test-barstring"}],
- {ok, RenderVars};
- setup("extends_path2") ->
- RenderVars = [{base_var, "base-barstring"}, {test_var, "test-barstring"}],
- {ok, RenderVars};
- setup("trans") ->
- RenderVars = [{locale, "reverse"}],
- {ok, RenderVars};
- setup("locale") ->
- {ok, _RenderVars = [{locale, "ru"}]};
- setup("custom_tag1") ->
- {ok, [{a, <<"a1">>}], [{locale, ru}, {custom_tags_context, ctx}], [<<"b1">>, <<"\n">>]};
- setup("custom_tag2") ->
- {ok, [{a, <<"a1">>}], [{locale, ru}, {custom_tags_context, ctx}], [<<"b2">>, <<"\n">>]};
- setup("custom_tag3") ->
- {ok, [{a, <<"a1">>}], [{locale, ru}], [<<"b3">>, <<"\n">>]};
- setup("ssi") ->
- RenderVars = [{path, filename:absname(filename:join(["tests", "input", "ssi_include.html"]))}],
- {ok, RenderVars};
- %%--------------------------------------------------------------------
- %% Custom tags
- %%--------------------------------------------------------------------
- setup("custom_call") ->
- RenderVars = [{var1, "something"}],
- {ok, RenderVars};
- setup(_) ->
- {ok, []}.
-
- run_tests() ->
- io:format("Running functional tests...~n"),
- case filelib:ensure_dir(filename:join([templates_outdir(), "foo"])) of
- ok ->
- case fold_tests() of
- {N, []}->
- Msg = lists:concat(["All ", N, " functional tests passed~n~n"]),
- io:format(Msg),
- {ok, Msg};
- {_, Errs} ->
- io:format("Errors: ~p~n~n",[Errs]),
- failed
- end;
- {error, Reason} ->
- io:format("Error: ~p~n~n", [Reason]),
- failed
- end.
- run_test(Name) ->
- test_compile_render(filename:join([templates_docroot(), Name])).
- %%====================================================================
- %% Internal functions
- %%====================================================================
- fold_tests() ->
- lists:foldl(fun(Name, {AccCount, AccErrs}) ->
- case test_compile_render(Name) of
- ok ->
- {AccCount + 1, AccErrs};
- {error, Reason} ->
- {AccCount + 1, [{Name, Reason} | AccErrs]}
- end
- end, {0, []}, test_list()
- ).
- test_compile_render(Name) ->
- File = filename:join([templates_docroot(), Name]),
- Module = "example_" ++ Name,
- case setup_compile(Name) of
- {CompileStatus, CompileVars} ->
- Options = [
- {vars, CompileVars},
- {force_recompile, true},
- {custom_tags_modules, [erlydtl_custom_tags]}],
- io:format(" Template: ~p, ... compiling ... ", [Name]),
- case erlydtl:compile(File, Module, Options) of
- ok ->
- case CompileStatus of
- ok -> test_render(Name, list_to_atom(Module));
- _ -> {error, "compiling should have failed :" ++ File}
- end;
- {error, Err} ->
- case CompileStatus of
- error ->
- io:format("~n"),
- ok;
- _ ->
- io:format("~nCompile errror: ~p~n",[Err]),
- Err
- end
- end;
- skip ->
- ok;
- _ ->
- {error, "no 'setup' clause defined for this test"}
- end.
- test_render(Name, Module) ->
- File = filename:join([templates_docroot(), Name]),
- {RenderStatus, Vars, Opts, RenderResult} =
- case setup(Name) of
- {RS, V} -> {RS, V, [], undefined};
- {RS, V, O} -> {RS, V, O, undefined};
- {RS, V, O, R} -> {RS, V, O, R}
- end,
- case catch Module:render(Vars, Opts) of
- {ok, Data} ->
- io:format("rendering~n"),
- case RenderStatus of
- ok ->
- case RenderResult of
- undefined ->
- {File, _} = Module:source(),
- OutFile = filename:join([templates_outdir(), filename:basename(File)]),
- case file:open(OutFile, [write]) of
- {ok, IoDev} ->
- file:write(IoDev, Data),
- file:close(IoDev),
- ok;
- Err ->
- Err
- end;
- _ when Data =:= RenderResult ->
- ok;
- _ ->
- {error, lists:flatten(io_lib:format("Test ~s failed\n"
- "Expected: ~p\n"
- "Value: ~p\n", [Name, RenderResult, Data]))}
- end;
- _ ->
- {error, "rendering should have failed :" ++ File}
- end;
- {'EXIT', Reason} ->
- io:format("~n"),
- {error, lists:flatten(io_lib:format("failed invoking render method of ~p ~p", [Module, Reason]))};
- Err ->
- io:format("~n"),
- case RenderStatus of
- error -> ok;
- _ -> Err
- end
- end.
- templates_docroot() ->
- filename:join([erlydtl_deps:get_base_dir(), "tests", "input"]).
- templates_outdir() ->
- filename:join([erlydtl_deps:get_base_dir(), "tests", "output"]).
|