-
Create a new check
+ <%= t(".#{@check.kind}.title") %>
<%= render "form", check: @check %>
diff --git a/app/views/kaminari/_first_page.html.erb b/app/views/kaminari/_first_page.html.erb
new file mode 100644
index 0000000..be84d7b
--- /dev/null
+++ b/app/views/kaminari/_first_page.html.erb
@@ -0,0 +1,11 @@
+<%# Link to the "First" page
+ - available local variables
+ url: url to the first page
+ current_page: a page object for the currently displayed page
+ total_pages: total number of pages
+ per_page: number of items to fetch per page
+ remote: data-remote
+-%>
+
+ <%= link_to t('views.pagination.first').html_safe, url, remote: remote, class: "page-link" %>
+
diff --git a/app/views/kaminari/_gap.html.erb b/app/views/kaminari/_gap.html.erb
new file mode 100644
index 0000000..cd730b7
--- /dev/null
+++ b/app/views/kaminari/_gap.html.erb
@@ -0,0 +1,10 @@
+<%# Non-link tag that stands for skipped pages...
+ - available local variables
+ current_page: a page object for the currently displayed page
+ total_pages: total number of pages
+ per_page: number of items to fetch per page
+ remote: data-remote
+-%>
+
+ <%= t('views.pagination.truncate').html_safe %>
+
diff --git a/app/views/kaminari/_last_page.html.erb b/app/views/kaminari/_last_page.html.erb
new file mode 100644
index 0000000..4ef40e0
--- /dev/null
+++ b/app/views/kaminari/_last_page.html.erb
@@ -0,0 +1,11 @@
+<%# Link to the "Last" page
+ - available local variables
+ url: url to the last page
+ current_page: a page object for the currently displayed page
+ total_pages: total number of pages
+ per_page: number of items to fetch per page
+ remote: data-remote
+-%>
+
+ <%= link_to t('views.pagination.last').html_safe, url, remote: remote, class: "page-link" %>
+
diff --git a/app/views/kaminari/_next_page.html.erb b/app/views/kaminari/_next_page.html.erb
new file mode 100644
index 0000000..c967dd8
--- /dev/null
+++ b/app/views/kaminari/_next_page.html.erb
@@ -0,0 +1,11 @@
+<%# Link to the "Next" page
+ - available local variables
+ url: url to the next page
+ current_page: a page object for the currently displayed page
+ total_pages: total number of pages
+ per_page: number of items to fetch per page
+ remote: data-remote
+-%>
+
+ <%= link_to t('views.pagination.next').html_safe, url, rel: 'next', remote: remote, class: "page-link" %>
+
diff --git a/app/views/kaminari/_page.html.erb b/app/views/kaminari/_page.html.erb
new file mode 100644
index 0000000..efcbe03
--- /dev/null
+++ b/app/views/kaminari/_page.html.erb
@@ -0,0 +1,15 @@
+<%# Link showing page number
+ - available local variables
+ page: a page object for "this" page
+ url: url to this page
+ current_page: a page object for the currently displayed page
+ total_pages: total number of pages
+ per_page: number of items to fetch per page
+ remote: data-remote
+-%>
+
+ <%= link_to page, url, remote: remote, rel: page.rel, class: "page-link" %>
+ <% if page.current? %>
+ (current)
+ <% end %>
+
diff --git a/app/views/kaminari/_paginator.html.erb b/app/views/kaminari/_paginator.html.erb
new file mode 100644
index 0000000..7a26612
--- /dev/null
+++ b/app/views/kaminari/_paginator.html.erb
@@ -0,0 +1,27 @@
+<%# The container tag
+ - available local variables
+ current_page: a page object for the currently displayed page
+ total_pages: total number of pages
+ per_page: number of items to fetch per page
+ remote: data-remote
+ paginator: the paginator that renders the pagination tags inside
+-%>
+<%= paginator.render do -%>
+
+
+
+<% end -%>
diff --git a/app/views/kaminari/_prev_page.html.erb b/app/views/kaminari/_prev_page.html.erb
new file mode 100644
index 0000000..d272a5a
--- /dev/null
+++ b/app/views/kaminari/_prev_page.html.erb
@@ -0,0 +1,11 @@
+<%# Link to the "Previous" page
+ - available local variables
+ url: url to the previous page
+ current_page: a page object for the currently displayed page
+ total_pages: total number of pages
+ per_page: number of items to fetch per page
+ remote: data-remote
+-%>
+
+ <%= link_to t('views.pagination.previous').html_safe, url, rel: 'prev', remote: remote, class: "page-link" %>
+
diff --git a/app/views/shared/_navbar.html.erb b/app/views/shared/_navbar.html.erb
index 02f3c53..fccb7eb 100644
--- a/app/views/shared/_navbar.html.erb
+++ b/app/views/shared/_navbar.html.erb
@@ -8,10 +8,13 @@
<% if user_signed_in? %>
- <%= link_to("My checks", checks_path, class: "nav-link") %>
+ <%= link_to(t(".my_checks"), checks_path, class: "nav-link") %>
- <%= link_to("Add a check", new_check_path, class: "nav-link") %>
+ <%= link_to(t(".new_domain_check"), new_check_path(kind: :domain), class: "nav-link") %>
+
+
+ <%= link_to(t(".new_ssl_check"), new_check_path(kind: :ssl), class: "nav-link") %>
<% end %>
diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb
index ac033bf..af698fc 100644
--- a/config/initializers/inflections.rb
+++ b/config/initializers/inflections.rb
@@ -11,6 +11,6 @@
# end
# These inflection rules are supported but not enabled by default:
-# ActiveSupport::Inflector.inflections(:en) do |inflect|
-# inflect.acronym 'RESTful'
-# end
+ActiveSupport::Inflector.inflections(:en) do |inflect|
+ inflect.acronym 'SSL'
+end
diff --git a/config/initializers/kaminari_config.rb b/config/initializers/kaminari_config.rb
new file mode 100644
index 0000000..aed7d31
--- /dev/null
+++ b/config/initializers/kaminari_config.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+Kaminari.configure do |config|
+ config.default_per_page = 20
+ config.max_per_page = 200
+ # config.window = 4
+ # config.outer_window = 0
+ # config.left = 0
+ # config.right = 0
+ # config.page_method_name = :page
+ # config.param_name = :page
+ # config.params_on_first_page = false
+end
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 9a34ad9..40adaf0 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -12,6 +12,11 @@ en:
check:
past: "can't be in the future"
+ date:
+ formats:
+ short: "%-d, %b %Y"
+ long: "%A, %B %-d, %Y"
+
devise:
registrations:
new:
@@ -53,6 +58,9 @@ en:
en: English
fr: French
navbar:
+ my_checks: "My checks"
+ new_domain_check: "New domain check"
+ new_ssl_check: "New SSL check"
sign_up: "Sign up"
sign_in: "Sign in"
sign_out: "Sign out"
@@ -60,11 +68,51 @@ en:
checks:
index:
+ title: List of your checks
+ no_matching_check: "No checks match your filters."
no_check_yet_html: |
You have not set up a check yet.
Please add a
domain
or a
ssl !
+
+ new:
+ title: New check
+ domain:
+ title: New domain check
+ ssl:
+ title: New SSL check
+
+ create:
+ saved: "Your check has been saved."
+ invalid: "Please check the form."
+
+ filters:
+ kind_domain: Domain
+ kind_ssl: SSL
+ with_error: With error
+
form:
+ generic:
+ domain: Domain
+ domain:
+ domain: Domain name
+ ssl:
+ domain: Hostname
notifications_hint: |
Receive notifications to warn you when our system detects that the
expiration date is coming. The time is set in number of days.
+
+ table:
+ th:
+ domain: Name
+ expiry_date: "Expiration date"
+ expiry_date_short: "Exp."
+ edit: Edit
+ kind_labels:
+ domain: Domain
+ ssl: SSL
+ never_succeeded: "Chexpire has never been able to perform a check."
+ days_from_last_success:
+ zero: "Last check successful: today"
+ one: "Last check successful: yesterday"
+ other: "Last check successful %{count} days ago"
diff --git a/config/locales/fr.yml b/config/locales/fr.yml
index ed5926f..799126a 100644
--- a/config/locales/fr.yml
+++ b/config/locales/fr.yml
@@ -2,8 +2,15 @@ fr:
activerecord:
attributes:
check:
+ domain: "Domaine"
+ comment: "Commentaire"
+ vendor: "Fournisseur"
+ kind: Type
domain_created_at: "Date de création"
domain_updated_at: "Date de modification"
+ notification:
+ interval: Délai
+ recipient: Destinataire
user:
tos_accepted: "Conditions d'utilisation"
notifications_enabled: "Notifications activées"
@@ -11,6 +18,26 @@ fr:
models:
check:
past: "ne peut être dans le futur"
+ helpers:
+ submit:
+ check:
+ create: "Créer"
+ update: "Valider"
+ page_entries_info:
+ one_page:
+ display_entries:
+ zero: "Pas de %{entry_name} trouvé."
+ one: "Affiche
1 %{entry_name}"
+ other: "Affiche
les %{count} %{entry_name}"
+ more_pages:
+ display_entries: "Affiche %{entry_name}
%{first} - %{last} de
%{total} au total"
+ views:
+ pagination:
+ first: "« Début"
+ last: "Fin »"
+ previous: "‹ Préc"
+ next: "Suiv ›"
+ truncate: "…"
time:
am: am
@@ -20,6 +47,11 @@ fr:
short: "%d %b %H:%M"
pm: pm
+ date:
+ formats:
+ short: "%d/%m/%Y"
+ long: "%A %d %B %Y"
+
devise:
registrations:
new:
@@ -61,6 +93,9 @@ fr:
en: Anglais
fr: Français
navbar:
+ my_checks: "Mes vérifications"
+ new_domain_check: "Nouveau nom de domaine"
+ new_ssl_check: "Nouveau certificat SSL"
sign_up: "Enregistrement"
sign_in: "Connexion"
sign_out: "Déconnexion"
@@ -68,11 +103,51 @@ fr:
checks:
index:
+ title: "Liste de vos vérifications"
+ no_matching_check: "Aucune vérification ne correspond à vos critères."
no_check_yet_html: |
Vous n'avez pas encore créé de vérification.
Vous pouvez en ajouter pour un
domaine
ou un
SSL !
+
+ new:
+ title: Nouvelle vérification
+ domain:
+ title: Nouvelle vérification d'un nom de domaine
+ ssl:
+ title: Nouvelle vérification d'un certificat SSL
+
+ create:
+ saved: La vérification est enregistrée.
+ invalid: Veuillez vérifier le formulaire.
+
+ filters:
+ kind_domain: Domaine
+ kind_ssl: SSL
+ with_error: En erreur
+
form:
+ generic:
+ domain: Domaine
+ domain:
+ domain: Nom de domaine
+ ssl:
+ domain: Nom d'hôte
notifications_hint: |
Recevez des notifications pour vous avertir lorsque notre système détecte
- que la date d'expiration approche. Le délais est indiqué ennombre de jours.
+ que la date d'expiration approche. Le délai est indiqué ennombre de jours.
+
+ table:
+ th:
+ domain: Nom
+ expiry_date: "Date d'expiration"
+ expiry_date_short: "Exp."
+ edit: Modifier
+ kind_labels:
+ domain: Domaine
+ ssl: SSL
+ never_succeeded: "Chexpire n'a jamais pu effectuer de vérification."
+ days_from_last_success:
+ zero: "Dernière vérification réussie : aujourd'hui"
+ one: "Dernière vérification réussie : hier"
+ other: "Dernière vérification réussie il y a %{count} jours"
diff --git a/db/seeds.rb b/db/seeds.rb
index 2bf199b..996d657 100644
--- a/db/seeds.rb
+++ b/db/seeds.rb
@@ -7,9 +7,20 @@ user1 = User.create!(
email: "colin@example.org",
password: "password",
tos_accepted: true,
- confirmed_at: Time.now
+ confirmed_at: Time.now,
+ locale: :fr,
)
+user2 = User.create!(
+ email: "colin+en@example.org",
+ password: "password",
+ tos_accepted: true,
+ confirmed_at: Time.now,
+ locale: :en,
+)
+
+users = [user1, user2]
+
check_chexpire_org = Check.create!(
user: user1,
kind: :domain,
@@ -24,14 +35,14 @@ check_chexpire_org = Check.create!(
check_chexpire_org_error = Check.create!(
user: user1,
kind: :domain,
- domain: "chexpire.org",
+ domain: "chexpire-error.org",
domain_expires_at: 1.week.from_now,
domain_updated_at: 6.months.ago,
domain_created_at: Time.new(2016, 8, 4, 12, 15, 1),
comment: "The date are fake, this is a seed !",
vendor: "Some random registrar",
last_run_at: 20.minutes.ago,
- last_success_at: 4.days.ago,
+ created_at: 3.weeks.ago,
)
ssl_check_chexpire_org = Check.create!(
@@ -48,7 +59,7 @@ ssl_check_chexpire_org = Check.create!(
ssl_check_chexpire_org_error = Check.create!(
user: user1,
kind: :ssl,
- domain: "chexpire.org",
+ domain: "chexpire-error.org",
domain_expires_at: 1.week.from_now,
domain_updated_at: 6.months.ago,
domain_created_at: Time.new(2016, 8, 4, 12, 15, 1),
@@ -59,6 +70,33 @@ ssl_check_chexpire_org_error = Check.create!(
)
+def check_factory(users)
+ ext = %w[com net org fr].sample
+ word = (0...rand(4..12)).map { (97 + rand(26)).chr }.join
+
+ Check.new(
+ user: users.sample,
+ kind: Check.kinds.keys.sample,
+ domain: "#{word}.#{ext}",
+ domain_expires_at: rand(8..300).days.from_now,
+ domain_updated_at: rand(1..300).days.ago,
+ domain_created_at: rand(301..3000).days.ago,
+ )
+end
+
+100.times do |i|
+ check_factory(users).save!
+end
+
+# checks with error
+10.times do |i|
+ check_factory(users).update_attributes(
+ created_at: rand(1..300).days.ago,
+ last_run_at: 4.hours.ago,
+ last_success_at: rand(10...100).days.ago,
+ )
+end
+
Notification.create!(
check: check_chexpire_org,
interval: 15,
diff --git a/package.json b/package.json
index 93b6085..e00de19 100644
--- a/package.json
+++ b/package.json
@@ -7,7 +7,8 @@
"exports-loader": "^0.7.0",
"jquery": "^3.3.1",
"popper.js": "^1.14.3",
- "rails-ujs": "^5.2.0"
+ "rails-ujs": "^5.2.0",
+ "turbolinks": "^5.1.1"
},
"devDependencies": {
"webpack-dev-server": "2.11.2"
diff --git a/test/application_system_test_case.rb b/test/application_system_test_case.rb
index 89fe8b5..e62a52a 100644
--- a/test/application_system_test_case.rb
+++ b/test/application_system_test_case.rb
@@ -4,7 +4,7 @@ class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
driven_by :headless_chrome
def teardown
- Capybara.reset_sessions!
Warden.test_reset!
+ super
end
end
diff --git a/test/controllers/.rubocop.yml b/test/controllers/.rubocop.yml
new file mode 100644
index 0000000..9df3ff0
--- /dev/null
+++ b/test/controllers/.rubocop.yml
@@ -0,0 +1,7 @@
+inherit_from: ../../.rubocop.yml
+
+Metrics/ClassLength:
+ Enabled: false
+
+Metrics/BlockLength:
+ Enabled: false
diff --git a/test/controllers/checks_controller_test.rb b/test/controllers/checks_controller_test.rb
index 77435b7..a430258 100644
--- a/test/controllers/checks_controller_test.rb
+++ b/test/controllers/checks_controller_test.rb
@@ -1,7 +1,150 @@
require "test_helper"
class ChecksControllerTest < ActionDispatch::IntegrationTest
- # test "the truth" do
- # assert true
- # end
+ setup do
+ @user = create(:user)
+ login_as(@user)
+ end
+
+ test "no logged users are redirected to signin form" do
+ logout
+ get new_check_path
+ assert_redirected_to new_user_session_path
+ end
+
+ test "new without kind does not trigger an error" do
+ get new_check_path
+ assert_response :success
+ end
+
+ test "new with kind domain does not trigger an error" do
+ get new_check_path(kind: :domain)
+ assert_response :success
+ end
+
+ test "new with kind ssl does not trigger an error" do
+ get new_check_path(kind: :ssl)
+ assert_response :success
+ end
+
+ test "new with an invalid kind returns an error" do
+ get new_check_path(kind: :invalid)
+ assert_response :not_found
+ end
+
+ test "checks are ordered by default by expiry date sort" do
+ c1 = create(:check, user: @user, domain_expires_at: 20.days.from_now)
+ c2 = create(:check, user: @user, domain_expires_at: 10.days.from_now)
+ c3 = create(:check, user: @user, domain_expires_at: 1.day.from_now)
+
+ get checks_path
+ assert_equal [c3, c2, c1], current_checks
+ end
+
+ test "checks are ordered by expiry date asc" do
+ c1 = create(:check, user: @user, domain_expires_at: 20.days.from_now)
+ c2 = create(:check, user: @user, domain_expires_at: 10.days.from_now)
+ c3 = create(:check, user: @user, domain_expires_at: 1.day.from_now)
+
+ get checks_path(sort: :domain_expires_at_asc)
+ assert_equal [c3, c2, c1], current_checks
+ end
+
+ test "checks are ordered by reverse expiring date" do
+ c1 = create(:check, user: @user, domain_expires_at: 1.day.from_now)
+ c2 = create(:check, user: @user, domain_expires_at: 10.days.from_now)
+ c3 = create(:check, user: @user, domain_expires_at: 20.days.from_now)
+
+ get checks_path(sort: :domain_expires_at_desc)
+ assert_equal [c3, c2, c1], current_checks
+ end
+
+ test "checks are ordered by domain name asc" do
+ c1 = create(:check, user: @user, domain: "a")
+ c2 = create(:check, user: @user, domain: "b")
+ c3 = create(:check, user: @user, domain: "c")
+
+ get checks_path(sort: :domain_asc)
+ assert_equal [c1, c2, c3], current_checks
+ end
+
+ test "checks are ordered by domain name desc" do
+ c1 = create(:check, user: @user, domain: "a")
+ c2 = create(:check, user: @user, domain: "b")
+ c3 = create(:check, user: @user, domain: "c")
+
+ get checks_path(sort: :domain_desc)
+ assert_equal [c3, c2, c1], current_checks
+ end
+
+ test "invalid sort fallback to default sort" do
+ c1 = create(:check, user: @user, domain_expires_at: 20.days.from_now)
+ c2 = create(:check, user: @user, domain_expires_at: 10.days.from_now)
+ c3 = create(:check, user: @user, domain_expires_at: 1.day.from_now)
+
+ get checks_path(sort: :invalid_sort_asc)
+ assert_equal [c3, c2, c1], current_checks
+ end
+
+ test "checks are filtered by domain kind" do
+ c1 = create(:check, :domain, user: @user)
+ c2 = create(:check, :domain, user: @user)
+ create(:check, :ssl, user: @user)
+
+ get checks_path(kind: :domain)
+ assert_equal [c1, c2], current_checks
+ end
+
+ test "checks are filtered by ssl kind" do
+ create(:check, :domain, user: @user)
+ create(:check, :domain, user: @user)
+ c3 = create(:check, :ssl, user: @user)
+
+ get checks_path(kind: :ssl)
+ assert_equal [c3], current_checks
+ end
+
+ test "checks are filtered by domain name" do
+ c1 = create(:check, user: @user, domain: "abc")
+ c2 = create(:check, user: @user, domain: "bcde")
+ create(:check, user: @user, domain: "hijk")
+
+ get checks_path(by_domain: "bc")
+ assert_equal [c1, c2], current_checks
+
+ get checks_path(by_domain: "klm")
+ assert_empty current_checks
+ end
+
+ test "checks in error are filtered" do
+ c1 = create(:check, :last_runs_failed, created_at: 1.week.ago, user: @user)
+ create(:check, user: @user)
+
+ get checks_path(recurrent_failures: true)
+ assert_equal [c1], current_checks
+ end
+
+ test "checks are paginated" do
+ create_list(:check, 40, user: @user)
+
+ get checks_path
+ assert_equal 1, current_checks.current_page
+ first_page = current_checks
+
+ get checks_path(page: 2)
+ assert_equal 2, current_checks.current_page
+ assert_not_equal first_page, current_checks
+ end
+
+ test "checks are scoped to current user" do
+ c1 = create(:check, user: @user)
+ create(:check)
+
+ get checks_path
+ assert_equal [c1], current_checks
+ end
+
+ def current_checks
+ @controller.instance_variable_get("@checks")
+ end
end
diff --git a/test/models/check_test.rb b/test/models/check_test.rb
index 1dde49b..9606150 100644
--- a/test/models/check_test.rb
+++ b/test/models/check_test.rb
@@ -49,4 +49,56 @@ class CheckTest < ActiveSupport::TestCase
assert notification.pending?
assert_nil notification.sent_at
end
+
+ test "in_error? for recently added" do
+ check = build(:check, created_at: 1.day.ago)
+ refute check.in_error?
+
+ check = build(:check, created_at: 1.day.ago, last_run_at: 3.minutes.ago)
+ refute check.in_error?
+
+ check = build(:check, created_at: 1.day.ago, last_success_at: 1.hour.ago)
+ refute check.in_error?
+ end
+
+ test "in_error? for never success check, with at least 1 run" do
+ check = build(:check, created_at: 3.weeks.ago, last_run_at: 1.day.ago)
+ assert check.in_error?
+
+ check = build(:check, created_at: 3.weeks.ago, last_run_at: 4.days.ago)
+ assert check.in_error?
+ end
+
+ test "in_error? ignore check without run" do
+ check = build(:check, created_at: 3.weeks.ago)
+ refute check.in_error?
+ end
+
+ test "in_error? for last success a few days ago" do
+ check = build(:check, created_at: 3.weeks.ago,
+ last_success_at: 10.days.ago, last_run_at: 1.day.ago)
+ assert check.in_error?
+
+ check = build(:check, created_at: 3.weeks.ago,
+ last_success_at: 1.days.ago, last_run_at: 1.day.ago)
+ refute check.in_error?
+ end
+
+ test "days_from_last_success without any success" do
+ check = build(:check)
+ assert_nil check.days_from_last_success
+
+ check = build(:check, last_run_at: 1.day.ago)
+ assert_nil check.days_from_last_success
+ end
+
+ test "days_from_last_success" do
+ check = build(:check, last_success_at: 10.days.ago - 1.hour)
+ assert_equal 10, check.days_from_last_success
+ end
+
+ test "days_from_last_success with a time" do
+ check = build(:check, last_success_at: (10.1 * 24).hours.ago)
+ assert_equal 10, check.days_from_last_success
+ end
end
diff --git a/test/system/.rubocop.yml b/test/system/.rubocop.yml
new file mode 100644
index 0000000..229dd53
--- /dev/null
+++ b/test/system/.rubocop.yml
@@ -0,0 +1,4 @@
+inherit_from: ../../.rubocop.yml
+
+Metrics/ClassLength:
+ Enabled: false
diff --git a/test/system/checks_test.rb b/test/system/checks_test.rb
index 1fefa51..994346c 100644
--- a/test/system/checks_test.rb
+++ b/test/system/checks_test.rb
@@ -4,16 +4,263 @@ class ChecksTest < ApplicationSystemTestCase
setup do
@user = create(:user)
login_as(@user)
-
- @check = create(:check, :with_notifications, user: @user)
end
- test "create a check and a notification" do
+ test "create a check and a notification without kind" do
visit new_check_path
+ choose "domain"
+
+ fill_and_valid_new_check
+ end
+
+ test "create a predefined domain check" do
+ visit new_check_path(kind: :domain)
+
+ refute page.has_css? "domain[kind]"
+
+ fill_and_valid_new_check
+ end
+
+ test "create a predefined ssl check" do
+ visit new_check_path(kind: :ssl)
+
+ refute page.has_css? "domain[kind]"
+
+ fill_and_valid_new_check
+ end
+
+ test "remove a notification" do
+ check = create(:check, :with_notifications, domain: "dom-with-notif.net", user: @user)
+ visit edit_check_path(check)
+ notification = check.notifications.first
+
+ selector = "[data-notification-id=\"#{notification.id}\"]"
+
+ assert_difference "Notification.where(check_id: #{check.id}).count", -1 do
+ within selector do
+ find(".btn-danger").click
+ end
+
+ page.has_no_content?(selector)
+ end
+ end
+
+ test "update a check" do
+ check = create(:check, :with_notifications, domain: "dom-with-notif.net", user: @user)
+ visit edit_check_path(check)
+
+ fill_in "check[comment]", with: "My comment"
+
+ click_button "Update Check"
+
+ assert_equal checks_path, page.current_path
+
+ assert page.has_css?(".alert-success")
+ check.reload
+ assert_equal "My comment", check.comment
+ end
+
+ test "add a notification" do
+ check = create(:check, :with_notifications, domain: "dom-with-notif.net", user: @user)
+ visit edit_check_path(check)
+
+ recipient = "recipient2@example.org"
+ fill_in("check[notifications_attributes][2][recipient]", with: recipient)
+ fill_in("check[notifications_attributes][2][interval]", with: 55)
+
+ assert_difference "Notification.where(check_id: #{check.id}).count", +1 do
+ click_button "Update Check"
+
+ assert_equal checks_path, page.current_path
+ end
+
+ assert page.has_css?(".alert-success")
+
+ notification = Notification.last
+ assert_equal recipient, notification.recipient
+ assert_equal 55, notification.interval
+ assert notification.email?
+ assert notification.pending?
+ end
+
+ test "list my checks" do
+ create(:check, :domain, domain: "dom.com", domain_expires_at: Time.new(2018, 7, 5, 12), user: @user) # rubocop:disable Metrics/LineLength
+ create(:check, :ssl, domain: "ssldom.com", user: @user)
+ create(:check, :ssl, domain: "ssldom2.com", user: @user)
+
+ visit checks_path
+
+ within ".checks-table" do
+ assert page.has_content?("SSL", count: 2)
+ assert page.has_content?("Domain", count: 1)
+ end
+
+ within ".check-row:first-of-type" do
+ assert page.has_content?("Domain")
+ assert page.has_content?("dom.com")
+ assert page.has_content?("Thursday, July 5, 2018")
+ end
+ end
+
+ test "list filterable by domain and ssl" do
+ create_list(:check, 2, :domain, domain: "mydom.fr", user: @user)
+ create_list(:check, 1, :ssl, domain: "ssl.com", user: @user)
+
+ visit checks_path
+
+ assert page.has_css?(".check-row", count: 3)
+
+ within ".checks-filters" do
+ click_on "Domain"
+ assert find_link("Domain").matches_css? ".active"
+ assert find_link("SSL").not_matches_css? ".active"
+ end
+
+ within ".checks-table" do
+ assert page.has_css?(".check-row", count: 2)
+ assert page.has_content?("Domain", count: 2)
+ end
+
+ within ".checks-filters" do
+ click_on "SSL"
+ assert find_link("SSL").matches_css? ".active"
+ assert find_link("Domain").not_matches_css? ".active"
+ end
+
+ within ".checks-table" do
+ assert page.has_css?(".check-row", count: 1)
+ assert page.has_content?("SSL", count: 1)
+ assert page.has_content?("ssl.com")
+ end
+ end
+
+ test "list filterable by check in error" do
+ create(:check, user: @user)
+ create(:check, :last_runs_failed, created_at: 1.week.ago, user: @user)
+
+ visit checks_path
+
+ within ".checks-table" do
+ assert page.has_css?(".check-row", count: 2)
+ assert page.has_css?(".in-error", count: 1)
+ end
+
+ within ".checks-filters" do
+ click_on(I18n.t("checks.filters.with_error"))
+ end
+
+ within ".checks-table" do
+ assert page.has_css?(".check-row", count: 1)
+ assert page.has_css?(".in-error", count: 1)
+ end
+ end
+
+ test "list filterable by name string" do
+ create(:check, user: @user)
+ create(:check, domain: "chexpire.org", user: @user)
+ create(:check, domain: "chexpire.net", user: @user)
+
+ visit checks_path
+
+ within ".checks-filters" do
+ fill_in("by_domain", with: "chex")
+ click_button
+ end
+
+ within ".checks-table" do
+ assert page.has_css?(".check-row", count: 2)
+ assert page.has_content?("chexpire.", count: 2)
+ end
+ end
+
+ test "list is paginated" do
+ create(:check, user: @user)
+
+ visit checks_path
+ assert page.has_no_css?("ul.pagination")
+
+ create_list(:check, 50, user: @user)
+
+ visit checks_path
+ assert page.has_css?("ul.pagination")
+ end
+
+ test "list is sortable by name" do
+ visit checks_path
+
+ create(:check, domain: "a.org", user: @user)
+ create(:check, domain: "b.org", user: @user)
+
+ visit checks_path
+
+ within ".checks-table thead th:nth-of-type(2)" do
+ find(".sort-links:first-child").click
+ end
+
+ within ".check-row:first-of-type" do
+ page.has_content? "a.org"
+ end
+
+ within ".checks-table thead th:nth-of-type(2)" do
+ find(".sort-links:last-child").click
+ end
+
+ within ".check-row:first-of-type" do
+ page.has_content? "b.org"
+ end
+ end
+
+ test "list is sorted by expiration date by default" do
+ visit checks_path
+
+ create(:check, domain_expires_at: Time.new(2018, 7, 6, 12), user: @user)
+ create(:check, domain_expires_at: Time.new(2018, 7, 5, 12), user: @user)
+
+ visit checks_path
+
+ within ".check-row:first-of-type" do
+ page.has_content? "Thursday, July 5, 2018"
+ end
+ end
+
+ test "list is sortable by expiration date" do
+ visit checks_path
+
+ create(:check, domain_expires_at: Time.new(2018, 7, 5, 12), user: @user)
+ create(:check, domain_expires_at: Time.new(2018, 7, 6, 12), user: @user)
+
+ visit checks_path
+
+ within ".check-row:first-of-type" do
+ page.has_content? "Thursday, July 5, 2018"
+ end
+
+ # only a desc link because of default sort
+ within ".checks-table thead th:nth-of-type(3)" do
+ find(".sort-links a").click
+ end
+
+ within ".check-row:first-of-type" do
+ page.has_content? "Friday, July 6, 2018"
+ end
+
+ within ".checks-table thead th:nth-of-type(3)" do
+ find(".sort-links a").click
+ end
+
+ within ".check-row:first-of-type" do
+ page.has_content? "Thursday, July 5, 2018"
+ end
+ end
+
+ private
+
+ # rubocop:disable Metrics/AbcSize
+ # rubocop:disable Metrics/MethodLength
+ def fill_and_valid_new_check
domain = "domain-test.fr"
fill_in("check[domain]", with: domain)
- choose "domain"
recipient = "recipient@example.org"
fill_in("check[notifications_attributes][0][recipient]", with: recipient)
@@ -32,55 +279,6 @@ class ChecksTest < ApplicationSystemTestCase
assert notification.email?
assert notification.pending?
end
-
- test "remove a notification" do
- visit edit_check_path(@check)
- notification = @check.notifications.first
-
- selector = "[data-notification-id=\"#{notification.id}\"]"
-
- assert_difference "Notification.where(check_id: #{@check.id}).count", -1 do
- within selector do
- find(".btn-danger").click
- end
-
- page.has_no_content?(selector)
- end
- end
-
- test "update a check" do
- visit edit_check_path(@check)
-
- fill_in "check[comment]", with: "My comment"
-
- click_button "Update Check"
-
- assert_equal checks_path, page.current_path
-
- assert page.has_css?(".alert-success")
- @check.reload
- assert_equal "My comment", @check.comment
- end
-
- test "add a notification" do
- visit edit_check_path(@check)
-
- recipient = "recipient2@example.org"
- fill_in("check[notifications_attributes][2][recipient]", with: recipient)
- fill_in("check[notifications_attributes][2][interval]", with: 55)
-
- assert_difference "Notification.where(check_id: #{@check.id}).count", +1 do
- click_button "Update Check"
-
- assert_equal checks_path, page.current_path
- end
-
- assert page.has_css?(".alert-success")
-
- notification = Notification.last
- assert_equal recipient, notification.recipient
- assert_equal 55, notification.interval
- assert notification.email?
- assert notification.pending?
- end
+ # rubocop:enable Metrics/AbcSize
+ # rubocop:enable Metrics/MethodLength
end
diff --git a/test/test_helper.rb b/test/test_helper.rb
index 91ae325..afc4077 100644
--- a/test/test_helper.rb
+++ b/test/test_helper.rb
@@ -42,6 +42,7 @@ Capybara.register_driver :headless_chrome do |app|
end
Capybara.save_path = Rails.root.join("tmp/capybara")
Capybara.javascript_driver = :headless_chrome
+Capybara.default_driver = :headless_chrome
# Disable Open4 real system calls
require "open4"
diff --git a/yarn.lock b/yarn.lock
index 83f3e0f..010038d 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5598,6 +5598,10 @@ tunnel-agent@~0.4.1:
version "0.4.3"
resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.4.3.tgz#6373db76909fe570e08d73583365ed828a74eeeb"
+turbolinks@^5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/turbolinks/-/turbolinks-5.1.1.tgz#3d418a2d8172edbde5e787bf74cb7bef151ae43f"
+
tweetnacl@^0.14.3, tweetnacl@~0.14.0:
version "0.14.5"
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"