houdini/spec/lib/insert/insert_custom_field_joins_spec.rb

312 lines
13 KiB
Ruby
Raw Normal View History

# License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later
require 'rails_helper'
describe InsertCustomFieldJoins do
describe '.find_or_create' do
let(:nonprofit) { force_create(:nonprofit)}
let(:other_nonprofit) { force_create(:nonprofit)}
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 {|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
it 'validate nonprofit existence' do
expect {InsertCustomFieldJoins.find_or_create(5, [555], [[1, 1]])}.to(raise_error {|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
it 'validate supporter in nonprofit' do
expect {InsertCustomFieldJoins.find_or_create(nonprofit.id, [other_supporter.id], [[1, 1]])}.to(raise_error {|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
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) {
@nonprofit = force_create(:nonprofit)
@bad_nonprofit = force_create(:nonprofit, :id => 50)
}
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) {
@nonprofit = force_create(:nonprofit)
@random_supporter = create(:supporter)
@other_nonprofit = force_create(: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 {|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 {|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)
}
}
}
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 = 10000000
Timecop.freeze(2020, 9, 1, 12, 0, 0) {
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
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) {
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 {|orig, db|
expect(db.attributes.length).to eq(orig.attributes.length)
expect(db.attributes).to eq(orig.attributes)
}
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 = ['updated_at', 'value']
original_db_pairs.each {|orig, db|
expect(db.attributes.length).to eq(orig.attributes.length)
expect(db.attributes.select {|key, value| !skip_attribs.include?(key)}).to eq(orig.attributes.select {|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"
}
expect(CustomFieldJoin.count).to eq 15
}
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 {|cfm|
value = use_nil ? nil : ''
use_nil = !use_nil
{custom_field_master_id: cfm, value: value}}
end
def get_original_and_db(original_items, ids_to_verify)
ids_to_verify.map {|i|
original_item = original_items.find {|oi| oi[:id] == i}
db_item = CustomFieldJoin.find(i)
[original_item, db_item]
}
end
end