-module(party_client_base_hg_tests_SUITE). -include_lib("dmsl/include/dmsl_domain_config_thrift.hrl"). -include_lib("dmsl/include/dmsl_payment_processing_thrift.hrl"). -include_lib("common_test/include/ct.hrl"). -export([all/0]). -export([groups/0]). -export([init_per_suite/1]). -export([end_per_suite/1]). -export([init_per_group/2]). -export([end_per_group/2]). -export([init_per_testcase/2]). -export([end_per_testcase/2]). -export([create_and_get_test/1]). -export([user_info_using_test/1]). -export([party_errors_test/1]). -export([party_operations_test/1]). -export([contract_create_and_get_test/1]). -export([shop_create_and_get_test/1]). -export([shop_operations_test/1]). -export([claim_operations_test/1]). -export([get_revision_test/1]). %% Internal types -type test_entry() :: atom() | {group, atom()}. -type group() :: {atom(), [Opts :: atom()], [test_entry()]}. -type config() :: [{atom(), any()}]. %% CT description -spec all() -> [test_entry()]. all() -> [ {group, party_management_api} ]. -spec groups() -> [group()]. groups() -> [ {party_management_api, [parallel], [ create_and_get_test, user_info_using_test, party_errors_test, party_operations_test, contract_create_and_get_test, shop_create_and_get_test, shop_operations_test, claim_operations_test, get_revision_test ]} ]. -spec init_per_suite(config()) -> config(). init_per_suite(Config) -> % _ = dbg:tracer(), % _ = dbg:p(all, c), % _ = dbg:tpl({'scoper_woody_event_handler', 'handle_event', '_'}, x), AppConfig = [ {dmt_client, [ {cache_update_interval, 5000}, % milliseconds {max_cache_size, #{ elements => 1, memory => 2048 % 2Kb }}, {service_urls, #{ 'Repository' => <<"http://dominant:8022/v1/domain/repository">>, 'RepositoryClient' => <<"http://dominant:8022/v1/domain/repository_client">> }} ]}, {party_client, []} ], Apps = lists:flatten([genlib_app:start_application_with(A, C) || {A, C} <- AppConfig]), {ok, Revision} = init_domain(), Client = party_client:create_client(), {ok, ClientPid} = party_client:start_link(Client), true = erlang:unlink(ClientPid), [{apps, Apps}, {client, Client}, {client_pid, ClientPid}, {test_id, genlib:to_binary(Revision)} | Config]. -spec end_per_suite(config()) -> config(). end_per_suite(C) -> true = erlang:exit(conf(client_pid, C), shutdown), genlib_app:stop_unload_applications(proplists:get_value(apps, C)). -spec init_per_group(atom(), config()) -> config(). init_per_group(Group, Config) -> [{test_id, genlib:to_binary(Group)} | Config]. -spec end_per_group(atom(), config()) -> config(). end_per_group(_Group, _Config) -> ok. -spec init_per_testcase(atom(), config()) -> config(). init_per_testcase(Name, Config) -> [{test_id, genlib:to_binary(Name)} | Config]. -spec end_per_testcase(atom(), config()) -> config(). end_per_testcase(_Name, _Config) -> ok. %% Tests -spec create_and_get_test(config()) -> any(). create_and_get_test(C) -> {ok, PartyId, Client, Context} = test_init_info(C), ContactInfo = #domain_PartyContactInfo{email = PartyId}, ok = party_client_thrift:create(PartyId, make_party_params(ContactInfo), Client, Context), {ok, Party} = party_client_thrift:get(PartyId, Client, Context), #domain_Party{id = PartyId, contact_info = ContactInfo} = Party. -spec user_info_using_test(config()) -> any(). user_info_using_test(C) -> {ok, PartyId, Client, _Context} = test_init_info(C), UserInfo = user_info(test, service), ContextWithoutUser = party_client:create_context(), ContextWithUser = party_client:create_context(#{user_info => UserInfo}), WoodyContext = woody_user_identity:put(UserInfo, woody_context:new()), ContextWithWoody = party_client:create_context(#{woody_context => WoodyContext}), ContactInfo = #domain_PartyContactInfo{email = PartyId}, ok = party_client_thrift:create(PartyId, make_party_params(ContactInfo), Client, ContextWithUser), {ok, _} = (catch party_client_thrift:get(PartyId, Client, ContextWithUser)), {ok, _} = (catch party_client_thrift:get(PartyId, Client, ContextWithWoody)), {'EXIT', {invalid_user_info, _}} = (catch party_client_thrift:get(PartyId, Client, ContextWithoutUser)), ok. -spec party_errors_test(config()) -> any(). party_errors_test(C) -> {ok, PartyId, Client, Context} = test_init_info(C), ContactInfo = #domain_PartyContactInfo{email = PartyId}, PartyParams = make_party_params(ContactInfo), ok = party_client_thrift:create(PartyId, PartyParams, Client, Context), {error, #payproc_PartyExists{}} = party_client_thrift:create(PartyId, PartyParams, Client, Context), {error, #payproc_PartyNotFound{}} = party_client_thrift:get(<<"not_exists">>, Client, Context), {error, #payproc_InvalidPartyRevision{}} = party_client_thrift:checkout(PartyId, {revision, 100500}, Client, Context), {error, #payproc_InvalidPartyStatus{}} = party_client_thrift:activate(PartyId, Client, Context), OtherContext = party_client:create_context(#{user_info => user_info(test2, external)}), {error, #payproc_InvalidUser{}} = party_client_thrift:get(PartyId, Client, OtherContext), ok. -spec party_operations_test(config()) -> any(). party_operations_test(C) -> {ok, _TestId, Client, Context} = test_init_info(C), {ok, PartyId} = create_party(C), ok = party_client_thrift:suspend(PartyId, Client, Context), ok = party_client_thrift:activate(PartyId, Client, Context), ok = party_client_thrift:block(PartyId, <<"block_test">>, Client, Context), ok = party_client_thrift:unblock(PartyId, <<"unblock_test">>, Client, Context), OtherContext = party_client:create_context(#{user_info => user_info(test2, external)}), {error, #payproc_InvalidUser{}} = party_client_thrift:get(PartyId, Client, OtherContext), ok. -spec contract_create_and_get_test(config()) -> any(). contract_create_and_get_test(C) -> {ok, _TestId, Client, Context} = test_init_info(C), {ok, PartyId} = create_party(C), {ok, ContractId} = create_contract(PartyId, C), {ok, Contract} = party_client_thrift:get_contract(PartyId, ContractId, Client, Context), #domain_Contract{id = ContractId} = Contract, Timestamp = genlib_format:format_timestamp_iso8601(genlib_time:unow() + 10), {ok, _Terms} = party_client_thrift:compute_contract_terms(PartyId, ContractId, Timestamp, Client, Context). -spec shop_create_and_get_test(config()) -> any(). shop_create_and_get_test(C) -> {ok, _TestId, Client, Context} = test_init_info(C), {ok, PartyId} = create_party(C), {ok, ContractId} = create_contract(PartyId, C), {ok, ShopId} = create_shop(PartyId, ContractId, C), {ok, Shop} = party_client_thrift:get_shop(PartyId, ShopId, Client, Context), #domain_Shop{id = ShopId} = Shop, Timestamp = genlib_format:format_timestamp_iso8601(genlib_time:unow() + 10), {ok, _Terms} = party_client_thrift:compute_shop_terms(PartyId, ShopId, Timestamp, Client, Context). -spec shop_operations_test(config()) -> any(). shop_operations_test(C) -> {ok, _TestId, Client, Context} = test_init_info(C), {ok, PartyId} = create_party(C), {ok, ContractId} = create_contract(PartyId, C), {ok, ShopId} = create_shop(PartyId, ContractId, C), ok = party_client_thrift:suspend_shop(PartyId, ShopId, Client, Context), ok = party_client_thrift:activate_shop(PartyId, ShopId, Client, Context), ok = party_client_thrift:block_shop(PartyId, ShopId, <<"block_test">>, Client, Context), ok = party_client_thrift:unblock_shop(PartyId, ShopId, <<"unblock_test">>, Client, Context). -spec claim_operations_test(config()) -> any(). claim_operations_test(C) -> {ok, TestId, Client, Context} = test_init_info(C), {ok, PartyId} = create_party(C), {ok, _ContractId} = create_contract(PartyId, C), {ok, [ContractClaim]} = party_client_thrift:get_claims(PartyId, Client, Context), #payproc_Claim{id = ClaimId, revision = _Revision} = ContractClaim, {ok, ContractClaim} = party_client_thrift:get_claim(PartyId, ClaimId, Client, Context), ContractParams = #payproc_ContractParams{ contractor = make_battle_ready_contractor(), template = undefined, payment_institution = #domain_PaymentInstitutionRef{id = 2} }, NewContractId = <>, Changeset = [ {contract_modification, #payproc_ContractModificationUnit{ id = NewContractId, modification = {creation, ContractParams} }} ], {ok, NewClaim0} = party_client_thrift:create_claim(PartyId, Changeset, Client, Context), #payproc_Claim{id = NewClaimId, revision = NewRevision0} = NewClaim0, ok = party_client_thrift:update_claim(PartyId, NewClaimId, NewRevision0, [], Client, Context), {ok, #payproc_Claim{revision = NewRevision1}} = party_client_thrift:get_claim(PartyId, NewClaimId, Client, Context), ok = party_client_thrift:deny_claim(PartyId, NewClaimId, NewRevision1, <<"deny_test">>, Client, Context), {ok, #payproc_Claim{revision = NewRevision2}} = party_client_thrift:get_claim(PartyId, NewClaimId, Client, Context), {error, #payproc_InvalidClaimStatus{}} = party_client_thrift:revoke_claim(PartyId, NewClaimId, NewRevision2, <<"revoke_test">>, Client, Context), {ok, [ContractClaim, _NewClaim]} = party_client_thrift:get_claims(PartyId, Client, Context). -spec get_revision_test(config()) -> any(). get_revision_test(C) -> {ok, PartyId, Client, Context} = test_init_info(C), ContactInfo = #domain_PartyContactInfo{email = PartyId}, ok = party_client_thrift:create(PartyId, make_party_params(ContactInfo), Client, Context), {ok, Party} = party_client_thrift:get(PartyId, Client, Context), {ok, R1} = party_client_thrift:get_revision(PartyId, Client, Context), #domain_Party{id = PartyId, contact_info = ContactInfo, revision = R1} = Party, {ok, []} = party_client_thrift:get_claims(PartyId, Client, Context), ContractParams = #payproc_ContractParams{ contractor = make_battle_ready_contractor(), template = undefined, payment_institution = #domain_PaymentInstitutionRef{id = 2} }, NewContractId = <>, Changeset = [ {contract_modification, #payproc_ContractModificationUnit{ id = NewContractId, modification = {creation, ContractParams} }} ], {ok, Claim} = party_client_thrift:create_claim(PartyId, Changeset, Client, Context), #payproc_Claim{id = ClaimId, revision = Revision} = Claim, {ok, R1} = party_client_thrift:get_revision(PartyId, Client, Context), ok = party_client_thrift:accept_claim(PartyId, ClaimId, Revision, Client, Context), {ok, R2} = party_client_thrift:get_revision(PartyId, Client, Context), R2 = R1 + 1. %% Internal functions %% Environment confirators -spec init_domain() -> {ok, integer()}. init_domain() -> {ok, _} = dmt_client_cache:update(), ok = party_domain_fixtures:cleanup(), {ok, _} = dmt_client_cache:update(), ok = party_domain_fixtures:apply_domain_fixture(), timer:sleep(5000), % Wait until hellgate dmt_client cache updating {ok, _Revision} = dmt_client_cache:update(). create_party(C) -> {ok, TestId, Client, Context} = test_init_info(C), PartyId = <>, ContactInfo = #domain_PartyContactInfo{email = <>}, ok = party_client_thrift:create(PartyId, make_party_params(ContactInfo), Client, Context), {ok, PartyId}. create_contract(PartyId, C) -> {ok, TestId, Client, Context} = test_init_info(C), ContractParams = #payproc_ContractParams{ contractor = make_battle_ready_contractor(), template = undefined, payment_institution = #domain_PaymentInstitutionRef{id = 2} }, PayoutToolParams = make_battle_ready_payout_tool_params(), ContractId = <>, Changeset = [ {contract_modification, #payproc_ContractModificationUnit{ id = ContractId, modification = {creation, ContractParams} }}, {contract_modification, #payproc_ContractModificationUnit{ id = ContractId, modification = {payout_tool_modification, #payproc_PayoutToolModificationUnit{ payout_tool_id = <<"1">>, modification = {creation, PayoutToolParams} }} }} ], create_and_accept_claim(PartyId, Changeset, Client, Context), {ok, ContractId}. create_shop(PartyId, ContractId, C) -> {ok, TestId, Client, Context} = test_init_info(C), ShopId = <>, Currency = #domain_CurrencyRef{symbolic_code = <<"RUB">>}, Details = #domain_ShopDetails{ name = <<"THRIFT SHOP">>, description = <<"Hot. Fancy. Almost free.">> }, Params = #payproc_ShopParams{ category = #domain_CategoryRef{id = 2}, location = {url, <<"https://somename.somedomain/p/123?redirect=1">>}, details = Details, contract_id = ContractId, payout_tool_id = get_first_payout_tool_id(PartyId, ContractId, Client, Context) }, ShopAccountParams = #payproc_ShopAccountParams{currency = Currency}, Changeset = [ {shop_modification, #payproc_ShopModificationUnit{ id = ShopId, modification = {creation, Params} }}, {shop_modification, #payproc_ShopModificationUnit{ id = ShopId, modification = {shop_account_creation, ShopAccountParams} }} ], create_and_accept_claim(PartyId, Changeset, Client, Context), {ok, ShopId}. create_and_accept_claim(PartyId, Changeset, Client, Context) -> {ok, Claim} = party_client_thrift:create_claim(PartyId, Changeset, Client, Context), #payproc_Claim{id = ClaimId, revision = Revision} = Claim, ok = party_client_thrift:accept_claim(PartyId, ClaimId, Revision, Client, Context). %% Config helpers -spec get_test_id(config()) -> binary(). get_test_id(Config) -> AllId = lists:reverse(proplists:append_values(test_id, Config)), erlang:iolist_to_binary([[<<".">> | I] || I <- AllId]). conf(Key, Config) -> proplists:get_value(Key, Config). %% Domain objects constructors make_party_params(ContactInfo) -> #payproc_PartyParams{contact_info = ContactInfo}. -spec user_info(any(), any()) -> party_client_context:user_info(). user_info(User, Realm) -> #{id => genlib:to_binary(User), realm => genlib:to_binary(Realm)}. create_context() -> party_client:create_context(#{user_info => user_info(test, service)}). test_init_info(C) -> PartyId = get_test_id(C), Client = conf(client, C), Context = create_context(), {ok, PartyId, Client, Context}. -spec make_battle_ready_contractor() -> dmsl_payment_processing_thrift:'Contractor'(). make_battle_ready_contractor() -> BankAccount = #domain_RussianBankAccount{ account = <<"4276300010908312893">>, bank_name = <<"SomeBank">>, bank_post_account = <<"123129876">>, bank_bik = <<"66642666">> }, {legal_entity, {russian_legal_entity, #domain_RussianLegalEntity { registered_name = <<"Hoofs & Horns OJSC">>, registered_number = <<"1234509876">>, inn = <<"1213456789012">>, actual_address = <<"Nezahualcoyotl 109 Piso 8, Centro, 06082, MEXICO">>, post_address = <<"NaN">>, representative_position = <<"Director">>, representative_full_name = <<"Someone">>, representative_document = <<"100$ banknote">>, russian_bank_account = BankAccount }} }. -spec make_battle_ready_payout_tool_params() -> dmsl_payment_processing_thrift:'PayoutToolParams'(). make_battle_ready_payout_tool_params() -> #payproc_PayoutToolParams{ currency = #domain_CurrencyRef{symbolic_code = <<"RUB">>}, tool_info = {russian_bank_account, #domain_RussianBankAccount{ account = <<"4276300010908312893">>, bank_name = <<"SomeBank">>, bank_post_account = <<"123129876">>, bank_bik = <<"66642666">> }} }. %% Other helpers -spec get_first_payout_tool_id(binary(), binary(), party_client:client(), party_client:context()) -> dmsl_domain_thrift:'PayoutToolID'(). get_first_payout_tool_id(PartyId, ContractId, Client, Context) -> {ok, Contract} = party_client_thrift:get_contract(PartyId, ContractId, Client, Context), #domain_Contract{payout_tools = PayoutTools} = Contract, case PayoutTools of [Tool | _] -> Tool#domain_PayoutTool.id; [] -> error(no_payout_tools) end.