diff --git a/CHANGELOG.md b/CHANGELOG.md index 5585ca6f1..6e53f4714 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,19 @@ +10.02.2021 +* Option to remove email addresses from AWS SES Supression list [#1839](https://github.com/internetee/registry/issues/1839) +* Added separate key for bounce API [#1842](https://github.com/internetee/registry/pull/1842) + +09.02.2021 +* Added new endpoint for WHOIS contact requests [#1794](https://github.com/internetee/registry/pull/1794) + +05.02.2021 +* Fixed IPv4 empty string issue in case of IPv6 only entries for IP whitelist [#1833](https://github.com/internetee/registry/issues/1833) + +02.02.2021 +* Fixed updateProhibited status not affecting bulk tech contact change operation [#1820](https://github.com/internetee/registry/pull/1820) + +01.02.2021 +* Improved tests for admin interface [#1805](https://github.com/internetee/registry/pull/1805) + 28.01.2021 * Fixed transfer with shared admin and tech contacts [#1808](https://github.com/internetee/registry/issues/1808) * Improved error handling with double admin/tech contacts [#1758](https://github.com/internetee/registry/issues/1758) diff --git a/Gemfile b/Gemfile index dd879a11b..82a0b4666 100644 --- a/Gemfile +++ b/Gemfile @@ -92,3 +92,5 @@ group :test do gem 'webdrivers' gem 'webmock' end + +gem 'aws-sdk-sesv2', '~> 1.16' diff --git a/Gemfile.lock b/Gemfile.lock index 51c880c9e..08daf4226 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -148,6 +148,18 @@ GEM attr_required (1.0.1) autoprefixer-rails (10.0.0.2) execjs + aws-eventstream (1.1.0) + aws-partitions (1.424.0) + aws-sdk-core (3.112.0) + aws-eventstream (~> 1, >= 1.0.2) + aws-partitions (~> 1, >= 1.239.0) + aws-sigv4 (~> 1.1) + jmespath (~> 1.0) + aws-sdk-sesv2 (1.16.0) + aws-sdk-core (~> 3, >= 3.112.0) + aws-sigv4 (~> 1.1) + aws-sigv4 (1.2.2) + aws-eventstream (~> 1, >= 1.0.2) bcrypt (3.1.16) bindata (2.4.8) bootsnap (1.4.8) @@ -226,6 +238,7 @@ GEM i18n_data (0.10.0) isikukood (0.1.2) iso8601 (0.12.1) + jmespath (1.4.0) jquery-rails (4.4.0) rails-dom-testing (>= 1, < 3) railties (>= 4.2.0) @@ -484,6 +497,7 @@ DEPENDENCIES active_interaction (~> 3.8) activerecord-import airbrake + aws-sdk-sesv2 (~> 1.16) bootsnap (>= 1.1.0) bootstrap-sass (~> 3.4) cancancan diff --git a/app/controllers/api/v1/base_controller.rb b/app/controllers/api/v1/base_controller.rb index b62b3e063..6ee986a48 100644 --- a/app/controllers/api/v1/base_controller.rb +++ b/app/controllers/api/v1/base_controller.rb @@ -11,7 +11,7 @@ module Api end def authenticate_shared_key - api_key = "Basic #{ENV['api_shared_key']}" + api_key = "Basic #{ENV['rwhois_internal_api_shared_key']}" head(:unauthorized) unless api_key == request.authorization end diff --git a/app/controllers/api/v1/bounces_controller.rb b/app/controllers/api/v1/bounces_controller.rb index fd10a3398..de2814250 100644 --- a/app/controllers/api/v1/bounces_controller.rb +++ b/app/controllers/api/v1/bounces_controller.rb @@ -1,7 +1,7 @@ module Api module V1 class BouncesController < BaseController - before_action :authenticate_shared_key + before_action :validate_shared_key_integrity # POST api/v1/bounces/ def create @@ -20,6 +20,13 @@ module Api params.require(:data) end + + private + + def validate_shared_key_integrity + api_key = "Basic #{ENV['rwhois_bounces_api_shared_key']}" + head(:unauthorized) unless api_key == request.authorization + end end end end diff --git a/app/controllers/api/v1/contact_requests_controller.rb b/app/controllers/api/v1/contact_requests_controller.rb new file mode 100644 index 000000000..2b5977f59 --- /dev/null +++ b/app/controllers/api/v1/contact_requests_controller.rb @@ -0,0 +1,37 @@ +module Api + module V1 + class ContactRequestsController < BaseController + before_action :authenticate_shared_key + + # POST api/v1/contact_requests/ + def create + return head(:bad_request) if contact_request_params[:email].blank? + + contact_request = ContactRequest.save_record(contact_request_params) + render json: contact_request, status: :created + rescue StandardError + head(:bad_request) + end + + def update + return head(:bad_request) if params[:id].blank? + + process_id(params[:id]) + end + + def process_id(id) + record = ContactRequest.find_by(id: id) + return :not_found unless record + + record.update_status(contact_request_params) + render json: record, status: :ok + rescue StandardError + head :bad_request + end + + def contact_request_params + params.require(:contact_request).permit(:email, :whois_record_id, :name, :status, :ip) + end + end + end +end diff --git a/app/models/bounced_mail_address.rb b/app/models/bounced_mail_address.rb index 73c6a0941..db4413829 100644 --- a/app/models/bounced_mail_address.rb +++ b/app/models/bounced_mail_address.rb @@ -1,5 +1,6 @@ class BouncedMailAddress < ApplicationRecord validates :email, :message_id, :bounce_type, :bounce_subtype, :action, :status, presence: true + after_destroy :destroy_aws_suppression def bounce_reason "#{action} (#{status} #{diagnostic})" @@ -25,4 +26,20 @@ class BouncedMailAddress < ApplicationRecord diagnostic: bounced_record['diagnosticCode'], } end + + def destroy_aws_suppression + return unless BouncedMailAddress.ses_configured? + + res = Aws::SESV2::Client.new.delete_suppressed_destination(email_address: email) + res.successful? + rescue Aws::SESV2::Errors::ServiceError => e + logger.warn("Suppression not removed. #{e}") + end + + def self.ses_configured? + ses ||= Aws::SESV2::Client.new + ses.config.credentials.access_key_id.present? + rescue Aws::Errors::MissingRegionError + false + end end diff --git a/app/models/concerns/domain/bulk_updatable.rb b/app/models/concerns/domain/bulk_updatable.rb new file mode 100644 index 000000000..a0aadb95f --- /dev/null +++ b/app/models/concerns/domain/bulk_updatable.rb @@ -0,0 +1,17 @@ +module Concerns + module Domain + module BulkUpdatable + extend ActiveSupport::Concern + + def bulk_update_prohibited? + discarded? || statuses_blocks_update? + end + + def statuses_blocks_update? + prohibited_array = [DomainStatus::SERVER_UPDATE_PROHIBITED, + DomainStatus::CLIENT_UPDATE_PROHIBITED] + prohibited_array.any? { |block_status| statuses.include?(block_status) } + end + end + end +end diff --git a/app/models/contact_request.rb b/app/models/contact_request.rb new file mode 100644 index 000000000..e6a5e9f7d --- /dev/null +++ b/app/models/contact_request.rb @@ -0,0 +1,40 @@ +class ContactRequest < ApplicationRecord + establish_connection :"whois_#{Rails.env}" + self.table_name = 'contact_requests' + + STATUS_NEW = 'new'.freeze + STATUS_CONFIRMED = 'confirmed'.freeze + STATUS_SENT = 'sent'.freeze + STATUSES = [STATUS_NEW, STATUS_CONFIRMED, STATUS_SENT].freeze + + validates :whois_record_id, presence: true + validates :email, presence: true + validates :name, presence: true + validates :status, inclusion: { in: STATUSES } + + attr_readonly :secret, + :valid_to + + def self.save_record(params) + contact_request = new(params) + contact_request.secret = create_random_secret + contact_request.valid_to = set_valid_to_24_hours_from_now + contact_request.status = STATUS_NEW + contact_request.save! + contact_request + end + + def update_status(params) + self.status = params['status'] + self.ip_address = params['ip'] + save! + end + + def self.create_random_secret + SecureRandom.hex(64) + end + + def self.set_valid_to_24_hours_from_now + (Time.zone.now + 24.hours) + end +end diff --git a/app/models/domain.rb b/app/models/domain.rb index 3acc08575..53f0fa5b6 100644 --- a/app/models/domain.rb +++ b/app/models/domain.rb @@ -10,6 +10,7 @@ class Domain < ApplicationRecord include Concerns::Domain::RegistryLockable include Concerns::Domain::Releasable include Concerns::Domain::Disputable + include Concerns::Domain::BulkUpdatable attr_accessor :roles diff --git a/app/models/tech_domain_contact.rb b/app/models/tech_domain_contact.rb index 92799061c..20f21b6ed 100644 --- a/app/models/tech_domain_contact.rb +++ b/app/models/tech_domain_contact.rb @@ -6,7 +6,7 @@ class TechDomainContact < DomainContact tech_contacts = where(contact: current_contact) tech_contacts.each do |tech_contact| - if tech_contact.domain.discarded? + if tech_contact.domain.bulk_update_prohibited? skipped_domains << tech_contact.domain.name next end @@ -18,7 +18,6 @@ class TechDomainContact < DomainContact skipped_domains << tech_contact.domain.name end end - [affected_domains.sort, skipped_domains.sort] end end diff --git a/app/models/white_ip.rb b/app/models/white_ip.rb index 417633b12..38cee7b6b 100644 --- a/app/models/white_ip.rb +++ b/app/models/white_ip.rb @@ -4,8 +4,13 @@ class WhiteIp < ApplicationRecord validate :valid_ipv4? validate :valid_ipv6? - validate :validate_ipv4_and_ipv6 + before_save :normalize_blank_values + + def normalize_blank_values + %i[ipv4 ipv6].each { |c| self[c].present? || self[c] = nil } + end + def validate_ipv4_and_ipv6 return if ipv4.present? || ipv6.present? errors.add(:base, I18n.t(:ipv4_or_ipv6_must_be_present)) @@ -50,10 +55,10 @@ class WhiteIp < ApplicationRecord def ids_including(ip) ipv4 = ipv6 = [] if check_ip4(ip).present? - ipv4 = select { |white_ip| IPAddr.new(white_ip.ipv4, Socket::AF_INET) === check_ip4(ip) } + ipv4 = select { |white_ip| check_ip4(white_ip.ipv4) === check_ip4(ip) } end if check_ip6(ip).present? - ipv6 = select { |white_ip| IPAddr.new(white_ip.ipv6, Socket::AF_INET6) === check_ip6(ip) } + ipv6 = select { |white_ip| check_ip6(white_ip.ipv6) === check_ip6(ip) } end (ipv4 + ipv6).pluck(:id).flatten.uniq end diff --git a/app/views/admin/repp_logs/show.haml b/app/views/admin/repp_logs/show.haml index bbaae977f..9bb9ea52e 100644 --- a/app/views/admin/repp_logs/show.haml +++ b/app/views/admin/repp_logs/show.haml @@ -1,6 +1,6 @@ - content_for :actions do = link_to(t(:back), :back, class: 'btn btn-primary') -= render 'shared/title', name: t(:repp_log) += render 'shared/title', name: t('.title') .row .col-md-12 diff --git a/config/application.yml.sample b/config/application.yml.sample index 5885c47a2..dd38e206c 100644 --- a/config/application.yml.sample +++ b/config/application.yml.sample @@ -87,8 +87,11 @@ sk_digi_doc_service_name: 'Testimine' registrant_api_base_url: registrant_api_auth_allowed_ips: '127.0.0.1, 0.0.0.0' #ips, separated with commas -# Bounces API -api_shared_key: testkey +# Shared key for REST-WHOIS Bounces API incl. CERT +rwhois_bounces_api_shared_key: testkey + +# Link to REST-WHOIS API +rwhois_internal_api_shared_key: testkey # Base URL (inc. https://) of REST registrant portal # Leave blank to use internal registrant portal diff --git a/config/initializers/aws_ses.rb b/config/initializers/aws_ses.rb new file mode 100644 index 000000000..baa148e65 --- /dev/null +++ b/config/initializers/aws_ses.rb @@ -0,0 +1,4 @@ +Aws.config.update( + region: ENV['aws_default_region'], + credentials: Aws::Credentials.new(ENV['aws_access_key_id'], ENV['aws_secret_access_key']) +) diff --git a/config/locales/admin/repp_logs.en.yml b/config/locales/admin/repp_logs.en.yml index 559ae234a..0a58fe7ba 100644 --- a/config/locales/admin/repp_logs.en.yml +++ b/config/locales/admin/repp_logs.en.yml @@ -4,3 +4,6 @@ en: index: title: REPP log reset_btn: Reset + show: + title: REPP log + diff --git a/config/routes.rb b/config/routes.rb index 3042eced4..1635789fe 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -91,6 +91,7 @@ Rails.application.routes.draw do end resources :auctions, only: %i[index show update], param: :uuid + resources :contact_requests, only: %i[create update], param: :id resources :bounces, only: %i[create] end diff --git a/test/application_system_test_case.rb b/test/application_system_test_case.rb index b31489691..726767390 100644 --- a/test/application_system_test_case.rb +++ b/test/application_system_test_case.rb @@ -35,7 +35,6 @@ class JavaScriptApplicationSystemTestCase < ApplicationSystemTestCase def setup DatabaseCleaner.start - super Capybara.current_driver = :chrome diff --git a/test/fixtures/contact_requests.yml b/test/fixtures/contact_requests.yml new file mode 100644 index 000000000..030a4d726 --- /dev/null +++ b/test/fixtures/contact_requests.yml @@ -0,0 +1,8 @@ +new: + whois_record_id: 1 + email: aaa@bbb.com + name: Testname + status: new + secret: somesecret + valid_to: 2010-07-05 + diff --git a/test/integration/admin_area/account_activities_test.rb b/test/integration/admin_area/account_activities_test.rb new file mode 100644 index 000000000..306935269 --- /dev/null +++ b/test/integration/admin_area/account_activities_test.rb @@ -0,0 +1,39 @@ +require 'test_helper' +require 'application_system_test_case' + +class AdminAreaAccountActivitiesIntegrationTest < ApplicationSystemTestCase + # /admin/account_activities + setup do + sign_in users(:admin) + @original_default_language = Setting.default_language + end + + def test_show_account_activities_page + account_activities(:one).update(sum: "123.00") + visit admin_account_activities_path + assert_text 'Account activities' + end + + def test_default_url_params + account_activities(:one).update(sum: "123.00") + visit admin_root_path + click_link_or_button 'Settings', match: :first + find(:xpath, "//ul/li/a[text()='Account activities']").click + + assert has_current_path?(admin_account_activities_path(created_after: 'today')) + end + + def test_download_account_activity + now = Time.zone.parse('2010-07-05 08:00') + travel_to now + account_activities(:one).update(sum: "123.00") + + get admin_account_activities_path(format: :csv) + + assert_response :ok + assert_equal "text/csv", response.headers['Content-Type'] + assert_equal %(attachment; filename="account_activities_#{Time.zone.now.to_formatted_s(:number)}.csv"; filename*=UTF-8''account_activities_#{Time.zone.now.to_formatted_s(:number)}.csv), + response.headers['Content-Disposition'] + assert_not_empty response.body + end +end diff --git a/test/integration/admin_area/admin_users_test.rb b/test/integration/admin_area/admin_users_test.rb new file mode 100644 index 000000000..89b9edef9 --- /dev/null +++ b/test/integration/admin_area/admin_users_test.rb @@ -0,0 +1,101 @@ +require 'test_helper' +require 'application_system_test_case' + +class AdminAreaAdminUsersIntegrationTest < JavaScriptApplicationSystemTestCase + include Devise::Test::IntegrationHelpers + include ActionView::Helpers::NumberHelper + + setup do + WebMock.allow_net_connect! + @original_default_language = Setting.default_language + sign_in users(:admin) + end + + def test_create_new_admin_user + createNewAdminUser(true) + end + + def test_create_with_invalid_data_new_admin_user + createNewAdminUser(false) + end + + def test_edit_successfully_exist_record + createNewAdminUser(true) + + visit admin_admin_users_path + click_on 'test_user_name' + + assert_text 'General' + click_on 'Edit' + + fill_in 'Password', with: 'test_password' + fill_in 'Password confirmation', with: 'test_password' + + click_on 'Save' + assert_text 'Record updated' + end + + def test_edit_exist_record_with_invalid_data + createNewAdminUser(true) + + visit admin_admin_users_path + click_on 'test_user_name' + + assert_text 'General' + click_on 'Edit' + + fill_in 'Password', with: 'test_password' + fill_in 'Password confirmation', with: 'test_password2' + + click_on 'Save' + assert_text 'Failed to update record' + end + + def test_delete_exist_record + createNewAdminUser(true) + + visit admin_admin_users_path + click_on 'test_user_name' + assert_text 'General' + click_on 'Delete' + + page.driver.browser.switch_to.alert.accept + + assert_text 'Record deleted' + end + + private + + def createNewAdminUser(valid) + visit admin_admin_users_path + click_on 'New admin user' + + fill_in 'Username', with: 'test_user_name' + # If valid=true creating valid user, if else, then with invalid data + if valid + fill_in 'Password', with: 'test_password' + fill_in 'Password confirmation', with: 'test_password' + else + fill_in 'Password', with: 'test_password' + fill_in 'Password confirmation', with: 'test_password2' + end + fill_in 'Identity code', with: '38903110313' + fill_in 'Email', with: 'oleg@tester.ee' + + select 'Estonia', from: 'admin_user_country_code', match: :first + + select_element = find(:xpath, "/html/body/div[2]/form/div[2]/div/div[7]/div[2]/div/div[1]") + select_element.click + + option_element = find(:xpath, "/html/body/div[2]/form/div[2]/div/div[7]/div[2]/div/div[2]/div/div[1]") + option_element.click + + click_on 'Save' + + if valid + assert_text 'Record created' + else + assert_text 'Failed to create record' + end + end +end diff --git a/test/integration/admin_area/blocked_domains_test.rb b/test/integration/admin_area/blocked_domains_test.rb new file mode 100644 index 000000000..7df9d30e7 --- /dev/null +++ b/test/integration/admin_area/blocked_domains_test.rb @@ -0,0 +1,68 @@ +require 'test_helper' +require 'application_system_test_case' + + +# /admin/blocked_domains +class AdminAreaBlockedDomainsIntegrationTest < JavaScriptApplicationSystemTestCase + setup do + WebMock.allow_net_connect! + sign_in users(:admin) + @domain = domains(:shop) + @blocked_domain = blocked_domains(:one) + end + + def test_page_successfully_loaded + visit_admin_blocked_domains_path + end + + def test_add_into_blocked_list + visit_admin_blocked_domains_path + add_domain_into_blocked_list(true) + end + + def test_add_into_blocked_list_same_domain + visit_admin_blocked_domains_path + add_domain_into_blocked_list(true) + add_domain_into_blocked_list(false) + end + + def test_delete_domain_from_blocked_list + visit_admin_blocked_domains_path + add_domain_into_blocked_list(true) + + click_link_or_button 'Delete', match: :first + + # Accept to delete in modal window + page.driver.browser.switch_to.alert.accept + + assert_text 'Domain deleted!' + end + + def test_find_blocked_domain_from_blocked_list + visit_admin_blocked_domains_path + add_domain_into_blocked_list(true) + + fill_in 'Name', with: @domain.name + find(:xpath, "//span[@class='glyphicon glyphicon-search']").click + + assert_text @domain.name + end + + private + + def visit_admin_blocked_domains_path + visit admin_blocked_domains_path + assert_text 'Blocked domains' + end + + def add_domain_into_blocked_list(value) + click_on 'New blocked domain' + assert_text 'Add domain to blocked list' + + fill_in 'Name', with: @domain.name + click_on 'Save' + + return assert_text 'Domain added!' if value + return assert_text 'Failed to add domain!' + end +end diff --git a/test/integration/admin_area/certificates_test.rb b/test/integration/admin_area/certificates_test.rb new file mode 100644 index 000000000..d2eec0bc4 --- /dev/null +++ b/test/integration/admin_area/certificates_test.rb @@ -0,0 +1,71 @@ +require 'test_helper' +require 'application_system_test_case' + +class AdminAreaCertificatesIntegrationTest < JavaScriptApplicationSystemTestCase + + setup do + WebMock.allow_net_connect! + sign_in users(:admin) + + @apiuser = users(:api_bestnames) + @certificate = certificates(:api) + @certificate.update!(csr: "-----BEGIN CERTIFICATE REQUEST-----\nMIICszCCAZsCAQAwbjELMAkGA1UEBhMCRUUxFDASBgNVBAMMC2ZyZXNoYm94LmVl\nMRAwDgYDVQQHDAdUYWxsaW5uMREwDwYDVQQKDAhGcmVzaGJveDERMA8GA1UECAwI\nSGFyanVtYWExETAPBgNVBAsMCEZyZXNoYm94MIIBIjANBgkqhkiG9w0BAQEFAAOC\nAQ8AMIIBCgKCAQEA1VVESynZoZhIbe8s9zHkELZ/ZDCGiM2Q8IIGb1IOieT5U2mx\nIsVXz85USYsSQY9+4YdEXnupq9fShArT8pstS/VN6BnxdfAiYXc3UWWAuaYAdNGJ\nDr5Jf6uMt1wVnCgoDL7eJq9tWMwARC/viT81o92fgqHFHW0wEolfCmnpik9o0ACD\nFiWZ9IBIevmFqXtq25v9CY2cT9+eZW127WtJmOY/PKJhzh0QaEYHqXTHWOLZWpnp\nHH4elyJ2CrFulOZbHPkPNB9Nf4XQjzk1ffoH6e5IVys2VV5xwcTkF0jY5XTROVxX\nlR2FWqic8Q2pIhSks48+J6o1GtXGnTxv94lSDwIDAQABoAAwDQYJKoZIhvcNAQEL\nBQADggEBAEFcYmQvcAC8773eRTWBJJNoA4kRgoXDMYiiEHih5iJPVSxfidRwYDTF\nsP+ttNTUg3JocFHY75kuM9T2USh+gu/trRF0o4WWa+AbK3JbbdjdT1xOMn7XtfUU\nZ/f1XCS9YdHQFCA6nk4Z+TLWwYsgk7n490AQOiB213fa1UIe83qIfw/3GRqRUZ7U\nwIWEGsHED5WT69GyxjyKHcqGoV7uFnqFN0sQVKVTy/NFRVQvtBUspCbsOirdDRie\nAB2KbGHL+t1QrRF10szwCJDyk5aYlVhxvdI8zn010nrxHkiyQpDFFldDMLJl10BW\n2w9PGO061z+tntdRcKQGuEpnIr9U5Vs=\n-----END CERTIFICATE REQUEST-----\n") + end + + def test_show_certificate_info + show_certificate_info + end + + def test_destroy_certificate + show_certificate_info + find(:xpath, "//a[text()='Delete']").click + + page.driver.browser.switch_to.alert.accept + + assert_text 'Record deleted' + end + + def test_download_csr + get download_csr_admin_api_user_certificate_path(api_user_id: @apiuser.id, id: @certificate.id) + + assert_response :ok + assert_equal 'application/octet-stream', response.headers['Content-Type'] + assert_equal "attachment; filename=\"test_bestnames.csr.pem\"; filename*=UTF-8''test_bestnames.csr.pem", response.headers['Content-Disposition'] + assert_not_empty response.body + end + + def test_download_crt + get download_crt_admin_api_user_certificate_path(api_user_id: @apiuser.id, id: @certificate.id) + + assert_response :ok + assert_equal 'application/octet-stream', response.headers['Content-Type'] + assert_equal "attachment; filename=\"test_bestnames.crt.pem\"; filename*=UTF-8''test_bestnames.crt.pem", response.headers['Content-Disposition'] + assert_not_empty response.body + end + + def test_failed_to_revoke_certificate + show_certificate_info + + find(:xpath, "//a[text()='Revoke this certificate']").click + assert_text 'Failed to update record' + end + + def test_new_api_user + visit new_admin_registrar_api_user_path(registrar_id: registrars(:bestnames).id) + + fill_in 'Username', with: 'testapiuser' + fill_in 'Password', with: 'secretpassword' + fill_in 'Identity code', with: '60305062718' + + click_on 'Create API user' + + assert_text 'API user has been successfully created' + end + + private + + def show_certificate_info + visit admin_api_user_certificate_path(api_user_id: @apiuser.id, id: @certificate.id) + assert_text 'Certificates' + end +end diff --git a/test/integration/admin_area/epp_logs_test.rb b/test/integration/admin_area/epp_logs_test.rb new file mode 100644 index 000000000..5ad514cb8 --- /dev/null +++ b/test/integration/admin_area/epp_logs_test.rb @@ -0,0 +1,52 @@ +# admin_epp_logs_path +require 'test_helper' +require 'application_system_test_case' + +class AdminEppLogsIntegrationTest < ApplicationSystemTestCase + setup do + sign_in users(:admin) + end + + def test_visit_epp_logs_page + visit admin_epp_logs_path + assert_text 'EPP log' + end + + def test_show_epp_log_page + visit admin_epp_logs_path + send_epp_request_hello + visit admin_epp_logs_path + + find(:xpath, "//tbody/tr/td/a", match: :first).click + assert_text 'Details' + end + + def test_dates_sort + Capybara.exact = true + visit admin_epp_logs_path + send_epp_request_hello + visit admin_epp_logs_path + + find(:xpath, "//a[contains(text(), 'Created at')]", match: :first).click + find(:xpath, "//a[contains(text(), 'Created at')]", match: :first).click + + epp_log_date = find(:xpath, "//table/tbody/tr/td[6]", match: :first).text(:all) + date_now = Date.today.to_s(:db) + + assert_match /#{date_now}/, epp_log_date + end + + private + + def send_epp_request_hello + request_xml = <<-XML + + + + + XML + + get epp_hello_path, params: { frame: request_xml }, + headers: { 'HTTP_COOKIE' => 'session=non-existent' } + end +end diff --git a/test/integration/admin_area/invoices_test.rb b/test/integration/admin_area/invoices_test.rb index 887f57212..2aa17201d 100644 --- a/test/integration/admin_area/invoices_test.rb +++ b/test/integration/admin_area/invoices_test.rb @@ -6,6 +6,27 @@ class AdminAreaInvoicesIntegrationTest < ApplicationIntegrationTest sign_in users(:admin) end + def test_create_new_invoice + visit new_admin_invoice_path + + assert_text 'Create new invoice' + select 'Best Names', from: 'deposit_registrar_id', match: :first + fill_in 'Amount', with: '1000' + click_on 'Save' + + assert_equal page.status_code, 200 + end + + def test_visit_list_of_invoices_pages + visit admin_invoices_path + assert_text 'Invoices' + end + + def test_visit_invoice_page + visit admin_invoices_path(id: @invoice.id) + assert_text "Invoice no. #{@invoice.number}" + end + def test_downloads_invoice assert_equal 1, @invoice.number diff --git a/test/integration/admin_area/pending_delete_test.rb b/test/integration/admin_area/pending_delete_test.rb new file mode 100644 index 000000000..737d12480 --- /dev/null +++ b/test/integration/admin_area/pending_delete_test.rb @@ -0,0 +1,60 @@ +require 'test_helper' +require 'application_system_test_case' + +class AdminAreaPendingDeleteIntegrationTest < JavaScriptApplicationSystemTestCase + setup do + WebMock.allow_net_connect! + sign_in users(:admin) + + @domain = domains(:shop) + @token = '123456' + + @domain.update!(statuses: [DomainStatus::PENDING_DELETE_CONFIRMATION], + registrant_verification_asked_at: Time.zone.now - 1.day, + registrant_verification_token: @token) + end + + def test_accept_pending_delete + visit edit_admin_domain_path(id: @domain.id) + + click_on 'Accept' + page.driver.browser.switch_to.alert.accept + + assert_text 'Pending was successfully applied.' + end + + def test_accept_pending_delete_no_success + @domain.update!(statuses: [DomainStatus::PENDING_DELETE_CONFIRMATION], + registrant_verification_asked_at: Time.zone.now - 1.day, + registrant_verification_token: nil) + + visit edit_admin_domain_path(id: @domain.id) + + click_on 'Accept' + page.driver.browser.switch_to.alert.accept + + assert_text 'Not success' + end + + def test_reject_panding_delete + visit edit_admin_domain_path(id: @domain.id) + + click_on 'Reject' + page.driver.browser.switch_to.alert.accept + + assert_text 'Pending was successfully removed.' + end + + def test_accept_pending_delete_no_success + @domain.update!(statuses: [DomainStatus::PENDING_DELETE_CONFIRMATION], + registrant_verification_asked_at: Time.zone.now - 1.day, + registrant_verification_token: nil) + + visit edit_admin_domain_path(id: @domain.id) + + click_on 'Reject' + page.driver.browser.switch_to.alert.accept + + assert_text 'Not success' + end +end diff --git a/test/integration/admin_area/pending_update_test.rb b/test/integration/admin_area/pending_update_test.rb new file mode 100644 index 000000000..5d08e104b --- /dev/null +++ b/test/integration/admin_area/pending_update_test.rb @@ -0,0 +1,96 @@ +require 'test_helper' +require 'application_system_test_case' + +class AdminAreaPendingUpdateIntegrationTest < JavaScriptApplicationSystemTestCase + + setup do + WebMock.allow_net_connect! + sign_in users(:admin) + + @domain = domains(:hospital) + + @new_registrant = contacts(:jack) + @user = users(:api_bestnames) + @token = '123456' + + @domain.update!(statuses: [DomainStatus::PENDING_UPDATE], + registrant_verification_asked_at: Time.zone.now - 1.day, + registrant_verification_token: @token) + end + + def test_accept_pending_update + pending_json = { new_registrant_id: @new_registrant.id, + new_registrant_name: @new_registrant.name, + new_registrant_email: @new_registrant.email, + current_user_id: @user.id } + + @domain.update(pending_json: pending_json) + @domain.reload + + visit edit_admin_domain_path(id: @domain.id) + + click_on 'Accept' + page.driver.browser.switch_to.alert.accept + + assert_text 'Pending was successfully applied.' + end + + def test_accept_pending_update_no_success + @domain.update!(statuses: [DomainStatus::PENDING_UPDATE], + registrant_verification_asked_at: Time.zone.now - 1.day, + registrant_verification_token: nil) + + pending_json = { new_registrant_id: @new_registrant.id, + new_registrant_name: @new_registrant.name, + new_registrant_email: @new_registrant.email, + current_user_id: @user.id, + } + + @domain.update(pending_json: pending_json) + @domain.reload + + visit edit_admin_domain_path(id: @domain.id) + + click_on 'Accept' + page.driver.browser.switch_to.alert.accept + assert_text 'Not success' + end + + def test_reject_panding_update + pending_json = { new_registrant_id: @new_registrant.id, + new_registrant_name: @new_registrant.name, + new_registrant_email: @new_registrant.email, + current_user_id: @user.id, + } + + @domain.update(pending_json: pending_json) + @domain.reload + + visit edit_admin_domain_path(id: @domain.id) + + click_on 'Reject' + page.driver.browser.switch_to.alert.accept + assert_text 'Pending was successfully removed.' + end + + def test_accept_pending_update_no_success + @domain.update!(statuses: [DomainStatus::PENDING_UPDATE], + registrant_verification_asked_at: Time.zone.now - 1.day, + registrant_verification_token: nil) + + pending_json = { new_registrant_id: @new_registrant.id, + new_registrant_name: @new_registrant.name, + new_registrant_email: @new_registrant.email, + current_user_id: @user.id, + } + + @domain.update(pending_json: pending_json) + @domain.reload + + visit edit_admin_domain_path(id: @domain.id) + + click_on 'Reject' + page.driver.browser.switch_to.alert.accept + assert_text 'Not success' + end +end diff --git a/test/integration/admin_area/registrars_test.rb b/test/integration/admin_area/registrars_test.rb index d73496899..552650791 100644 --- a/test/integration/admin_area/registrars_test.rb +++ b/test/integration/admin_area/registrars_test.rb @@ -17,4 +17,4 @@ class AdminAreaRegistrarsIntegrationTest < ActionDispatch::IntegrationTest assert_equal new_iban, @registrar.iban end -end \ No newline at end of file +end diff --git a/test/integration/admin_area/repp_logs_test.rb b/test/integration/admin_area/repp_logs_test.rb new file mode 100644 index 000000000..6630a6d57 --- /dev/null +++ b/test/integration/admin_area/repp_logs_test.rb @@ -0,0 +1,23 @@ +require 'test_helper' +require 'application_system_test_case' + +class AdminAreaReppLogsIntegrationTest < ApplicationSystemTestCase + setup do + sign_in users(:admin) + end + + def test_repp_logs_page + visit admin_repp_logs_path + assert_text 'REPP log' + end + + def test_show_repp_log_page + visit admin_repp_logs_path + get repp_v1_contacts_path + visit admin_repp_logs_path + + find(:xpath, "//tbody/tr/td/a", match: :first).click + + assert_text 'REPP log' + end +end diff --git a/test/integration/admin_area/reserved_domains_test.rb b/test/integration/admin_area/reserved_domains_test.rb new file mode 100644 index 000000000..c09c3723b --- /dev/null +++ b/test/integration/admin_area/reserved_domains_test.rb @@ -0,0 +1,39 @@ +require 'test_helper' +require 'application_system_test_case' + +class AdminAreaReservedDomainsIntegrationTest < JavaScriptApplicationSystemTestCase + + setup do + WebMock.allow_net_connect! + @original_default_language = Setting.default_language + sign_in users(:admin) + + @reserved_domain = reserved_domains(:one) + end + + def test_remove_reserved_domain + visit admin_reserved_domains_path + click_link_or_button 'Delete', match: :first + page.driver.browser.switch_to.alert.accept + + assert_text 'Domain deleted!' + end + + def test_add_invalid_domain + visit admin_reserved_domains_path + click_on 'New reserved domain' + fill_in "Name", with: "@##@$" + click_on 'Save' + + assert_text 'Failed to add domain!' + end + + def test_update_reserved_domain + visit admin_reserved_domains_path + click_link_or_button 'Edit Pw', match: :first + fill_in 'Password', with: '12345678' + click_on 'Save' + + assert_text 'Domain updated!' + end +end diff --git a/test/integration/admin_area/white_ips_test.rb b/test/integration/admin_area/white_ips_test.rb new file mode 100644 index 000000000..499c86f57 --- /dev/null +++ b/test/integration/admin_area/white_ips_test.rb @@ -0,0 +1,94 @@ +require 'test_helper' +require 'application_system_test_case' + +class AdminAreaWhiteIpsIntegrationTest < JavaScriptApplicationSystemTestCase + + setup do + WebMock.allow_net_connect! + sign_in users(:admin) + + @registrar = registrars(:bestnames) + @white_ip = white_ips(:one) + end + + def test_visit_new_whitelisted_ip_page + visit_new_whitelisted_ip_page + end + + def test_create_new_whitelisted_ip + visit_new_whitelisted_ip_page + fill_in 'IPv4', with: "127.0.0.1" + fill_in 'IPv6', with: "::ffff:192.0.2.1" + + find(:css, "#white_ip_interfaces_api").set(true) + find(:css, "#white_ip_interfaces_registrar").set(true) + + click_on 'Save' + + assert_text 'Record created' + end + + def test_failed_to_create_new_whitelisted_ip + visit_new_whitelisted_ip_page + fill_in 'IPv4', with: "asdadadad.asd" + + click_on 'Save' + + assert_text 'Failed to create record' + end + + def test_visit_edit_whitelisted_ip_page + visit_edit_whitelisted_ip_page + end + + def test_update_whitelisted_ip + visit_info_whitelisted_ip_page + click_on 'Edit' + + fill_in 'IPv4', with: "127.0.0.2" + find(:css, "#white_ip_interfaces_api").set(false) + click_on 'Save' + + assert_text 'Record updated' + end + + def test_failed_to_update_whitelisted_ip + visit_info_whitelisted_ip_page + click_on 'Edit' + fill_in 'IPv4', with: "asdadad#" + + click_on 'Save' + + assert_text 'Failed to update record' + end + + def test_visit_info_whitelisted_ip_page + visit_info_whitelisted_ip_page + end + + def test_delete_whitelisted_ip + visit_info_whitelisted_ip_page + click_on 'Delete' + + page.driver.browser.switch_to.alert.accept + + assert_text 'Record deleted' + end + + private + + def visit_new_whitelisted_ip_page + visit new_admin_registrar_white_ip_path(registrar_id: @registrar.id) + assert_text 'New whitelisted IP' + end + + def visit_edit_whitelisted_ip_page + visit edit_admin_registrar_white_ip_path(registrar_id: @registrar.id, id: @white_ip.id) + assert_text 'Edit white IP' + end + + def visit_info_whitelisted_ip_page + visit admin_registrar_white_ip_path(registrar_id: @registrar.id, id: @white_ip.id) + assert_text 'White IP' + end +end diff --git a/test/integration/api/domain_contacts_test.rb b/test/integration/api/domain_contacts_test.rb index 6704739d1..efd7032b4 100644 --- a/test/integration/api/domain_contacts_test.rb +++ b/test/integration/api/domain_contacts_test.rb @@ -107,6 +107,24 @@ class APIDomainContactsTest < ApplicationIntegrationTest JSON.parse(response.body, symbolize_names: true) end + def test_tech_bulk_changed_when_domain_update_prohibited + domains(:shop).update!(statuses: [DomainStatus::SERVER_UPDATE_PROHIBITED]) + + shop_tech_contact = Contact.find_by(code: 'william-001') + assert domains(:shop).tech_contacts.include?(shop_tech_contact) + + patch '/repp/v1/domains/contacts', params: { current_contact_id: 'william-001', + new_contact_id: 'john-001' }, + headers: { 'HTTP_AUTHORIZATION' => http_auth_key } + + assert_response :ok + assert_equal ({ code: 1000, + message: 'Command completed successfully', + data: { affected_domains: ["airport.test"], + skipped_domains: ["shop.test"] }}), + JSON.parse(response.body, symbolize_names: true) + end + private def http_auth_key diff --git a/test/integration/api/v1/bounces/create_test.rb b/test/integration/api/v1/bounces/create_test.rb index 899b6c5c7..0d3dc65d7 100644 --- a/test/integration/api/v1/bounces/create_test.rb +++ b/test/integration/api/v1/bounces/create_test.rb @@ -2,7 +2,7 @@ require 'test_helper' class BouncesApiV1CreateTest < ActionDispatch::IntegrationTest def setup - @api_key = "Basic #{ENV['api_shared_key']}" + @api_key = "Basic #{ENV['rwhois_bounces_api_shared_key']}" @headers = { "Authorization": "#{@api_key}" } @json_body = { "data": valid_bounce_request }.as_json end diff --git a/test/integration/api/v1/contact_requests_test.rb b/test/integration/api/v1/contact_requests_test.rb new file mode 100644 index 000000000..c9e2ac9bd --- /dev/null +++ b/test/integration/api/v1/contact_requests_test.rb @@ -0,0 +1,68 @@ +require 'test_helper' + +class ApiV1ContactRequestTest < ActionDispatch::IntegrationTest + def setup + @api_key = "Basic #{ENV['rwhois_internal_api_shared_key']}" + @headers = { "Authorization": "#{@api_key}" } + @json_create = { "contact_request": valid_contact_request_create }.as_json + @json_update = { "contact_request": valid_contact_request_update }.as_json + @contact_request = contact_requests(:new) + end + + def test_authorizes_api_request + post api_v1_contact_requests_path, params: @json_create, headers: @headers + assert_response :created + + invalid_headers = { "Authorization": "Basic invalid_api_key" } + post api_v1_contact_requests_path, params: @json_create, headers: invalid_headers + assert_response :unauthorized + end + + def test_saves_new_contact_request + request_body = @json_create.dup + random_mail = "#{rand(10000..99999)}@registry.test" + request_body['contact_request']['email'] = random_mail + + post api_v1_contact_requests_path, params: request_body, headers: @headers + assert_response :created + + contact_request = ContactRequest.last + assert_equal contact_request.email, random_mail + assert ContactRequest::STATUS_NEW, contact_request.status + end + + def test_updates_existing_contact_request + request_body = @json_update.dup + + put api_v1_contact_request_path(@contact_request.id), params: request_body, headers: @headers + assert_response :ok + + @contact_request.reload + assert ContactRequest::STATUS_CONFIRMED, @contact_request.status + end + + def test_not_updates_if_status_error + request_body = @json_update.dup + request_body['contact_request']['status'] = 'some_error_status' + + put api_v1_contact_request_path(@contact_request.id), params: request_body, headers: @headers + assert_response 400 + + @contact_request.reload + assert ContactRequest::STATUS_NEW, @contact_request.status + end + + def valid_contact_request_create + { + "email": "aaa@bbb.com", + "whois_record_id": "1", + "name": "test" + }.as_json + end + + def valid_contact_request_update + { + "status": "#{ContactRequest::STATUS_CONFIRMED}", + }.as_json + end +end diff --git a/test/integration/api/v1/registrant/contacts/list_test.rb b/test/integration/api/v1/registrant/contacts/list_test.rb index 2389019f1..33e8b67eb 100644 --- a/test/integration/api/v1/registrant/contacts/list_test.rb +++ b/test/integration/api/v1/registrant/contacts/list_test.rb @@ -1,5 +1,6 @@ require 'test_helper' require 'auth_token/auth_token_creator' +require 'json' CompanyRegisterClientStub = Struct.new(:any_method) do def representation_rights(citizen_personal_code:, citizen_country_code:) @@ -55,6 +56,42 @@ class RegistrantApiV1ContactListTest < ActionDispatch::IntegrationTest assert_equal '1234', response_json.first[:ident][:code] end + def test_out_of_range_limit + get api_v1_registrant_contacts_path + "?limit=300", as: :json, headers: { 'HTTP_AUTHORIZATION' => auth_token } + response_json = JSON.parse(response.body, symbolize_names: true) + + text_response = JSON.pretty_generate(response_json[:errors][0][:limit][0]) + + assert_equal text_response, '"parameter is out of range"' + end + + def test_negative_offset + get api_v1_registrant_contacts_path + "?offset=-300", as: :json, headers: { 'HTTP_AUTHORIZATION' => auth_token } + response_json = JSON.parse(response.body, symbolize_names: true) + + text_response = JSON.pretty_generate(response_json[:errors][0][:offset][0]) + + assert_equal text_response, '"parameter is out of range"' + end + + def test_show_valid_contact + get api_v1_registrant_contacts_path + "/eb2f2766-b44c-4e14-9f16-32ab1a7cb957", as: :json, headers: { 'HTTP_AUTHORIZATION' => auth_token } + response_json = JSON.parse(response.body, symbolize_names: true) + + text_response = response_json[:name] + + assert_equal @contact[:name], text_response + end + + def test_show_invalid_contact + get api_v1_registrant_contacts_path + "/435", as: :json, headers: { 'HTTP_AUTHORIZATION' => auth_token } + response_json = JSON.parse(response.body, symbolize_names: true) + + text_response = response_json[:errors][0][:base][0] + + assert_equal text_response, 'Contact not found' + end + private def delete_direct_contact diff --git a/test/integration/api/v1/registrant/contacts/update_test.rb b/test/integration/api/v1/registrant/contacts/update_test.rb index 4ddf8b0ff..c1eaa005c 100644 --- a/test/integration/api/v1/registrant/contacts/update_test.rb +++ b/test/integration/api/v1/registrant/contacts/update_test.rb @@ -4,11 +4,12 @@ require 'auth_token/auth_token_creator' class RegistrantApiV1ContactUpdateTest < ActionDispatch::IntegrationTest setup do @contact = contacts(:john) + @contact_org = contacts(:acme_ltd) @original_address_processing = Setting.address_processing @original_fax_enabled_setting = ENV['fax_enabled'] - @user = users(:registrant) + end teardown do @@ -90,6 +91,32 @@ class RegistrantApiV1ContactUpdateTest < ActionDispatch::IntegrationTest @contact.address end + def test_update_address_when_enabled_without_address_params + Setting.address_processing = true + + patch api_v1_registrant_contact_path(@contact.uuid), params: { address: { } }, + as: :json, + headers: { 'HTTP_AUTHORIZATION' => auth_token } + + assert_response :bad_request + @contact.reload + assert_equal Contact::Address.new(nil, nil, nil, nil, nil), + @contact.address + end + + def test_update_address_when_enabled_without_address_params + Setting.address_processing = true + + patch api_v1_registrant_contact_path(@contact.uuid), params: { }, + as: :json, + headers: { 'HTTP_AUTHORIZATION' => auth_token } + + assert_response :bad_request + @contact.reload + assert_equal Contact::Address.new(nil, nil, nil, nil, nil), + @contact.address + end + def test_address_is_optional_when_enabled Setting.address_processing = true @contact.update!(street: 'any', zip: 'any', city: 'any', state: 'any', country_code: 'US') @@ -211,6 +238,21 @@ class RegistrantApiV1ContactUpdateTest < ActionDispatch::IntegrationTest symbolize_names: true) end + def test_org_disclosed_attributes + patch api_v1_registrant_contact_path(@contact_org.uuid), params: { disclosed_attributes: ["some_attr"] }, + as: :json, + headers: { 'HTTP_AUTHORIZATION' => auth_token } + + assert_response :bad_request + + err_msg = "Legal person's data is visible by default and cannot be concealed. Please remove this parameter." + + response_json = JSON.parse(response.body, symbolize_names: true) + response_msg = response_json[:errors][0][:disclosed_attributes][0] + + assert_equal err_msg, response_msg + end + def test_unmanaged_contact_cannot_be_updated assert_equal 'US-1234', @user.registrant_ident @contact.update!(ident: '12345') diff --git a/test/models/domain_test.rb b/test/models/domain_test.rb index ae12f4a1e..15ab8b0c2 100644 --- a/test/models/domain_test.rb +++ b/test/models/domain_test.rb @@ -69,6 +69,12 @@ class DomainTest < ActiveSupport::TestCase domain.name = 'xn--mnchen-3ya.test' assert domain.valid? + + domain.name = '####' + assert domain.invalid? + + domain.name = 'https://example.test' + assert domain.invalid? end def test_invalid_when_name_is_already_taken diff --git a/test/models/white_ip_test.rb b/test/models/white_ip_test.rb index 607887730..ba5abe42f 100644 --- a/test/models/white_ip_test.rb +++ b/test/models/white_ip_test.rb @@ -38,6 +38,20 @@ class WhiteIpTest < ActiveSupport::TestCase assert white_ip.valid? end + def test_validates_include_empty_ipv4 + white_ip = WhiteIp.new + + white_ip.ipv4 = nil + white_ip.ipv6 = '001:0db8:85a3:0000:0000:8a2e:0370:7334' + white_ip.registrar = registrars(:bestnames) + + assert_nothing_raised { white_ip.save } + assert white_ip.valid? + + assert WhiteIp.include_ip?(white_ip.ipv6) + assert_not WhiteIp.include_ip?('192.168.1.1') + end + private def valid_white_ip diff --git a/test/system/admin_area/bank_statement_test.rb b/test/system/admin_area/bank_statement_test.rb index 6de21b1c3..8630049dc 100644 --- a/test/system/admin_area/bank_statement_test.rb +++ b/test/system/admin_area/bank_statement_test.rb @@ -4,6 +4,35 @@ class AdminAreaBankStatementTest < ApplicationSystemTestCase setup do sign_in users(:admin) travel_to Time.zone.parse('2010-07-05 00:30:00') + + @invoice = invoices(:one) + end + + def test_update_bank_statement + visit admin_bank_statement_path(id: @invoice.id) + + click_link_or_button 'Add' + + fill_in 'Description', with: 'Invoice with id 123' + fill_in 'Reference number', with: '1232' + fill_in 'Sum', with: '500' + fill_in 'Paid at', with: Time.zone.today.to_s + + click_link_or_button 'Save' + assert_text 'Bank transaction' + + click_link_or_button 'Edit' + fill_in 'Description', with: 'Invoice with id 123' + click_link_or_button 'Save' + + assert_text 'Record updated' + end + + def test_bind_bank + visit admin_bank_statement_path(id: @invoice.id) + click_link_or_button 'Bind invoices' + + assert_text 'No invoices were binded' end def test_can_create_statement_manually diff --git a/test/system/admin_area/contacts_test.rb b/test/system/admin_area/contacts_test.rb index d98882dff..19b15c8a5 100644 --- a/test/system/admin_area/contacts_test.rb +++ b/test/system/admin_area/contacts_test.rb @@ -8,6 +8,17 @@ class AdminContactsTest < ApplicationSystemTestCase sign_in users(:admin) end + def test_update_contact + visit admin_contact_path(id: @contact.id) + assert_text "#{@contact.name}" + + click_on 'Edit statuses' + assert_text "Edit: #{@contact.name}" + + click_on 'Save' + assert_text 'Contact updated' + end + def test_display_list visit admin_contacts_path diff --git a/test/system/admin_area/domains/legal_doc_test.rb b/test/system/admin_area/domains/legal_doc_test.rb index 00cc7cc3a..48eedcf4f 100644 --- a/test/system/admin_area/domains/legal_doc_test.rb +++ b/test/system/admin_area/domains/legal_doc_test.rb @@ -15,7 +15,7 @@ class AdminAreaDomainsLegalDocTest < ApplicationSystemTestCase def test_absent_doc_downloading_without_errors visit admin_domain_url(@domain) assert_nothing_raised do - click_on "#{@document.created_at}" + click_on "#{@document.created_at}", match: :first end end end diff --git a/test/system/admin_area/invoices_test.rb b/test/system/admin_area/invoices_test.rb index 814f95d4a..40a50e1c7 100644 --- a/test/system/admin_area/invoices_test.rb +++ b/test/system/admin_area/invoices_test.rb @@ -40,4 +40,4 @@ class AdminAreaInvoicesTest < ApplicationSystemTestCase assert_current_path admin_invoice_path(@invoice) assert_text 'Invoice has been sent' end -end \ No newline at end of file +end diff --git a/test/system/admin_area/protected_area_test.rb b/test/system/admin_area/protected_area_test.rb index f3375776a..fa413291b 100644 --- a/test/system/admin_area/protected_area_test.rb +++ b/test/system/admin_area/protected_area_test.rb @@ -19,4 +19,4 @@ class AdminAreaProtectedAreaTest < ApplicationSystemTestCase assert_text 'You are already signed in' assert_current_path admin_domains_path end -end \ No newline at end of file +end