cov-loupe 3.0.0 → 4.0.0.pre

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 (281) hide show
  1. checksums.yaml +4 -4
  2. data/AGENTS.md +230 -0
  3. data/CLAUDE.md +5 -0
  4. data/CODE_OF_CONDUCT.md +62 -0
  5. data/CONTRIBUTING.md +102 -0
  6. data/GEMINI.md +5 -0
  7. data/README.md +154 -51
  8. data/RELEASE_NOTES.md +452 -0
  9. data/dev/images/cov-loupe-icon-lores.png +0 -0
  10. data/dev/images/cov-loupe-icon-square.png +0 -0
  11. data/dev/images/cov-loupe-icon.png +0 -0
  12. data/dev/images/cov-loupe-logo.png +0 -0
  13. data/dev/prompts/README.md +74 -0
  14. data/dev/prompts/archive/architectural-review-and-actions-prompt.md +53 -0
  15. data/dev/prompts/archive/investigate-and-report-issues-prompt.md +33 -0
  16. data/dev/prompts/archive/produce-action-items-prompt.md +25 -0
  17. data/dev/prompts/guidelines/ai-code-evaluator-guidelines.md +337 -0
  18. data/dev/prompts/improve/refactor-test-suite.md +18 -0
  19. data/dev/prompts/improve/simplify-code-logic.md +133 -0
  20. data/dev/prompts/improve/update-documentation.md +21 -0
  21. data/dev/prompts/review/comprehensive-codebase-review.md +176 -0
  22. data/dev/prompts/review/identify-action-items.md +143 -0
  23. data/dev/prompts/review/verify-code-changes.md +54 -0
  24. data/dev/prompts/validate/create-screencast-outline.md +234 -0
  25. data/dev/prompts/validate/test-documentation-examples.md +180 -0
  26. data/docs/QUICKSTART.md +63 -0
  27. data/docs/assets/images/cov-loupe-logo-lores.png +0 -0
  28. data/docs/assets/images/cov-loupe-logo.png +0 -0
  29. data/docs/assets/images/favicon.png +0 -0
  30. data/docs/assets/stylesheets/branding.css +16 -0
  31. data/docs/assets/stylesheets/extra.css +15 -0
  32. data/docs/code_of_conduct.md +1 -0
  33. data/docs/contributing.md +1 -0
  34. data/docs/dev/ARCHITECTURE.md +56 -11
  35. data/docs/dev/DEVELOPMENT.md +116 -12
  36. data/docs/dev/FUTURE_ENHANCEMENTS.md +14 -0
  37. data/docs/dev/README.md +3 -2
  38. data/docs/dev/RELEASING.md +2 -0
  39. data/docs/dev/arch-decisions/README.md +10 -7
  40. data/docs/dev/arch-decisions/application-architecture.md +259 -0
  41. data/docs/dev/arch-decisions/coverage-data-quality.md +193 -0
  42. data/docs/dev/arch-decisions/output-character-mode.md +217 -0
  43. data/docs/dev/arch-decisions/path-resolution.md +90 -0
  44. data/docs/dev/arch-decisions/{004-x-arch-decision.md → policy-validation.md} +32 -28
  45. data/docs/dev/arch-decisions/{005-x-arch-decision.md → simplecov-integration.md} +47 -44
  46. data/docs/dev/presentations/cov-loupe-presentation.md +15 -13
  47. data/docs/examples/mcp-inputs.md +3 -0
  48. data/docs/examples/prompts.md +3 -0
  49. data/docs/examples/success_predicates.md +3 -0
  50. data/docs/fixtures/demo_project/.resultset.json +170 -0
  51. data/docs/fixtures/demo_project/README.md +6 -0
  52. data/docs/fixtures/demo_project/app/controllers/admin/audit_logs_controller.rb +19 -0
  53. data/docs/fixtures/demo_project/app/controllers/orders_controller.rb +26 -0
  54. data/docs/fixtures/demo_project/app/models/order.rb +20 -0
  55. data/docs/fixtures/demo_project/app/models/user.rb +19 -0
  56. data/docs/fixtures/demo_project/lib/api/client.rb +22 -0
  57. data/docs/fixtures/demo_project/lib/ops/jobs/cleanup_job.rb +16 -0
  58. data/docs/fixtures/demo_project/lib/ops/jobs/report_job.rb +17 -0
  59. data/docs/fixtures/demo_project/lib/payments/processor.rb +15 -0
  60. data/docs/fixtures/demo_project/lib/payments/refund_service.rb +15 -0
  61. data/docs/fixtures/demo_project/lib/payments/reporting/exporter.rb +16 -0
  62. data/docs/index.md +1 -0
  63. data/docs/license.md +3 -0
  64. data/docs/release_notes.md +3 -0
  65. data/docs/user/ADVANCED_USAGE.md +208 -115
  66. data/docs/user/CLI_FALLBACK_FOR_LLMS.md +2 -0
  67. data/docs/user/CLI_USAGE.md +276 -101
  68. data/docs/user/ERROR_HANDLING.md +4 -4
  69. data/docs/user/EXAMPLES.md +121 -128
  70. data/docs/user/INSTALLATION.md +9 -28
  71. data/docs/user/LIBRARY_API.md +227 -122
  72. data/docs/user/MCP_INTEGRATION.md +114 -203
  73. data/docs/user/README.md +5 -1
  74. data/docs/user/TROUBLESHOOTING.md +49 -27
  75. data/docs/user/installing-a-prelease-version-of-covloupe.md +43 -0
  76. data/docs/user/{V2-BREAKING-CHANGES.md → migrations/MIGRATING_TO_V2.md} +62 -72
  77. data/docs/user/migrations/MIGRATING_TO_V3.md +72 -0
  78. data/docs/user/migrations/MIGRATING_TO_V4.md +591 -0
  79. data/docs/user/migrations/README.md +22 -0
  80. data/docs/user/prompts/README.md +9 -0
  81. data/docs/user/prompts/non-web-coverage-analysis-prompt.md +103 -0
  82. data/docs/user/prompts/rails-coverage-analysis-prompt.md +94 -0
  83. data/docs/user/prompts/use-cli-not-mcp-prompt.md +53 -0
  84. data/examples/cli_demo.sh +77 -0
  85. data/examples/filter_and_table_demo-output.md +114 -0
  86. data/examples/filter_and_table_demo.rb +174 -0
  87. data/examples/fixtures/demo_project/coverage/.resultset.json +10 -0
  88. data/examples/mcp-inputs/README.md +66 -0
  89. data/examples/mcp-inputs/coverage_detailed.json +1 -0
  90. data/examples/mcp-inputs/coverage_raw.json +1 -0
  91. data/examples/mcp-inputs/coverage_summary.json +1 -0
  92. data/examples/mcp-inputs/list.json +1 -0
  93. data/examples/mcp-inputs/uncovered_lines.json +1 -0
  94. data/examples/prompts/README.md +27 -0
  95. data/examples/prompts/custom_resultset.txt +2 -0
  96. data/examples/prompts/detailed_with_source.txt +2 -0
  97. data/examples/prompts/list_lowest.txt +2 -0
  98. data/examples/prompts/summary.txt +2 -0
  99. data/examples/prompts/uncovered.txt +2 -0
  100. data/examples/success_predicates/README.md +198 -0
  101. data/examples/success_predicates/all_files_above_threshold_predicate.rb +21 -0
  102. data/examples/success_predicates/directory_specific_thresholds_predicate.rb +30 -0
  103. data/examples/success_predicates/project_coverage_minimum_predicate.rb +6 -0
  104. data/lib/cov_loupe/base_tool.rb +229 -20
  105. data/lib/cov_loupe/cli.rb +132 -23
  106. data/lib/cov_loupe/commands/base_command.rb +25 -6
  107. data/lib/cov_loupe/commands/command_factory.rb +0 -1
  108. data/lib/cov_loupe/commands/detailed_command.rb +10 -5
  109. data/lib/cov_loupe/commands/list_command.rb +2 -1
  110. data/lib/cov_loupe/commands/raw_command.rb +7 -5
  111. data/lib/cov_loupe/commands/summary_command.rb +12 -7
  112. data/lib/cov_loupe/commands/totals_command.rb +74 -10
  113. data/lib/cov_loupe/commands/uncovered_command.rb +7 -5
  114. data/lib/cov_loupe/commands/validate_command.rb +11 -3
  115. data/lib/cov_loupe/commands/version_command.rb +6 -4
  116. data/lib/cov_loupe/{app_config.rb → config/app_config.rb} +13 -5
  117. data/lib/cov_loupe/config/app_context.rb +43 -0
  118. data/lib/cov_loupe/config/boolean_type.rb +91 -0
  119. data/lib/cov_loupe/config/logger.rb +92 -0
  120. data/lib/cov_loupe/{option_normalizers.rb → config/option_normalizers.rb} +55 -24
  121. data/lib/cov_loupe/{option_parser_builder.rb → config/option_parser_builder.rb} +46 -24
  122. data/lib/cov_loupe/coverage/coverage_calculator.rb +53 -0
  123. data/lib/cov_loupe/coverage/coverage_reporter.rb +63 -0
  124. data/lib/cov_loupe/coverage/coverage_table_formatter.rb +133 -0
  125. data/lib/cov_loupe/{error_handler.rb → errors/error_handler.rb} +21 -33
  126. data/lib/cov_loupe/{errors.rb → errors/errors.rb} +48 -71
  127. data/lib/cov_loupe/formatters/formatters.rb +75 -0
  128. data/lib/cov_loupe/formatters/source_formatter.rb +18 -7
  129. data/lib/cov_loupe/formatters/table_formatter.rb +80 -0
  130. data/lib/cov_loupe/loaders/all.rb +15 -0
  131. data/lib/cov_loupe/loaders/all_cli.rb +10 -0
  132. data/lib/cov_loupe/loaders/all_mcp.rb +23 -0
  133. data/lib/cov_loupe/loaders/resultset_loader.rb +147 -0
  134. data/lib/cov_loupe/mcp_server.rb +3 -2
  135. data/lib/cov_loupe/model/model.rb +520 -0
  136. data/lib/cov_loupe/model/model_data.rb +13 -0
  137. data/lib/cov_loupe/model/model_data_cache.rb +116 -0
  138. data/lib/cov_loupe/option_parsers/env_options_parser.rb +17 -6
  139. data/lib/cov_loupe/option_parsers/error_helper.rb +16 -10
  140. data/lib/cov_loupe/output_chars.rb +192 -0
  141. data/lib/cov_loupe/paths/glob_utils.rb +100 -0
  142. data/lib/cov_loupe/{path_relativizer.rb → paths/path_relativizer.rb} +5 -13
  143. data/lib/cov_loupe/paths/path_utils.rb +265 -0
  144. data/lib/cov_loupe/paths/volume_case_sensitivity.rb +173 -0
  145. data/lib/cov_loupe/presenters/base_coverage_presenter.rb +9 -13
  146. data/lib/cov_loupe/presenters/coverage_payload_presenter.rb +21 -0
  147. data/lib/cov_loupe/presenters/payload_caching.rb +23 -0
  148. data/lib/cov_loupe/presenters/project_coverage_presenter.rb +73 -21
  149. data/lib/cov_loupe/presenters/project_totals_presenter.rb +16 -10
  150. data/lib/cov_loupe/repositories/coverage_repository.rb +149 -0
  151. data/lib/cov_loupe/resolvers/coverage_line_resolver.rb +90 -76
  152. data/lib/cov_loupe/resolvers/{resolver_factory.rb → resolver_helpers.rb} +6 -5
  153. data/lib/cov_loupe/resolvers/resultset_path_resolver.rb +40 -12
  154. data/lib/cov_loupe/scripts/command_execution.rb +113 -0
  155. data/lib/cov_loupe/scripts/latest_ci_status.rb +97 -0
  156. data/lib/cov_loupe/scripts/pre_release_check.rb +164 -0
  157. data/lib/cov_loupe/scripts/setup_doc_server.rb +23 -0
  158. data/lib/cov_loupe/scripts/start_doc_server.rb +24 -0
  159. data/lib/cov_loupe/staleness/stale_status.rb +23 -0
  160. data/lib/cov_loupe/staleness/staleness_checker.rb +328 -0
  161. data/lib/cov_loupe/staleness/staleness_message_formatter.rb +91 -0
  162. data/lib/cov_loupe/tools/coverage_detailed_tool.rb +14 -15
  163. data/lib/cov_loupe/tools/coverage_raw_tool.rb +14 -14
  164. data/lib/cov_loupe/tools/coverage_summary_tool.rb +16 -16
  165. data/lib/cov_loupe/tools/coverage_table_tool.rb +139 -21
  166. data/lib/cov_loupe/tools/coverage_totals_tool.rb +31 -13
  167. data/lib/cov_loupe/tools/help_tool.rb +16 -20
  168. data/lib/cov_loupe/tools/list_tool.rb +65 -0
  169. data/lib/cov_loupe/tools/uncovered_lines_tool.rb +14 -14
  170. data/lib/cov_loupe/tools/validate_tool.rb +18 -24
  171. data/lib/cov_loupe/tools/version_tool.rb +8 -3
  172. data/lib/cov_loupe/version.rb +1 -1
  173. data/lib/cov_loupe.rb +83 -55
  174. metadata +184 -154
  175. data/docs/dev/BRANCH_ONLY_COVERAGE.md +0 -158
  176. data/docs/dev/arch-decisions/001-x-arch-decision.md +0 -95
  177. data/docs/dev/arch-decisions/002-x-arch-decision.md +0 -159
  178. data/docs/dev/arch-decisions/003-x-arch-decision.md +0 -165
  179. data/lib/cov_loupe/app_context.rb +0 -26
  180. data/lib/cov_loupe/constants.rb +0 -22
  181. data/lib/cov_loupe/coverage_reporter.rb +0 -31
  182. data/lib/cov_loupe/formatters.rb +0 -51
  183. data/lib/cov_loupe/mode_detector.rb +0 -56
  184. data/lib/cov_loupe/model.rb +0 -339
  185. data/lib/cov_loupe/presenters/coverage_detailed_presenter.rb +0 -14
  186. data/lib/cov_loupe/presenters/coverage_raw_presenter.rb +0 -14
  187. data/lib/cov_loupe/presenters/coverage_summary_presenter.rb +0 -14
  188. data/lib/cov_loupe/presenters/coverage_uncovered_presenter.rb +0 -14
  189. data/lib/cov_loupe/resultset_loader.rb +0 -131
  190. data/lib/cov_loupe/staleness_checker.rb +0 -247
  191. data/lib/cov_loupe/table_formatter.rb +0 -64
  192. data/lib/cov_loupe/tools/all_files_coverage_tool.rb +0 -51
  193. data/lib/cov_loupe/util.rb +0 -88
  194. data/spec/MCP_INTEGRATION_TESTS_README.md +0 -111
  195. data/spec/TIMESTAMPS.md +0 -48
  196. data/spec/all_files_coverage_tool_spec.rb +0 -53
  197. data/spec/app_config_spec.rb +0 -142
  198. data/spec/base_tool_spec.rb +0 -62
  199. data/spec/cli/show_default_report_spec.rb +0 -33
  200. data/spec/cli_enumerated_options_spec.rb +0 -90
  201. data/spec/cli_error_spec.rb +0 -184
  202. data/spec/cli_format_spec.rb +0 -123
  203. data/spec/cli_json_options_spec.rb +0 -50
  204. data/spec/cli_source_spec.rb +0 -44
  205. data/spec/cli_spec.rb +0 -192
  206. data/spec/cli_table_spec.rb +0 -28
  207. data/spec/cli_usage_spec.rb +0 -42
  208. data/spec/commands/base_command_spec.rb +0 -107
  209. data/spec/commands/command_factory_spec.rb +0 -76
  210. data/spec/commands/detailed_command_spec.rb +0 -34
  211. data/spec/commands/list_command_spec.rb +0 -28
  212. data/spec/commands/raw_command_spec.rb +0 -69
  213. data/spec/commands/summary_command_spec.rb +0 -34
  214. data/spec/commands/totals_command_spec.rb +0 -34
  215. data/spec/commands/uncovered_command_spec.rb +0 -55
  216. data/spec/commands/validate_command_spec.rb +0 -213
  217. data/spec/commands/version_command_spec.rb +0 -38
  218. data/spec/constants_spec.rb +0 -61
  219. data/spec/cov_loupe/formatters/source_formatter_spec.rb +0 -267
  220. data/spec/cov_loupe/formatters_spec.rb +0 -76
  221. data/spec/cov_loupe/presenters/base_coverage_presenter_spec.rb +0 -79
  222. data/spec/cov_loupe_model_spec.rb +0 -454
  223. data/spec/cov_loupe_module_spec.rb +0 -37
  224. data/spec/cov_loupe_opts_spec.rb +0 -185
  225. data/spec/coverage_reporter_spec.rb +0 -102
  226. data/spec/coverage_table_tool_spec.rb +0 -59
  227. data/spec/coverage_totals_tool_spec.rb +0 -37
  228. data/spec/error_handler_spec.rb +0 -197
  229. data/spec/error_mode_spec.rb +0 -139
  230. data/spec/errors_edge_cases_spec.rb +0 -312
  231. data/spec/errors_stale_spec.rb +0 -83
  232. data/spec/file_based_mcp_tools_spec.rb +0 -99
  233. data/spec/help_tool_spec.rb +0 -26
  234. data/spec/integration_spec.rb +0 -789
  235. data/spec/logging_fallback_spec.rb +0 -128
  236. data/spec/mcp_logging_spec.rb +0 -44
  237. data/spec/mcp_server_integration_spec.rb +0 -23
  238. data/spec/mcp_server_spec.rb +0 -106
  239. data/spec/mode_detector_spec.rb +0 -153
  240. data/spec/model_error_handling_spec.rb +0 -269
  241. data/spec/model_staleness_spec.rb +0 -79
  242. data/spec/option_normalizers_spec.rb +0 -203
  243. data/spec/option_parsers/env_options_parser_spec.rb +0 -221
  244. data/spec/option_parsers/error_helper_spec.rb +0 -222
  245. data/spec/path_relativizer_spec.rb +0 -98
  246. data/spec/presenters/coverage_detailed_presenter_spec.rb +0 -19
  247. data/spec/presenters/coverage_raw_presenter_spec.rb +0 -15
  248. data/spec/presenters/coverage_summary_presenter_spec.rb +0 -15
  249. data/spec/presenters/coverage_uncovered_presenter_spec.rb +0 -16
  250. data/spec/presenters/project_coverage_presenter_spec.rb +0 -87
  251. data/spec/presenters/project_totals_presenter_spec.rb +0 -144
  252. data/spec/resolvers/coverage_line_resolver_spec.rb +0 -282
  253. data/spec/resolvers/resolver_factory_spec.rb +0 -61
  254. data/spec/resolvers/resultset_path_resolver_spec.rb +0 -60
  255. data/spec/resultset_loader_spec.rb +0 -167
  256. data/spec/shared_examples/README.md +0 -115
  257. data/spec/shared_examples/coverage_presenter_examples.rb +0 -66
  258. data/spec/shared_examples/file_based_mcp_tools.rb +0 -179
  259. data/spec/shared_examples/formatted_command_examples.rb +0 -64
  260. data/spec/shared_examples/mcp_tool_text_json_response.rb +0 -16
  261. data/spec/spec_helper.rb +0 -127
  262. data/spec/staleness_checker_spec.rb +0 -374
  263. data/spec/staleness_more_spec.rb +0 -42
  264. data/spec/support/cli_helpers.rb +0 -22
  265. data/spec/support/control_flow_helpers.rb +0 -20
  266. data/spec/support/fake_mcp.rb +0 -40
  267. data/spec/support/io_helpers.rb +0 -29
  268. data/spec/support/mcp_helpers.rb +0 -35
  269. data/spec/support/mcp_runner.rb +0 -66
  270. data/spec/support/mocking_helpers.rb +0 -30
  271. data/spec/table_format_spec.rb +0 -70
  272. data/spec/tools/validate_tool_spec.rb +0 -132
  273. data/spec/tools_error_handling_spec.rb +0 -130
  274. data/spec/util_spec.rb +0 -154
  275. data/spec/version_spec.rb +0 -123
  276. data/spec/version_tool_spec.rb +0 -141
  277. /data/{spec/fixtures/project1 → examples/fixtures/demo_project}/lib/bar.rb +0 -0
  278. /data/{spec/fixtures/project1 → examples/fixtures/demo_project}/lib/foo.rb +0 -0
  279. /data/lib/cov_loupe/{config_parser.rb → config/config_parser.rb} +0 -0
  280. /data/lib/cov_loupe/{predicate_evaluator.rb → config/predicate_evaluator.rb} +0 -0
  281. /data/lib/cov_loupe/{error_handler_factory.rb → errors/error_handler_factory.rb} +0 -0
