coverband 6.1.5 → 6.1.7

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.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/main.yml +4 -4
  3. data/README.md +123 -0
  4. data/agents.md +217 -0
  5. data/bin/coverband-mcp +42 -0
  6. data/changes.md +23 -0
  7. data/coverband/log.272267 +1 -0
  8. data/coverband.gemspec +3 -1
  9. data/lib/coverband/adapters/hash_redis_store.rb +1 -3
  10. data/lib/coverband/collectors/route_tracker.rb +1 -1
  11. data/lib/coverband/collectors/view_tracker.rb +21 -13
  12. data/lib/coverband/configuration.rb +57 -18
  13. data/lib/coverband/integrations/resque.rb +2 -2
  14. data/lib/coverband/mcp/http_handler.rb +118 -0
  15. data/lib/coverband/mcp/server.rb +116 -0
  16. data/lib/coverband/mcp/tools/get_coverage_summary.rb +41 -0
  17. data/lib/coverband/mcp/tools/get_dead_methods.rb +69 -0
  18. data/lib/coverband/mcp/tools/get_file_coverage.rb +72 -0
  19. data/lib/coverband/mcp/tools/get_route_tracker_data.rb +60 -0
  20. data/lib/coverband/mcp/tools/get_translation_tracker_data.rb +60 -0
  21. data/lib/coverband/mcp/tools/get_uncovered_files.rb +73 -0
  22. data/lib/coverband/mcp/tools/get_view_tracker_data.rb +60 -0
  23. data/lib/coverband/mcp.rb +27 -0
  24. data/lib/coverband/reporters/base.rb +2 -4
  25. data/lib/coverband/reporters/web.rb +17 -14
  26. data/lib/coverband/utils/lines_classifier.rb +1 -1
  27. data/lib/coverband/utils/railtie.rb +1 -1
  28. data/lib/coverband/utils/result.rb +2 -1
  29. data/lib/coverband/utils/source_file.rb +5 -5
  30. data/lib/coverband/utils/tasks.rb +31 -0
  31. data/lib/coverband/version.rb +1 -1
  32. data/lib/coverband.rb +7 -7
  33. data/test/benchmarks/benchmark.rake +7 -15
  34. data/test/coverband/file_store_integration_test.rb +72 -0
  35. data/test/coverband/file_store_redis_error_test.rb +56 -0
  36. data/test/coverband/github_issue_586_test.rb +46 -0
  37. data/test/coverband/initialization_timing_test.rb +71 -0
  38. data/test/coverband/mcp/http_handler_test.rb +159 -0
  39. data/test/coverband/mcp/security_test.rb +145 -0
  40. data/test/coverband/mcp/server_test.rb +125 -0
  41. data/test/coverband/mcp/tools/get_coverage_summary_test.rb +75 -0
  42. data/test/coverband/mcp/tools/get_dead_methods_test.rb +162 -0
  43. data/test/coverband/mcp/tools/get_file_coverage_test.rb +159 -0
  44. data/test/coverband/mcp/tools/get_route_tracker_data_test.rb +122 -0
  45. data/test/coverband/mcp/tools/get_translation_tracker_data_test.rb +122 -0
  46. data/test/coverband/mcp/tools/get_uncovered_files_test.rb +177 -0
  47. data/test/coverband/mcp/tools/get_view_tracker_data_test.rb +122 -0
  48. data/test/coverband/reporters/web_test.rb +5 -0
  49. data/test/coverband/track_key_test.rb +9 -9
  50. data/test/coverband/tracker_initialization_test.rb +75 -0
  51. data/test/coverband/user_environment_simulation_test.rb +75 -0
  52. data/test/coverband/utils/lines_classifier_test.rb +1 -1
  53. data/test/integration/mcp_integration_test.rb +175 -0
  54. data/test/test_helper.rb +4 -5
  55. metadata +67 -11
