houdini/spec/lib/insert/insert_custom_field_joins_spec.rb
Bradley M. Kuhn 6772312ea7 Relicense all .rb files under new project license.
The primary license of the project is changing to:
  AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later

with some specific files to be licensed under the one of two licenses:
   CC0-1.0
   LGPL-3.0-or-later

This commit is one of the many steps to relicense the entire codebase.

Documentation granting permission for this relicensing (from all past
contributors who hold copyrights) is on file with Software Freedom
Conservancy, Inc.
2018-03-25 15:10:40 -04:00

311 lines
13 KiB
Ruby

# 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