capydash 0.1.3 → 0.1.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: aa238074c05a59e8c88ec84c887944dc2c376ae379ffde69c3422b939d052d77
4
- data.tar.gz: fdfc24fbe669f5a8d0ff44792383b5eae3abcf69d21ed52810228972d0773959
3
+ metadata.gz: 49eae6d67432aa999fc952f38f9268dd145275fccc64e31ebf9ec325580084f1
4
+ data.tar.gz: c169ad633644fadf23a8c6a672bb0e73621fdf66c2c16d35662dcea5e7fea0a7
5
5
  SHA512:
6
- metadata.gz: b49bd9f834a849025f79fc72fc3c317e971fba0ea74504e09d35026a4bdb18b224f48a86ab6041fb43a78de5dd6897ecba9ca43e9f57bfc356385a318313f0e4
7
- data.tar.gz: 9c3f988ea6164e454f73d1600ec61ceddfc63f9f6dbb4220c535df60ecf4662f08653fdbcfc9bf6936616382455d8bef473a5f03336d6af8aba72da328c67428
6
+ metadata.gz: 13a7e91002c75629f074f0e717f585a066296f90847599da479c6d54a6bb622cd354d0449d0e5526a7af253bc702fad7629a5bb595a3426b525f153110546880
7
+ data.tar.gz: 95432cc4068cd79a74c1f569a5c239eef704d152918fe81f81e8771e451295f0d9664977cf4127680b91483424ea89945991bda8df79a325e1266d44a45c4d10
data/README.md CHANGED
@@ -16,8 +16,36 @@ Or run:
16
16
  bundle add capydash
17
17
  ```
18
18
 
19
+ ## Quick Setup
20
+
21
+ ### One-Command Installation
22
+
23
+ After adding CapyDash to your Gemfile and running `bundle install`, simply run:
24
+
25
+ ```bash
26
+ bundle exec rails generate capydash:install
27
+ ```
28
+
29
+ This will automatically:
30
+ - ✅ Create the CapyDash initializer
31
+ - ✅ Update your test helper with all necessary hooks
32
+ - ✅ Add rake tasks for report generation
33
+ - ✅ Works with parallel testing out of the box
34
+
35
+ ### Manual Setup (Alternative)
36
+
37
+ If you prefer to set up CapyDash manually, see the [Manual Setup Guide](#manual-setup) below.
38
+
19
39
  ## Usage
20
40
 
41
+ ### Run Tests with CapyDash
42
+
43
+ Run your tests normally - CapyDash will automatically instrument them:
44
+
45
+ ```bash
46
+ bundle exec rails test
47
+ ```
48
+
21
49
  ### Generate Test Report
22
50
 
23
51
  After running your Capybara tests, generate a static HTML report:
@@ -45,17 +73,133 @@ open capydash_report/index.html
45
73
  bundle exec rake capydash:server
46
74
  ```
47
75
 
48
- Then open `http://localhost:5173` in your browser.
76
+ Then open `http://localhost:4000` in your browser.
49
77
 
50
- ### Run Tests with CapyDash
78
+ ## Troubleshooting
51
79
 
52
- Run your tests normally - CapyDash will automatically instrument them:
80
+ ### Common Issues
53
81
 