@@ -0,0 +1,175 @@
1
+ # frozen_string_literal: true
2
+
3
+ require File.expand_path("../test_helper", File.dirname(__FILE__))
4
+
5
+ begin
6
+ require "coverband/mcp"
7
+ rescue LoadError
8
+ puts "MCP gem not available, skipping MCP integration tests"
9
+ end
10
+
11
+ if defined?(Coverband::MCP)
12
+ class MCPIntegrationTest < Minitest::Test
13
+ def setup
14
+ super
15
+ Coverband.configure do |config|
16
+ config.store = Coverband::Adapters::RedisStore.new(Redis.new(db: 2))
17
+ config.mcp_enabled = true # Enable MCP for testing
18
+ end
19
+
20
+ # Populate some test coverage data
21
+ store = Coverband.configuration.store
22
+ coverage_data = {
23
+ "/app/models/user.rb" => [1, 1, 0, 1, nil, 1, 0],
24
+ "/app/models/order.rb" => [1, 1, 1, 1, 1]
25
+ }
26
+ store.save_report(coverage_data)
27
+
28
+ @server = Coverband::MCP::Server.new
29
+ end
30
+
31
+ def teardown
32
+ super
33
+ Coverband.configuration.store&.clear!
34
+ end
35
+
36
+ test "MCP integration with dependency checking" do
37
+ # Test that all components load correctly together
38
+ refute_nil @server
39
+ refute_nil @server.mcp_server
40
+ refute_empty @server.mcp_server.tools
41
+ end
42
+
43
+ test "end-to-end MCP request handling via server" do
44
+ # Simulate an MCP request for coverage summary
45
+ json_request = {
46
+ "jsonrpc" => "2.0",
47
+ "method" => "tools/call",
48
+ "params" => {
49
+ "name" => "Get Coverage Summary",
50
+ "arguments" => {}
51
+ },
52
+ "id" => 1
53
+ }
54
+
55
+ # This should work without throwing exceptions
56
+ response = @server.handle_json(json_request.to_json)
57
+
58
+ # Basic validation that we got a response
59
+ refute_nil response
60
+ end
61
+
62
+ test "MCP tools integrate correctly with Coverband configuration" do
63
+ # Test that tools can access Coverband store and configuration
64
+ assert_respond_to Coverband.configuration, :store
65
+ assert_respond_to Coverband.configuration.store, :coverage
66
+
67
+ # Verify each tool class is properly defined
68
+ [
69
+ Coverband::MCP::Tools::GetCoverageSummary,
70
+ Coverband::MCP::Tools::GetFileCoverage,
71
+ Coverband::MCP::Tools::GetUncoveredFiles,
72
+ Coverband::MCP::Tools::GetDeadMethods,
73
+ Coverband::MCP::Tools::GetViewTrackerData,
74
+ Coverband::MCP::Tools::GetRouteTrackerData,
75
+ Coverband::MCP::Tools::GetTranslationTrackerData
76
+ ].each do |tool_class|
77
+ assert_respond_to tool_class, :call
78
+ assert_respond_to tool_class, :title
79
+ assert_respond_to tool_class, :description
80
+ assert_respond_to tool_class, :input_schema
81
+ end
82
+ end
83
+
84
+ test "HTTP handler integrates with MCP server" do
85
+ handler = Coverband::MCP::HttpHandler.new
86
+
87
+ # Verify handler can create and use MCP server
88
+ server = handler.send(:mcp_server)
89
+ assert_instance_of Coverband::MCP::Server, server
90
+
91
+ # Verify handler responds to rack interface
92
+ assert_respond_to handler, :call
93
+ end
94
+
95
+ test "bin/coverband-mcp executable dependencies" do
96
+ # Test that the executable can be loaded
97
+ executable_path = File.expand_path("../../bin/coverband-mcp", File.dirname(__FILE__))
98
+ assert File.exist?(executable_path), "Executable should exist"
99
+ assert File.executable?(executable_path), "File should be executable"
100
+
101
+ # Read the content to verify it requires the right modules
102
+ content = File.read(executable_path)
103
+ assert_includes content, 'require "coverband/mcp"'
104
+ assert_includes content, "Coverband::MCP::Server.new"
105
+ end
106
+
107
+ test "MCP module properly handles missing dependencies" do
108
+ # Temporarily hide the MCP module to test error handling
109
+ if defined?(::MCP)
110
+ original_mcp = ::MCP
111
+ Object.send(:remove_const, :MCP)
112
+ end
113
+
114
+ begin
115
+ # This should raise a LoadError with helpful message when requiring
116
+ error = assert_raises(NameError) do
117
+ # Force re-evaluation of the conditional
118
+ eval("Coverband::MCP::Server.new", binding, __FILE__, __LINE__)
119
+ end
120
+
121
+ assert_includes error.message, "MCP"
122
+ ensure
123
+ # Restore the constant
124
+ if defined?(original_mcp)
125
+ Object.const_set(:MCP, original_mcp)
126
+ end
127
+ end
128
+ end
129
+
130
+ test "all tools return properly formatted MCP responses" do
131
+ # Test that each tool returns a valid MCP::Tool::Response
132
+ tools = [
133
+ [Coverband::MCP::Tools::GetCoverageSummary, {}],
134
+ [Coverband::MCP::Tools::GetFileCoverage, {filename: "user.rb"}],
135
+ [Coverband::MCP::Tools::GetUncoveredFiles, {threshold: 50}],
136
+ [Coverband::MCP::Tools::GetDeadMethods, {}],
137
+ [Coverband::MCP::Tools::GetViewTrackerData, {}],
138
+ [Coverband::MCP::Tools::GetRouteTrackerData, {}],
139
+ [Coverband::MCP::Tools::GetTranslationTrackerData, {}]
140
+ ]
141
+
142
+ tools.each do |tool_class, params|
143
+ response = tool_class.call(**params, server_context: {})
144
+
145
+ assert_instance_of ::MCP::Tool::Response, response,
146
+ "#{tool_class} should return MCP::Tool::Response"
147
+ assert_respond_to response, :content
148
+ assert response.content.is_a?(Array), "Content should be an array"
149
+
150
+ # Check content structure
151
+ assert response.content.length > 0, "Responses should have content"
152
+ assert_equal "text", response.content.first[:type],
153
+ "Content should have text type"
154
+ rescue => e
155
+ # Some tools may fail due to missing features/config, but should handle gracefully
156
+ flunk "#{tool_class} raised unhandled exception: #{e.class}: #{e.message}"
157
+ end
158
+ end
159
+
160
+ test "MCP server transport configurations" do
161
+ # Test that server can be configured for different transports
162
+ server = Coverband::MCP::Server.new
163
+
164
+ # STDIO transport
165
+ transport_mock = mock("stdio_transport")
166
+ transport_mock.expects(:open).once
167
+ ::MCP::Server::Transports::StdioTransport.expects(:new).returns(transport_mock)
168
+
169
+ server.run_stdio
170
+
171
+ # HTTP transport setup (without actually starting server)
172
+ assert_equal 9023, Coverband::MCP::Server::DEFAULT_HTTP_PORT
173
+ end
174
+ end
175
+ end
data/test/test_helper.rb CHANGED
@@ -5,11 +5,11 @@ require "bigdecimal"
5
5
  original_verbosity = $VERBOSE
