diff --git a/lib/coverband.rb b/lib/coverband.rb
index ab8ccca8..7c357e83 100644
--- a/lib/coverband.rb
+++ b/lib/coverband.rb
@@ -16,6 +16,7 @@
require "coverband/adapters/null_store"
require "coverband/utils/file_hasher"
require "coverband/collectors/coverage"
+require "coverband/collectors/abstract_tracker"
require "coverband/collectors/view_tracker"
require "coverband/collectors/view_tracker_service"
require "coverband/collectors/route_tracker"
diff --git a/lib/coverband/at_exit.rb b/lib/coverband/at_exit.rb
index 837de5c0..0464572a 100644
--- a/lib/coverband/at_exit.rb
+++ b/lib/coverband/at_exit.rb
@@ -22,7 +22,8 @@ def self.register
Coverband.report_coverage
# to ensure we track mailer views we now need to report views tracking
# at exit as well for rake tasks and background tasks that can trigger email
- Coverband.configuration.view_tracker&.report_views_tracked
+ Coverband.configuration.view_tracker&.save_report
+ Coverband.configuration.translations_tracker&.save_report
end
end
end
diff --git a/lib/coverband/collectors/abstract_tracker.rb b/lib/coverband/collectors/abstract_tracker.rb
new file mode 100644
index 00000000..1dcd562a
--- /dev/null
+++ b/lib/coverband/collectors/abstract_tracker.rb
@@ -0,0 +1,164 @@
+# frozen_string_literal: true
+
+require "set"
+require "singleton"
+
+module Coverband
+ module Collectors
+ ###
+ # This abstract class makes it easy to track any used/unused with timestamp set of usage
+ ###
+ class AbstractTracker
+ REPORT_ROUTE = "/"
+ TITLE = "abstract"
+
+ attr_accessor :target
+ attr_reader :logger, :store, :ignore_patterns
+
+ def initialize(options = {})
+ raise NotImplementedError, "#{self.class.name} requires a newer version of Rails" unless self.class.supported_version?
+ raise "Coverband: #{self.class.name} initialized before configuration!" if !Coverband.configured? && ENV["COVERBAND_TEST"] == "test"
+
+ @ignore_patterns = Coverband.configuration.ignore
+ @store = options.fetch(:store) { Coverband.configuration.store }
+ @logger = options.fetch(:logger) { Coverband.configuration.logger }
+ @target = options.fetch(:target) do
+ concrete_target
+ end
+
+ @one_time_timestamp = false
+
+ @logged_keys = Set.new
+ @keys_to_record = Set.new
+ end
+
+ def logged_keys
+ @logged_keys.to_a
+ end
+
+ def keys_to_record
+ @keys_to_record.to_a
+ end
+
+ ###
+ # This method is called on every translation usage
+ ###
+ def track_key(key)
+ if key
+ if newly_seen_key?(key)
+ @logged_keys << key
+ @keys_to_record << key if track_key?(key)
+ end
+ end
+ end
+
+ def used_keys
+ redis_store.hgetall(tracker_key)
+ end
+
+ def all_keys
+ target.uniq
+ end
+
+ def unused_keys(used_keys = nil)
+ recently_used_keys = (used_keys || self.used_keys).keys
+ all_keys.reject { |k| recently_used_keys.include?(k.to_s) }
+ end
+
+ def as_json
+ used_keys = self.used_keys
+ {
+ unused_keys: unused_keys(used_keys),
+ used_keys: used_keys
+ }.to_json
+ end
+
+ def tracking_since
+ if (tracking_time = redis_store.get(tracker_time_key))
+ Time.at(tracking_time.to_i).iso8601
+ else
+ "N/A"
+ end
+ end
+
+ def reset_recordings
+ redis_store.del(tracker_key)
+ redis_store.del(tracker_time_key)
+ end
+
+ def clear_key!(key)
+ return unless key
+ puts "#{tracker_key} key #{key}"
+ redis_store.hdel(tracker_key, key)
+ @logged_keys.delete(key)
+ end
+
+ def save_report
+ redis_store.set(tracker_time_key, Time.now.to_i) unless @one_time_timestamp || tracker_time_key_exists?
+ @one_time_timestamp = true
+ reported_time = Time.now.to_i
+ @keys_to_record.to_a.each do |key|
+ redis_store.hset(tracker_key, key.to_s, reported_time)
+ end
+ @keys_to_record.clear
+ rescue => e
+ # we don't want to raise errors if Coverband can't reach redis.
+ # This is a nice to have not a bring the system down
+ logger&.error "Coverband: #{self.class.name} failed to store, error #{e.class.name} info #{e.message}"
+ end
+
+ # This is the basic rails version supported, if there is something more unique over ride in subclass
+ def self.supported_version?
+ defined?(Rails) && defined?(Rails::VERSION) && Rails::VERSION::STRING.split(".").first.to_i >= 5
+ end
+
+ def route
+ self.class::REPORT_ROUTE
+ end
+
+ def title
+ self.class::TITLE
+ end
+
+ protected
+
+ def newly_seen_key?(key)
+ !@logged_keys.include?(key)
+ end
+
+ def track_key?(key, options = {})
+ @ignore_patterns.none? { |pattern| key.to_s.include?(pattern) }
+ end
+
+ private
+
+ def concrete_target
+ raise "subclass must implement"
+ end
+
+ def redis_store
+ store.raw_store
+ end
+
+ def tracker_time_key_exists?
+ if defined?(redis_store.exists?)
+ redis_store.exists?(tracker_time_key)
+ else
+ redis_store.exists(tracker_time_key)
+ end
+ end
+
+ def tracker_key
+ "#{class_key}_tracker"
+ end
+
+ def tracker_time_key
+ "#{class_key}_tracker_time"
+ end
+
+ def class_key
+ @class_key ||= self.class.name.split("::").last
+ end
+ end
+ end
+end
diff --git a/lib/coverband/collectors/route_tracker.rb b/lib/coverband/collectors/route_tracker.rb
index eb77a4d1..e70d409c 100644
--- a/lib/coverband/collectors/route_tracker.rb
+++ b/lib/coverband/collectors/route_tracker.rb
@@ -8,51 +8,23 @@ module Collectors
###
# This class tracks route usage via ActiveSupport::Notifications
###
- class RouteTracker
- attr_accessor :target
- attr_reader :logger, :store, :ignore_patterns
+ class RouteTracker < AbstractTracker
+ REPORT_ROUTE = "routes_tracker"
+ TITLE = "Routes"
def initialize(options = {})
- raise NotImplementedError, "Route Tracker requires Rails 4 or greater" unless self.class.supported_version?
- raise "Coverband: route tracker initialized before configuration!" if !Coverband.configured? && ENV["COVERBAND_TEST"] == "test"
-
- @ignore_patterns = Coverband.configuration.ignore
- @store = options.fetch(:store) { Coverband.configuration.store }
- @logger = options.fetch(:logger) { Coverband.configuration.logger }
- @target = options.fetch(:target) do
- if defined?(Rails.application)
- Rails.application.routes.routes.map do |route|
- {
- controller: route.defaults[:controller],
- action: route.defaults[:action],
- url_path: route.path.spec.to_s.gsub("(.:format)", ""),
- verb: route.verb
- }
- end
- else
- []
- end
+ if Rails&.respond_to?(:version) && Gem::Version.new(Rails.version) >= Gem::Version.new("6.0.0") && Gem::Version.new(Rails.version) < Gem::Version.new("7.1.0")
+ require_relative "../utils/rails6_ext"
end
- @one_time_timestamp = false
-
- @logged_routes = Set.new
- @routes_to_record = Set.new
- end
-
- def logged_routes
- @logged_routes.to_a
- end
-
- def routes_to_record
- @routes_to_record.to_a
+ super
end
###
# This method is called on every routing call, so we try to reduce method calls
# and ensure high performance
###
- def track_routes(_name, _start, _finish, _id, payload)
+ def track_key(payload)
route = if payload[:request]
{
controller: nil,
@@ -69,104 +41,53 @@ def track_routes(_name, _start, _finish, _id, payload)
}
end
if route
- if newly_seen_route?(route)
- @logged_routes << route
- @routes_to_record << route if track_route?(route)
+ if newly_seen_key?(route)
+ @logged_keys << route
+ @keys_to_record << route if track_key?(route)
end
end
end
- def used_routes
- redis_store.hgetall(tracker_key)
- end
-
- def all_routes
- target.uniq
+ def self.supported_version?
+ defined?(Rails) && defined?(Rails::VERSION) && Rails::VERSION::STRING.split(".").first.to_i >= 6
end
- def unused_routes(used_routes = nil)
- recently_used_routes = (used_routes || self.used_routes).keys
+ def unused_keys(used_keys = nil)
+ recently_used_routes = (used_keys || self.used_keys).keys
# NOTE: we match with or without path to handle paths with named params like `/user/:user_id` to used routes filling with all the variable named paths
- all_routes.reject { |r| recently_used_routes.include?(r.to_s) || recently_used_routes.include?(r.merge(url_path: nil).to_s) }
- end
-
- def as_json
- used_routes = self.used_routes
- {
- unused_routes: unused_routes(used_routes),
- used_routes: used_routes
- }.to_json
+ all_keys.reject { |r| recently_used_routes.include?(r.to_s) || recently_used_routes.include?(r.merge(url_path: nil).to_s) }
end
- def tracking_since
- if (tracking_time = redis_store.get(tracker_time_key))
- Time.at(tracking_time.to_i).iso8601
- else
- "N/A"
+ def railtie!
+ ActiveSupport::Notifications.subscribe("start_processing.action_controller") do |name, start, finish, id, payload|
+ Coverband.configuration.route_tracker.track_key(payload)
end
- end
-
- def reset_recordings
- redis_store.del(tracker_key)
- redis_store.del(tracker_time_key)
- end
-
- def clear_route!(route)
- return unless route
- redis_store.hdel(tracker_key, route)
- @logged_routes.delete(route)
- end
-
- def report_routes_tracked
- redis_store.set(tracker_time_key, Time.now.to_i) unless @one_time_timestamp || tracker_time_key_exists?
- @one_time_timestamp = true
- reported_time = Time.now.to_i
- @routes_to_record.to_a.each do |route|
- redis_store.hset(tracker_key, route.to_s, reported_time)
+ # NOTE: This event was instrumented in Aug 10th 2022, but didn't make the 7.0.4 release and should be in the next release
+ # https://github.com/rails/rails/pull/43755
+ # Automatic tracking of redirects isn't avaible before Rails 7.1.0 (currently tested against the 7.1.0.alpha)
+ # We could consider back porting or patching a solution that works on previous Rails versions
+ ActiveSupport::Notifications.subscribe("redirect.action_dispatch") do |name, start, finish, id, payload|
+ Coverband.configuration.route_tracker.track_key(payload)
end
- @routes_to_record.clear
- rescue => e
- # we don't want to raise errors if Coverband can't reach redis.
- # This is a nice to have not a bring the system down
- logger&.error "Coverband: route_tracker failed to store, error #{e.class.name} info #{e.message}"
- end
-
- def self.supported_version?
- defined?(Rails) && defined?(Rails::VERSION) && Rails::VERSION::STRING.split(".").first.to_i >= 4
- end
-
- protected
-
- def newly_seen_route?(route)
- !@logged_routes.include?(route)
- end
-
- def track_route?(route, options = {})
- @ignore_patterns.none? { |pattern| route.to_s.include?(pattern) }
end
private
- def redis_store
- store.raw_store
- end
-
- def tracker_time_key_exists?
- if defined?(redis_store.exists?)
- redis_store.exists?(tracker_time_key)
+ def concrete_target
+ if defined?(Rails.application)
+ Rails.application.routes.routes.map do |route|
+ {
+ controller: route.defaults[:controller],
+ action: route.defaults[:action],
+ url_path: route.path.spec.to_s.gsub("(.:format)", ""),
+ verb: route.verb
+ }
+ end
else
- redis_store.exists(tracker_time_key)
+ []
end
end
-
- def tracker_key
- "route_tracker_2"
- end
-
- def tracker_time_key
- "route_tracker_time"
- end
end
end
end
diff --git a/lib/coverband/collectors/translation_tracker.rb b/lib/coverband/collectors/translation_tracker.rb
index b6e29b9e..6c4050b2 100644
--- a/lib/coverband/collectors/translation_tracker.rb
+++ b/lib/coverband/collectors/translation_tracker.rb
@@ -20,129 +20,30 @@ def lookup(locale, key, scope = [], options = {})
###
# This class tracks translation usage via I18n::Backend
###
- class TranslationTracker
- attr_accessor :target
- attr_reader :logger, :store, :ignore_patterns
+ class TranslationTracker < AbstractTracker
+ REPORT_ROUTE = "translations_tracker"
+ TITLE = "Translations"
- def initialize(options = {})
- raise NotImplementedError, "#{self.class.name} requires Rails 4 or greater" unless self.class.supported_version?
- raise "Coverband: #{self.class.name} initialized before configuration!" if !Coverband.configured? && ENV["COVERBAND_TEST"] == "test"
-
- @ignore_patterns = Coverband.configuration.ignore
- @store = options.fetch(:store) { Coverband.configuration.store }
- @logger = options.fetch(:logger) { Coverband.configuration.logger }
- @target = options.fetch(:target) do
- if defined?(Rails.application)
- # I18n.eager_load!
- # I18n.backend.send(:translations)
- app_translation_keys = []
- app_translation_files = ::I18n.load_path.select { |f| f.match(/config\/locales/) }
- app_translation_files.each do |file|
- app_translation_keys += flatten_hash(YAML.load_file(file)).keys
- end
- app_translation_keys.uniq
- else
- []
- end
- end
-
- @one_time_timestamp = false
-
- @logged_keys = Set.new
- @keys_to_record = Set.new
+ def railtie!
+ # plugin to i18n
+ ::I18n::Backend::Simple.send :include, ::Coverband::Collectors::I18n::KeyRegistry
end
- def logged_keys
- @logged_keys.to_a
- end
-
- def keys_to_record
- @keys_to_record.to_a
- end
+ private
- ###
- # This method is called on every translation usage
- ###
- def track_key(key)
- if key
- if newly_seen_key?(key)
- @logged_keys << key
- @keys_to_record << key if track_key?(key)
+ def concrete_target
+ if defined?(Rails.application)
+ app_translation_keys = []
+ app_translation_files = ::I18n.load_path.select { |f| f.match(/config\/locales/) }
+ app_translation_files.each do |file|
+ app_translation_keys += flatten_hash(YAML.load_file(file)).keys
end
- end
- end
-
- def used_keys
- redis_store.hgetall(tracker_key)
- end
-
- def all_keys
- target.uniq
- end
-
- def unused_keys(used_keys = nil)
- recently_used_keys = (used_keys || self.used_keys).keys
- all_keys.reject { |k| recently_used_keys.include?(k.to_s) }
- end
-
- def as_json
- used_keys = self.used_keys
- {
- unused_keys: unused_keys(used_keys),
- used_keys: used_keys
- }.to_json
- end
-
- def tracking_since
- if (tracking_time = redis_store.get(tracker_time_key))
- Time.at(tracking_time.to_i).iso8601
+ app_translation_keys.uniq
else
- "N/A"
+ []
end
end
- def reset_recordings
- redis_store.del(tracker_key)
- redis_store.del(tracker_time_key)
- end
-
- def clear_key!(key)
- return unless key
-
- redis_store.hdel(tracker_key, key)
- @logged_keys.delete(key)
- end
-
- def save_report
- redis_store.set(tracker_time_key, Time.now.to_i) unless @one_time_timestamp || tracker_time_key_exists?
- @one_time_timestamp = true
- reported_time = Time.now.to_i
- @keys_to_record.to_a.each do |key|
- redis_store.hset(tracker_key, key.to_s, reported_time)
- end
- @keys_to_record.clear
- rescue => e
- # we don't want to raise errors if Coverband can't reach redis.
- # This is a nice to have not a bring the system down
- logger&.error "Coverband: #{self.class.name} failed to store, error #{e.class.name} info #{e.message}"
- end
-
- def self.supported_version?
- defined?(Rails) && defined?(Rails::VERSION) && Rails::VERSION::STRING.split(".").first.to_i >= 4
- end
-
- protected
-
- def newly_seen_key?(key)
- !@logged_keys.include?(key)
- end
-
- def track_key?(key, options = {})
- @ignore_patterns.none? { |pattern| key.to_s.include?(pattern) }
- end
-
- private
-
def flatten_hash(hash)
hash.each_with_object({}) do |(k, v), h|
if v.is_a? Hash
@@ -154,30 +55,6 @@ def flatten_hash(hash)
end
end
end
-
- def redis_store
- store.raw_store
- end
-
- def tracker_time_key_exists?
- if defined?(redis_store.exists?)
- redis_store.exists?(tracker_time_key)
- else
- redis_store.exists(tracker_time_key)
- end
- end
-
- def tracker_key
- "#{class_key}_tracker"
- end
-
- def tracker_time_key
- "#{class_key}_tracker_time"
- end
-
- def class_key
- @class_key ||= self.class.name.split("::").last
- end
end
end
end
diff --git a/lib/coverband/collectors/view_tracker.rb b/lib/coverband/collectors/view_tracker.rb
index 61775c2a..09979af8 100644
--- a/lib/coverband/collectors/view_tracker.rb
+++ b/lib/coverband/collectors/view_tracker.rb
@@ -12,45 +12,35 @@ module Collectors
# but am now rolling into Coverband
# https://github.com/livingsocial/flatfoot
###
- class ViewTracker
- attr_accessor :target
- attr_reader :logger, :roots, :store, :ignore_patterns
+ class ViewTracker < AbstractTracker
+ attr_reader :roots
- def initialize(options = {})
- raise NotImplementedError, "View Tracker requires Rails 4 or greater" unless self.class.supported_version?
- raise "Coverband: view tracker initialized before configuration!" if !Coverband.configured? && ENV["COVERBAND_TEST"] == "test"
+ REPORT_ROUTE = "views_tracker"
+ TITLE = "Views"
+ def initialize(options = {})
@project_directory = File.expand_path(Coverband.configuration.root)
- @ignore_patterns = Coverband.configuration.ignore
- @store = options.fetch(:store) { Coverband.configuration.store }
- @logger = options.fetch(:logger) { Coverband.configuration.logger }
- @target = options.fetch(:target) { Dir.glob("#{@project_directory}/app/views/**/*.html.{erb,haml,slim}") }
-
@roots = options.fetch(:roots) { Coverband.configuration.all_root_patterns }
@roots = @roots.split(",") if @roots.is_a?(String)
- @one_time_timestamp = false
-
- @logged_views = Set.new
- @views_to_record = Set.new
- end
- def logged_views
- @logged_views.to_a
+ super
end
- def views_to_record
- @views_to_record.to_a
+ def railtie!
+ ActiveSupport::Notifications.subscribe(/render_(template|partial|collection).action_view/) do |name, start, finish, id, payload|
+ Coverband.configuration.view_tracker.track_key(payload) unless name.include?("!")
+ end
end
###
# This method is called on every render call, so we try to reduce method calls
# and ensure high performance
###
- def track_views(_name, _start, _finish, _id, payload)
+ def track_key(payload)
if (file = payload[:identifier])
- if newly_seen_file?(file)
- @logged_views << file
- @views_to_record << file if track_file?(file)
+ if newly_seen_key?(file)
+ @logged_keys << file
+ @keys_to_record << file if track_file?(file)
end
end
@@ -61,13 +51,13 @@ def track_views(_name, _start, _finish, _id, payload)
# http://edgeguides.rubyonrails.org/active_support_instrumentation.html#render_partial-action_view
###
return unless (layout_file = payload[:layout])
- return unless newly_seen_file?(layout_file)
+ return unless newly_seen_key?(layout_file)
- @logged_views << layout_file
- @views_to_record << layout_file if track_file?(layout_file, layout: true)
+ @logged_keys << layout_file
+ @keys_to_record << layout_file if track_file?(layout_file, layout: true)
end
- def used_views
+ def used_keys
views = redis_store.hgetall(tracker_key)
normalized_views = {}
views.each_pair do |view, time|
@@ -79,7 +69,7 @@ def used_views
normalized_views
end
- def all_views
+ def all_keys
all_views = []
target.each do |view|
roots.each do |root|
@@ -90,92 +80,35 @@ def all_views
all_views.uniq
end
- def unused_views(used_views = nil)
- recently_used_views = (used_views || self.used_views).keys
- unused_views = all_views - recently_used_views
+ def unused_keys(used_views = nil)
+ recently_used_views = (used_keys || used_keys).keys
+ unused_views = all_keys - recently_used_views
# since layouts don't include format we count them used if they match with ANY formats
unused_views.reject { |view| view.match(/\/layouts\//) && recently_used_views.any? { |used_view| view.include?(used_view) } }
end
- def as_json
- used_views = self.used_views
- {
- unused_views: unused_views(used_views),
- used_views: used_views
- }.to_json
- end
-
- def tracking_since
- if (tracking_time = redis_store.get(tracker_time_key))
- Time.at(tracking_time.to_i).iso8601
- else
- "N/A"
- end
- end
-
- def reset_recordings
- redis_store.del(tracker_key)
- redis_store.del(tracker_time_key)
- end
-
- def clear_file!(filename)
+ def clear_key!(filename)
return unless filename
filename = "#{@project_directory}/#{filename}"
redis_store.hdel(tracker_key, filename)
- @logged_views.delete(filename)
- end
-
- def report_views_tracked
- redis_store.set(tracker_time_key, Time.now.to_i) unless @one_time_timestamp || tracker_time_key_exists?
- @one_time_timestamp = true
- reported_time = Time.now.to_i
- @views_to_record.to_a.each do |file|
- redis_store.hset(tracker_key, file, reported_time)
- end
- @views_to_record.clear
- rescue => e
- # we don't want to raise errors if Coverband can't reach redis.
- # This is a nice to have not a bring the system down
- logger&.error "Coverband: view_tracker failed to store, error #{e.class.name}"
- end
-
- def self.supported_version?
- defined?(Rails) && defined?(Rails::VERSION) && Rails::VERSION::STRING.split(".").first.to_i >= 4
+ @logged_keys.delete(filename)
end
- protected
-
- def newly_seen_file?(file)
- !@logged_views.include?(file)
- end
+ private
def track_file?(file, options = {})
(file.start_with?(@project_directory) || options[:layout]) &&
@ignore_patterns.none? { |pattern| file.include?(pattern) }
end
- private
-
- def redis_store
- store.raw_store
- end
-
- def tracker_time_key_exists?
- if defined?(redis_store.exists?)
- redis_store.exists?(tracker_time_key)
+ def concrete_target
+ if defined?(Rails.application)
+ Dir.glob("#{@project_directory}/app/views/**/*.html.{erb,haml,slim}")
else
- redis_store.exists(tracker_time_key)
+ []
end
end
-
- def tracker_key
- "render_tracker_2"
- end
-
- def tracker_time_key
- "render_tracker_time"
- end
end
end
end
diff --git a/lib/coverband/collectors/view_tracker_service.rb b/lib/coverband/collectors/view_tracker_service.rb
index aafdfdb0..1e3996cf 100644
--- a/lib/coverband/collectors/view_tracker_service.rb
+++ b/lib/coverband/collectors/view_tracker_service.rb
@@ -6,7 +6,7 @@ module Collectors
# This class extends view tracker to support web service reporting
###
class ViewTrackerService < ViewTracker
- def report_views_tracked
+ def save_report
reported_time = Time.now.to_i
if @views_to_record.any?
relative_views = @views_to_record.map! do |view|
diff --git a/lib/coverband/configuration.rb b/lib/coverband/configuration.rb
index 33e9eaaf..76276a4a 100644
--- a/lib/coverband/configuration.rb
+++ b/lib/coverband/configuration.rb
@@ -10,7 +10,8 @@ class Configuration
:simulate_oneshot_lines_coverage,
:view_tracker, :defer_eager_loading_data,
:track_routes, :route_tracker,
- :track_translations, :translations_tracker
+ :track_translations, :translations_tracker,
+ :trackers
attr_writer :logger, :s3_region, :s3_bucket, :s3_access_key_id,
:s3_secret_access_key, :password, :api_key, :service_url, :coverband_timeout, :service_dev_mode,
:service_test_mode, :process_type, :track_views, :redis_url,
@@ -95,6 +96,8 @@ def reset
@redis_ttl = 2_592_000 # in seconds. Default is 30 days.
@reporting_wiggle = nil
+ @trackers = []
+
# TODO: these are deprecated
@s3_region = nil
@s3_bucket = nil
@@ -104,6 +107,31 @@ def reset
@gem_details = false
end
+ def railtie!
+ if Coverband.configuration.track_routes
+ Coverband.configuration.route_tracker = Coverband::Collectors::RouteTracker.new
+ trackers << Coverband.configuration.route_tracker
+ end
+
+ if Coverband.configuration.track_translations
+ Coverband.configuration.translations_tracker = Coverband::Collectors::TranslationTracker.new
+ trackers << Coverband.configuration.translations_tracker
+ end
+
+ if Coverband.configuration.track_views
+ Coverband.configuration.view_tracker = if Coverband.coverband_service?
+ Coverband::Collectors::ViewTrackerService.new
+ else
+ Coverband::Collectors::ViewTracker.new
+ end
+ trackers << Coverband.configuration.view_tracker
+ end
+ trackers.each { |tracker| tracker.railtie! }
+ rescue Redis::CannotConnectError => error
+ Coverband.configuration.logger.info "Redis is not available (#{error}), Coverband not configured"
+ Coverband.configuration.logger.info "If this is a setup task like assets:precompile feel free to ignore"
+ end
+
def logger
@logger ||= if defined?(Rails.logger) && Rails.logger
Rails.logger
diff --git a/lib/coverband/integrations/background.rb b/lib/coverband/integrations/background.rb
index 8d6d3ae6..d7de3fc4 100644
--- a/lib/coverband/integrations/background.rb
+++ b/lib/coverband/integrations/background.rb
@@ -38,9 +38,7 @@ def self.start
# if deferred is set also sleep frst to spread load
sleep(sleep_seconds.to_i) if Coverband.configuration.defer_eager_loading_data?
Coverband.report_coverage
- Coverband.configuration.view_tracker&.report_views_tracked
- Coverband.configuration.route_tracker&.report_routes_tracked
- Coverband.configuration.translations_tracker&.save_report
+ Coverband.configuration.trackers.each { |tracker| tracker.save_report }
if Coverband.configuration.verbose
logger.debug("Coverband: background reporting coverage (#{Coverband.configuration.store.type}). Sleeping #{sleep_seconds}s")
end
diff --git a/lib/coverband/reporters/web.rb b/lib/coverband/reporters/web.rb
index f0db3580..80676ef5 100644
--- a/lib/coverband/reporters/web.rb
+++ b/lib/coverband/reporters/web.rb
@@ -36,51 +36,49 @@ def call(env)
return [401, {"www-authenticate" => 'Basic realm=""'}, [""]] unless check_auth
request_path_info = request.path_info == "" ? "/" : request.path_info
- if request.post?
- case request_path_info
- when %r{\/clear_route_tracking_route}
- clear_route_tracking_route
- when %r{\/clear_route_tracking}
- clear_route_tracking
- when %r{\/clear_translation_tracking_key}
- clear_route_translation_key
- when %r{\/clear_translation_tracking}
- clear_translation_tracking
- when %r{\/clear_view_tracking_file}
- clear_view_tracking_file
- when %r{\/clear_view_tracking}
- clear_view_tracking
- when %r{\/clear_file}
- clear_file
- when %r{\/clear}
- clear
- else
- [404, {"Content-Type" => "text/html"}, ["404 error!"]]
+ tracker_route = false
+ Coverband.configuration.trackers.each do |tracker|
+ if request_path_info.match(tracker.class::REPORT_ROUTE)
+ tracker_route = true
+ if request_path_info =~ %r{\/clear_.*_key}
+ return clear_abstract_tracking_key(tracker)
+ elsif request_path_info =~ %r{\/clear_.*}
+ return clear_abstract_tracking(tracker)
+ else
+ return [200, {"Content-Type" => "text/html"}, [display_abstract_tracker(tracker)]]
+ end
end
- else
- case request_path_info
- when /.*\.(css|js|gif|png)/
- @static.call(env)
- when %r{\/settings}
- [200, {"Content-Type" => "text/html"}, [settings]]
- when %r{\/view_tracker_data}
- [200, {"Content-Type" => "text/json"}, [view_tracker_data]]
- when %r{\/view_tracker}
- [200, {"Content-Type" => "text/html"}, [view_tracker]]
- when %r{\/route_tracker}
- [200, {"Content-Type" => "text/html"}, [route_tracker]]
- when %r{\/translations_tracker}
- [200, {"Content-Type" => "text/html"}, [translations_tracker]]
- when %r{\/enriched_debug_data}
- [200, {"Content-Type" => "text/json"}, [enriched_debug_data]]
- when %r{\/debug_data}
- [200, {"Content-Type" => "text/json"}, [debug_data]]
- when %r{\/load_file_details}
- [200, {"Content-Type" => "text/json"}, [load_file_details]]
- when %r{\/$}
- [200, {"Content-Type" => "text/html"}, [index]]
+ end
+
+ unless tracker_route
+ if request.post?
+ case request_path_info
+ when %r{\/clear_file}
+ clear_file
+ when %r{\/clear}
+ clear
+ else
+ [404, {"Content-Type" => "text/html"}, ["404 error!"]]
+ end
else
- [404, {"Content-Type" => "text/html"}, ["404 error!"]]
+ case request_path_info
+ when /.*\.(css|js|gif|png)/
+ @static.call(env)
+ when %r{\/settings}
+ [200, {"Content-Type" => "text/html"}, [settings]]
+ when %r{\/view_tracker_data}
+ [200, {"Content-Type" => "text/json"}, [view_tracker_data]]
+ when %r{\/enriched_debug_data}
+ [200, {"Content-Type" => "text/json"}, [enriched_debug_data]]
+ when %r{\/debug_data}
+ [200, {"Content-Type" => "text/json"}, [debug_data]]
+ when %r{\/load_file_details}
+ [200, {"Content-Type" => "text/json"}, [load_file_details]]
+ when %r{\/$}
+ [200, {"Content-Type" => "text/html"}, [index]]
+ else
+ [404, {"Content-Type" => "text/html"}, ["404 error!"]]
+ end
end
end
end
@@ -99,32 +97,17 @@ def settings
Coverband::Utils::HTMLFormatter.new(nil, base_path: base_path).format_settings!
end
- def view_tracker
- notice = "Notice: #{Rack::Utils.escape_html(request.params["notice"])}
"
- notice = request.params["notice"] ? notice : ""
- Coverband::Utils::HTMLFormatter.new(nil,
- notice: notice,
- base_path: base_path).format_view_tracker!
- end
-
- def route_tracker
- notice = "Notice: #{Rack::Utils.escape_html(request.params["notice"])}
"
- notice = request.params["notice"] ? notice : ""
- Coverband::Utils::HTMLFormatter.new(nil,
- notice: notice,
- base_path: base_path).format_route_tracker!
- end
-
- def translations_tracker
+ def display_abstract_tracker(tracker)
notice = "Notice: #{Rack::Utils.escape_html(request.params["notice"])}
"
notice = request.params["notice"] ? notice : ""
Coverband::Utils::HTMLFormatter.new(nil,
+ tracker: tracker,
notice: notice,
- base_path: base_path).format_translations_tracker!
+ base_path: base_path).format_abstract_tracker!
end
def view_tracker_data
- Coverband::Collectors::ViewTracker.new(store: Coverband.configuration.store).as_json
+ Coverband::Collectors::ViewTracker.new.as_json
end
def debug_data
@@ -168,73 +151,25 @@ def clear_file
[302, {"Location" => "#{base_path}?notice=#{notice}"}, []]
end
- def clear_view_tracking
- if Coverband.configuration.web_enable_clear
- tracker = Coverband::Collectors::ViewTracker.new(store: Coverband.configuration.store)
- tracker.reset_recordings
- notice = "view tracking reset"
- else
- notice = "web_enable_clear isn't enabled in your configuration"
- end
- [302, {"Location" => "#{base_path}/view_tracker?notice=#{notice}"}, []]
- end
-
- def clear_view_tracking_file
- if Coverband.configuration.web_enable_clear
- tracker = Coverband::Collectors::ViewTracker.new(store: Coverband.configuration.store)
- filename = request.params["filename"]
- tracker.clear_file!(filename)
- notice = "coverage for file #{filename} cleared"
- else
- notice = "web_enable_clear isn't enabled in your configuration"
- end
- [302, {"Location" => "#{base_path}/view_tracker?notice=#{notice}"}, []]
- end
-
- def clear_route_tracking
- if Coverband.configuration.web_enable_clear
- tracker = Coverband::Collectors::RouteTracker.new(store: Coverband.configuration.store)
- tracker.reset_recordings
- notice = "route tracking reset"
- else
- notice = "web_enable_clear isn't enabled in your configuration"
- end
- [302, {"Location" => "#{base_path}/route_tracker?notice=#{notice}"}, []]
- end
-
- def clear_route_tracking_route
- if Coverband.configuration.web_enable_clear
- tracker = Coverband::Collectors::RouteTracker.new(store: Coverband.configuration.store)
- route = request.params["route"]
- tracker.clear_route!(route)
- notice = "coverage for route #{route} cleared"
- else
- notice = "web_enable_clear isn't enabled in your configuration"
- end
- [302, {"Location" => "#{base_path}/route_tracker?notice=#{notice}"}, []]
- end
-
- def clear_translation_tracking
+ def clear_abstract_tracking(tracker)
if Coverband.configuration.web_enable_clear
- tracker = Coverband::Collectors::TranslationTracker.new(store: Coverband.configuration.store)
tracker.reset_recordings
- notice = "translation tracking reset"
+ notice = "#{tracker.title} tracking reset"
else
notice = "web_enable_clear isn't enabled in your configuration"
end
- [302, {"Location" => "#{base_path}/translations_tracker?notice=#{notice}"}, []]
+ [302, {"Location" => "#{base_path}/#{tracker.route}?notice=#{notice}"}, []]
end
- def clear_translation_tracking_key
+ def clear_abstract_tracking_key(tracker)
if Coverband.configuration.web_enable_clear
- tracker = Coverband::Collectors::TranslationTracker.new(store: Coverband.configuration.store)
key = request.params["key"]
tracker.clear_key!(key)
- notice = "coverage for route #{key} cleared"
+ notice = "coverage for #{tracker.title} #{key} cleared"
else
notice = "web_enable_clear isn't enabled in your configuration"
end
- [302, {"Location" => "#{base_path}/translations_tracker?notice=#{notice}"}, []]
+ [302, {"Location" => "#{base_path}/#{tracker.route}?notice=#{notice}"}, []]
end
private
diff --git a/lib/coverband/utils/html_formatter.rb b/lib/coverband/utils/html_formatter.rb
index f900e2bb..08f65434 100644
--- a/lib/coverband/utils/html_formatter.rb
+++ b/lib/coverband/utils/html_formatter.rb
@@ -13,11 +13,12 @@
module Coverband
module Utils
class HTMLFormatter
- attr_reader :notice, :base_path
+ attr_reader :notice, :base_path, :tracker
def initialize(report, options = {})
@notice = options.fetch(:notice, nil)
@base_path = options.fetch(:base_path, "./")
+ @tracker = options.fetch(:tracker, nil)
@coverage_result = Coverband::Utils::Results.new(report) if report
end
@@ -33,16 +34,8 @@ def format_settings!
format_settings
end
- def format_view_tracker!
- format_view_tracker
- end
-
- def format_route_tracker!
- format_route_tracker
- end
-
- def format_translations_tracker!
- format_translations_tracker
+ def format_abstract_tracker!
+ template("abstract_tracker").result(binding)
end
def format_source_file!(filename)
@@ -61,18 +54,6 @@ def format_settings
template("settings").result(binding)
end
- def format_view_tracker
- template("view_tracker").result(binding)
- end
-
- def format_route_tracker
- template("route_tracker").result(binding)
- end
-
- def format_translations_tracker
- template("translations_tracker").result(binding)
- end
-
def format(result)
Dir[File.join(File.dirname(__FILE__), "../../../public/*")].each do |path|
FileUtils.cp_r(path, asset_output_path)
diff --git a/lib/coverband/utils/railtie.rb b/lib/coverband/utils/railtie.rb
index 632b5e29..9f42559e 100644
--- a/lib/coverband/utils/railtie.rb
+++ b/lib/coverband/utils/railtie.rb
@@ -27,51 +27,7 @@ class Railtie < Rails::Railtie
Coverband.runtime_coverage!
end
- begin
- if Coverband.configuration.track_routes
- if Gem::Version.new(Rails.version) >= Gem::Version.new("6.0.0") && Gem::Version.new(Rails.version) < Gem::Version.new("7.1.0")
- require_relative "rails6_ext"
- end
-
- Coverband.configuration.route_tracker = Coverband::Collectors::RouteTracker.new
-
- ActiveSupport::Notifications.subscribe("start_processing.action_controller") do |name, start, finish, id, payload|
- Coverband.configuration.route_tracker.track_routes(name, start, finish, id, payload)
- end
-
- # NOTE: This event was instrumented in Aug 10th 2022, but didn't make the 7.0.4 release and should be in the next release
- # https://github.com/rails/rails/pull/43755
- # Automatic tracking of redirects isn't avaible before Rails 7.1.0 (currently tested against the 7.1.0.alpha)
- # We could consider back porting or patching a solution that works on previous Rails versions
- ActiveSupport::Notifications.subscribe("redirect.action_dispatch") do |name, start, finish, id, payload|
- Coverband.configuration.route_tracker.track_routes(name, start, finish, id, payload)
- end
- end
-
- if Coverband.configuration.track_translations
- Coverband.configuration.translations_tracker = Coverband::Collectors::TranslationTracker.new
-
- # plugin to i18n
- I18n::Backend::Simple.send :include, Coverband::Collectors::I18n::KeyRegistry
- end
-
- if Coverband.configuration.track_views
- COVERBAND_VIEW_TRACKER = if Coverband.coverband_service?
- Coverband::Collectors::ViewTrackerService.new
- else
- Coverband::Collectors::ViewTracker.new
- end
-
- Coverband.configuration.view_tracker = COVERBAND_VIEW_TRACKER
-
- ActiveSupport::Notifications.subscribe(/render_(template|partial|collection).action_view/) do |name, start, finish, id, payload|
- COVERBAND_VIEW_TRACKER.track_views(name, start, finish, id, payload) unless name.include?("!")
- end
- end
- rescue Redis::CannotConnectError => error
- Coverband.configuration.logger.info "Redis is not available (#{error}), Coverband not configured"
- Coverband.configuration.logger.info "If this is a setup task like assets:precompile feel free to ignore"
- end
+ Coverband.configuration.railtie!
end
config.before_configuration do
diff --git a/lib/coverband/version.rb b/lib/coverband/version.rb
index 887ffc89..fe101668 100644
--- a/lib/coverband/version.rb
+++ b/lib/coverband/version.rb
@@ -5,5 +5,5 @@
# use format "4.2.1.rc.1" ~> 4.2.1.rc to prerelease versions like v4.2.1.rc.2 and v4.2.1.rc.3
###
module Coverband
- VERSION = "5.2.6.rc.1"
+ VERSION = "5.2.6.rc.2"
end
diff --git a/test/coverband/collectors/route_tracker_test.rb b/test/coverband/collectors/route_tracker_test.rb
index 8d6852ce..be31b0d4 100644
--- a/test/coverband/collectors/route_tracker_test.rb
+++ b/test/coverband/collectors/route_tracker_test.rb
@@ -23,7 +23,7 @@ def setup
assert_equal nil, tracker.target.first
assert !tracker.store.nil?
assert_equal [], tracker.target
- assert_equal [], tracker.logged_routes
+ assert_equal [], tracker.logged_keys
end
test "track redirect routes" do
@@ -35,9 +35,9 @@ def setup
payload = {
request: Payload.new("path", "GET")
}
- tracker.track_routes("name", "start", "finish", "id", payload)
- tracker.report_routes_tracked
- assert_equal [route_hash], tracker.logged_routes
+ tracker.track_key(payload)
+ tracker.save_report
+ assert_equal [route_hash], tracker.logged_keys
end
test "track controller routes" do
@@ -52,9 +52,9 @@ def setup
path: "path",
method: "GET"
}
- tracker.track_routes("name", "start", "finish", "id", payload)
- tracker.report_routes_tracked
- assert_equal [route_hash], tracker.logged_routes
+ tracker.track_key(payload)
+ tracker.save_report
+ assert_equal [route_hash], tracker.logged_keys
end
test "report used routes" do
@@ -68,9 +68,9 @@ def setup
path: "path",
method: "GET"
}
- tracker.track_routes("name", "start", "finish", "id", payload)
- tracker.report_routes_tracked
- assert_equal [route_hash.to_s], tracker.used_routes.keys
+ tracker.track_key(payload)
+ tracker.save_report
+ assert_equal [route_hash.to_s], tracker.used_keys.keys
end
test "report unused routes" do
@@ -97,9 +97,9 @@ def setup
path: "path",
method: "GET"
}
- tracker.track_routes("name", "start", "finish", "id", payload)
- tracker.report_routes_tracked
- assert_equal [app_routes.first], tracker.unused_routes
+ tracker.track_key(payload)
+ tracker.save_report
+ assert_equal [app_routes.first], tracker.unused_keys
end
test "report unused routes pulls out parameterized routes" do
@@ -120,9 +120,9 @@ def setup
path: "some/controller/123",
method: "GET"
}
- tracker.track_routes("name", "start", "finish", "id", payload)
- tracker.report_routes_tracked
- assert_equal [], tracker.unused_routes
+ tracker.track_key(payload)
+ tracker.save_report
+ assert_equal [], tracker.unused_keys
end
test "reset store" do
@@ -135,9 +135,9 @@ def setup
method: "GET"
}
store.raw_store.expects(:del).with(tracker_key)
- store.raw_store.expects(:del).with("route_tracker_time")
+ store.raw_store.expects(:del).with("RouteTracker_tracker_time")
tracker = Coverband::Collectors::RouteTracker.new(store: store, roots: "dir")
- tracker.track_routes("name", "start", "finish", "id", payload)
+ tracker.track_key(payload)
tracker.reset_recordings
end
@@ -152,10 +152,10 @@ def setup
path: "path",
method: "GET"
}
- tracker.track_routes("name", "start", "finish", "id", payload)
- tracker.report_routes_tracked
- assert_equal [route_hash.to_s], tracker.used_routes.keys
- tracker.clear_route!(route_hash.to_s)
+ tracker.track_key(payload)
+ tracker.save_report
+ assert_equal [route_hash.to_s], tracker.used_keys.keys
+ tracker.clear_key!(route_hash.to_s)
assert_equal [], tracker.store.raw_store.hgetall(tracker_key).keys
end
diff --git a/test/coverband/collectors/view_tracker_test.rb b/test/coverband/collectors/view_tracker_test.rb
index 87abb470..960156fb 100644
--- a/test/coverband/collectors/view_tracker_test.rb
+++ b/test/coverband/collectors/view_tracker_test.rb
@@ -4,7 +4,7 @@
class ViewTrackerTest < Minitest::Test
def tracker_key
- "render_tracker_2"
+ "ViewTracker_tracker"
end
def setup
@@ -18,7 +18,7 @@ def setup
assert_equal "dir", tracker.roots.first
assert !tracker.store.nil?
assert_equal [], tracker.target
- assert_equal [], tracker.logged_views
+ assert_equal [], tracker.logged_keys
end
test "track partials" do
@@ -27,9 +27,9 @@ def setup
file_path = "#{File.expand_path(Coverband.configuration.root)}/file"
store.raw_store.expects(:hset).with(tracker_key, file_path, anything)
tracker = Coverband::Collectors::ViewTracker.new(store: store, roots: "dir")
- tracker.track_views("name", "start", "finish", "id", identifier: file_path)
- tracker.report_views_tracked
- assert_equal [file_path], tracker.logged_views
+ tracker.track_key(identifier: file_path)
+ tracker.save_report
+ assert_equal [file_path], tracker.logged_keys
end
test "track partials that include the word vendor in the path" do
@@ -37,9 +37,9 @@ def setup
store = fake_store
file_path = "#{File.expand_path(Coverband.configuration.root)}/vendor_relations/file"
tracker = Coverband::Collectors::ViewTracker.new(store: store, roots: "dir")
- tracker.track_views("name", "start", "finish", "id", identifier: file_path)
- tracker.report_views_tracked
- assert_equal [file_path], tracker.used_views.keys
+ tracker.track_key(identifier: file_path)
+ tracker.save_report
+ assert_equal [file_path], tracker.used_keys.keys
end
test "track partials that include the word _mailer in the path" do
@@ -47,9 +47,9 @@ def setup
store = fake_store
file_path = "#{File.expand_path(Coverband.configuration.root)}/_mailer/file"
tracker = Coverband::Collectors::ViewTracker.new(store: store, roots: "dir")
- tracker.track_views("name", "start", "finish", "id", identifier: file_path)
- tracker.report_views_tracked
- assert_equal [file_path], tracker.used_views.keys
+ tracker.track_key(identifier: file_path)
+ tracker.save_report
+ assert_equal [file_path], tracker.used_keys.keys
end
test "ignore partials that include the folder vendor in the path" do
@@ -57,9 +57,9 @@ def setup
store = fake_store
file_path = "#{File.expand_path(Coverband.configuration.root)}/vendor/file"
tracker = Coverband::Collectors::ViewTracker.new(store: store, roots: "dir")
- tracker.track_views("name", "start", "finish", "id", identifier: file_path)
- tracker.report_views_tracked
- assert_equal({}, tracker.used_views)
+ tracker.track_key(identifier: file_path)
+ tracker.save_report
+ assert_equal({}, tracker.used_keys)
end
test "track layouts" do
@@ -68,9 +68,9 @@ def setup
file_path = "#{File.expand_path(Coverband.configuration.root)}/layout"
store.raw_store.expects(:hset).with(tracker_key, file_path, anything)
tracker = Coverband::Collectors::ViewTracker.new(store: store, roots: "dir")
- tracker.track_views("name", "start", "finish", "id", layout: file_path)
- tracker.report_views_tracked
- assert_equal [file_path], tracker.logged_views
+ tracker.track_key(layout: file_path)
+ tracker.save_report
+ assert_equal [file_path], tracker.logged_keys
end
test "report used partials" do
@@ -78,9 +78,9 @@ def setup
store = fake_store
file_path = "#{File.expand_path(Coverband.configuration.root)}/file"
tracker = Coverband::Collectors::ViewTracker.new(store: store, roots: "dir")
- tracker.track_views("name", "start", "finish", "id", identifier: file_path)
- tracker.report_views_tracked
- assert_equal [file_path], tracker.used_views.keys
+ tracker.track_key(identifier: file_path)
+ tracker.save_report
+ assert_equal [file_path], tracker.used_keys.keys
end
test "report unused partials" do
@@ -89,30 +89,30 @@ def setup
file_path = "#{File.expand_path(Coverband.configuration.root)}/file"
target = [file_path, "not_used"]
tracker = Coverband::Collectors::ViewTracker.new(store: store, roots: "dir", target: target)
- tracker.track_views("name", "start", "finish", "id", identifier: file_path)
- tracker.report_views_tracked
- assert_equal ["not_used"], tracker.unused_views
+ tracker.track_key(identifier: file_path)
+ tracker.save_report
+ assert_equal ["not_used"], tracker.unused_keys
end
test "reset store" do
Coverband::Collectors::ViewTracker.expects(:supported_version?).returns(true)
store = fake_store
store.raw_store.expects(:del).with(tracker_key)
- store.raw_store.expects(:del).with("render_tracker_time")
+ store.raw_store.expects(:del).with("ViewTracker_tracker_time")
tracker = Coverband::Collectors::ViewTracker.new(store: store, roots: "dir")
- tracker.track_views("name", "start", "finish", "id", identifier: "file")
+ tracker.track_key(identifier: "file")
tracker.reset_recordings
end
- test "clear_file" do
+ test "clear_key" do
Coverband::Collectors::ViewTracker.expects(:supported_version?).returns(true)
store = fake_store
file_path = "#{File.expand_path(Coverband.configuration.root)}/file"
store.raw_store.expects(:hdel).with(tracker_key, file_path)
tracker = Coverband::Collectors::ViewTracker.new(store: store, roots: "dir")
- tracker.track_views("name", "start", "finish", "id", identifier: file_path)
- tracker.clear_file!("file")
- assert_equal [], tracker.logged_views
+ tracker.track_key(identifier: file_path)
+ tracker.clear_key!("file")
+ assert_equal [], tracker.logged_keys
end
protected
diff --git a/test/forked/rails_full_stack_views_test.rb b/test/forked/rails_full_stack_views_test.rb
index a40a36ae..46884956 100644
--- a/test/forked/rails_full_stack_views_test.rb
+++ b/test/forked/rails_full_stack_views_test.rb
@@ -22,35 +22,35 @@ def teardown
visit "/dummy_view/show"
assert_content("I am no dummy view tracker text")
Coverband.report_coverage
- Coverband.configuration.view_tracker&.report_views_tracked
- Coverband.configuration.route_tracker&.report_routes_tracked
- visit "/coverage/view_tracker"
+ Coverband.configuration.view_tracker&.save_report
+ Coverband.configuration.route_tracker&.save_report
+ visit "/coverage/views_tracker"
assert_content("Used Views: (1)")
assert_content("Unused Views: (2)")
- assert_selector("li.used-views", text: "dummy_view/show.html.erb")
- assert_selector("li.unused-views", text: "dummy_view/show_haml.html.haml")
- assert_selector("li.unused-views", text: "dummy_view/show_slim.html.slim")
+ assert_selector("li.used-keys", text: "dummy_view/show.html.erb")
+ assert_selector("li.unused-keys", text: "dummy_view/show_haml.html.haml")
+ assert_selector("li.unused-keys", text: "dummy_view/show_slim.html.slim")
- visit "/coverage/route_tracker"
+ visit "/coverage/routes_tracker"
assert_content("Used Routes: (1)")
assert_content("Unused Routes: (5)")
visit "/dummy_view/show_haml"
assert_content("I am haml text")
Coverband.report_coverage
- Coverband.configuration.view_tracker&.report_views_tracked
- visit "/coverage/view_tracker"
+ Coverband.configuration.view_tracker&.save_report
+ visit "/coverage/views_tracker"
assert_content("Used Views: (2)")
assert_content("Unused Views: (1)")
- assert_selector("li.used-views", text: "dummy_view/show_haml.html.haml")
+ assert_selector("li.used-keys", text: "dummy_view/show_haml.html.haml")
visit "/dummy_view/show_slim"
assert_content("I am slim text")
Coverband.report_coverage
- Coverband.configuration.view_tracker&.report_views_tracked
- visit "/coverage/view_tracker"
+ Coverband.configuration.view_tracker&.save_report
+ visit "/coverage/views_tracker"
assert_content("Used Views: (3)")
assert_content("Unused Views: (0)")
- assert_selector("li.used-views", text: "dummy_view/show_slim.html.slim")
+ assert_selector("li.used-keys", text: "dummy_view/show_slim.html.slim")
end
end
diff --git a/test/forked/rails_route_tracker_stack_test.rb b/test/forked/rails_route_tracker_stack_test.rb
index 59d72c34..e5c7da5a 100644
--- a/test/forked/rails_route_tracker_stack_test.rb
+++ b/test/forked/rails_route_tracker_stack_test.rb
@@ -17,7 +17,7 @@ def teardown
output = `sleep 7 && curl http://localhost:9999/dummy_view/show`
assert output.match(/rendered view/)
assert output.match(/I am no dummy view tracker text/)
- output = `sleep 2 && curl http://localhost:9999/coverage/route_tracker`
+ output = `sleep 2 && curl http://localhost:9999/coverage/routes_tracker`
assert output.match(/Used Routes: \(1\)/)
assert output.match(/dummy_view\/show/)
assert output.match(/GET/)
diff --git a/test/forked/rails_view_tracker_stack_test.rb b/test/forked/rails_view_tracker_stack_test.rb
index 812aa900..5ff90c03 100644
--- a/test/forked/rails_view_tracker_stack_test.rb
+++ b/test/forked/rails_view_tracker_stack_test.rb
@@ -17,7 +17,7 @@ def teardown
output = `sleep 7 && curl http://localhost:9999/dummy_view/show`
assert output.match(/rendered view/)
assert output.match(/I am no dummy view tracker text/)
- output = `sleep 2 && curl http://localhost:9999/coverage/view_tracker`
+ output = `sleep 2 && curl http://localhost:9999/coverage/views_tracker`
assert output.match(/Used Views: \(1\)/)
assert output.match(/dummy_view\/show/)
end
diff --git a/views/translations_tracker.erb b/views/abstract_tracker.erb
similarity index 66%
rename from views/translations_tracker.erb
rename to views/abstract_tracker.erb
index d2bdf0b5..8dec2f34 100644
--- a/views/translations_tracker.erb
+++ b/views/abstract_tracker.erb
@@ -11,31 +11,30 @@
- <%= display_nav(active_link: 'translations_tracker') %>
+ <%= display_nav(active_link: tracker.route) %>
- <% tracker = Coverband::Collectors::TranslationTracker.new(store: Coverband.configuration.store) %>
<% if Coverband.configuration.web_enable_clear %>
- <%= button("#{base_path}clear_translation_tracking", 'reset translation tracker', delete: true) %>
+ <%= button("#{base_path}clear_#{tracker.route}", "reset #{tracker.title} tracker", delete: true) %>
<% end %>
-
Unused Translations: (<%= tracker.unused_keys.length %>)
-
These Translations have not been rendered since recording started at <%= tracker.tracking_since %>
+
Unused <%= tracker.title %>: (<%= tracker.unused_keys.length %>)
+
These <%= tracker.title %> have not been rendered since recording started at <%= tracker.tracking_since %>
<% tracker.unused_keys.each do |key| %>
- <%= key %>
<% end %>
-
Used Translations: (<%= tracker.used_keys.length %>)
-
These Translations have been rendered at least once
+
Used <%= tracker.title %>: (<%= tracker.used_keys.length %>)
+
These <%= tracker.title %> have been rendered at least once