1: -module(graphql_domain_SUITE).
    2: 
    3:  -include_lib("common_test/include/ct.hrl").
    4:  -include_lib("eunit/include/eunit.hrl").
    5:  -include_lib("exml/include/exml.hrl").
    6: 
    7:  -compile([export_all, nowarn_export_all]).
    8: 
    9: -import(distributed_helper, [mim/0, require_rpc_nodes/1, rpc/4]).
   10: -import(graphql_helper, [execute_auth/2, init_admin_handler/1]).
   11: 
   12: -define(HOST_TYPE, <<"dummy auth">>).
   13: -define(SECOND_HOST_TYPE, <<"test type">>).
   14: 
   15: suite() ->
   16:     require_rpc_nodes([mim]) ++ escalus:suite().
   17: 
   18: all() ->
   19:      [{group, domain_handler}].
   20: 
   21: groups() ->
   22:      [{domain_handler, [sequence], domain_handler()}].
   23: 
   24: domain_handler() ->
   25:     [create_domain,
   26:      unknown_host_type_error_formatting,
   27:      static_domain_error_formatting,
   28:      domain_duplicate_error_formatting,
   29:      domain_not_found_error_formatting_after_mutation_disable_domain,
   30:      domain_not_found_error_formatting_after_mutation_enable_domain,
   31:      domain_not_found_error_formatting_after_query,
   32:      wrong_host_type_error_formatting,
   33:      disable_domain,
   34:      enable_domain,
   35:      get_domains_by_host_type,
   36:      get_domain_details,
   37:      delete_domain,
   38:      get_domains_after_deletion].
   39: 
   40: init_per_suite(Config) ->
   41:     case mongoose_helper:is_rdbms_enabled(?HOST_TYPE) of
   42:         true -> escalus:init_per_suite(init_admin_handler(Config));
   43:         false -> {skip, require_rdbms}
   44:     end.
   45: 
   46: end_per_suite(Config) ->
   47:     escalus_fresh:clean(),
   48:     escalus:end_per_suite(Config).
   49: 
   50: init_per_testcase(CaseName, Config) ->
   51:      escalus:init_per_testcase(CaseName, Config).
   52: 
   53: end_per_testcase(CaseName, Config) ->
   54:      escalus:end_per_testcase(CaseName, Config).
   55: 
   56: create_domain(Config) ->
   57:     create_domain(Config, <<"exampleDomain">>),
   58:     create_domain(Config, <<"exampleDomain2">>).
   59: 
   60: create_domain(Config, DomainName) ->
   61:     Vars = #{domain => DomainName, hostType => ?HOST_TYPE},
   62:     Result = execute_auth(#{query => create_domain_call(), variables => Vars,
   63:         operationName => <<"M1">>}, Config),
   64:     ParsedResult = ok_result(<<"domains">>, <<"addDomain">>, Result),
   65:     ?assertEqual(#{<<"domain">> => DomainName,
   66:         <<"hostType">> => ?HOST_TYPE,
   67:         <<"enabled">> => null}, ParsedResult).
   68: 
   69: unknown_host_type_error_formatting(Config) ->
   70:     DomainName = <<"exampleDomain">>,
   71:     HostType = <<"NonExistingHostType">>,
   72:     Vars = #{domain => DomainName, hostType => HostType},
   73:     Result = execute_auth(#{query => create_domain_call(), variables => Vars,
   74:                    operationName => <<"M1">>}, Config),
   75:     ParsedResult = error_result(1, Result),
   76:     ?assertEqual(#{<<"extensions">> =>
   77:                      #{<<"code">> => <<"unknown_host_type">>,
   78:                        <<"hostType">> => HostType},
   79:                    <<"message">> => <<"Unknown host type">>,
   80:                    <<"path">> => [<<"domains">>, <<"addDomain">>]}, ParsedResult).
   81: 
   82: static_domain_error_formatting(Config) ->
   83:     DomainName = <<"localhost">>,
   84:     Vars = #{domain => DomainName, hostType => ?HOST_TYPE},
   85:     Result = execute_auth(#{query => create_domain_call(), variables => Vars,
   86:                    operationName => <<"M1">>}, Config),
   87:     ParsedResult = error_result(1, Result),
   88:     ?assertEqual(#{<<"extensions">> =>
   89:                      #{<<"code">> => <<"domain_static">>,
   90:                        <<"domain">> => DomainName},
   91:                    <<"message">> => <<"Domain static">>,
   92:                    <<"path">> => [<<"domains">>, <<"addDomain">>]}, ParsedResult).
   93: 
   94: domain_duplicate_error_formatting(Config) ->
   95:     DomainName = <<"exampleDomain">>,
   96:     Vars = #{domain => DomainName, hostType => ?SECOND_HOST_TYPE},
   97:     Result = execute_auth(#{query => create_domain_call(), variables => Vars,
   98:                    operationName => <<"M1">>}, Config),
   99:     ParsedResult = error_result(1, Result),
  100:     ?assertEqual(#{<<"extensions">> =>
  101:                      #{<<"code">> => <<"domain_duplicate">>,
  102:                        <<"domain">> => DomainName},
  103:                    <<"message">> => <<"Domain already exists">>,
  104:                    <<"path">> => [<<"domains">>, <<"addDomain">>]}, ParsedResult).
  105: 
  106: domain_not_found_error_formatting_after_mutation_enable_domain(Config) ->
  107:     DomainName = <<"NonExistingDomain">>,
  108:     Vars = #{domain => DomainName},
  109:     Result = execute_auth(#{query => enable_domain_call(), variables => Vars,
  110:                    operationName => <<"M1">>}, Config),
  111:     domain_not_found_error_formatting(Result, DomainName, <<"enableDomain">>).
  112: 
  113: domain_not_found_error_formatting_after_mutation_disable_domain(Config) ->
  114:     DomainName = <<"NonExistingDomain">>,
  115:     Vars = #{domain => DomainName},
  116:     Result = execute_auth(#{query => disable_domain_call(), variables => Vars,
  117:                    operationName => <<"M1">>}, Config),
  118:     domain_not_found_error_formatting(Result, DomainName, <<"disableDomain">>).
  119: 
  120: domain_not_found_error_formatting_after_query(Config) ->
  121:     DomainName = <<"NonExistingDomain">>,
  122:     Vars = #{domain => DomainName},
  123:     Result = execute_auth(#{query => get_domain_details_call(), variables => Vars,
  124:                    operationName => <<"Q1">>}, Config),
  125:     domain_not_found_error_formatting(Result, DomainName, <<"domainDetails">>).
  126: 
  127: domain_not_found_error_formatting(Result, DomainName, GraphqlCall) ->
  128:     ParsedResult = error_result(1, Result),
  129:     ?assertEqual(#{<<"extensions">> =>
  130:                      #{<<"code">> => <<"domain_not_found">>,
  131:                        <<"domain">> => DomainName},
  132:                    <<"message">> => <<"Given domain does not exist">>,
  133:                    <<"path">> => [<<"domains">>, GraphqlCall]}, ParsedResult).
  134: 
  135: wrong_host_type_error_formatting(Config) ->
  136:     DomainName = <<"exampleDomain">>,
  137:     Vars = #{domain => DomainName, hostType => ?SECOND_HOST_TYPE},
  138:     Result = execute_auth(#{query => delete_domain_call(), variables => Vars,
  139:                    operationName => <<"M1">>}, Config),
  140:     ParsedResult = error_result(1, Result),
  141:     ?assertEqual(#{<<"extensions">> =>
  142:                      #{<<"code">> => <<"wrong_host_type">>,
  143:                        <<"hostType">> => ?SECOND_HOST_TYPE},
  144:                    <<"message">> => <<"Wrong host type">>,
  145:                    <<"path">> => [<<"domains">>, <<"removeDomain">>]}, ParsedResult).
  146: 
  147: disable_domain(Config) ->
  148:     Vars = #{domain => <<"exampleDomain">>},
  149:     Result = execute_auth(#{query => disable_domain_call(), variables => Vars,
  150:                    operationName => <<"M1">>}, Config),
  151:     ParsedResult = ok_result(<<"domains">>, <<"disableDomain">>, Result),
  152:     ?assertEqual(#{<<"domain">> => <<"exampleDomain">>, <<"enabled">> => false}, ParsedResult),
  153:     {ok, Domain} = rpc(mim(), mongoose_domain_sql, select_domain, [<<"exampleDomain">>]),
  154:     ?assertEqual(#{host_type => ?HOST_TYPE,
  155:                    enabled => false}, Domain).
  156: 
  157: 
  158: enable_domain(Config) ->
  159:     Vars = #{domain => <<"exampleDomain">>},
  160:     Result = execute_auth(#{query => enable_domain_call(), variables => Vars,
  161:                    operationName => <<"M1">>}, Config),
  162:     ParsedResult = ok_result(<<"domains">>, <<"enableDomain">>, Result),
  163:     ?assertEqual(#{<<"domain">> => <<"exampleDomain">>, <<"enabled">> => true}, ParsedResult).
  164: 
  165: get_domains_by_host_type(Config) ->
  166:     Vars = #{hostType => ?HOST_TYPE},
  167:     Result = execute_auth(#{query => get_domains_by_host_type_call(),
  168:                    variables => Vars,
  169:                    operationName => <<"Q1">>}, Config),
  170:     ParsedResult = ok_result(<<"domains">>, <<"domainsByHostType">>, Result),
  171:     ?assertEqual(lists:sort([<<"exampleDomain">>, <<"exampleDomain2">>]),
  172:                  lists:sort(ParsedResult)).
  173: 
  174: get_domain_details(Config) ->
  175:     Vars = #{domain => <<"exampleDomain">>},
  176:     Result = execute_auth(#{query => get_domain_details_call(),
  177:                    variables => Vars,
  178:                    operationName => <<"Q1">>}, Config),
  179:     ParsedResult = ok_result(<<"domains">>, <<"domainDetails">>, Result),
  180:     ?assertEqual(#{<<"domain">> => <<"exampleDomain">>,
  181:                    <<"hostType">> => ?HOST_TYPE,
  182:                    <<"enabled">> => true}, ParsedResult).
  183: 
  184: delete_domain(Config) ->
  185:     Vars = #{domain => <<"exampleDomain">>, hostType => ?HOST_TYPE},
  186:     Result1 = execute_auth(#{query => delete_domain_call(), variables => Vars,
  187:                    operationName => <<"M1">>}, Config),
  188:     ParsedResult1 = ok_result(<<"domains">>, <<"removeDomain">>, Result1),
  189:     ?assertEqual(#{<<"msg">> => <<"Domain removed!">>,
  190:                    <<"domain">> => #{<<"domain">> => <<"exampleDomain">>}},
  191:                    ParsedResult1),
  192: 
  193:     Vars2 = #{domain => <<"exampleDomain2">>, hostType => ?HOST_TYPE},
  194:     Result2 = execute_auth(#{query => delete_domain_call(), variables => Vars2,
  195:                    operationName => <<"M1">>}, Config),
  196:     ParsedResult2 = ok_result(<<"domains">>, <<"removeDomain">>, Result2),
  197:     ?assertEqual(#{<<"msg">> => <<"Domain removed!">>,
  198:                    <<"domain">> => #{<<"domain">> => <<"exampleDomain2">>}},
  199:                    ParsedResult2).
  200: 
  201: get_domains_after_deletion(Config) ->
  202:     Vars = #{hostType => ?HOST_TYPE},
  203:     Result = execute_auth(#{query => get_domains_by_host_type_call(),
  204:                    variables => Vars,
  205:                    operationName => <<"Q1">>}, Config),
  206:     ParsedResult = ok_result(<<"domains">>, <<"domainsByHostType">>, Result),
  207:     ?assertEqual([], ParsedResult).
  208: 
  209: create_domain_call() ->
  210:     <<"mutation M1($domain: String!, $hostType: String!)
  211:            {domains
  212:                {addDomain(domain: $domain, hostType: $hostType)
  213:                    {
  214:                        domain
  215:                        hostType
  216:                        enabled
  217:                    }
  218:                }
  219:            }">>.
  220: 
  221: enable_domain_call() ->
  222:     <<"mutation M1($domain: String!)
  223:            {domains
  224:                {enableDomain(domain: $domain)
  225:                    {
  226:                        enabled
  227:                        domain
  228:                    }
  229:                }
  230:            }">>.
  231: 
  232: disable_domain_call() ->
  233:     <<"mutation M1($domain: String!)
  234:            {domains
  235:                {disableDomain(domain: $domain)
  236:                    {
  237:                        enabled
  238:                        domain
  239:                    }
  240:                }
  241:            }">>.
  242: 
  243: get_domains_by_host_type_call() ->
  244:     <<"query Q1($hostType: String!)
  245:            {domains
  246:                {domainsByHostType(hostType: $hostType)}
  247:            }">>.
  248: 
  249: get_domain_details_call() ->
  250:     <<"query Q1($domain: String!)
  251:            {domains
  252:                {domainDetails(domain: $domain)
  253:                    {
  254:                        domain
  255:                        hostType
  256:                        enabled
  257:                    }
  258:                }
  259:            }">>.
  260: 
  261: delete_domain_call() ->
  262:     <<"mutation M1($domain: String!, $hostType: String!)
  263:            {domains
  264:                {removeDomain(domain: $domain, hostType: $hostType)
  265:                    {
  266:                        msg
  267:                        domain
  268:                            {domain}
  269:                    }
  270:                }
  271:            }">>.
  272: 
  273: %% Helpers
  274: ok_result(What1, What2, {{<<"200">>, <<"OK">>}, #{<<"data">> := Data}}) ->
  275:     maps:get(What2, maps:get(What1, Data)).
  276: 
  277: error_result(ErrorNumber, {{<<"200">>, <<"OK">>}, #{<<"errors">> := Errors}}) ->
  278:     lists:nth(ErrorNumber, Errors).