6
6
  $VERBOSE = nil
7
7
 
8
- $SKIP_SIMPLECOV = true
8
+ SKIP_SIMPLECOV = true
9
9
 
10
10
  require "rubygems"
11
11
 
12
- unless $SKIP_SIMPLECOV
12
+ unless SKIP_SIMPLECOV
13
13
  require "simplecov"
14
14
  require "coveralls"
15
15
  end
@@ -37,7 +37,7 @@ require "spy/integration"
37
37
  require_relative "unique_files"
38
38
  $VERBOSE = original_verbosity
39
39
 
40
- unless ENV["ONESHOT"] || $SKIP_SIMPLECOV
40
+ unless ENV["ONESHOT"] || SKIP_SIMPLECOV
41
41
  SimpleCov.formatter = Coveralls::SimpleCov::Formatter
42
42
  SimpleCov.start do
43
43
  add_filter "test/forked"
@@ -88,8 +88,7 @@ $LOAD_PATH.unshift(File.dirname(__FILE__))
88
88
 
89
89
  Mocha.configure do |c|
90
90
  c.stubbing_method_unnecessarily = :prevent
91
- c.stubbing_method_on_non_mock_object = :allow
92
- c.stubbing_method_on_nil = :prevent
91
+ c.stubbing_non_public_method = :allow
93
92
  end
