Refactor inactive contact archivation

Fixes #956
This commit is contained in:
Artur Beljajev 2019-03-28 22:08:16 +02:00
parent 296442e330
commit 487613db1e
14 changed files with 424 additions and 84 deletions

View file

@ -1,11 +1,6 @@
class ContactMailerPreview < ActionMailer::Preview
def email_changed
# Replace with `Contact.in_use` once https://github.com/internetee/registry/pull/1146 is merged
contact = Contact.where('EXISTS(SELECT 1 FROM domains WHERE domains.registrant_id = contacts.id)
OR
EXISTS(SELECT 1 FROM domain_contacts WHERE domain_contacts.contact_id =
contacts.id)')
contact = Contact.linked
contact = contact.where.not(email: nil, country_code: nil, code: nil).first
ContactMailer.email_changed(contact: contact, old_email: 'old@inbox.test')

View file

@ -0,0 +1,81 @@
require 'test_helper'
class ArchivableContactTest < ActiveSupport::TestCase
setup do
@contact = contacts(:john)
end
def test_contact_is_archivable_when_it_was_linked_and_inactivity_period_has_passed
DomainVersion.stub(:was_contact_linked?, true) do
DomainVersion.stub(:contact_unlinked_more_than?, true) do
assert @contact.archivable?
end
end
end
def test_contact_is_archivable_when_it_was_never_linked_and_inactivity_period_has_passed
Contact.inactivity_period = 1.second
@contact.created_at = Time.zone.parse('2010-07-05 00:00:00')
travel_to Time.zone.parse('2010-07-05 00:00:01')
DomainVersion.stub(:was_contact_linked?, false) do
assert @contact.archivable?
end
end
def test_contact_is_not_archivable_when_it_was_never_linked_and_inactivity_period_has_not_passed
Contact.inactivity_period = 1.second
@contact.created_at = Time.zone.parse('2010-07-05')
travel_to Time.zone.parse('2010-07-05')
DomainVersion.stub(:contact_unlinked_more_than?, false) do
assert_not @contact.archivable?
end
end
def test_contact_is_not_archivable_when_it_was_ever_linked_but_linked_within_inactivity_period
DomainVersion.stub(:was_contact_linked?, true) do
DomainVersion.stub(:contact_unlinked_more_than?, false) do
assert_not @contact.archivable?
end
end
end
def test_archives_contact
contact = archivable_contact
assert_difference 'Contact.count', -1 do
contact.archive
end
end
def test_unarchivable_contact_cannot_be_archived
contact = unarchivable_contact
e = assert_raises do
contact.archive
end
assert_equal 'Contact cannot be archived', e.message
end
private
def archivable_contact
contact = contacts(:john)
Contact.inactivity_period = 0.seconds
DomainVersion.delete_all
other_contact = contacts(:william)
assert_not_equal other_contact, contact
Domain.update_all(registrant_id: other_contact)
DomainContact.delete_all
contact
end
def unarchivable_contact
Contact.inactivity_period = 99.years
@contact
end
end

View file

@ -133,6 +133,52 @@ class ContactTest < ActiveSupport::TestCase
assert_not @contact.deletable?
end
def test_linked_scope_returns_contact_that_acts_as_registrant
domains(:shop).update!(registrant: @contact.becomes(Registrant))
assert Contact.linked.include?(@contact), 'Contact should be included'
end
def test_linked_scope_returns_contact_that_acts_as_admin_contact
domains(:shop).admin_contacts = [@contact]
assert Contact.linked.include?(@contact), 'Contact should be included'
end
def test_linked_scope_returns_contact_that_acts_as_tech_contact
domains(:shop).tech_contacts = [@contact]
assert Contact.linked.include?(@contact), 'Contact should be included'
end
def test_linked_scope_skips_unlinked_contact
contact = unlinked_contact
assert_not Contact.linked.include?(contact), 'Contact should be excluded'
end
def test_unlinked_scope_returns_unlinked_contact
contact = unlinked_contact
assert Contact.unlinked.include?(contact), 'Contact should be included'
end
def test_unlinked_scope_skips_contact_that_is_linked_as_registrant
contact = unlinked_contact
domains(:shop).update_columns(registrant_id: contact.becomes(Registrant))
assert Contact.unlinked.exclude?(contact), 'Contact should be excluded'
end
def test_unlinked_scope_skips_contact_that_is_linked_as_admin_contact
contact = unlinked_contact
domains(:shop).admin_contacts = [contact]
assert Contact.unlinked.exclude?(contact), 'Contact should be excluded'
end
def test_unlinked_scope_skips_contact_that_is_linked_as_tech_contact
contact = unlinked_contact
domains(:shop).tech_contacts = [contact]
assert Contact.unlinked.exclude?(contact), 'Contact should be excluded'
end
private
def make_contact_free_of_domains_where_it_acts_as_a_registrant(contact)
@ -142,8 +188,12 @@ class ContactTest < ActiveSupport::TestCase
end
def unlinked_contact
Domain.update_all(registrant_id: contacts(:william))
other_contact = contacts(:william)
assert_not_equal @contact, other_contact
Domain.update_all(registrant_id: other_contact)
DomainContact.delete_all
contacts(:john)
@contact
end
end

View file

@ -0,0 +1,13 @@
require 'test_helper'
class InactiveContactsTest < ActiveSupport::TestCase
def test_archives_inactive_contacts
contact_mock = Minitest::Mock.new
contact_mock.expect(:archive, nil)
inactive_contacts = InactiveContacts.new([contact_mock])
inactive_contacts.archive
assert_mock contact_mock
end
end

View file

@ -0,0 +1,105 @@
require 'test_helper'
class DomainVersionTest < ActiveSupport::TestCase
setup do
@domain_version = log_domains(:one)
@contact = contacts(:john)
end
def test_was_contact_linked_returns_true_when_contact_was_used_as_registrant
@domain_version.update!(children: { admin_contacts: [],
tech_contacts: [],
registrant: [@contact.id] })
assert DomainVersion.was_contact_linked?(@contact)
end
def test_was_contact_linked_returns_true_when_contact_was_used_as_admin_contact
@domain_version.update!(children: { admin_contacts: [@contact.id],
tech_contacts: [],
registrant: [] })
assert DomainVersion.was_contact_linked?(@contact)
end
def test_was_contact_linked_returns_true_when_contact_was_used_as_tech_contact
@domain_version.update!(children: { admin_contacts: [],
tech_contacts: [@contact.id],
registrant: [] })
assert DomainVersion.was_contact_linked?(@contact)
end
def test_was_contact_linked_returns_false_when_contact_was_not_used
@domain_version.update!(children: { admin_contacts: [],
tech_contacts: [],
registrant: [] })
assert_not DomainVersion.was_contact_linked?(@contact)
end
def test_contact_unlinked_more_than_returns_true_when_contact_was_linked_as_registrant_more_than_given_period
@domain_version.update!(created_at: Time.zone.parse('2010-07-04 00:00:00'),
children: { admin_contacts: [],
tech_contacts: [],
registrant: [@contact.id] })
travel_to Time.zone.parse('2010-07-05 00:00:01')
assert DomainVersion.contact_unlinked_more_than?(contact: @contact, period: 1.day)
end
def test_contact_unlinked_more_than_given_period_as_admin_contact
@domain_version.update!(created_at: Time.zone.parse('2010-07-04 00:00:00'),
children: { admin_contacts: [1, @contact.id],
tech_contacts: [],
registrant: [] })
travel_to Time.zone.parse('2010-07-05 00:00:01')
assert DomainVersion.contact_unlinked_more_than?(contact: @contact, period: 1.day)
end
def test_contact_unlinked_more_than_given_period_as_tech_contact
@domain_version.update!(created_at: Time.zone.parse('2010-07-04 00:00:00'),
children: { admin_contacts: [],
tech_contacts: [1, @contact.id],
registrant: [] })
travel_to Time.zone.parse('2010-07-05 00:00:01')
assert DomainVersion.contact_unlinked_more_than?(contact: @contact, period: 1.day)
end
def test_contact_linked_within_given_period_as_registrant
@domain_version.update!(created_at: Time.zone.parse('2010-07-05'),
children: { admin_contacts: [],
tech_contacts: [],
registrant: [@contact.id] })
travel_to Time.zone.parse('2010-07-05')
assert_not DomainVersion.contact_unlinked_more_than?(contact: @contact, period: 1.day)
end
def test_contact_linked_within_given_period_as_admin_contact
@domain_version.update!(created_at: Time.zone.parse('2010-07-05'),
children: { admin_contacts: [1, @contact.id],
tech_contacts: [],
registrant: [] })
travel_to Time.zone.parse('2010-07-05')
assert_not DomainVersion.contact_unlinked_more_than?(contact: @contact, period: 1.day)
end
def test_contact_linked_within_given_period_as_tech_contact
@domain_version.update!(created_at: Time.zone.parse('2010-07-05'),
children: { admin_contacts: [],
tech_contacts: [1, @contact.id],
registrant: [] })
travel_to Time.zone.parse('2010-07-05')
assert_not DomainVersion.contact_unlinked_more_than?(contact: @contact, period: 1.day)
end
def test_contact_was_never_linked
DomainVersion.delete_all
assert_not DomainVersion.contact_unlinked_more_than?(contact: @contact, period: 1.day)
end
end

View file

@ -0,0 +1,46 @@
require 'test_helper'
class ArchiveContactsTaskTest < ActiveSupport::TestCase
def test_archives_inactive_contacts
eliminate_effect_of_all_contacts_except(archivable_contact)
assert_difference 'Contact.count', -1 do
capture_io { run_task }
end
end
def test_output
contact = archivable_contact
eliminate_effect_of_all_contacts_except(contact)
expected_output = "Contact ##{contact.id} (code: #{contact.code}) is archived\n" \
"Archived total: 1\n"
assert_output(expected_output) { run_task }
end
private
def archivable_contact
contact = contacts(:john)
Contact.inactivity_period = 0.seconds
DomainVersion.delete_all
other_contact = contacts(:william)
assert_not_equal other_contact, contact
Domain.update_all(registrant_id: other_contact)
DomainContact.delete_all
contact
end
def eliminate_effect_of_all_contacts_except(contact)
Contact.connection.disable_referential_integrity do
Contact.delete_all("id != #{contact.id}")
end
end
def run_task
Rake::Task['contacts:archive'].execute
end
end

View file

@ -33,6 +33,7 @@ class ActiveSupport::TestCase
ActiveRecord::Migration.check_pending!
fixtures :all
set_fixture_class log_domains: DomainVersion
teardown do
travel_back