286 lines
14 KiB
Ruby
286 lines
14 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
# License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later
|
|
# Full license explanation at https://github.com/houdiniproject/houdini/blob/master/LICENSE
|
|
require 'rails_helper'
|
|
|
|
describe InsertCustomFieldJoins do
|
|
describe '.find_or_create' do
|
|
let(:nonprofit) { force_create(:nm_justice) }
|
|
let(:other_nonprofit) { force_create(:fv_poverty) }
|
|
let(:supporter) { force_create(:supporter, nonprofit: nonprofit) }
|
|
let(:other_supporter) { force_create(:supporter, nonprofit: other_nonprofit) }
|
|
|
|
let(:initial_custom_field_master) { force_create(:custom_field_master, nonprofit: nonprofit, name: 'CFM Name') }
|
|
|
|
describe 'param validation' do
|
|
it 'basic validation' do
|
|
expect { InsertCustomFieldJoins.find_or_create(nil, nil, nil) }.to(raise_error do |error|
|
|
expect(error).to be_a ParamValidation::ValidationError
|
|
expect_validation_errors(error.data, [
|
|
{ key: :np_id, name: :required },
|
|
{ key: :np_id, name: :is_integer },
|
|
{ key: :supporter_ids, name: :required },
|
|
{ key: :supporter_ids, name: :is_array },
|
|
{ key: :supporter_ids, name: :min_length },
|
|
{ key: :field_data, name: :required },
|
|
{ key: :field_data, name: :is_array },
|
|
{ key: :field_data, name: :min_length }
|
|
])
|
|
end)
|
|
end
|
|
|
|
it 'validate nonprofit existence' do
|
|
expect { InsertCustomFieldJoins.find_or_create(5, [555], [[1, 1]]) }.to(raise_error do |error|
|
|
expect(error).to be_a ParamValidation::ValidationError
|
|
expect_validation_errors(error.data, [
|
|
{ key: :np_id }
|
|
])
|
|
|
|
expect(error.message).to eq '5 is not a valid non-profit'
|
|
end)
|
|
end
|
|
|
|
it 'validate supporter in nonprofit' do
|
|
expect { InsertCustomFieldJoins.find_or_create(nonprofit.id, [other_supporter.id], [[1, 1]]) }.to(raise_error do |error|
|
|
expect(error).to be_a ParamValidation::ValidationError
|
|
expect_validation_errors(error.data, [
|
|
{ key: :supporter_ids }
|
|
])
|
|
|
|
expect(error.message).to eq "#{other_supporter.id} is not a valid supporter for nonprofit #{nonprofit.id}"
|
|
end)
|
|
end
|
|
end
|
|
|
|
it 'run insert' do
|
|
new_cf_name = 'new cf name'
|
|
new_cf_value = 'value'
|
|
old_cf_value = 'old_cf_value'
|
|
expect(InsertCustomFieldJoins).to receive(:in_bulk) do |np_id, supporters_id, field_data|
|
|
expect(np_id).to eq nonprofit.id
|
|
expect(supporters_id).to eq [supporter.id]
|
|
expect(field_data.length).to eq 2
|
|
expect(field_data).to include(custom_field_master_id: initial_custom_field_master.id, value: old_cf_value)
|
|
expect(field_data).to include(custom_field_master_id: CustomFieldMaster.where(name: new_cf_name).first.id, value: new_cf_value)
|
|
end
|
|
result = InsertCustomFieldJoins.find_or_create(nonprofit.id, [supporter.id], [
|
|
[
|
|
initial_custom_field_master.name,
|
|
old_cf_value
|
|
],
|
|
[
|
|
new_cf_name,
|
|
new_cf_value
|
|
]
|
|
])
|
|
expect(CustomFieldMaster.count).to eq 2
|
|
end
|
|
end
|
|
|
|
describe '.in_bulk' do
|
|
context 'parameter validation' do
|
|
it 'should validate parameters' do
|
|
response = InsertCustomFieldJoins.in_bulk(nil, nil, nil)
|
|
errors = response[:json][:errors]
|
|
expect(errors.length).to eq(6)
|
|
expect(response[:status]).to eq :unprocessable_entity
|
|
expect_validation_errors(errors, [
|
|
{ key: :np_id, name: :required },
|
|
{ key: :np_id, name: :is_integer },
|
|
{ key: :supporter_ids, name: :required },
|
|
{ key: :supporter_ids, name: :is_array },
|
|
{ key: :field_data, name: :is_array },
|
|
{ key: :field_data, name: :required }
|
|
])
|
|
end
|
|
context 'requiring db' do
|
|
before(:each) do
|
|
@nonprofit = force_create(:nm_justice)
|
|
@bad_nonprofit = force_create(:fv_poverty, id: 50)
|
|
end
|
|
it 'nonprofit must be valid' do
|
|
response = InsertCustomFieldJoins.in_bulk(@nonprofit.id + 1, [], [])
|
|
expect(response[:status]).to eq :unprocessable_entity
|
|
expect(response[:json][:error]).to include("Nonprofit #{@nonprofit.id + 1} is not valid")
|
|
end
|
|
|
|
it 'supporters if empty should do nothing' do
|
|
response = InsertCustomFieldJoins.in_bulk(@nonprofit.id, [], [])
|
|
expect(response).to eq(successful_json(0, 0))
|
|
end
|
|
|
|
it 'supporters if empty should do nothing' do
|
|
response = InsertCustomFieldJoins.in_bulk(@nonprofit.id, [50], [])
|
|
expect(response).to eq(successful_json(0, 0))
|
|
end
|
|
end
|
|
end
|
|
|
|
context 'main testing' do
|
|
before(:each) do
|
|
@nonprofit = force_create(:nm_justice)
|
|
@other_nonprofit = force_create(:fv_poverty)
|
|
@random_supporter = create(:supporter, nonprofit: @other_nonprofit)
|
|
|
|
|
|
@delete_cfm = [20, 40, 60]
|
|
@add_cfm = [25, 35]
|
|
|
|
@supporters = {
|
|
np_supporter_with_add: {
|
|
cfm_ids: [65, 75, 85]
|
|
},
|
|
np_supporter_with_cfms_to_delete: {
|
|
cfm_ids: [40, 75, 85]
|
|
},
|
|
|
|
np_supporter_with_no_changes: {
|
|
cfm_ids: @add_cfm
|
|
},
|
|
np_supporter_with_some_of_both: {
|
|
|
|
cfm_ids: [20, 35]
|
|
},
|
|
supporter_from_other_np: {
|
|
cfm_ids: [100, 150, 200],
|
|
other_np: true
|
|
}
|
|
|
|
}
|
|
|
|
@supporters.each_key do |k|
|
|
i = @supporters[k]
|
|
nonprofit_for_supporter = i[:other_np] ? @other_nonprofit : @nonprofit
|
|
i[:entity] = create(:supporter, nonprofit: nonprofit_for_supporter)
|
|
i[:cfm_ids].each do |j|
|
|
cfm = CustomFieldMaster.exists?(id: j) ? CustomFieldMaster.find(j) : create(:custom_field_master, id: j, nonprofit: nonprofit_for_supporter, name: "CFM #{j}")
|
|
|
|
create(:custom_field_join, :value_from_id, supporter_id: i[:entity].id, custom_field_master: cfm)
|
|
end
|
|
end
|
|
end
|
|
|
|
it 'invalid nonprofit-supporter combo returns okay' do
|
|
results = InsertCustomFieldJoins.in_bulk(@nonprofit.id, [@supporters[:supporter_from_other_np][:entity].id], [])
|
|
expect(results).to eq(successful_json(0, 0))
|
|
end
|
|
|
|
it 'strips cfms which dont belong to nonprofit' do
|
|
results = InsertCustomFieldJoins.in_bulk(@nonprofit.id, [@supporters[:np_supporter_with_add][:entity].id],
|
|
create_cfm_data([100], [150]))
|
|
expect(results).to eq(successful_json(0, 0))
|
|
|
|
expect(CustomFieldJoin.where('supporter_id = ? and custom_field_master_id = ?', @supporters[:np_supporter_with_add][:entity].id, 100).count).to eq 0
|
|
end
|
|
|
|
it 'delete' do
|
|
expect(CustomFieldJoin.count).to eq 13
|
|
@supporters[:np_supporter_with_some_of_both][:entity].id
|
|
|
|
results = InsertCustomFieldJoins.in_bulk(@nonprofit.id,
|
|
[@supporters[:np_supporter_with_some_of_both][:entity].id, @supporters[:np_supporter_with_cfms_to_delete][:entity].id, @supporters[:np_supporter_with_add][:entity].id, @supporters[:supporter_from_other_np][:entity].id, @supporters[:np_supporter_with_no_changes][:entity].id],
|
|
create_cfm_data(@add_cfm, @delete_cfm))
|
|
|
|
expect(CustomFieldJoin.where('supporter_id = ? ', @supporters[:np_supporter_with_some_of_both][:entity].id).count).to eq 2
|
|
|
|
expect(CustomFieldJoin.where('supporter_id = ?', @supporters[:np_supporter_with_add][:entity].id).count).to eq 5
|
|
|
|
expect(CustomFieldJoin.where('supporter_id = ?', @supporters[:np_supporter_with_cfms_to_delete][:entity].id).count).to eq 4
|
|
|
|
expect(CustomFieldJoin.where('supporter_id = ?', @supporters[:supporter_from_other_np][:entity].id).count).to eq 3
|
|
|
|
expect(CustomFieldJoin.where('supporter_id = ?', @supporters[:np_supporter_with_no_changes][:entity].id).count).to eq 2
|
|
|
|
expect(CustomFieldJoin.count).to eq 16
|
|
end
|
|
|
|
it 'id, updated_at, created_at changes are stripped' do
|
|
invalid_id = 10_000_000
|
|
Timecop.freeze(2020, 9, 1, 12, 0, 0) do
|
|
results = InsertCustomFieldJoins.in_bulk(@nonprofit.id,
|
|
[@supporters[:np_supporter_with_add][:entity].id],
|
|
[{ custom_field_master_id: 25, value: 'CFM value 25', id: invalid_id, created_at: Time.now.ago(3000), updated_at: Time.now.ago(2999) }])
|
|
expected = { custom_field_master_id: 25, value: 'CFM value 25', created_at: Time.now, updated_at: Time.now, supporter_id: @supporters[:np_supporter_with_add][:entity].id }.with_indifferent_access
|
|
|
|
expect(results).to eq(successful_json(1, 0))
|
|
|
|
result_tag = @supporters[:np_supporter_with_add][:entity].custom_field_joins.where('custom_field_master_id = ?', 25).first
|
|
|
|
expect(result_tag.attributes.with_indifferent_access.reject { |k, _| k == 'id' }).to eq(expected)
|
|
|
|
expect(result_tag.attributes[:id]).to_not eq invalid_id
|
|
end
|
|
end
|
|
|
|
it 'add_to_one' do
|
|
expect(CustomFieldJoin.count).to eq 13
|
|
|
|
np_supporter_with_add_cfms = @supporters[:np_supporter_with_add][:entity].custom_field_joins.to_a
|
|
np_supporter_with_some_of_both_cfms = @supporters[:np_supporter_with_some_of_both][:entity].custom_field_joins.to_a
|
|
np_supporter_with_no_changes_cfms = @supporters[:np_supporter_with_no_changes][:entity].custom_field_joins.to_a
|
|
|
|
Timecop.travel(20) do
|
|
results = InsertCustomFieldJoins.in_bulk(@nonprofit.id,
|
|
[
|
|
@supporters[:np_supporter_with_add][:entity].id, # add 2
|
|
@supporters[:np_supporter_with_no_changes][:entity], # update 2
|
|
@supporters[:np_supporter_with_some_of_both][:entity].id
|
|
], # add 2, delete 1
|
|
create_cfm_data(@add_cfm, @delete_cfm))
|
|
|
|
expect(results).to eq(successful_json(6, 1))
|
|
|
|
expect(@supporters[:np_supporter_with_no_changes][:entity].custom_field_joins).to match_array(np_supporter_with_no_changes_cfms)
|
|
|
|
expect(CustomFieldJoin.where('supporter_id = ? ', @supporters[:np_supporter_with_add][:entity].id).count).to eq 5
|
|
|
|
original_db_pairs = get_original_and_db(np_supporter_with_add_cfms, CustomFieldJoin.where('supporter_id = ? and custom_field_master_id in (?)',
|
|
@supporters[:np_supporter_with_add][:entity].id,
|
|
@supporters[:np_supporter_with_add][:cfm_ids]).pluck(:id))
|
|
|
|
original_db_pairs.each do |orig, db|
|
|
expect(db.attributes.length).to eq(orig.attributes.length)
|
|
expect(db.attributes).to eq(orig.attributes)
|
|
end
|
|
|
|
expect(CustomFieldJoin.where('supporter_id = ?', @supporters[:np_supporter_with_some_of_both][:entity].id).count).to eq 2
|
|
|
|
original_db_pairs = get_original_and_db(np_supporter_with_some_of_both_cfms, CustomFieldJoin.where('supporter_id = ? and custom_field_master_id in (?)',
|
|
@supporters[:np_supporter_with_some_of_both][:entity].id,
|
|
[35]).pluck(:id))
|
|
skip_attribs = %w[updated_at value]
|
|
original_db_pairs.each do |orig, db|
|
|
expect(db.attributes.length).to eq(orig.attributes.length)
|
|
expect(db.attributes.reject { |key, _value| skip_attribs.include?(key) }).to eq(orig.attributes.reject { |key, _value| skip_attribs.include?(key) })
|
|
expect(db.attributes['updated_at']).to be > orig.attributes['updated_at']
|
|
expect(db.attributes['value']).to eq 'CFM value 35'
|
|
end
|
|
|
|
expect(CustomFieldJoin.count).to eq 15
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
def successful_json(inserted, deleted)
|
|
{ json: { inserted_count: inserted, removed_count: deleted }, status: :ok }
|
|
end
|
|
|
|
def create_cfm_data(cfm_to_add = [], cfm_to_delete = [])
|
|
use_nil = true
|
|
cfm_to_add.map { |cfm| { custom_field_master_id: cfm, value: "CFM value #{cfm}" } } + cfm_to_delete.map do |cfm|
|
|
value = use_nil ? nil : ''
|
|
use_nil = !use_nil
|
|
{ custom_field_master_id: cfm, value: value }
|
|
end
|
|
end
|
|
|
|
def get_original_and_db(original_items, ids_to_verify)
|
|
ids_to_verify.map do |i|
|
|
original_item = original_items.find { |oi| oi[:id] == i }
|
|
db_item = CustomFieldJoin.find(i)
|
|
[original_item, db_item]
|
|
end
|
|
end
|
|
end
|