capydash 0.1.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 0d65145bed2681cec5831f3f5b8715c90f06fe94d7f88d3fa7c8cb85781ef8f7
4
+ data.tar.gz: 8fa286bd777abe9c901d34587bcefb5b25f6dad9d73bda2a7ee8b28419552634
5
+ SHA512:
6
+ metadata.gz: 0e329477548327159151a4a88a54bd12fd53444a6c3c7ca56381f88ca2042d08e6a6b0e7f365f38a15d97c3f61a347884a43a7c31d4791c7775cce7e6b9c09e7
7
+ data.tar.gz: f3fd9b929e4a0bbe145078fe48769280ab40b965099a0e2eb4a581e508963c2c84117009775544eaf9511c231eaf4a9ded96b6893faff543a93e336e311d8413
data/README.md ADDED
@@ -0,0 +1,286 @@
1
+ # CapyDash
2
+
3
+ A real-time test monitoring dashboard for Rails applications that provides live visualization of test execution with screenshots, step-by-step tracking, and comprehensive error reporting.
4
+
5
+ ## Features
6
+
7
+ - **Real-time Test Monitoring**: Watch tests execute live with WebSocket updates
8
+ - **Visual Test Flow**: See each test step with screenshots and detailed information
9
+ - **Hierarchical Organization**: Test classes → methods → individual steps
10
+ - **Screenshot Capture**: Automatic screenshots at each test step
11
+ - **Error Tracking**: Comprehensive error reporting and logging
12
+ - **Configurable**: YAML-based configuration system
13
+ - **Production Ready**: Built-in logging, error handling, and persistence
14
+
15
+ ## Quick Start
16
+
17
+ ### 1. Installation
18
+
19
+ #### Option A: Install from RubyGems (Recommended)
20
+
21
+ Add to your Gemfile:
22
+
23
+ ```ruby
24
+ gem 'capydash'
25
+ ```
26
+
27
+ Then run:
28
+
29
+ ```bash
30
+ bundle install
31
+ ```
32
+
33
+ #### Option B: Install from source
34
+
35
+ ```bash
36
+ git clone https://github.com/damonclark/capydash.git
37
+ cd capydash
38
+ bundle install
39
+ ```
40
+
41
+ #### Option C: Local development
42
+
43
+ For local development, add to your Gemfile:
44
+
45
+ ```ruby
46
+ gem 'capydash', path: '/path/to/capydash'
47
+ ```
48
+
49
+ ### 2. Configuration
50
+
51
+ Create a configuration file at `config/capydash.yml`:
52
+
53
+ ```yaml
54
+ # CapyDash Configuration
55
+ server:
56
+ host: "localhost"
57
+ port: 4000
58
+ max_connections: 100
59
+
60
+ dashboard:
61
+ title: "My Test Dashboard"
62
+ auto_scroll: true
63
+ show_timestamps: true
64
+
65
+ tests:
66
+ system_tests_dir: "test/system"
67
+ feature_tests_dir: "test/features"
68
+ screenshot_dir: "tmp/capydash_screenshots"
69
+
70
+ logging:
71
+ level: "info"
72
+ file: "log/capydash.log"
73
+
74
+ security:
75
+ enable_auth: false
76
+ secret_key: "your-secret-key-here"
77
+ ```
78
+
79
+ ### 3. Setup in Rails
80
+
81
+ Add to your `test/test_helper.rb`:
82
+
83
+ ```ruby
84
+ require 'capydash'
85
+
86
+ # CapyDash will automatically instrument your tests
87
+ ```
88
+
89
+ ### 4. Running Tests
90
+
91
+ #### Option A: Standalone Server (Recommended)
92
+
93
+ ```bash
94
+ # Terminal 1: Start the dashboard server
95
+ bundle exec rake capydash:server
96
+
97
+ # Terminal 2: Run tests with external WebSocket
98
+ CAPYDASH_EXTERNAL_WS=1 bundle exec rails test
99
+ ```
100
+
101
+ #### Option B: In-Process Server (Development)
102
+
103
+ ```bash
104
+ # Just run your tests - CapyDash starts automatically
105
+ bundle exec rails test
106
+ ```
107
+
108
+ ### 5. View Dashboard
109
+
110
+ Open your browser to `http://localhost:4000` to see the live test dashboard.
111
+
112
+ ## Configuration Options
113
+
114
+ ### Server Configuration
115
+
116
+ ```yaml
117
+ server:
118
+ host: "localhost" # Server host
119
+ port: 4000 # Server port
120
+ websocket_path: "/websocket" # WebSocket endpoint
121
+ max_connections: 100 # Max concurrent connections
122
+ message_history_limit: 1000 # Max messages to keep in memory
123
+ ```
124
+
125
+ ### Dashboard Configuration
126
+
127
+ ```yaml
128
+ dashboard:
129
+ title: "CapyDash Test Monitor" # Dashboard title
130
+ refresh_interval: 1000 # UI refresh rate (ms)
131
+ auto_scroll: true # Auto-scroll to latest step
132
+ show_timestamps: true # Show timestamps in UI
133
+ screenshot_quality: 0.8 # Screenshot compression (0.0-1.0)
134
+ max_screenshot_width: 1200 # Max screenshot width (px)
135
+ ```
136
+
137
+ ### Test Configuration
138
+
139
+ ```yaml
140
+ tests:
141
+ default_directory: "test" # Default test directory
142
+ system_tests_dir: "test/system" # System tests directory
143
+ feature_tests_dir: "test/features" # Feature tests directory
144
+ controller_tests_dir: "test/controllers" # Controller tests directory
145
+ model_tests_dir: "test/models" # Model tests directory
146
+ screenshot_dir: "tmp/capydash_screenshots" # Screenshot storage
147
+ timeout: 300 # Test timeout (seconds)
148
+ ```
149
+
150
+ ### Logging Configuration
151
+
152
+ ```yaml
153
+ logging:
154
+ level: "info" # Log level: debug, info, warn, error
155
+ file: "log/capydash.log" # Log file path
156
+ max_file_size: "10MB" # Max log file size
157
+ max_files: 5 # Number of log files to keep
158
+ ```
159
+
160
+ ### Security Configuration
161
+
162
+ ```yaml
163
+ security:
164
+ enable_auth: false # Enable authentication
165
+ secret_key: "your-secret-key-here" # Secret key for tokens
166
+ session_timeout: 3600 # Session timeout (seconds)
167
+ ```
168
+
169
+ ## Usage
170
+
171
+ ### Running Individual Test Classes
172
+
173
+ The dashboard allows you to run individual test classes by clicking the "Run" button next to each class. CapyDash automatically:
174
+
175
+ 1. Detects the test class name from the test method names
176
+ 2. Generates the appropriate file path (e.g., `NavigationTest` → `test/system/navigation_test.rb`)
177
+ 3. Executes the test with proper environment setup
178
+
179
+ ### Running All Tests
180
+
181
+ Click "Run All System Tests" to execute all system tests with live monitoring.
182
+
183
+ ### Viewing Test Results
184
+
185
+ - **Test Classes**: Top-level organization by test class
186
+ - **Test Methods**: Individual test methods within each class
187
+ - **Test Steps**: Detailed step-by-step execution with screenshots
188
+ - **Status Indicators**: Visual status for each level (PASSED/FAILED/RUNNING)
189
+ - **Error Details**: Comprehensive error information for failed tests
190
+
191
+ ## Development
192
+
193
+ ### Project Structure
194
+
195
+ ```
196
+ lib/capydash/
197
+ ├── engine.rb # Rails engine integration
198
+ ├── instrumentation.rb # Capybara method instrumentation
199
+ ├── dashboard_server.rb # WebSocket server
200
+ ├── event_emitter.rb # Event broadcasting
201
+ ├── forwarder.rb # External WebSocket forwarding
202
+ ├── configuration.rb # Configuration management
203
+ ├── logger.rb # Logging system
204
+ ├── error_handler.rb # Error handling
205
+ ├── persistence.rb # Data persistence
206
+ └── auth.rb # Authentication
207
+
208
+ dashboard/
209
+ ├── src/
210
+ │ └── App.jsx # React dashboard
211
+ └── public/ # Static assets
212
+
213
+ config/
214
+ └── capydash.yml # Configuration file
215
+ ```
216
+
217
+ ### Adding New Features
218
+
219
+ 1. **Configuration**: Add new options to `Configuration` class
220
+ 2. **Logging**: Use `CapyDash::Logger` for all logging
221
+ 3. **Error Handling**: Use `CapyDash::ErrorHandler` for error management
222
+ 4. **Persistence**: Use `CapyDash::Persistence` for data storage
223
+
224
+ ### Testing
225
+
226
+ ```bash
227
+ # Run the dummy app tests
228
+ cd spec/dummy_app
229
+ bundle exec rails test
230
+
231
+ # Run with CapyDash monitoring
232
+ CAPYDASH_EXTERNAL_WS=1 bundle exec rails test
233
+ ```
234
+
235
+ ## Troubleshooting
236
+
237
+ ### Common Issues
238
+
239
+ 1. **WebSocket Connection Failed**
240
+ - Check if port 4000 is available
241
+ - Verify firewall settings
242
+ - Check server logs for errors
243
+
244
+ 2. **Tests Not Appearing**
245
+ - Ensure `CAPYDASH_EXTERNAL_WS=1` is set
246
+ - Check that tests are in the correct directories
247
+ - Verify test class naming conventions
248
+
249
+ 3. **Screenshots Not Capturing**
250
+ - Check screenshot directory permissions
251
+ - Verify Capybara configuration
252
+ - Check available disk space
253
+
254
+ ### Debug Mode
255
+
256
+ Enable debug logging:
257
+
258
+ ```yaml
259
+ logging:
260
+ level: "debug"
261
+ ```
262
+
263
+ ### Logs
264
+
265
+ Check logs at:
266
+ - `log/capydash.log` - Application logs
267
+ - `tmp/capydash_screenshots/` - Screenshot storage
268
+ - `tmp/capydash_data/` - Test run persistence
269
+
270
+ ## Contributing
271
+
272
+ 1. Fork the repository
273
+ 2. Create a feature branch
274
+ 3. Make your changes
275
+ 4. Add tests
276
+ 5. Submit a pull request
277
+
278
+ ## License
279
+
280
+ MIT License - see LICENSE file for details.
281
+
282
+ ## Support
283
+
284
+ - GitHub Issues: [Report bugs and request features](https://github.com/damonclark/capydash/issues)
285
+ - Documentation: [Full documentation](https://github.com/damonclark/capydash/wiki)
286
+ - Examples: [Example configurations and usage](https://github.com/damonclark/capydash/examples)
data/capydash.gemspec ADDED
@@ -0,0 +1,30 @@
1
+ # capydash.gemspec
2
+ require_relative "lib/capydash/version"
3
+
4
+ Gem::Specification.new do |spec|
5
+ spec.name = "capydash"
6
+ spec.version = Capydash::VERSION
7
+ spec.authors = ["Damon Clark"]
8
+ spec.email = ["dclark312@gmail.com"]
9
+
10
+ spec.summary = "Real-time Capybara test dashboard"
11
+ spec.description = "CapyDash instruments Capybara tests and streams test steps, screenshots, and DOM snapshots to a live dashboard."
12
+ spec.homepage = "https://github.com/damonclark/capydash"
13
+ spec.license = "MIT"
14
+
15
+ # Specify which files should be added to the gem when it is released.
16
+ spec.files = Dir["lib/**/*", "bin/*", "README.md", "LICENSE*", "*.gemspec"]
17
+ spec.require_paths = ["lib"]
18
+
19
+ # Dependencies
20
+ spec.add_runtime_dependency "capybara", ">= 3.0"
21
+ spec.add_runtime_dependency "faye-websocket"
22
+ spec.add_runtime_dependency "eventmachine"
23
+ spec.add_runtime_dependency "em-websocket"
24
+
25
+ # Development dependencies
26
+ spec.add_development_dependency "rspec", "~> 3.0"
27
+ spec.add_development_dependency "rails", "~> 7.0"
28
+
29
+ spec.metadata["allowed_push_host"] = "https://rubygems.org"
30
+ end
@@ -0,0 +1,103 @@
1
+ require 'securerandom'
2
+ require 'digest'
3
+
4
+ module CapyDash
5
+ class Auth
6
+ class << self
7
+ def authenticate(username, password)
8
+ return false unless auth_enabled?
9
+
10
+ # Simple hardcoded credentials for MVP
11
+ # In production, this would connect to a proper user database
12
+ valid_credentials = {
13
+ 'admin' => 'capydash123',
14
+ 'developer' => 'test123',
15
+ 'viewer' => 'readonly123'
16
+ }
17
+
18
+ if valid_credentials[username] == password
19
+ token = generate_token(username)
20
+ Logger.info("User authenticated", {
21
+ username: username,
22
+ token: token[0..8] + "..."
23
+ })
24
+ token
25
+ else
26
+ Logger.warn("Authentication failed", {
27
+ username: username,
28
+ ip: current_ip
29
+ })
30
+ nil
31
+ end
32
+ end
33
+
34
+ def validate_token(token)
35
+ return false unless auth_enabled?
36
+ return false unless token && token.length > 10
37
+
38
+ # Simple token validation for MVP
39
+ # In production, this would use JWT or similar
40
+ begin
41
+ decoded = Base64.decode64(token)
42
+ parts = decoded.split(':')
43
+ return false unless parts.length == 3
44
+
45
+ username, timestamp, signature = parts
46
+ expected_signature = generate_signature(username, timestamp)
47
+
48
+ if signature == expected_signature
49
+ # Check if token is not expired (24 hours)
50
+ token_time = Time.at(timestamp.to_i)
51
+ if Time.now - token_time < 24 * 60 * 60
52
+ Logger.debug("Token validated", { username: username })
53
+ username
54
+ else
55
+ Logger.warn("Token expired", { username: username })
56
+ false
57
+ end
58
+ else
59
+ Logger.warn("Invalid token signature", { token: token[0..8] + "..." })
60
+ false
61
+ end
62
+ rescue => e
63
+ ErrorHandler.handle_error(e, {
64
+ error_type: 'authentication',
65
+ operation: 'validate_token'
66
+ })
67
+ false
68
+ end
69
+ end
70
+
71
+ def auth_enabled?
72
+ CapyDash.config.auth_enabled?
73
+ end
74
+
75
+ def require_auth!
76
+ return true unless auth_enabled?
77
+ # This would be called by middleware or controllers
78
+ # For now, just return true
79
+ true
80
+ end
81
+
82
+ private
83
+
84
+ def generate_token(username)
85
+ timestamp = Time.now.to_i.to_s
86
+ signature = generate_signature(username, timestamp)
87
+ token_data = "#{username}:#{timestamp}:#{signature}"
88
+ Base64.encode64(token_data).strip
89
+ end
90
+
91
+ def generate_signature(username, timestamp)
92
+ secret = CapyDash.config.secret_key
93
+ data = "#{username}:#{timestamp}:#{secret}"
94
+ Digest::SHA256.hexdigest(data)
95
+ end
96
+
97
+ def current_ip
98
+ # In a real app, this would get the actual IP
99
+ "127.0.0.1"
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,186 @@
1
+ module CapyDash
2
+ class Configuration
3
+ attr_accessor :server, :dashboard, :tests, :logging, :security, :performance
4
+
5
+ def initialize
6
+ @server = {
7
+ host: "localhost",
8
+ port: 4000,
9
+ websocket_path: "/websocket",
10
+ max_connections: 100,
11
+ message_history_limit: 1000
12
+ }
13
+
14
+ @dashboard = {
15
+ title: "CapyDash Test Monitor",
16
+ refresh_interval: 1000,
17
+ auto_scroll: true,
18
+ show_timestamps: true,
19
+ screenshot_quality: 0.8,
20
+ max_screenshot_width: 1200
21
+ }
22
+
23
+ @tests = {
24
+ default_directory: "test",
25
+ system_tests_dir: "test/system",
26
+ feature_tests_dir: "test/features",
27
+ controller_tests_dir: "test/controllers",
28
+ model_tests_dir: "test/models",
29
+ screenshot_dir: "tmp/capydash_screenshots",
30
+ timeout: 300
31
+ }
32
+
33
+ @logging = {
34
+ level: "info",
35
+ file: "log/capydash.log",
36
+ max_file_size: "10MB",
37
+ max_files: 5
38
+ }
39
+
40
+ @security = {
41
+ enable_auth: false,
42
+ secret_key: "your-secret-key-here",
43
+ session_timeout: 3600
44
+ }
45
+
46
+ @performance = {
47
+ enable_compression: true,
48
+ cleanup_interval: 300,
49
+ max_memory_usage: "512MB"
50
+ }
51
+ end
52
+
53
+ def self.load_from_file(config_path = nil)
54
+ config_path ||= File.join(Dir.pwd, "config", "capydash.yml")
55
+
56
+ if File.exist?(config_path)
57
+ require 'yaml'
58
+ yaml_config = YAML.load_file(config_path)
59
+
60
+ config = new
61
+ config.load_from_hash(yaml_config)
62
+ config
63
+ else
64
+ # Return default configuration if file doesn't exist
65
+ new
66
+ end
67
+ rescue => e
68
+ puts "Warning: Could not load configuration from #{config_path}: #{e.message}"
69
+ puts "Using default configuration."
70
+ new
71
+ end
72
+
73
+ def load_from_hash(hash)
74
+ @server.merge!(hash['server']) if hash['server']
75
+ @dashboard.merge!(hash['dashboard']) if hash['dashboard']
76
+ @tests.merge!(hash['tests']) if hash['tests']
77
+ @logging.merge!(hash['logging']) if hash['logging']
78
+ @security.merge!(hash['security']) if hash['security']
79
+ @performance.merge!(hash['performance']) if hash['performance']
80
+ end
81
+
82
+ def server_host
83
+ @server[:host]
84
+ end
85
+
86
+ def server_port
87
+ @server[:port]
88
+ end
89
+
90
+ def websocket_path
91
+ @server[:websocket_path]
92
+ end
93
+
94
+ def max_connections
95
+ @server[:max_connections]
96
+ end
97
+
98
+ def message_history_limit
99
+ @server[:message_history_limit]
100
+ end
101
+
102
+ def dashboard_title
103
+ @dashboard[:title]
104
+ end
105
+
106
+ def auto_scroll?
107
+ @dashboard[:auto_scroll]
108
+ end
109
+
110
+ def show_timestamps?
111
+ @dashboard[:show_timestamps]
112
+ end
113
+
114
+ def screenshot_quality
115
+ @dashboard[:screenshot_quality]
116
+ end
117
+
118
+ def max_screenshot_width
119
+ @dashboard[:max_screenshot_width]
120
+ end
121
+
122
+ def system_tests_dir
123
+ @tests[:system_tests_dir]
124
+ end
125
+
126
+ def feature_tests_dir
127
+ @tests[:feature_tests_dir]
128
+ end
129
+
130
+ def controller_tests_dir
131
+ @tests[:controller_tests_dir]
132
+ end
133
+
134
+ def model_tests_dir
135
+ @tests[:model_tests_dir]
136
+ end
137
+
138
+ def screenshot_dir
139
+ @tests[:screenshot_dir]
140
+ end
141
+
142
+ def test_timeout
143
+ @tests[:timeout]
144
+ end
145
+
146
+ def log_level
147
+ @logging[:level]
148
+ end
149
+
150
+ def log_file
151
+ @logging[:file]
152
+ end
153
+
154
+ def max_files
155
+ @logging[:max_files]
156
+ end
157
+
158
+ def max_file_size
159
+ @logging[:max_file_size]
160
+ end
161
+
162
+ def auth_enabled?
163
+ @security[:enable_auth]
164
+ end
165
+
166
+ def secret_key
167
+ @security[:secret_key]
168
+ end
169
+
170
+ def session_timeout
171
+ @security[:session_timeout]
172
+ end
173
+
174
+ def compression_enabled?
175
+ @performance[:enable_compression]
176
+ end
177
+
178
+ def cleanup_interval
179
+ @performance[:cleanup_interval]
180
+ end
181
+
182
+ def max_memory_usage
183
+ @performance[:max_memory_usage]
184
+ end
185
+ end
186
+ end