From ad0220088a0a1024c164235f1d1a930bfaf8973c Mon Sep 17 00:00:00 2001 From: Artur Beljajev Date: Fri, 28 Oct 2016 00:36:12 +0300 Subject: [PATCH] Refactor domain expiration email #186 --- app/jobs/domain_expiration_email_job.rb | 11 +++ app/mailers/domain_mailer.rb | 21 ++-- app/models/concerns/domain/expirable.rb | 31 ++++++ app/models/contact.rb | 7 ++ app/models/domain.rb | 19 ++++ app/models/nameserver.rb | 6 +- app/presenters/domain_presenter.rb | 33 +++++++ app/presenters/registrar_presenter.rb | 27 ++++++ .../mailers/domain_mailer/expiration.html.erb | 67 +++++++++++++ .../mailers/domain_mailer/expiration.text.erb | 60 ++++++++++++ config/locales/en.yml | 1 - config/locales/mailers/domain.en.yml | 4 + spec/factories/admin_domain_contact.rb | 5 + spec/factories/contact.rb | 16 ++++ spec/factories/dnskey.rb | 15 +++ spec/factories/domain.rb | 15 +++ spec/factories/domain_contact.rb | 5 + spec/factories/nameserver.rb | 6 ++ spec/factories/registrant.rb | 5 + spec/factories/registrar.rb | 13 +++ spec/factories/tech_domain_contact.rb | 5 + spec/jobs/domain_expiration_email_job_spec.rb | 40 ++++++++ spec/mailers/domain_mailer_spec.rb | 38 ++++++++ spec/models/concerns/domain/expirable_spec.rb | 57 +++++++++++ spec/models/contact_spec.rb | 22 +---- spec/models/domain_spec.rb | 25 ----- spec/presenters/domain_presenter_spec.rb | 96 +++++++++++++++++++ spec/presenters/registrar_presenter_spec.rb | 34 +++++++ .../domain_mailer/expiration.html.erb_spec.rb | 36 +++++++ .../domain_mailer/expiration.text.erb_spec.rb | 36 +++++++ 30 files changed, 697 insertions(+), 59 deletions(-) create mode 100644 app/jobs/domain_expiration_email_job.rb create mode 100644 app/models/concerns/domain/expirable.rb create mode 100644 app/presenters/domain_presenter.rb create mode 100644 app/presenters/registrar_presenter.rb create mode 100644 app/views/mailers/domain_mailer/expiration.html.erb create mode 100644 app/views/mailers/domain_mailer/expiration.text.erb create mode 100644 config/locales/mailers/domain.en.yml create mode 100644 spec/factories/admin_domain_contact.rb create mode 100644 spec/factories/contact.rb create mode 100644 spec/factories/dnskey.rb create mode 100644 spec/factories/domain.rb create mode 100644 spec/factories/domain_contact.rb create mode 100644 spec/factories/nameserver.rb create mode 100644 spec/factories/registrant.rb create mode 100644 spec/factories/registrar.rb create mode 100644 spec/factories/tech_domain_contact.rb create mode 100644 spec/jobs/domain_expiration_email_job_spec.rb create mode 100644 spec/mailers/domain_mailer_spec.rb create mode 100644 spec/models/concerns/domain/expirable_spec.rb create mode 100644 spec/presenters/domain_presenter_spec.rb create mode 100644 spec/presenters/registrar_presenter_spec.rb create mode 100644 spec/views/mailers/domain_mailer/expiration.html.erb_spec.rb create mode 100644 spec/views/mailers/domain_mailer/expiration.text.erb_spec.rb diff --git a/app/jobs/domain_expiration_email_job.rb b/app/jobs/domain_expiration_email_job.rb new file mode 100644 index 000000000..1066d3f35 --- /dev/null +++ b/app/jobs/domain_expiration_email_job.rb @@ -0,0 +1,11 @@ +class DomainExpirationEmailJob < ActiveJob::Base + queue_as :default + + def perform(domain_id:) + domain = Domain.find(domain_id) + + return if domain.registered? + + DomainMailer.expiration(domain).deliver! + end +end diff --git a/app/mailers/domain_mailer.rb b/app/mailers/domain_mailer.rb index afdfe89fc..e53c6d596 100644 --- a/app/mailers/domain_mailer.rb +++ b/app/mailers/domain_mailer.rb @@ -117,17 +117,6 @@ class DomainMailer < ApplicationMailer name: @domain.name)} [#{@domain.name}]") end - def expiration_reminder(domain_id) - @domain = Domain.find_by(id: domain_id) - return if @domain.nil? || !@domain.statuses.include?(DomainStatus::EXPIRED) || whitelist_blocked?(@domain.registrant.email) - return if whitelist_blocked?(@domain.registrant.email) - - mail(to: format(@domain.registrant.email), - subject: "#{I18n.t(:expiration_remind_subject, - name: @domain.name)} [#{@domain.name}]") - end - - def force_delete(domain_id, should_deliver) @domain = Domain.find_by(id: domain_id) return if delivery_off?(@domain, should_deliver) @@ -140,6 +129,16 @@ class DomainMailer < ApplicationMailer ) end + def expiration(domain:) + @domain = DomainPresenter.new(domain: domain, view: view_context) + @registrar = RegistrarPresenter.new(registrar: domain.registrar, view: view_context) + + recipients = domain.admin_contact_emails << domain.registrant_email + + subject = default_i18n_subject(domain_name: domain.name) + mail(to: recipients, subject: subject) + end + private # app/models/DomainMailModel provides the data for mail that can be composed_from # which ensures that values of objects are captured when they are valid, not later when this method is executed diff --git a/app/models/concerns/domain/expirable.rb b/app/models/concerns/domain/expirable.rb new file mode 100644 index 000000000..237bdfd34 --- /dev/null +++ b/app/models/concerns/domain/expirable.rb @@ -0,0 +1,31 @@ +module Concerns::Domain::Expirable + extend ActiveSupport::Concern + + included do + alias_attribute :expire_time, :valid_to + end + + class_methods do + def expired + where("#{attribute_alias(:expire_time)} <= ?", Time.zone.now) + end + end + + def registered? + valid_to >= Time.zone.now + end + + def expired? + statuses.include?(DomainStatus::EXPIRED) + end + + def expirable? + return false if valid_to > Time.zone.now + + if expired? && outzone_at.present? && delete_at.present? + return false + end + + true + end +end diff --git a/app/models/contact.rb b/app/models/contact.rb index 50e78ef54..822394d22 100644 --- a/app/models/contact.rb +++ b/app/models/contact.rb @@ -250,6 +250,13 @@ class Contact < ActiveRecord::Base kit.to_pdf end + def names + pluck(:name) + end + + def emails + pluck(:email) + end end def roid diff --git a/app/models/domain.rb b/app/models/domain.rb index 1d96dbfde..7b7087dd9 100644 --- a/app/models/domain.rb +++ b/app/models/domain.rb @@ -3,12 +3,16 @@ class Domain < ActiveRecord::Base include UserEvents include Versions # version/domain_version.rb include Statuses + include Concerns::Domain::Expirable has_paper_trail class_name: "DomainVersion", meta: { children: :children_log } attr_accessor :roles attr_accessor :legal_document_id + alias_attribute :on_hold_time, :outzone_at + alias_attribute :delete_time, :delete_at + # TODO: whois requests ip whitelist for full info for own domains and partial info for other domains # TODO: most inputs should be trimmed before validatation, probably some global logic? @@ -746,6 +750,21 @@ class Domain < ActiveRecord::Base DomainMailer.send(action, DomainMailModel.new(self).send(action)).deliver end + def admin_contact_names + admin_contacts.names + end + + def admin_contact_emails + admin_contacts.emails + end + + def tech_contact_names + tech_contacts.names + end + + def nameserver_hostnames + nameservers.hostnames + end def self.to_csv CSV.generate do |csv| diff --git a/app/models/nameserver.rb b/app/models/nameserver.rb index 7b4daab3d..fb56f1198 100644 --- a/app/models/nameserver.rb +++ b/app/models/nameserver.rb @@ -18,7 +18,7 @@ class Nameserver < ActiveRecord::Base before_validation :normalize_attributes before_validation :check_puny_symbols before_validation :check_label_length - + delegate :name, to: :domain, prefix: true def epp_code_map @@ -117,5 +117,9 @@ class Nameserver < ActiveRecord::Base # ignoring ips rel end + + def hostnames + pluck(:hostname) + end end end diff --git a/app/presenters/domain_presenter.rb b/app/presenters/domain_presenter.rb new file mode 100644 index 000000000..ea8b0ba22 --- /dev/null +++ b/app/presenters/domain_presenter.rb @@ -0,0 +1,33 @@ +class DomainPresenter + delegate :name, :registrant_name, to: :domain + + def initialize(domain:, view:) + @domain = domain + @view = view + end + + def on_hold_date + view.l(domain.on_hold_time, format: :date) if domain.on_hold_time + end + + def delete_date + view.l(domain.delete_time, format: :date) if domain.delete_time + end + + def admin_contact_names + domain.admin_contact_names.join(', ') + end + + def tech_contact_names + domain.tech_contact_names.join(', ') + end + + def nameserver_names + domain.nameserver_hostnames.join(', ') + end + + private + + attr_reader :domain + attr_reader :view +end diff --git a/app/presenters/registrar_presenter.rb b/app/presenters/registrar_presenter.rb new file mode 100644 index 000000000..1fe415feb --- /dev/null +++ b/app/presenters/registrar_presenter.rb @@ -0,0 +1,27 @@ +class RegistrarPresenter + def initialize(registrar:, view:) + @registrar = registrar + @view = view + end + + def name + registrar.name + end + + def email + registrar.email + end + + def phone + registrar.phone + end + + def url + registrar.url + end + + private + + attr_reader :registrar + attr_reader :view +end diff --git a/app/views/mailers/domain_mailer/expiration.html.erb b/app/views/mailers/domain_mailer/expiration.html.erb new file mode 100644 index 000000000..d06a8803e --- /dev/null +++ b/app/views/mailers/domain_mailer/expiration.html.erb @@ -0,0 +1,67 @@ +Domeen <%= @domain.name %> on aegunud
+Lugupeetud .ee domeeni kasutaja
+
+Domeeninimi <%= @domain.name %> on aegunud ja ei ole alates <%= @domain.on_hold_date %> internetis kättesaadav. Alates <%= @domain.delete_date %> on domeen <%= @domain.name %> avatud registreerimiseks kõigile huvilistele. +