data/spec/version_spec.rb DELETED
@@ -1,123 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
-
5
- RSpec.describe 'CovLoupe::VERSION' do
6
- describe 'constant existence' do
7
- it 'defines a VERSION constant' do
8
- expect(CovLoupe.const_defined?(:VERSION)).to be true
9
- end
10
-
11
- it 'exposes VERSION as a non-empty string' do
12
- expect(CovLoupe::VERSION).to be_a(String)
13
- expect(CovLoupe::VERSION).not_to be_empty
14
- end
15
-
16
- it 'is frozen (immutable)' do
17
- expect(CovLoupe::VERSION).to be_frozen
18
- end
19
- end
20
-
21
- describe 'semantic versioning compliance' do
22
- let(:version) { CovLoupe::VERSION }
23
- # Simplified semantic versioning regex
24
- # Preserves key semver rules: no leading zeros on numeric parts, optional prerelease/build metadata
25
- let(:semver_regex) do
26
- %r{\A
27
- (?<major>0|[1-9]\d*)\.
28
- (?<minor>0|[1-9]\d*)\.
29
- (?<patch>0|[1-9]\d*)
30
- (?:[.-](?<prerelease>[0-9A-Za-z.-]+))?
31
- (?:\+(?<buildmetadata>[0-9A-Za-z.-]+))?
32
- \z}x
33
- end
34
-
35
- it 'follows semantic versioning format (accepting hyphen or dot pre-release separator)' do
36
- expect(version).to match(semver_regex)
37
- end
38
-
39
- it 'has valid major.minor.patch core version' do
40
- match = version.match(semver_regex)
41
- expect(match).not_to be_nil, "VERSION '#{version}' does not match semantic versioning format"
42
-
43
- major = match[:major].to_i
44
- minor = match[:minor].to_i
45
- patch = match[:patch].to_i
46
-
47
- expect(major).to be >= 0
48
- expect(minor).to be >= 0
49
- expect(patch).to be >= 0
50
- end
51
-
52
- context 'when version has prerelease identifier' do
53
- let(:prerelease_version) { '9.9.9-rc.1' }
54
-
55
- before do
56
- stub_const('CovLoupe::VERSION', prerelease_version)
57
- end
58
-
59
- it 'has valid prerelease format' do
60
- match = version.match(semver_regex)
61
- prerelease = match[:prerelease]
62
- expect(prerelease).not_to be_empty
63
- expect(prerelease).not_to start_with('.')
64
- expect(prerelease).not_to end_with('.')
65
- end
66
- end
67
-
68
- context 'when version has build metadata' do
69
- let(:build_metadata_version) { '9.9.9+build.42' }
70
-
71
- before do
72
- stub_const('CovLoupe::VERSION', build_metadata_version)
73
- end
74
-
75
- it 'has valid build metadata format' do
76
- match = version.match(semver_regex)
77
- buildmetadata = match[:buildmetadata]
78
- expect(buildmetadata).not_to be_empty
79
- expect(buildmetadata).to match(/\A[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*\z/)
80
- end
81
- end
82
- end
83
-
84
- describe 'version consistency' do
85
- it 'is accessible via require path' do
86
- expect { CovLoupe::VERSION }.not_to raise_error
87
- end
88
-
89
- it 'matches the version referenced in gemspec' do
90
- gemspec_path = File.expand_path('../cov-loupe.gemspec', __dir__)
91
- gemspec_content = File.read(gemspec_path)
92
-
93
- version_line = gemspec_content.lines.find { |line| line.include?('spec.version') }
94
- expect(version_line).not_to be_nil, 'Could not find version line in gemspec'
95
- expect(version_line).to include('CovLoupe::VERSION')
96
- end
97
- end
98
-
99
- describe 'current version sanity check' do
100
- it 'is not the initial 0.0.0 version' do
101
- # Ensure this is a real release, not an uninitialized version
102
- expect(CovLoupe::VERSION).not_to eq('0.0.0')
103
- end
104
- end
105
-
106
- describe 'standalone version file load' do
107
- it 'defines the module and VERSION constant when only version.rb is loaded' do
108
- original_version = CovLoupe::VERSION
109
-
110
- stub_const('CovLoupe', Module.new do
111
- class << self
112
- attr_accessor :default_log_file, :active_log_file
113
- end
114
- end)
115
-
116
- version_path = File.expand_path('../lib/cov_loupe/version.rb', __dir__)
117
- load version_path
118
-
119
- expect(Object.const_defined?(:CovLoupe)).to be true
120
- expect(CovLoupe::VERSION).to eq(original_version)
121
- end
122
- end
123
- end
@@ -1,141 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
- require 'cov_loupe/tools/version_tool'
5
-
6
- RSpec.describe CovLoupe::Tools::VersionTool do
7
- let(:server_context) { instance_double('ServerContext').as_null_object }
8
-
9
- before do
10
- setup_mcp_response_stub
11
- end
12
-
13
- describe '.call' do
14
- it 'returns a text payload with the version string when called without arguments' do
15
- response = described_class.call(server_context: server_context)
16
- item = response.payload.first
17
- expect(item[:type] || item['type']).to eq('text')
18
- text = item['text']
19
- expect(text).to eq("CovLoupe version: #{CovLoupe::VERSION}")
20
- end
21
-
22
- it 'includes the exact version constant value' do
23
- response = described_class.call(server_context: server_context)
24
- item = response.payload.first
25
- text = item['text']
26
- expect(text).to include(CovLoupe::VERSION)
27
- end
28
-
29
- it 'matches the expected format exactly' do
30
- expected_format = "CovLoupe version: #{CovLoupe::VERSION}"
31
- response = described_class.call(server_context: server_context)
32
- item = response.payload.first
33
- text = item['text']
34
- expect(text).to eq(expected_format)
35
- end
36
-
37
- it 'returns an MCP::Tool::Response object' do
38
- response = described_class.call(server_context: server_context)
39
- expect(response).to be_a(MCP::Tool::Response)
40
- end
41
-
42
- it 'has a single payload item' do
43
- response = described_class.call(server_context: server_context)
44
- expect(response.payload).to be_an(Array)
45
- expect(response.payload.size).to eq(1)
46
- end
47
-
48
- context 'when error_mode is specified' do
49
- it 'accepts error_mode parameter without affecting output' do
50
- response = described_class.call(error_mode: 'off', server_context: server_context)
51
- item = response.payload.first
52
- text = item['text']
53
- expect(text).to eq("CovLoupe version: #{CovLoupe::VERSION}")
54
- end
55
-
56
- it 'accepts error_mode "log" (default)' do
57
- response = described_class.call(error_mode: 'log', server_context: server_context)
58
- item = response.payload.first
59
- expect(item[:type] || item['type']).to eq('text')
60
- end
61
-
62
- it 'accepts error_mode "debug"' do
63
- response = described_class.call(error_mode: 'debug', server_context: server_context)
64
- item = response.payload.first
65
- expect(item[:type] || item['type']).to eq('text')
66
- end
67
- end
68
-
69
- context 'when additional arguments are passed' do
70
- it 'ignores additional arguments gracefully' do
71
- response = described_class.call(
72
- server_context: server_context,
73
- extra_arg: 'value',
74
- another: { nested: 'data' }
75
- )
76
- item = response.payload.first
77
- text = item['text']
78
- expect(text).to eq("CovLoupe version: #{CovLoupe::VERSION}")
79
- end
80
- end
81
-
82
- context 'when an error occurs' do
83
- it 'handles VERSION constant access errors and returns structured error response' do
84
- # Force an error by hiding VERSION so const_missing is triggered
85
- hide_const('CovLoupe::VERSION')
86
- allow(CovLoupe).to receive(:const_missing).with(:VERSION)
87
- .and_raise(StandardError, 'Version access error')
88
-
89
- response = described_class.call(error_mode: 'log', server_context: server_context)
90
-
91
- # Should return error response in MCP format
92
- expect(response).to be_a(MCP::Tool::Response)
93
- item = response.payload.first
94
- expect(item[:type] || item['type']).to eq('text')
95
-
96
- error_text = item['text']
97
- expect(error_text).to include('Error')
98
- end
99
-
100
- it 'handles errors in the response creation process' do
101
- # Force an error by mocking string interpolation to fail
102
- version_obj = double('VERSION')
103
- allow(version_obj).to receive(:to_s).and_raise(StandardError, 'String conversion error')
104
-
105
- # Replace VERSION with our mock object
106
- stub_const('CovLoupe::VERSION', version_obj)
107
-
108
- response = described_class.call(error_mode: 'log', server_context: server_context)
109
-
110
- # Should return error response in MCP format via the rescue block
111
- expect(response).to be_a(MCP::Tool::Response)
112
- item = response.payload.first
113
- expect(item[:type] || item['type']).to eq('text')
114
-
115
- error_text = item['text']
116
- expect(error_text).to include('Error')
117
- end
118
-
119
- it 'respects error_mode setting when handling errors' do
120
- # Force an error using a mock VERSION that raises an exception
121
- version_obj = double('VERSION')
122
- allow(version_obj).to receive(:to_s).and_raise(StandardError, 'Version error')
123
- stub_const('CovLoupe::VERSION', version_obj)
124
-
125
- # Test error_mode 'off' (should be silent but still return structured response)
126
- response = described_class.call(error_mode: 'off', server_context: server_context)
127
- expect(response).to be_a(MCP::Tool::Response)
128
- item = response.payload.first
129
- expect(item[:type] || item['type']).to eq('text')
130
-
131
- # Test error_mode 'debug' (should include more detail)
132
- response = described_class.call(error_mode: 'debug', server_context: server_context)
133
- expect(response).to be_a(MCP::Tool::Response)
134
- item = response.payload.first
135
- expect(item[:type] || item['type']).to eq('text')
136
- error_text = item['text']
137
- expect(error_text).to include('Error')
138
- end
139
- end
140
- end
141
- end