1: %% @doc This suite tests API of adhoc module which implements XEP-0050: Ad-Hoc Commands
    2: -module(adhoc_SUITE).
    3: -compile([export_all, nowarn_export_all]).
    4: 
    5: -include_lib("exml/include/exml.hrl").
    6: -include_lib("eunit/include/eunit.hrl").
    7: -include("jlib.hrl").
    8: -include("adhoc.hrl").
    9: 
   10: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   11: %%%% Suite configuration
   12: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   13: 
   14: all() ->
   15:     [
   16:         {group, basic}
   17:     ].
   18: 
   19: groups() ->
   20:     [
   21:         {basic, [parallel], [
   22:             parse_correct_request_with_form,
   23:             parse_correct_request_without_form,
   24:             parse_incorrect_request_wrong_type,
   25:             parse_incorrect_request_wrong_namespace,
   26:             produce_response_full,
   27:             produce_response_no_session_id,
   28:             produce_response_no_actions,
   29:             produce_response_no_default_action,
   30:             produce_response_default_action_not_present
   31:         ]}
   32:     ].
   33: 
   34: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   35: %%%% Tests
   36: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   37: 
   38: parse_correct_request_with_form(_C) ->
   39:     parse_correct_request(sample_form()).
   40: 
   41: parse_correct_request_without_form(_C) ->
   42:     parse_correct_request(false).
   43: 
   44: parse_correct_request(Form) ->
   45:     % given
   46:     IqRequest =
   47:         case Form of
   48:             false -> sample_request();
   49:             _ -> sample_request([Form])
   50:         end,
   51:     % when
   52:     #adhoc_request{
   53:         lang = Lang,
   54:         node = Node,
   55:         session_id = SessionID,
   56:         action = Action,
   57:         xdata = XData,
   58:         others = Others
   59:     } = adhoc:parse_request(IqRequest),
   60:     % then
   61:     ?assertEqual(Lang, <<"en-us">>),
   62:     ?assertEqual(Node, <<"node_name">>),
   63:     ?assertEqual(SessionID, <<"1">>),
   64:     ?assertEqual(Action, <<"execute">>),
   65:     ?assertEqual(XData, Form),
   66:     ?assertEqual(Others, [#xmlel{name = <<"test">>}]).
   67: 
   68: parse_incorrect_request_wrong_type(_C) ->
   69:     % given
   70:     IqRequest = (sample_request())#iq{type = get},
   71:     % when
   72:     {error, Error} = adhoc:parse_request(IqRequest),
   73:     % then
   74:     ?assert(is_bad_request(Error)).
   75: 
   76: parse_incorrect_request_wrong_namespace(_C) ->
   77:     % given
   78:     IqRequest = (sample_request())#iq{xmlns = <<"wrong_namespace">>},
   79:     % when
   80:     {error, Error} = adhoc:parse_request(IqRequest),
   81:     % then
   82:     ?assert(is_bad_request(Error)).
   83: 
   84: produce_response_full(_C) ->
   85:     % given
   86:     Actions = [<<"next">>, <<"complete">>],
   87:     Notes = [{<<"info">>, <<"Information message.">>}],
   88:     AdditionalElements = [sample_form()],
   89:     AdhocResponse = #adhoc_response{
   90:         node = <<"node_name">>,
   91:         session_id = <<"1234">>,
   92:         status = executing,
   93:         default_action = <<"next">>,
   94:         actions = Actions,
   95:         notes = Notes,
   96:         elements = AdditionalElements
   97:     },
   98:     ExpectedActionsEls = [#xmlel{
   99:         name = <<"actions">>,
  100:         attrs = [{<<"execute">>, <<"next">>}],
  101:         children = [#xmlel{name = Action} || Action <- Actions]
  102:     }],
  103:     ExpectedNotesEls = [
  104:         #xmlel{
  105:             name = <<"note">>,
  106:             attrs = [{<<"type">>, Type}],
  107:             children = [#xmlcdata{content = Text}]
  108:         }
  109:      || {Type, Text} <- Notes
  110:     ],
  111:     ExpectedChildren = ExpectedActionsEls ++ ExpectedNotesEls ++ AdditionalElements,
  112:     % when
  113:     #xmlel{
  114:         name = <<"command">>,
  115:         attrs = Attrs,
  116:         children = Children
  117:     } = adhoc:produce_response(AdhocResponse),
  118:     % then
  119:     ?assertEqual(<<"1234">>, proplists:get_value(<<"sessionid">>, Attrs)),
  120:     ?assertEqual(<<"node_name">>, proplists:get_value(<<"node">>, Attrs)),
  121:     ?assertEqual(<<"executing">>, proplists:get_value(<<"status">>, Attrs)),
  122:     ?assertEqual(lists:sort(ExpectedChildren), lists:sort(Children)).
  123: 
  124: produce_response_no_session_id(_C) ->
  125:     % given
  126:     AdhocResponse = #adhoc_response{
  127:         session_id = <<>>
  128:     },
  129:     % when
  130:     #xmlel{
  131:         name = <<"command">>,
  132:         attrs = Attrs
  133:     } = adhoc:produce_response(AdhocResponse),
  134:     % then
  135:     SessionID = proplists:get_value(<<"sessionid">>, Attrs),
  136:     ?assert(is_binary(SessionID)),
  137:     ?assertNotEqual(<<>>, SessionID).
  138: 
  139: produce_response_no_actions(_C) ->
  140:     % given
  141:     AdhocResponse = #adhoc_response{
  142:         actions = []
  143:     },
  144:     % when
  145:     #xmlel{
  146:         name = <<"command">>,
  147:         children = Children
  148:     } = adhoc:produce_response(AdhocResponse),
  149:     % then
  150:     ?assertEqual([], Children).
  151: 
  152: produce_response_no_default_action(_C) ->
  153:     % given
  154:     Actions = [<<"complete">>],
  155:     AdhocResponse = #adhoc_response{
  156:         actions = Actions
  157:     },
  158:     ExpectedActionsEls = [#xmlel{
  159:         name = <<"actions">>,
  160:         attrs = [],
  161:         children = [#xmlel{name = Action} || Action <- [<<"next">> | Actions]]
  162:     }],
  163:     % when
  164:     #xmlel{
  165:         name = <<"command">>,
  166:         children = Children
  167:     } = adhoc:produce_response(AdhocResponse),
  168:     % then
  169:     ?assertEqual(lists:sort(ExpectedActionsEls), lists:sort(Children)).
  170: 
  171: produce_response_default_action_not_present(_C) ->
  172:     % given
  173:     Actions = [<<"complete">>],
  174:     AdhocResponse = #adhoc_response{
  175:         default_action = <<"prev">>,
  176:         actions = Actions
  177:     },
  178:     ExpectedActionsEls = [#xmlel{
  179:         name = <<"actions">>,
  180:         attrs = [{<<"execute">>, <<"prev">>}],
  181:         children = [#xmlel{name = Action} || Action <- [<<"prev">> | Actions]]
  182:     }],
  183:     % when
  184:     #xmlel{
  185:         name = <<"command">>,
  186:         children = Children
  187:     } = adhoc:produce_response(AdhocResponse),
  188:     % then
  189:     ?assertEqual(lists:sort(ExpectedActionsEls), lists:sort(Children)).
  190: 
  191: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  192: %%%% Helpers
  193: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  194: 
  195: sample_form() ->
  196:     #xmlel{
  197:         name = <<"x">>,
  198:         attrs = [
  199:             {<<"xmlns">>, <<"jabber:x:data">>},
  200:             {<<"type">>, <<"form">>}
  201:         ],
  202:         children = []
  203:     }.
  204: 
  205: sample_request() ->
  206:     sample_request([]).
  207: 
  208: sample_request(MaybeForm) ->
  209:     #iq{
  210:         type = set,
  211:         lang = <<"en-us">>,
  212:         sub_el = #xmlel{
  213:             attrs = [
  214:                 {<<"node">>, <<"node_name">>},
  215:                 {<<"sessionid">>, <<"1">>},
  216:                 {<<"action">>, <<"execute">>}
  217:             ],
  218:             children = [#xmlel{name = <<"test">>}] ++ MaybeForm
  219:         },
  220:         xmlns = ?NS_COMMANDS
  221:     }.
  222: 
  223: is_bad_request(#xmlel{
  224:     name = <<"error">>,
  225:     attrs = [{<<"code">>, <<"400">>}, {<<"type">>, <<"modify">>}],
  226:     children = [#xmlel{name = <<"bad-request">>}]
  227: }) ->
  228:     true;
  229: is_bad_request(_) ->
  230:     false.