Initial commit

This commit is contained in:
Yaser
2026-08-13 19:56:46 +03:30
commit de1d57a67b
474 changed files with 43185 additions and 0 deletions

View File

@@ -0,0 +1,572 @@
# 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] = "'LarkinFork' 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] = "'LarkinFork' @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] = 'HubliDharwad'
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