-module(xdg_pipe_menu_renderer_tests).
-include_lib("eunit/include/eunit.hrl").
-include_lib("xmerl/include/xmerl.hrl").
-include("xdg_pipe_menu.hrl").
entry(Name, Exec, Icon) ->
entry(Name, Exec, Icon, []).
entry(Name, Exec, Icon, Categories) ->
entry(Name, Exec, Icon, Categories, false).
entry(Name, Exec, Icon, Categories, Hidden) ->
#desktop_entry{
name = Name, exec = Exec, icon = Icon, categories = Categories, hidden = Hidden
}.
empty_list_renders_empty_menu_test() ->
?assertEqual(
<<"\n"
"\n"
"\n">>,
xdg_pipe_menu_renderer:render([])
).
single_entry_with_icon_test() ->
Rendered = xdg_pipe_menu_renderer:render([
entry(<<"Firefox">>, <<"firefox">>, <<"firefox">>, [<<"Network">>])
]),
?assertEqual(
<<"\n"
"\n"
" \n"
"\n">>,
Rendered
).
entry_without_icon_omits_icon_attr_test() ->
Rendered = xdg_pipe_menu_renderer:render([
entry(<<"Foo">>, <<"foo">>, undefined, [<<"Utility">>])
]),
?assertEqual(
<<"\n"
"\n"
" \n"
"\n">>,
Rendered
).
entries_without_categories_go_in_other_submenu_test() ->
Rendered = xdg_pipe_menu_renderer:render([entry(<<"Foo">>, <<"foo">>, undefined)]),
?assertEqual(
<<"\n"
"\n"
" \n"
"\n">>,
Rendered
).
hidden_entries_are_dropped_test() ->
Entries = [
entry(<<"Visible">>, <<"visible">>, undefined, [<<"Utility">>]),
entry(<<"Invisible">>, <<"invisible">>, undefined, [<<"Utility">>], true)
],
Rendered = xdg_pipe_menu_renderer:render(Entries),
?assertNot(binary:match(Rendered, <<"Invisible">>) =/= nomatch),
?assert(binary:match(Rendered, <<"Visible">>) =/= nomatch).
hidden_entry_leaves_no_empty_submenu_test() ->
Entries = [entry(<<"Invisible">>, <<"invisible">>, undefined, [<<"Utility">>], true)],
Rendered = xdg_pipe_menu_renderer:render(Entries),
?assertNot(binary:match(Rendered, <<"Utility">>) =/= nomatch).
entries_are_sorted_case_insensitively_within_a_submenu_test() ->
Entries = [
entry(<<"zeta">>, <<"zeta">>, undefined, [<<"Utility">>]),
entry(<<"Alpha">>, <<"alpha">>, undefined, [<<"Utility">>]),
entry(<<"beta">>, <<"beta">>, undefined, [<<"Utility">>])
],
Rendered = xdg_pipe_menu_renderer:render(Entries),
Positions = [
element(1, binary:match(Rendered, <<"label=\"Alpha\"">>)),
element(1, binary:match(Rendered, <<"label=\"beta\"">>)),
element(1, binary:match(Rendered, <<"label=\"zeta\"">>))
],
?assertEqual(Positions, lists:sort(Positions)).
submenus_are_sorted_case_insensitively_test() ->
Entries = [
entry(<<"Zed App">>, <<"zed">>, undefined, [<<"zeta">>]),
entry(<<"Alpha App">>, <<"alpha">>, undefined, [<<"Alpha">>]),
entry(<<"Beta App">>, <<"beta">>, undefined, [<<"beta">>])
],
Rendered = xdg_pipe_menu_renderer:render(Entries),
Positions = [
element(1, binary:match(Rendered, <<"label=\"Alpha\"">>)),
element(1, binary:match(Rendered, <<"label=\"beta\"">>)),
element(1, binary:match(Rendered, <<"label=\"zeta\"">>))
],
?assertEqual(Positions, lists:sort(Positions)).
entry_with_multiple_categories_appears_in_each_submenu_test() ->
Entries = [entry(<<"Foo">>, <<"foo">>, undefined, [<<"Utility">>, <<"Development">>])],
Rendered = xdg_pipe_menu_renderer:render(Entries),
{Doc, _Rest} = xmerl_scan:string(binary_to_list(Rendered)),
Menus = [E || E = #xmlElement{name = menu} <- Doc#xmlElement.content],
?assertEqual([<<"Development">>, <<"Utility">>], lists:sort([menu_id(M) || M <- Menus])),
Items = [I || M <- Menus, I = #xmlElement{name = item} <- M#xmlElement.content],
?assertEqual(2, length(Items)).
escapes_special_characters_test() ->
Entry = entry(
<<"Foo & \"Baz\"">>,
<<"foo --title=\"&y\"">>,
<<"icon\"&<>">>,
[<<"Foo & ">>]
),
Rendered = xdg_pipe_menu_renderer:render([Entry]),
?assertEqual(
<<"\n"
"\n"
" \n"
"\n">>,
Rendered
).
output_is_well_formed_xml_test() ->
Entries = [
entry(<<"Firefox">>, <<"firefox">>, <<"firefox">>, [<<"Network">>]),
entry(<<"Foo & Bar">>, <<"foo">>, undefined, [<<"Network">>])
],
Rendered = xdg_pipe_menu_renderer:render(Entries),
{Doc, _Rest} = xmerl_scan:string(binary_to_list(Rendered)),
?assertEqual(openbox_pipe_menu, Doc#xmlElement.name),
Menus = [E || E = #xmlElement{name = menu} <- Doc#xmlElement.content],
?assertEqual(1, length(Menus)),
[Menu] = Menus,
Items = [E || E = #xmlElement{name = item} <- Menu#xmlElement.content],
?assertEqual(2, length(Items)).
menu_id(#xmlElement{attributes = Attrs}) ->
[Value] = [V || #xmlAttribute{name = id, value = V} <- Attrs],
list_to_binary(Value).