simplecov-mcp 0.3.0 → 1.0.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 +4 -4
- data/LICENSE +21 -0
- data/README.md +173 -356
- data/docs/ADVANCED_USAGE.md +967 -0
- data/docs/ARCHITECTURE.md +79 -0
- data/docs/BRANCH_ONLY_COVERAGE.md +81 -0
- data/docs/CLI_USAGE.md +637 -0
- data/docs/DEVELOPMENT.md +82 -0
- data/docs/ERROR_HANDLING.md +93 -0
- data/docs/EXAMPLES.md +430 -0
- data/docs/INSTALLATION.md +352 -0
- data/docs/LIBRARY_API.md +635 -0
- data/docs/MCP_INTEGRATION.md +488 -0
- data/docs/TROUBLESHOOTING.md +276 -0
- data/docs/arch-decisions/001-x-arch-decision.md +93 -0
- data/docs/arch-decisions/002-x-arch-decision.md +157 -0
- data/docs/arch-decisions/003-x-arch-decision.md +163 -0
- data/docs/arch-decisions/004-x-arch-decision.md +199 -0
- data/docs/arch-decisions/005-x-arch-decision.md +187 -0
- data/docs/arch-decisions/README.md +60 -0
- data/docs/presentations/simplecov-mcp-presentation.md +249 -0
- data/exe/simplecov-mcp +4 -4
- data/lib/simplecov_mcp/app_context.rb +26 -0
- data/lib/simplecov_mcp/base_tool.rb +74 -0
- data/lib/simplecov_mcp/cli.rb +234 -0
- data/lib/simplecov_mcp/cli_config.rb +56 -0
- data/lib/simplecov_mcp/commands/base_command.rb +78 -0
- data/lib/simplecov_mcp/commands/command_factory.rb +39 -0
- data/lib/simplecov_mcp/commands/detailed_command.rb +24 -0
- data/lib/simplecov_mcp/commands/list_command.rb +13 -0
- data/lib/simplecov_mcp/commands/raw_command.rb +22 -0
- data/lib/simplecov_mcp/commands/summary_command.rb +24 -0
- data/lib/simplecov_mcp/commands/uncovered_command.rb +26 -0
- data/lib/simplecov_mcp/commands/version_command.rb +18 -0
- data/lib/simplecov_mcp/constants.rb +22 -0
- data/lib/simplecov_mcp/error_handler.rb +124 -0
- data/lib/simplecov_mcp/error_handler_factory.rb +31 -0
- data/lib/simplecov_mcp/errors.rb +179 -0
- data/lib/simplecov_mcp/formatters/source_formatter.rb +148 -0
- data/lib/simplecov_mcp/mcp_server.rb +40 -0
- data/lib/simplecov_mcp/mode_detector.rb +55 -0
- data/lib/simplecov_mcp/model.rb +300 -0
- data/lib/simplecov_mcp/option_normalizers.rb +92 -0
- data/lib/simplecov_mcp/option_parser_builder.rb +134 -0
- data/lib/simplecov_mcp/option_parsers/env_options_parser.rb +50 -0
- data/lib/simplecov_mcp/option_parsers/error_helper.rb +109 -0
- data/lib/simplecov_mcp/path_relativizer.rb +61 -0
- data/lib/simplecov_mcp/presenters/base_coverage_presenter.rb +44 -0
- data/lib/simplecov_mcp/presenters/coverage_detailed_presenter.rb +16 -0
- data/lib/simplecov_mcp/presenters/coverage_raw_presenter.rb +16 -0
- data/lib/simplecov_mcp/presenters/coverage_summary_presenter.rb +16 -0
- data/lib/simplecov_mcp/presenters/coverage_uncovered_presenter.rb +16 -0
- data/lib/simplecov_mcp/presenters/project_coverage_presenter.rb +52 -0
- data/lib/simplecov_mcp/resolvers/coverage_line_resolver.rb +126 -0
- data/lib/simplecov_mcp/resolvers/resolver_factory.rb +28 -0
- data/lib/simplecov_mcp/resolvers/resultset_path_resolver.rb +78 -0
- data/lib/simplecov_mcp/resultset_loader.rb +136 -0
- data/lib/simplecov_mcp/staleness_checker.rb +243 -0
- data/lib/{simple_cov_mcp → simplecov_mcp}/tools/all_files_coverage_tool.rb +31 -13
- data/lib/{simple_cov_mcp → simplecov_mcp}/tools/coverage_detailed_tool.rb +7 -7
- data/lib/{simple_cov_mcp → simplecov_mcp}/tools/coverage_raw_tool.rb +7 -7
- data/lib/{simple_cov_mcp → simplecov_mcp}/tools/coverage_summary_tool.rb +7 -7
- data/lib/simplecov_mcp/tools/coverage_table_tool.rb +90 -0
- data/lib/{simple_cov_mcp → simplecov_mcp}/tools/help_tool.rb +13 -4
- data/lib/{simple_cov_mcp → simplecov_mcp}/tools/uncovered_lines_tool.rb +7 -7
- data/lib/{simple_cov_mcp → simplecov_mcp}/tools/version_tool.rb +11 -3
- data/lib/simplecov_mcp/util.rb +82 -0
- data/lib/{simple_cov_mcp → simplecov_mcp}/version.rb +1 -1
- data/lib/simplecov_mcp.rb +144 -2
- data/spec/MCP_INTEGRATION_TESTS_README.md +111 -0
- data/spec/TIMESTAMPS.md +48 -0
- data/spec/all_files_coverage_tool_spec.rb +29 -25
- data/spec/base_tool_spec.rb +11 -10
- data/spec/cli/show_default_report_spec.rb +33 -0
- data/spec/cli_config_spec.rb +137 -0
- data/spec/cli_enumerated_options_spec.rb +68 -0
- data/spec/cli_error_spec.rb +105 -47
- data/spec/cli_source_spec.rb +82 -23
- data/spec/cli_spec.rb +140 -5
- data/spec/cli_success_predicate_spec.rb +141 -0
- data/spec/cli_table_spec.rb +1 -1
- data/spec/cli_usage_spec.rb +10 -26
- data/spec/commands/base_command_spec.rb +187 -0
- data/spec/commands/command_factory_spec.rb +72 -0
- data/spec/commands/detailed_command_spec.rb +48 -0
- data/spec/commands/raw_command_spec.rb +46 -0
- data/spec/commands/summary_command_spec.rb +47 -0
- data/spec/commands/uncovered_command_spec.rb +49 -0
- data/spec/constants_spec.rb +61 -0
- data/spec/coverage_table_tool_spec.rb +17 -33
- data/spec/error_handler_spec.rb +22 -13
- data/spec/error_mode_spec.rb +143 -0
- data/spec/errors_edge_cases_spec.rb +239 -0
- data/spec/errors_stale_spec.rb +2 -2
- data/spec/file_based_mcp_tools_spec.rb +99 -0
- data/spec/fixtures/project1/lib/bar.rb +0 -1
- data/spec/fixtures/project1/lib/foo.rb +0 -1
- data/spec/help_tool_spec.rb +11 -17
- data/spec/integration_spec.rb +845 -0
- data/spec/logging_fallback_spec.rb +128 -0
- data/spec/mcp_logging_spec.rb +44 -0
- data/spec/mcp_server_integration_spec.rb +23 -0
- data/spec/mcp_server_spec.rb +15 -4
- data/spec/mode_detector_spec.rb +148 -0
- data/spec/model_error_handling_spec.rb +210 -0
- data/spec/model_staleness_spec.rb +40 -10
- data/spec/option_normalizers_spec.rb +204 -0
- data/spec/option_parsers/env_options_parser_spec.rb +233 -0
- data/spec/option_parsers/error_helper_spec.rb +222 -0
- data/spec/path_relativizer_spec.rb +83 -0
- data/spec/presenters/coverage_detailed_presenter_spec.rb +19 -0
- data/spec/presenters/coverage_raw_presenter_spec.rb +15 -0
- data/spec/presenters/coverage_summary_presenter_spec.rb +15 -0
- data/spec/presenters/coverage_uncovered_presenter_spec.rb +16 -0
- data/spec/presenters/project_coverage_presenter_spec.rb +86 -0
- data/spec/resolvers/coverage_line_resolver_spec.rb +57 -0
- data/spec/resolvers/resolver_factory_spec.rb +61 -0
- data/spec/resolvers/resultset_path_resolver_spec.rb +55 -0
- data/spec/resultset_loader_spec.rb +167 -0
- data/spec/shared_examples/README.md +115 -0
- data/spec/shared_examples/coverage_presenter_examples.rb +66 -0
- data/spec/shared_examples/file_based_mcp_tools.rb +174 -0
- data/spec/shared_examples/mcp_tool_text_json_response.rb +16 -0
- data/spec/simple_cov_mcp_module_spec.rb +16 -0
- data/spec/simplecov_mcp_model_spec.rb +340 -9
- data/spec/simplecov_mcp_opts_spec.rb +182 -0
- data/spec/spec_helper.rb +147 -4
- data/spec/staleness_checker_spec.rb +373 -0
- data/spec/staleness_more_spec.rb +16 -13
- data/spec/support/mcp_runner.rb +64 -0
- data/spec/tools_error_handling_spec.rb +144 -0
- data/spec/util_spec.rb +109 -34
- data/spec/version_spec.rb +117 -9
- data/spec/version_tool_spec.rb +131 -10
- metadata +120 -63
- data/lib/simple_cov/mcp.rb +0 -9
- data/lib/simple_cov_mcp/base_tool.rb +0 -70
- data/lib/simple_cov_mcp/cli.rb +0 -390
- data/lib/simple_cov_mcp/error_handler.rb +0 -131
- data/lib/simple_cov_mcp/error_handler_factory.rb +0 -38
- data/lib/simple_cov_mcp/errors.rb +0 -176
- data/lib/simple_cov_mcp/mcp_server.rb +0 -30
- data/lib/simple_cov_mcp/model.rb +0 -104
- data/lib/simple_cov_mcp/staleness_checker.rb +0 -125
- data/lib/simple_cov_mcp/tools/coverage_table_tool.rb +0 -61
- data/lib/simple_cov_mcp/util.rb +0 -122
- data/lib/simple_cov_mcp.rb +0 -102
- data/spec/coverage_detailed_tool_spec.rb +0 -36
- data/spec/coverage_raw_tool_spec.rb +0 -32
- data/spec/coverage_summary_tool_spec.rb +0 -39
- data/spec/legacy_shim_spec.rb +0 -13
- data/spec/uncovered_lines_tool_spec.rb +0 -33
@@ -0,0 +1,99 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require_relative 'shared_examples/file_based_mcp_tools'
|
5
|
+
|
6
|
+
# Load all the tool classes that will be tested
|
7
|
+
require 'simplecov_mcp/tools/coverage_summary_tool'
|
8
|
+
require 'simplecov_mcp/tools/coverage_raw_tool'
|
9
|
+
require 'simplecov_mcp/tools/uncovered_lines_tool'
|
10
|
+
require 'simplecov_mcp/tools/coverage_detailed_tool'
|
11
|
+
|
12
|
+
RSpec.describe 'File-based MCP Tools' do
|
13
|
+
# Test each file-based tool using the shared example with its specific configuration
|
14
|
+
FILE_BASED_TOOL_CONFIGS.each do |tool_name, config|
|
15
|
+
describe config[:tool_class] do
|
16
|
+
it_behaves_like 'a file-based MCP tool', config
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Test that all file-based tools handle the same parameters consistently
|
21
|
+
describe 'parameter consistency' do
|
22
|
+
let(:server_context) { instance_double('ServerContext').as_null_object }
|
23
|
+
|
24
|
+
before do
|
25
|
+
setup_mcp_response_stub
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'all file-based tools accept the same basic parameters' do
|
29
|
+
# Test that all tools can be called with the same parameter signature
|
30
|
+
FILE_BASED_TOOL_CONFIGS.each do |tool_name, config|
|
31
|
+
model = instance_double(SimpleCovMcp::CoverageModel)
|
32
|
+
allow(SimpleCovMcp::CoverageModel).to receive(:new).and_return(model)
|
33
|
+
allow(model).to receive(config[:model_method]).and_return(config[:mock_data])
|
34
|
+
allow(model).to receive(:relativize) { |payload| payload }
|
35
|
+
allow(model).to receive(:staleness_for).and_return(false)
|
36
|
+
|
37
|
+
expect do
|
38
|
+
config[:tool_class].call(
|
39
|
+
path: 'lib/example.rb',
|
40
|
+
root: '.',
|
41
|
+
resultset: 'coverage',
|
42
|
+
server_context: server_context
|
43
|
+
)
|
44
|
+
end.not_to raise_error
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'all file-based tools return JSON resources with consistent structure' do
|
49
|
+
FILE_BASED_TOOL_CONFIGS.each do |tool_name, config|
|
50
|
+
model = instance_double(SimpleCovMcp::CoverageModel)
|
51
|
+
allow(SimpleCovMcp::CoverageModel).to receive(:new).and_return(model)
|
52
|
+
allow(model).to receive(config[:model_method]).and_return(config[:mock_data])
|
53
|
+
allow(model).to receive(:relativize) { |payload| payload }
|
54
|
+
allow(model).to receive(:staleness_for).and_return(false)
|
55
|
+
|
56
|
+
response = config[:tool_class].call(path: 'lib/foo.rb', server_context: server_context)
|
57
|
+
|
58
|
+
# All should have the same basic MCP text structure
|
59
|
+
expect(response.payload).to be_an(Array)
|
60
|
+
expect(response.payload.first['type']).to eq('text')
|
61
|
+
expect(response.payload.first).to have_key('text')
|
62
|
+
|
63
|
+
# All should return valid JSON
|
64
|
+
expect { JSON.parse(response.payload.first['text']) }.not_to raise_error
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Performance/behavior comparison tests
|
70
|
+
describe 'cross-tool consistency' do
|
71
|
+
let(:server_context) { instance_double('ServerContext').as_null_object }
|
72
|
+
|
73
|
+
before do
|
74
|
+
setup_mcp_response_stub
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'tools that include summary data return consistent summary format' do
|
78
|
+
summary_tools = FILE_BASED_TOOL_CONFIGS.select do |_, config|
|
79
|
+
config[:expected_keys].include?('summary')
|
80
|
+
end
|
81
|
+
|
82
|
+
summary_tools.each do |tool_name, config|
|
83
|
+
model = instance_double(SimpleCovMcp::CoverageModel)
|
84
|
+
allow(SimpleCovMcp::CoverageModel).to receive(:new).and_return(model)
|
85
|
+
allow(model).to receive(config[:model_method]).and_return(config[:mock_data])
|
86
|
+
allow(model).to receive(:relativize) { |payload| payload }
|
87
|
+
allow(model).to receive(:staleness_for).and_return(false)
|
88
|
+
|
89
|
+
response = config[:tool_class].call(path: 'lib/foo.rb', server_context: server_context)
|
90
|
+
data = JSON.parse(response.payload.first['text'])
|
91
|
+
|
92
|
+
if data.key?('summary')
|
93
|
+
expect(data['summary']).to include('covered', 'total', 'pct')
|
94
|
+
expect(data['summary']['pct']).to be_a(Numeric)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
data/spec/help_tool_spec.rb
CHANGED
@@ -1,21 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'spec_helper'
|
4
|
-
require '
|
4
|
+
require 'simplecov_mcp/tools/help_tool'
|
5
5
|
|
6
6
|
RSpec.describe SimpleCovMcp::Tools::HelpTool do
|
7
7
|
let(:server_context) { instance_double('ServerContext').as_null_object }
|
8
8
|
|
9
9
|
before do
|
10
|
-
|
11
|
-
attr_reader :payload, :meta
|
12
|
-
|
13
|
-
def initialize(payload)
|
14
|
-
@payload = payload
|
15
|
-
@meta = nil
|
16
|
-
end
|
17
|
-
end
|
18
|
-
stub_const('MCP::Tool::Response', response_class)
|
10
|
+
setup_mcp_response_stub
|
19
11
|
end
|
20
12
|
|
21
13
|
it 'returns guidance for each registered tool' do
|
@@ -23,24 +15,26 @@ RSpec.describe SimpleCovMcp::Tools::HelpTool do
|
|
23
15
|
expect(response.meta).to be_nil
|
24
16
|
|
25
17
|
payload = response.payload.first
|
26
|
-
expect(payload['type']).to eq('
|
27
|
-
|
28
|
-
data = JSON.parse(payload['resource']['text'])
|
18
|
+
expect(payload['type']).to eq('text')
|
19
|
+
data = JSON.parse(payload['text'])
|
29
20
|
tool_names = data['tools'].map { |entry| entry['tool'] }
|
30
21
|
|
31
|
-
expect(tool_names).to include('coverage_summary_tool', 'uncovered_lines_tool',
|
22
|
+
expect(tool_names).to include('coverage_summary_tool', 'uncovered_lines_tool',
|
23
|
+
'all_files_coverage_tool', 'coverage_table_tool', 'version_tool')
|
32
24
|
expect(data['tools']).to all(include('use_when', 'avoid_when', 'inputs', 'example'))
|
33
25
|
end
|
34
26
|
|
35
27
|
it 'filters entries when a query is provided' do
|
36
28
|
response = described_class.call(query: 'uncovered', server_context: server_context)
|
37
29
|
payload = response.payload.first
|
38
|
-
expect(payload['type']).to eq('
|
39
|
-
data = JSON.parse(payload['
|
30
|
+
expect(payload['type']).to eq('text')
|
31
|
+
data = JSON.parse(payload['text'])
|
40
32
|
|
41
33
|
expect(data['tools']).not_to be_empty
|
42
34
|
expect(data['tools']).to all(satisfy do |entry|
|
43
|
-
combined =
|
35
|
+
combined =
|
36
|
+
[entry['tool'], entry['label'], entry['use_when'], entry['avoid_when']]
|
37
|
+
.compact.join(' ').downcase
|
44
38
|
combined.include?('uncovered')
|
45
39
|
end)
|
46
40
|
expect(data['tools'].map { |entry| entry['tool'] }).to include('uncovered_lines_tool')
|