mensa 0.6.17 → 0.6.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.shipkit.yml +1 -1
- data/CHANGELOG.md +34 -0
- data/Gemfile.lock +1 -1
- data/README.md +150 -3
- data/app/components/mensa/row_action/component.html.erb +1 -1
- data/app/helpers/mensa/application_helper.rb +11 -6
- data/app/jobs/mensa/export_job.rb +28 -10
- data/app/tables/mensa/base.rb +3 -1
- data/app/tables/mensa/column.rb +18 -3
- data/app/tables/mensa/config/column_dsl.rb +2 -1
- data/app/tables/mensa/filter.rb +40 -0
- data/app/tables/mensa/scope.rb +3 -0
- data/app/tables/mensa/search.rb +2 -1
- data/lib/generators/mensa/templates/config/initializers/mensa.rb +4 -0
- data/lib/mensa/configuration.rb +9 -0
- data/lib/mensa/testing.rb +63 -0
- data/lib/mensa/verifier/result.rb +121 -0
- data/lib/mensa/verifier.rb +875 -0
- data/lib/mensa/version.rb +1 -1
- data/lib/mensa.rb +11 -0
- data/lib/tasks/mensa.rake +13 -0
- metadata +6 -2
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Mensa
|
|
4
|
+
class Verifier
|
|
5
|
+
# One verified aspect of a table, e.g. sorting a column descending.
|
|
6
|
+
#
|
|
7
|
+
# +section+ groups checks in the report (:loads, :columns, :filters, ...),
|
|
8
|
+
# +subject+ is the column, filter or view it relates to. Warnings (N+1
|
|
9
|
+
# queries, slow queries) don't fail the table unless it's verified strict.
|
|
10
|
+
Check = Struct.new(:section, :subject, :name, :status, :message, :sql, :error) do
|
|
11
|
+
def passed?
|
|
12
|
+
status == :passed
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def failed?
|
|
16
|
+
status == :failed
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def skipped?
|
|
20
|
+
status == :skipped
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def warning?
|
|
24
|
+
status == :warning
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def label
|
|
28
|
+
[subject, name].compact.join(": ")
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
class Result
|
|
33
|
+
SECTIONS = {
|
|
34
|
+
loads: "Loads",
|
|
35
|
+
columns: "Columns",
|
|
36
|
+
filters: "Filters",
|
|
37
|
+
search: "Search",
|
|
38
|
+
render: "Rendering",
|
|
39
|
+
combined: "Combined",
|
|
40
|
+
exports: "Exports",
|
|
41
|
+
grouping: "Grouping",
|
|
42
|
+
views: "Views"
|
|
43
|
+
}.freeze
|
|
44
|
+
|
|
45
|
+
SYMBOLS = {passed: "✓", failed: "✗", skipped: "-", warning: "!"}.freeze
|
|
46
|
+
|
|
47
|
+
attr_reader :table_class, :checks, :label
|
|
48
|
+
|
|
49
|
+
# +label+ names the context it was verified in, e.g. "user: User#1"
|
|
50
|
+
def initialize(table_class, strict: false, label: nil)
|
|
51
|
+
@table_class = table_class
|
|
52
|
+
@strict = strict
|
|
53
|
+
@label = label
|
|
54
|
+
@checks = []
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# False for a class that isn't a Mensa::Base subclass, which is skipped
|
|
58
|
+
def mensa_table?
|
|
59
|
+
table_class.is_a?(Class) && table_class < Mensa::Base
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def strict?
|
|
63
|
+
@strict
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def success?
|
|
67
|
+
failures.empty? && (!strict? || warnings.empty?)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def failures
|
|
71
|
+
checks.select(&:failed?)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def passes
|
|
75
|
+
checks.select(&:passed?)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def skips
|
|
79
|
+
checks.select(&:skipped?)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def warnings
|
|
83
|
+
checks.select(&:warning?)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def summary
|
|
87
|
+
"#{passes.size} passed, #{failures.size} failed, #{skips.size} skipped, #{warnings.size} #{"warning".pluralize(warnings.size)}"
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def title
|
|
91
|
+
[table_class.name || table_class.to_s, ("(#{label})" if label)].compact.join(" ")
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def to_s
|
|
95
|
+
return "#{title}\n - skipped: #{checks.first&.message}" unless mensa_table?
|
|
96
|
+
|
|
97
|
+
lines = [title]
|
|
98
|
+
|
|
99
|
+
checks.group_by(&:section).each do |section, section_checks|
|
|
100
|
+
lines << " #{SECTIONS.fetch(section, section.to_s.humanize)}"
|
|
101
|
+
section_checks.each do |check|
|
|
102
|
+
lines << " #{SYMBOLS[check.status]} #{check.label}#{" (skipped: #{check.message})" if check.skipped?}"
|
|
103
|
+
next unless check.failed? || check.warning?
|
|
104
|
+
|
|
105
|
+
check.message.to_s.each_line { |line| lines << " #{line.chomp}" }
|
|
106
|
+
lines << " SQL: #{check.sql}" if check.sql.present?
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
lines << ""
|
|
111
|
+
lines << "#{success? ? "OK" : "FAILED"}: #{summary}#{" (strict: warnings fail)" if strict? && warnings.any?}"
|
|
112
|
+
lines.join("\n")
|
|
113
|
+
end
|
|
114
|
+
alias_method :report, :to_s
|
|
115
|
+
|
|
116
|
+
def inspect
|
|
117
|
+
"#<#{self.class.name} #{title} #{summary}>"
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|