1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
|
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe CustomerRelations::Contact, type: :model do
let_it_be(:group) { create(:group) }
describe 'associations' do
it { is_expected.to belong_to(:group) }
it { is_expected.to belong_to(:organization).optional }
it { is_expected.to have_many(:issue_contacts) }
it { is_expected.to have_many(:issues) }
end
describe 'validations' do
subject { build(:contact) }
it { is_expected.to validate_presence_of(:group) }
it { is_expected.to validate_presence_of(:first_name) }
it { is_expected.to validate_presence_of(:last_name) }
it { is_expected.to validate_length_of(:phone).is_at_most(32) }
it { is_expected.to validate_length_of(:first_name).is_at_most(255) }
it { is_expected.to validate_length_of(:last_name).is_at_most(255) }
it { is_expected.to validate_length_of(:email).is_at_most(255) }
it { is_expected.to validate_length_of(:description).is_at_most(1024) }
it { is_expected.to validate_uniqueness_of(:email).case_insensitive.scoped_to(:group_id) }
it_behaves_like 'an object with RFC3696 compliant email-formatted attributes', :email
end
describe '.reference_prefix' do
it { expect(described_class.reference_prefix).to eq('[contact:') }
end
describe '.reference_prefix_quoted' do
it { expect(described_class.reference_prefix_quoted).to eq('["contact:') }
end
describe '.reference_postfix' do
it { expect(described_class.reference_postfix).to eq(']') }
end
describe '#root_group' do
context 'when root group' do
subject { build(:contact, group: group) }
it { is_expected.to be_valid }
end
context 'when subgroup' do
subject { build(:contact, group: create(:group, parent: group)) }
it { is_expected.to be_invalid }
end
end
describe '#before_validation' do
it 'strips leading and trailing whitespace' do
contact = described_class.new(first_name: ' First ', last_name: ' Last ', phone: ' 123456 ')
contact.valid?
expect(contact.first_name).to eq('First')
expect(contact.last_name).to eq('Last')
expect(contact.phone).to eq('123456')
end
end
describe '#self.find_ids_by_emails' do
let_it_be(:group_contacts) { create_list(:contact, 2, group: group) }
let_it_be(:other_contacts) { create_list(:contact, 2) }
it 'returns ids of contacts from group' do
contact_ids = described_class.find_ids_by_emails(group, group_contacts.pluck(:email))
expect(contact_ids).to match_array(group_contacts.pluck(:id))
end
it 'does not return ids of contacts from other groups' do
contact_ids = described_class.find_ids_by_emails(group, other_contacts.pluck(:email))
expect(contact_ids).to be_empty
end
it 'raises ArgumentError when called with too many emails' do
too_many_emails = described_class::MAX_PLUCK + 1
expect { described_class.find_ids_by_emails(group, Array(0..too_many_emails)) }.to raise_error(ArgumentError)
end
it 'finds contacts regardless of email casing' do
new_contact = create(:contact, group: group, email: "UPPERCASE@example.com")
emails = [group_contacts[0].email.downcase, group_contacts[1].email.upcase, new_contact.email]
contact_ids = described_class.find_ids_by_emails(group, emails)
expect(contact_ids).to contain_exactly(group_contacts[0].id, group_contacts[1].id, new_contact.id)
end
end
describe '#self.exists_for_group?' do
context 'with no contacts in group' do
it 'returns false' do
expect(described_class.exists_for_group?(group)).to be_falsey
end
end
context 'with contacts in group' do
it 'returns true' do
create(:contact, group: group)
expect(described_class.exists_for_group?(group)).to be_truthy
end
end
end
describe '#self.move_to_root_group' do
let!(:old_root_group) { create(:group) }
let!(:contacts) { create_list(:contact, 4, group: old_root_group) }
let!(:project) { create(:project, group: old_root_group) }
let!(:issue) { create(:issue, project: project) }
let!(:issue_contact1) { create(:issue_customer_relations_contact, issue: issue, contact: contacts[0]) }
let!(:issue_contact2) { create(:issue_customer_relations_contact, issue: issue, contact: contacts[1]) }
let!(:new_root_group) { create(:group) }
let!(:dupe_contact1) { create(:contact, group: new_root_group, email: contacts[1].email) }
let!(:dupe_contact2) { create(:contact, group: new_root_group, email: contacts[3].email.upcase) }
before do
old_root_group.update!(parent: new_root_group)
CustomerRelations::Contact.move_to_root_group(old_root_group)
end
it 'moves contacts with unique emails and deletes the rest' do
expect(contacts[0].reload.group_id).to eq(new_root_group.id)
expect(contacts[2].reload.group_id).to eq(new_root_group.id)
expect { contacts[1].reload }.to raise_error(ActiveRecord::RecordNotFound)
expect { contacts[3].reload }.to raise_error(ActiveRecord::RecordNotFound)
end
it 'updates issue_contact.contact_id for dupes and leaves the rest untouched' do
expect(issue_contact1.reload.contact_id).to eq(contacts[0].id)
expect(issue_contact2.reload.contact_id).to eq(dupe_contact1.id)
end
end
end
|