From 3bfca3b81fe198fa522be08bedc56348ca9c800f Mon Sep 17 00:00:00 2001 From: Colin Darie Date: Wed, 4 Jul 2018 19:05:52 +0200 Subject: [PATCH] Display an icon for check in error --- app/frontend/packs/application.js | 5 +++ app/frontend/scss/components/checks.scss | 4 ++ app/helpers/checks_helper.rb | 6 +++ app/models/check.rb | 21 ++++++++- app/views/checks/_table.html.erb | 13 +++++- config/locales/en.yml | 5 +++ config/locales/fr.yml | 5 +++ db/seeds.rb | 23 ++++++++-- test/controllers/checks_controller_test.rb | 2 +- test/models/check_test.rb | 52 ++++++++++++++++++++++ 10 files changed, 128 insertions(+), 8 deletions(-) diff --git a/app/frontend/packs/application.js b/app/frontend/packs/application.js index 4ae8b7a..d2d55db 100644 --- a/app/frontend/packs/application.js +++ b/app/frontend/packs/application.js @@ -13,8 +13,13 @@ import Turbolinks from 'turbolinks'; import 'bootstrap/js/dist/collapse'; import 'bootstrap/js/dist/dropdown'; import 'bootstrap/js/dist/button'; +import 'bootstrap/js/dist/tooltip'; import '../scss'; Rails.start() Turbolinks.start() + +document.addEventListener("turbolinks:load", () => { + $('[data-toggle="tooltip"]').tooltip(); +}); diff --git a/app/frontend/scss/components/checks.scss b/app/frontend/scss/components/checks.scss index 26f3f5d..6c24b24 100644 --- a/app/frontend/scss/components/checks.scss +++ b/app/frontend/scss/components/checks.scss @@ -2,4 +2,8 @@ .action a { color: black; } + + .kind .octicon { + vertical-align: middle; + } } diff --git a/app/helpers/checks_helper.rb b/app/helpers/checks_helper.rb index 654671d..5976d8e 100644 --- a/app/helpers/checks_helper.rb +++ b/app/helpers/checks_helper.rb @@ -49,4 +49,10 @@ module ChecksHelper "btn-outline-info" end end + + def check_last_success_title(check) + return t(".never_succeeded") if check.last_success_at.nil? + + t(".days_from_last_success", count: check.days_from_last_success) + end end diff --git a/app/models/check.rb b/app/models/check.rb index 5074339..958f5ca 100644 --- a/app/models/check.rb +++ b/app/models/check.rb @@ -27,6 +27,8 @@ # class Check < ApplicationRecord + ERROR_DELAY_DAYS = 3 + belongs_to :user has_many :logs, class_name: "CheckLog" has_many :notifications, validate: true, dependent: :destroy @@ -61,14 +63,29 @@ class Check < ApplicationRecord scope :kind, ->(kind) { where(kind: kind) } scope :by_domain, ->(domain) { where("domain LIKE ?", "%#{domain}%") } scope :recurrent_failures, -> { - where("last_run_at IS NOT NULL") - .where("last_success_at IS NULL OR last_success_at <= DATE_SUB(last_run_at, INTERVAL 3 DAY)") + interval = "INTERVAL #{ERROR_DELAY_DAYS} DAY" + where("last_run_at IS NOT NULL AND created_at <= DATE_SUB(NOW(), #{interval})") + .where("last_success_at IS NULL OR last_success_at <= DATE_SUB(last_run_at, #{interval})") } def self.default_sort { domain_expires_at: :asc } end + def in_error? + return false if created_at > ERROR_DELAY_DAYS.days.ago + return false if last_run_at.nil? + return true if last_success_at.nil? + + last_success_at < ERROR_DELAY_DAYS.days.ago + end + + def days_from_last_success + return unless last_success_at.present? + + (Date.today - last_success_at.to_date).to_i + end + private def domain_created_at_past diff --git a/app/views/checks/_table.html.erb b/app/views/checks/_table.html.erb index 074cd57..e164399 100644 --- a/app/views/checks/_table.html.erb +++ b/app/views/checks/_table.html.erb @@ -21,8 +21,19 @@ <% checks.each do |check| %> - + <%= t(".kind_labels.#{check.kind}") %> + <%- if check.in_error? %> + <%== content_tag( + :span, + Octicons::Octicon.new("alert", class: "ml-1").to_svg.html_safe, + class: "text-danger", + data: { + toggle: "tooltip", + placement: "right", + title: check_last_success_title(check) + }) %> + <% end %> <%= check.domain %> diff --git a/config/locales/en.yml b/config/locales/en.yml index a17b4ec..bd4ab70 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -109,3 +109,8 @@ en: 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 aa2c3b7..5c76b55 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -144,3 +144,8 @@ fr: 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 e81814b..996d657 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -19,6 +19,8 @@ user2 = User.create!( locale: :en, ) +users = [user1, user2] + check_chexpire_org = Check.create!( user: user1, kind: :domain, @@ -40,7 +42,7 @@ check_chexpire_org_error = Check.create!( 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!( @@ -68,12 +70,12 @@ ssl_check_chexpire_org_error = Check.create!( ) -100.times do |i| +def check_factory(users) ext = %w[com net org fr].sample word = (0...rand(4..12)).map { (97 + rand(26)).chr }.join - Check.create!( - user: [user1, user2].sample, + Check.new( + user: users.sample, kind: Check.kinds.keys.sample, domain: "#{word}.#{ext}", domain_expires_at: rand(8..300).days.from_now, @@ -82,6 +84,19 @@ ssl_check_chexpire_org_error = Check.create!( ) 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/test/controllers/checks_controller_test.rb b/test/controllers/checks_controller_test.rb index 92e22d9..a430258 100644 --- a/test/controllers/checks_controller_test.rb +++ b/test/controllers/checks_controller_test.rb @@ -117,7 +117,7 @@ class ChecksControllerTest < ActionDispatch::IntegrationTest end test "checks in error are filtered" do - c1 = create(:check, :last_runs_failed, user: @user) + c1 = create(:check, :last_runs_failed, created_at: 1.week.ago, user: @user) create(:check, user: @user) get checks_path(recurrent_failures: true) 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