+Domeeni registreeringu pikendamiseks pöörduge palun oma registripidaja <%= @registrar.name %> poole. Registripidajate kontaktid leiate aadressilt www.internet.ee/registripidajad. +

+Domeeni <%= @domain.name %> kohta on registris järgmised andmed: +

+Registreerija: <%= @domain.registrant_name %>
+Halduskontakt: <%= @domain.admin_contact_names %>
+Tehniline kontakt: <%= @domain.tech_contact_names %>
+Registripidaja: <%= @registrar.name %>
+Nimeserverid: <%= @domain.nameserver_names %>
+Ülevaate kõikidest endaga seotud domeenidest saate registreerija portaalist. <%= ENV['registrant_url'] %>.
+

+Lugupidamisega
+Eesti Interneti Sihtasutus +

+
+

+The <%= @domain.name %> domain has expired
+Dear user of .ee domain,
+
+The domain name <%= @domain.name %> has expired and will not be available on the Internet from <%= @domain.on_hold_date %>. From <%= @domain.delete_date %>, the <%= @domain.name %> domain will be available for registration on a first come first served basis. +

+To renew the domain registration, please contact your registrar <%= @registrar.name %>. You can find the registrar's contacts at http://internet.ee/registrars. +

+The following data for the <%= @domain.name %> domain have been entered into the registry: +

