capydash 0.2.4 → 0.3.0

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.
@@ -0,0 +1,180 @@
1
+ require 'time'
2
+ require 'fileutils'
3
+ require 'erb'
4
+ require 'cgi'
5
+ require 'tmpdir'
6
+
7
+ module CapyDash
8
+ class ReportData
9
+ attr_reader :processed_tests, :created_at, :total_tests, :passed_tests, :failed_tests
10
+
11
+ def initialize(processed_tests:, created_at:, total_tests:, passed_tests:, failed_tests:)
12
+ @processed_tests = processed_tests
13
+ @created_at = created_at
14
+ @total_tests = total_tests
15
+ @passed_tests = passed_tests
16
+ @failed_tests = failed_tests
17
+ end
18
+
19
+ def h(text)
20
+ CGI.escapeHTML(text.to_s)
21
+ end
22
+
23
+ def get_binding
24
+ binding
25
+ end
26
+ end
27
+
28
+ module Reporter
29
+ def start_run
30
+ @results = []
31
+ @started_at = Time.now
32
+ end
33
+
34
+ def record_result(result_hash)
35
+ return unless @started_at
36
+ @results << result_hash
37
+ end
38
+
39
+ def generate_report
40
+ return unless @started_at
41
+ return if @results.empty?
42
+
43
+ report_dir = File.join(Dir.pwd, "capydash_report")
44
+ FileUtils.mkdir_p(report_dir)
45
+
46
+ assets_dir = File.join(report_dir, "assets")
47
+ FileUtils.mkdir_p(assets_dir)
48
+
49
+ screenshots_dir = File.join(assets_dir, "screenshots")
50
+ FileUtils.rm_rf(screenshots_dir)
51
+ FileUtils.mkdir_p(screenshots_dir)
52
+
53
+ # Group results by class
54
+ tests_by_class = @results.group_by { |r| r[:class_name] }
55
+
56
+ # Calculate statistics
57
+ total_tests = @results.length
58
+ passed_tests = @results.count { |r| r[:status] == 'passed' }
59
+ failed_tests = @results.count { |r| r[:status] == 'failed' }
60
+
61
+ # Copy screenshots into report and build relative paths
62
+ screenshot_index = 0
63
+ @results.each do |result|
64
+ if result[:screenshot_path] && File.exist?(result[:screenshot_path])
65
+ screenshot_index += 1
66
+ dest_name = format("%03d.png", screenshot_index)
67
+ dest_path = File.join(screenshots_dir, dest_name)
68
+ FileUtils.cp(result[:screenshot_path], dest_path)
69
+ result[:screenshot_relative] = "assets/screenshots/#{dest_name}"
70
+ end
71
+ end
72
+
73
+ # Process for template
74
+ processed_tests = tests_by_class.map do |class_name, examples|
75
+ {
76
+ class_name: class_name,
77
+ methods: examples.map do |ex|
78
+ {
79
+ name: ex[:method_name],
80
+ status: ex[:status],
81
+ steps: [{
82
+ name: 'test_execution',
83
+ detail: ex[:method_name],
84
+ status: ex[:status],
85
+ error: ex[:error],
86
+ screenshot: ex[:screenshot_relative]
87
+ }]
88
+ }
89
+ end
90
+ }
91
+ end
92
+
93
+ # Generate HTML
94
+ html_content = generate_html(processed_tests, @started_at, total_tests, passed_tests, failed_tests)
95
+ File.write(File.join(report_dir, "index.html"), html_content)
96
+
97
+ # Generate CSS
98
+ css_content = generate_css
99
+ File.write(File.join(assets_dir, "dashboard.css"), css_content)
100
+
101
+ # Generate JS
102
+ js_content = generate_javascript
103
+ File.write(File.join(assets_dir, "dashboard.js"), js_content)
104
+
105
+ report_dir
106
+ end
107
+
108
+ def normalize_status(status)
109
+ case status
110
+ when :passed, 'passed'
111
+ 'passed'
112
+ when :failed, 'failed'
113
+ 'failed'
114
+ when :pending, 'pending', :skipped, 'skipped'
115
+ 'pending'
116
+ else
117
+ status.to_s
118
+ end
119
+ end
120
+
121
+ def format_exception(exception)
122
+ return nil unless exception
123
+
124
+ message = exception.message || 'Unknown error'
125
+ backtrace = exception.backtrace || []
126
+
127
+ formatted = "#{exception.class}: #{message}"
128
+ if backtrace.any?
129
+ formatted += "\n" + backtrace.first(5).map { |line| " #{line}" }.join("\n")
130
+ end
131
+
132
+ formatted
133
+ end
134
+
135
+ def capture_screenshot
136
+ return nil unless defined?(::Capybara) && defined?(::Capybara.current_session)
137
+
138
+ session = ::Capybara.current_session
139
+ return nil unless session.respond_to?(:save_screenshot)
140
+
141
+ tmpfile = File.join(Dir.tmpdir, "capydash_#{Time.now.to_i}_#{rand(10000)}.png")
142
+ session.save_screenshot(tmpfile)
143
+ tmpfile
144
+ rescue => _e
145
+ nil
146
+ end
147
+
148
+ private
149
+
150
+ def generate_html(processed_tests, created_at, total_tests, passed_tests, failed_tests)
151
+ processed_tests.each do |test_class|
152
+ test_class[:methods].each do |method|
153
+ method[:safe_id] = method[:name].gsub(/['"]/, '').gsub(/[^a-zA-Z0-9]/, '_')
154
+ end
155
+ end
156
+
157
+ template_path = File.join(File.dirname(__FILE__), 'templates', 'report.html.erb')
158
+ template = File.read(template_path)
159
+ erb = ERB.new(template)
160
+
161
+ report_data = CapyDash::ReportData.new(
162
+ processed_tests: processed_tests,
163
+ created_at: created_at,
164
+ total_tests: total_tests,
165
+ passed_tests: passed_tests,
166
+ failed_tests: failed_tests
167
+ )
168
+
169
+ erb.result(report_data.get_binding)
170
+ end
171
+
172
+ def generate_css
173
+ File.read(File.join(File.dirname(__FILE__), 'assets', 'dashboard.css'))
174
+ end
175
+
176
+ def generate_javascript
177
+ File.read(File.join(File.dirname(__FILE__), 'assets', 'dashboard.js'))
178
+ end
179
+ end
180
+ end