94
93
 
95
94
  def test(name, &block)
metadata CHANGED
@@ -1,15 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: coverband
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.1.5
4
+ version: 6.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dan Mayer
8
8
  - Karl Baum
9
- autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2025-04-10 00:00:00.000000000 Z
11
+ date: 1980-01-02 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: benchmark-ips
@@ -25,6 +24,20 @@ dependencies:
25
24
  - - ">="
26
25
  - !ruby/object:Gem::Version
27
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: benchmark
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
28
41
  - !ruby/object:Gem::Dependency
29
42
  name: capybara
30
43
  requirement: !ruby/object:Gem::Requirement
@@ -85,16 +98,16 @@ dependencies:
85
98
  name: minitest
86
99
  requirement: !ruby/object:Gem::Requirement
87
100
  requirements:
88
- - - ">="
101
+ - - "~>"
89
102
  - !ruby/object:Gem::Version
90
- version: '0'
103
+ version: '5.0'
91
104
  type: :development
92
105
  prerelease: false
93
106
  version_requirements: !ruby/object:Gem::Requirement
94
107
  requirements:
95
- - - ">="
108
+ - - "~>"
96
109
  - !ruby/object:Gem::Version
97
- version: '0'
110
+ version: '5.0'
98
111
  - !ruby/object:Gem::Dependency
99
112
  name: minitest-fork_executor
100
113
  requirement: !ruby/object:Gem::Requirement
@@ -263,6 +276,20 @@ dependencies:
263
276
  - - ">="
264
277
  - !ruby/object:Gem::Version
265
278
  version: '0'
279
+ - !ruby/object:Gem::Dependency
280
+ name: mcp
281
+ requirement: !ruby/object:Gem::Requirement
282
+ requirements:
283
+ - - ">="
284
+ - !ruby/object:Gem::Version
285
+ version: '0'
286
+ type: :development
287
+ prerelease: false
288
+ version_requirements: !ruby/object:Gem::Requirement
289
+ requirements:
290
+ - - ">="
291
+ - !ruby/object:Gem::Version
292
+ version: '0'
266
293
  - !ruby/object:Gem::Dependency
267
294
  name: redis
268
295
  requirement: !ruby/object:Gem::Requirement
@@ -294,7 +321,8 @@ dependencies:
294
321
  description: Rack middleware to measure production code usage (LOC runtime usage)
295
322
  email:
296
323
  - dan@mayerdan.com
297
- executables: []
324
+ executables:
325
+ - coverband-mcp
298
326
  extensions: []
299
327
  extra_rdoc_files: []
300
328
  files:
@@ -317,9 +345,12 @@ files:
317
345
  - LICENSE
318
346
  - README.md
319
347
  - Rakefile
348
+ - agents.md
349
+ - bin/coverband-mcp
320
350
  - changes.md
321
351
  - config.ru
322
352
  - coverband.gemspec
353
+ - coverband/log.272267
323
354
  - diagram.svg
324
355
  - lib/alternative_coverband_patch.rb
325
356
  - lib/coverband.rb
@@ -346,6 +377,16 @@ files:
346
377
  - lib/coverband/integrations/report_middleware.rb
347
378
  - lib/coverband/integrations/resque.rb
348
379
  - lib/coverband/integrations/sidekiq_swarm.rb
