simplecov-mcp 1.0.0 → 2.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/README.md +98 -50
- data/docs/{ARCHITECTURE.md → dev/ARCHITECTURE.md} +11 -10
- data/docs/dev/BRANCH_ONLY_COVERAGE.md +158 -0
- data/docs/{DEVELOPMENT.md → dev/DEVELOPMENT.md} +2 -1
- data/docs/dev/README.md +10 -0
- data/docs/dev/RELEASING.md +146 -0
- data/docs/{arch-decisions → dev/arch-decisions}/001-x-arch-decision.md +3 -1
- data/docs/{arch-decisions → dev/arch-decisions}/002-x-arch-decision.md +7 -5
- data/docs/{arch-decisions → dev/arch-decisions}/003-x-arch-decision.md +2 -0
- data/docs/{arch-decisions → dev/arch-decisions}/004-x-arch-decision.md +6 -2
- data/docs/{arch-decisions → dev/arch-decisions}/005-x-arch-decision.md +4 -2
- data/docs/{arch-decisions → dev/arch-decisions}/README.md +3 -3
- data/docs/{presentations → dev/presentations}/simplecov-mcp-presentation.md +28 -22
- data/docs/fixtures/demo_project/README.md +9 -0
- data/docs/{ADVANCED_USAGE.md → user/ADVANCED_USAGE.md} +129 -319
- data/docs/user/CLI_FALLBACK_FOR_LLMS.md +34 -0
- data/docs/user/CLI_USAGE.md +750 -0
- data/docs/{ERROR_HANDLING.md → user/ERROR_HANDLING.md} +12 -12
- data/docs/user/EXAMPLES.md +588 -0
- data/docs/user/INSTALLATION.md +130 -0
- data/docs/{LIBRARY_API.md → user/LIBRARY_API.md} +90 -32
- data/docs/{MCP_INTEGRATION.md → user/MCP_INTEGRATION.md} +36 -34
- data/docs/user/README.md +14 -0
- data/docs/{TROUBLESHOOTING.md → user/TROUBLESHOOTING.md} +21 -100
- data/docs/user/V2-BREAKING-CHANGES.md +472 -0
- data/exe/simplecov-mcp +1 -1
- data/lib/simplecov_mcp/{cli_config.rb → app_config.rb} +12 -12
- data/lib/simplecov_mcp/app_context.rb +1 -1
- data/lib/simplecov_mcp/base_tool.rb +66 -38
- data/lib/simplecov_mcp/cli.rb +67 -123
- data/lib/simplecov_mcp/commands/base_command.rb +16 -27
- data/lib/simplecov_mcp/commands/command_factory.rb +8 -2
- data/lib/simplecov_mcp/commands/detailed_command.rb +16 -2
- data/lib/simplecov_mcp/commands/list_command.rb +1 -1
- data/lib/simplecov_mcp/commands/raw_command.rb +18 -2
- data/lib/simplecov_mcp/commands/summary_command.rb +20 -3
- data/lib/simplecov_mcp/commands/totals_command.rb +53 -0
- data/lib/simplecov_mcp/commands/uncovered_command.rb +24 -5
- data/lib/simplecov_mcp/commands/validate_command.rb +60 -0
- data/lib/simplecov_mcp/commands/version_command.rb +19 -4
- data/lib/simplecov_mcp/config_parser.rb +32 -0
- data/lib/simplecov_mcp/constants.rb +3 -3
- data/lib/simplecov_mcp/coverage_reporter.rb +31 -0
- data/lib/simplecov_mcp/error_handler.rb +81 -40
- data/lib/simplecov_mcp/error_handler_factory.rb +2 -2
- data/lib/simplecov_mcp/errors.rb +32 -20
- data/lib/simplecov_mcp/formatters/source_formatter.rb +23 -19
- data/lib/simplecov_mcp/formatters.rb +51 -0
- data/lib/simplecov_mcp/mcp_server.rb +9 -7
- data/lib/simplecov_mcp/mode_detector.rb +6 -5
- data/lib/simplecov_mcp/model.rb +122 -83
- data/lib/simplecov_mcp/option_normalizers.rb +39 -18
- data/lib/simplecov_mcp/option_parser_builder.rb +82 -65
- data/lib/simplecov_mcp/option_parsers/env_options_parser.rb +3 -5
- data/lib/simplecov_mcp/option_parsers/error_helper.rb +18 -17
- data/lib/simplecov_mcp/path_relativizer.rb +17 -14
- data/lib/simplecov_mcp/predicate_evaluator.rb +72 -0
- data/lib/simplecov_mcp/presenters/base_coverage_presenter.rb +1 -3
- data/lib/simplecov_mcp/presenters/coverage_detailed_presenter.rb +1 -3
- data/lib/simplecov_mcp/presenters/coverage_raw_presenter.rb +1 -3
- data/lib/simplecov_mcp/presenters/coverage_summary_presenter.rb +1 -3
- data/lib/simplecov_mcp/presenters/coverage_uncovered_presenter.rb +1 -3
- data/lib/simplecov_mcp/presenters/project_coverage_presenter.rb +1 -3
- data/lib/simplecov_mcp/presenters/project_totals_presenter.rb +27 -0
- data/lib/simplecov_mcp/resolvers/coverage_line_resolver.rb +14 -18
- data/lib/simplecov_mcp/resolvers/resultset_path_resolver.rb +7 -9
- data/lib/simplecov_mcp/resultset_loader.rb +20 -25
- data/lib/simplecov_mcp/staleness_checker.rb +50 -46
- data/lib/simplecov_mcp/table_formatter.rb +64 -0
- data/lib/simplecov_mcp/tools/all_files_coverage_tool.rb +20 -50
- data/lib/simplecov_mcp/tools/coverage_detailed_tool.rb +13 -7
- data/lib/simplecov_mcp/tools/coverage_raw_tool.rb +12 -7
- data/lib/simplecov_mcp/tools/coverage_summary_tool.rb +13 -8
- data/lib/simplecov_mcp/tools/coverage_table_tool.rb +20 -60
- data/lib/simplecov_mcp/tools/coverage_totals_tool.rb +44 -0
- data/lib/simplecov_mcp/tools/help_tool.rb +38 -66
- data/lib/simplecov_mcp/tools/uncovered_lines_tool.rb +13 -8
- data/lib/simplecov_mcp/tools/validate_tool.rb +72 -0
- data/lib/simplecov_mcp/tools/version_tool.rb +7 -14
- data/lib/simplecov_mcp/util.rb +18 -12
- data/lib/simplecov_mcp/version.rb +1 -1
- data/lib/simplecov_mcp.rb +23 -29
- data/spec/all_files_coverage_tool_spec.rb +4 -3
- data/spec/{cli_config_spec.rb → app_config_spec.rb} +31 -26
- data/spec/base_tool_spec.rb +17 -14
- data/spec/cli/show_default_report_spec.rb +2 -2
- data/spec/cli_enumerated_options_spec.rb +31 -9
- data/spec/cli_error_spec.rb +46 -23
- data/spec/cli_format_spec.rb +123 -0
- data/spec/cli_json_options_spec.rb +50 -0
- data/spec/cli_source_spec.rb +11 -63
- data/spec/cli_spec.rb +82 -97
- data/spec/cli_usage_spec.rb +15 -15
- data/spec/commands/base_command_spec.rb +12 -92
- data/spec/commands/command_factory_spec.rb +7 -3
- data/spec/commands/detailed_command_spec.rb +10 -24
- data/spec/commands/list_command_spec.rb +28 -0
- data/spec/commands/raw_command_spec.rb +43 -20
- data/spec/commands/summary_command_spec.rb +10 -23
- data/spec/commands/totals_command_spec.rb +34 -0
- data/spec/commands/uncovered_command_spec.rb +29 -23
- data/spec/commands/validate_command_spec.rb +213 -0
- data/spec/commands/version_command_spec.rb +38 -0
- data/spec/constants_spec.rb +3 -3
- data/spec/coverage_reporter_spec.rb +102 -0
- data/spec/coverage_table_tool_spec.rb +21 -10
- data/spec/coverage_totals_tool_spec.rb +37 -0
- data/spec/error_handler_spec.rb +120 -4
- data/spec/error_mode_spec.rb +18 -22
- data/spec/errors_edge_cases_spec.rb +101 -28
- data/spec/errors_stale_spec.rb +34 -0
- data/spec/file_based_mcp_tools_spec.rb +6 -6
- data/spec/fixtures/project1/lib/bar.rb +2 -0
- data/spec/fixtures/project1/lib/foo.rb +2 -0
- data/spec/help_tool_spec.rb +2 -18
- data/spec/integration_spec.rb +114 -170
- data/spec/logging_fallback_spec.rb +3 -3
- data/spec/mcp_server_integration_spec.rb +1 -1
- data/spec/mcp_server_spec.rb +70 -53
- data/spec/mode_detector_spec.rb +46 -41
- data/spec/model_error_handling_spec.rb +141 -82
- data/spec/model_staleness_spec.rb +13 -13
- data/spec/option_normalizers_spec.rb +111 -112
- data/spec/option_parsers/env_options_parser_spec.rb +25 -37
- data/spec/option_parsers/error_helper_spec.rb +56 -56
- data/spec/path_relativizer_spec.rb +15 -0
- data/spec/presenters/coverage_detailed_presenter_spec.rb +1 -1
- data/spec/presenters/coverage_summary_presenter_spec.rb +1 -1
- data/spec/presenters/coverage_uncovered_presenter_spec.rb +1 -1
- data/spec/presenters/project_coverage_presenter_spec.rb +9 -8
- data/spec/presenters/project_totals_presenter_spec.rb +144 -0
- data/spec/resolvers/coverage_line_resolver_spec.rb +261 -36
- data/spec/resolvers/resultset_path_resolver_spec.rb +13 -8
- data/spec/shared_examples/file_based_mcp_tools.rb +23 -18
- data/spec/shared_examples/formatted_command_examples.rb +64 -0
- data/spec/simple_cov_mcp_module_spec.rb +24 -3
- data/spec/simplecov_mcp/formatters/source_formatter_spec.rb +267 -0
- data/spec/simplecov_mcp/formatters_spec.rb +76 -0
- data/spec/simplecov_mcp/presenters/base_coverage_presenter_spec.rb +79 -0
- data/spec/simplecov_mcp_model_spec.rb +99 -49
- data/spec/simplecov_mcp_opts_spec.rb +42 -39
- data/spec/spec_helper.rb +27 -92
- data/spec/staleness_checker_spec.rb +10 -9
- data/spec/staleness_more_spec.rb +4 -4
- data/spec/support/cli_helpers.rb +22 -0
- data/spec/support/control_flow_helpers.rb +20 -0
- data/spec/support/fake_mcp.rb +40 -0
- data/spec/support/io_helpers.rb +29 -0
- data/spec/support/mcp_helpers.rb +35 -0
- data/spec/support/mcp_runner.rb +10 -8
- data/spec/support/mocking_helpers.rb +30 -0
- data/spec/table_format_spec.rb +70 -0
- data/spec/tools/validate_tool_spec.rb +132 -0
- data/spec/tools_error_handling_spec.rb +34 -48
- data/spec/util_spec.rb +5 -4
- data/spec/version_spec.rb +7 -7
- data/spec/version_tool_spec.rb +20 -22
- metadata +90 -23
- data/docs/BRANCH_ONLY_COVERAGE.md +0 -81
- data/docs/CLI_USAGE.md +0 -637
- data/docs/EXAMPLES.md +0 -430
- data/docs/INSTALLATION.md +0 -352
- data/spec/cli_success_predicate_spec.rb +0 -141
|
@@ -14,12 +14,8 @@ RSpec.describe SimpleCovMcp::Commands::BaseCommand do
|
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
# Expose protected methods for testing
|
|
17
|
-
def public_handle_with_path(args, name, &
|
|
18
|
-
handle_with_path(args, name, &
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def public_fetch_raw(model, path)
|
|
22
|
-
fetch_raw(model, path)
|
|
17
|
+
def public_handle_with_path(args, name, &)
|
|
18
|
+
handle_with_path(args, name, &)
|
|
23
19
|
end
|
|
24
20
|
end
|
|
25
21
|
end
|
|
@@ -33,8 +29,8 @@ RSpec.describe SimpleCovMcp::Commands::BaseCommand do
|
|
|
33
29
|
|
|
34
30
|
# Stub the block to raise Errno::ENOENT
|
|
35
31
|
expect do
|
|
36
|
-
test_command.public_handle_with_path(args, 'test') do |
|
|
37
|
-
raise Errno::ENOENT
|
|
32
|
+
test_command.public_handle_with_path(args, 'test') do |_path|
|
|
33
|
+
raise Errno::ENOENT, 'No such file or directory'
|
|
38
34
|
end
|
|
39
35
|
end.to raise_error(SimpleCovMcp::FileNotFoundError, 'File not found: lib/missing.rb')
|
|
40
36
|
end
|
|
@@ -43,8 +39,8 @@ RSpec.describe SimpleCovMcp::Commands::BaseCommand do
|
|
|
43
39
|
args = ['some/other/path.rb']
|
|
44
40
|
|
|
45
41
|
expect do
|
|
46
|
-
test_command.public_handle_with_path(args, 'test') do |
|
|
47
|
-
raise Errno::ENOENT
|
|
42
|
+
test_command.public_handle_with_path(args, 'test') do |_path|
|
|
43
|
+
raise Errno::ENOENT, 'No such file or directory'
|
|
48
44
|
end
|
|
49
45
|
end.to raise_error(SimpleCovMcp::FileNotFoundError, /some\/other\/path\.rb/)
|
|
50
46
|
end
|
|
@@ -56,8 +52,8 @@ RSpec.describe SimpleCovMcp::Commands::BaseCommand do
|
|
|
56
52
|
|
|
57
53
|
# Stub the block to raise Errno::EACCES
|
|
58
54
|
expect do
|
|
59
|
-
test_command.public_handle_with_path(args, 'test') do |
|
|
60
|
-
raise Errno::EACCES
|
|
55
|
+
test_command.public_handle_with_path(args, 'test') do |_path|
|
|
56
|
+
raise Errno::EACCES, 'Permission denied'
|
|
61
57
|
end
|
|
62
58
|
end.to raise_error(SimpleCovMcp::FilePermissionError, 'Permission denied: lib/secret.rb')
|
|
63
59
|
end
|
|
@@ -66,8 +62,8 @@ RSpec.describe SimpleCovMcp::Commands::BaseCommand do
|
|
|
66
62
|
args = ['/root/protected.rb']
|
|
67
63
|
|
|
68
64
|
expect do
|
|
69
|
-
test_command.public_handle_with_path(args, 'test') do |
|
|
70
|
-
raise Errno::EACCES
|
|
65
|
+
test_command.public_handle_with_path(args, 'test') do |_path|
|
|
66
|
+
raise Errno::EACCES, 'Permission denied'
|
|
71
67
|
end
|
|
72
68
|
end.to raise_error(SimpleCovMcp::FilePermissionError, /\/root\/protected\.rb/)
|
|
73
69
|
end
|
|
@@ -78,7 +74,7 @@ RSpec.describe SimpleCovMcp::Commands::BaseCommand do
|
|
|
78
74
|
args = []
|
|
79
75
|
|
|
80
76
|
expect do
|
|
81
|
-
test_command.public_handle_with_path(args, 'summary') do |
|
|
77
|
+
test_command.public_handle_with_path(args, 'summary') do |_path|
|
|
82
78
|
# Should not reach here
|
|
83
79
|
end
|
|
84
80
|
end.to raise_error(SimpleCovMcp::UsageError, /summary <path>/)
|
|
@@ -100,7 +96,7 @@ RSpec.describe SimpleCovMcp::Commands::BaseCommand do
|
|
|
100
96
|
it 'shifts the path from args' do
|
|
101
97
|
args = ['lib/foo.rb', 'extra', 'args']
|
|
102
98
|
|
|
103
|
-
test_command.public_handle_with_path(args, 'test') do |
|
|
99
|
+
test_command.public_handle_with_path(args, 'test') do |_path|
|
|
104
100
|
# Block execution
|
|
105
101
|
end
|
|
106
102
|
|
|
@@ -108,80 +104,4 @@ RSpec.describe SimpleCovMcp::Commands::BaseCommand do
|
|
|
108
104
|
end
|
|
109
105
|
end
|
|
110
106
|
end
|
|
111
|
-
|
|
112
|
-
describe '#fetch_raw' do
|
|
113
|
-
let(:model) { SimpleCovMcp::CoverageModel.new(root: root, resultset: 'coverage') }
|
|
114
|
-
|
|
115
|
-
context 'when model.raw_for raises an exception' do
|
|
116
|
-
it 'returns nil instead of propagating the error' do
|
|
117
|
-
# Stub model.raw_for to raise an exception
|
|
118
|
-
allow(model).to receive(:raw_for).and_raise(StandardError, 'Something went wrong')
|
|
119
|
-
|
|
120
|
-
result = test_command.public_fetch_raw(model, 'lib/nonexistent.rb')
|
|
121
|
-
|
|
122
|
-
expect(result).to be_nil
|
|
123
|
-
end
|
|
124
|
-
|
|
125
|
-
it 'handles RuntimeError' do
|
|
126
|
-
allow(model).to receive(:raw_for).and_raise(RuntimeError, 'Runtime error')
|
|
127
|
-
|
|
128
|
-
result = test_command.public_fetch_raw(model, 'lib/foo.rb')
|
|
129
|
-
|
|
130
|
-
expect(result).to be_nil
|
|
131
|
-
end
|
|
132
|
-
|
|
133
|
-
it 'handles ArgumentError' do
|
|
134
|
-
allow(model).to receive(:raw_for).and_raise(ArgumentError, 'Invalid argument')
|
|
135
|
-
|
|
136
|
-
result = test_command.public_fetch_raw(model, 'lib/foo.rb')
|
|
137
|
-
|
|
138
|
-
expect(result).to be_nil
|
|
139
|
-
end
|
|
140
|
-
end
|
|
141
|
-
|
|
142
|
-
context 'when successful' do
|
|
143
|
-
it 'returns the raw coverage data' do
|
|
144
|
-
result = test_command.public_fetch_raw(model, 'lib/foo.rb')
|
|
145
|
-
|
|
146
|
-
expect(result).to be_a(Hash)
|
|
147
|
-
expect(result).to have_key('lines')
|
|
148
|
-
expect(result['lines']).to be_an(Array)
|
|
149
|
-
end
|
|
150
|
-
|
|
151
|
-
it 'caches the result for subsequent calls' do
|
|
152
|
-
# First call should hit the model
|
|
153
|
-
expect(model).to receive(:raw_for).with('lib/foo.rb').once.and_call_original
|
|
154
|
-
|
|
155
|
-
result1 = test_command.public_fetch_raw(model, 'lib/foo.rb')
|
|
156
|
-
result2 = test_command.public_fetch_raw(model, 'lib/foo.rb')
|
|
157
|
-
|
|
158
|
-
expect(result1).to eq(result2)
|
|
159
|
-
end
|
|
160
|
-
|
|
161
|
-
it 'caches different paths separately' do
|
|
162
|
-
result1 = test_command.public_fetch_raw(model, 'lib/foo.rb')
|
|
163
|
-
result2 = test_command.public_fetch_raw(model, 'lib/bar.rb')
|
|
164
|
-
|
|
165
|
-
expect(result1).not_to eq(result2)
|
|
166
|
-
end
|
|
167
|
-
|
|
168
|
-
it 'does not cache nil results from exceptions' do
|
|
169
|
-
# Set up the stub to raise an error
|
|
170
|
-
call_count = 0
|
|
171
|
-
allow(model).to receive(:raw_for).with('lib/missing.rb') do
|
|
172
|
-
call_count += 1
|
|
173
|
-
raise StandardError, 'File not found'
|
|
174
|
-
end
|
|
175
|
-
|
|
176
|
-
result1 = test_command.public_fetch_raw(model, 'lib/missing.rb')
|
|
177
|
-
result2 = test_command.public_fetch_raw(model, 'lib/missing.rb')
|
|
178
|
-
|
|
179
|
-
expect(result1).to be_nil
|
|
180
|
-
expect(result2).to be_nil
|
|
181
|
-
# Note: Due to current implementation, nil results are NOT cached,
|
|
182
|
-
# so raw_for is called each time an exception occurs
|
|
183
|
-
expect(call_count).to eq(2)
|
|
184
|
-
end
|
|
185
|
-
end
|
|
186
|
-
end
|
|
187
107
|
end
|
|
@@ -13,7 +13,9 @@ RSpec.describe SimpleCovMcp::Commands::CommandFactory do
|
|
|
13
13
|
['summary', SimpleCovMcp::Commands::SummaryCommand],
|
|
14
14
|
['raw', SimpleCovMcp::Commands::RawCommand],
|
|
15
15
|
['uncovered', SimpleCovMcp::Commands::UncoveredCommand],
|
|
16
|
-
['detailed', SimpleCovMcp::Commands::DetailedCommand]
|
|
16
|
+
['detailed', SimpleCovMcp::Commands::DetailedCommand],
|
|
17
|
+
['totals', SimpleCovMcp::Commands::TotalsCommand],
|
|
18
|
+
['total', SimpleCovMcp::Commands::TotalsCommand] # Alias
|
|
17
19
|
].each do |command_name, command_class|
|
|
18
20
|
it "creates a #{command_class.name.split('::').last} for \"#{command_name}\"" do
|
|
19
21
|
command = described_class.create(command_name, cli_context)
|
|
@@ -27,7 +29,7 @@ RSpec.describe SimpleCovMcp::Commands::CommandFactory do
|
|
|
27
29
|
[
|
|
28
30
|
'invalid_cmd',
|
|
29
31
|
'invalid command',
|
|
30
|
-
/list
|
|
32
|
+
/list \| summary <path> \| raw <path> \| uncovered <path>/
|
|
31
33
|
],
|
|
32
34
|
[nil, 'nil command', nil],
|
|
33
35
|
['', 'empty string command', nil],
|
|
@@ -47,7 +49,7 @@ RSpec.describe SimpleCovMcp::Commands::CommandFactory do
|
|
|
47
49
|
commands = described_class.available_commands
|
|
48
50
|
expect(commands).to be_an(Array)
|
|
49
51
|
expect(commands).to contain_exactly('list', 'version', 'summary', 'raw', 'uncovered',
|
|
50
|
-
'detailed')
|
|
52
|
+
'detailed', 'totals', 'total', 'validate')
|
|
51
53
|
end
|
|
52
54
|
|
|
53
55
|
it 'returns the keys from COMMAND_MAP' do
|
|
@@ -67,6 +69,8 @@ RSpec.describe SimpleCovMcp::Commands::CommandFactory do
|
|
|
67
69
|
expect(described_class::COMMAND_MAP['raw']).to eq(SimpleCovMcp::Commands::RawCommand)
|
|
68
70
|
expect(described_class::COMMAND_MAP['uncovered']).to eq(SimpleCovMcp::Commands::UncoveredCommand)
|
|
69
71
|
expect(described_class::COMMAND_MAP['detailed']).to eq(SimpleCovMcp::Commands::DetailedCommand)
|
|
72
|
+
expect(described_class::COMMAND_MAP['totals']).to eq(SimpleCovMcp::Commands::TotalsCommand)
|
|
73
|
+
expect(described_class::COMMAND_MAP['total']).to eq(SimpleCovMcp::Commands::TotalsCommand)
|
|
70
74
|
end
|
|
71
75
|
end
|
|
72
76
|
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'spec_helper'
|
|
4
|
+
require_relative '../shared_examples/formatted_command_examples'
|
|
4
5
|
|
|
5
6
|
RSpec.describe SimpleCovMcp::Commands::DetailedCommand do
|
|
6
7
|
let(:root) { (FIXTURES_DIR / 'project1').to_s }
|
|
@@ -10,39 +11,24 @@ RSpec.describe SimpleCovMcp::Commands::DetailedCommand do
|
|
|
10
11
|
before do
|
|
11
12
|
cli_context.config.root = root
|
|
12
13
|
cli_context.config.resultset = 'coverage'
|
|
13
|
-
cli_context.config.
|
|
14
|
+
cli_context.config.format = :table
|
|
14
15
|
cli_context.config.source_mode = nil
|
|
15
16
|
end
|
|
16
17
|
|
|
17
18
|
describe '#execute' do
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
context 'with table format' do
|
|
20
|
+
it 'prints the detailed coverage table' do
|
|
21
|
+
output = capture_command_output(command, ['lib/foo.rb'])
|
|
20
22
|
|
|
21
|
-
|
|
22
|
-
command.execute(['lib/foo.rb'])
|
|
23
|
-
output = stdout.string
|
|
23
|
+
expect(output).to include('File: lib/foo.rb', 'Line', 'Covered')
|
|
24
24
|
end
|
|
25
|
-
|
|
26
|
-
expect(output).to include('File: lib/foo.rb')
|
|
27
|
-
expect(output).to include('Line')
|
|
28
|
-
expect(output).to include('Covered')
|
|
29
25
|
end
|
|
30
26
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
stub_staleness_check('L')
|
|
34
|
-
|
|
35
|
-
json_output = nil
|
|
36
|
-
silence_output do |stdout, _stderr|
|
|
37
|
-
command.execute(['lib/foo.rb'])
|
|
38
|
-
json_output = stdout.string
|
|
39
|
-
end
|
|
27
|
+
context 'with stale data' do
|
|
28
|
+
before { stub_staleness_check('L') }
|
|
40
29
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
expect(payload['lines']).to be_an(Array)
|
|
44
|
-
expect(payload['summary']).to include('covered' => 2, 'total' => 3, 'pct' => 66.67)
|
|
45
|
-
expect(payload['stale']).to eq('L')
|
|
30
|
+
it_behaves_like 'a command with formatted output', ['lib/foo.rb'],
|
|
31
|
+
{ 'file' => 'lib/foo.rb', 'lines' => nil, 'summary' => nil, 'stale' => 'L' }
|
|
46
32
|
end
|
|
47
33
|
end
|
|
48
34
|
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
require_relative '../shared_examples/formatted_command_examples'
|
|
5
|
+
|
|
6
|
+
RSpec.describe SimpleCovMcp::Commands::ListCommand do
|
|
7
|
+
let(:root) { (FIXTURES_DIR / 'project1').to_s }
|
|
8
|
+
let(:cli_context) { SimpleCovMcp::CoverageCLI.new }
|
|
9
|
+
let(:command) { described_class.new(cli_context) }
|
|
10
|
+
|
|
11
|
+
before do
|
|
12
|
+
cli_context.config.root = root
|
|
13
|
+
cli_context.config.resultset = 'coverage'
|
|
14
|
+
cli_context.config.format = :table
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
describe '#execute' do
|
|
18
|
+
context 'with table format' do
|
|
19
|
+
it 'outputs a formatted table' do
|
|
20
|
+
output = capture_command_output(command, [])
|
|
21
|
+
|
|
22
|
+
expect(output).to include('│', 'lib/foo.rb', 'lib/bar.rb')
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it_behaves_like 'a command with formatted output', [], ['files', 'counts']
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'spec_helper'
|
|
4
|
+
require_relative '../shared_examples/formatted_command_examples'
|
|
4
5
|
|
|
5
6
|
RSpec.describe SimpleCovMcp::Commands::RawCommand do
|
|
6
7
|
let(:root) { (FIXTURES_DIR / 'project1').to_s }
|
|
@@ -10,37 +11,59 @@ RSpec.describe SimpleCovMcp::Commands::RawCommand do
|
|
|
10
11
|
before do
|
|
11
12
|
cli_context.config.root = root
|
|
12
13
|
cli_context.config.resultset = 'coverage'
|
|
13
|
-
cli_context.config.
|
|
14
|
+
cli_context.config.format = :table
|
|
14
15
|
end
|
|
15
16
|
|
|
16
17
|
describe '#execute' do
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
context 'with table format' do
|
|
19
|
+
it 'prints the raw coverage lines for the requested file' do
|
|
20
|
+
output = capture_command_output(command, ['lib/foo.rb'])
|
|
19
21
|
|
|
20
|
-
|
|
21
|
-
command.execute(['lib/foo.rb'])
|
|
22
|
-
output = stdout.string
|
|
22
|
+
expect(output).to include('│', 'lib/foo.rb', 'Line', 'Coverage')
|
|
23
23
|
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
context 'when the file is fully covered' do
|
|
27
|
+
it 'still prints the raw table' do
|
|
28
|
+
mock_presenter(
|
|
29
|
+
SimpleCovMcp::Presenters::CoverageRawPresenter,
|
|
30
|
+
absolute_payload: {
|
|
31
|
+
'file' => 'lib/perfect.rb',
|
|
32
|
+
'lines' => [1, 1, 1],
|
|
33
|
+
'stale' => false
|
|
34
|
+
},
|
|
35
|
+
relative_path: 'lib/perfect.rb'
|
|
36
|
+
)
|
|
24
37
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
38
|
+
output = capture_command_output(command, ['lib/perfect.rb'])
|
|
39
|
+
|
|
40
|
+
expect(output).to include('│', '│ 1 │ 1 │')
|
|
41
|
+
expect(output).not_to include('All lines covered!')
|
|
42
|
+
end
|
|
28
43
|
end
|
|
29
44
|
|
|
30
|
-
|
|
31
|
-
cli_context.config.
|
|
32
|
-
stub_staleness_check('L')
|
|
45
|
+
context 'with JSON output' do
|
|
46
|
+
before { cli_context.config.format = :json }
|
|
33
47
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
48
|
+
it 'emits JSON with specific line data' do
|
|
49
|
+
stub_staleness_check('L') # Needed for stale data
|
|
50
|
+
|
|
51
|
+
output = capture_command_output(command, ['lib/foo.rb'])
|
|
52
|
+
|
|
53
|
+
payload = JSON.parse(output)
|
|
54
|
+
expect(payload['file']).to eq('lib/foo.rb')
|
|
55
|
+
expect(payload['lines']).to be_an(Array)
|
|
56
|
+
expect(payload['lines'][0]).to eq(1) # specific value
|
|
57
|
+
expect(payload['lines'][1]).to eq(0) # specific value
|
|
58
|
+
expect(payload['stale']).to eq('L')
|
|
38
59
|
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
context 'with stale data (other formats)' do
|
|
63
|
+
before { stub_staleness_check('L') }
|
|
39
64
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
expect(payload['lines']).to eq([1, 0, nil, 2])
|
|
43
|
-
expect(payload['stale']).to eq('L')
|
|
65
|
+
# Use an array for expected_json_keys as we don't need exact value matching for these generic format tests
|
|
66
|
+
it_behaves_like 'a command with formatted output', ['lib/foo.rb'], ['file', 'lines', 'stale']
|
|
44
67
|
end
|
|
45
68
|
end
|
|
46
69
|
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'spec_helper'
|
|
4
|
+
require_relative '../shared_examples/formatted_command_examples'
|
|
4
5
|
|
|
5
6
|
RSpec.describe SimpleCovMcp::Commands::SummaryCommand do
|
|
6
7
|
let(:root) { (FIXTURES_DIR / 'project1').to_s }
|
|
@@ -10,38 +11,24 @@ RSpec.describe SimpleCovMcp::Commands::SummaryCommand do
|
|
|
10
11
|
before do
|
|
11
12
|
cli_context.config.root = root
|
|
12
13
|
cli_context.config.resultset = 'coverage'
|
|
13
|
-
cli_context.config.
|
|
14
|
+
cli_context.config.format = :table
|
|
14
15
|
cli_context.config.source_mode = nil
|
|
15
16
|
end
|
|
16
17
|
|
|
17
18
|
describe '#execute' do
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
context 'with table format' do
|
|
20
|
+
it 'prints a coverage summary line with a relative path' do
|
|
21
|
+
output = capture_command_output(command, ['lib/foo.rb'])
|
|
20
22
|
|
|
21
|
-
|
|
22
|
-
command.execute(['lib/foo.rb'])
|
|
23
|
-
output = stdout.string
|
|
23
|
+
expect(output).to include('│', '66.67%', 'lib/foo.rb')
|
|
24
24
|
end
|
|
25
|
-
|
|
26
|
-
# Example match: " 66.67% 2/3 lib/foo.rb"
|
|
27
|
-
expect(output).to match(/66\.67%.*2\/3.*lib\/foo\.rb/)
|
|
28
25
|
end
|
|
29
26
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
stub_staleness_check('L')
|
|
33
|
-
|
|
34
|
-
json_output = nil
|
|
35
|
-
silence_output do |stdout, _stderr|
|
|
36
|
-
command.execute(['lib/foo.rb'])
|
|
37
|
-
json_output = stdout.string
|
|
38
|
-
end
|
|
27
|
+
context 'with stale data' do
|
|
28
|
+
before { stub_staleness_check('L') }
|
|
39
29
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
expect(payload['summary']).to include('covered' => 2, 'total' => 3, 'pct' => 66.67)
|
|
43
|
-
expect(payload).to have_key('stale')
|
|
44
|
-
expect(payload['stale']).to eq('L')
|
|
30
|
+
it_behaves_like 'a command with formatted output', ['lib/foo.rb'],
|
|
31
|
+
{ 'file' => 'lib/foo.rb', 'summary' => nil, 'stale' => 'L' }
|
|
45
32
|
end
|
|
46
33
|
end
|
|
47
34
|
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
require_relative '../shared_examples/formatted_command_examples'
|
|
5
|
+
|
|
6
|
+
RSpec.describe SimpleCovMcp::Commands::TotalsCommand do
|
|
7
|
+
let(:root) { (FIXTURES_DIR / 'project1').to_s }
|
|
8
|
+
let(:cli_context) { SimpleCovMcp::CoverageCLI.new }
|
|
9
|
+
let(:command) { described_class.new(cli_context) }
|
|
10
|
+
|
|
11
|
+
before do
|
|
12
|
+
cli_context.config.root = root
|
|
13
|
+
cli_context.config.resultset = 'coverage'
|
|
14
|
+
cli_context.config.format = :table
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
describe '#execute' do
|
|
18
|
+
context 'with table format' do
|
|
19
|
+
it 'prints aggregated totals for the project' do
|
|
20
|
+
output = capture_command_output(command, [])
|
|
21
|
+
|
|
22
|
+
expect(output).to include('│', 'Lines', '50.00%')
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it_behaves_like 'a command with formatted output', [], ['lines', 'files', 'percentage']
|
|
27
|
+
|
|
28
|
+
it 'raises when unexpected arguments are provided' do
|
|
29
|
+
expect do
|
|
30
|
+
command.execute(['extra'])
|
|
31
|
+
end.to raise_error(SimpleCovMcp::UsageError, include('totals'))
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'spec_helper'
|
|
4
|
+
require_relative '../shared_examples/formatted_command_examples'
|
|
4
5
|
|
|
5
6
|
RSpec.describe SimpleCovMcp::Commands::UncoveredCommand do
|
|
6
7
|
let(:root) { (FIXTURES_DIR / 'project1').to_s }
|
|
@@ -10,40 +11,45 @@ RSpec.describe SimpleCovMcp::Commands::UncoveredCommand do
|
|
|
10
11
|
before do
|
|
11
12
|
cli_context.config.root = root
|
|
12
13
|
cli_context.config.resultset = 'coverage'
|
|
13
|
-
cli_context.config.
|
|
14
|
+
cli_context.config.format = :table
|
|
14
15
|
cli_context.config.source_mode = nil
|
|
15
16
|
end
|
|
16
17
|
|
|
17
18
|
describe '#execute' do
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
context 'with table format' do
|
|
20
|
+
it 'prints uncovered line numbers with the summary' do
|
|
21
|
+
output = capture_command_output(command, ['lib/bar.rb'])
|
|
20
22
|
|
|
21
|
-
|
|
22
|
-
command.execute(['lib/foo.rb'])
|
|
23
|
-
output = stdout.string
|
|
23
|
+
expect(output).to include('│', 'lib/bar.rb', '33.33%')
|
|
24
24
|
end
|
|
25
|
-
|
|
26
|
-
expect(output).to include('File: lib/foo.rb')
|
|
27
|
-
expect(output).to include('Uncovered lines: 2')
|
|
28
|
-
# Example match: "Summary: 66.67% 2/3"
|
|
29
|
-
expect(output).to match(/Summary:\s+66\.67%.*2\/3/)
|
|
30
25
|
end
|
|
31
26
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
27
|
+
context 'when the file is fully covered' do
|
|
28
|
+
before do
|
|
29
|
+
mock_presenter(
|
|
30
|
+
SimpleCovMcp::Presenters::CoverageUncoveredPresenter,
|
|
31
|
+
absolute_payload: {
|
|
32
|
+
'file' => 'lib/perfect.rb',
|
|
33
|
+
'uncovered' => [],
|
|
34
|
+
'summary' => { 'covered' => 10, 'total' => 10, 'percentage' => 100.0 }
|
|
35
|
+
},
|
|
36
|
+
relative_path: 'lib/perfect.rb'
|
|
37
|
+
)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it 'prints a success message instead of a table' do
|
|
41
|
+
output = capture_command_output(command, ['lib/perfect.rb'])
|
|
35
42
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
command.execute(['lib/foo.rb'])
|
|
39
|
-
json_output = stdout.string
|
|
43
|
+
expect(output).to include('All lines covered!', '100.00%')
|
|
44
|
+
expect(output).not_to include('│')
|
|
40
45
|
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
context 'with stale data' do
|
|
49
|
+
before { stub_staleness_check('L') }
|
|
41
50
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
expect(payload['uncovered']).to eq([2])
|
|
45
|
-
expect(payload['summary']).to include('covered' => 2, 'total' => 3, 'pct' => 66.67)
|
|
46
|
-
expect(payload['stale']).to eq('L')
|
|
51
|
+
it_behaves_like 'a command with formatted output', ['lib/foo.rb'],
|
|
52
|
+
{ 'file' => 'lib/foo.rb', 'uncovered' => [2], 'summary' => nil, 'stale' => 'L' }
|
|
47
53
|
end
|
|
48
54
|
end
|
|
49
55
|
end
|