+Registrant: <%= @domain.registrant_name %>
+Administrative contact: <%= @domain.admin_contact_names %>
+Technical contact: <%= @domain.tech_contact_names %>
+Registrar: <%= @registrar.name %>
+Name servers: <%= @domain.nameserver_names %>
+You can find an overview of all your domains at the registrant's portal. <%= ENV['registrant_url'] %>.
+

+Best Regards,
+Estonian Internet Foundation +

+
+

+Домен <%= @domain.name %> устарел
+Уважаемый пользователь домена .ee
+
+ +Доменное имя <%= @domain.name %> устарело и с <%= @domain.on_hold_date %> недоступно в Интернете. С <%= @domain.delete_date %> домен <%= @domain.name %> доступен для регистрации всем желающим по принципу "first come, first served". + +

+ +Для продления регистрации домена просим обратиться к своему регистратору <%= @registrar.name %>. Контактные данные регистраторов можно найти по адресу http://internet.ee/registratory. +

+ +Относительно домена <%= @domain.name %> в реестр внесены следующие данные: +

+ +Регистрант: <%= @domain.registrant_name %>
+Административный контакт: <%= @domain.admin_contact_names %>
+Технический контакт: <%= @domain.tech_contact_names %>
+Регистратор: <%= @registrar.name %>
+Серверы доменных имен: <%= @domain.nameserver_names %>
+Обзор всех связанных с Вами доменов можете получить на портале регистранта. <%= ENV['registrant_url'] %>.
+ +

