573 lines
21 KiB
Ruby
573 lines
21 KiB
Ruby
# frozen_string_literal: true
|
||
|
||
describe 'API::V2::Resource::Profiles' do
|
||
before { allow(Barong::App.config).to receive_messages(kyc_provider: 'local') }
|
||
|
||
include_context 'bearer authentication'
|
||
let!(:create_member_permission) do
|
||
create :permission,
|
||
role: 'member'
|
||
end
|
||
let!(:optional_params) do
|
||
{
|
||
metadata: {
|
||
gender: Faker::Creature::Dog.gender,
|
||
place_of_birth: Faker::Address.city
|
||
}.to_json
|
||
}
|
||
end
|
||
|
||
describe 'POST /api/v2/resource/profiles' do
|
||
describe 'KYC verification' do
|
||
let!(:request_params) do
|
||
{
|
||
last_name: Faker::Name.last_name,
|
||
first_name: Faker::Name.first_name,
|
||
dob: Faker::Date.birthday,
|
||
country: Faker::Address.country_code,
|
||
city: Faker::Address.city,
|
||
address: Faker::Address.state,
|
||
postcode: Faker::Address.zip_code
|
||
}
|
||
end
|
||
let!(:url) { '/api/v2/resource/profiles' }
|
||
|
||
it 'triggers KycService' do
|
||
expect(KycService).to receive(:profile_step)
|
||
|
||
post url, params: request_params, headers: auth_header
|
||
expect(response.status).to eq(201)
|
||
end
|
||
|
||
context 'Local verification' do
|
||
before { allow(Barong::App.config).to receive_messages(kyc_provider: 'local') }
|
||
|
||
it 'adds a label for first verification' do
|
||
expect(test_user.labels).to eq([])
|
||
post url, params: request_params, headers: auth_header
|
||
expect(test_user.reload.labels.count).to eq(1)
|
||
expect(test_user.reload.labels.first.key).to eq('profile')
|
||
expect(test_user.reload.labels.first.value).to eq('drafted')
|
||
end
|
||
|
||
it 'doesnt trigger KYCAID worker' do
|
||
expect(KycService).to receive(:profile_step)
|
||
expect(KYC::Kycaid::ApplicantWorker).not_to receive(:perform_async)
|
||
|
||
post url, params: request_params, headers: auth_header
|
||
expect(response.status).to eq(201)
|
||
end
|
||
|
||
it 'updates label on re-submit' do
|
||
expect(test_user.labels).to eq([])
|
||
post url, params: request_params, headers: auth_header
|
||
expect(test_user.reload.labels.count).to eq(1)
|
||
expect(test_user.reload.labels.first.key).to eq('profile')
|
||
expect(test_user.reload.labels.first.value).to eq('drafted')
|
||
|
||
put url, params: request_params.merge(confirm: true), headers: auth_header
|
||
expect(test_user.reload.labels.count).to eq(1)
|
||
expect(test_user.reload.labels.first.key).to eq('profile')
|
||
expect(test_user.reload.labels.first.value).to eq('submitted')
|
||
end
|
||
end
|
||
|
||
context 'KYCAID verification' do
|
||
before { allow(Barong::App.config).to receive_messages(kyc_provider: 'kycaid') }
|
||
|
||
it 'adds a label for first verification' do
|
||
expect(test_user.labels).to eq([])
|
||
post url, params: request_params, headers: auth_header
|
||
expect(test_user.reload.labels.count).to eq(1)
|
||
expect(test_user.reload.labels.first.key).to eq('profile')
|
||
expect(test_user.reload.labels.first.value).to eq('drafted')
|
||
end
|
||
|
||
it 'updates label on re-submit' do
|
||
expect(test_user.labels).to eq([])
|
||
post url, params: request_params, headers: auth_header
|
||
expect(test_user.reload.labels.count).to eq(1)
|
||
expect(test_user.reload.labels.first.key).to eq('profile')
|
||
expect(test_user.reload.labels.first.value).to eq('drafted')
|
||
|
||
put url, params: request_params.merge(confirm: true), headers: auth_header
|
||
expect(test_user.reload.labels.count).to eq(1)
|
||
expect(test_user.reload.labels.first.key).to eq('profile')
|
||
expect(test_user.reload.labels.first.value).to eq('submitted')
|
||
end
|
||
|
||
it 'triggers KYCAID worker on submitted state' do
|
||
expect(KYC::Kycaid::ApplicantWorker).to receive(:perform_async)
|
||
post url, params: request_params.merge(confirm: true), headers: auth_header
|
||
expect(response.status).to eq(201)
|
||
end
|
||
|
||
it 'doesnt trigger KYCAID worker on drafted state' do
|
||
expect(KYC::Kycaid::ApplicantWorker).not_to receive(:perform_async)
|
||
post url, params: request_params, headers: auth_header
|
||
expect(response.status).to eq(201)
|
||
end
|
||
|
||
it 'doesnt trigger KYCAID worker on rejected state' do
|
||
post url, params: request_params.merge(confirm: true), headers: auth_header
|
||
expect(response.status).to eq(201)
|
||
|
||
expect(KYC::Kycaid::ApplicantWorker).not_to receive(:perform_async)
|
||
test_user.reload.profiles.last.update(state: 'rejected')
|
||
end
|
||
|
||
it 'doesnt trigger KYCAID worker on verified state' do
|
||
post url, params: request_params.merge(confirm: true), headers: auth_header
|
||
expect(response.status).to eq(201)
|
||
|
||
expect(KYC::Kycaid::ApplicantWorker).not_to receive(:perform_async)
|
||
test_user.reload.profiles.last.update(state: 'verified')
|
||
end
|
||
end
|
||
end
|
||
|
||
let!(:url) { '/api/v2/resource/profiles' }
|
||
let!(:user_info) { '/api/v2/resource/users/me' }
|
||
let!(:request_params) do
|
||
{
|
||
last_name: Faker::Name.last_name,
|
||
first_name: Faker::Name.first_name,
|
||
dob: Faker::Date.birthday,
|
||
country: Faker::Address.country_code_long,
|
||
city: Faker::Address.city,
|
||
address: Faker::Address.state,
|
||
postcode: Faker::Address.zip_code
|
||
}
|
||
end
|
||
|
||
let!(:asian_params) do
|
||
{
|
||
last_name: "국",
|
||
first_name: "채원",
|
||
dob: Faker::Date.birthday,
|
||
country: Faker::Address.country_code_long,
|
||
city: "안산시",
|
||
address: "사직로3길 23",
|
||
postcode: Faker::Address.zip_code
|
||
}
|
||
end
|
||
|
||
it 'accept / , ; in address' do
|
||
request_params[:address] = '28/2 Kevin Brook; Miami, USA'
|
||
expect { post url, params: request_params, headers: auth_header }
|
||
.to change { Profile.count }.by (1)
|
||
expect(response.status).to eq(201)
|
||
res = json_body
|
||
expect(res[:address]).to eq request_params[:address]
|
||
end
|
||
|
||
it 'accept . in address' do
|
||
request_params[:address] = 'Larkin Fork.South, New York/AP'
|
||
expect { post url, params: request_params, headers: auth_header }
|
||
.to change { Profile.count }.by (1)
|
||
expect(response.status).to eq(201)
|
||
res = json_body
|
||
expect(res[:address]).to eq request_params[:address]
|
||
end
|
||
|
||
it 'accept # ~ \ : " & ( ) in address' do
|
||
request_params[:address] = '28~1/2 \"Kevin & Brook": (Miami, USA)'
|
||
expect { post url, params: request_params, headers: auth_header }
|
||
.to change { Profile.count }.by (1)
|
||
expect(response.status).to eq(201)
|
||
res = json_body
|
||
expect(res[:address]).to eq request_params[:address]
|
||
end
|
||
|
||
it "accept ' in address" do
|
||
request_params[:address] = "'Larkin Fork' South New York"
|
||
expect { post url, params: request_params, headers: auth_header }
|
||
.to change { Profile.count }.by (1)
|
||
expect(response.status).to eq(201)
|
||
res = json_body
|
||
expect(res[:address]).to eq request_params[:address]
|
||
end
|
||
|
||
it "accept – in address" do
|
||
request_params[:address] = "'Larkin–Fork' South New York"
|
||
expect { post url, params: request_params, headers: auth_header }
|
||
.to change { Profile.count }.by (1)
|
||
expect(response.status).to eq(201)
|
||
res = json_body
|
||
expect(res[:address]).to eq request_params[:address]
|
||
end
|
||
|
||
it "doesn't accept @ in address" do
|
||
request_params[:address] = "'Larkin–Fork' @South New York"
|
||
expect { post url, params: request_params, headers: auth_header }
|
||
.not_to change { Profile.count }
|
||
expect(response.status).to eq(422)
|
||
end
|
||
|
||
it 'accept . in city' do
|
||
request_params[:city] = 'St. Petersburg'
|
||
expect { post url, params: request_params, headers: auth_header }
|
||
.to change { Profile.count }.by (1)
|
||
expect(response.status).to eq(201)
|
||
res = json_body
|
||
expect(res[:city]).to eq request_params[:city]
|
||
end
|
||
|
||
it 'accept dash in city' do
|
||
request_params[:city] = 'Hubli–Dharwad'
|
||
expect { post url, params: request_params, headers: auth_header }
|
||
.to change { Profile.count }.by (1)
|
||
expect(response.status).to eq(201)
|
||
res = json_body
|
||
expect(res[:city]).to eq request_params[:city]
|
||
end
|
||
|
||
it 'accept hyphen in city' do
|
||
request_params[:city] = 'Hubli-Dharwad'
|
||
expect { post url, params: request_params, headers: auth_header }
|
||
.to change { Profile.count }.by (1)
|
||
expect(response.status).to eq(201)
|
||
res = json_body
|
||
expect(res[:city]).to eq request_params[:city]
|
||
end
|
||
|
||
it 'accept \' in city' do
|
||
request_params[:city] = 'Cava de\' Tirreni'
|
||
expect { post url, params: request_params, headers: auth_header }
|
||
.to change { Profile.count }.by (1)
|
||
expect(response.status).to eq(201)
|
||
res = json_body
|
||
expect(res[:city]).to eq request_params[:city]
|
||
end
|
||
|
||
it "doesn't accept # in city" do
|
||
request_params[:city] = 'Cava de\' #Tirreni'
|
||
expect { post url, params: request_params, headers: auth_header }
|
||
.not_to change { Profile.count }
|
||
expect(response.status).to eq(422)
|
||
end
|
||
|
||
it "doesn't accept @ in city" do
|
||
request_params[:city] = 'Cava de\' @Tirreni'
|
||
expect { post url, params: request_params, headers: auth_header }
|
||
.not_to change { Profile.count }
|
||
expect(response.status).to eq(422)
|
||
end
|
||
|
||
it 'creates new profile with only required fields' do
|
||
expect { post url, params: request_params, headers: auth_header }
|
||
.to change { Profile.count }.by (1)
|
||
expect(response.status).to eq(201)
|
||
|
||
res = json_body
|
||
expect(res[:last_name]).to eq request_params[:last_name].sub(/(?<=\A.{1})(.*)/) { |match| '*' * match.length }
|
||
expect(res[:first_name]).to eq request_params[:first_name]
|
||
expect(res[:dob]).to eq request_params[:dob].to_s.sub(/(?<=\A.{8})(.*)/) { |match| '*' * match.length }
|
||
expect(res[:country]).to eq request_params[:country]
|
||
expect(res[:city]).to eq request_params[:city]
|
||
expect(res[:address]).to eq request_params[:address]
|
||
expect(res[:postcode]).to eq request_params[:postcode]
|
||
expect(res[:metadata]).to be_blank
|
||
end
|
||
|
||
it 'creates new profile with only required fields without masking' do
|
||
Barong::App.config.stub(:api_data_masking_enabled).and_return(false)
|
||
expect { post url, params: request_params, headers: auth_header }
|
||
.to change { Profile.count }.by (1)
|
||
expect(response.status).to eq(201)
|
||
|
||
res = json_body
|
||
expect(res[:last_name]).to eq request_params[:last_name]
|
||
expect(res[:first_name]).to eq request_params[:first_name]
|
||
expect(res[:dob]).to eq request_params[:dob].to_s
|
||
expect(res[:country]).to eq request_params[:country]
|
||
expect(res[:city]).to eq request_params[:city]
|
||
expect(res[:address]).to eq request_params[:address]
|
||
expect(res[:postcode]).to eq request_params[:postcode]
|
||
expect(res[:metadata]).to be_blank
|
||
end
|
||
|
||
it 'creates new profile with corean symbols fields' do
|
||
expect { post url, params: asian_params, headers: auth_header }
|
||
.to change { Profile.count }.by (1)
|
||
expect(response.status).to eq(201)
|
||
|
||
res = json_body
|
||
|
||
expect(res[:last_name]).to eq asian_params[:last_name]
|
||
expect(res[:first_name]).to eq asian_params[:first_name]
|
||
expect(res[:dob]).to eq asian_params[:dob].to_s.sub(/(?<=\A.{8})(.*)/) { |match| '*' * match.length }
|
||
expect(res[:country]).to eq asian_params[:country]
|
||
expect(res[:city]).to eq asian_params[:city]
|
||
expect(res[:address]).to eq asian_params[:address]
|
||
expect(res[:postcode]).to eq asian_params[:postcode]
|
||
expect(res[:metadata]).to be_blank
|
||
end
|
||
|
||
it 'creates new profile with all metadata fields' do
|
||
expect { post url, params: request_params.merge(optional_params), headers: auth_header }
|
||
.to change { Profile.count }.by (1)
|
||
expect(response.status).to eq(201)
|
||
|
||
res = json_body
|
||
expect(res[:metadata]).to eq(optional_params[:metadata])
|
||
end
|
||
|
||
it 'renders an error if metadata is not json' do
|
||
expect { post url, params: request_params.merge({ metadata: '{ bar: baz }' }), headers: auth_header }
|
||
.not_to change { Profile.count }
|
||
expect_status_to_eq 422
|
||
expect_body.to eq(errors: ["metadata.invalid_format"])
|
||
end
|
||
|
||
context 'create another one profile with state drafted' do
|
||
before do
|
||
post url, params: request_params.merge(optional_params), headers: auth_header
|
||
end
|
||
|
||
it 'doesn\'t create new profile' do
|
||
post url, params: request_params.merge(optional_params), headers: auth_header
|
||
|
||
result = json_body
|
||
expect(*result[:errors]).to eq('state.exists')
|
||
end
|
||
end
|
||
|
||
context 'create another one profile with state submitted' do
|
||
before do
|
||
post url, params: request_params.merge(optional_params, confirm: true), headers: auth_header
|
||
end
|
||
|
||
it 'doesn\'t create new profile' do
|
||
post url, params: request_params.merge(optional_params, confirm: true), headers: auth_header
|
||
|
||
result = json_body
|
||
expect(*result[:errors]).to eq('state.exists')
|
||
end
|
||
end
|
||
|
||
context 'create another one profile with state submitted and drafted' do
|
||
before do
|
||
post url, params: request_params.merge(optional_params, confirm: true), headers: auth_header
|
||
end
|
||
|
||
it 'doesn\'t create new profile' do
|
||
post url, params: request_params.merge(optional_params), headers: auth_header
|
||
|
||
result = json_body
|
||
expect(*result[:errors]).to eq('state.exists')
|
||
end
|
||
end
|
||
|
||
context 'partial creating profile' do
|
||
context 'empty params' do
|
||
|
||
it 'returns profile' do
|
||
expect { post url, params: {}, headers: auth_header }
|
||
.to change { Profile.count }.by (1)
|
||
|
||
expect(response.status).to eq(201)
|
||
expect(json_body[:state]).to eq('drafted')
|
||
expect(json_body[:metadata].blank?).to be_truthy
|
||
Profile::OPTIONAL_PARAMS.each { |p|
|
||
expect(json_body[p].blank?).to be_truthy
|
||
}
|
||
Profile::OPTIONAL_PARAMS.each { |p|
|
||
expect(json_body.with_indifferent_access[p].blank?).to be_truthy
|
||
}
|
||
expect(Profile.last.user.labels.find_by(key: 'profile').value).to eq('drafted')
|
||
end
|
||
end
|
||
|
||
context 'several params' do
|
||
let(:params) { { last_name: Faker::Name.last_name, first_name: Faker::Name.first_name } }
|
||
|
||
it 'returns profile' do
|
||
expect { post url, params: params, headers: auth_header }
|
||
.to change { Profile.count }.by (1)
|
||
|
||
expect(response.status).to eq(201)
|
||
expect(json_body[:first_name].nil?).to be_falsey
|
||
expect(json_body[:last_name].nil?).to be_falsey
|
||
expect(json_body[:state]).to eq('drafted')
|
||
expect(json_body[:metadata].blank?).to be_truthy
|
||
(Profile::OPTIONAL_PARAMS - params.stringify_keys.keys).each { |p|
|
||
expect(json_body.with_indifferent_access[p].blank?).to be_truthy
|
||
}
|
||
expect(Profile.last.user.labels.find_by(key: :profile).value).to eq('drafted')
|
||
end
|
||
end
|
||
|
||
context 'several params with profile confirmation' do
|
||
let(:params) { { last_name: Faker::Name.last_name, first_name: Faker::Name.first_name } }
|
||
|
||
it 'returns profile' do
|
||
expect { post url, params: params.merge(confirm: true), headers: auth_header }
|
||
.to change { Profile.count }.by (1)
|
||
|
||
expect(response.status).to eq(201)
|
||
expect(json_body[:first_name].nil?).to be_falsey
|
||
expect(json_body[:last_name].nil?).to be_falsey
|
||
expect(json_body[:state]).to eq('submitted')
|
||
expect(json_body[:metadata].blank?).to be_truthy
|
||
(Profile::OPTIONAL_PARAMS - params.stringify_keys.keys).each { |p|
|
||
expect(json_body.with_indifferent_access[p].blank?).to be_truthy
|
||
}
|
||
expect(Profile.last.user.labels.find_by(key: :profile).value).to eq('submitted')
|
||
end
|
||
end
|
||
|
||
context 'full profile params' do
|
||
it 'returns profile' do
|
||
expect { post url, params: request_params, headers: auth_header }
|
||
.to change { Profile.count }.by (1)
|
||
|
||
expect(response.status).to eq(201)
|
||
expect(json_body[:state]).to eq('drafted')
|
||
expect(json_body[:metadata].blank?).to be_truthy
|
||
request_params.keys.each { |p|
|
||
expect(json_body[p].present?).to be_truthy
|
||
}
|
||
expect(Profile.last.user.labels.find_by(key: 'profile').value).to eq('drafted')
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
describe 'GET /api/v2/resource/profiles/me' do
|
||
let!(:url) { '/api/v2/resource/profiles/me' }
|
||
let!(:request_params) do
|
||
{
|
||
first_name: Faker::Name.first_name,
|
||
last_name: Faker::Name.last_name,
|
||
dob: Faker::Date.birthday,
|
||
address: Faker::Address.state,
|
||
postcode: Faker::Address.zip_code,
|
||
city: Faker::Address.city,
|
||
country: Faker::Address.country_code_long
|
||
}
|
||
end
|
||
|
||
it 'returns user profile data with metadata' do
|
||
post '/api/v2/resource/profiles', params: request_params.merge(optional_params),
|
||
headers: auth_header
|
||
expect(response.status).to eq(201)
|
||
|
||
get url, headers: auth_header
|
||
expect(response.status).to eq(200)
|
||
last_name = request_params[:last_name].sub(/(?<=\A.{1})(.*)/) { |match| '*' * match.length }
|
||
dob = request_params[:dob].to_s.sub(/(?<=\A.{8})(.*)/) { |match| '*' * match.length }
|
||
expected_json = request_params.merge(state: 'drafted', last_name: last_name,dob: dob).merge(optional_params).to_json
|
||
expect(JSON.parse(response.body)[0].except('created_at', 'updated_at')).to eq(JSON.parse(expected_json))
|
||
end
|
||
end
|
||
|
||
context 'event API behavior' do
|
||
let!(:url) { '/api/v2/resource/profiles' }
|
||
let!(:request_params) do
|
||
{
|
||
last_name: Faker::Name.last_name,
|
||
first_name: Faker::Name.first_name,
|
||
dob: Faker::Date.birthday,
|
||
country: Faker::Address.country_code_long,
|
||
city: Faker::Address.city,
|
||
address: Faker::Address.state,
|
||
postcode: Faker::Address.zip_code
|
||
}
|
||
end
|
||
|
||
before do
|
||
allow(EventAPI).to receive(:notify)
|
||
end
|
||
|
||
it 'receive model.profile.created notify' do
|
||
expect(EventAPI).to receive(:notify).ordered.with('model.user.created', hash_including(:record))
|
||
expect(EventAPI).to receive(:notify).ordered.with('model.profile.created', hash_including(:record))
|
||
|
||
post url, params: request_params, headers: auth_header
|
||
end
|
||
|
||
it 'receive model.profile.created notify with user and profile params' do
|
||
expect(EventAPI).to receive(:notify).ordered.with('model.user.created', hash_including(:record))
|
||
expect(EventAPI).to receive(:notify).ordered.with(
|
||
'model.profile.created',
|
||
hash_including(
|
||
record: {
|
||
user: anything,
|
||
address: anything,
|
||
city: anything,
|
||
country: anything,
|
||
created_at: anything,
|
||
updated_at: anything,
|
||
dob: anything,
|
||
first_name: anything,
|
||
last_name: anything,
|
||
postcode: anything
|
||
}
|
||
)
|
||
)
|
||
|
||
post url, params: request_params, headers: auth_header
|
||
end
|
||
end
|
||
|
||
describe 'PUT /api/v2/resource/profiles' do
|
||
let!(:url) { '/api/v2/resource/profiles' }
|
||
let!(:request_params) do
|
||
{
|
||
last_name: Faker::Name.last_name,
|
||
first_name: Faker::Name.first_name,
|
||
dob: Faker::Date.birthday,
|
||
country: Faker::Address.country_code_long,
|
||
city: Faker::Address.city,
|
||
address: Faker::Address.street_address,
|
||
postcode: Faker::Address.zip_code
|
||
}
|
||
end
|
||
|
||
context 'user without profile' do
|
||
it 'renders an error when profile doesnt exist' do
|
||
put url, params: request_params, headers: auth_header
|
||
|
||
expect_status.to eq(404)
|
||
expect_body.to eq(errors: ['resource.profile.doesnt_exist_or_not_editable'])
|
||
end
|
||
end
|
||
|
||
context 'user with profile' do
|
||
let!(:profile) { create(:profile, user: test_user)}
|
||
|
||
it 'returns submitted profile' do
|
||
expect { put url, params: request_params.merge(confirm: true), headers: auth_header }
|
||
.not_to change { Profile.count }
|
||
|
||
expect(response.status).to eq(200)
|
||
expect(json_body[:state]).to eq('submitted')
|
||
expect(profile[:metadata]).to be_blank
|
||
end
|
||
end
|
||
|
||
context 'user with partial profile' do
|
||
let!(:profile) { create(:profile, user: test_user, last_name: nil, first_name: nil) }
|
||
|
||
it 'returns partial profile' do
|
||
expect { put url, params: request_params.except(:first_name), headers: auth_header }
|
||
.not_to change { Profile.count }
|
||
|
||
expect(response.status).to eq(200)
|
||
expect(json_body[:state]).to eq('drafted')
|
||
expect(json_body[:metadata]).to be_blank
|
||
end
|
||
|
||
it 'returns completed profile' do
|
||
expect { put url, params: request_params, headers: auth_header }
|
||
.not_to change { Profile.count }
|
||
|
||
expect(response.status).to eq(200)
|
||
expect(json_body[:state]).to eq('drafted')
|
||
expect(json_body[:metadata]).to be_blank
|
||
end
|
||
end
|
||
end
|
||
end
|