Files
Dena/spec/api/v2/management/operations_spec.rb
2026-08-13 19:50:53 +03:30

362 lines
13 KiB
Ruby

# encoding: UTF-8
# frozen_string_literal: true
describe API::V2::Management::Operations, type: :request do
before do
defaults_for_management_api_v1_security_configuration!
management_api_v1_security_configuration.merge! \
scopes: {
read_operations: { permitted_signers: %i[alex jeff], mandatory_signers: %i[alex] },
write_operations: { permitted_signers: %i[alex jeff james], mandatory_signers: %i[alex jeff] }
}
end
describe 'list operations' do
def request(op_type)
post_json "/api/v2/management/#{op_type}", multisig_jwt_management_api_v1({ data: data }, *signers)
end
def optional_request(op_type, data)
post_json "/api/v2/management/#{op_type}", multisig_jwt_management_api_v1({ data: data }, *signers)
end
Operations::Account::PLATFORM_TYPES.each do |op_type|
context op_type do
let(:data) { {} }
let(:signers) { %i[alex] }
let(:operations_number) { 15 }
let!(:operations) { create_list(op_type, operations_number) }
before do
request(op_type.to_s.pluralize)
end
it { expect(response).to have_http_status(200) }
context 'filter by currency' do
let(:data) { { currency: :btc } }
it { expect(response).to have_http_status(200) }
it 'returns operations by currency' do
operations = "operations/#{op_type}"
.camelize
.constantize
.where(currency_id: :btc)
expect(JSON.parse(response.body).count).to eq operations.count
expect(JSON.parse(response.body).map { |h| h['currency'] }).to\
eq operations.pluck(:currency_id)
end
end
context 'pagination' do
let(:data) { { page: 2, limit: 8 } }
it 'returns second page of operations' do
expect(response).to have_http_status(200)
expect(JSON.parse(response.body).count).to eq 7
credits = "operations/#{op_type}"
.camelize
.constantize
.order(id: :desc)
.pluck(:credit)
# Consider that credit sequence is unique.
expect(JSON.parse(response.body).map { |h| h['credit'].to_d }).to eq credits[8..15]
end
end
end
end
Operations::Account::MEMBER_TYPES.each do |op_type|
context op_type do
let(:data) { {} }
let(:signers) { %i[alex] }
let(:operations_number) { 15 }
let!(:operations) { create_list(op_type, operations_number, :with_member) }
before do
request(op_type.to_s.pluralize)
end
it { expect(response).to have_http_status(200) }
context 'filter by currency' do
let(:data) { { currency: :btc } }
it 'returns operations by currency' do
expect(response).to have_http_status(200)
operations = "operations/#{op_type}"
.camelize
.constantize
.where(currency_id: :btc)
expect(JSON.parse(response.body).count).to eq operations.count
expect(JSON.parse(response.body).map { |h| h['currency'] }).to\
eq operations.pluck(:currency_id)
end
end
context 'filter by uid' do
let(:member) { create(:member, :barong) }
let!(:member_operations) do
create_list(op_type, operations_number, member_id: member.id)
end
let(:data) { { uid: member.uid } }
it 'returns operations by member UID' do
expect(response).to have_http_status(200)
request(op_type.to_s.pluralize)
operations = "operations/#{op_type}"
.camelize
.constantize
.where(member: member)
expect(JSON.parse(response.body).count).to eq operations.count
expect(JSON.parse(response.body).map { |h| h['uid'] }).to\
eq [member.uid] * operations_number
end
end
context 'filter by reference type' do
let(:deposit_data) { { reference_type: 'deposit' } }
let(:trade_data) { { reference_type: 'trade' } }
let(:order_data) { { reference_type: 'order' } }
it { expect(response).to have_http_status(200) }
def equal_amount!(response, optional_field, op_type)
operations = "operations/#{op_type}"
.camelize
.constantize
.where(optional_field)
expect(JSON.parse(response.body).count).to eq operations.count
end
it 'returns operations by reference type deposit' do
optional_request(op_type.to_s.pluralize, deposit_data)
equal_amount!(response, deposit_data, op_type)
end
it 'returns operations by reference type trade' do
optional_request(op_type.to_s.pluralize, trade_data)
equal_amount!(response, trade_data, op_type)
end
it 'returns operations by reference type order' do
optional_request(op_type.to_s.pluralize, order_data)
equal_amount!(response, order_data, op_type)
end
end
context 'time range' do
let(:time_from) { 2.days.ago }
let(:time_to) { 1.day.ago }
let(:data) { { time_from: time_from.to_i, time_to: time_to.to_i } }
it { expect(response).to have_http_status(200) }
it 'returns operations between 48h and 24h ago' do
request(op_type.to_s.pluralize)
operations = "operations/#{op_type}"
.camelize
.constantize
.where('created_at >= ?', time_from)
.where('created_at < ?', time_to)
expect(JSON.parse(response.body).count).to eq operations.count
end
end
context 'pagination' do
let(:data) { { page: 2, limit: 8 } }
it { expect(response).to have_http_status(200) }
it 'returns second page of operations' do
expect(JSON.parse(response.body).count).to eq 7
credits = "operations/#{op_type}"
.camelize
.constantize
.order(id: :desc)
.pluck(:credit)
# Consider that credit sequence is unique.
expect(JSON.parse(response.body).map{ |h| h['credit'].to_d }).to eq credits[8..15]
end
end
end
end
end
describe 'create operation' do
def request(op_type)
post_json "/api/v2/management/#{op_type}/new", multisig_jwt_management_api_v1({ data: data }, *signers)
end
Operations::Account::PLATFORM_TYPES.each do |op_type|
context op_type do
let(:currency) { Currency.coins.sample }
let(:signers) { %i[alex jeff] }
let(:data) do
{ currency: currency.code,
code: Operations::Account.find_by(type: op_type, currency_type: currency.type).code}
end
context 'credit' do
let(:amount) { '0.2515' }
before do
data[:credit] = amount
request(op_type.to_s.pluralize)
end
it 'returns operation' do
expect(response).to have_http_status 200
expect(JSON.parse(response.body)['currency']).to eq currency.code.to_s
expect(JSON.parse(response.body)['credit'].to_d).to eq amount.to_d
expect(JSON.parse(response.body)['code']).to \
eq Operations::Account.find_by(type: op_type,
kind: :main,
currency_type: currency.type).code
end
it 'saves operation' do
op_klass = "operations/#{op_type}"
.camelize
.constantize
expect { request(op_type.to_s.pluralize) }.to \
change(op_klass, :count).by(1)
end
context 'wrong account code' do
before do
data[:code] = (::Operations::Account.pluck(:code) - [data[:code]]).sample
request(op_type.to_s.pluralize)
end
it { expect(response).to have_http_status 422 }
end
end
context 'debit' do
let(:amount) { '0.1545' }
before do
# Create credit operation to avoid negative balance.
create(op_type, credit: amount)
data[:debit] = amount
request(op_type.to_s.pluralize)
end
it 'returns operation' do
expect(response).to have_http_status 200
expect(JSON.parse(response.body)['currency']).to eq currency.code.to_s
expect(JSON.parse(response.body)['debit'].to_d).to eq amount.to_d
expect(JSON.parse(response.body)['code']).to \
eq Operations::Account.find_by(type: op_type,
kind: :main,
currency_type: currency.type).code
end
it 'saves operation' do
op_klass = "operations/#{op_type}"
.camelize
.constantize
expect { request(op_type.to_s.pluralize) }.to \
change(op_klass, :count).by(1)
end
end
end
end
Operations::Account::MEMBER_TYPES.each do |op_type|
context op_type do
let(:currency) { Currency.coins.sample }
let(:signers) { %i[alex jeff] }
let(:member) { create(:member, :barong) }
let(:data) do
{ currency: currency.code,
code: Operations::Account.find_by(type: op_type, currency_type: currency.type, kind: :main).code,
uid: member.uid }
end
context 'credit' do
let(:amount) { '0.2515' }
before do
data[:credit] = amount
request(op_type.to_s.pluralize)
end
it 'returns operation' do
expect(response).to have_http_status 200
expect(JSON.parse(response.body)['uid']).to eq member.uid
expect(JSON.parse(response.body)['currency']).to eq currency.code.to_s
expect(JSON.parse(response.body)['credit'].to_d).to eq amount.to_d
expect(JSON.parse(response.body)['code']).to \
eq Operations::Account.find_by(type: op_type,
kind: :main,
currency_type: currency.type).code
end
it 'saves operation' do
op_klass = "operations/#{op_type}"
.camelize
.constantize
expect { request(op_type.to_s.pluralize) }.to \
change(op_klass, :count).by(1)
end
it 'updates legacy balance' do
currency_id = JSON.parse(response.body)['currency']
expect(member.get_account(currency_id).balance).to \
eq JSON.parse(response.body)['credit'].to_d
end
context 'wrong account code' do
before do
data[:code] = 999
request(op_type.to_s.pluralize)
end
it { expect(response).to have_http_status 422 }
end
end
context 'debit' do
let(:amount) { '0.1545' }
before do
# Create credit operation to avoid negative balance.
create(op_type, :with_member, credit: amount,
member: member, currency: currency)
data[:debit] = amount
request(op_type.to_s.pluralize)
end
it 'returns operation' do
expect(response).to have_http_status 200
expect(JSON.parse(response.body)['uid']).to eq member.uid
expect(JSON.parse(response.body)['currency']).to eq currency.code.to_s
expect(JSON.parse(response.body)['debit'].to_d).to eq amount.to_d
expect(JSON.parse(response.body)['code']).to \
eq Operations::Account.find_by(type: op_type,
kind: :main,
currency_type: currency.type).code
end
it 'saves operation' do
# Create one more credit operation to avoid negative balance.
# So we can create one more debit operation.
create(op_type, :with_member, credit: amount, member: member, currency: currency)
op_klass = "operations/#{op_type}"
.camelize
.constantize
expect { request(op_type.to_s.pluralize) }.to \
change(op_klass, :count).by(1)
end
it 'updates legacy balance' do
currency_id = JSON.parse(response.body)['currency']
expect(member.get_account(currency_id).balance).to \
eq 0.to_d
end
end
end
end
end
end