+ +С наилучшими пожеланиями
+Целевое учреждение Eesti Internet diff --git a/app/views/mailers/domain_mailer/expiration.text.erb b/app/views/mailers/domain_mailer/expiration.text.erb new file mode 100644 index 000000000..7cfa9a9fc --- /dev/null +++ b/app/views/mailers/domain_mailer/expiration.text.erb @@ -0,0 +1,60 @@ +Domeen <%= @domain.name %> on aegunud +Lugupeetud .ee domeeni kasutaja + +Domeeninimi <%= @domain.name %> on aegunud ja ei ole alates <%= @domain.on_hold_date %> internetis kättesaadav. Alates <%= @domain.delete_date %> on domeen <%= @domain.name %> avatud registreerimiseks kõigile huvilistele. + +Domeeni registreeringu pikendamiseks pöörduge palun oma registripidaja <%= @registrar.name %> poole. Registripidajate kontaktid leiate aadressilt www.internet.ee/registripidajad. + +Domeeni <%= @domain.name %> kohta on registris järgmised andmed: + +Registreerija: <%= @domain.registrant_name %> +Halduskontakt: <%= @domain.admin_contact_names %> +Tehniline kontakt: <%= @domain.tech_contact_names %> +Registripidaja: <%= @registrar.name %> +Nimeserverid: <%= @domain.nameserver_names %> +Ülevaate kõikidest endaga seotud domeenidest saate registreerija portaalist. <%= ENV['registrant_url'] %>. + +Parimate soovidega +Eesti Interneti Sihtasutus + +-------------------------------------- + +The <%= @domain.name %> domain has expired +Dear user of .ee domain, + +The domain name <%= @domain.name %> has expired and will not be available on the Internet from <%= @domain.on_hold_date %>. From <%= @domain.delete_date %>, the <%= @domain.name %> domain will be available for registration on a first come first served basis. + +To renew the domain registration, please contact your registrar <%= @registrar.name %>. You can find the registrar's contacts at http://internet.ee/registrars. + +The following data for the <%= @domain.name %> domain have been entered into the registry: + +Registrant: <%= @domain.registrant_name %> +Administrative contact: <%= @domain.admin_contact_names %> +Technical contact: <%= @domain.tech_contact_names %> +Registrar: <%= @registrar.name %> +Name servers: <%= @domain.nameserver_names %> +You can find an overview of all your domains at the registrant's portal. <%= ENV['registrant_url'] %>. + +Best Regards, +Estonian Internet Foundation + +-------------------------------------- + +Домен <%= @domain.name %> устарел +Уважаемый пользователь домена .ee + +Доменное имя <%= @domain.name %> устарело и с <%= @domain.on_hold_date %> недоступно в Интернете. С <%= @domain.delete_date %> домен <%= @domain.name %> доступен для регистрации всем желающим по принципу "first come, first served". + +Для продления регистрации домена просим обратиться к своему регистратору <%= @registrar.name %>. Контактные данные регистраторов можно найти по адресу http://internet.ee/registratory. + +Относительно домена <%= @domain %> в реестр внесены следующие данные: + +Регистрант: <%= @domain.registrant_name %> +Административный контакт: <%= @domain.admin_contact_names %> +Технический контакт: <%= @domain.tech_contact_names %> +Регистратор: <%= @registrar.name %> +Серверы доменных имен: <%= @domain.nameserver_names %> +Обзор всех связанных с Вами доменов можете получить на портале регистранта. <%= ENV['registrant_url'] %>. + +С наилучшими пожеланиями +Целевое учреждение Eesti Internet diff --git a/config/locales/en.yml b/config/locales/en.yml index a5bf12885..264502adf 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -945,7 +945,6 @@ en: list_format_is_in_yaml: 'List format is in YAML' if_auth_info_is_left_empty_it_will_be_auto_generated: 'If auth info is left empty, it will be auto generated.' each_domain_name_must_end_with_colon_sign: 'Each domain name must end with colon (:) sign.' - expiration_remind_subject: 'The %{name} domain has expired' next: 'Next' previous: 'Previous' personal_domain_verification_url: 'Personal domain verification url' diff --git a/config/locales/mailers/domain.en.yml b/config/locales/mailers/domain.en.yml new file mode 100644 index 000000000..99dc33a5a --- /dev/null +++ b/config/locales/mailers/domain.en.yml @@ -0,0 +1,4 @@ +en: + domain_mailer: + expiration: + subject: The %{domain_name} domain has expired diff --git a/spec/factories/admin_domain_contact.rb b/spec/factories/admin_domain_contact.rb new file mode 100644 index 000000000..786825214 --- /dev/null +++ b/spec/factories/admin_domain_contact.rb @@ -0,0 +1,5 @@ +FactoryGirl.define do + factory :admin_domain_contact, parent: :domain_contact, class: AdminDomainContact do + + end +end diff --git a/spec/factories/contact.rb b/spec/factories/contact.rb new file mode 100644 index 000000000..5218da399 --- /dev/null +++ b/spec/factories/contact.rb @@ -0,0 +1,16 @@ +FactoryGirl.define do + factory :contact do + name 'test' + sequence(:code) { |n| "test#{n}" } + phone '+123.456789' + email 'test@test.com' + street 'test' + city 'test' + zip 12345 + country_code 'EE' + ident '37605030299' + ident_type 'priv' + ident_country_code 'EE' + registrar + end +end diff --git a/spec/factories/dnskey.rb b/spec/factories/dnskey.rb new file mode 100644 index 000000000..e06387487 --- /dev/null +++ b/spec/factories/dnskey.rb @@ -0,0 +1,15 @@ +FactoryGirl.define do + factory :dnskey do + alg Dnskey::ALGORITHMS.first + flags Dnskey::FLAGS.first + protocol Dnskey::PROTOCOLS.first + ds_digest_type 2 + domain + public_key 'AwEAAaOf5+lz3ftsL+0CCvfJbhUF/NVsNh8BKo61oYs5fXVbuWDiH872 '\ + 'LC8uKDO92TJy7Q4TF9XMAKMMlf1GMAxlRspD749SOCTN00sqfWx1OMTu '\ + 'a28L1PerwHq7665oDJDKqR71btcGqyLKhe2QDvCdA0mENimF1NudX1BJ '\ + 'DDFi6oOZ0xE/0CuveB64I3ree7nCrwLwNs56kXC4LYoX3XdkOMKiJLL/ '\ + 'MAhcxXa60CdZLoRtTEW3z8/oBq4hEAYMCNclpbd6y/exScwBxFTdUfFk '\ + 'KsdNcmvai1lyk9vna0WQrtpYpHKMXvY9LFHaJxCOLR4umfeQ42RuTd82 lqfU6ClMeXs=' + end +end diff --git a/spec/factories/domain.rb b/spec/factories/domain.rb new file mode 100644 index 000000000..5a396362d --- /dev/null +++ b/spec/factories/domain.rb @@ -0,0 +1,15 @@ +FactoryGirl.define do + factory :domain do + sequence(:name) { |n| "test#{n}.com" } + period 1 + period_unit 'y' # Year + registrar + registrant + + after :build do |domain| + domain.nameservers << FactoryGirl.build_pair(:nameserver) + domain.admin_domain_contacts << FactoryGirl.build(:admin_domain_contact) + domain.tech_domain_contacts << FactoryGirl.build(:tech_domain_contact) + end + end +end diff --git a/spec/factories/domain_contact.rb b/spec/factories/domain_contact.rb new file mode 100644 index 000000000..ae05fd293 --- /dev/null +++ b/spec/factories/domain_contact.rb @@ -0,0 +1,5 @@ +FactoryGirl.define do + factory :domain_contact do + contact + end +end diff --git a/spec/factories/nameserver.rb b/spec/factories/nameserver.rb new file mode 100644 index 000000000..ebe7a7909 --- /dev/null +++ b/spec/factories/nameserver.rb @@ -0,0 +1,6 @@ +FactoryGirl.define do + factory :nameserver do + sequence(:hostname) { |n| "ns.test#{n}.ee" } + ipv4 '192.168.1.1' + end +end diff --git a/spec/factories/registrant.rb b/spec/factories/registrant.rb new file mode 100644 index 000000000..c4846fcd4 --- /dev/null +++ b/spec/factories/registrant.rb @@ -0,0 +1,5 @@ +FactoryGirl.define do + factory :registrant, parent: :contact, class: Registrant do + name 'test' + end +end diff --git a/spec/factories/registrar.rb b/spec/factories/registrar.rb new file mode 100644 index 000000000..dd581a1d1 --- /dev/null +++ b/spec/factories/registrar.rb @@ -0,0 +1,13 @@ +FactoryGirl.define do + factory :registrar do + sequence(:name) { |n| "test#{n}" } + sequence(:code) { |n| "test#{n}" } + sequence(:reg_no) { |n| "test#{n}" } + street 'test' + city 'test' + state 'test' + zip 'test' + email 'test@test.com' + country_code 'EE' + end +end diff --git a/spec/factories/tech_domain_contact.rb b/spec/factories/tech_domain_contact.rb new file mode 100644 index 000000000..e407474a3 --- /dev/null +++ b/spec/factories/tech_domain_contact.rb @@ -0,0 +1,5 @@ +FactoryGirl.define do + factory :tech_domain_contact, parent: :domain_contact, class: TechDomainContact do + + end +end diff --git a/spec/jobs/domain_expiration_email_job_spec.rb b/spec/jobs/domain_expiration_email_job_spec.rb new file mode 100644 index 000000000..f435b1f0b --- /dev/null +++ b/spec/jobs/domain_expiration_email_job_spec.rb @@ -0,0 +1,40 @@ +require 'rails_helper' + +RSpec.describe DomainExpirationEmailJob do + it 'queues the job' do + expect { described_class.perform_later }.to have_enqueued_job(described_class) + end + + describe '#perform' do + let(:domain) { instance_double(Domain) } + + before :example do + expect(Domain).to receive(:find).and_return(domain) + end + + context 'when domain is expired' do + let(:message) { instance_double(ActionMailer::MessageDelivery) } + + before :example do + allow(domain).to receive(:registered?).and_return(false) + end + + it 'sends email notification' do + expect(DomainMailer).to receive(:expiration).with(domain: domain).and_return(message) + expect(message).to receive(:deliver!) + described_class.perform_now(domain_id: 1) + end + end + + context 'when domain is registered' do + before :example do + allow(domain).to receive(:registered?).and_return(true) + end + + it 'does not send email notification' do + expect(DomainMailer).to_not receive(:expiration) + described_class.perform_now(domain_id: 1) + end + end + end +end diff --git a/spec/mailers/domain_mailer_spec.rb b/spec/mailers/domain_mailer_spec.rb new file mode 100644 index 000000000..c3679f116 --- /dev/null +++ b/spec/mailers/domain_mailer_spec.rb @@ -0,0 +1,38 @@ +require 'rails_helper' + +RSpec.describe DomainMailer do + describe '#expiration' do + let(:domain) { instance_spy(Domain, + name: 'test.com', + registrant_email: 'registrant@test.com', + admin_contact_emails: ['admin.contact.email@test.com'] + ) } + let(:domain_presenter) { instance_spy(DomainPresenter) } + let(:registrar_presenter) { instance_spy(RegistrarPresenter) } + subject(:message) { described_class.expiration(domain: domain) } + + before :example do + expect(DomainPresenter).to receive(:new).and_return(domain_presenter) + expect(RegistrarPresenter).to receive(:new).and_return(registrar_presenter) + end + + it 'has valid sender' do + message.deliver! + expect(message.from).to eq(['noreply@internet.ee']) + end + + it 'has registrant and administrative contacts as recipient' do + message.deliver! + expect(message.to).to match_array(['registrant@test.com', 'admin.contact.email@test.com']) + end + + it 'has valid subject' do + message.deliver! + expect(message.subject).to eq('The test.com domain has expired') + end + + it 'sends message' do + expect { message.deliver! }.to change { ActionMailer::Base.deliveries.count }.by(1) + end + end +end diff --git a/spec/models/concerns/domain/expirable_spec.rb b/spec/models/concerns/domain/expirable_spec.rb new file mode 100644 index 000000000..72fde82ab --- /dev/null +++ b/spec/models/concerns/domain/expirable_spec.rb @@ -0,0 +1,57 @@ +require 'rails_helper' + +RSpec.describe Domain, db: false do + it { is_expected.to alias_attribute(:expire_time, :valid_to) } + + describe '::expired', db: true do + before :example do + travel_to Time.zone.parse('05.07.2010 00:00') + + FactoryGirl.create(:domain, id: 1, expire_time: Time.zone.parse('04.07.2010 23:59')) + FactoryGirl.create(:domain, id: 2, expire_time: Time.zone.parse('05.07.2010 00:00')) + FactoryGirl.create(:domain, id: 3, expire_time: Time.zone.parse('05.07.2010 00:01')) + end + + it 'returns expired domains' do + expect(described_class.expired.ids).to eq([1, 2]) + end + end + + describe '#registered?' do + before :example do + travel_to Time.zone.parse('05.07.2010 00:00') + end + + context 'when :valid_to is in the future' do + let(:domain) { described_class.new(expire_time: Time.zone.parse('06.07.2010 00:01')) } + + specify { expect(domain).to be_registered } + end + + context 'when :valid_to is the same as current time' do + let(:domain) { described_class.new(expire_time: Time.zone.parse('05.07.2010 00:00')) } + + specify { expect(domain).to_not be_registered } + end + + context 'when :valid_to is in the past' do + let(:domain) { described_class.new(expire_time: Time.zone.parse('04.07.2010 23:59')) } + + specify { expect(domain).to_not be_registered } + end + end + + describe '#expired?' do + context 'when :statuses contains expired status' do + let(:domain) { described_class.new(statuses: [DomainStatus::EXPIRED]) } + + specify { expect(domain).to be_expired } + end + + context 'when :statuses does not contain expired status' do + let(:domain) { described_class.new(statuses: [DomainStatus::CLIENT_HOLD]) } + + specify { expect(domain).to_not be_expired } + end + end +end diff --git a/spec/models/contact_spec.rb b/spec/models/contact_spec.rb index b54c5a47f..b20f4bf60 100644 --- a/spec/models/contact_spec.rb +++ b/spec/models/contact_spec.rb @@ -1,28 +1,8 @@ require 'rails_helper' -describe Contact do +RSpec.describe Contact do before :example do - Setting.ds_algorithm = 2 - Setting.ds_data_allowed = true - Setting.ds_data_with_key_allowed = true - Setting.key_data_allowed = true - - Setting.dnskeys_min_count = 0 - Setting.dnskeys_max_count = 9 - Setting.ns_min_count = 2 - Setting.ns_max_count = 11 - - Setting.transfer_wait_time = 0 - - Setting.admin_contacts_min_count = 1 - Setting.admin_contacts_max_count = 10 - Setting.tech_contacts_min_count = 0 - Setting.tech_contacts_max_count = 10 - - Setting.client_side_status_editing_enabled = true - Fabricate(:zonefile_setting, origin: 'ee') - @api_user = Fabricate(:api_user) end context 'about class' do diff --git a/spec/models/domain_spec.rb b/spec/models/domain_spec.rb index 1d6a63fb8..a8384372c 100644 --- a/spec/models/domain_spec.rb +++ b/spec/models/domain_spec.rb @@ -928,29 +928,4 @@ RSpec.describe Domain, db: false do expect(domain.nameserver_hostnames).to eq('hostnames') end end - - describe '#registered?' do - before :example do - travel_to Time.zone.parse('05.07.2010 00:00:01') - end - - context 'when :valid_to is in the future' do - let(:domain) { described_class.new(valid_to: Time.zone.parse('06.07.2010')) } - - specify { expect(domain).to be_registered } - end - - context 'when :valid_to is the same as current time' do - let(:domain) { described_class.new(valid_to: Time.zone.parse('05.07.2010 00:00:01')) } - - - specify { expect(domain).to be_registered } - end - - context 'when :valid_to is in the past' do - let(:domain) { described_class.new(valid_to: Time.zone.parse('04.07.2010 23:59:59')) } - - specify { expect(domain).to_not be_registered } - end - end end diff --git a/spec/presenters/domain_presenter_spec.rb b/spec/presenters/domain_presenter_spec.rb new file mode 100644 index 000000000..a6799095b --- /dev/null +++ b/spec/presenters/domain_presenter_spec.rb @@ -0,0 +1,96 @@ +require 'rails_helper' + +RSpec.describe DomainPresenter do + let(:presenter) { described_class.new(domain: domain, view: view) } + + describe '#on_hold_date' do + subject(:on_hold_date) { presenter.on_hold_date } + + context 'when present' do + let(:domain) { instance_double(Domain, on_hold_time: '05.07.2010') } + + it 'returns localized date' do + expect(view).to receive(:l).with('05.07.2010', format: :date).and_return('on hold date') + expect(on_hold_date).to eq('on hold date') + end + end + + context 'when absent' do + let(:domain) { instance_double(Domain, on_hold_time: nil) } + + specify { expect(on_hold_date).to be_nil } + end + end + + describe '#delete_date' do + subject(:delete_date) { presenter.delete_date } + + context 'when present' do + let(:domain) { instance_double(Domain, delete_time: '05.07.2010') } + + it 'returns localized date' do + expect(view).to receive(:l).with('05.07.2010', format: :date).and_return('delete date') + expect(delete_date).to eq('delete date') + end + end + + context 'when absent' do + let(:domain) { instance_double(Domain, delete_time: nil) } + + specify { expect(delete_date).to be_nil } + end + end + + describe '#admin_contact_names' do + let(:domain) { instance_double(Domain) } + + before :example do + expect(domain).to receive(:admin_contact_names).and_return(%w(test1 test2 test3)) + end + + it 'returns admin contact names' do + expect(presenter.admin_contact_names).to eq('test1, test2, test3') + end + end + + describe '#tech_contact_names' do + let(:domain) { instance_double(Domain) } + + before :example do + expect(domain).to receive(:tech_contact_names).and_return(%w(test1 test2 test3)) + end + + it 'returns technical contact names' do + expect(presenter.tech_contact_names).to eq('test1, test2, test3') + end + end + + describe '#nameserver_names' do + let(:domain) { instance_double(Domain) } + + before :example do + expect(domain).to receive(:nameserver_hostnames).and_return(%w(test1 test2 test3)) + end + + it 'returns nameserver names' do + expect(presenter.nameserver_names).to eq('test1, test2, test3') + end + end + + + domain_delegatable_attributes = %i( + name + registrant_name + ) + + domain_delegatable_attributes.each do |attribute_name| + describe "##{attribute_name}" do + let(:domain) { instance_spy(Domain) } + + it 'delegates to domain' do + presenter.send(attribute_name) + expect(domain).to have_received(attribute_name) + end + end + end +end diff --git a/spec/presenters/registrar_presenter_spec.rb b/spec/presenters/registrar_presenter_spec.rb new file mode 100644 index 000000000..462f8049c --- /dev/null +++ b/spec/presenters/registrar_presenter_spec.rb @@ -0,0 +1,34 @@ +require 'rails_helper' + +RSpec.describe RegistrarPresenter do + let(:registrar) { instance_double(Registrar) } + let(:presenter) { described_class.new(registrar: registrar, view: nil) } + + describe '#name' do + it 'returns name' do + expect(registrar).to receive(:name).and_return('test name') + expect(presenter.name).to eq('test name') + end + end + + describe '#email' do + it 'returns email' do + expect(registrar).to receive(:email).and_return('test email') + expect(presenter.email).to eq('test email') + end + end + + describe '#phone' do + it 'returns phone' do + expect(registrar).to receive(:phone).and_return('test phone') + expect(presenter.phone).to eq('test phone') + end + end + + describe '#url' do + it 'returns url' do + expect(registrar).to receive(:url).and_return('test url') + expect(presenter.url).to eq('test url') + end + end +end diff --git a/spec/views/mailers/domain_mailer/expiration.html.erb_spec.rb b/spec/views/mailers/domain_mailer/expiration.html.erb_spec.rb new file mode 100644 index 000000000..fc1e18e61 --- /dev/null +++ b/spec/views/mailers/domain_mailer/expiration.html.erb_spec.rb @@ -0,0 +1,36 @@ +require 'rails_helper' + +RSpec.describe 'mailers/domain_mailer/expiration.html.erb' do + let(:domain) { instance_spy(DomainPresenter) } + let(:registrar) { instance_spy(RegistrarPresenter) } + let(:lang_count) { 3 } + + before :example do + assign(:domain, domain) + assign(:registrar, registrar) + end + + it 'has registrar name' do + mention_count = 2 * lang_count + expect(registrar).to receive(:name).exactly(mention_count).times.and_return('test registrar name') + render + expect(rendered).to have_text('test registrar name', count: mention_count) + end + + attributes = %i( + on_hold_date + delete_date + registrant_name + admin_contact_names + tech_contact_names + nameserver_names + ) + + attributes.each do |attr_name| + it "has :#{attr_name}" do + expect(domain).to receive(attr_name).exactly(lang_count).times.and_return(attr_name.to_s) + render + expect(rendered).to have_text(attr_name.to_s, count: lang_count) + end + end +end diff --git a/spec/views/mailers/domain_mailer/expiration.text.erb_spec.rb b/spec/views/mailers/domain_mailer/expiration.text.erb_spec.rb new file mode 100644 index 000000000..39a36cdb7 --- /dev/null +++ b/spec/views/mailers/domain_mailer/expiration.text.erb_spec.rb @@ -0,0 +1,36 @@ +require 'rails_helper' + +RSpec.describe 'mailers/domain_mailer/expiration.text.erb' do + let(:domain) { instance_spy(DomainPresenter) } + let(:registrar) { instance_spy(RegistrarPresenter) } + let(:lang_count) { 3 } + + before :example do + assign(:domain, domain) + assign(:registrar, registrar) + end + + it 'has registrar name' do + mention_count = 2 * lang_count + expect(registrar).to receive(:name).exactly(mention_count).times.and_return('test registrar name') + render + expect(rendered).to have_text('test registrar name', count: mention_count) + end + + attributes = %i( + on_hold_date + delete_date + registrant_name + admin_contact_names + tech_contact_names + nameserver_names + ) + + attributes.each do |attr_name| + it "has :#{attr_name}" do + expect(domain).to receive(attr_name).exactly(lang_count).times.and_return(attr_name.to_s) + render + expect(rendered).to have_text(attr_name.to_s, count: lang_count) + end + end +end