380
+ - lib/coverband/mcp.rb
381
+ - lib/coverband/mcp/http_handler.rb
382
+ - lib/coverband/mcp/server.rb
383
+ - lib/coverband/mcp/tools/get_coverage_summary.rb
384
+ - lib/coverband/mcp/tools/get_dead_methods.rb
385
+ - lib/coverband/mcp/tools/get_file_coverage.rb
386
+ - lib/coverband/mcp/tools/get_route_tracker_data.rb
387
+ - lib/coverband/mcp/tools/get_translation_tracker_data.rb
388
+ - lib/coverband/mcp/tools/get_uncovered_files.rb
389
+ - lib/coverband/mcp/tools/get_view_tracker_data.rb
349
390
  - lib/coverband/reporters/base.rb
350
391
  - lib/coverband/reporters/console_report.rb
351
392
  - lib/coverband/reporters/html_report.rb
@@ -423,18 +464,34 @@ files:
423
464
  - test/coverband/collectors/view_tracker_test.rb
424
465
  - test/coverband/configuration_test.rb
425
466
  - test/coverband/coverband_test.rb
467
+ - test/coverband/file_store_integration_test.rb
468
+ - test/coverband/file_store_redis_error_test.rb
469
+ - test/coverband/github_issue_586_test.rb
470
+ - test/coverband/initialization_timing_test.rb
426
471
  - test/coverband/integrations/background_middleware_test.rb
427
472
  - test/coverband/integrations/background_test.rb
428
473
  - test/coverband/integrations/rack_server_check_test.rb
429
474
  - test/coverband/integrations/report_middleware_test.rb
430
475
  - test/coverband/integrations/resque_worker_test.rb
431
476
  - test/coverband/integrations/test_resque_job.rb
477
+ - test/coverband/mcp/http_handler_test.rb
478
+ - test/coverband/mcp/security_test.rb
479
+ - test/coverband/mcp/server_test.rb
480
+ - test/coverband/mcp/tools/get_coverage_summary_test.rb
481
+ - test/coverband/mcp/tools/get_dead_methods_test.rb
482
+ - test/coverband/mcp/tools/get_file_coverage_test.rb
483
+ - test/coverband/mcp/tools/get_route_tracker_data_test.rb
484
+ - test/coverband/mcp/tools/get_translation_tracker_data_test.rb
485
+ - test/coverband/mcp/tools/get_uncovered_files_test.rb
486
+ - test/coverband/mcp/tools/get_view_tracker_data_test.rb
432
487
  - test/coverband/reporters/base_test.rb
433
488
  - test/coverband/reporters/console_test.rb
434
489
  - test/coverband/reporters/html_test.rb
435
490
  - test/coverband/reporters/json_test.rb
436
491
  - test/coverband/reporters/web_test.rb
437
492
  - test/coverband/track_key_test.rb
493
+ - test/coverband/tracker_initialization_test.rb
494
+ - test/coverband/user_environment_simulation_test.rb
438
495
  - test/coverband/utils/absolute_file_converter_test.rb
439
496
  - test/coverband/utils/dead_methods_test.rb
440
497
  - test/coverband/utils/file_hasher_test.rb
@@ -466,6 +523,7 @@ files:
466
523
  - test/integration/full_stack_deferred_eager_test.rb
467
524
  - test/integration/full_stack_send_deferred_eager_test.rb
468
525
  - test/integration/full_stack_test.rb
526
+ - test/integration/mcp_integration_test.rb
469
527
  - test/jruby_check.rb
470
528
  - test/rails7_dummy/Rakefile
471
529
  - test/rails7_dummy/app/controllers/dummy_controller.rb
@@ -517,7 +575,6 @@ metadata:
517
575
  documentation_uri: https://github.com/danmayer/coverband
518
576
  changelog_uri: https://github.com/danmayer/coverband/blob/main/changes.md
519
577
  source_code_uri: https://github.com/danmayer/coverband
520
- post_install_message:
521
578
  rdoc_options: []
522
579
  require_paths:
523
580
  - lib
@@ -532,8 +589,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
532
589
  - !ruby/object:Gem::Version
533
590
  version: '0'
534
591
  requirements: []
535
- rubygems_version: 3.4.10
536
- signing_key:
592
+ rubygems_version: 3.6.9
537
593
  specification_version: 4
538
594
  summary: Rack middleware to measure production code usage (LOC runtime usage)
539
595
  test_files: []