54
- ```bash
55
- bundle exec rails test
82
+ 1. **"No test data found"**: Make sure you've added the test helper configuration and are running actual Capybara tests (not just unit tests).
83
+
84
+ 2. **"log shifting failed" error**: This is a Rails logger issue, not related to CapyDash. It's harmless but you can fix it by updating your Rails version.
85
+
86
+ 3. **Screenshots not working**: Make sure you're using a driver that supports screenshots (like Selenium, not rack_test).
87
+
88
+ 4. **Tests not appearing in report**: Ensure your tests are using Capybara methods like `visit`, `click_button`, `fill_in`, etc.
89
+
90
+ 5. **"No test data found"**: Make sure you're running system tests that use Capybara methods. CapyDash works with parallel testing by default.
91
+
92
+ ### Example Test
93
+
94
+ Here's an example test that will work with CapyDash:
95
+
96
+ ```ruby
97
+ require 'test_helper'
98
+
99
+ class HomepageTest < ActionDispatch::IntegrationTest
100
+ include Capybara::DSL
101
+
102
+ test "homepage loads with correct content" do
103
+ visit "/"
104
+ assert_text "Welcome"
105
+
106
+ fill_in "Your name", with: "Alice"
107
+ click_button "Greet"
108
+ assert_text "Hello, Alice!"
109
+ end
110
+ end
111
+ ```
112
+
113
+ ## Manual Setup
114
+
115
+ If you prefer to set up CapyDash manually instead of using the generator:
116
+
117
+ ### Step 1: Create CapyDash Initializer
118
+
119
+ Create `config/initializers/capydash.rb` in your Rails project:
120
+
121
+ ```ruby
122
+ require 'capydash'
123
+
124
+ # Configure CapyDash
125
+ CapyDash.configure do |config|
126
+ config.port = 4000
127
+ config.screenshot_path = "tmp/capydash_screenshots"
128
+ end
129
+
130
+ # Subscribe to events for test data collection
131
+ CapyDash::EventEmitter.subscribe do |event|
132
+ # Collect test data for report generation
133
+ CapyDash::TestDataAggregator.handle_event(event)
134
+ end
56
135
  ```
57
136
 
58
- The report will be generated in `capydash_report/index.html` after test completion.
137
+ ### Step 2: Update Test Helper
138
+
139
+ In your `test/test_helper.rb`, add the following:
140
+
141
+ ```ruby
142
+ require 'capydash'
143
+
144
+ # Start test run data collection
145
+ CapyDash::TestDataCollector.start_test_run
146
+
147
+ # Hook into test execution to set current test name and manage test runs
148
+ module CapyDash
149
+ module TestHooks
150
+ def run(&block)
151
+ # Set the current test name for CapyDash
152
+ CapyDash.current_test = self.name
153
+
154
+ # Start test run data collection if not already started
155
+ CapyDash::TestDataAggregator.start_test_run unless CapyDash::TestDataAggregator.instance_variable_get(:@current_run)
156
+
157
+ super
158
+ end
159
+ end
160
+ end
161
+
162
+ # Apply the hook to the test case
163
+ class ActiveSupport::TestCase
164
+ prepend CapyDash::TestHooks
165
+ end
166
+
167
+ # Hook to finish test run when all tests are done
168
+ Minitest.after_run do
169
+ CapyDash::TestDataCollector.finish_test_run
170
+ CapyDash::TestDataAggregator.finish_test_run
171
+ end
172
+ ```
173
+
174
+ ### Step 3: Add Rake Tasks
175
+
176
+ Create `lib/tasks/capydash.rake` in your Rails project:
177
+
178
+ ```ruby
179
+ namespace :capydash do
180
+ desc "Generate static HTML test report"
181
+ task :report => :environment do
182
+ CapyDash::ReportGenerator.generate_report
183
+ end
184
+
185
+ desc "Start local server to view static HTML report"
186
+ task :server => :environment do
187
+ CapyDash::DashboardServer.start
188
+ end
189
+ end
190
+ ```
191
+
192
+ ### Step 4: Configure System Tests (Optional)
193
+
194
+ If you're using system tests, make sure your `test/application_system_test_case.rb` uses a driver that supports screenshots:
195
+
196
+ ```ruby
197
+ require "test_helper"
198
+
199
+ class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
200
+ driven_by :selenium, using: :headless_chrome, screen_size: [ 800, 600 ]
201
+ end
202
+ ```
59
203
 
60
204
  ## Development
61
205
 
data/capydash.gemspec CHANGED
@@ -16,6 +16,9 @@ Gem::Specification.new do |spec|
16
16
  spec.files = Dir["lib/**/*", "bin/*", "README.md", "LICENSE*", "*.gemspec"]
17
17
  spec.require_paths = ["lib"]
18
18
 
19
+ # Add generator support
20
+ spec.add_runtime_dependency "railties", ">= 5.0"
21
+
19
22
  # Dependencies
20
23
  spec.add_runtime_dependency "capybara", ">= 3.0"
21
24
  spec.add_runtime_dependency "faye-websocket"
@@ -1,103 +1,128 @@
1
1
  require 'json'
2
2
  require 'time'
3
3
  require 'securerandom'
4
+ require 'fileutils'
4
5
 
5
6
  module CapyDash
6
7
  class TestDataAggregator
7
8
  class << self
8
9
  def start_test_run
9
- @current_run = {
10
- id: generate_run_id,
10
+ run_id = generate_run_id
11
+ run_data = {
12
+ id: run_id,
11
13
  created_at: Time.now.iso8601,
12
14
  total_tests: 0,
13
15
  passed_tests: 0,
14
16
  failed_tests: 0,
15
17
  tests: []
16
18
  }
17
- @current_test = nil
18
- @test_steps = []
19
+
20
+ # Save initial run data to file
21
+ save_run_data(run_data)
22
+
23
+ # Set current test context
24
+ set_current_test_context(run_id, nil, [])
19
25
  end
20
26
 
21
27
  def finish_test_run
22
- return unless @current_run
28
+ run_id = get_current_run_id
29
+ return unless run_id
23
30
 
24
- # Save the test run data
25
- CapyDash.save_test_run(@current_run)
31
+ # Load current run data
32
+ run_data = load_run_data(run_id)
33
+ return unless run_data
34
+
35
+ # Save the final test run data
36
+ CapyDash.save_test_run(run_data)
26
37
 
27
38
  # Clear current state
28
- @current_run = nil
29
- @current_test = nil
30
- @test_steps = nil
39
+ clear_current_test_context
31
40
  end
32
41
 
33
42
  def handle_event(event)
34
- return unless @current_run
43
+ run_id = get_current_run_id
44
+ return unless run_id
45
+
46
+ # Load current run data
47
+ run_data = load_run_data(run_id)
48
+ return unless run_data
35
49
 
36
50
  case event[:step_name]
37
51
  when 'test_start'
38
- start_new_test(event)
52
+ start_new_test(event, run_data)
39
53
  when 'test_finish'
40
- finish_current_test(event)
54
+ finish_current_test(event, run_data)
41
55
  when 'test_result'
42
56
  # This indicates the test is finished
43
- finish_current_test(event)
57
+ finish_current_test(event, run_data)
44
58
  else
45
59
  # This is a test step (visit, click_button, fill_in, etc.)
46
60
  # If we don't have a current test, start one
47
- start_new_test(event) unless @current_test
48
- add_test_step(event)
61
+ current_test = get_current_test
62
+ start_new_test(event, run_data) unless current_test
63
+ add_test_step(event, run_data)
49
64
  end
50
65
  end
51
66
 
52
67
  private
53
68
 
54
- def start_new_test(event)
69
+ def start_new_test(event, run_data)
55
70
  # Extract test name from the current test context
56
71
  test_name = event[:test_name] || CapyDash.current_test || "unknown_test"
57
72
 
58
- @current_test = {
73
+ current_test = {
59
74
  test_name: test_name,
60
75
  steps: []
61
76
  }
62
- @test_steps = []
77
+
78
+ # Set current test context
79
+ set_current_test_context(run_data[:id], current_test, [])
63
80
 
64
81
  # Add the test_start step
65
- add_test_step(event)
82
+ add_test_step(event, run_data)
66
83
  end
67
84
 
68
- def finish_current_test(event)
69
- return unless @current_test
85
+ def finish_current_test(event, run_data)
86
+ current_test = get_current_test
87
+ return unless current_test
70
88
 
71
89
  # Add the test_finish step
72
- add_test_step(event)
90
+ add_test_step(event, run_data)
91
+
92
+ # Get updated test data
93
+ current_test = get_current_test
94
+ test_steps = get_current_test_steps
73
95
 
74
96
  # Determine test status
75
- test_status = determine_test_status(@test_steps)
97
+ test_status = determine_test_status(test_steps)
76
98
 
77
99
  # Update counters
78
- @current_run[:total_tests] += 1
100
+ run_data[:total_tests] += 1
79
101
  if test_status == 'passed'
80
- @current_run[:passed_tests] += 1
102
+ run_data[:passed_tests] += 1
81
103
  elsif test_status == 'failed'
82
- @current_run[:failed_tests] += 1
104
+ run_data[:failed_tests] += 1
83
105
  end
84
106
 
85
107
  # Add test to current run
86
- @current_run[:tests] << @current_test
108
+ run_data[:tests] << current_test
109
+
110
+ # Save updated run data
111
+ save_run_data(run_data)
87
112
 
88
113
  # Clear current test
89
- @current_test = nil
90
- @test_steps = nil
114
+ set_current_test_context(run_data[:id], nil, [])
91
115
  end
92
116
 
93
- def add_test_step(event)
94
- return unless @current_test
117
+ def add_test_step(event, run_data)
118
+ current_test = get_current_test
119
+ return unless current_test
95
120
 
96
121
  step = {
97
122
  step_name: event[:step_name],
98
123
  detail: event[:detail],
99
124
  status: event[:status],
100
- test_name: event[:test_name] || CapyDash.current_test || @current_test[:test_name]
125
+ test_name: event[:test_name] || CapyDash.current_test || current_test[:test_name]
101
126
  }
102
127
 
103
128
  # Add screenshot if present
@@ -110,8 +135,12 @@ module CapyDash
110
135
  step[:error] = event[:error]
111
136
  end
112
137
 
113
- @current_test[:steps] << step
114
- @test_steps << step
138
+ # Update current test with new step
139
+ current_test[:steps] << step
140
+ test_steps = get_current_test_steps + [step]
141
+
142
+ # Save updated test context
143
+ set_current_test_context(run_data[:id], current_test, test_steps)
115
144
  end
116
145
 
117
146
  def determine_test_status(steps)
@@ -123,6 +152,63 @@ module CapyDash
123
152
  def generate_run_id
124
153
  "#{Time.now.to_i}_#{SecureRandom.hex(4)}"
125
154
  end
155
+
156
+ # File-based storage methods for parallel testing support
157
+ def run_data_file(run_id)
158
+ File.join(Dir.pwd, "tmp", "capydash_data", "run_#{run_id}.json")
159
+ end
160
+
161
+ def context_file
162
+ File.join(Dir.pwd, "tmp", "capydash_data", "current_context.json")
163
+ end
164
+
165
+ def save_run_data(run_data)
166
+ FileUtils.mkdir_p(File.dirname(run_data_file(run_data[:id])))
167
+ File.write(run_data_file(run_data[:id]), run_data.to_json)
168
+ end
169
+
170
+ def load_run_data(run_id)
171
+ file_path = run_data_file(run_id)
172
+ return nil unless File.exist?(file_path)
173
+
174
+ JSON.parse(File.read(file_path), symbolize_names: true)
175
+ end
176
+
177
+ def set_current_test_context(run_id, current_test, test_steps)
178
+ context = {
179
+ run_id: run_id,
180
+ current_test: current_test,
181
+ test_steps: test_steps
182
+ }
183
+
184
+ FileUtils.mkdir_p(File.dirname(context_file))
185
+ File.write(context_file, context.to_json)
186
+ end
187
+
188
+ def get_current_run_id
189
+ return nil unless File.exist?(context_file)
190
+
191
+ context = JSON.parse(File.read(context_file), symbolize_names: true)
192
+ context[:run_id]
193
+ end
194
+
195
+ def get_current_test
196
+ return nil unless File.exist?(context_file)
197
+
198
+ context = JSON.parse(File.read(context_file), symbolize_names: true)
199
+ context[:current_test]
200
+ end
201
+
202
+ def get_current_test_steps
203
+ return [] unless File.exist?(context_file)
204
+
205
+ context = JSON.parse(File.read(context_file), symbolize_names: true)
206
+ context[:test_steps] || []
207
+ end
208
+
209
+ def clear_current_test_context
210
+ File.delete(context_file) if File.exist?(context_file)
211
+ end
126
212
  end
127
213
  end
128
214
  end
@@ -1,3 +1,3 @@
1
1
  module Capydash
2
- VERSION = "0.1.3"
2
+ VERSION = "0.1.5"
3
3
  end
@@ -0,0 +1,124 @@
1
+ require 'rails/generators'
2
+
3
+ module Capydash
4
+ module Generators
5
+ class InstallGenerator < Rails::Generators::Base
6
+ source_root File.expand_path('templates', __dir__)
7
+
8
+ desc "Installs CapyDash with all necessary configuration files"
9
+
10
+ def create_initializer
11
+ create_file "config/initializers/capydash.rb", <<~RUBY
12
+ require 'capydash'
13
+
14
+ # Configure CapyDash
15
+ CapyDash.configure do |config|
16
+ config.port = 4000
17
+ config.screenshot_path = "tmp/capydash_screenshots"
18
+ end
19
+
20
+ # Subscribe to events for test data collection
21
+ CapyDash::EventEmitter.subscribe do |event|
22
+ # Collect test data for report generation
23
+ CapyDash::TestDataAggregator.handle_event(event)
24
+ end
25
+ RUBY
26
+ end
27
+
28
+ def create_rake_tasks
29
+ create_file "lib/tasks/capydash.rake", <<~RUBY
30
+ namespace :capydash do
31
+ desc "Generate static HTML test report"
32
+ task :report => :environment do
33
+ CapyDash::ReportGenerator.generate_report
34
+ end
35
+
36
+ desc "Start local server to view static HTML report"
37
+ task :server => :environment do
38
+ CapyDash::DashboardServer.start
39
+ end
40
+ end
41
+ RUBY
42
+ end
43
+
44
+ def update_test_helper
45
+ test_helper_path = "test/test_helper.rb"
46
+
47
+ if File.exist?(test_helper_path)
48
+ # Read existing test helper
49
+ content = File.read(test_helper_path)
50
+
51
+ # Check if CapyDash is already configured
52
+ unless content.include?("require 'capydash'")
53
+ # Add CapyDash configuration
54
+ capydash_config = <<~RUBY
55
+
56
+ # CapyDash configuration
57
+ require 'capydash'
58
+
59
+ # Start test run data collection
60
+ CapyDash::TestDataCollector.start_test_run
61
+
62
+ # Hook into test execution to set current test name and manage test runs
63
+ module CapyDash
64
+ module TestHooks
65
+ def run(&block)
66
+ # Set the current test name for CapyDash
67
+ CapyDash.current_test = self.name
68
+
69
+ # Start test run data collection if not already started
70
+ CapyDash::TestDataAggregator.start_test_run unless CapyDash::TestDataAggregator.instance_variable_get(:@current_run)
71
+
72
+ super
73
+ end
74
+ end
75
+ end
76
+
77
+ # Apply the hook to the test case
78
+ class ActiveSupport::TestCase
79
+ prepend CapyDash::TestHooks
80
+ end
81
+
82
+ # Hook to finish test run when all tests are done
83
+ Minitest.after_run do
84
+ CapyDash::TestDataCollector.finish_test_run
85
+ CapyDash::TestDataAggregator.finish_test_run
86
+ end
87
+ RUBY
88
+
89
+ # Insert after the last require statement
90
+ if content.match(/require.*\n/)
91
+ content = content.gsub(/(require.*\n)/, "\\1#{capydash_config}")
92
+ else
93
+ content = capydash_config + content
94
+ end
95
+
96
+ File.write(test_helper_path, content)
97
+ say "Updated test/test_helper.rb with CapyDash configuration"
98
+ else
99
+ say "CapyDash already configured in test/test_helper.rb", :yellow
100
+ end
101
+ else
102
+ say "test/test_helper.rb not found. Please add CapyDash configuration manually.", :red
103
+ end
104
+ end
105
+
106
+
107
+ def show_instructions
108
+ say "\n" + "="*60, :green
109
+ say "CapyDash has been successfully installed!", :green
110
+ say "="*60, :green
111
+ say "\nNext steps:", :yellow
112
+ say "1. Run your tests: bundle exec rails test"
113
+ say "2. Generate report: bundle exec rake capydash:report"
114
+ say "3. View report: open capydash_report/index.html"
115
+ say "\nImportant:", :yellow
116
+ say "- CapyDash only captures system tests that use Capybara methods (visit, click, fill_in, etc.)"
117
+ say "- Unit tests and integration tests without Capybara won't appear in the report"
118
+ say "- Works with parallel testing - no configuration needed"
119
+ say "\nFor more information, see the README.md file."
120
+ say "="*60, :green
121
+ end
122
+ end
123
+ end
124
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: capydash
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Damon Clark
@@ -9,6 +9,20 @@ bindir: bin
9
9
  cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: railties
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '5.0'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '5.0'
12
26
  - !ruby/object:Gem::Dependency
13
27
  name: capybara
14
28
  requirement: !ruby/object:Gem::Requirement
@@ -119,6 +133,7 @@ files:
119
133
  - lib/capydash/test_data_aggregator.rb
120
134
  - lib/capydash/test_data_collector.rb
121
135
  - lib/capydash/version.rb
136
+ - lib/generators/capydash/install_generator.rb
122
137
  - lib/tasks/capydash.rake
123
138
  homepage: https://github.com/damonclark/capydash
124
139
  licenses: